1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <overlayobject.hxx>
21
22 #include <drawinglayer/attribute/fontattribute.hxx>
23 #include <drawinglayer/geometry/viewinformation2d.hxx>
24 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
25 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
26 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
27 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
28 #include <basegfx/polygon/b2dpolygontools.hxx>
29 #include <basegfx/matrix/b2dhommatrixtools.hxx>
30 #include <tools/lineend.hxx>
31 #include <vcl/outdev.hxx>
32 #include <vcl/settings.hxx>
33 #include <vcl/metric.hxx>
34
35 #define HINT_LINESPACE 2
36 #define HINT_INDENT 3
37 #define HINT_MARGIN 4
38
ScOverlayHint(const OUString & rTit,const OUString & rMsg,const Color & rColor,const vcl::Font & rFont)39 ScOverlayHint::ScOverlayHint(const OUString& rTit, const OUString& rMsg, const Color& rColor, const vcl::Font& rFont)
40 : OverlayObject(rColor)
41 , m_aTitle(rTit)
42 , m_aMessage(convertLineEnd(rMsg, LINEEND_CR))
43 , m_aTextFont(rFont)
44 , m_aMapMode(MapUnit::MapPixel)
45 , m_nLeft(0)
46 , m_nTop(0)
47 {
48 }
49
createOverlaySequence(sal_Int32 nLeft,sal_Int32 nTop,const MapMode & rMapMode,basegfx::B2DRange & rRange) const50 drawinglayer::primitive2d::Primitive2DContainer ScOverlayHint::createOverlaySequence(sal_Int32 nLeft, sal_Int32 nTop,
51 const MapMode &rMapMode,
52 basegfx::B2DRange &rRange) const
53 {
54 OutputDevice* pDefaultDev = Application::GetDefaultDevice();
55 MapMode aOld = pDefaultDev->GetMapMode();
56 pDefaultDev->SetMapMode(rMapMode);
57
58 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
59 const Color& rColor = rStyleSettings.GetLabelTextColor();
60 vcl::Font aTextFont = m_aTextFont;
61 aTextFont.SetFontSize(pDefaultDev->PixelToLogic(aTextFont.GetFontSize(), rMapMode));
62 vcl::Font aHeadFont = aTextFont;
63 aHeadFont.SetWeight(WEIGHT_BOLD);
64
65 // Create the text primitive for the title
66 basegfx::B2DVector aFontSize;
67 drawinglayer::attribute::FontAttribute aFontAttr =
68 drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, aHeadFont, false, false);
69
70 FontMetric aFontMetric = pDefaultDev->GetFontMetric(aHeadFont);
71 Size aHintMargin = pDefaultDev->PixelToLogic(Size(HINT_MARGIN, HINT_MARGIN), rMapMode);
72 Size aIndent = pDefaultDev->PixelToLogic(Size(HINT_INDENT, HINT_LINESPACE), rMapMode);
73 double nTextOffsetY = nTop + aHintMargin.Height() + aFontMetric.GetAscent();
74 Point aTextPos(nLeft + aHintMargin.Width() , nTextOffsetY);
75 rRange = basegfx::B2DRange(nLeft, nTop, nLeft + aHintMargin.Width(), nTop + aHintMargin.Height());
76
77 basegfx::B2DHomMatrix aTextMatrix(basegfx::utils::createScaleTranslateB2DHomMatrix(
78 aFontSize.getX(), aFontSize.getY(),
79 aTextPos.X(), aTextPos.Y()));
80
81 drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pTitle =
82 new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
83 aTextMatrix, m_aTitle, 0, m_aTitle.getLength(),
84 std::vector<double>(), aFontAttr, css::lang::Locale(),
85 rColor.getBColor());
86
87 const drawinglayer::primitive2d::Primitive2DReference aTitle(pTitle);
88
89 Point aTextStart(nLeft + aHintMargin.Width() + aIndent.Width(),
90 nTop + aHintMargin.Height() + aFontMetric.GetLineHeight() + aIndent.Height());
91
92 drawinglayer::geometry::ViewInformation2D aDummy;
93 rRange.expand(pTitle->getB2DRange(aDummy));
94
95 drawinglayer::primitive2d::Primitive2DContainer aSeq { aTitle };
96
97 aFontMetric = pDefaultDev->GetFontMetric(aTextFont);
98 pDefaultDev->SetMapMode(aOld);
99
100 nTextOffsetY = aFontMetric.GetAscent();
101 sal_Int32 nLineHeight = aFontMetric.GetLineHeight();
102
103 aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, aTextFont, false, false);
104
105 sal_Int32 nIndex = 0;
106 Point aLineStart = aTextStart;
107 while (nIndex != -1)
108 {
109 OUString aLine = m_aMessage.getToken( 0, '\r', nIndex );
110
111 aTextMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(
112 aFontSize.getX(), aFontSize.getY(),
113 aLineStart.X(), aLineStart.Y() + nTextOffsetY);
114
115 // Create the text primitive for each line of text
116 drawinglayer::primitive2d::TextSimplePortionPrimitive2D* pMessage =
117 new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
118 aTextMatrix, aLine, 0, aLine.getLength(),
119 std::vector<double>(), aFontAttr, css::lang::Locale(),
120 rColor.getBColor());
121
122 rRange.expand(pMessage->getB2DRange(aDummy));
123
124 const drawinglayer::primitive2d::Primitive2DReference aMessage(pMessage);
125 aSeq.push_back(aMessage);
126
127 aLineStart.AdjustY(nLineHeight );
128 }
129
130 rRange.expand(basegfx::B2DTuple(rRange.getMaxX() + aHintMargin.Width(),
131 rRange.getMaxY() + aHintMargin.Height()));
132
133 basegfx::B2DPolygon aPoly(basegfx::utils::createPolygonFromRect(rRange));
134
135 const drawinglayer::primitive2d::Primitive2DReference aBg(
136 new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPoly), getBaseColor().getBColor()));
137
138 basegfx::BColor aBorderColor(0.5, 0.5, 0.5);
139 const drawinglayer::primitive2d::Primitive2DReference aBorder(
140 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
141 aPoly, aBorderColor));
142
143 aSeq.insert(aSeq.begin(), aBorder);
144 aSeq.insert(aSeq.begin(), aBg);
145
146 return aSeq;
147 }
148
createOverlayObjectPrimitive2DSequence()149 drawinglayer::primitive2d::Primitive2DContainer ScOverlayHint::createOverlayObjectPrimitive2DSequence()
150 {
151 basegfx::B2DRange aRange;
152 return createOverlaySequence(m_nLeft, m_nTop, m_aMapMode, aRange);
153 }
154
GetSizePixel() const155 Size ScOverlayHint::GetSizePixel() const
156 {
157 basegfx::B2DRange aRange;
158 createOverlaySequence(0, 0, MapMode(MapUnit::MapPixel), aRange);
159 return Size(aRange.getWidth(), aRange.getHeight());
160 }
161
SetPos(const Point & rPos,const MapMode & rMode)162 void ScOverlayHint::SetPos(const Point& rPos, const MapMode& rMode)
163 {
164 m_nLeft = rPos.X();
165 m_nTop = rPos.Y();
166 m_aMapMode = rMode;
167 }
168
169 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
170