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