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 <dpcontrol.hxx>
21
22 #include <vcl/outdev.hxx>
23 #include <vcl/settings.hxx>
24 #include <scitems.hxx>
25 #include <document.hxx>
26 #include <docpool.hxx>
27 #include <patattr.hxx>
28
ScDPFieldButton(OutputDevice * pOutDev,const StyleSettings * pStyle,const Fraction * pZoomY,ScDocument * pDoc)29 ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pStyle, const Fraction* pZoomY, ScDocument* pDoc) :
30 mpDoc(pDoc),
31 mpOutDev(pOutDev),
32 mpStyle(pStyle),
33 mbBaseButton(true),
34 mbPopupButton(false),
35 mbHasHiddenMember(false),
36 mbPopupPressed(false),
37 mbPopupLeft(false)
38 {
39 if (pZoomY)
40 maZoomY = *pZoomY;
41 else
42 maZoomY = Fraction(1, 1);
43 }
44
~ScDPFieldButton()45 ScDPFieldButton::~ScDPFieldButton()
46 {
47 }
48
setText(const OUString & rText)49 void ScDPFieldButton::setText(const OUString& rText)
50 {
51 maText = rText;
52 }
53
setBoundingBox(const Point & rPos,const Size & rSize,bool bLayoutRTL)54 void ScDPFieldButton::setBoundingBox(const Point& rPos, const Size& rSize, bool bLayoutRTL)
55 {
56 maPos = rPos;
57 maSize = rSize;
58 if (bLayoutRTL)
59 {
60 // rPos is the logical-left position, adjust maPos to visual-left (inside the cell border)
61 maPos.AdjustX( -(maSize.Width() - 1) );
62 }
63 }
64
setDrawBaseButton(bool b)65 void ScDPFieldButton::setDrawBaseButton(bool b)
66 {
67 mbBaseButton = b;
68 }
69
setDrawPopupButton(bool b)70 void ScDPFieldButton::setDrawPopupButton(bool b)
71 {
72 mbPopupButton = b;
73 }
74
setHasHiddenMember(bool b)75 void ScDPFieldButton::setHasHiddenMember(bool b)
76 {
77 mbHasHiddenMember = b;
78 }
79
setPopupPressed(bool b)80 void ScDPFieldButton::setPopupPressed(bool b)
81 {
82 mbPopupPressed = b;
83 }
84
setPopupLeft(bool b)85 void ScDPFieldButton::setPopupLeft(bool b)
86 {
87 mbPopupLeft = b;
88 }
89
draw()90 void ScDPFieldButton::draw()
91 {
92 if (mbBaseButton)
93 {
94 // Background
95 tools::Rectangle aRect(maPos, maSize);
96 mpOutDev->SetLineColor(mpStyle->GetFaceColor());
97 mpOutDev->SetFillColor(mpStyle->GetFaceColor());
98 mpOutDev->DrawRect(aRect);
99
100 // Border lines
101 mpOutDev->SetLineColor(mpStyle->GetLightColor());
102 mpOutDev->DrawLine(maPos, Point(maPos.X(), maPos.Y()+maSize.Height()-1));
103 mpOutDev->DrawLine(maPos, Point(maPos.X()+maSize.Width()-1, maPos.Y()));
104
105 mpOutDev->SetLineColor(mpStyle->GetShadowColor());
106 mpOutDev->DrawLine(Point(maPos.X(), maPos.Y()+maSize.Height()-1),
107 Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
108 mpOutDev->DrawLine(Point(maPos.X()+maSize.Width()-1, maPos.Y()),
109 Point(maPos.X()+maSize.Width()-1, maPos.Y()+maSize.Height()-1));
110
111 // Field name.
112 // Get the font and size the same way as in scenario selection (lcl_DrawOneFrame in gridwin4.cxx)
113 vcl::Font aTextFont( mpStyle->GetAppFont() );
114 if ( mpDoc )
115 {
116 // use ScPatternAttr::GetFont only for font size
117 vcl::Font aAttrFont;
118 mpDoc->GetPool()->GetDefaultItem(ATTR_PATTERN).
119 GetFont( aAttrFont, SC_AUTOCOL_BLACK, mpOutDev, &maZoomY );
120 aTextFont.SetFontSize( aAttrFont.GetFontSize() );
121 }
122 mpOutDev->SetFont(aTextFont);
123 mpOutDev->SetTextColor(mpStyle->GetButtonTextColor());
124
125 Point aTextPos = maPos;
126 tools::Long nTHeight = mpOutDev->GetTextHeight();
127 aTextPos.setX(maPos.getX() + 2); // 2 = Margin
128 aTextPos.setY(maPos.getY() + (maSize.Height()-nTHeight)/2);
129
130 mpOutDev->Push(PushFlags::CLIPREGION);
131 mpOutDev->IntersectClipRegion(aRect);
132 mpOutDev->DrawText(aTextPos, maText);
133 mpOutDev->Pop();
134 }
135
136 if (mbPopupButton)
137 drawPopupButton();
138 }
139
getPopupBoundingBox(Point & rPos,Size & rSize) const140 void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const
141 {
142 float fScaleFactor = mpOutDev->GetDPIScaleFactor();
143
144 tools::Long nMaxSize = 18 * fScaleFactor; // Button max size in either dimension
145
146 tools::Long nW = std::min(maSize.getWidth() / 2, nMaxSize);
147 tools::Long nH = std::min(maSize.getHeight(), nMaxSize);
148
149 double fZoom = static_cast<double>(maZoomY) > 1.0 ? static_cast<double>(maZoomY) : 1.0;
150 if (fZoom > 1.0)
151 {
152 nW = fZoom * (nW - 1);
153 nH = fZoom * (nH - 1);
154 }
155
156 // #i114944# AutoFilter button is left-aligned in RTL.
157 // DataPilot button is always right-aligned for now, so text output isn't affected.
158 if (mbPopupLeft)
159 rPos.setX(maPos.getX());
160 else
161 rPos.setX(maPos.getX() + maSize.getWidth() - nW);
162
163 rPos.setY(maPos.getY() + maSize.getHeight() - nH);
164 rSize.setWidth(nW);
165 rSize.setHeight(nH);
166 }
167
drawPopupButton()168 void ScDPFieldButton::drawPopupButton()
169 {
170 Point aPos;
171 Size aSize;
172 getPopupBoundingBox(aPos, aSize);
173
174 float fScaleFactor = mpOutDev->GetDPIScaleFactor();
175
176 // Background & outer black border
177 mpOutDev->SetLineColor(COL_BLACK);
178 Color aBackgroundColor
179 = mbHasHiddenMember ? mpStyle->GetHighlightColor()
180 : mbPopupPressed ? mpStyle->GetShadowColor() : mpStyle->GetFaceColor();
181 mpOutDev->SetFillColor(aBackgroundColor);
182 mpOutDev->DrawRect(tools::Rectangle(aPos, aSize));
183
184 // the arrowhead
185 Color aArrowColor = mbHasHiddenMember ? mpStyle->GetHighlightTextColor() : mpStyle->GetButtonTextColor();
186 mpOutDev->SetLineColor(aArrowColor);
187 mpOutDev->SetFillColor(aArrowColor);
188
189 Point aCenter(aPos.X() + (aSize.Width() / 2), aPos.Y() + (aSize.Height() / 2));
190
191 Size aArrowSize(4 * fScaleFactor, 2 * fScaleFactor);
192
193 tools::Polygon aPoly(3);
194 aPoly.SetPoint(Point(aCenter.X() - aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 0);
195 aPoly.SetPoint(Point(aCenter.X() + aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 1);
196 aPoly.SetPoint(Point(aCenter.X(), aCenter.Y() + aArrowSize.Height()), 2);
197 mpOutDev->DrawPolygon(aPoly);
198
199 if (mbHasHiddenMember)
200 {
201 // tiny little box to display in presence of hidden member(s).
202 Point aBoxPos(aPos.X() + aSize.Width() - 5 * fScaleFactor, aPos.Y() + aSize.Height() - 5 * fScaleFactor);
203 Size aBoxSize(3 * fScaleFactor, 3 * fScaleFactor);
204 mpOutDev->DrawRect(tools::Rectangle(aBoxPos, aBoxSize));
205 }
206 }
207
208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
209