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 <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>
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>
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())
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
)
61 Update(COL_TRANSPARENT
, true);
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
))
78 case SID_ATTR_CHAR_COLOR
:
79 case SID_ATTR_CHAR_COLOR2
:
80 Update(NamedColor(COL_DEFAULT_FONT
, SvxResId(RID_SVXSTR_COLOR_DEFAULT_FONT
)));
82 case SID_FRAME_LINECOLOR
:
83 Update(NamedColor(COL_DEFAULT_FRAMELINE
, SvxResId(RID_SVXSTR_COLOR_DEFAULT_FRAMELINE
)));
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
)));
91 case SID_ATTR_LINE_COLOR
:
92 Update(NamedColor(COL_DEFAULT_SHAPE_STROKE
, SvxResId(RID_SVXSTR_COLOR_DEFAULT_SHAPE_STROKE
)));
94 case SID_ATTR_FILL_COLOR
:
95 Update(NamedColor(COL_DEFAULT_SHAPE_FILLING
, SvxResId(RID_SVXSTR_COLOR_DEFAULT_SHAPE_FILLING
)));
98 Update(COL_TRANSPARENT
);
102 void ToolboxButtonColorUpdaterBase::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
104 if (rHint
.GetId() == SfxHintId::Dying
)
108 else if (rHint
.GetId() == SfxHintId::ColorsChanged
)
110 if (auto oColor
= static_cast<SfxObjectShell
&>(rBC
).GetRecentColor(mnSlotId
))
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
)
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
)
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");
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
171 return mpTbx
->GetItemContentSize(mnBtnId
);
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
;
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
)
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())
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));
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
);
248 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
249 mbWasHiContrastMode
= rStyleSettings
.GetHighContrastMode();
251 if ((COL_TRANSPARENT
!= aColor
) && (maBmpSize
.Width() == maBmpSize
.Height()))
252 pVirDev
->SetLineColor(aColor
);
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());
261 if (bIsFullyTransparent
)
263 pVirDev
->SetFillColor();
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();
284 sColorName
= sColorName
.copy( 0, nLength
- 1);
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
)
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();
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();
345 const SvxDashListItem
* pItem
= pSh
->GetItem( SID_DASH_LIST
);
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();
360 m_nDashStyleIndex
= i
;
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
379 case css::drawing::LineStyle_NONE
:
382 case css::drawing::LineStyle_SOLID
:
386 nRet
= m_nDashStyleIndex
+ 2;
393 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */