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/primitive2d/fillgraphicprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
29 #include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
30 #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
31 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
32 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
33 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
34 #include <vcl/graph.hxx>
35 #include <vcl/texteng.hxx>
37 using namespace basegfx
;
38 using namespace basegfx::utils
;
39 using namespace ::com::sun::star
;
40 using namespace drawinglayer::attribute
;
41 using namespace drawinglayer::primitive2d
;
43 ThumbnailViewItem::ThumbnailViewItem(ThumbnailViewBase
&rView
, sal_uInt16 nId
)
54 ThumbnailViewItem::~ThumbnailViewItem()
58 static_cast< ThumbnailViewItemAcc
* >( mxAcc
.get() )->ParentDestroyed();
62 void ThumbnailViewItem::show (bool bVisible
)
67 void ThumbnailViewItem::setSelection (bool state
)
72 void ThumbnailViewItem::setHighlight (bool state
)
77 ::tools::Rectangle
ThumbnailViewItem::updateHighlight(bool bVisible
, const Point
& rPoint
)
79 bool bNeedsPaint
= false;
81 if (bVisible
&& getDrawArea().IsInside(rPoint
))
97 return ::tools::Rectangle();
100 void ThumbnailViewItem::setTitle (const OUString
& rTitle
)
102 if (mrParent
.renameItem(this, rTitle
))
106 uno::Reference
< accessibility::XAccessible
> const & ThumbnailViewItem::GetAccessible( bool bIsTransientChildrenDisabled
)
109 mxAcc
= new ThumbnailViewItemAcc( this, bIsTransientChildrenDisabled
);
114 void ThumbnailViewItem::setDrawArea (const ::tools::Rectangle
&area
)
119 void ThumbnailViewItem::calculateItemsPosition (const tools::Long nThumbnailHeight
,
120 const tools::Long nPadding
, sal_uInt32 nMaxTextLength
,
121 const ThumbnailItemAttributes
*pAttrs
)
123 drawinglayer::primitive2d::TextLayouterDevice aTextDev
;
124 aTextDev
.setFontAttribute(pAttrs
->aFontAttr
,
125 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(),
126 css::lang::Locale() );
128 Size aRectSize
= maDrawArea
.GetSize();
129 Size aImageSize
= maPreview1
.GetSizePixel();
131 // Calculate thumbnail position
132 Point aPos
= maDrawArea
.TopLeft();
133 aPos
.setX( maDrawArea
.getX() + (aRectSize
.Width()-aImageSize
.Width())/2 );
134 aPos
.setY( maDrawArea
.getY() + nPadding
+ (nThumbnailHeight
-aImageSize
.Height())/2 );
137 // Calculate text position
138 aPos
.setY( maDrawArea
.getY() + nThumbnailHeight
+ nPadding
* 2 );
139 aPos
.setX( maDrawArea
.Left() + (aRectSize
.Width() - aTextDev
.getTextWidth(maTitle
,0,nMaxTextLength
))/2 );
143 void ThumbnailViewItem::Paint (drawinglayer::processor2d::BaseProcessor2D
*pProcessor
,
144 const ThumbnailItemAttributes
*pAttrs
)
146 BColor aFillColor
= pAttrs
->aFillColor
;
147 drawinglayer::primitive2d::Primitive2DContainer
aSeq(4);
148 double fTransparence
= 0.0;
151 if( mbSelected
&& mbHover
)
152 aFillColor
= pAttrs
->aSelectHighlightColor
;
153 else if (mbSelected
|| mbHover
)
155 aFillColor
= pAttrs
->aHighlightColor
;
157 fTransparence
= pAttrs
->fHighlightTransparence
;
160 sal_uInt32 nPrimitive
= 0;
161 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference(
162 new PolyPolygonSelectionPrimitive2D( B2DPolyPolygon(::tools::Polygon(maDrawArea
, THUMBNAILVIEW_ITEM_CORNER
, THUMBNAILVIEW_ITEM_CORNER
).getB2DPolygon()),
169 Point aPos
= maPrev1Pos
;
170 Size aImageSize
= maPreview1
.GetSizePixel();
172 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference( new FillGraphicPrimitive2D(
173 createTranslateB2DHomMatrix(aPos
.X(),aPos
.Y()),
174 FillGraphicAttribute(Graphic(maPreview1
),
177 B2DPoint(aImageSize
.Width(),aImageSize
.Height())),
183 // draw thumbnail borders
184 float fWidth
= aImageSize
.Width() - 1;
185 float fHeight
= aImageSize
.Height() - 1;
186 float fPosX
= maPrev1Pos
.getX();
187 float fPosY
= maPrev1Pos
.getY();
190 aBounds
.append(B2DPoint(fPosX
,fPosY
));
191 aBounds
.append(B2DPoint(fPosX
+fWidth
,fPosY
));
192 aBounds
.append(B2DPoint(fPosX
+fWidth
,fPosY
+fHeight
));
193 aBounds
.append(B2DPoint(fPosX
,fPosY
+fHeight
));
194 aBounds
.setClosed(true);
196 aSeq
[nPrimitive
++] = drawinglayer::primitive2d::Primitive2DReference(createBorderLine(aBounds
));
199 // Draw text below thumbnail
200 addTextPrimitives(maTitle
, pAttrs
, maTextPos
, aSeq
);
202 pProcessor
->process(aSeq
);
205 void ThumbnailViewItem::addTextPrimitives (const OUString
& rText
, const ThumbnailItemAttributes
*pAttrs
, Point aPos
, drawinglayer::primitive2d::Primitive2DContainer
& rSeq
)
207 // adjust text drawing position according to text font
208 drawinglayer::primitive2d::TextLayouterDevice aTextDev
;
209 aTextDev
.setFontAttribute(
211 pAttrs
->aFontSize
.getX(),
212 pAttrs
->aFontSize
.getY(),
213 css::lang::Locale());
215 aPos
.setY(aPos
.getY() + aTextDev
.getTextHeight());
217 sal_Int32 nMnemonicPos
= -1;
218 OUString
aOrigText(mrParent
.isDrawMnemonic() ? OutputDevice::GetNonMnemonicString(rText
, nMnemonicPos
) : rText
);
220 TextEngine aTextEngine
;
221 aTextEngine
.SetFont(getVclFontFromFontAttribute(pAttrs
->aFontAttr
,
222 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(), 0,
223 css::lang::Locale()));
224 aTextEngine
.SetMaxTextWidth(maDrawArea
.getWidth());
225 aTextEngine
.SetText(aOrigText
);
227 sal_Int32 nPrimitives
= rSeq
.size();
228 sal_Int32 nFinalPrimCount
= nPrimitives
+ aTextEngine
.GetLineCount(0);
229 rSeq
.resize(nFinalPrimCount
);
231 // Create the text primitives
232 sal_uInt16 nLineStart
= 0;
233 OUString
aText(aOrigText
);
234 for (sal_uInt16 i
=0; i
< aTextEngine
.GetLineCount(0); ++i
)
236 sal_Int32 nLineLength
= aTextEngine
.GetLineLen(0, i
);
237 double nLineWidth
= aTextDev
.getTextWidth (aText
, nLineStart
, nLineLength
);
239 bool bTooLong
= (aPos
.getY() + aTextEngine
.GetCharHeight()) > maDrawArea
.Bottom();
240 if (bTooLong
&& (nLineLength
+ nLineStart
) < aOrigText
.getLength())
242 // Add the '...' to the last line to show, even though it may require to shorten the line
243 double nDotsWidth
= aTextDev
.getTextWidth("...",0,3);
245 sal_Int32 nLength
= nLineLength
- 1;
246 while ( nDotsWidth
+ aTextDev
.getTextWidth(aText
, nLineStart
, nLength
) > maDrawArea
.getWidth() && nLength
> 0)
251 aText
= OUString::Concat(aText
.subView(0, nLineStart
+nLength
)) + "...";
252 nLineLength
= nLength
+ 3;
255 double nLineX
= maDrawArea
.Left() + (maDrawArea
.getWidth() - nLineWidth
) / 2.0;
257 basegfx::B2DHomMatrix
aTextMatrix( createScaleTranslateB2DHomMatrix(
258 pAttrs
->aFontSize
.getX(), pAttrs
->aFontSize
.getY(),
259 nLineX
, double( aPos
.Y() ) ) );
262 BColor aTextColor
= pAttrs
->aTextColor
;
266 aTextColor
= pAttrs
->aSelectHighlightTextColor
;
268 aTextColor
= pAttrs
->aHighlightTextColor
;
271 rSeq
[nPrimitives
++] = drawinglayer::primitive2d::Primitive2DReference(
272 new TextSimplePortionPrimitive2D(aTextMatrix
,
273 aText
, nLineStart
, nLineLength
,
274 std::vector
<double>(),
279 if (nMnemonicPos
!= -1 && nMnemonicPos
>= nLineStart
&& nMnemonicPos
< nLineStart
+ nLineLength
)
281 rSeq
.resize(nFinalPrimCount
+ 1);
283 auto aCaretPositions
= aTextDev
.getCaretPositions(aText
, nLineStart
, nLineLength
);
285 auto lc_x1
= aCaretPositions
[2*(nMnemonicPos
- nLineStart
)];
286 auto lc_x2
= aCaretPositions
[2*(nMnemonicPos
- nLineStart
)+1];
287 auto fMnemonicWidth
= std::abs(lc_x1
- lc_x2
);
288 auto fMnemonicHeight
= aTextDev
.getUnderlineHeight();
290 auto fPosX
= nLineX
+ std::min(lc_x1
, lc_x2
);
291 auto fPosY
= aPos
.Y() + aTextDev
.getUnderlineOffset();
294 aLine
.append(B2DPoint(fPosX
, fPosY
));
295 aLine
.append(B2DPoint(fPosX
+ fMnemonicWidth
, fPosY
));
297 drawinglayer::attribute::LineAttribute
aLineAttribute(Color(aTextColor
).getBColor(), fMnemonicHeight
);
299 rSeq
[nPrimitives
++] = drawinglayer::primitive2d::Primitive2DReference(
300 new PolygonStrokePrimitive2D(aLine
, aLineAttribute
));
303 nLineStart
+= nLineLength
;
304 aPos
.setY(aPos
.getY() + aTextEngine
.GetCharHeight());
311 drawinglayer::primitive2d::PolygonHairlinePrimitive2D
*
312 ThumbnailViewItem::createBorderLine (const basegfx::B2DPolygon
& rPolygon
)
314 return new PolygonHairlinePrimitive2D(rPolygon
, Color(128, 128, 128).getBColor());
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */