Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / tbxctrls / tbxcolorupdate.cxx
blobedd8357362681a86eafd0c089dbf6f805531e7ff
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/sfxbasemodel.hxx>
21 #include <sfx2/objsh.hxx>
22 #include <svx/drawitem.hxx>
23 #include <tbxcolorupdate.hxx>
24 #include <svx/svxids.hrc>
25 #include <svx/xdef.hxx>
26 #include <svx/xlineit0.hxx>
27 #include <svx/xlndsit.hxx>
29 #include <utility>
30 #include <vcl/commandinfoprovider.hxx>
31 #include <vcl/gdimtf.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/toolbox.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/weld.hxx>
36 #include <vcl/settings.hxx>
38 #include <svx/strings.hrc>
39 #include <svx/dialmgr.hxx>
41 namespace svx
43 ToolboxButtonColorUpdaterBase::ToolboxButtonColorUpdaterBase(bool bWideButton, OUString aCommandLabel,
44 OUString aCommandURL, sal_uInt16 nSlotId,
45 css::uno::Reference<css::frame::XFrame> xFrame)
46 : mbWideButton(bWideButton)
47 , mbWasHiContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
48 , mnSlotId(nSlotId)
49 , maCurColor(COL_TRANSPARENT)
50 , meImageType(vcl::ImageType::Size16)
51 , maCommandLabel(std::move(aCommandLabel))
52 , maCommandURL(std::move(aCommandURL))
53 , mxFrame(std::move(xFrame))
57 void ToolboxButtonColorUpdaterBase::Init(sal_uInt16 nSlotId)
59 if (mbWideButton)
61 Update(COL_TRANSPARENT, true);
62 return;
65 if (rtl::Reference xModel = dynamic_cast<SfxBaseModel*>(mxFrame->getController()->getModel().get()))
67 auto pDocSh = xModel->GetObjectShell();
68 StartListening(*pDocSh);
69 if (auto oColor = pDocSh->GetRecentColor(nSlotId))
71 Update(*oColor);
72 return;
76 switch (nSlotId)
78 case SID_ATTR_CHAR_COLOR:
79 case SID_ATTR_CHAR_COLOR2:
80 Update(NamedColor(COL_DEFAULT_FONT, SvxResId(RID_SVXSTR_COLOR_DEFAULT_FONT)));
81 break;
82 case SID_FRAME_LINECOLOR:
83 Update(NamedColor(COL_DEFAULT_FRAMELINE, SvxResId(RID_SVXSTR_COLOR_DEFAULT_FRAMELINE)));
84 break;
85 case SID_ATTR_CHAR_COLOR_BACKGROUND:
86 case SID_ATTR_CHAR_BACK_COLOR:
87 case SID_BACKGROUND_COLOR:
88 case SID_TABLE_CELL_BACKGROUND_COLOR:
89 Update(NamedColor(COL_DEFAULT_HIGHLIGHT, SvxResId(RID_SVXSTR_COLOR_DEFAULT_HIGHLIGHT)));
90 break;
91 case SID_ATTR_LINE_COLOR:
92 Update(NamedColor(COL_DEFAULT_SHAPE_STROKE, SvxResId(RID_SVXSTR_COLOR_DEFAULT_SHAPE_STROKE)));
93 break;
94 case SID_ATTR_FILL_COLOR:
95 Update(NamedColor(COL_DEFAULT_SHAPE_FILLING, SvxResId(RID_SVXSTR_COLOR_DEFAULT_SHAPE_FILLING)));
96 break;
97 default:
98 Update(COL_TRANSPARENT);
102 void ToolboxButtonColorUpdaterBase::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
104 if (rHint.GetId() == SfxHintId::Dying)
106 EndListeningAll();
108 else if (rHint.GetId() == SfxHintId::ColorsChanged)
110 if (auto oColor = static_cast<SfxObjectShell&>(rBC).GetRecentColor(mnSlotId))
111 Update(*oColor);
115 void ToolboxButtonColorUpdaterBase::SetRecentColor(const NamedColor &rNamedColor)
117 if (rtl::Reference xModel = dynamic_cast<SfxBaseModel*>(mxFrame->getController()->getModel().get()))
118 xModel->GetObjectShell()->SetRecentColor(mnSlotId, rNamedColor);
119 else if (!mbWideButton)
120 Update(rNamedColor);
123 VclToolboxButtonColorUpdater::VclToolboxButtonColorUpdater(
124 sal_uInt16 nSlotId, ToolBoxItemId nTbxBtnId, ToolBox* pToolBox, bool bWideButton,
125 const OUString& rCommandLabel, const OUString& rCommandURL,
126 const css::uno::Reference<css::frame::XFrame>& rFrame)
127 : ToolboxButtonColorUpdaterBase(bWideButton, rCommandLabel, rCommandURL, nSlotId, rFrame)
128 , mnBtnId(nTbxBtnId)
129 , mpTbx(pToolBox)
131 Init(nSlotId);
134 void VclToolboxButtonColorUpdater::SetQuickHelpText(const OUString& rText)
136 mpTbx->SetQuickHelpText(mnBtnId, rText);
139 OUString VclToolboxButtonColorUpdater::GetQuickHelpText() const
141 return mpTbx->GetQuickHelpText(mnBtnId);
144 void VclToolboxButtonColorUpdater::SetImage(VirtualDevice* pVirDev)
146 GDIMetaFile* pMtf = pVirDev->GetConnectMetaFile();
148 assert(pMtf && "should have been set in ToolboxButtonColorUpdaterBase::Update");
150 pMtf->Stop();
151 pMtf->WindStart();
153 Graphic aGraphic(*pMtf);
155 mpTbx->SetItemImage(mnBtnId, Image(aGraphic.GetXGraphic()));
158 VclPtr<VirtualDevice> VclToolboxButtonColorUpdater::CreateVirtualDevice() const
160 return VclPtr<VirtualDevice>::Create(*mpTbx->GetOutDev());
163 vcl::ImageType VclToolboxButtonColorUpdater::GetImageSize() const
165 return mpTbx->GetImageSize();
168 Size VclToolboxButtonColorUpdater::GetItemSize(const Size& rImageSize) const
170 if (mbWideButton)
171 return mpTbx->GetItemContentSize(mnBtnId);
172 return rImageSize;
175 ToolboxButtonColorUpdaterBase::~ToolboxButtonColorUpdaterBase()
178 void ToolboxButtonColorUpdaterBase::Update(const NamedColor &rNamedColor)
180 Update(rNamedColor.m_aColor);
182 // Also show the current color as QuickHelpText
183 OUString colorSuffix = OUString(" (%1)").replaceFirst("%1", rNamedColor.m_aName);
184 OUString colorHelpText = maCommandLabel + colorSuffix;
185 SetQuickHelpText(colorHelpText);
188 void ToolboxButtonColorUpdaterBase::Update(const Color& rColor, bool bForceUpdate)
190 vcl::ImageType eImageType = GetImageSize();
192 #ifdef IOS // tdf#126966
193 eImageType = vcl::ImageType::Size32;
194 #endif
196 const bool bSizeChanged = (meImageType != eImageType);
197 meImageType = eImageType;
198 const bool bDisplayModeChanged = (mbWasHiContrastMode != Application::GetSettings().GetStyleSettings().GetHighContrastMode());
199 Color aColor(rColor);
201 // !!! #109290# Workaround for SetFillColor with COL_AUTO
202 if (aColor == COL_AUTO)
203 aColor = COL_TRANSPARENT;
205 if ((maCurColor == aColor) && !bSizeChanged && !bDisplayModeChanged && !bForceUpdate)
206 return;
208 auto xImage = vcl::CommandInfoProvider::GetXGraphicForCommand(maCommandURL, mxFrame, meImageType);
209 Image aImage(xImage);
211 Size aItemSize = GetItemSize(aImage.GetSizePixel());
212 if (!aItemSize.Width() || !aItemSize.Height())
213 return;
215 ScopedVclPtr<VirtualDevice> pVirDev(CreateVirtualDevice());
216 pVirDev->SetOutputSizePixel(aItemSize);
217 maBmpSize = aItemSize;
219 std::unique_ptr<GDIMetaFile> xMetaFile;
220 if (RecordVirtualDevice())
222 xMetaFile.reset(new GDIMetaFile);
223 xMetaFile->SetPrefSize(pVirDev->GetOutputSize());
224 xMetaFile->SetPrefMapMode(pVirDev->GetMapMode());
225 xMetaFile->Record(pVirDev.get());
226 pVirDev->EnableOutput(false);
229 if (maBmpSize.Width() == maBmpSize.Height())
230 // tdf#84985 align color bar with icon bottom edge; integer arithmetic e.g. 26 - 26/4 <> 26 * 3/4
231 maUpdRect = tools::Rectangle(Point( 0, maBmpSize.Height() - maBmpSize.Height() / 4), Size(maBmpSize.Width(), maBmpSize.Height() / 4));
232 else
233 maUpdRect = tools::Rectangle(Point( maBmpSize.Height() + 2, 2), Point(maBmpSize.Width() - 3, maBmpSize.Height() - 3));
235 pVirDev->Push(vcl::PushFlags::CLIPREGION);
237 // tdf#135121 don't include the part of the image which we will
238 // overwrite with the target color so that for the transparent color
239 // case the original background of the device is shown
240 vcl::Region aRegion(tools::Rectangle(Point(0, 0), maBmpSize));
241 aRegion.Exclude(maUpdRect);
242 pVirDev->SetClipRegion(aRegion);
244 pVirDev->DrawImage(Point(0, 0), aImage);
246 pVirDev->Pop();
248 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
249 mbWasHiContrastMode = rStyleSettings.GetHighContrastMode();
251 if ((COL_TRANSPARENT != aColor) && (maBmpSize.Width() == maBmpSize.Height()))
252 pVirDev->SetLineColor(aColor);
253 else
254 pVirDev->SetLineColor(rStyleSettings.GetDisableColor());
256 // use not only COL_TRANSPARENT for detection of transparence,
257 // but the method/way which is designed to do that
258 const bool bIsFullyTransparent(aColor.IsFullyTransparent());
259 maCurColor = aColor;
261 if (bIsFullyTransparent)
263 pVirDev->SetFillColor();
265 else
267 pVirDev->SetFillColor(maCurColor);
270 pVirDev->DrawRect(maUpdRect);
272 SetImage(pVirDev.get());
275 OUString ToolboxButtonColorUpdaterBase::GetCurrentColorName() const
277 OUString sColorName = GetQuickHelpText();
278 // The obtained string is of format: color context (color name)
279 // Generate a substring which contains only the color name
280 sal_Int32 nStart = sColorName.indexOf('(');
281 sColorName = sColorName.copy( nStart + 1 );
282 sal_Int32 nLength = sColorName.getLength();
283 if(nLength > 0)
284 sColorName = sColorName.copy( 0, nLength - 1);
285 return sColorName;
288 ToolboxButtonColorUpdater::ToolboxButtonColorUpdater(sal_uInt16 nSlotId, const OUString& rTbxBtnId, weld::Toolbar* ptrTbx, bool bWideButton,
289 const OUString& rCommandLabel, const css::uno::Reference<css::frame::XFrame>& rFrame)
290 : ToolboxButtonColorUpdaterBase(bWideButton, rCommandLabel, rTbxBtnId, nSlotId, rFrame)
291 , msBtnId(rTbxBtnId)
292 , mpTbx(ptrTbx)
294 Init(nSlotId);
297 void ToolboxButtonColorUpdater::SetQuickHelpText(const OUString& rText)
299 mpTbx->set_item_tooltip_text(msBtnId, rText);
302 OUString ToolboxButtonColorUpdater::GetQuickHelpText() const
304 return mpTbx->get_item_tooltip_text(msBtnId);
307 void ToolboxButtonColorUpdater::SetImage(VirtualDevice* pVirDev)
309 mpTbx->set_item_image(msBtnId, pVirDev);
312 VclPtr<VirtualDevice> ToolboxButtonColorUpdater::CreateVirtualDevice() const
314 return mpTbx->create_virtual_device();
317 vcl::ImageType ToolboxButtonColorUpdater::GetImageSize() const
319 return mpTbx->get_icon_size();
322 Size ToolboxButtonColorUpdater::GetItemSize(const Size& rImageSize) const
324 auto nWidth = rImageSize.Width();
325 if (mbWideButton)
326 nWidth = nWidth * 5;
327 return Size(nWidth, rImageSize.Height());
330 ToolboxButtonLineStyleUpdater::ToolboxButtonLineStyleUpdater()
331 : m_eXLS(css::drawing::LineStyle_NONE)
332 , m_nDashStyleIndex(-1)
336 void ToolboxButtonLineStyleUpdater::Update(const com::sun::star::frame::FeatureStateEvent& rEvent)
338 if (rEvent.FeatureURL.Complete == ".uno:LineDash")
340 m_nDashStyleIndex = -1;
342 SfxObjectShell* pSh = SfxObjectShell::Current();
343 if (!pSh)
344 return;
345 const SvxDashListItem* pItem = pSh->GetItem( SID_DASH_LIST );
346 if (!pItem)
347 return;
349 XLineDashItem aDashItem;
350 aDashItem.PutValue(rEvent.State, 0);
351 const XDash& rDash = aDashItem.GetDashValue();
353 XDashListRef xLineStyleList = pItem->GetDashList();
354 for (tools::Long i = 0; i < xLineStyleList->Count(); ++i)
356 const XDashEntry* pEntry = xLineStyleList->GetDash(i);
357 const XDash& rEntry = pEntry->GetDash();
358 if (rDash == rEntry)
360 m_nDashStyleIndex = i;
361 break;
365 else if (rEvent.FeatureURL.Complete == ".uno:XLineStyle")
367 XLineStyleItem aLineStyleItem;
368 aLineStyleItem.PutValue(rEvent.State, 0);
370 m_eXLS = aLineStyleItem.GetValue();
374 int ToolboxButtonLineStyleUpdater::GetStyleIndex() const
376 int nRet;
377 switch (m_eXLS)
379 case css::drawing::LineStyle_NONE:
380 nRet = 0;
381 break;
382 case css::drawing::LineStyle_SOLID:
383 nRet = 1;
384 break;
385 default:
386 nRet = m_nDashStyleIndex + 2;
387 break;
389 return nRet;
393 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */