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>
21 #include <sfx2/thumbnailview.hxx>
22 #include "thumbnailviewacc.hxx"
24 #include <basegfx/matrix/b2dhommatrixtools.hxx>
25 #include <basegfx/polygon/b2dpolygon.hxx>
26 #include <drawinglayer/attribute/fillgraphicattribute.hxx>
27 #include <drawinglayer/attribute/fontattribute.hxx>
28 #include <drawinglayer/attribute/lineattribute.hxx>
29 #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
30 #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
31 #include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
32 #include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
33 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
34 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
35 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
36 #include <vcl/event.hxx>
37 #include <vcl/graph.hxx>
38 #include <vcl/mnemonic.hxx>
39 #include <vcl/outdev.hxx>
40 #include <vcl/texteng.hxx>
41 #include <bitmaps.hlst>
42 #include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx>
43 #include <unotools/historyoptions.hxx>
46 using namespace basegfx
;
47 using namespace basegfx::utils
;
48 using namespace ::com::sun::star
;
49 using namespace drawinglayer::attribute
;
50 using namespace drawinglayer::primitive2d
;
52 ThumbnailViewItem::ThumbnailViewItem(ThumbnailView
& rView
, sal_uInt16 nId
)
62 ThumbnailViewItem::~ThumbnailViewItem()
66 mxAcc
->ParentDestroyed();
70 void ThumbnailViewItem::show (bool bVisible
)
75 void ThumbnailViewItem::setSelection (bool state
)
80 void ThumbnailViewItem::setHighlight (bool state
)
85 ::tools::Rectangle
ThumbnailViewItem::updateHighlight(bool bVisible
, const Point
& rPoint
)
87 bool bNeedsPaint
= false;
89 if (bVisible
&& getDrawArea().Contains(rPoint
))
103 return getDrawArea();
105 return ::tools::Rectangle();
108 void ThumbnailViewItem::setTitle (const OUString
& rTitle
)
110 if (mrParent
.renameItem(this, rTitle
))
114 const rtl::Reference
< ThumbnailViewItemAcc
> & ThumbnailViewItem::GetAccessible( bool bIsTransientChildrenDisabled
)
117 mxAcc
= new ThumbnailViewItemAcc( this, bIsTransientChildrenDisabled
);
122 void ThumbnailViewItem::setDrawArea (const ::tools::Rectangle
&area
)
127 void ThumbnailViewItem::calculateItemsPosition (const tools::Long nThumbnailHeight
,
128 const tools::Long nPadding
, sal_uInt32 nMaxTextLength
,
129 const ThumbnailItemAttributes
*pAttrs
)
131 drawinglayer::primitive2d::TextLayouterDevice aTextDev
;
132 aTextDev
.setFontAttribute(pAttrs
->aFontAttr
,
133 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(),
134 css::lang::Locale() );
136 Size aImageSize
= maPreview1
.GetSizePixel();
138 // Calculate thumbnail position
139 const Point aPos
= maDrawArea
.TopCenter();
140 maPrev1Pos
= aPos
+ Point(-aImageSize
.Width() / 2, nPadding
+ (nThumbnailHeight
- aImageSize
.Height()) / 2);
142 // Calculate pin position
143 maPinPos
= maDrawArea
.TopLeft() + Point(nPadding
, nPadding
);
145 // Calculate text position
146 maTextPos
= aPos
+ Point(-aTextDev
.getTextWidth(maTitle
, 0, nMaxTextLength
) / 2, nThumbnailHeight
+ nPadding
* 2);
149 void ThumbnailViewItem::Paint (drawinglayer::processor2d::BaseProcessor2D
*pProcessor
,
150 const ThumbnailItemAttributes
*pAttrs
)
152 BColor aFillColor
= pAttrs
->aFillColor
;
153 drawinglayer::primitive2d::Primitive2DContainer
aSeq(4);
154 double fTransparence
= 0.0;
157 if( mbSelected
&& mbHover
)
158 aFillColor
= pAttrs
->aHighlightColor
;
159 else if (mbSelected
|| mbHover
)
161 aFillColor
= pAttrs
->aHighlightColor
;
163 fTransparence
= pAttrs
->fHighlightTransparence
;
166 sal_uInt32 nPrimitive
= 0;
167 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference(
168 new PolyPolygonSelectionPrimitive2D( B2DPolyPolygon(::tools::Polygon(maDrawArea
, THUMBNAILVIEW_ITEM_CORNER
, THUMBNAILVIEW_ITEM_CORNER
).getB2DPolygon()),
175 Point aPos
= maPrev1Pos
;
176 Size aImageSize
= maPreview1
.GetSizePixel();
178 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference( new FillGraphicPrimitive2D(
179 createTranslateB2DHomMatrix(aPos
.X(),aPos
.Y()),
180 FillGraphicAttribute(Graphic(maPreview1
),
183 B2DPoint(aImageSize
.Width(),aImageSize
.Height())),
189 // draw thumbnail borders
190 float fWidth
= aImageSize
.Width() - 1;
191 float fHeight
= aImageSize
.Height() - 1;
192 float fPosX
= maPrev1Pos
.getX();
193 float fPosY
= maPrev1Pos
.getY();
196 aBounds
.append(B2DPoint(fPosX
,fPosY
));
197 aBounds
.append(B2DPoint(fPosX
+fWidth
,fPosY
));
198 aBounds
.append(B2DPoint(fPosX
+fWidth
,fPosY
+fHeight
));
199 aBounds
.append(B2DPoint(fPosX
,fPosY
+fHeight
));
200 aBounds
.setClosed(true);
202 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference(createBorderLine(aBounds
));
205 // Draw text below thumbnail
206 addTextPrimitives(maTitle
, pAttrs
, maTextPos
, aSeq
);
208 pProcessor
->process(aSeq
);
211 void ThumbnailViewItem::addTextPrimitives (const OUString
& rText
, const ThumbnailItemAttributes
*pAttrs
, Point aPos
, drawinglayer::primitive2d::Primitive2DContainer
& rSeq
)
213 // adjust text drawing position according to text font
214 drawinglayer::primitive2d::TextLayouterDevice aTextDev
;
215 aTextDev
.setFontAttribute(
217 pAttrs
->aFontSize
.getX(),
218 pAttrs
->aFontSize
.getY(),
219 css::lang::Locale());
221 aPos
.setY(aPos
.getY() + aTextDev
.getTextHeight());
223 sal_Int32 nMnemonicPos
= -1;
224 OUString
aOrigText(mrParent
.isDrawMnemonic() ? removeMnemonicFromString(rText
, nMnemonicPos
) : rText
);
226 TextEngine aTextEngine
;
227 aTextEngine
.SetFont(getVclFontFromFontAttribute(pAttrs
->aFontAttr
,
228 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(), 0,
229 css::lang::Locale()));
230 aTextEngine
.SetMaxTextWidth(maDrawArea
.getOpenWidth());
231 aTextEngine
.SetText(aOrigText
);
233 sal_Int32 nPrimitives
= rSeq
.size();
234 sal_Int32 nFinalPrimCount
= nPrimitives
+ aTextEngine
.GetLineCount(0);
235 rSeq
.resize(nFinalPrimCount
);
237 // Create the text primitives
238 sal_Int32 nLineStart
= 0;
239 OUString
aText(aOrigText
);
240 for (sal_Int32 i
=0; i
< aTextEngine
.GetLineCount(0); ++i
)
242 sal_Int32 nLineLength
= aTextEngine
.GetLineLen(0, i
);
243 double nLineWidth
= aTextDev
.getTextWidth (aText
, nLineStart
, nLineLength
);
245 bool bTooLong
= (aPos
.getY() + aTextEngine
.GetCharHeight()) > maDrawArea
.Bottom();
246 if (bTooLong
&& (nLineLength
+ nLineStart
) < aOrigText
.getLength())
248 // Add the '...' to the last line to show, even though it may require to shorten the line
249 double nDotsWidth
= aTextDev
.getTextWidth("...",0,3);
251 sal_Int32 nLength
= nLineLength
- 1;
252 while ( nDotsWidth
+ aTextDev
.getTextWidth(aText
, nLineStart
, nLength
) > maDrawArea
.getOpenWidth() && nLength
> 0)
257 aText
= OUString::Concat(aText
.subView(0, nLineStart
+nLength
)) + "...";
258 nLineLength
= nLength
+ 3;
261 double nLineX
= maDrawArea
.Left() + (maDrawArea
.getOpenWidth() - nLineWidth
) / 2.0;
263 basegfx::B2DHomMatrix
aTextMatrix( createScaleTranslateB2DHomMatrix(
264 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(),
265 nLineX
, double( aPos
.Y() ) ) );
268 BColor aTextColor
= pAttrs
->aTextColor
;
271 aTextColor
= pAttrs
->aHighlightTextColor
;
274 rSeq
[nPrimitives
++] = drawinglayer::primitive2d::Primitive2DReference(
275 new TextSimplePortionPrimitive2D(aTextMatrix
,
276 aText
, nLineStart
, nLineLength
,
277 std::vector
<double>(),
283 if (nMnemonicPos
!= -1 && nMnemonicPos
>= nLineStart
&& nMnemonicPos
< nLineStart
+ nLineLength
)
285 rSeq
.resize(nFinalPrimCount
+ 1);
287 auto aTextArray
= aTextDev
.getTextArray(aText
, nLineStart
, nLineLength
, true);
289 auto nPos
= nMnemonicPos
- nLineStart
;
290 auto lc_x1
= nPos
? aTextArray
[nPos
- 1] : 0;
291 auto lc_x2
= aTextArray
[nPos
];
292 auto fMnemonicWidth
= std::abs(lc_x1
- lc_x2
);
293 auto fMnemonicHeight
= aTextDev
.getUnderlineHeight();
295 auto fPosX
= nLineX
+ std::min(lc_x1
, lc_x2
);
296 auto fPosY
= aPos
.Y() + aTextDev
.getUnderlineOffset();
299 aLine
.append(B2DPoint(fPosX
, fPosY
));
300 aLine
.append(B2DPoint(fPosX
+ fMnemonicWidth
, fPosY
));
302 drawinglayer::attribute::LineAttribute
aLineAttribute(Color(aTextColor
).getBColor(), fMnemonicHeight
);
304 rSeq
[nPrimitives
++] = drawinglayer::primitive2d::Primitive2DReference(
305 new PolygonStrokePrimitive2D(std::move(aLine
), aLineAttribute
));
308 nLineStart
+= nLineLength
;
309 aPos
.setY(aPos
.getY() + aTextEngine
.GetCharHeight());
316 rtl::Reference
<drawinglayer::primitive2d::PolygonHairlinePrimitive2D
>
317 ThumbnailViewItem::createBorderLine (const basegfx::B2DPolygon
& rPolygon
)
319 return new PolygonHairlinePrimitive2D(rPolygon
, Color(128, 128, 128).getBColor());
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */