1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/thumbnailviewitem.hxx>
22 #include <sfx2/thumbnailview.hxx>
23 #include "thumbnailviewacc.hxx"
25 #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 #include <basegfx/range/b2drectangle.hxx>
27 #include <basegfx/vector/b2dsize.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <drawinglayer/attribute/fillgraphicattribute.hxx>
30 #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
31 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
33 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
34 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
35 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
36 #include <vcl/button.hxx>
37 #include <vcl/graph.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/texteng.hxx>
40 #include <svtools/optionsdrawinglayer.hxx>
42 using namespace basegfx
;
43 using namespace basegfx::tools
;
44 using namespace ::com::sun::star
;
45 using namespace drawinglayer::attribute
;
46 using namespace drawinglayer::primitive2d
;
48 class ResizableMultiLineEdit
: public VclMultiLineEdit
51 ThumbnailViewItem
* mpItem
;
55 ResizableMultiLineEdit (Window
* pParent
, ThumbnailViewItem
* pItem
);
56 ~ResizableMultiLineEdit ();
58 void SetInGrabFocus(bool bInGrabFocus
) { mbIsInGrabFocus
= bInGrabFocus
; }
60 virtual long PreNotify(NotifyEvent
& rNEvt
);
61 virtual void Modify();
64 ResizableMultiLineEdit::ResizableMultiLineEdit (Window
* pParent
, ThumbnailViewItem
* pItem
) :
65 VclMultiLineEdit (pParent
, WB_CENTER
| WB_BORDER
),
67 mbIsInGrabFocus(false)
71 ResizableMultiLineEdit::~ResizableMultiLineEdit ()
75 long ResizableMultiLineEdit::PreNotify(NotifyEvent
& rNEvt
)
78 if( rNEvt
.GetType() == EVENT_KEYINPUT
)
80 const KeyEvent
& rKEvt
= *rNEvt
.GetKeyEvent();
81 KeyCode aCode
= rKEvt
.GetKeyCode();
82 switch (aCode
.GetCode())
85 mpItem
->setTitle( GetText() );
87 mpItem
->setEditTitle(false);
94 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
&& !mbIsInGrabFocus
)
96 mpItem
->setTitle( GetText() );
97 mpItem
->setEditTitle(false, false);
99 return nDone
? nDone
: VclMultiLineEdit::PreNotify(rNEvt
);
102 void ResizableMultiLineEdit::Modify()
104 VclMultiLineEdit::Modify();
105 mpItem
->updateTitleEditSize();
108 ThumbnailViewItem::ThumbnailViewItem(ThumbnailView
&rView
, sal_uInt16 nId
)
117 , maTextEditMaxArea()
119 mpTitleED
= new ResizableMultiLineEdit(&rView
, this);
122 ThumbnailViewItem::~ThumbnailViewItem()
127 static_cast< ThumbnailViewItemAcc
* >( mpxAcc
->get() )->ParentDestroyed();
132 void ThumbnailViewItem::show (bool bVisible
)
134 mbVisible
= bVisible
;
136 mpTitleED
->Show(false);
139 void ThumbnailViewItem::setSelection (bool state
)
144 void ThumbnailViewItem::setHighlight (bool state
)
149 OUString
ThumbnailViewItem::getHelpText() const
154 void ThumbnailViewItem::setEditTitle (bool edit
, bool bChangeFocus
)
157 mpTitleED
->Show(edit
);
160 mpTitleED
->SetText(maTitle
);
161 updateTitleEditSize();
162 static_cast<ResizableMultiLineEdit
*>(mpTitleED
)->SetInGrabFocus(true);
163 mpTitleED
->GrabFocus();
164 static_cast<ResizableMultiLineEdit
*>(mpTitleED
)->SetInGrabFocus(false);
166 else if (bChangeFocus
)
168 mrParent
.GrabFocus();
172 Rectangle
ThumbnailViewItem::getTextArea() const
174 Rectangle
aTextArea(maTextEditMaxArea
);
176 TextEngine aTextEngine
;
177 aTextEngine
.SetMaxTextWidth(maDrawArea
.getWidth());
178 aTextEngine
.SetText(maTitle
);
180 long nTxtHeight
= aTextEngine
.GetTextHeight() + 6;
181 if (nTxtHeight
< aTextArea
.GetHeight())
182 aTextArea
.SetSize(Size(aTextArea
.GetWidth(), nTxtHeight
));
187 void ThumbnailViewItem::updateTitleEditSize()
189 Rectangle aTextArea
= getTextArea();
190 Point aPos
= aTextArea
.TopLeft();
191 Size aSize
= aTextArea
.GetSize();
192 mpTitleED
->SetPosSizePixel(aPos
, aSize
);
195 void ThumbnailViewItem::setTitle (const OUString
& rTitle
)
197 if (mrParent
.renameItem(this, rTitle
))
201 uno::Reference
< accessibility::XAccessible
> ThumbnailViewItem::GetAccessible( bool bIsTransientChildrenDisabled
)
204 mpxAcc
= new uno::Reference
< accessibility::XAccessible
>( new ThumbnailViewItemAcc( this, bIsTransientChildrenDisabled
) );
209 void ThumbnailViewItem::setDrawArea (const Rectangle
&area
)
214 void ThumbnailViewItem::calculateItemsPosition (const long nThumbnailHeight
, const long,
215 const long nPadding
, sal_uInt32 nMaxTextLenght
,
216 const ThumbnailItemAttributes
*pAttrs
)
218 drawinglayer::primitive2d::TextLayouterDevice aTextDev
;
219 aTextDev
.setFontAttribute(pAttrs
->aFontAttr
,
220 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(),
221 com::sun::star::lang::Locale() );
223 Size aRectSize
= maDrawArea
.GetSize();
224 Size aImageSize
= maPreview1
.GetSizePixel();
226 // Calculate thumbnail position
227 Point aPos
= maDrawArea
.TopLeft();
228 aPos
.X() = maDrawArea
.getX() + (aRectSize
.Width()-aImageSize
.Width())/2;
229 aPos
.Y() = maDrawArea
.getY() + nPadding
+ (nThumbnailHeight
-aImageSize
.Height())/2;
232 // Calculate text position
233 aPos
.Y() = maDrawArea
.getY() + nThumbnailHeight
+ nPadding
* 2;
234 aPos
.X() = maDrawArea
.Left() + (aRectSize
.Width() - aTextDev
.getTextWidth(maTitle
,0,nMaxTextLenght
))/2;
237 // Calculate the text edit max area
238 aPos
= Point(maDrawArea
.getX() + nPadding
, maTextPos
.getY());
239 Size
aEditSize(maDrawArea
.GetWidth() - nPadding
* 2,
240 maDrawArea
.Bottom() - maTextPos
.Y());
241 maTextEditMaxArea
= Rectangle( aPos
, aEditSize
);
244 void ThumbnailViewItem::setSelectClickHdl (const Link
&link
)
249 void ThumbnailViewItem::Paint (drawinglayer::processor2d::BaseProcessor2D
*pProcessor
,
250 const ThumbnailItemAttributes
*pAttrs
)
252 BColor aFillColor
= pAttrs
->aFillColor
;
253 drawinglayer::primitive2d::Primitive2DSequence
aSeq(4);
254 double fTransparence
= 0.0;
257 if (mbSelected
|| mbHover
)
258 aFillColor
= pAttrs
->aHighlightColor
;
262 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
263 fTransparence
= aSvtOptionsDrawinglayer
.GetTransparentSelectionPercent() * 0.01;
266 sal_uInt32 nPrimitive
= 0;
267 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference( new PolyPolygonSelectionPrimitive2D(
268 B2DPolyPolygon(Polygon(maDrawArea
,5,5).getB2DPolygon()),
275 Point aPos
= maPrev1Pos
;
276 Size aImageSize
= maPreview1
.GetSizePixel();
278 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference( new FillGraphicPrimitive2D(
279 createTranslateB2DHomMatrix(aPos
.X(),aPos
.Y()),
280 FillGraphicAttribute(Graphic(maPreview1
),
283 B2DPoint(aImageSize
.Width(),aImageSize
.Height())),
287 // draw thumbnail borders
288 float fWidth
= aImageSize
.Width();
289 float fHeight
= aImageSize
.Height();
290 float fPosX
= maPrev1Pos
.getX();
291 float fPosY
= maPrev1Pos
.getY();
294 aBounds
.append(B2DPoint(fPosX
,fPosY
));
295 aBounds
.append(B2DPoint(fPosX
+fWidth
,fPosY
));
296 aBounds
.append(B2DPoint(fPosX
+fWidth
,fPosY
+fHeight
));
297 aBounds
.append(B2DPoint(fPosX
,fPosY
+fHeight
));
298 aBounds
.setClosed(true);
300 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference(createBorderLine(aBounds
));
302 // Draw text below thumbnail
304 addTextPrimitives( maTitle
, pAttrs
, aPos
, aSeq
);
306 pProcessor
->process(aSeq
);
309 void ThumbnailViewItem::addTextPrimitives (const OUString
& rText
, const ThumbnailItemAttributes
*pAttrs
, Point aPos
, drawinglayer::primitive2d::Primitive2DSequence
& rSeq
)
311 drawinglayer::primitive2d::TextLayouterDevice aTextDev
;
313 aPos
.setY(aPos
.getY() + aTextDev
.getTextHeight());
315 OUString
aText (rText
);
317 TextEngine aTextEngine
;
318 aTextEngine
.SetMaxTextWidth(maDrawArea
.getWidth());
319 aTextEngine
.SetText(rText
);
321 sal_Int32 nPrimitives
= rSeq
.getLength();
322 rSeq
.realloc(nPrimitives
+ aTextEngine
.GetLineCount(0));
324 // Create the text primitives
325 sal_uInt16 nLineStart
= 0;
326 for (sal_uInt16 i
=0; i
<aTextEngine
.GetLineCount(0); ++i
)
328 sal_uInt16 nLineLength
= aTextEngine
.GetLineLen(0, i
);
329 double nLineWidth
= aTextDev
.getTextWidth (aText
, nLineStart
, nLineLength
);
331 bool bTooLong
= (aPos
.getY() + aTextEngine
.GetCharHeight()) > maDrawArea
.Bottom();
332 if (bTooLong
&& (nLineLength
+ nLineStart
) < rText
.getLength())
334 // Add the '...' to the last line to show, even though it may require to shorten the line
335 double nDotsWidth
= aTextDev
.getTextWidth(OUString("..."),0,3);
337 sal_uInt16 nLength
= nLineLength
- 1;
338 while ( nDotsWidth
+ aTextDev
.getTextWidth(aText
, nLineStart
, nLength
) > maDrawArea
.getWidth() && nLength
> 0)
343 aText
= aText
.copy(0, nLineStart
+nLength
);
345 nLineLength
= nLength
+ 3;
348 double nLineX
= maDrawArea
.Left() + (maDrawArea
.getWidth() - nLineWidth
) / 2.0;
350 basegfx::B2DHomMatrix
aTextMatrix( createScaleTranslateB2DHomMatrix(
351 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(),
352 nLineX
, double( aPos
.Y() ) ) );
354 rSeq
[nPrimitives
++] = drawinglayer::primitive2d::Primitive2DReference(
355 new TextSimplePortionPrimitive2D(aTextMatrix
,
356 aText
,nLineStart
,nLineLength
,
357 std::vector
< double >( ),
359 com::sun::star::lang::Locale(),
360 Color(COL_BLACK
).getBColor() ) );
361 nLineStart
+= nLineLength
;
362 aPos
.setY(aPos
.getY() + aTextEngine
.GetCharHeight());
369 drawinglayer::primitive2d::PolygonHairlinePrimitive2D
*
370 ThumbnailViewItem::createBorderLine (const basegfx::B2DPolygon
& rPolygon
)
372 return new PolygonHairlinePrimitive2D(rPolygon
, Color(186,186,186).getBColor());
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */