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 <dpcontrol.hxx>
22 #include <vcl/outdev.hxx>
23 #include <vcl/settings.hxx>
24 #include <comphelper/lok.hxx>
25 #include <scitems.hxx>
26 #include <document.hxx>
27 #include <docpool.hxx>
28 #include <patattr.hxx>
29 #include <svtools/colorcfg.hxx>
31 ScDPFieldButton::ScDPFieldButton(OutputDevice
* pOutDev
, const StyleSettings
* pStyle
, const Fraction
* pZoomY
, ScDocument
* pDoc
) :
38 mbPopupButtonMulti(false),
39 mbToggleButton(false),
40 mbToggleCollapse(false),
41 mbHasHiddenMember(false),
42 mbPopupPressed(false),
48 maZoomY
= Fraction(1, 1);
51 ScDPFieldButton::~ScDPFieldButton()
55 void ScDPFieldButton::setText(const OUString
& rText
)
60 void ScDPFieldButton::setBoundingBox(const Point
& rPos
, const Size
& rSize
, bool bLayoutRTL
)
66 // rPos is the logical-left position, adjust maPos to visual-left (inside the cell border)
67 maPos
.AdjustX( -(maSize
.Width() - 1) );
71 void ScDPFieldButton::setDrawBaseButton(bool b
)
76 void ScDPFieldButton::setDrawPopupButton(bool b
)
81 void ScDPFieldButton::setDrawPopupButtonMulti(bool b
)
83 mbPopupButtonMulti
= b
;
86 void ScDPFieldButton::setDrawToggleButton(bool b
, bool bCollapse
, sal_Int32 nIndent
)
89 mbToggleCollapse
= bCollapse
;
90 mnToggleIndent
= nIndent
;
93 void ScDPFieldButton::setHasHiddenMember(bool b
)
95 mbHasHiddenMember
= b
;
98 void ScDPFieldButton::setPopupPressed(bool b
)
103 void ScDPFieldButton::setPopupLeft(bool b
)
108 void ScDPFieldButton::draw()
110 bool bOldMapEnabled
= mpOutDev
->IsMapModeEnabled();
112 if (mpOutDev
->GetMapMode().GetMapUnit() != MapUnit::MapPixel
)
113 mpOutDev
->EnableMapMode(false);
118 tools::Rectangle
aRect(maPos
, maSize
);
119 mpOutDev
->SetLineColor(mpStyle
->GetFaceColor());
120 mpOutDev
->SetFillColor(mpStyle
->GetFaceColor());
121 mpOutDev
->DrawRect(aRect
);
124 mpOutDev
->SetLineColor(mpStyle
->GetLightColor());
125 mpOutDev
->DrawLine(maPos
, Point(maPos
.X(), maPos
.Y()+maSize
.Height()-1));
126 mpOutDev
->DrawLine(maPos
, Point(maPos
.X()+maSize
.Width()-1, maPos
.Y()));
128 mpOutDev
->SetLineColor(mpStyle
->GetShadowColor());
129 mpOutDev
->DrawLine(Point(maPos
.X(), maPos
.Y()+maSize
.Height()-1),
130 Point(maPos
.X()+maSize
.Width()-1, maPos
.Y()+maSize
.Height()-1));
131 mpOutDev
->DrawLine(Point(maPos
.X()+maSize
.Width()-1, maPos
.Y()),
132 Point(maPos
.X()+maSize
.Width()-1, maPos
.Y()+maSize
.Height()-1));
135 // Get the font and size the same way as in scenario selection (lcl_DrawOneFrame in gridwin4.cxx)
136 vcl::Font
aTextFont( mpStyle
->GetAppFont() );
139 // use ScPatternAttr::GetFont only for font size
141 mpDoc
->getCellAttributeHelper().getDefaultCellAttribute().fillFontOnly(aAttrFont
, mpOutDev
, &maZoomY
);
142 aTextFont
.SetFontSize(aAttrFont
.GetFontSize());
144 mpOutDev
->SetFont(aTextFont
);
145 mpOutDev
->SetTextColor(mpStyle
->GetButtonTextColor());
147 Point aTextPos
= maPos
;
148 tools::Long nTHeight
= mpOutDev
->GetTextHeight();
149 aTextPos
.setX(maPos
.getX() + 2); // 2 = Margin
150 aTextPos
.setY(maPos
.getY() + (maSize
.Height()-nTHeight
)/2);
152 mpOutDev
->Push(vcl::PushFlags::CLIPREGION
);
153 mpOutDev
->IntersectClipRegion(aRect
);
154 mpOutDev
->DrawText(aTextPos
, maText
);
158 if (mbPopupButton
|| mbPopupButtonMulti
)
164 mpOutDev
->EnableMapMode(bOldMapEnabled
);
167 void ScDPFieldButton::getPopupBoundingBox(Point
& rPos
, Size
& rSize
) const
169 float fScaleFactor
= mpOutDev
->GetDPIScaleFactor();
171 tools::Long nMaxSize
= 18 * fScaleFactor
; // Button max size in either dimension
173 tools::Long nW
= std::min(maSize
.getWidth() / 2, nMaxSize
);
174 tools::Long nH
= std::min(maSize
.getHeight(), nMaxSize
);
176 double fZoom
= static_cast<double>(maZoomY
) > 1.0 ? static_cast<double>(maZoomY
) : 1.0;
179 nW
= fZoom
* (nW
- 1);
180 nH
= fZoom
* (nH
- 1);
183 // #i114944# AutoFilter button is left-aligned in RTL.
184 // DataPilot button is always right-aligned for now, so text output isn't affected.
186 rPos
.setX(maPos
.getX());
188 rPos
.setX(maPos
.getX() + maSize
.getWidth() - nW
);
190 rPos
.setY(maPos
.getY() + maSize
.getHeight() - nH
);
195 void ScDPFieldButton::getToggleBoundingBox(Point
& rPos
, Size
& rSize
) const
197 const float fScaleFactor
= mpOutDev
->GetDPIScaleFactor();
199 tools::Long nMaxSize
= 13 * fScaleFactor
; // Button max size in either dimension
200 tools::Long nMargin
= 3 * fScaleFactor
;
202 tools::Long nIndent
= fScaleFactor
* o3tl::convert(mnToggleIndent
, o3tl::Length::twip
, o3tl::Length::px
);
203 tools::Long nW
= std::min(maSize
.getWidth() / 2, nMaxSize
);
204 tools::Long nH
= std::min(maSize
.getHeight(), nMaxSize
);
205 nIndent
= std::min(nIndent
, maSize
.getWidth());
207 double fZoom
= static_cast<double>(maZoomY
) > 1.0 ? static_cast<double>(maZoomY
) : 1.0;
210 nW
= fZoom
* (nW
- 1);
211 nH
= fZoom
* (nH
- 1);
212 nIndent
= fZoom
* (nIndent
-1);
213 nMargin
= fZoom
* (nMargin
- 1);
217 rPos
.setX(maPos
.getX() + nIndent
- nW
+ nMargin
);
218 rPos
.setY(maPos
.getY() + maSize
.getHeight() / 2 - nH
/ 2 + nMargin
);
219 rSize
.setWidth(nW
- nMargin
- 1);
220 rSize
.setHeight(nH
- nMargin
- 1);
223 void ScDPFieldButton::drawPopupButton()
227 getPopupBoundingBox(aPos
, aSize
);
229 float fScaleFactor
= mpOutDev
->GetDPIScaleFactor();
231 // Button background color
232 Color aFaceColor
= mpStyle
->GetFaceColor();
233 Color aBackgroundColor
234 = mbHasHiddenMember
? mpStyle
->GetHighlightColor()
235 : mbPopupPressed
? mpStyle
->GetShadowColor() : aFaceColor
;
238 mpOutDev
->SetLineColor(mpStyle
->GetLabelTextColor());
239 // If the document background is light and face color is dark, use ShadowColor instead
240 Color aDocColor
= svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
241 if (aDocColor
.IsBright() && aFaceColor
.IsDark())
242 mpOutDev
->SetLineColor(mpStyle
->GetShadowColor());
244 mpOutDev
->SetFillColor(aBackgroundColor
);
245 mpOutDev
->DrawRect(tools::Rectangle(aPos
, aSize
));
248 Color aArrowColor
= mbHasHiddenMember
? mpStyle
->GetHighlightTextColor() : mpStyle
->GetButtonTextColor();
249 // FIXME: HACK: The following DrawPolygon draws twice in lok rtl mode for some reason.
250 // => one at the correct location with fill (possibly no outline)
251 // => and the other at an x offset with outline and without fill
252 // eg. Replacing this with a DrawRect() does not have any such problems.
253 comphelper::LibreOfficeKit::isActive() ? mpOutDev
->SetLineColor() : mpOutDev
->SetLineColor(aArrowColor
);
254 mpOutDev
->SetFillColor(aArrowColor
);
256 Point
aCenter(aPos
.X() + (aSize
.Width() / 2), aPos
.Y() + (aSize
.Height() / 2));
258 Size
aArrowSize(4 * fScaleFactor
, 2 * fScaleFactor
);
260 tools::Polygon
aPoly(3);
261 aPoly
.SetPoint(Point(aCenter
.X() - aArrowSize
.Width(), aCenter
.Y() - aArrowSize
.Height()), 0);
262 aPoly
.SetPoint(Point(aCenter
.X() + aArrowSize
.Width(), aCenter
.Y() - aArrowSize
.Height()), 1);
263 aPoly
.SetPoint(Point(aCenter
.X(), aCenter
.Y() + aArrowSize
.Height()), 2);
264 mpOutDev
->DrawPolygon(aPoly
);
266 if (mbHasHiddenMember
)
268 // tiny little box to display in presence of hidden member(s).
269 Point
aBoxPos(aPos
.X() + aSize
.Width() - 5 * fScaleFactor
, aPos
.Y() + aSize
.Height() - 5 * fScaleFactor
);
270 Size
aBoxSize(3 * fScaleFactor
, 3 * fScaleFactor
);
271 mpOutDev
->DrawRect(tools::Rectangle(aBoxPos
, aBoxSize
));
275 void ScDPFieldButton::drawToggleButton()
279 getToggleBoundingBox(aPos
, aSize
);
281 // Background & outer black border
282 mpOutDev
->SetLineColor(COL_BLACK
);
283 mpOutDev
->SetFillColor();
284 mpOutDev
->DrawRect(tools::Rectangle(aPos
, aSize
));
286 Point
aCenter(aPos
.X() + aSize
.getWidth() / 2, aPos
.Y() + aSize
.getHeight() / 2);
289 Point(aPos
.X() + 2, aCenter
.Y()),
290 Point(aPos
.X() + aSize
.getWidth() - 2, aCenter
.Y()));
292 if (!mbToggleCollapse
)
295 Point(aCenter
.X(), aPos
.Y() + 2),
296 Point(aCenter
.X(), aPos
.Y() + aSize
.getHeight() - 2));
300 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */