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 <string>
21 #include <typeinfo>
22 #include <utility>
23 
24 #include <comphelper/propertysequence.hxx>
25 #include <tools/color.hxx>
26 #include <svl/poolitem.hxx>
27 #include <svl/eitem.hxx>
28 #include <svl/itemset.hxx>
29 #include <vcl/commandinfoprovider.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/toolbox.hxx>
32 #include <vcl/bitmapaccess.hxx>
33 #include <vcl/menubtn.hxx>
34 #include <vcl/vclptr.hxx>
35 #include <svtools/valueset.hxx>
36 #include <svtools/ctrlbox.hxx>
37 #include <svl/style.hxx>
38 #include <svtools/ctrltool.hxx>
39 #include <svtools/borderhelper.hxx>
40 #include <svl/stritem.hxx>
41 #include <sfx2/tplpitem.hxx>
42 #include <sfx2/dispatch.hxx>
43 #include <sfx2/viewsh.hxx>
44 #include <sfx2/docfac.hxx>
45 #include <sfx2/templdlg.hxx>
46 #include <svl/isethint.hxx>
47 #include <sfx2/sfxstatuslistener.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <tools/urlobj.hxx>
50 #include <sfx2/childwin.hxx>
51 #include <sfx2/viewfrm.hxx>
52 #include <unotools/fontoptions.hxx>
53 #include <vcl/builderfactory.hxx>
54 #include <vcl/mnemonic.hxx>
55 #include <vcl/svapp.hxx>
56 #include <vcl/settings.hxx>
57 #include <vcl/virdev.hxx>
58 #include <svtools/colorcfg.hxx>
59 #include <com/sun/star/awt/FontDescriptor.hpp>
60 #include <com/sun/star/table/BorderLine2.hpp>
61 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
62 #include <com/sun/star/lang/XServiceInfo.hpp>
63 #include <com/sun/star/beans/XPropertySet.hpp>
64 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
65 #include <com/sun/star/frame/XDispatchProvider.hpp>
66 #include <com/sun/star/frame/XFrame.hpp>
67 #include <svx/strings.hrc>
68 #include <svx/svxitems.hrc>
69 #include <svx/svxids.hrc>
70 #include <helpids.h>
71 #include <sfx2/htmlmode.hxx>
72 #include <sfx2/sidebar/Sidebar.hxx>
73 #include <sfx2/sidebar/SidebarToolBox.hxx>
74 #include <svx/xtable.hxx>
75 #include <editeng/editids.hrc>
76 #include <editeng/fontitem.hxx>
77 #include <editeng/fhgtitem.hxx>
78 #include <editeng/boxitem.hxx>
79 #include <editeng/charreliefitem.hxx>
80 #include <editeng/contouritem.hxx>
81 #include <editeng/colritem.hxx>
82 #include <editeng/crossedoutitem.hxx>
83 #include <editeng/emphasismarkitem.hxx>
84 #include <editeng/flstitem.hxx>
85 #include <editeng/lineitem.hxx>
86 #include <editeng/postitem.hxx>
87 #include <editeng/shdditem.hxx>
88 #include <editeng/udlnitem.hxx>
89 #include <editeng/wghtitem.hxx>
90 #include <editeng/svxfont.hxx>
91 #include <editeng/cmapitem.hxx>
92 #include <svx/colorwindow.hxx>
93 #include <svx/colorbox.hxx>
94 #include <svx/drawitem.hxx>
95 #include <svx/tbcontrl.hxx>
96 #include <svx/dlgutil.hxx>
97 #include <svx/dialmgr.hxx>
98 #include <svx/PaletteManager.hxx>
99 #include <memory>
100 
101 #include <svx/framelink.hxx>
102 #include <svx/tbxcolorupdate.hxx>
103 #include <editeng/eerdll.hxx>
104 #include <editeng/editrids.hrc>
105 #include <svx/xdef.hxx>
106 #include <svx/xlnclit.hxx>
107 #include <svx/xfillit0.hxx>
108 #include <svx/xflclit.hxx>
109 #include <svl/currencytable.hxx>
110 #include <svtools/langtab.hxx>
111 #include <cppu/unotype.hxx>
112 #include <cppuhelper/supportsservice.hxx>
113 #include <officecfg/Office/Common.hxx>
114 #include <o3tl/typed_flags_set.hxx>
115 #include <bitmaps.hlst>
116 #include <sal/log.hxx>
117 #include <unotools/collatorwrapper.hxx>
118 #include <boost/property_tree/ptree.hpp>
119 
120 #define MAX_MRU_FONTNAME_ENTRIES    5
121 
122 // don't make more than 15 entries visible at once
123 #define MAX_STYLES_ENTRIES          15
124 
125 // namespaces
126 using namespace ::editeng;
127 using namespace ::com::sun::star;
128 using namespace ::com::sun::star::uno;
129 using namespace ::com::sun::star::frame;
130 using namespace ::com::sun::star::beans;
131 using namespace ::com::sun::star::lang;
132 
133 SFX_IMPL_TOOLBOX_CONTROL( SvxStyleToolBoxControl, SfxTemplateItem );
134 SFX_IMPL_TOOLBOX_CONTROL( SvxSimpleUndoRedoController, SfxStringItem );
135 
136 class SvxStyleBox_Impl : public ComboBox
137 {
138     using Window::IsVisible;
139 public:
140     SvxStyleBox_Impl( vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider,
141                         const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode );
142     virtual ~SvxStyleBox_Impl() override;
143     virtual void dispose() override;
144 
145     void            SetFamily( SfxStyleFamily eNewFamily );
IsVisible() const146     bool            IsVisible() const { return bVisible; }
147 
148     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
149     virtual bool    EventNotify( NotifyEvent& rNEvt ) override;
150     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
151     virtual void    StateChanged( StateChangedType nStateChange ) override;
152 
153     virtual void    UserDraw( const UserDrawEvent& rUDEvt ) override;
154 
SetVisibilityListener(const Link<SvxStyleBox_Impl &,void> & aVisListener)155     void            SetVisibilityListener( const Link<SvxStyleBox_Impl&,void>& aVisListener ) { aVisibilityListener = aVisListener; }
156 
SetDefaultStyle(const OUString & rDefault)157     void            SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; }
158     virtual boost::property_tree::ptree DumpAsPropertyTree() override;
159 
160 protected:
161     /// Calculate the optimal width of the dropdown.  Very expensive operation, triggers lots of font measurement.
162     DECL_LINK(CalcOptimalExtraUserWidth, VclWindowEvent&, void);
163 
164     virtual void    Select() override;
165 
166 private:
167     SfxStyleFamily                  eStyleFamily;
168     sal_Int32                       nCurSel;
169     bool                            bRelease;
170     Size const                      aLogicalSize;
171     Link<SvxStyleBox_Impl&,void>    aVisibilityListener;
172     bool                            bVisible;
173     Reference< XDispatchProvider >  m_xDispatchProvider;
174     Reference< XFrame >             m_xFrame;
175     OUString const                  m_aCommand;
176     OUString const                  aClearFormatKey;
177     OUString const                  aMoreKey;
178     OUString                        sDefaultStyle;
179     bool const                      bInSpecialMode;
180     VclPtr<MenuButton>              m_pButtons[MAX_STYLES_ENTRIES];
181     VclBuilder                      m_aBuilder;
182     VclPtr<PopupMenu>               m_pMenu;
183 
184     void            ReleaseFocus();
185     static Color    TestColorsVisible(const Color &FontCol, const Color &BackCol);
186     static void     UserDrawEntry(const UserDrawEvent& rUDEvt, const OUString &rStyleName);
187     void            SetupEntry(vcl::RenderContext& rRenderContext, vcl::Window* pParent, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected);
188     static bool     AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rectangle const & rTextRect, long nHeight);
189     void            SetOptimalSize();
190     DECL_LINK( MenuSelectHdl, Menu *, bool );
191     DECL_STATIC_LINK(SvxStyleBox_Impl, ShowMoreHdl, void*, void);
192 };
193 
194 class SvxFontNameBox_Impl : public FontNameBox
195 {
196     using Window::Update;
197 private:
198     const FontList*                pFontList;
199     ::std::unique_ptr<FontList>    m_aOwnFontList;
200     vcl::Font                      aCurFont;
201     Size const                     aLogicalSize;
202     OUString                       aCurText;
203     sal_uInt16                     nFtCount;
204     bool                           bRelease;
205     Reference< XDispatchProvider > m_xDispatchProvider;
206     Reference< XFrame >            m_xFrame;
207     bool            mbEndPreview;
208     bool            mbCheckingUnknownFont;
209 
210     void            ReleaseFocus_Impl();
211     void            EnableControls_Impl();
212 
EndPreview()213     void            EndPreview()
214     {
215         Sequence< PropertyValue > aArgs;
216         SfxToolBoxControl::Dispatch( m_xDispatchProvider,
217                                          ".uno:CharEndPreviewFontName",
218                                          aArgs );
219     }
220     DECL_LINK( CheckAndMarkUnknownFont, VclWindowEvent&, void );
221 
222     void            SetOptimalSize();
223 
224 protected:
225     virtual void    Select() override;
226     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
227 
228 public:
229     SvxFontNameBox_Impl( vcl::Window* pParent, const Reference< XDispatchProvider >& rDispatchProvider,const Reference< XFrame >& _xFrame
230         , WinBits nStyle
231         );
232     virtual ~SvxFontNameBox_Impl() override;
233     virtual void dispose() override;
234 
235     void            FillList();
236     void            Update( const css::awt::FontDescriptor* pFontDesc );
GetListCount() const237     sal_uInt16      GetListCount() const { return nFtCount; }
Clear()238     void            Clear() { FontNameBox::Clear(); nFtCount = 0; }
Fill(const FontList * pList)239     void            Fill( const FontList* pList )
240                         { FontNameBox::Fill( pList );
241                           nFtCount = pList->GetFontNameCount(); }
242     virtual void    UserDraw( const UserDrawEvent& rUDEvt ) override;
243     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
244     virtual bool    EventNotify( NotifyEvent& rNEvt ) override;
245     virtual Reference< css::accessibility::XAccessible > CreateAccessible() override;
SetOwnFontList(::std::unique_ptr<FontList> && _aOwnFontList)246     void     SetOwnFontList(::std::unique_ptr<FontList> && _aOwnFontList) { m_aOwnFontList = std::move(_aOwnFontList); }
247     virtual boost::property_tree::ptree DumpAsPropertyTree() override;
248 };
249 
250 // SelectHdl needs the Modifiers, get them in MouseButtonUp
251 class SvxFrmValueSet_Impl : public ValueSet
252 {
253     sal_uInt16          nModifier;
254     virtual void    MouseButtonUp( const MouseEvent& rMEvt ) override;
255 public:
SvxFrmValueSet_Impl(vcl::Window * pParent,WinBits nWinStyle)256     SvxFrmValueSet_Impl(vcl::Window* pParent,  WinBits nWinStyle)
257         : ValueSet(pParent, nWinStyle), nModifier(0) {}
GetModifier() const258     sal_uInt16          GetModifier() const {return nModifier;}
259 
260 };
261 
MouseButtonUp(const MouseEvent & rMEvt)262 void SvxFrmValueSet_Impl::MouseButtonUp( const MouseEvent& rMEvt )
263 {
264     nModifier = rMEvt.GetModifier();
265     ValueSet::MouseButtonUp(rMEvt);
266 }
267 
268 class SvxFrameWindow_Impl : public svtools::ToolbarPopup
269 {
270 private:
271     VclPtr<SvxFrmValueSet_Impl> aFrameSet;
272     svt::ToolboxController&     mrController;
273     std::vector<BitmapEx>       aImgVec;
274     bool                        bParagraphMode;
275 
276     void InitImageList();
277     void CalcSizeValueSet();
278     DECL_LINK( SelectHdl, ValueSet*, void );
279 
280 protected:
281     virtual void    GetFocus() override;
282     virtual void    KeyInput( const KeyEvent& rKEvt ) override;
283 
284 public:
285     SvxFrameWindow_Impl( svt::ToolboxController& rController, vcl::Window* pParentWindow );
286     virtual ~SvxFrameWindow_Impl() override;
287     virtual void dispose() override;
288 
289     virtual void    statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
290     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
291 };
292 
293 namespace
294 {
295     class LineListBox final : public ListBox
296     {
297     public:
298         typedef Color (*ColorFunc)(Color);
299         typedef Color (*ColorDistFunc)(Color, Color);
300 
301                         LineListBox( vcl::Window* pParent );
302         virtual         ~LineListBox() override;
303         virtual void    dispose() override;
304 
305         /** Set the width in Twips */
SetWidth(long nWidth)306         void SetWidth( long nWidth )
307         {
308             long nOldWidth = m_nWidth;
309             m_nWidth = nWidth;
310             UpdateEntries( nOldWidth );
311         }
312 
SetNone(const OUString & sNone)313         void SetNone( const OUString& sNone )
314         {
315             m_sNone = sNone;
316         }
317 
318         using ListBox::InsertEntry;
319         /** Insert a listbox entry with all widths in Twips. */
320         void            InsertEntry(const BorderWidthImpl& rWidthImpl,
321                             SvxBorderLineStyle nStyle, long nMinWidth = 0,
322                             ColorFunc pColor1Fn = &sameColor,
323                             ColorFunc pColor2Fn = &sameColor,
324                             ColorDistFunc pColorDistFn = &sameDistColor);
325 
326         SvxBorderLineStyle GetEntryStyle( sal_Int32 nPos ) const;
327 
328         SvxBorderLineStyle GetSelectEntryStyle() const;
329 
SetSourceUnit(FieldUnit eNewUnit)330         void            SetSourceUnit( FieldUnit eNewUnit ) { eSourceUnit = eNewUnit; }
331 
GetColor() const332         const Color&    GetColor() const { return aColor; }
333 
334     private:
335 
336         void         ImpGetLine(long nLine1, long nLine2, long nDistance,
337                                 Color nColor1, Color nColor2, Color nColorDist,
338                                 SvxBorderLineStyle nStyle, BitmapEx& rBmp);
339         using Window::ImplInit;
340         void            UpdatePaintLineColor();       // returns sal_True if maPaintCol has changed
341         virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
342 
343         void            UpdateEntries( long nOldWidth );
344         sal_Int32       GetStylePos( sal_Int32  nListPos, long nWidth );
345 
GetPaintColor() const346         const Color& GetPaintColor() const
347         {
348             return maPaintCol;
349         }
350 
351         Color   GetColorLine1( sal_Int32  nPos );
352         Color   GetColorLine2( sal_Int32  nPos );
353         Color   GetColorDist( sal_Int32  nPos );
354 
355                         LineListBox( const LineListBox& ) = delete;
356         LineListBox&    operator =( const LineListBox& ) = delete;
357 
358         std::vector<std::unique_ptr<ImpLineListData>> m_vLineList;
359         long            m_nWidth;
360         OUString        m_sNone;
361         ScopedVclPtr<VirtualDevice>   aVirDev;
362         Size            aTxtSize;
363         Color const     aColor;
364         Color           maPaintCol;
365         FieldUnit       eSourceUnit;
366     };
367 
GetSelectEntryStyle() const368     SvxBorderLineStyle LineListBox::GetSelectEntryStyle() const
369     {
370         SvxBorderLineStyle nStyle = SvxBorderLineStyle::SOLID;
371         sal_Int32 nPos = GetSelectedEntryPos();
372         if ( nPos != LISTBOX_ENTRY_NOTFOUND )
373         {
374             if (!m_sNone.isEmpty())
375                 nPos--;
376             nStyle = GetEntryStyle( nPos );
377         }
378 
379         return nStyle;
380     }
381 
ImpGetLine(long nLine1,long nLine2,long nDistance,Color aColor1,Color aColor2,Color aColorDist,SvxBorderLineStyle nStyle,BitmapEx & rBmp)382     void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance,
383                                 Color aColor1, Color aColor2, Color aColorDist,
384                                 SvxBorderLineStyle nStyle, BitmapEx& rBmp )
385     {
386         //TODO, rather than including the " " text to force
387         //the line height, better would be do drop
388         //this calculation and draw a bitmap of height
389         //equal to normal text line and center the
390         //line within that
391         long nMinWidth = GetTextWidth("----------");
392         Size aSize = CalcSubEditSize();
393         aSize.setWidth( std::max(nMinWidth, aSize.Width()) );
394         aSize.AdjustWidth( -(aTxtSize.Width()) );
395         aSize.AdjustWidth( -6 );
396         aSize.setHeight( aTxtSize.Height() );
397 
398         // SourceUnit to Twips
399         if ( eSourceUnit == FieldUnit::POINT )
400         {
401             nLine1      /= 5;
402             nLine2      /= 5;
403             nDistance   /= 5;
404         }
405 
406         // Paint the lines
407         aSize = aVirDev->PixelToLogic( aSize );
408         long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height();
409         sal_uInt32 n1 = nLine1;
410         sal_uInt32 n2 = nLine2;
411         long nDist  = nDistance;
412         n1 += nPix-1;
413         n1 -= n1%nPix;
414         if ( n2 )
415         {
416             nDist += nPix-1;
417             nDist -= nDist%nPix;
418             n2    += nPix-1;
419             n2    -= n2%nPix;
420         }
421         long nVirHeight = n1+nDist+n2;
422         if ( nVirHeight > aSize.Height() )
423             aSize.setHeight( nVirHeight );
424         // negative width should not be drawn
425         if ( aSize.Width() <= 0 )
426             return;
427 
428         Size aVirSize = aVirDev->LogicToPixel( aSize );
429         if ( aVirDev->GetOutputSizePixel() != aVirSize )
430             aVirDev->SetOutputSizePixel( aVirSize );
431         aVirDev->SetFillColor( aColorDist );
432         aVirDev->DrawRect( tools::Rectangle( Point(), aSize ) );
433 
434         aVirDev->SetFillColor( aColor1 );
435 
436         double y1 = double( n1 ) / 2;
437         svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle );
438 
439         if ( n2 )
440         {
441             double y2 =  n1 + nDist + double( n2 ) / 2;
442             aVirDev->SetFillColor( aColor2 );
443             svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, SvxBorderLineStyle::SOLID );
444         }
445         rBmp = aVirDev->GetBitmapEx( Point(), Size( aSize.Width(), n1+nDist+n2 ) );
446     }
447 
LineListBox(vcl::Window * pParent)448     LineListBox::LineListBox( vcl::Window* pParent ) :
449         ListBox( pParent, WB_BORDER ),
450         m_nWidth( 5 ),
451         m_sNone( ),
452         aVirDev( VclPtr<VirtualDevice>::Create() ),
453         aColor( COL_BLACK ),
454         maPaintCol( COL_BLACK )
455     {
456         aTxtSize.setWidth( GetTextWidth( " " ) );
457         aTxtSize.setHeight( GetTextHeight() );
458         eSourceUnit = FieldUnit::POINT;
459 
460         aVirDev->SetLineColor();
461         aVirDev->SetMapMode( MapMode( MapUnit::MapTwip ) );
462 
463         UpdatePaintLineColor();
464     }
465 
~LineListBox()466     LineListBox::~LineListBox()
467     {
468         disposeOnce();
469     }
470 
dispose()471     void LineListBox::dispose()
472     {
473         m_vLineList.clear();
474         ListBox::dispose();
475     }
476 
GetStylePos(sal_Int32 nListPos,long nWidth)477     sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, long nWidth )
478     {
479         sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
480         if (!m_sNone.isEmpty())
481             nListPos--;
482 
483         sal_Int32 n = 0;
484         size_t i = 0;
485         size_t nCount = m_vLineList.size();
486         while ( nPos == LISTBOX_ENTRY_NOTFOUND && i < nCount )
487         {
488             auto& pData = m_vLineList[ i ];
489             if ( pData->GetMinWidth() <= nWidth )
490             {
491                 if ( nListPos == n )
492                     nPos = static_cast<sal_Int32>(i);
493                 n++;
494             }
495             i++;
496         }
497 
498         return nPos;
499     }
500 
InsertEntry(const BorderWidthImpl & rWidthImpl,SvxBorderLineStyle nStyle,long nMinWidth,ColorFunc pColor1Fn,ColorFunc pColor2Fn,ColorDistFunc pColorDistFn)501     void LineListBox::InsertEntry(
502         const BorderWidthImpl& rWidthImpl, SvxBorderLineStyle nStyle, long nMinWidth,
503         ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn )
504     {
505         m_vLineList.emplace_back(new ImpLineListData(
506             rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn));
507     }
508 
GetEntryStyle(sal_Int32 nPos) const509     SvxBorderLineStyle LineListBox::GetEntryStyle( sal_Int32 nPos ) const
510     {
511         ImpLineListData* pData = (0 <= nPos && static_cast<size_t>(nPos) < m_vLineList.size()) ? m_vLineList[ nPos ].get() : nullptr;
512         return pData ? pData->GetStyle() : SvxBorderLineStyle::NONE;
513     }
514 
UpdatePaintLineColor()515     void LineListBox::UpdatePaintLineColor()
516     {
517         const StyleSettings&    rSettings = GetSettings().GetStyleSettings();
518         Color                   aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor );
519 
520         bool bRet = aNewCol != maPaintCol;
521 
522         if( bRet )
523             maPaintCol = aNewCol;
524     }
525 
UpdateEntries(long nOldWidth)526     void LineListBox::UpdateEntries( long nOldWidth )
527     {
528         SetUpdateMode( false );
529 
530         UpdatePaintLineColor( );
531 
532         sal_Int32      nSelEntry = GetSelectedEntryPos();
533         sal_Int32       nTypePos = GetStylePos( nSelEntry, nOldWidth );
534 
535         // Remove the old entries
536         while ( GetEntryCount( ) > 0 )
537             ListBox::RemoveEntry( 0 );
538 
539         // Add the new entries based on the defined width
540         if (!m_sNone.isEmpty())
541             ListBox::InsertEntry( m_sNone );
542 
543         sal_uInt16 n = 0;
544         sal_uInt16 nCount = m_vLineList.size( );
545         while ( n < nCount )
546         {
547             auto& pData = m_vLineList[ n ];
548             if ( pData->GetMinWidth() <= m_nWidth )
549             {
550                 BitmapEx aBmp;
551                 ImpGetLine( pData->GetLine1ForWidth( m_nWidth ),
552                         pData->GetLine2ForWidth( m_nWidth ),
553                         pData->GetDistForWidth( m_nWidth ),
554                         GetColorLine1( GetEntryCount( ) ),
555                         GetColorLine2( GetEntryCount( ) ),
556                         GetColorDist( GetEntryCount( ) ),
557                         pData->GetStyle(), aBmp );
558                 ListBox::InsertEntry(" ", Image(aBmp));
559                 if ( n == nTypePos )
560                     SelectEntryPos( GetEntryCount() - 1 );
561             }
562             else if ( n == nTypePos )
563                 SetNoSelection();
564             n++;
565         }
566 
567         SetUpdateMode( true );
568         Invalidate();
569     }
570 
GetColorLine1(sal_Int32 nPos)571     Color LineListBox::GetColorLine1( sal_Int32 nPos )
572     {
573         sal_Int32 nStyle = GetStylePos( nPos, m_nWidth );
574         if (nStyle == LISTBOX_ENTRY_NOTFOUND)
575             return GetPaintColor( );
576         auto& pData = m_vLineList[ nStyle ];
577         return pData->GetColorLine1( GetColor( ) );
578     }
579 
GetColorLine2(sal_Int32 nPos)580     Color LineListBox::GetColorLine2( sal_Int32 nPos )
581     {
582         sal_Int32 nStyle = GetStylePos( nPos, m_nWidth );
583         if (nStyle == LISTBOX_ENTRY_NOTFOUND)
584             return GetPaintColor( );
585         auto& pData = m_vLineList[ nStyle ];
586         return pData->GetColorLine2( GetColor( ) );
587     }
588 
GetColorDist(sal_Int32 nPos)589     Color LineListBox::GetColorDist( sal_Int32 nPos )
590     {
591         Color rResult = GetSettings().GetStyleSettings().GetFieldColor();
592 
593         sal_Int32 nStyle = GetStylePos( nPos, m_nWidth );
594         if (nStyle == LISTBOX_ENTRY_NOTFOUND)
595             return rResult;
596         auto& pData = m_vLineList[ nStyle ];
597         return pData->GetColorDist( GetColor( ), rResult );
598     }
599 
DataChanged(const DataChangedEvent & rDCEvt)600     void LineListBox::DataChanged( const DataChangedEvent& rDCEvt )
601     {
602         ListBox::DataChanged( rDCEvt );
603 
604         if( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
605             UpdateEntries( m_nWidth );
606     }
607 }
608 
609 class SvxLineWindow_Impl : public svtools::ToolbarPopup
610 {
611 private:
612     VclPtr<LineListBox> m_aLineStyleLb;
613     svt::ToolboxController& m_rController;
614     bool                m_bIsWriter;
615 
616     DECL_LINK( SelectHdl, ListBox&, void );
617 
618 protected:
619     virtual void    Resize() override;
620     virtual void    GetFocus() override;
621 public:
622     SvxLineWindow_Impl( svt::ToolboxController& rController, vcl::Window* pParentWindow );
~SvxLineWindow_Impl()623     virtual ~SvxLineWindow_Impl() override { disposeOnce(); }
dispose()624     virtual void dispose() override { m_aLineStyleLb.disposeAndClear(); ToolbarPopup::dispose(); }
625 };
626 
627 class SvxCurrencyList_Impl : public svtools::ToolbarPopup
628 {
629 private:
630     VclPtr<ListBox> m_pCurrencyLb;
631     rtl::Reference<SvxCurrencyToolBoxControl> m_xControl;
632     OUString&       m_rSelectedFormat;
633     LanguageType&   m_eSelectedLanguage;
634 
635     std::vector<OUString> m_aFormatEntries;
636     LanguageType          m_eFormatLanguage;
637     DECL_LINK( SelectHdl, ListBox&, void );
638 
639 public:
640     SvxCurrencyList_Impl( SvxCurrencyToolBoxControl* pControl,
641                           vcl::Window* pParentWindow,
642                           OUString&     rSelectFormat,
643                           LanguageType& eSelectLanguage );
~SvxCurrencyList_Impl()644     virtual ~SvxCurrencyList_Impl() override { disposeOnce(); }
645     virtual void dispose() override;
646 };
647 
648 class SvxStyleToolBoxControl;
649 
650 class SfxStyleControllerItem_Impl : public SfxStatusListener
651 {
652     public:
653         SfxStyleControllerItem_Impl( const Reference< XDispatchProvider >& rDispatchProvider,
654                                      sal_uInt16 nSlotId,
655                                      const OUString& rCommand,
656                                      SvxStyleToolBoxControl& rTbxCtl );
657 
658     protected:
659         virtual void StateChanged( SfxItemState eState, const SfxPoolItem* pState ) override;
660 
661     private:
662         SvxStyleToolBoxControl& rControl;
663 };
664 
665 #define BUTTON_WIDTH 20
666 #define BUTTON_PADDING 10
667 #define ITEM_HEIGHT 30
668 
SvxStyleBox_Impl(vcl::Window * pParent,const OUString & rCommand,SfxStyleFamily eFamily,const Reference<XDispatchProvider> & rDispatchProvider,const Reference<XFrame> & _xFrame,const OUString & rClearFormatKey,const OUString & rMoreKey,bool bInSpec)669 SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent,
670                                    const OUString& rCommand,
671                                    SfxStyleFamily eFamily,
672                                    const Reference< XDispatchProvider >& rDispatchProvider,
673                                    const Reference< XFrame >& _xFrame,
674                                    const OUString& rClearFormatKey,
675                                    const OUString& rMoreKey,
676                                    bool bInSpec)
677     : ComboBox(pParent, WB_SORT | WB_BORDER | WB_HIDE | WB_DROPDOWN | WB_AUTOHSCROLL)
678     , eStyleFamily( eFamily )
679     , nCurSel(0)
680     , bRelease( true )
681     , aLogicalSize(60, 86)
682     , bVisible(false)
683     , m_xDispatchProvider( rDispatchProvider )
684     , m_xFrame(_xFrame)
685     , m_aCommand( rCommand )
686     , aClearFormatKey( rClearFormatKey )
687     , aMoreKey( rMoreKey )
688     , bInSpecialMode( bInSpec )
689     , m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/stylemenu.ui", "")
690     , m_pMenu(m_aBuilder.get_menu("menu"))
691 {
692     SetHelpId(HID_STYLE_LISTBOX);
693     m_pMenu->SetSelectHdl( LINK( this, SvxStyleBox_Impl, MenuSelectHdl ) );
694     for(VclPtr<MenuButton> & rpButton : m_pButtons)
695         rpButton = nullptr;
696     SetOptimalSize();
697     EnableAutocomplete( true );
698     EnableUserDraw( true );
699     AddEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth));
700     SetUserItemSize( Size( 0, ITEM_HEIGHT ) );
701     set_id("applystyle");
702 }
703 
~SvxStyleBox_Impl()704 SvxStyleBox_Impl::~SvxStyleBox_Impl()
705 {
706     disposeOnce();
707 }
708 
dispose()709 void SvxStyleBox_Impl::dispose()
710 {
711     RemoveEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth));
712 
713     for (VclPtr<MenuButton>& rButton : m_pButtons)
714     {
715         rButton.disposeAndClear();
716     }
717 
718     m_pMenu.clear();
719     m_aBuilder.disposeBuilder();
720 
721     ComboBox::dispose();
722 }
723 
ReleaseFocus()724 void SvxStyleBox_Impl::ReleaseFocus()
725 {
726     if ( !bRelease )
727     {
728         bRelease = true;
729         return;
730     }
731     if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() )
732         m_xFrame->getContainerWindow()->setFocus();
733 }
734 
IMPL_LINK(SvxStyleBox_Impl,MenuSelectHdl,Menu *,pMenu,bool)735 IMPL_LINK( SvxStyleBox_Impl, MenuSelectHdl, Menu*, pMenu, bool)
736 {
737     OUString sEntry = GetSelectedEntry();
738     OString sMenuIdent = pMenu->GetCurItemIdent();
739     ReleaseFocus(); // It must be after getting entry pos!
740     if (IsInDropDown())
741         ToggleDropDown();
742     Sequence< PropertyValue > aArgs( 2 );
743     aArgs[0].Name   = "Param";
744     aArgs[0].Value  <<= sEntry;
745     aArgs[1].Name   = "Family";
746     aArgs[1].Value  <<= sal_Int16( eStyleFamily );
747 
748     if (sMenuIdent == "update")
749     {
750         SfxToolBoxControl::Dispatch( m_xDispatchProvider,
751             ".uno:StyleUpdateByExample", aArgs );
752     }
753     else if (sMenuIdent == "edit")
754     {
755         SfxToolBoxControl::Dispatch( m_xDispatchProvider,
756             ".uno:EditStyle", aArgs );
757     }
758 
759     return false;
760 }
761 
IMPL_STATIC_LINK_NOARG(SvxStyleBox_Impl,ShowMoreHdl,void *,void)762 IMPL_STATIC_LINK_NOARG(SvxStyleBox_Impl, ShowMoreHdl, void*, void)
763 {
764     SfxViewFrame* pViewFrm = SfxViewFrame::Current();
765     DBG_ASSERT( pViewFrm, "SvxStyleBox_Impl::Select(): no viewframe" );
766     if (!pViewFrm)
767         return;
768     pViewFrm->ShowChildWindow(SID_SIDEBAR);
769     ::sfx2::sidebar::Sidebar::ShowPanel("StyleListPanel", pViewFrm->GetFrame().GetFrameInterface(), true);
770 }
771 
Select()772 void SvxStyleBox_Impl::Select()
773 {
774     // Tell base class about selection so that AT get informed about it.
775     ComboBox::Select();
776 
777     if ( IsTravelSelect() )
778         return;
779 
780     OUString aSearchEntry( GetText() );
781     bool bDoIt = true, bClear = false;
782     if( bInSpecialMode )
783     {
784         if( aSearchEntry == aClearFormatKey && GetSelectedEntryPos() == 0 )
785         {
786             aSearchEntry = sDefaultStyle;
787             bClear = true;
788             //not only apply default style but also call 'ClearFormatting'
789             Sequence< PropertyValue > aEmptyVals;
790             SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:ResetAttributes",
791                 aEmptyVals);
792         }
793         else if( aSearchEntry == aMoreKey && GetSelectedEntryPos() == ( GetEntryCount() - 1 ) )
794         {
795             Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Impl, ShowMoreHdl));
796             //tdf#113214 change text back to previous entry
797             SetText(GetSavedValue());
798             bDoIt = false;
799         }
800     }
801 
802     //Do we need to create a new style?
803     SfxObjectShell *pShell = SfxObjectShell::Current();
804     SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool();
805     SfxStyleSheetBase* pStyle = nullptr;
806 
807     bool bCreateNew = false;
808 
809     if ( pPool )
810     {
811         pPool->SetSearchMask( eStyleFamily );
812 
813         pStyle = pPool->First();
814         while ( pStyle && pStyle->GetName() != aSearchEntry )
815             pStyle = pPool->Next();
816     }
817 
818     if ( !pStyle )
819     {
820         // cannot find the style for whatever reason
821         // therefore create a new style
822         bCreateNew = true;
823     }
824 
825     /*  #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
826         This instance may be deleted in the meantime (i.e. when a dialog is opened
827         while in Dispatch()), accessing members will crash in this case. */
828     ReleaseFocus();
829 
830     if( bDoIt )
831     {
832         if ( bClear )
833             SetText( aSearchEntry );
834         SaveValue();
835 
836         Sequence< PropertyValue > aArgs( 2 );
837         aArgs[0].Value  <<= aSearchEntry;
838         aArgs[1].Name   = "Family";
839         aArgs[1].Value  <<= sal_Int16( eStyleFamily );
840         if( bCreateNew )
841         {
842             aArgs[0].Name   = "Param";
843             SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:StyleNewByExample", aArgs);
844         }
845         else
846         {
847             aArgs[0].Name   = "Template";
848             SfxToolBoxControl::Dispatch( m_xDispatchProvider, m_aCommand, aArgs );
849         }
850     }
851 }
852 
SetFamily(SfxStyleFamily eNewFamily)853 void SvxStyleBox_Impl::SetFamily( SfxStyleFamily eNewFamily )
854 {
855     eStyleFamily = eNewFamily;
856 }
857 
PreNotify(NotifyEvent & rNEvt)858 bool SvxStyleBox_Impl::PreNotify( NotifyEvent& rNEvt )
859 {
860     MouseNotifyEvent nType = rNEvt.GetType();
861 
862     if ( MouseNotifyEvent::MOUSEBUTTONDOWN == nType || MouseNotifyEvent::GETFOCUS == nType )
863         nCurSel = GetSelectedEntryPos();
864     else if ( MouseNotifyEvent::LOSEFOCUS == nType )
865     {
866         // don't handle before our Select() is called
867         if (!HasFocus() && !HasChildPathFocus() && !IsChild(rNEvt.GetWindow()))
868             SetText( GetSavedValue() );
869     }
870     return ComboBox::PreNotify( rNEvt );
871 }
872 
EventNotify(NotifyEvent & rNEvt)873 bool SvxStyleBox_Impl::EventNotify( NotifyEvent& rNEvt )
874 {
875     bool bHandled = false;
876 
877     if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
878     {
879         sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
880 
881         switch ( nCode )
882         {
883             case KEY_CONTEXTMENU:
884             {
885                 if(IsInDropDown())
886                 {
887                     const sal_Int32 nItem = GetSelectedEntryPos() - 1;
888                     if(nItem < MAX_STYLES_ENTRIES)
889                         m_pButtons[nItem]->ExecuteMenu();
890                     bHandled = true;
891                 }
892                 break;
893             }
894             case KEY_RETURN:
895             case KEY_TAB:
896             {
897                 if ( KEY_TAB == nCode )
898                     bRelease = false;
899                 else
900                     bHandled = true;
901                 Select();
902                 break;
903             }
904 
905             case KEY_ESCAPE:
906                 SelectEntryPos( nCurSel );
907                 if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) )
908                     ReleaseFocus();
909                 bHandled = true;
910                 break;
911         }
912     }
913     return bHandled || ComboBox::EventNotify( rNEvt );
914 }
915 
DataChanged(const DataChangedEvent & rDCEvt)916 void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
917 {
918     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
919          (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
920     {
921         SetOptimalSize();
922     }
923 
924     ComboBox::DataChanged( rDCEvt );
925 }
926 
StateChanged(StateChangedType nStateChange)927 void SvxStyleBox_Impl::StateChanged( StateChangedType nStateChange )
928 {
929     ComboBox::StateChanged( nStateChange );
930 
931     if ( nStateChange == StateChangedType::Visible )
932     {
933         bVisible = IsReallyVisible();
934         aVisibilityListener.Call( *this );
935     }
936     else if ( nStateChange == StateChangedType::InitShow )
937     {
938         bVisible = true;
939         aVisibilityListener.Call( *this );
940     }
941 }
942 
AdjustFontForItemHeight(OutputDevice * pDevice,tools::Rectangle const & rTextRect,long nHeight)943 bool SvxStyleBox_Impl::AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rectangle const & rTextRect, long nHeight)
944 {
945     if (rTextRect.Bottom() > nHeight)
946     {
947         // the text does not fit, adjust the font size
948         double ratio = static_cast< double >( nHeight ) / rTextRect.Bottom();
949         vcl::Font aFont(pDevice->GetFont());
950         Size aPixelSize(aFont.GetFontSize());
951         aPixelSize.setWidth( aPixelSize.Width() * ratio );
952         aPixelSize.setHeight( aPixelSize.Height() * ratio );
953         aFont.SetFontSize(aPixelSize);
954         pDevice->SetFont(aFont);
955         return true;
956     }
957     return false;
958 }
959 
SetOptimalSize()960 void SvxStyleBox_Impl::SetOptimalSize()
961 {
962     Size aSize(LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont)));
963     set_width_request(aSize.Width());
964     set_height_request(aSize.Height());
965     SetSizePixel(aSize);
966 }
967 
UserDrawEntry(const UserDrawEvent & rUDEvt,const OUString & rStyleName)968 void SvxStyleBox_Impl::UserDrawEntry(const UserDrawEvent& rUDEvt, const OUString &rStyleName)
969 {
970     vcl::RenderContext *pDevice = rUDEvt.GetRenderContext();
971 
972     // IMG_TXT_DISTANCE in ilstbox.hxx is 6, then 1 is added as
973     // nBorder, and we are adding 1 in order to look better when
974     // italics is present
975     const int nLeftDistance = 8;
976 
977     tools::Rectangle aTextRect;
978     pDevice->GetTextBoundRect(aTextRect, rStyleName);
979 
980     Point aPos( rUDEvt.GetRect().TopLeft() );
981     aPos.AdjustX(nLeftDistance );
982 
983     if (!AdjustFontForItemHeight(pDevice, aTextRect, rUDEvt.GetRect().GetHeight()))
984         aPos.AdjustY(( rUDEvt.GetRect().GetHeight() - aTextRect.Bottom() ) / 2 );
985 
986     pDevice->DrawText(aPos, rStyleName);
987 }
988 
SetupEntry(vcl::RenderContext & rRenderContext,vcl::Window * pParent,sal_Int32 nItem,const tools::Rectangle & rRect,const OUString & rStyleName,bool bIsNotSelected)989 void SvxStyleBox_Impl::SetupEntry(vcl::RenderContext& rRenderContext, vcl::Window* pParent, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected)
990 {
991     unsigned int nId = rRect.GetHeight() != 0 ? (rRect.getY() / rRect.GetHeight()) : MAX_STYLES_ENTRIES;
992     if (nItem == 0 || nItem == GetEntryCount() - 1)
993     {
994         if(nId < MAX_STYLES_ENTRIES && m_pButtons[nId])
995             m_pButtons[nId]->Hide();
996     }
997     else
998     {
999         SfxObjectShell *pShell = SfxObjectShell::Current();
1000         SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool();
1001         SfxStyleSheetBase* pStyle = nullptr;
1002 
1003         if ( pPool )
1004         {
1005             pPool->SetSearchMask( eStyleFamily );
1006 
1007             pStyle = pPool->First();
1008             while (pStyle && pStyle->GetName() != rStyleName)
1009                 pStyle = pPool->Next();
1010         }
1011 
1012         if (pStyle )
1013         {
1014             std::unique_ptr<const SfxItemSet> const pItemSet(pStyle->GetItemSetForPreview());
1015             if (!pItemSet) return;
1016 
1017             const SvxFontItem * const pFontItem =
1018                 pItemSet->GetItem<SvxFontItem>(SID_ATTR_CHAR_FONT);
1019             const SvxFontHeightItem * const pFontHeightItem =
1020                 pItemSet->GetItem<SvxFontHeightItem>(SID_ATTR_CHAR_FONTHEIGHT);
1021 
1022             if ( pFontItem && pFontHeightItem )
1023             {
1024                 Size aFontSize( 0, pFontHeightItem->GetHeight() );
1025                 Size aPixelSize(rRenderContext.LogicToPixel(aFontSize, MapMode(pShell->GetMapUnit())));
1026 
1027                 // setup the font properties
1028                 SvxFont aFont;
1029                 aFont.SetFamilyName(pFontItem->GetFamilyName());
1030                 aFont.SetStyleName(pFontItem->GetStyleName());
1031                 aFont.SetFontSize(aPixelSize);
1032 
1033                 const SfxPoolItem *pItem = pItemSet->GetItem( SID_ATTR_CHAR_WEIGHT );
1034                 if ( pItem )
1035                     aFont.SetWeight( static_cast< const SvxWeightItem* >( pItem )->GetWeight() );
1036 
1037                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_POSTURE );
1038                 if ( pItem )
1039                     aFont.SetItalic( static_cast< const SvxPostureItem* >( pItem )->GetPosture() );
1040 
1041                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_CONTOUR );
1042                 if ( pItem )
1043                     aFont.SetOutline( static_cast< const SvxContourItem* >( pItem )->GetValue() );
1044 
1045                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_SHADOWED );
1046                 if ( pItem )
1047                     aFont.SetShadow( static_cast< const SvxShadowedItem* >( pItem )->GetValue() );
1048 
1049                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_RELIEF );
1050                 if ( pItem )
1051                     aFont.SetRelief( static_cast< const SvxCharReliefItem* >( pItem )->GetValue() );
1052 
1053                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_UNDERLINE );
1054                 if ( pItem )
1055                     aFont.SetUnderline( static_cast< const SvxUnderlineItem* >( pItem )->GetLineStyle() );
1056 
1057                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_OVERLINE );
1058                 if ( pItem )
1059                     aFont.SetOverline( static_cast< const SvxOverlineItem* >( pItem )->GetValue() );
1060 
1061                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_STRIKEOUT );
1062                 if ( pItem )
1063                     aFont.SetStrikeout( static_cast< const SvxCrossedOutItem* >( pItem )->GetStrikeout() );
1064 
1065                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_CASEMAP );
1066                 if ( pItem )
1067                     aFont.SetCaseMap(static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap());
1068 
1069                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_EMPHASISMARK );
1070                 if ( pItem )
1071                     aFont.SetEmphasisMark( static_cast< const SvxEmphasisMarkItem* >( pItem )->GetEmphasisMark() );
1072 
1073                 // setup the device & draw
1074                 vcl::Font aOldFont(rRenderContext.GetFont());
1075 
1076                 Color aFontCol = COL_AUTO, aBackCol = COL_AUTO;
1077 
1078                 rRenderContext.SetFont(aFont);
1079 
1080                 pItem = pItemSet->GetItem( SID_ATTR_CHAR_COLOR );
1081                 // text color, when nothing is selected
1082                 if ( (nullptr != pItem) && bIsNotSelected)
1083                     aFontCol = static_cast< const SvxColorItem* >( pItem )->GetValue();
1084 
1085                 drawing::FillStyle style = drawing::FillStyle_NONE;
1086                 // which kind of Fill style is selected
1087                 pItem = pItemSet->GetItem( XATTR_FILLSTYLE );
1088                 // only when ok and not selected
1089                 if ( (nullptr != pItem) && bIsNotSelected)
1090                     style = static_cast< const XFillStyleItem* >( pItem )->GetValue();
1091 
1092                 switch(style)
1093                 {
1094                     case drawing::FillStyle_SOLID:
1095                     {
1096                         // set background color
1097                         pItem = pItemSet->GetItem( XATTR_FILLCOLOR );
1098                         if ( nullptr != pItem )
1099                             aBackCol = static_cast< const XFillColorItem* >( pItem )->GetColorValue();
1100 
1101                         if ( aBackCol != COL_AUTO )
1102                         {
1103                             rRenderContext.SetFillColor(aBackCol);
1104                             rRenderContext.DrawRect(rRect);
1105                         }
1106                     }
1107                     break;
1108 
1109                     default: break;
1110                     //TODO Draw the other background styles: gradient, hatching and bitmap
1111                 }
1112 
1113                 // when the font and background color are too similar, adjust the Font-Color
1114                 if( (aFontCol != COL_AUTO) || (aBackCol != COL_AUTO) )
1115                     aFontCol = TestColorsVisible(aFontCol, (aBackCol != COL_AUTO) ? aBackCol : rRenderContext.GetBackground().GetColor());
1116 
1117                 // set text color
1118                 if ( aFontCol != COL_AUTO )
1119                     rRenderContext.SetTextColor(aFontCol);
1120 
1121                 // handle the push-button
1122                 if (bIsNotSelected)
1123                 {
1124                     if (nId < MAX_STYLES_ENTRIES && m_pButtons[nId])
1125                         m_pButtons[nId]->Hide();
1126                 }
1127                 else
1128                 {
1129                     if (nId < MAX_STYLES_ENTRIES)
1130                     {
1131                         if (!m_pButtons[nId] && pParent)
1132                         {
1133                             m_pButtons[nId] = VclPtr<MenuButton>::Create(pParent, WB_FLATBUTTON | WB_NOPOINTERFOCUS);
1134                             m_pButtons[nId]->SetSizePixel(Size(BUTTON_WIDTH, rRect.GetHeight()));
1135                             m_pButtons[nId]->SetPopupMenu(m_pMenu);
1136                         }
1137                         m_pButtons[nId]->SetPosPixel(Point(rRect.GetWidth() - BUTTON_WIDTH, rRect.getY()));
1138                         m_pButtons[nId]->Show();
1139                     }
1140                 }
1141             }
1142         }
1143     }
1144 }
1145 
UserDraw(const UserDrawEvent & rUDEvt)1146 void SvxStyleBox_Impl::UserDraw( const UserDrawEvent& rUDEvt )
1147 {
1148     sal_uInt16 nItem = rUDEvt.GetItemId();
1149     OUString aStyleName( GetEntry( nItem ) );
1150 
1151     vcl::RenderContext *pDevice = rUDEvt.GetRenderContext();
1152     pDevice->Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
1153 
1154     const tools::Rectangle& rRect(rUDEvt.GetRect());
1155     bool bIsNotSelected = rUDEvt.GetItemId() != GetSelectedEntryPos();
1156 
1157     SetupEntry(*pDevice, rUDEvt.GetWindow(), nItem, rRect, aStyleName, bIsNotSelected);
1158 
1159     UserDrawEntry(rUDEvt, aStyleName);
1160 
1161     pDevice->Pop();
1162     // draw separator, if present
1163     DrawEntry( rUDEvt, false, false );
1164 }
1165 
IMPL_LINK(SvxStyleBox_Impl,CalcOptimalExtraUserWidth,VclWindowEvent &,event,void)1166 IMPL_LINK(SvxStyleBox_Impl, CalcOptimalExtraUserWidth, VclWindowEvent&, event, void)
1167 {
1168     // perform the calculation only when we are opening the dropdown
1169     if (event.GetId() != VclEventId::DropdownPreOpen)
1170         return;
1171 
1172     long nMaxNormalFontWidth = 0;
1173     sal_Int32 nEntryCount = GetEntryCount();
1174     for (sal_Int32 i = 0; i < nEntryCount; ++i)
1175     {
1176         OUString sStyleName(GetEntry(i));
1177         tools::Rectangle aTextRectForDefaultFont;
1178         GetTextBoundRect(aTextRectForDefaultFont, sStyleName);
1179 
1180         const long nWidth = aTextRectForDefaultFont.GetWidth();
1181 
1182         nMaxNormalFontWidth = std::max(nWidth, nMaxNormalFontWidth);
1183     }
1184 
1185     long nMaxUserDrawFontWidth = nMaxNormalFontWidth;
1186     for (sal_Int32 i = 1; i < nEntryCount-1; ++i)
1187     {
1188         OUString sStyleName(GetEntry(i));
1189 
1190         Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
1191         SetupEntry(*this /*FIXME rendercontext*/, this, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true);
1192         tools::Rectangle aTextRectForActualFont;
1193         GetTextBoundRect(aTextRectForActualFont, sStyleName);
1194         if (AdjustFontForItemHeight(this, aTextRectForActualFont, ITEM_HEIGHT))
1195         {
1196             //Font didn't fit, so it was changed, refetch with final font size
1197             GetTextBoundRect(aTextRectForActualFont, sStyleName);
1198         }
1199         Pop();
1200 
1201         const long nWidth = aTextRectForActualFont.GetWidth() + BUTTON_WIDTH + BUTTON_PADDING;
1202 
1203         nMaxUserDrawFontWidth = std::max(nWidth, nMaxUserDrawFontWidth);
1204     }
1205 
1206     SetUserItemSize(Size(nMaxUserDrawFontWidth - nMaxNormalFontWidth, ITEM_HEIGHT));
1207 }
1208 
1209 // test is the color between Font- and background-color to be identify
1210 // return is always the Font-Color
1211 //        when both light or dark, change the Contrast
1212 //        in other case do not change the origin color
1213 //        when the color is R=G=B=128 the DecreaseContrast make 128 the need an exception
TestColorsVisible(const Color & FontCol,const Color & BackCol)1214 Color SvxStyleBox_Impl::TestColorsVisible(const Color &FontCol, const Color &BackCol)
1215 {
1216     const sal_uInt8  ChgVal = 60;       // increase/decrease the Contrast
1217 
1218     Color  retCol = FontCol;
1219     if ((FontCol.IsDark() == BackCol.IsDark()) && (FontCol.IsBright() == BackCol.IsBright()))
1220     {
1221         sal_uInt8 lumi = retCol.GetLuminance();
1222 
1223         if((lumi > 120) && (lumi < 140))
1224             retCol.DecreaseLuminance(ChgVal / 2);
1225         else
1226             retCol.DecreaseContrast(ChgVal);
1227     }
1228 
1229     return retCol;
1230 }
1231 
DumpAsPropertyTree()1232 boost::property_tree::ptree SvxStyleBox_Impl::DumpAsPropertyTree()
1233 {
1234     boost::property_tree::ptree aTree(ComboBox::DumpAsPropertyTree());
1235 
1236     boost::property_tree::ptree aEntries;
1237 
1238     for (int i = 0; i < GetEntryCount(); ++i)
1239     {
1240         boost::property_tree::ptree aEntry;
1241         aEntry.put("", GetEntry(i));
1242         aEntries.push_back(std::make_pair("", aEntry));
1243     }
1244 
1245     aTree.add_child("entries", aEntries);
1246 
1247     boost::property_tree::ptree aSelected;
1248 
1249     for (int i = 0; i < GetSelectedEntryCount(); ++i)
1250     {
1251         boost::property_tree::ptree aEntry;
1252         aEntry.put("", GetSelectedEntryPos(i));
1253         aSelected.push_back(std::make_pair("", aEntry));
1254     }
1255 
1256     aTree.put("selectedCount", GetSelectedEntryCount());
1257     aTree.add_child("selectedEntries", aSelected);
1258     aTree.put("command", ".uno:StyleApply");
1259 
1260     return aTree;
1261 }
1262 
1263 
lcl_GetDocFontList(const FontList ** ppFontList,SvxFontNameBox_Impl * pBox)1264 static bool lcl_GetDocFontList( const FontList** ppFontList, SvxFontNameBox_Impl* pBox )
1265 {
1266     bool bChanged = false;
1267     const SfxObjectShell* pDocSh = SfxObjectShell::Current();
1268     const SvxFontListItem* pFontListItem = nullptr;
1269 
1270     if ( pDocSh )
1271         pFontListItem =
1272             static_cast<const SvxFontListItem*>(pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ));
1273     else
1274     {
1275         ::std::unique_ptr<FontList> aFontList(new FontList( pBox->GetParent() ));
1276         *ppFontList = aFontList.get();
1277         pBox->SetOwnFontList(std::move(aFontList));
1278         bChanged = true;
1279     }
1280 
1281     if ( pFontListItem )
1282     {
1283         const FontList* pNewFontList = pFontListItem->GetFontList();
1284         DBG_ASSERT( pNewFontList, "Doc-FontList not available!" );
1285 
1286         // No old list, but a new list
1287         if ( !*ppFontList && pNewFontList )
1288         {
1289             // => take over
1290             *ppFontList = pNewFontList;
1291             bChanged = true;
1292         }
1293         else
1294         {
1295             // Comparing the font lists is not perfect.
1296             // When you change the font list in the Doc, you can track
1297             // changes here only on the Listbox, because ppFontList
1298             // has already been updated.
1299             bChanged =
1300                 ( ( *ppFontList != pNewFontList ) ||
1301                   pBox->GetListCount() != pNewFontList->GetFontNameCount() );
1302             // HACK: Comparing is incomplete
1303 
1304             if ( bChanged )
1305                 *ppFontList = pNewFontList;
1306         }
1307 
1308         if ( pBox )
1309             pBox->Enable();
1310     }
1311     else if ( pBox && ( pDocSh || !ppFontList ))
1312     {
1313         // Disable box only when we have a SfxObjectShell and didn't get a font list OR
1314         // we don't have a SfxObjectShell and no current font list.
1315         // It's possible that we currently have no SfxObjectShell, but a current font list.
1316         // See #i58471: When a user set the focus into the font name combo box and opens
1317         // the help window with F1. After closing the help window, we disable the font name
1318         // combo box. The SfxObjectShell::Current() method returns in that case zero. But the
1319         // font list hasn't changed and therefore the combo box shouldn't be disabled!
1320         pBox->Disable();
1321     }
1322 
1323     // Fill the FontBox, also the new list if necessary
1324     if ( pBox && bChanged )
1325     {
1326         if ( *ppFontList )
1327             pBox->Fill( *ppFontList );
1328         else
1329             pBox->Clear();
1330     }
1331     return bChanged;
1332 }
1333 
SvxFontNameBox_Impl(vcl::Window * pParent,const Reference<XDispatchProvider> & rDispatchProvider,const Reference<XFrame> & _xFrame,WinBits nStyle)1334 SvxFontNameBox_Impl::SvxFontNameBox_Impl( vcl::Window* pParent, const Reference< XDispatchProvider >& rDispatchProvider,const Reference< XFrame >& _xFrame, WinBits nStyle ) :
1335 
1336     FontNameBox        ( pParent, nStyle | WinBits( WB_DROPDOWN | WB_AUTOHSCROLL ) ),
1337     pFontList          ( nullptr ),
1338     aLogicalSize       ( 60,160 ),
1339     nFtCount           ( 0 ),
1340     bRelease           ( true ),
1341     m_xDispatchProvider( rDispatchProvider ),
1342     m_xFrame (_xFrame),
1343     mbEndPreview(false),
1344     mbCheckingUnknownFont(false)
1345 {
1346     SetOptimalSize();
1347     EnableControls_Impl();
1348     GetSubEdit()->AddEventListener( LINK( this, SvxFontNameBox_Impl, CheckAndMarkUnknownFont ));
1349     set_id("fontnamecombobox");
1350 }
1351 
~SvxFontNameBox_Impl()1352 SvxFontNameBox_Impl::~SvxFontNameBox_Impl()
1353 {
1354     disposeOnce();
1355 }
1356 
dispose()1357 void SvxFontNameBox_Impl::dispose()
1358 {
1359     GetSubEdit()->RemoveEventListener( LINK( this, SvxFontNameBox_Impl, CheckAndMarkUnknownFont ));
1360     FontNameBox::dispose();
1361 }
1362 
FillList()1363 void SvxFontNameBox_Impl::FillList()
1364 {
1365     // Save old Selection, set back in the end
1366     Selection aOldSel = GetSelection();
1367     // Did Doc-Fontlist change?
1368     lcl_GetDocFontList( &pFontList, this );
1369     aCurText = GetText();
1370     SetSelection( aOldSel );
1371 }
1372 
IMPL_LINK(SvxFontNameBox_Impl,CheckAndMarkUnknownFont,VclWindowEvent &,event,void)1373 IMPL_LINK( SvxFontNameBox_Impl, CheckAndMarkUnknownFont, VclWindowEvent&, event, void )
1374 {
1375     if( event.GetId() != VclEventId::EditModify )
1376         return;
1377     if (mbCheckingUnknownFont) //tdf#117537 block rentry
1378         return;
1379     mbCheckingUnknownFont = true;
1380     OUString fontname = GetSubEdit()->GetText();
1381     lcl_GetDocFontList( &pFontList, this );
1382     // If the font is unknown, show it in italic.
1383     vcl::Font font = GetControlFont();
1384     if( pFontList != nullptr && pFontList->IsAvailable( fontname ))
1385     {
1386         if( font.GetItalic() != ITALIC_NONE )
1387         {
1388             font.SetItalic( ITALIC_NONE );
1389             SetControlFont( font );
1390             SetQuickHelpText( SvxResId( RID_SVXSTR_CHARFONTNAME ));
1391         }
1392     }
1393     else
1394     {
1395         if( font.GetItalic() != ITALIC_NORMAL )
1396         {
1397             font.SetItalic( ITALIC_NORMAL );
1398             SetControlFont( font );
1399             SetQuickHelpText( SvxResId( RID_SVXSTR_CHARFONTNAME_NOTAVAILABLE ));
1400         }
1401     }
1402     mbCheckingUnknownFont = false;
1403 }
1404 
Update(const css::awt::FontDescriptor * pFontDesc)1405 void SvxFontNameBox_Impl::Update( const css::awt::FontDescriptor* pFontDesc )
1406 {
1407     if ( pFontDesc )
1408     {
1409         aCurFont.SetFamilyName  ( pFontDesc->Name );
1410         aCurFont.SetFamily      ( FontFamily( pFontDesc->Family ) );
1411         aCurFont.SetStyleName   ( pFontDesc->StyleName );
1412         aCurFont.SetPitch       ( FontPitch( pFontDesc->Pitch ) );
1413         aCurFont.SetCharSet     ( rtl_TextEncoding( pFontDesc->CharSet ) );
1414     }
1415     OUString aCurName = aCurFont.GetFamilyName();
1416     if ( GetText() != aCurName )
1417         SetText( aCurName );
1418 }
1419 
PreNotify(NotifyEvent & rNEvt)1420 bool SvxFontNameBox_Impl::PreNotify( NotifyEvent& rNEvt )
1421 {
1422     MouseNotifyEvent nType = rNEvt.GetType();
1423 
1424     if ( MouseNotifyEvent::MOUSEBUTTONDOWN == nType || MouseNotifyEvent::GETFOCUS == nType )
1425     {
1426         EnableControls_Impl();
1427         FillList();
1428     }
1429     return FontNameBox::PreNotify( rNEvt );
1430 }
1431 
EventNotify(NotifyEvent & rNEvt)1432 bool SvxFontNameBox_Impl::EventNotify( NotifyEvent& rNEvt )
1433 {
1434     bool bHandled = false;
1435     mbEndPreview = false;
1436     if ( rNEvt.GetType() == MouseNotifyEvent::KEYUP )
1437         mbEndPreview = true;
1438 
1439     if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
1440     {
1441         sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
1442 
1443         switch ( nCode )
1444         {
1445             case KEY_RETURN:
1446             case KEY_TAB:
1447             {
1448                 if ( KEY_TAB == nCode )
1449                     bRelease = false;
1450                 else
1451                     bHandled = true;
1452                 Select();
1453                 break;
1454             }
1455 
1456             case KEY_ESCAPE:
1457                 SetText( aCurText );
1458                 if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) )
1459                     ReleaseFocus_Impl();
1460                 EndPreview();
1461                 break;
1462         }
1463     }
1464     else if ( MouseNotifyEvent::LOSEFOCUS == rNEvt.GetType() )
1465     {
1466         vcl::Window* pFocusWin = Application::GetFocusWindow();
1467         if ( !HasFocus() && GetSubEdit() != pFocusWin )
1468             SetText( GetSavedValue() );
1469         // send EndPreview
1470         EndPreview();
1471     }
1472 
1473     return bHandled || FontNameBox::EventNotify( rNEvt );
1474 }
1475 
SetOptimalSize()1476 void SvxFontNameBox_Impl::SetOptimalSize()
1477 {
1478     Size aSize(LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont)));
1479     set_width_request(aSize.Width());
1480     set_height_request(aSize.Height());
1481     SetSizePixel(aSize);
1482 }
1483 
DataChanged(const DataChangedEvent & rDCEvt)1484 void SvxFontNameBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
1485 {
1486     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1487          (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1488     {
1489         SetOptimalSize();
1490     }
1491     else if ( ( rDCEvt.GetType() == DataChangedEventType::FONTS ) ||
1492               ( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) )
1493     {
1494         // The old font list in shell has likely been destroyed at this point, so we need to get
1495         // the new one before doing anything further.
1496         lcl_GetDocFontList( &pFontList, this );
1497     }
1498 
1499     FontNameBox::DataChanged( rDCEvt );
1500 }
1501 
ReleaseFocus_Impl()1502 void SvxFontNameBox_Impl::ReleaseFocus_Impl()
1503 {
1504     if ( !bRelease )
1505     {
1506         bRelease = true;
1507         return;
1508     }
1509     if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() )
1510         m_xFrame->getContainerWindow()->setFocus();
1511 }
1512 
EnableControls_Impl()1513 void SvxFontNameBox_Impl::EnableControls_Impl()
1514 {
1515     SvtFontOptions aFontOpt;
1516     bool bEnable = aFontOpt.IsFontHistoryEnabled();
1517     sal_uInt16 nEntries = bEnable ? MAX_MRU_FONTNAME_ENTRIES : 0;
1518     if ( GetMaxMRUCount() != nEntries )
1519     {
1520         // refill in the next GetFocus-Handler
1521         pFontList = nullptr;
1522         Clear();
1523         SetMaxMRUCount( nEntries );
1524     }
1525 
1526     bEnable = aFontOpt.IsFontWYSIWYGEnabled();
1527     EnableWYSIWYG( bEnable );
1528 }
1529 
UserDraw(const UserDrawEvent & rUDEvt)1530 void SvxFontNameBox_Impl::UserDraw( const UserDrawEvent& rUDEvt )
1531 {
1532     FontNameBox::UserDraw( rUDEvt );
1533 
1534     // Hack - GetStyle now contains the currently
1535     // selected item in the list box
1536     // ItemId contains the id of the current item to draw
1537     // or select
1538     if (  rUDEvt.GetItemId() == rUDEvt.GetStyle() )
1539     {
1540         OUString fontName(GetText());
1541         if (IsInDropDown())
1542         {
1543             /*
1544              * when in dropdown mode the selected item should be
1545              * used and not the current selection
1546              */
1547              fontName = GetEntry(rUDEvt.GetItemId());
1548         }
1549         Sequence< PropertyValue > aArgs( 1 );
1550         FontMetric aFontMetric( pFontList->Get( fontName,
1551             aCurFont.GetWeight(),
1552             aCurFont.GetItalic() ) );
1553 
1554         SvxFontItem aFontItem( aFontMetric.GetFamilyType(),
1555             aFontMetric.GetFamilyName(),
1556             aFontMetric.GetStyleName(),
1557             aFontMetric.GetPitch(),
1558             aFontMetric.GetCharSet(),
1559             SID_ATTR_CHAR_FONT );
1560         aFontItem.QueryValue( aArgs[0].Value );
1561         aArgs[0].Name   = "CharPreviewFontName";
1562         SfxToolBoxControl::Dispatch( m_xDispatchProvider,
1563             ".uno:CharPreviewFontName",
1564                 aArgs );
1565     }
1566 }
1567 
Select()1568 void SvxFontNameBox_Impl::Select()
1569 {
1570     FontNameBox::Select();
1571 
1572     Sequence< PropertyValue > aArgs( 1 );
1573     std::unique_ptr<SvxFontItem> pFontItem;
1574     if ( pFontList )
1575     {
1576         FontMetric aFontMetric( pFontList->Get( GetText(),
1577             aCurFont.GetWeight(),
1578             aCurFont.GetItalic() ) );
1579         aCurFont = aFontMetric;
1580 
1581         pFontItem.reset( new SvxFontItem( aFontMetric.GetFamilyType(),
1582             aFontMetric.GetFamilyName(),
1583             aFontMetric.GetStyleName(),
1584             aFontMetric.GetPitch(),
1585             aFontMetric.GetCharSet(),
1586             SID_ATTR_CHAR_FONT ) );
1587 
1588         Any a;
1589         pFontItem->QueryValue( a );
1590         aArgs[0].Value  = a;
1591     }
1592     if ( !IsTravelSelect() )
1593     {
1594         //  #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
1595         //  This instance may be deleted in the meantime (i.e. when a dialog is opened
1596         //  while in Dispatch()), accessing members will crash in this case.
1597         ReleaseFocus_Impl();
1598         EndPreview();
1599         if (pFontItem)
1600         {
1601             aArgs[0].Name   = "CharFontName";
1602             SfxToolBoxControl::Dispatch( m_xDispatchProvider,
1603                                          ".uno:CharFontName",
1604                                          aArgs );
1605         }
1606     }
1607     else
1608     {
1609         if ( mbEndPreview )
1610         {
1611             EndPreview();
1612             return;
1613         }
1614         if (pFontItem)
1615         {
1616             aArgs[0].Name   = "CharPreviewFontName";
1617             SfxToolBoxControl::Dispatch( m_xDispatchProvider,
1618                                          ".uno:CharPreviewFontName",
1619                                          aArgs );
1620         }
1621     }
1622 }
1623 
DumpAsPropertyTree()1624 boost::property_tree::ptree SvxFontNameBox_Impl::DumpAsPropertyTree()
1625 {
1626     boost::property_tree::ptree aTree(FontNameBox::DumpAsPropertyTree());
1627 
1628     boost::property_tree::ptree aEntries;
1629 
1630     for (int i = 0; i < GetEntryCount(); ++i)
1631     {
1632         boost::property_tree::ptree aEntry;
1633         aEntry.put("", GetEntry(i));
1634         aEntries.push_back(std::make_pair("", aEntry));
1635     }
1636 
1637     aTree.add_child("entries", aEntries);
1638 
1639     boost::property_tree::ptree aSelected;
1640 
1641     for (int i = 0; i < GetSelectedEntryCount(); ++i)
1642     {
1643         boost::property_tree::ptree aEntry;
1644         aEntry.put("", GetSelectedEntryPos(i));
1645         aSelected.push_back(std::make_pair("", aEntry));
1646     }
1647 
1648     aTree.put("selectedCount", GetSelectedEntryCount());
1649     aTree.add_child("selectedEntries", aSelected);
1650     aTree.put("command", ".uno:CharFontName");
1651 
1652     return aTree;
1653 }
1654 
SvxColorWindow(const OUString & rCommand,std::shared_ptr<PaletteManager> const & rPaletteManager,ColorStatus & rColorStatus,sal_uInt16 nSlotId,const Reference<XFrame> & rFrame,vcl::Window * pParentWindow,bool bReuseParentForPicker,ColorSelectFunction const & aFunction)1655 SvxColorWindow::SvxColorWindow(const OUString&            rCommand,
1656                                std::shared_ptr<PaletteManager> const & rPaletteManager,
1657                                ColorStatus&               rColorStatus,
1658                                sal_uInt16                 nSlotId,
1659                                const Reference< XFrame >& rFrame,
1660                                vcl::Window*               pParentWindow,
1661                                bool                       bReuseParentForPicker,
1662                                ColorSelectFunction const & aFunction):
1663 
1664     ToolbarPopup( rFrame, pParentWindow, "palette_popup_window", "svx/ui/oldcolorwindow.ui" ),
1665     theSlotId( nSlotId ),
1666     maCommand( rCommand ),
1667     mxParentWindow(pParentWindow),
1668     mxPaletteManager( rPaletteManager ),
1669     mrColorStatus( rColorStatus ),
1670     maColorSelectFunction(aFunction),
1671     mbReuseParentForPicker(bReuseParentForPicker)
1672 {
1673     get(mpPaletteListBox,     "palette_listbox");
1674     get(mpButtonAutoColor,    "auto_color_button");
1675     get(mpButtonNoneColor,    "none_color_button");
1676     get(mpButtonPicker,       "color_picker_button");
1677     get(mpColorSet,           "colorset");
1678     get(mpRecentColorSet,     "recent_colorset");
1679     get(mpAutomaticSeparator, "separator4");
1680 
1681     mpColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) );
1682     mpRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) );
1683 
1684     switch ( theSlotId )
1685     {
1686         case SID_ATTR_CHAR_COLOR_BACKGROUND:
1687         case SID_BACKGROUND_COLOR:
1688         case SID_ATTR_CHAR_BACK_COLOR:
1689         case SID_TABLE_CELL_BACKGROUND_COLOR:
1690         {
1691             mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_NOFILL ) );
1692             break;
1693         }
1694         case SID_AUTHOR_COLOR:
1695         {
1696             mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_BY_AUTHOR ) );
1697             break;
1698         }
1699         case SID_BMPMASK_COLOR:
1700         {
1701             mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_TRANSPARENT ) );
1702             break;
1703         }
1704         case SID_ATTR_CHAR_COLOR:
1705         case SID_ATTR_CHAR_COLOR2:
1706         case SID_EXTRUSION_3D_COLOR:
1707         {
1708             mpButtonAutoColor->SetText(EditResId(RID_SVXSTR_AUTOMATIC));
1709             break;
1710         }
1711         case SID_FM_CTL_PROPERTIES:
1712         {
1713             mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_DEFAULT ) );
1714             break;
1715         }
1716         default:
1717         {
1718             mpButtonAutoColor->Hide();
1719             mpAutomaticSeparator->Hide();
1720             break;
1721         }
1722     }
1723 
1724     mpColorSet->SetAccessibleName( GetText() );
1725 
1726     mpPaletteListBox->SetStyle( mpPaletteListBox->GetStyle() | WB_BORDER );
1727     mpPaletteListBox->SetSelectHdl( LINK( this, SvxColorWindow, SelectPaletteHdl ) );
1728     mpPaletteListBox->AdaptDropDownLineCountToMaximum();
1729     std::vector<OUString> aPaletteList = mxPaletteManager->GetPaletteList();
1730     for (const auto& rPalette : aPaletteList )
1731     {
1732         mpPaletteListBox->InsertEntry( rPalette );
1733     }
1734     OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() );
1735     mpPaletteListBox->SelectEntry( aPaletteName );
1736     const sal_Int32 nSelectedEntry(mpPaletteListBox->GetSelectedEntryPos());
1737     if (nSelectedEntry != LISTBOX_ENTRY_NOTFOUND)
1738         mxPaletteManager->SetPalette(nSelectedEntry);
1739 
1740     mpButtonAutoColor->SetClickHdl( LINK( this, SvxColorWindow, AutoColorClickHdl ) );
1741     mpButtonNoneColor->SetClickHdl( LINK( this, SvxColorWindow, AutoColorClickHdl ) );
1742     mpButtonPicker->SetClickHdl( LINK( this, SvxColorWindow, OpenPickerClickHdl ) );
1743 
1744     mpColorSet->SetSelectHdl( LINK( this, SvxColorWindow, SelectHdl ) );
1745     mpRecentColorSet->SetSelectHdl( LINK( this, SvxColorWindow, SelectHdl ) );
1746     SetHelpId( HID_POPUP_COLOR );
1747     mpColorSet->SetHelpId( HID_POPUP_COLOR_CTRL );
1748 
1749     mxPaletteManager->ReloadColorSet(*mpColorSet);
1750     const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount());
1751     Size aSize = mpColorSet->layoutAllVisible(nMaxItems);
1752     mpColorSet->set_height_request(aSize.Height());
1753     mpColorSet->set_width_request(aSize.Width());
1754 
1755     mxPaletteManager->ReloadRecentColorSet(*mpRecentColorSet);
1756     aSize = mpRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount());
1757     mpRecentColorSet->set_height_request(aSize.Height());
1758     mpRecentColorSet->set_width_request(aSize.Width());
1759 
1760     AddStatusListener( ".uno:ColorTableState" );
1761     AddStatusListener( maCommand );
1762     if ( maCommand == ".uno:FrameLineColor" )
1763     {
1764         AddStatusListener( ".uno:BorderTLBR" );
1765         AddStatusListener( ".uno:BorderBLTR" );
1766     }
1767 }
1768 
ColorWindow(std::shared_ptr<PaletteManager> const & rPaletteManager,ColorStatus & rColorStatus,sal_uInt16 nSlotId,const Reference<XFrame> & rFrame,weld::Window * pParentWindow,const MenuOrToolMenuButton & rMenuButton,ColorSelectFunction const & aFunction)1769 ColorWindow::ColorWindow(std::shared_ptr<PaletteManager> const & rPaletteManager,
1770                          ColorStatus&               rColorStatus,
1771                          sal_uInt16                 nSlotId,
1772                          const Reference< XFrame >& rFrame,
1773                          weld::Window*              pParentWindow,
1774                          const MenuOrToolMenuButton& rMenuButton,
1775                          ColorSelectFunction const & aFunction)
1776     : ToolbarPopupBase(rFrame)
1777     , m_xBuilder(Application::CreateBuilder(rMenuButton.get_widget(), "svx/ui/colorwindow.ui"))
1778     , theSlotId(nSlotId)
1779     , mpParentWindow(pParentWindow)
1780     , maMenuButton(rMenuButton)
1781     , mxPaletteManager(rPaletteManager)
1782     , mrColorStatus(rColorStatus)
1783     , maColorSelectFunction(aFunction)
1784     , mxColorSet(new ColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin")))
1785     , mxRecentColorSet(new ColorValueSet(nullptr))
1786     , mxTopLevel(m_xBuilder->weld_container("palette_popup_window"))
1787     , mxPaletteListBox(m_xBuilder->weld_combo_box("palette_listbox"))
1788     , mxButtonAutoColor(m_xBuilder->weld_button("auto_color_button"))
1789     , mxButtonNoneColor(m_xBuilder->weld_button("none_color_button"))
1790     , mxButtonPicker(m_xBuilder->weld_button("color_picker_button"))
1791     , mxAutomaticSeparator(m_xBuilder->weld_widget("separator4"))
1792     , mxColorSetWin(new weld::CustomWeld(*m_xBuilder, "colorset", *mxColorSet))
1793     , mxRecentColorSetWin(new weld::CustomWeld(*m_xBuilder, "recent_colorset", *mxRecentColorSet))
1794     , mpDefaultButton(nullptr)
1795 {
1796     mxColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) );
1797     mxRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) );
1798 
1799     switch ( theSlotId )
1800     {
1801         case SID_ATTR_CHAR_COLOR_BACKGROUND:
1802         case SID_BACKGROUND_COLOR:
1803         case SID_ATTR_CHAR_BACK_COLOR:
1804         case SID_TABLE_CELL_BACKGROUND_COLOR:
1805         {
1806             mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_NOFILL ) );
1807             break;
1808         }
1809         case SID_AUTHOR_COLOR:
1810         {
1811             mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_BY_AUTHOR ) );
1812             break;
1813         }
1814         case SID_BMPMASK_COLOR:
1815         {
1816             mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_TRANSPARENT ) );
1817             break;
1818         }
1819         case SID_ATTR_CHAR_COLOR:
1820         case SID_ATTR_CHAR_COLOR2:
1821         case SID_EXTRUSION_3D_COLOR:
1822         {
1823             mxButtonAutoColor->set_label(EditResId(RID_SVXSTR_AUTOMATIC));
1824             break;
1825         }
1826         case SID_FM_CTL_PROPERTIES:
1827         {
1828             mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_DEFAULT ) );
1829             break;
1830         }
1831         default:
1832         {
1833             mxButtonAutoColor->hide();
1834             mxAutomaticSeparator->hide();
1835             break;
1836         }
1837     }
1838 
1839     mxPaletteListBox->connect_changed(LINK(this, ColorWindow, SelectPaletteHdl));
1840     std::vector<OUString> aPaletteList = mxPaletteManager->GetPaletteList();
1841     mxPaletteListBox->freeze();
1842     for (const auto& rPalette : aPaletteList)
1843         mxPaletteListBox->append_text(rPalette);
1844     mxPaletteListBox->thaw();
1845     OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() );
1846     mxPaletteListBox->set_active_text(aPaletteName);
1847     const int nSelectedEntry(mxPaletteListBox->get_active());
1848     if (nSelectedEntry != -1)
1849         mxPaletteManager->SetPalette(nSelectedEntry);
1850 
1851     mxButtonAutoColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl));
1852     mxButtonNoneColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl));
1853     mxButtonPicker->connect_clicked(LINK(this, ColorWindow, OpenPickerClickHdl));
1854 
1855     mxColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl));
1856     mxRecentColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl));
1857     mxTopLevel->set_help_id(HID_POPUP_COLOR);
1858     mxTopLevel->connect_focus_in(LINK(this, ColorWindow, FocusHdl));
1859     mxColorSet->SetHelpId(HID_POPUP_COLOR_CTRL);
1860 
1861     mxPaletteManager->ReloadColorSet(*mxColorSet);
1862     const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount());
1863     Size aSize = mxColorSet->layoutAllVisible(nMaxItems);
1864     mxColorSet->set_size_request(aSize.Width(), aSize.Height());
1865 
1866     mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet);
1867     aSize = mxRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount());
1868     mxRecentColorSet->set_size_request(aSize.Width(), aSize.Height());
1869 
1870     AddStatusListener( ".uno:ColorTableState" );
1871 }
1872 
IMPL_LINK_NOARG(ColorWindow,FocusHdl,weld::Widget &,void)1873 IMPL_LINK_NOARG(ColorWindow, FocusHdl, weld::Widget&, void)
1874 {
1875     if (mxColorSet->IsNoSelection() && mpDefaultButton)
1876         mpDefaultButton->grab_focus();
1877     else
1878         mxColorSet->GrabFocus();
1879 }
1880 
ShowNoneButton()1881 void SvxColorWindow::ShowNoneButton()
1882 {
1883     mpButtonNoneColor->Show();
1884 }
1885 
ShowNoneButton()1886 void ColorWindow::ShowNoneButton()
1887 {
1888     mxButtonNoneColor->show();
1889 }
1890 
~SvxColorWindow()1891 SvxColorWindow::~SvxColorWindow()
1892 {
1893     disposeOnce();
1894 }
1895 
~ColorWindow()1896 ColorWindow::~ColorWindow()
1897 {
1898 }
1899 
dispose()1900 void SvxColorWindow::dispose()
1901 {
1902     mpColorSet.clear();
1903     mpRecentColorSet.clear();
1904     mpPaletteListBox.clear();
1905     mpButtonAutoColor.clear();
1906     mpButtonNoneColor.clear();
1907     mpButtonPicker.clear();
1908     mpAutomaticSeparator.clear();
1909     mxParentWindow.clear();
1910     ToolbarPopup::dispose();
1911 }
1912 
KeyInput(const KeyEvent & rKEvt)1913 void SvxColorWindow::KeyInput( const KeyEvent& rKEvt )
1914 {
1915     mpColorSet->GrabFocus();
1916     mpColorSet->KeyInput(rKEvt);
1917 }
1918 
GetSelectEntryColor(ValueSet const * pColorSet)1919 NamedColor SvxColorWindow::GetSelectEntryColor(ValueSet const * pColorSet)
1920 {
1921     Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId());
1922     OUString sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId());
1923     return std::make_pair(aColor, sColorName);
1924 }
1925 
GetSelectEntryColor(SvtValueSet const * pColorSet)1926 NamedColor ColorWindow::GetSelectEntryColor(SvtValueSet const * pColorSet)
1927 {
1928     Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId());
1929     OUString sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId());
1930     return std::make_pair(aColor, sColorName);
1931 }
1932 
1933 namespace
1934 {
GetAutoColor(sal_uInt16 nSlotId)1935     NamedColor GetAutoColor(sal_uInt16 nSlotId)
1936     {
1937         Color aColor;
1938         OUString sColorName;
1939         switch (nSlotId)
1940         {
1941             case SID_ATTR_CHAR_COLOR_BACKGROUND:
1942             case SID_BACKGROUND_COLOR:
1943             case SID_ATTR_CHAR_BACK_COLOR:
1944             case SID_TABLE_CELL_BACKGROUND_COLOR:
1945                 aColor = COL_TRANSPARENT;
1946                 sColorName = SvxResId(RID_SVXSTR_NOFILL);
1947                 break;
1948             case SID_AUTHOR_COLOR:
1949                 aColor = COL_TRANSPARENT;
1950                 sColorName = SvxResId(RID_SVXSTR_BY_AUTHOR);
1951                 break;
1952             case SID_BMPMASK_COLOR:
1953                 aColor = COL_TRANSPARENT;
1954                 sColorName = SvxResId(RID_SVXSTR_TRANSPARENT);
1955                 break;
1956             case SID_FM_CTL_PROPERTIES:
1957                 aColor = COL_TRANSPARENT;
1958                 sColorName = SvxResId(RID_SVXSTR_DEFAULT);
1959                 break;
1960             case SID_ATTR_CHAR_COLOR:
1961             case SID_ATTR_CHAR_COLOR2:
1962             case SID_EXTRUSION_3D_COLOR:
1963             default:
1964                 aColor = COL_AUTO;
1965                 sColorName = EditResId(RID_SVXSTR_AUTOMATIC);
1966                 break;
1967         }
1968 
1969         return std::make_pair(aColor, sColorName);
1970     }
1971 
GetNoneColor()1972     NamedColor GetNoneColor()
1973     {
1974         return std::make_pair(COL_NONE_COLOR, SvxResId(RID_SVXSTR_NONE));
1975     }
1976 }
1977 
GetSelectEntryColor() const1978 NamedColor SvxColorWindow::GetSelectEntryColor() const
1979 {
1980     if (!mpColorSet->IsNoSelection())
1981         return GetSelectEntryColor(mpColorSet);
1982     if (!mpRecentColorSet->IsNoSelection())
1983         return GetSelectEntryColor(mpRecentColorSet);
1984     if (mpButtonNoneColor->GetStyle() & WB_DEFBUTTON)
1985         return GetNoneColor();
1986     return GetAutoColor();
1987 }
1988 
GetSelectEntryColor() const1989 NamedColor ColorWindow::GetSelectEntryColor() const
1990 {
1991     if (!mxColorSet->IsNoSelection())
1992         return GetSelectEntryColor(mxColorSet.get());
1993     if (!mxRecentColorSet->IsNoSelection())
1994         return GetSelectEntryColor(mxRecentColorSet.get());
1995     if (mxButtonNoneColor.get() == mpDefaultButton)
1996         return GetNoneColor();
1997     return GetAutoColor();
1998 }
1999 
IMPL_LINK(SvxColorWindow,SelectHdl,ValueSet *,pColorSet,void)2000 IMPL_LINK(SvxColorWindow, SelectHdl, ValueSet*, pColorSet, void)
2001 {
2002     VclPtr<SvxColorWindow> xThis(this);
2003 
2004     NamedColor aNamedColor = GetSelectEntryColor(pColorSet);
2005 
2006     if ( pColorSet != mpRecentColorSet )
2007     {
2008          mxPaletteManager->AddRecentColor(aNamedColor.first, aNamedColor.second);
2009          if ( !IsInPopupMode() )
2010             mxPaletteManager->ReloadRecentColorSet(*mpRecentColorSet);
2011     }
2012 
2013     if ( IsInPopupMode() )
2014         EndPopupMode();
2015 
2016     maSelectedLink.Call(aNamedColor);
2017 
2018     maColorSelectFunction(maCommand, aNamedColor);
2019 }
2020 
IMPL_LINK(ColorWindow,SelectHdl,SvtValueSet *,pColorSet,void)2021 IMPL_LINK(ColorWindow, SelectHdl, SvtValueSet*, pColorSet, void)
2022 {
2023     NamedColor aNamedColor = GetSelectEntryColor(pColorSet);
2024 
2025     if (pColorSet != mxRecentColorSet.get())
2026     {
2027          mxPaletteManager->AddRecentColor(aNamedColor.first, aNamedColor.second);
2028          if (!maMenuButton.get_active())
2029             mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet);
2030     }
2031 
2032     if (maMenuButton.get_active())
2033         maMenuButton.set_active(false);
2034 
2035     maColorSelectFunction(OUString(), aNamedColor);
2036 }
2037 
IMPL_LINK_NOARG(SvxColorWindow,SelectPaletteHdl,ListBox &,void)2038 IMPL_LINK_NOARG(SvxColorWindow, SelectPaletteHdl, ListBox&, void)
2039 {
2040     sal_Int32 nPos = mpPaletteListBox->GetSelectedEntryPos();
2041     mxPaletteManager->SetPalette( nPos );
2042     mxPaletteManager->ReloadColorSet(*mpColorSet);
2043     mpColorSet->layoutToGivenHeight(mpColorSet->GetSizePixel().Height(), mxPaletteManager->GetColorCount());
2044 }
2045 
IMPL_LINK_NOARG(ColorWindow,SelectPaletteHdl,weld::ComboBox &,void)2046 IMPL_LINK_NOARG(ColorWindow, SelectPaletteHdl, weld::ComboBox&, void)
2047 {
2048     int nPos = mxPaletteListBox->get_active();
2049     mxPaletteManager->SetPalette( nPos );
2050     mxPaletteManager->ReloadColorSet(*mxColorSet);
2051     mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount());
2052 }
2053 
GetAutoColor() const2054 NamedColor SvxColorWindow::GetAutoColor() const
2055 {
2056     return ::GetAutoColor(theSlotId);
2057 }
2058 
GetAutoColor() const2059 NamedColor ColorWindow::GetAutoColor() const
2060 {
2061     return ::GetAutoColor(theSlotId);
2062 }
2063 
IMPL_LINK(SvxColorWindow,AutoColorClickHdl,Button *,pButton,void)2064 IMPL_LINK(SvxColorWindow, AutoColorClickHdl, Button*, pButton, void)
2065 {
2066     VclPtr<SvxColorWindow> xThis(this);
2067 
2068     NamedColor aNamedColor = pButton == mpButtonAutoColor ? GetAutoColor() : GetNoneColor();
2069 
2070     mpRecentColorSet->SetNoSelection();
2071 
2072     if ( IsInPopupMode() )
2073         EndPopupMode();
2074 
2075     maSelectedLink.Call(aNamedColor);
2076 
2077     maColorSelectFunction(maCommand, aNamedColor);
2078 }
2079 
IMPL_LINK(ColorWindow,AutoColorClickHdl,weld::Button &,rButton,void)2080 IMPL_LINK(ColorWindow, AutoColorClickHdl, weld::Button&, rButton, void)
2081 {
2082     NamedColor aNamedColor = &rButton == mxButtonAutoColor.get() ? GetAutoColor() : GetNoneColor();
2083 
2084     mxColorSet->SetNoSelection();
2085     mxRecentColorSet->SetNoSelection();
2086     mpDefaultButton = &rButton;
2087 
2088     if (maMenuButton.get_active())
2089         maMenuButton.set_active(false);
2090 
2091     maColorSelectFunction(OUString(), aNamedColor);
2092 }
2093 
IMPL_LINK_NOARG(SvxColorWindow,OpenPickerClickHdl,Button *,void)2094 IMPL_LINK_NOARG(SvxColorWindow, OpenPickerClickHdl, Button*, void)
2095 {
2096     VclPtr<SvxColorWindow> xThis(this);
2097 
2098     if ( IsInPopupMode() )
2099         EndPopupMode();
2100 
2101     weld::Window* pParentFrame;
2102     if (mbReuseParentForPicker)
2103     {
2104         pParentFrame = mxParentWindow->GetFrameWeld();
2105     }
2106     else
2107     {
2108         const css::uno::Reference<css::awt::XWindow> xParent = mxFrame->getContainerWindow();
2109         pParentFrame = Application::GetFrameWeld(xParent);
2110     }
2111     mxPaletteManager->PopupColorPicker(pParentFrame, maCommand, GetSelectEntryColor().first);
2112 }
2113 
IMPL_LINK_NOARG(ColorWindow,OpenPickerClickHdl,weld::Button &,void)2114 IMPL_LINK_NOARG(ColorWindow, OpenPickerClickHdl, weld::Button&, void)
2115 {
2116     if (maMenuButton.get_active())
2117         maMenuButton.set_active(false);
2118     mxPaletteManager->PopupColorPicker(mpParentWindow, OUString(), GetSelectEntryColor().first);
2119 }
2120 
StartSelection()2121 void SvxColorWindow::StartSelection()
2122 {
2123     mpColorSet->StartSelection();
2124     mpRecentColorSet->StartSelection();
2125 }
2126 
SetNoSelection()2127 void SvxColorWindow::SetNoSelection()
2128 {
2129     mpColorSet->SetNoSelection();
2130     mpRecentColorSet->SetNoSelection();
2131     mpButtonAutoColor->set_property("has-default", "false");
2132     mpButtonNoneColor->set_property("has-default", "false");
2133 }
2134 
SetNoSelection()2135 void ColorWindow::SetNoSelection()
2136 {
2137     mxColorSet->SetNoSelection();
2138     mxRecentColorSet->SetNoSelection();
2139     mpDefaultButton = nullptr;
2140 }
2141 
IsNoSelection() const2142 bool SvxColorWindow::IsNoSelection() const
2143 {
2144     if (!mpColorSet->IsNoSelection())
2145         return false;
2146     if (!mpRecentColorSet->IsNoSelection())
2147         return false;
2148     return !mpButtonAutoColor->IsVisible() && !mpButtonNoneColor->IsVisible();
2149 }
2150 
IsNoSelection() const2151 bool ColorWindow::IsNoSelection() const
2152 {
2153     if (!mxColorSet->IsNoSelection())
2154         return false;
2155     if (!mxRecentColorSet->IsNoSelection())
2156         return false;
2157     return !mxButtonAutoColor->get_visible() && !mxButtonNoneColor->get_visible();
2158 }
2159 
statusChanged(const css::frame::FeatureStateEvent & rEvent)2160 void SvxColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent )
2161 {
2162     if (rEvent.FeatureURL.Complete == ".uno:ColorTableState")
2163     {
2164         if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0)
2165         {
2166             mxPaletteManager->ReloadColorSet(*mpColorSet);
2167             mpColorSet->layoutToGivenHeight(mpColorSet->GetSizePixel().Height(), mxPaletteManager->GetColorCount());
2168         }
2169     }
2170     else
2171     {
2172         mrColorStatus.statusChanged(rEvent);
2173         SelectEntry(mrColorStatus.GetColor());
2174     }
2175 }
2176 
statusChanged(const css::frame::FeatureStateEvent & rEvent)2177 void ColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent )
2178 {
2179     if (rEvent.FeatureURL.Complete == ".uno:ColorTableState")
2180     {
2181         if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0)
2182         {
2183             mxPaletteManager->ReloadColorSet(*mxColorSet);
2184             mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount());
2185         }
2186     }
2187     else
2188     {
2189         mrColorStatus.statusChanged(rEvent);
2190         SelectEntry(mrColorStatus.GetColor());
2191     }
2192 }
2193 
SelectValueSetEntry(SvxColorValueSet * pColorSet,const Color & rColor)2194 bool SvxColorWindow::SelectValueSetEntry(SvxColorValueSet* pColorSet, const Color& rColor)
2195 {
2196     for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i)
2197     {
2198         if (rColor == pColorSet->GetItemColor(i))
2199         {
2200             pColorSet->SelectItem(i);
2201             return true;
2202         }
2203     }
2204     return false;
2205 }
2206 
SelectValueSetEntry(ColorValueSet * pColorSet,const Color & rColor)2207 bool ColorWindow::SelectValueSetEntry(ColorValueSet* pColorSet, const Color& rColor)
2208 {
2209     for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i)
2210     {
2211         if (rColor == pColorSet->GetItemColor(i))
2212         {
2213             pColorSet->SelectItem(i);
2214             return true;
2215         }
2216     }
2217     return false;
2218 }
2219 
SelectEntry(const NamedColor & rNamedColor)2220 void SvxColorWindow::SelectEntry(const NamedColor& rNamedColor)
2221 {
2222     SetNoSelection();
2223 
2224     const Color &rColor = rNamedColor.first;
2225 
2226     if (rColor == COL_TRANSPARENT || rColor == COL_AUTO)
2227     {
2228         mpButtonAutoColor->set_property("has-default", "true");
2229         return;
2230     }
2231 
2232     if (mpButtonNoneColor->IsVisible() && rColor == COL_NONE_COLOR)
2233     {
2234         mpButtonNoneColor->set_property("has-default", "true");
2235         return;
2236     }
2237 
2238     // try current palette
2239     bool bFoundColor = SelectValueSetEntry(mpColorSet, rColor);
2240     // try recently used
2241     if (!bFoundColor)
2242         bFoundColor = SelectValueSetEntry(mpRecentColorSet, rColor);
2243     // if it's not there, add it there now to the end of the recently used
2244     // so its available somewhere handy, but not without trashing the
2245     // whole recently used
2246     if (!bFoundColor)
2247     {
2248         const OUString& rColorName = rNamedColor.second;
2249         mxPaletteManager->AddRecentColor(rColor, rColorName, false);
2250         mxPaletteManager->ReloadRecentColorSet(*mpRecentColorSet);
2251         SelectValueSetEntry(mpRecentColorSet, rColor);
2252     }
2253 }
2254 
SelectEntry(const Color & rColor)2255 void SvxColorWindow::SelectEntry(const Color& rColor)
2256 {
2257     OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase();
2258     SvxColorWindow::SelectEntry(std::make_pair(rColor, sColorName));
2259 }
2260 
SelectEntry(const NamedColor & rNamedColor)2261 void ColorWindow::SelectEntry(const NamedColor& rNamedColor)
2262 {
2263     SetNoSelection();
2264 
2265     const Color &rColor = rNamedColor.first;
2266 
2267     if (mxButtonAutoColor->get_visible() && (rColor == COL_TRANSPARENT || rColor == COL_AUTO))
2268     {
2269         mpDefaultButton = mxButtonAutoColor.get();
2270         return;
2271     }
2272 
2273     if (mxButtonNoneColor->get_visible() && rColor == COL_NONE_COLOR)
2274     {
2275         mpDefaultButton = mxButtonNoneColor.get();
2276         return;
2277     }
2278 
2279     // try current palette
2280     bool bFoundColor = SelectValueSetEntry(mxColorSet.get(), rColor);
2281     // try recently used
2282     if (!bFoundColor)
2283         bFoundColor = SelectValueSetEntry(mxRecentColorSet.get(), rColor);
2284     // if it's not there, add it there now to the end of the recently used
2285     // so its available somewhere handy, but not without trashing the
2286     // whole recently used
2287     if (!bFoundColor)
2288     {
2289         const OUString& rColorName = rNamedColor.second;
2290         mxPaletteManager->AddRecentColor(rColor, rColorName, false);
2291         mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet);
2292         SelectValueSetEntry(mxRecentColorSet.get(), rColor);
2293     }
2294 }
2295 
SelectEntry(const Color & rColor)2296 void ColorWindow::SelectEntry(const Color& rColor)
2297 {
2298     OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase();
2299     ColorWindow::SelectEntry(std::make_pair(rColor, sColorName));
2300 }
2301 
ColorStatus()2302 ColorStatus::ColorStatus() :
2303     maColor( COL_TRANSPARENT ),
2304     maTLBRColor( COL_TRANSPARENT ),
2305     maBLTRColor( COL_TRANSPARENT )
2306 {
2307 }
2308 
~ColorStatus()2309 ColorStatus::~ColorStatus()
2310 {
2311 }
2312 
statusChanged(const css::frame::FeatureStateEvent & rEvent)2313 void ColorStatus::statusChanged( const css::frame::FeatureStateEvent& rEvent )
2314 {
2315     Color aColor( COL_TRANSPARENT );
2316     css::table::BorderLine2 aTable;
2317 
2318     if ( rEvent.State >>= aTable )
2319     {
2320         SvxBorderLine aLine;
2321         SvxBoxItem::LineToSvxLine( aTable, aLine, false );
2322         if ( !aLine.isEmpty() )
2323             aColor = aLine.GetColor();
2324     }
2325     else
2326         rEvent.State >>= aColor;
2327 
2328     if ( rEvent.FeatureURL.Path == "BorderTLBR" )
2329         maTLBRColor = aColor;
2330     else if ( rEvent.FeatureURL.Path == "BorderBLTR" )
2331         maBLTRColor = aColor;
2332     else
2333         maColor = aColor;
2334 }
2335 
GetColor()2336 Color ColorStatus::GetColor()
2337 {
2338     Color aColor( maColor );
2339 
2340     if ( maTLBRColor != COL_TRANSPARENT )
2341     {
2342         if ( aColor != maTLBRColor && aColor != COL_TRANSPARENT )
2343             return COL_TRANSPARENT;
2344         aColor = maTLBRColor;
2345     }
2346 
2347     if ( maBLTRColor != COL_TRANSPARENT )
2348     {
2349         if ( aColor != maBLTRColor && aColor != COL_TRANSPARENT )
2350             return COL_TRANSPARENT;
2351         return maBLTRColor;
2352     }
2353 
2354     return aColor;
2355 }
2356 
2357 
SvxFrameWindow_Impl(svt::ToolboxController & rController,vcl::Window * pParentWindow)2358 SvxFrameWindow_Impl::SvxFrameWindow_Impl ( svt::ToolboxController& rController, vcl::Window* pParentWindow ) :
2359     ToolbarPopup( rController.getFrameInterface(), pParentWindow, WB_STDPOPUP | WB_MOVEABLE | WB_CLOSEABLE ),
2360     aFrameSet   ( VclPtr<SvxFrmValueSet_Impl>::Create(this, WinBits( WB_ITEMBORDER | WB_DOUBLEBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT )) ),
2361     mrController( rController ),
2362     bParagraphMode(false)
2363 {
2364     AddStatusListener(".uno:BorderReducedMode");
2365     InitImageList();
2366 
2367     /*
2368      *  1       2        3         4
2369      *  -------------------------------------
2370      *  NONE    LEFT     RIGHT     LEFTRIGHT
2371      *  TOP     BOTTOM   TOPBOTTOM OUTER
2372      *  -------------------------------------
2373      *  HOR     HORINNER VERINNER   ALL         <- can be switched of via bParagraphMode
2374      */
2375 
2376     sal_uInt16 i = 0;
2377 
2378     for ( i=1; i<9; i++ )
2379         aFrameSet->InsertItem(i, Image(aImgVec[i-1]));
2380 
2381     //bParagraphMode should have been set in StateChanged
2382     if ( !bParagraphMode )
2383         for ( i = 9; i < 13; i++ )
2384             aFrameSet->InsertItem(i, Image(aImgVec[i-1]));
2385 
2386     aFrameSet->SetColCount( 4 );
2387     aFrameSet->SetSelectHdl( LINK( this, SvxFrameWindow_Impl, SelectHdl ) );
2388     CalcSizeValueSet();
2389 
2390     SetHelpId( HID_POPUP_FRAME );
2391     SetText( SvxResId(RID_SVXSTR_FRAME) );
2392     aFrameSet->SetAccessibleName( SvxResId(RID_SVXSTR_FRAME) );
2393     aFrameSet->Show();
2394 }
2395 
~SvxFrameWindow_Impl()2396 SvxFrameWindow_Impl::~SvxFrameWindow_Impl()
2397 {
2398     disposeOnce();
2399 }
2400 
dispose()2401 void SvxFrameWindow_Impl::dispose()
2402 {
2403     aFrameSet.disposeAndClear();
2404     ToolbarPopup::dispose();
2405 }
2406 
GetFocus()2407 void SvxFrameWindow_Impl::GetFocus()
2408 {
2409     if (aFrameSet)
2410         aFrameSet->StartSelection();
2411 }
2412 
KeyInput(const KeyEvent & rKEvt)2413 void SvxFrameWindow_Impl::KeyInput( const KeyEvent& rKEvt )
2414 {
2415     aFrameSet->GrabFocus();
2416     aFrameSet->KeyInput( rKEvt );
2417 }
2418 
DataChanged(const DataChangedEvent & rDCEvt)2419 void SvxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt )
2420 {
2421     ToolbarPopup::DataChanged( rDCEvt );
2422 
2423     if ( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
2424     {
2425         InitImageList();
2426 
2427         sal_uInt16 nNumOfItems = aFrameSet->GetItemCount();
2428         for ( sal_uInt16 i = 1 ; i <= nNumOfItems ; ++i )
2429             aFrameSet->SetItemImage( i, Image(aImgVec[i-1]) );
2430     }
2431 }
2432 
2433 enum class FrmValidFlags {
2434     NONE      = 0x00,
2435     Left      = 0x01,
2436     Right     = 0x02,
2437     Top       = 0x04,
2438     Bottom    = 0x08,
2439     HInner    = 0x10,
2440     VInner    = 0x20,
2441     AllMask   = 0x3f,
2442 };
2443 namespace o3tl {
2444     template<> struct typed_flags<FrmValidFlags> : is_typed_flags<FrmValidFlags, 0x3f> {};
2445 }
2446 
2447 // By default unset lines remain unchanged.
2448 // Via Shift unset lines are reset
2449 
IMPL_LINK_NOARG(SvxFrameWindow_Impl,SelectHdl,ValueSet *,void)2450 IMPL_LINK_NOARG(SvxFrameWindow_Impl, SelectHdl, ValueSet*, void)
2451 {
2452     VclPtr<SvxFrameWindow_Impl> xThis(this);
2453 
2454     SvxBoxItem          aBorderOuter( SID_ATTR_BORDER_OUTER );
2455     SvxBoxInfoItem      aBorderInner( SID_ATTR_BORDER_INNER );
2456     SvxBorderLine       theDefLine;
2457     SvxBorderLine       *pLeft = nullptr,
2458                         *pRight = nullptr,
2459                         *pTop = nullptr,
2460                         *pBottom = nullptr;
2461     sal_uInt16           nSel = aFrameSet->GetSelectedItemId();
2462     sal_uInt16           nModifier = aFrameSet->GetModifier();
2463     FrmValidFlags        nValidFlags = FrmValidFlags::NONE;
2464 
2465     theDefLine.GuessLinesWidths(theDefLine.GetBorderLineStyle(),
2466             DEF_LINE_WIDTH_0);
2467     switch ( nSel )
2468     {
2469         case 1: nValidFlags |= FrmValidFlags::AllMask;
2470         break;  // NONE
2471         case 2: pLeft = &theDefLine;
2472                 nValidFlags |= FrmValidFlags::Left;
2473         break;  // LEFT
2474         case 3: pRight = &theDefLine;
2475                 nValidFlags |= FrmValidFlags::Right;
2476         break;  // RIGHT
2477         case 4: pLeft = pRight = &theDefLine;
2478                 nValidFlags |=  FrmValidFlags::Right|FrmValidFlags::Left;
2479         break;  // LEFTRIGHT
2480         case 5: pTop = &theDefLine;
2481                 nValidFlags |= FrmValidFlags::Top;
2482         break;  // TOP
2483         case 6: pBottom = &theDefLine;
2484                 nValidFlags |= FrmValidFlags::Bottom;
2485         break;  // BOTTOM
2486         case 7: pTop =  pBottom = &theDefLine;
2487                 nValidFlags |= FrmValidFlags::Bottom|FrmValidFlags::Top;
2488         break;  // TOPBOTTOM
2489         case 8: pLeft = pRight = pTop = pBottom = &theDefLine;
2490                 nValidFlags |= FrmValidFlags::Left | FrmValidFlags::Right | FrmValidFlags::Top | FrmValidFlags::Bottom;
2491         break;  // OUTER
2492 
2493         // Inner Table:
2494         case 9: // HOR
2495             pTop = pBottom = &theDefLine;
2496             aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI );
2497             aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT );
2498             nValidFlags |= FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom;
2499             break;
2500 
2501         case 10: // HORINNER
2502             pLeft = pRight = pTop = pBottom = &theDefLine;
2503             aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI );
2504             aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT );
2505             nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom;
2506             break;
2507 
2508         case 11: // VERINNER
2509             pLeft = pRight = pTop = pBottom = &theDefLine;
2510             aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::HORI );
2511             aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT );
2512             nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::VInner|FrmValidFlags::Top|FrmValidFlags::Bottom;
2513         break;
2514 
2515         case 12: // ALL
2516             pLeft = pRight = pTop = pBottom = &theDefLine;
2517             aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI );
2518             aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT );
2519             nValidFlags |= FrmValidFlags::AllMask;
2520             break;
2521 
2522         default:
2523         break;
2524     }
2525     aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT );
2526     aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT );
2527     aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP );
2528     aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM );
2529 
2530     if(nModifier == KEY_SHIFT)
2531         nValidFlags |= FrmValidFlags::AllMask;
2532     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP,       bool(nValidFlags&FrmValidFlags::Top ));
2533     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM,    bool(nValidFlags&FrmValidFlags::Bottom ));
2534     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT,      bool(nValidFlags&FrmValidFlags::Left));
2535     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT,     bool(nValidFlags&FrmValidFlags::Right ));
2536     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI,      bool(nValidFlags&FrmValidFlags::HInner ));
2537     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT,      bool(nValidFlags&FrmValidFlags::VInner));
2538     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE );
2539     aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE,   false );
2540 
2541     if ( IsInPopupMode() )
2542         EndPopupMode();
2543 
2544     Any a;
2545     Sequence< PropertyValue > aArgs( 2 );
2546     aArgs[0].Name = "OuterBorder";
2547     aBorderOuter.QueryValue( a );
2548     aArgs[0].Value = a;
2549     aArgs[1].Name = "InnerBorder";
2550     aBorderInner.QueryValue( a );
2551     aArgs[1].Value = a;
2552 
2553     if (aFrameSet)
2554     {
2555         /* #i33380# Moved the following line above the Dispatch() call.
2556            This instance may be deleted in the meantime (i.e. when a dialog is opened
2557            while in Dispatch()), accessing members will crash in this case. */
2558         aFrameSet->SetNoSelection();
2559     }
2560 
2561     mrController.dispatchCommand( ".uno:SetBorderStyle", aArgs );
2562 }
2563 
statusChanged(const css::frame::FeatureStateEvent & rEvent)2564 void SvxFrameWindow_Impl::statusChanged( const css::frame::FeatureStateEvent& rEvent )
2565 {
2566     if ( rEvent.FeatureURL.Complete == ".uno:BorderReducedMode" )
2567     {
2568         bool bValue;
2569         if ( rEvent.State >>= bValue )
2570         {
2571             bParagraphMode = bValue;
2572             //initial calls mustn't insert or remove elements
2573             if(aFrameSet->GetItemCount())
2574             {
2575                 bool bTableMode = ( aFrameSet->GetItemCount() == 12 );
2576                 bool bResize    = false;
2577 
2578                 if ( bTableMode && bParagraphMode )
2579                 {
2580                     for ( sal_uInt16 i = 9; i < 13; i++ )
2581                         aFrameSet->RemoveItem(i);
2582                     bResize = true;
2583                 }
2584                 else if ( !bTableMode && !bParagraphMode )
2585                 {
2586                     for ( sal_uInt16 i = 9; i < 13; i++ )
2587                         aFrameSet->InsertItem(i, Image(aImgVec[i-1]));
2588                     bResize = true;
2589                 }
2590 
2591                 if ( bResize )
2592                 {
2593                     CalcSizeValueSet();
2594                 }
2595             }
2596         }
2597     }
2598 }
2599 
CalcSizeValueSet()2600 void SvxFrameWindow_Impl::CalcSizeValueSet()
2601 {
2602     Size aItemSize( 20 * GetParent()->GetDPIScaleFactor(), 20 * GetParent()->GetDPIScaleFactor() );
2603     Size aSize = aFrameSet->CalcWindowSizePixel( aItemSize );
2604     aFrameSet->SetPosSizePixel( Point( 2, 2 ), aSize );
2605     aSize.AdjustWidth(4 );
2606     aSize.AdjustHeight(4 );
2607     SetOutputSizePixel( aSize );
2608 }
2609 
InitImageList()2610 void SvxFrameWindow_Impl::InitImageList()
2611 {
2612     aImgVec.clear();
2613     aImgVec.emplace_back(RID_SVXBMP_FRAME1);
2614     aImgVec.emplace_back(RID_SVXBMP_FRAME2);
2615     aImgVec.emplace_back(RID_SVXBMP_FRAME3);
2616     aImgVec.emplace_back(RID_SVXBMP_FRAME4);
2617     aImgVec.emplace_back(RID_SVXBMP_FRAME5);
2618     aImgVec.emplace_back(RID_SVXBMP_FRAME6);
2619     aImgVec.emplace_back(RID_SVXBMP_FRAME7);
2620     aImgVec.emplace_back(RID_SVXBMP_FRAME8);
2621     aImgVec.emplace_back(RID_SVXBMP_FRAME9);
2622     aImgVec.emplace_back(RID_SVXBMP_FRAME10);
2623     aImgVec.emplace_back(RID_SVXBMP_FRAME11);
2624     aImgVec.emplace_back(RID_SVXBMP_FRAME12);
2625 }
2626 
lcl_mediumColor(Color aMain,Color)2627 static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ )
2628 {
2629     return SvxBorderLine::threeDMediumColor( aMain );
2630 }
2631 
SvxCurrencyList_Impl(SvxCurrencyToolBoxControl * pControl,vcl::Window * pParentWindow,OUString & rSelectedFormat,LanguageType & eSelectedLanguage)2632 SvxCurrencyList_Impl::SvxCurrencyList_Impl(
2633     SvxCurrencyToolBoxControl* pControl,
2634     vcl::Window* pParentWindow,
2635     OUString& rSelectedFormat,
2636     LanguageType& eSelectedLanguage ) :
2637     ToolbarPopup( pControl->getFrameInterface(), pParentWindow, WB_STDPOPUP | WB_MOVEABLE | WB_CLOSEABLE ),
2638     m_pCurrencyLb( VclPtr<ListBox>::Create(this) ),
2639     m_xControl( pControl ),
2640     m_rSelectedFormat( rSelectedFormat ),
2641     m_eSelectedLanguage( eSelectedLanguage )
2642 {
2643     m_pCurrencyLb->setPosSizePixel( 2, 2, 300, 140 );
2644     SetOutputSizePixel( Size( 304, 144 ) );
2645 
2646     std::vector< OUString > aList;
2647     std::vector< sal_uInt16 > aCurrencyList;
2648     const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
2649     sal_uInt16 nLen = rCurrencyTable.size();
2650 
2651     SvNumberFormatter aFormatter( m_xControl->getContext(), LANGUAGE_SYSTEM );
2652     m_eFormatLanguage = aFormatter.GetLanguage();
2653 
2654     SvxCurrencyToolBoxControl::GetCurrencySymbols( aList, true, aCurrencyList );
2655 
2656     sal_uInt16 nPos = 0, nCount = 0;
2657     sal_Int32 nSelectedPos = -1;
2658     bool bIsSymbol;
2659     NfWSStringsDtor aStringsDtor;
2660 
2661     for( const auto& rItem : aList )
2662     {
2663         sal_uInt16& rCurrencyIndex = aCurrencyList[ nCount ];
2664         if ( rCurrencyIndex < nLen )
2665         {
2666             m_pCurrencyLb->InsertEntry( rItem );
2667             const NfCurrencyEntry& aCurrencyEntry = rCurrencyTable[ rCurrencyIndex ];
2668 
2669             bIsSymbol = nPos >= nLen;
2670 
2671             sal_uInt16 nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, aCurrencyEntry, bIsSymbol );
2672             const OUString& rFormatStr = aStringsDtor[ nDefaultFormat ];
2673             m_aFormatEntries.push_back( rFormatStr );
2674             if( rFormatStr == m_rSelectedFormat )
2675                 nSelectedPos = nPos;
2676             ++nPos;
2677         }
2678         ++nCount;
2679     }
2680     m_pCurrencyLb->SetSelectHdl( LINK( this, SvxCurrencyList_Impl, SelectHdl ) );
2681     SetText( SvxResId( RID_SVXSTR_TBLAFMT_CURRENCY ) );
2682     if ( nSelectedPos >= 0 )
2683         m_pCurrencyLb->SelectEntryPos( nSelectedPos );
2684     m_pCurrencyLb->Show();
2685 }
2686 
dispose()2687 void SvxCurrencyList_Impl::dispose()
2688 {
2689     m_xControl.clear();
2690     m_pCurrencyLb.disposeAndClear();
2691     ToolbarPopup::dispose();
2692 }
2693 
SvxLineWindow_Impl(svt::ToolboxController & rController,vcl::Window * pParentWindow)2694 SvxLineWindow_Impl::SvxLineWindow_Impl( svt::ToolboxController& rController, vcl::Window* pParentWindow ) :
2695     ToolbarPopup( rController.getFrameInterface(), pParentWindow, WB_STDPOPUP | WB_MOVEABLE | WB_CLOSEABLE ),
2696     m_aLineStyleLb( VclPtr<LineListBox>::Create(this) ),
2697     m_rController( rController )
2698 {
2699     try
2700     {
2701         Reference< lang::XServiceInfo > xServices( rController.getFrameInterface()->getController()->getModel(), UNO_QUERY_THROW );
2702         m_bIsWriter = xServices->supportsService("com.sun.star.text.TextDocument");
2703     }
2704     catch(const uno::Exception& )
2705     {
2706     }
2707 
2708     m_aLineStyleLb->setPosSizePixel( 2, 2, 110, 140 );
2709     SetOutputSizePixel( Size( 114, 144 ) );
2710 
2711     m_aLineStyleLb->SetSourceUnit( FieldUnit::TWIP );
2712     m_aLineStyleLb->SetNone( SvxResId(RID_SVXSTR_NONE) );
2713 
2714     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::SOLID ), SvxBorderLineStyle::SOLID );
2715     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOTTED ), SvxBorderLineStyle::DOTTED );
2716     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DASHED ), SvxBorderLineStyle::DASHED );
2717 
2718     // Double lines
2719     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOUBLE ), SvxBorderLineStyle::DOUBLE );
2720     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_SMALLGAP ), SvxBorderLineStyle::THINTHICK_SMALLGAP, 20 );
2721     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_MEDIUMGAP ), SvxBorderLineStyle::THINTHICK_MEDIUMGAP );
2722     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_LARGEGAP ), SvxBorderLineStyle::THINTHICK_LARGEGAP );
2723     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_SMALLGAP ), SvxBorderLineStyle::THICKTHIN_SMALLGAP, 20 );
2724     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ), SvxBorderLineStyle::THICKTHIN_MEDIUMGAP );
2725     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_LARGEGAP ), SvxBorderLineStyle::THICKTHIN_LARGEGAP );
2726 
2727     // Engraved / Embossed
2728     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::EMBOSSED ), SvxBorderLineStyle::EMBOSSED, 15,
2729             &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor,
2730             &lcl_mediumColor );
2731     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::ENGRAVED ), SvxBorderLineStyle::ENGRAVED, 15,
2732             &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor,
2733             &lcl_mediumColor );
2734 
2735     // Inset / Outset
2736     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::OUTSET ), SvxBorderLineStyle::OUTSET, 10,
2737            &SvxBorderLine::lightColor, &SvxBorderLine::darkColor );
2738     m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::INSET ), SvxBorderLineStyle::INSET, 10,
2739            &SvxBorderLine::darkColor, &SvxBorderLine::lightColor );
2740     m_aLineStyleLb->SetWidth( 20 ); // 1pt by default
2741 
2742     m_aLineStyleLb->SetSelectHdl( LINK( this, SvxLineWindow_Impl, SelectHdl ) );
2743 
2744     SetHelpId( HID_POPUP_LINE );
2745     SetText( SvxResId(RID_SVXSTR_FRAME_STYLE) );
2746     m_aLineStyleLb->Show();
2747 }
2748 
IMPL_LINK_NOARG(SvxCurrencyList_Impl,SelectHdl,ListBox &,void)2749 IMPL_LINK_NOARG(SvxCurrencyList_Impl, SelectHdl, ListBox&, void)
2750 {
2751     VclPtr<SvxCurrencyList_Impl> xThis(this);
2752 
2753     if ( IsInPopupMode() )
2754         EndPopupMode();
2755 
2756     if (!m_xControl.is())
2757         return;
2758 
2759     m_rSelectedFormat = m_aFormatEntries[ m_pCurrencyLb->GetSelectedEntryPos() ];
2760     m_eSelectedLanguage = m_eFormatLanguage;
2761 
2762     m_xControl->execute( m_pCurrencyLb->GetSelectedEntryPos() + 1 );
2763 }
2764 
IMPL_LINK_NOARG(SvxLineWindow_Impl,SelectHdl,ListBox &,void)2765 IMPL_LINK_NOARG(SvxLineWindow_Impl, SelectHdl, ListBox&, void)
2766 {
2767     VclPtr<SvxLineWindow_Impl> xThis(this);
2768 
2769     SvxLineItem     aLineItem( SID_FRAME_LINESTYLE );
2770     SvxBorderLineStyle  nStyle = m_aLineStyleLb->GetSelectEntryStyle();
2771 
2772     if ( m_aLineStyleLb->GetSelectedEntryPos( ) > 0 )
2773     {
2774         SvxBorderLine aTmp;
2775         aTmp.SetBorderLineStyle( nStyle );
2776         aTmp.SetWidth( 20 ); // TODO Make it depend on a width field
2777         aLineItem.SetLine( &aTmp );
2778     }
2779     else
2780         aLineItem.SetLine( nullptr );
2781 
2782     if ( IsInPopupMode() )
2783         EndPopupMode();
2784 
2785     Any a;
2786     Sequence< PropertyValue > aArgs( 1 );
2787     aArgs[0].Name = "LineStyle";
2788     aLineItem.QueryValue( a, m_bIsWriter ? CONVERT_TWIPS : 0 );
2789     aArgs[0].Value = a;
2790 
2791     m_rController.dispatchCommand( ".uno:LineStyle", aArgs );
2792 }
2793 
Resize()2794 void SvxLineWindow_Impl::Resize()
2795 {
2796     m_aLineStyleLb->Resize();
2797 }
2798 
GetFocus()2799 void SvxLineWindow_Impl::GetFocus()
2800 {
2801     if ( m_aLineStyleLb )
2802         m_aLineStyleLb->GrabFocus();
2803 }
2804 
SfxStyleControllerItem_Impl(const Reference<XDispatchProvider> & rDispatchProvider,sal_uInt16 nSlotId,const OUString & rCommand,SvxStyleToolBoxControl & rTbxCtl)2805 SfxStyleControllerItem_Impl::SfxStyleControllerItem_Impl(
2806     const Reference< XDispatchProvider >& rDispatchProvider,
2807     sal_uInt16                                nSlotId,      // Family-ID
2808     const OUString&                  rCommand,     // .uno: command bound to this item
2809     SvxStyleToolBoxControl&               rTbxCtl )     // controller instance, which the item is assigned to.
2810     :   SfxStatusListener( rDispatchProvider, nSlotId, rCommand ),
2811         rControl( rTbxCtl )
2812 {
2813 }
2814 
StateChanged(SfxItemState eState,const SfxPoolItem * pState)2815 void SfxStyleControllerItem_Impl::StateChanged(
2816     SfxItemState eState, const SfxPoolItem* pState )
2817 {
2818     switch ( GetId() )
2819     {
2820         case SID_STYLE_FAMILY1:
2821         case SID_STYLE_FAMILY2:
2822         case SID_STYLE_FAMILY3:
2823         case SID_STYLE_FAMILY4:
2824         case SID_STYLE_FAMILY5:
2825         {
2826             const sal_uInt16 nIdx = GetId() - SID_STYLE_FAMILY_START;
2827 
2828             if ( SfxItemState::DEFAULT == eState )
2829             {
2830                 const SfxTemplateItem* pStateItem =
2831                     dynamic_cast<const SfxTemplateItem*>( pState  );
2832                 DBG_ASSERT( pStateItem != nullptr, "SfxTemplateItem expected" );
2833                 rControl.SetFamilyState( nIdx, pStateItem );
2834             }
2835             else
2836                 rControl.SetFamilyState( nIdx, nullptr );
2837             break;
2838         }
2839     }
2840 }
2841 
2842 struct SvxStyleToolBoxControl::Impl
2843 {
2844     OUString                     aClearForm;
2845     OUString                     aMore;
2846     ::std::vector< OUString >    aDefaultStyles;
2847     bool                     bSpecModeWriter;
2848     bool                     bSpecModeCalc;
2849 
ImplSvxStyleToolBoxControl::Impl2850     Impl()
2851         :aClearForm         ( SvxResId( RID_SVXSTR_CLEARFORM ) )
2852         ,aMore              ( SvxResId( RID_SVXSTR_MORE_STYLES ) )
2853         ,bSpecModeWriter    ( false )
2854         ,bSpecModeCalc      ( false )
2855     {
2856 
2857 
2858     }
InitializeStylesSvxStyleToolBoxControl::Impl2859     void InitializeStyles(const Reference < frame::XModel >& xModel)
2860     {
2861         //now convert the default style names to the localized names
2862         try
2863         {
2864             Reference< style::XStyleFamiliesSupplier > xStylesSupplier( xModel, UNO_QUERY_THROW );
2865             Reference< lang::XServiceInfo > xServices( xModel, UNO_QUERY_THROW );
2866             bSpecModeWriter = xServices->supportsService("com.sun.star.text.TextDocument");
2867             if(bSpecModeWriter)
2868             {
2869                 Reference<container::XNameAccess> xParaStyles;
2870                 xStylesSupplier->getStyleFamilies()->getByName("ParagraphStyles") >>=
2871                     xParaStyles;
2872                 static const std::vector<OUString> aWriterStyles =
2873                 {
2874                     "Standard",
2875                     "Text body",
2876                     "Title",
2877                     "Subtitle",
2878                     "Heading 1",
2879                     "Heading 2",
2880                     "Heading 3",
2881                     "Quotations"
2882                 };
2883                 for( const OUString& aStyle: aWriterStyles )
2884                 {
2885                     try
2886                     {
2887                         Reference< beans::XPropertySet > xStyle;
2888                         xParaStyles->getByName( aStyle ) >>= xStyle;
2889                         OUString sName;
2890                         xStyle->getPropertyValue("DisplayName") >>= sName;
2891                         if( !sName.isEmpty() )
2892                             aDefaultStyles.push_back(sName);
2893                     }
2894                     catch( const uno::Exception& )
2895                     {}
2896                 }
2897 
2898             }
2899             else if( (
2900                 bSpecModeCalc = xServices->supportsService(
2901                     "com.sun.star.sheet.SpreadsheetDocument")))
2902             {
2903                 static const sal_Char* aCalcStyles[] =
2904                 {
2905                     "Default",
2906                     "Heading1",
2907                     "Result",
2908                     "Result2"
2909                 };
2910                 Reference<container::XNameAccess> xCellStyles;
2911                 xStylesSupplier->getStyleFamilies()->getByName("CellStyles") >>= xCellStyles;
2912                 for(const char* pCalcStyle : aCalcStyles)
2913                 {
2914                     try
2915                     {
2916                         const OUString sStyleName( OUString::createFromAscii( pCalcStyle ) );
2917                         if( xCellStyles->hasByName( sStyleName ) )
2918                         {
2919                             Reference< beans::XPropertySet > xStyle( xCellStyles->getByName( sStyleName), UNO_QUERY_THROW );
2920                             OUString sName;
2921                             xStyle->getPropertyValue("DisplayName") >>= sName;
2922                             if( !sName.isEmpty() )
2923                                 aDefaultStyles.push_back(sName);
2924                         }
2925                     }
2926                     catch( const uno::Exception& )
2927                     {}
2928                 }
2929             }
2930         }
2931         catch(const uno::Exception& )
2932         {
2933             OSL_FAIL("error while initializing style names");
2934         }
2935     }
2936 };
2937 
2938 // mapping table from bound items. BE CAREFUL this table must be in the
2939 // same order as the uno commands bound to the slots SID_STYLE_FAMILY1..n
2940 // MAX_FAMILIES must also be correctly set!
2941 static const char* StyleSlotToStyleCommand[MAX_FAMILIES] =
2942 {
2943     ".uno:CharStyle",
2944     ".uno:ParaStyle",
2945     ".uno:FrameStyle",
2946     ".uno:PageStyle",
2947     ".uno:TemplateFamily5"
2948 };
2949 
SvxStyleToolBoxControl(sal_uInt16 nSlotId,sal_uInt16 nId,ToolBox & rTbx)2950 SvxStyleToolBoxControl::SvxStyleToolBoxControl(
2951     sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx )
2952     :   SfxToolBoxControl   ( nSlotId, nId, rTbx ),
2953         pImpl               ( new Impl ),
2954         pStyleSheetPool     ( nullptr ),
2955         nActFamily          ( 0xffff )
2956 {
2957     for ( sal_uInt16 i=0; i<MAX_FAMILIES; i++ )
2958     {
2959         pBoundItems[i] = nullptr;
2960         m_xBoundItems[i].clear();
2961         pFamilyState[i]  = nullptr;
2962     }
2963 }
2964 
~SvxStyleToolBoxControl()2965 SvxStyleToolBoxControl::~SvxStyleToolBoxControl()
2966 {
2967 }
2968 
initialize(const Sequence<Any> & aArguments)2969 void SAL_CALL SvxStyleToolBoxControl::initialize( const Sequence< Any >& aArguments )
2970 {
2971     SfxToolBoxControl::initialize( aArguments );
2972 
2973     // After initialize we should have a valid frame member where we can retrieve our
2974     // dispatch provider.
2975     if ( m_xFrame.is() )
2976     {
2977         pImpl->InitializeStyles(m_xFrame->getController()->getModel());
2978         Reference< XDispatchProvider > xDispatchProvider( m_xFrame->getController(), UNO_QUERY );
2979         for ( sal_uInt16 i=0; i<MAX_FAMILIES; i++ )
2980         {
2981             pBoundItems[i]   = new SfxStyleControllerItem_Impl( xDispatchProvider,
2982                                                                 SID_STYLE_FAMILY_START + i,
2983                                                                 OUString::createFromAscii( StyleSlotToStyleCommand[i] ),
2984                                                                 *this );
2985             m_xBoundItems[i].set( static_cast< OWeakObject* >( pBoundItems[i] ), UNO_QUERY );
2986             pFamilyState[i]  = nullptr;
2987         }
2988     }
2989 }
2990 
2991 // XComponent
dispose()2992 void SAL_CALL SvxStyleToolBoxControl::dispose()
2993 {
2994     SfxToolBoxControl::dispose();
2995 
2996     for( sal_uInt16 i=0; i<MAX_FAMILIES; i++ )
2997     {
2998         if ( m_xBoundItems[i].is() )
2999         {
3000             try
3001             {
3002                 m_xBoundItems[i]->dispose();
3003             }
3004             catch ( Exception& )
3005             {
3006             }
3007 
3008             m_xBoundItems[i].clear();
3009             pBoundItems[i] = nullptr;
3010         }
3011         pFamilyState[i].reset();
3012     }
3013     pStyleSheetPool = nullptr;
3014     pImpl.reset();
3015 }
3016 
update()3017 void SAL_CALL SvxStyleToolBoxControl::update()
3018 {
3019     // Do nothing, we will start binding our listener when we are visible.
3020     // See link SvxStyleToolBoxControl::VisibilityNotification.
3021     SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
3022     if ( pBox->IsVisible() )
3023     {
3024         for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
3025             pBoundItem->ReBind();
3026 
3027         bindListener();
3028     }
3029 }
3030 
GetActFamily() const3031 SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const
3032 {
3033     switch ( nActFamily-1 + SID_STYLE_FAMILY_START )
3034     {
3035         case SID_STYLE_FAMILY1: return SfxStyleFamily::Char;
3036         case SID_STYLE_FAMILY2: return SfxStyleFamily::Para;
3037         case SID_STYLE_FAMILY3: return SfxStyleFamily::Frame;
3038         case SID_STYLE_FAMILY4: return SfxStyleFamily::Page;
3039         case SID_STYLE_FAMILY5: return SfxStyleFamily::Pseudo;
3040         default:
3041             OSL_FAIL( "unknown style family" );
3042             break;
3043     }
3044     return SfxStyleFamily::Para;
3045 }
3046 
FillStyleBox()3047 void SvxStyleToolBoxControl::FillStyleBox()
3048 {
3049     SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
3050 
3051     DBG_ASSERT( pStyleSheetPool, "StyleSheetPool not found!" );
3052     DBG_ASSERT( pBox,            "Control not found!" );
3053 
3054     if ( pStyleSheetPool && pBox && nActFamily!=0xffff )
3055     {
3056         const SfxStyleFamily    eFamily     = GetActFamily();
3057         sal_uInt16              nCount      = pStyleSheetPool->Count();
3058         SfxStyleSheetBase*      pStyle      = nullptr;
3059         bool                    bDoFill     = false;
3060 
3061         pStyleSheetPool->SetSearchMask( eFamily, SfxStyleSearchBits::Used );
3062 
3063         // Check whether fill is necessary
3064         pStyle = pStyleSheetPool->First();
3065         //!!! TODO: This condition isn't right any longer, because we always show some default entries
3066         //!!! so the list doesn't show the count
3067         if ( nCount != pBox->GetEntryCount() )
3068         {
3069             bDoFill = true;
3070         }
3071         else
3072         {
3073             sal_uInt16 i= 0;
3074             while ( pStyle && !bDoFill )
3075             {
3076                 bDoFill = ( pBox->GetEntry(i) != pStyle->GetName() );
3077                 pStyle = pStyleSheetPool->Next();
3078                 i++;
3079             }
3080         }
3081 
3082         if ( bDoFill )
3083         {
3084             pBox->SetUpdateMode( false );
3085             pBox->Clear();
3086 
3087             {
3088                 pStyle = pStyleSheetPool->Next();
3089 
3090                 if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc )
3091                 {
3092                     while ( pStyle )
3093                     {
3094                         // sort out default styles
3095                         bool bInsert = true;
3096                         OUString aName( pStyle->GetName() );
3097                         for( auto const & _i: pImpl->aDefaultStyles )
3098                         {
3099                             if( _i == aName )
3100                             {
3101                                 bInsert = false;
3102                                 break;
3103                             }
3104                         }
3105 
3106                         if( bInsert )
3107                             pBox->InsertEntry( aName );
3108                         pStyle = pStyleSheetPool->Next();
3109                     }
3110                 }
3111                 else
3112                 {
3113                     while ( pStyle )
3114                     {
3115                         pBox->InsertEntry( pStyle->GetName() );
3116                         pStyle = pStyleSheetPool->Next();
3117                     }
3118                 }
3119             }
3120 
3121             if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc )
3122             {
3123                 // disable sort to preserve special order
3124                 WinBits nWinBits = pBox->GetStyle();
3125                 nWinBits &= ~WB_SORT;
3126                 pBox->SetStyle( nWinBits );
3127 
3128                 // insert default styles
3129                 sal_uInt16 nPos = 1;
3130                 for( auto const & _i: pImpl->aDefaultStyles )
3131                 {
3132                     pBox->InsertEntry( _i, nPos );
3133                     ++nPos;
3134                 }
3135 
3136                 pBox->InsertEntry( pImpl->aClearForm, 0 );
3137                 pBox->SetSeparatorPos( 0 );
3138 
3139                 pBox->InsertEntry( pImpl->aMore );
3140 
3141                 // enable sort again
3142                 nWinBits |= WB_SORT;
3143                 pBox->SetStyle( nWinBits );
3144             }
3145 
3146             pBox->SetUpdateMode( true );
3147             pBox->SetFamily( eFamily );
3148 
3149             sal_uInt16 nLines = static_cast<sal_uInt16>(
3150                     std::min( pBox->GetEntryCount(), static_cast<sal_Int32>(MAX_STYLES_ENTRIES)));
3151             pBox->SetDropDownLineCount( nLines );
3152         }
3153     }
3154 }
3155 
SelectStyle(const OUString & rStyleName)3156 void SvxStyleToolBoxControl::SelectStyle( const OUString& rStyleName )
3157 {
3158     SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
3159     DBG_ASSERT( pBox, "Control not found!" );
3160 
3161     if ( pBox )
3162     {
3163         OUString aStrSel( pBox->GetText() );
3164 
3165         if ( !rStyleName.isEmpty() )
3166         {
3167             if ( rStyleName != aStrSel )
3168                 pBox->SetText( rStyleName );
3169         }
3170         else
3171             pBox->SetNoSelection();
3172         pBox->SaveValue();
3173     }
3174 }
3175 
Update()3176 void SvxStyleToolBoxControl::Update()
3177 {
3178     SfxStyleSheetBasePool*  pPool     = nullptr;
3179     SfxObjectShell*         pDocShell = SfxObjectShell::Current();
3180 
3181     if ( pDocShell )
3182         pPool = pDocShell->GetStyleSheetPool();
3183 
3184     sal_uInt16 i;
3185     for ( i=0; i<MAX_FAMILIES; i++ )
3186         if( pFamilyState[i] )
3187             break;
3188 
3189     if ( i==MAX_FAMILIES || !pPool )
3190     {
3191         pStyleSheetPool = pPool;
3192         return;
3193     }
3194 
3195 
3196     const SfxTemplateItem* pItem = nullptr;
3197 
3198     if ( nActFamily == 0xffff || nullptr == (pItem = pFamilyState[nActFamily-1].get()) )
3199     // Current range not within allowed ranges or default
3200     {
3201         pStyleSheetPool = pPool;
3202         nActFamily      = 2;
3203 
3204         pItem = pFamilyState[nActFamily-1].get();
3205         if ( !pItem )
3206         {
3207             nActFamily++;
3208             pItem = pFamilyState[nActFamily-1].get();
3209         }
3210 
3211         if ( !pItem )
3212         {
3213             SAL_INFO( "svx", "Unknown Family" ); // can happen
3214         }
3215     }
3216     else if ( pPool != pStyleSheetPool )
3217         pStyleSheetPool = pPool;
3218 
3219     FillStyleBox(); // Decides by itself whether Fill is needed
3220 
3221     if ( pItem )
3222         SelectStyle( pItem->GetStyleName() );
3223 }
3224 
SetFamilyState(sal_uInt16 nIdx,const SfxTemplateItem * pItem)3225 void SvxStyleToolBoxControl::SetFamilyState( sal_uInt16 nIdx,
3226                                              const SfxTemplateItem* pItem )
3227 {
3228     pFamilyState[nIdx].reset( pItem == nullptr ? nullptr : new SfxTemplateItem( *pItem ) );
3229     Update();
3230 }
3231 
IMPL_LINK_NOARG(SvxStyleToolBoxControl,VisibilityNotification,SvxStyleBox_Impl &,void)3232 IMPL_LINK_NOARG(SvxStyleToolBoxControl, VisibilityNotification, SvxStyleBox_Impl&, void)
3233 {
3234     // Call ReBind() && UnBind() according to visibility
3235     SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>( GetToolBox().GetItemWindow( GetId() ));
3236 
3237     if ( pBox && pBox->IsVisible() && !isBound() )
3238     {
3239         for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
3240             pBoundItem->ReBind();
3241 
3242         bindListener();
3243     }
3244     else if ( (!pBox || !pBox->IsVisible()) && isBound() )
3245     {
3246         for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
3247             pBoundItem->UnBind();
3248         unbindListener();
3249     }
3250 }
3251 
StateChanged(sal_uInt16,SfxItemState eState,const SfxPoolItem * pState)3252 void SvxStyleToolBoxControl::StateChanged(
3253     sal_uInt16 , SfxItemState eState, const SfxPoolItem* pState )
3254 {
3255     sal_uInt16       nId    = GetId();
3256     ToolBox&     rTbx   = GetToolBox();
3257     SvxStyleBox_Impl* pBox   = static_cast<SvxStyleBox_Impl*>(rTbx.GetItemWindow( nId ));
3258     TriState     eTri   = TRISTATE_FALSE;
3259 
3260     DBG_ASSERT( pBox, "Control not found!" );
3261 
3262     if ( SfxItemState::DISABLED == eState )
3263         pBox->Disable();
3264     else
3265         pBox->Enable();
3266 
3267     rTbx.EnableItem( nId, SfxItemState::DISABLED != eState );
3268 
3269     switch ( eState )
3270     {
3271         case SfxItemState::DEFAULT:
3272             eTri = static_cast<const SfxTemplateItem*>(pState)->GetValue() != SfxStyleSearchBits::Auto
3273                         ? TRISTATE_TRUE
3274                         : TRISTATE_FALSE;
3275             break;
3276 
3277         case SfxItemState::DONTCARE:
3278             eTri = TRISTATE_INDET;
3279             break;
3280 
3281         default:
3282             break;
3283     }
3284 
3285     rTbx.SetItemState( nId, eTri );
3286 
3287     if ( SfxItemState::DISABLED != eState )
3288         Update();
3289 }
3290 
CreateItemWindow(vcl::Window * pParent)3291 VclPtr<vcl::Window> SvxStyleToolBoxControl::CreateItemWindow( vcl::Window *pParent )
3292 {
3293     VclPtrInstance<SvxStyleBox_Impl> pBox( pParent,
3294                                            OUString( ".uno:StyleApply" ),
3295                                            SfxStyleFamily::Para,
3296                                            Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ),
3297                                            m_xFrame,
3298                                            pImpl->aClearForm,
3299                                            pImpl->aMore,
3300                                            pImpl->bSpecModeWriter || pImpl->bSpecModeCalc );
3301     if( !pImpl->aDefaultStyles.empty())
3302         pBox->SetDefaultStyle( pImpl->aDefaultStyles[0] );
3303     // Set visibility listener to bind/unbind controller
3304     pBox->SetVisibilityListener( LINK( this, SvxStyleToolBoxControl, VisibilityNotification ));
3305 
3306     return pBox.get();
3307 }
3308 
3309 class SvxFontNameToolBoxControl : public cppu::ImplInheritanceHelper< svt::ToolboxController,
3310                                                                       css::lang::XServiceInfo >
3311 {
3312 public:
3313     SvxFontNameToolBoxControl();
3314 
3315     // XStatusListener
3316     virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
3317 
3318     // XToolbarController
3319     virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& rParent ) override;
3320 
3321     // XComponent
3322     virtual void SAL_CALL dispose() override;
3323 
3324     // XServiceInfo
3325     virtual OUString SAL_CALL getImplementationName() override;
3326     virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override;
3327     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
3328 
3329 private:
3330     VclPtr<SvxFontNameBox_Impl> m_pBox;
3331 };
3332 
SvxFontNameToolBoxControl()3333 SvxFontNameToolBoxControl::SvxFontNameToolBoxControl()
3334 {
3335 }
3336 
statusChanged(const css::frame::FeatureStateEvent & rEvent)3337 void SvxFontNameToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent )
3338 {
3339     SolarMutexGuard aGuard;
3340     ToolBox* pToolBox = nullptr;
3341     sal_uInt16 nId = 0;
3342     if ( !getToolboxId( nId, &pToolBox ) )
3343         return;
3344 
3345     if ( !rEvent.IsEnabled )
3346     {
3347         m_pBox->Disable();
3348         m_pBox->Update( nullptr );
3349     }
3350     else
3351     {
3352         m_pBox->Enable();
3353 
3354         css::awt::FontDescriptor aFontDesc;
3355         if ( rEvent.State >>= aFontDesc )
3356             m_pBox->Update( &aFontDesc );
3357         else
3358             m_pBox->SetText( "" );
3359         m_pBox->SaveValue();
3360     }
3361 
3362     pToolBox->EnableItem( nId, rEvent.IsEnabled );
3363 }
3364 
createItemWindow(const css::uno::Reference<css::awt::XWindow> & rParent)3365 css::uno::Reference< css::awt::XWindow > SvxFontNameToolBoxControl::createItemWindow( const css::uno::Reference< css::awt::XWindow >& rParent )
3366 {
3367     SolarMutexGuard aGuard;
3368     m_pBox = VclPtr<SvxFontNameBox_Impl>::Create( VCLUnoHelper::GetWindow( rParent ),
3369                                                   Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ),
3370                                                   m_xFrame, 0);
3371     return VCLUnoHelper::GetInterface( m_pBox );
3372 }
3373 
dispose()3374 void SvxFontNameToolBoxControl::dispose()
3375 {
3376     m_pBox.disposeAndClear();
3377     ToolboxController::dispose();
3378 }
3379 
getImplementationName()3380 OUString SvxFontNameToolBoxControl::getImplementationName()
3381 {
3382     return "com.sun.star.comp.svx.FontNameToolBoxControl";
3383 }
3384 
supportsService(const OUString & rServiceName)3385 sal_Bool SvxFontNameToolBoxControl::supportsService( const OUString& rServiceName )
3386 {
3387     return cppu::supportsService( this, rServiceName );
3388 }
3389 
getSupportedServiceNames()3390 css::uno::Sequence< OUString > SvxFontNameToolBoxControl::getSupportedServiceNames()
3391 {
3392     return { "com.sun.star.frame.ToolbarController" };
3393 }
3394 
3395 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)3396 com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation(
3397     css::uno::XComponentContext*,
3398     css::uno::Sequence<css::uno::Any> const & )
3399 {
3400     return cppu::acquire( new SvxFontNameToolBoxControl() );
3401 }
3402 
SvxColorToolBoxControl(const css::uno::Reference<css::uno::XComponentContext> & rContext)3403 SvxColorToolBoxControl::SvxColorToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) :
3404     ImplInheritanceHelper( rContext, nullptr, OUString() ),
3405     m_bSplitButton(true),
3406     m_nSlotId(0),
3407     m_aColorSelectFunction(PaletteManager::DispatchColorCommand)
3408 {
3409 }
3410 
3411 namespace {
3412 
MapCommandToSlotId(const OUString & rCommand)3413 sal_uInt16 MapCommandToSlotId(const OUString& rCommand)
3414 {
3415     if (rCommand == ".uno:Color")
3416         return SID_ATTR_CHAR_COLOR;
3417     else if (rCommand == ".uno:FontColor")
3418         return SID_ATTR_CHAR_COLOR2;
3419     else if (rCommand == ".uno:BackColor")
3420         return SID_ATTR_CHAR_COLOR_BACKGROUND;
3421     else if (rCommand == ".uno:CharBackColor")
3422         return SID_ATTR_CHAR_BACK_COLOR;
3423     else if (rCommand == ".uno:BackgroundColor")
3424         return SID_BACKGROUND_COLOR;
3425     else if (rCommand == ".uno:TableCellBackgroundColor")
3426         return SID_TABLE_CELL_BACKGROUND_COLOR;
3427     else if (rCommand == ".uno:Extrusion3DColor")
3428         return SID_EXTRUSION_3D_COLOR;
3429     else if (rCommand == ".uno:XLineColor")
3430         return SID_ATTR_LINE_COLOR;
3431     else if (rCommand == ".uno:FillColor")
3432         return SID_ATTR_FILL_COLOR;
3433     else if (rCommand == ".uno:FrameLineColor")
3434         return SID_FRAME_LINECOLOR;
3435 
3436     SAL_WARN("svx.tbxcrtls", "Unknown color command: " << rCommand);
3437     return 0;
3438 }
3439 
3440 }
3441 
initialize(const css::uno::Sequence<css::uno::Any> & rArguments)3442 void SvxColorToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments )
3443 {
3444     PopupWindowController::initialize( rArguments );
3445 
3446     ToolBox* pToolBox = nullptr;
3447     sal_uInt16 nId = 0;
3448     if ( !getToolboxId( nId, &pToolBox ) )
3449     {
3450         SAL_WARN("svx.tbxcrtls", "ToolBox not found!");
3451         return;
3452     }
3453 
3454     m_nSlotId = MapCommandToSlotId( m_aCommandURL );
3455     if ( m_nSlotId == SID_ATTR_LINE_COLOR || m_nSlotId == SID_ATTR_FILL_COLOR ||
3456          m_nSlotId == SID_FRAME_LINECOLOR || m_nSlotId == SID_BACKGROUND_COLOR )
3457         // Sidebar uses wide buttons for those.
3458         m_bSplitButton = typeid( *pToolBox ) != typeid( sfx2::sidebar::SidebarToolBox );
3459 
3460     auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(getCommandURL(), getModuleName());
3461     OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
3462 
3463     m_xBtnUpdater.reset( new svx::ToolboxButtonColorUpdater( m_nSlotId, nId, pToolBox, !m_bSplitButton,  aCommandLabel ) );
3464     pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ( m_bSplitButton ? ToolBoxItemBits::DROPDOWN : ToolBoxItemBits::DROPDOWNONLY ) );
3465 }
3466 
update()3467 void SvxColorToolBoxControl::update()
3468 {
3469     PopupWindowController::update();
3470 
3471     switch( m_nSlotId )
3472     {
3473         case SID_ATTR_CHAR_COLOR2:
3474             addStatusListener( ".uno:CharColorExt");
3475             break;
3476 
3477         case SID_ATTR_CHAR_COLOR_BACKGROUND:
3478             addStatusListener( ".uno:CharBackgroundExt");
3479             break;
3480 
3481         case SID_FRAME_LINECOLOR:
3482             addStatusListener( ".uno:BorderTLBR");
3483             addStatusListener( ".uno:BorderBLTR");
3484             break;
3485     }
3486 }
3487 
EnsurePaletteManager()3488 void SvxColorToolBoxControl::EnsurePaletteManager()
3489 {
3490     if (!m_xPaletteManager)
3491     {
3492         m_xPaletteManager.reset(new PaletteManager);
3493         m_xPaletteManager->SetBtnUpdater(m_xBtnUpdater.get());
3494     }
3495 }
3496 
~SvxColorToolBoxControl()3497 SvxColorToolBoxControl::~SvxColorToolBoxControl()
3498 {
3499     if (m_xPaletteManager)
3500         m_xPaletteManager->SetBtnUpdater(nullptr);
3501 }
3502 
setColorSelectFunction(const ColorSelectFunction & aColorSelectFunction)3503 void SvxColorToolBoxControl::setColorSelectFunction(const ColorSelectFunction& aColorSelectFunction)
3504 {
3505     m_aColorSelectFunction = aColorSelectFunction;
3506     if (m_xPaletteManager)
3507         m_xPaletteManager->SetColorSelectFunction(aColorSelectFunction);
3508 }
3509 
createPopupWindow(vcl::Window * pParent)3510 VclPtr<vcl::Window> SvxColorToolBoxControl::createPopupWindow( vcl::Window* pParent )
3511 {
3512     EnsurePaletteManager();
3513 
3514     VclPtrInstance<SvxColorWindow> pColorWin(
3515                             m_aCommandURL,
3516                             m_xPaletteManager,
3517                             m_aColorStatus,
3518                             m_nSlotId,
3519                             m_xFrame,
3520                             pParent,
3521                             false,
3522                             m_aColorSelectFunction);
3523 
3524     auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(m_aCommandURL, m_sModuleName);
3525     OUString aWindowTitle = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
3526     pColorWin->SetText( aWindowTitle );
3527     pColorWin->StartSelection();
3528     if ( m_bSplitButton )
3529         pColorWin->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) );
3530     return pColorWin;
3531 }
3532 
IMPL_LINK(SvxColorToolBoxControl,SelectedHdl,const NamedColor &,rColor,void)3533 IMPL_LINK(SvxColorToolBoxControl, SelectedHdl, const NamedColor&, rColor, void)
3534 {
3535     m_xBtnUpdater->Update(rColor);
3536 }
3537 
statusChanged(const css::frame::FeatureStateEvent & rEvent)3538 void SvxColorToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent )
3539 {
3540     ToolBox* pToolBox = nullptr;
3541     sal_uInt16 nId = 0;
3542     if ( !getToolboxId( nId, &pToolBox ) )
3543         return;
3544 
3545     if ( rEvent.FeatureURL.Complete == m_aCommandURL )
3546         pToolBox->EnableItem( nId, rEvent.IsEnabled );
3547 
3548     bool bValue;
3549     if ( !m_bSplitButton )
3550     {
3551         m_aColorStatus.statusChanged( rEvent );
3552         m_xBtnUpdater->Update( m_aColorStatus.GetColor() );
3553     }
3554     else if ( rEvent.State >>= bValue )
3555         pToolBox->CheckItem( nId, bValue );
3556 }
3557 
execute(sal_Int16)3558 void SvxColorToolBoxControl::execute(sal_Int16 /*nSelectModifier*/)
3559 {
3560     if ( !m_bSplitButton )
3561     {
3562         // Open the popup also when Enter key is pressed.
3563         createPopupWindow();
3564         return;
3565     }
3566 
3567     OUString aCommand = m_aCommandURL;
3568     Color aColor = m_xBtnUpdater->GetCurrentColor();
3569 
3570     switch( m_nSlotId )
3571     {
3572         case SID_ATTR_CHAR_COLOR2 :
3573             aCommand    = ".uno:CharColorExt";
3574             break;
3575 
3576         case SID_ATTR_CHAR_COLOR_BACKGROUND :
3577             aCommand    = ".uno:CharBackgroundExt";
3578             break;
3579     }
3580 
3581     auto aArgs( comphelper::InitPropertySequence( {
3582         { m_aCommandURL.copy(5), css::uno::makeAny(aColor) }
3583     } ) );
3584     dispatchCommand( aCommand, aArgs );
3585 
3586     EnsurePaletteManager();
3587     OUString sColorName = m_xBtnUpdater->GetCurrentColorName();
3588     m_xPaletteManager->AddRecentColor(aColor, sColorName);
3589 }
3590 
opensSubToolbar()3591 sal_Bool SvxColorToolBoxControl::opensSubToolbar()
3592 {
3593     // For a split button, we mark this controller as a sub-toolbar controller,
3594     // so we get notified (through updateImage method) on button image changes,
3595     // and could redraw the last used color on top of it.
3596     return m_bSplitButton;
3597 }
3598 
updateImage()3599 void SvxColorToolBoxControl::updateImage()
3600 {
3601     ToolBox* pToolBox = nullptr;
3602     sal_uInt16 nId = 0;
3603     if ( !getToolboxId( nId, &pToolBox ) )
3604         return;
3605 
3606     Image aImage = vcl::CommandInfoProvider::GetImageForCommand(m_aCommandURL, m_xFrame, pToolBox->GetImageSize());
3607     if ( !!aImage )
3608     {
3609         pToolBox->SetItemImage( nId, aImage );
3610         m_xBtnUpdater->Update(m_xBtnUpdater->GetCurrentColor(), true);
3611     }
3612 }
3613 
getSubToolbarName()3614 OUString SvxColorToolBoxControl::getSubToolbarName()
3615 {
3616     return OUString();
3617 }
3618 
functionSelected(const OUString &)3619 void SvxColorToolBoxControl::functionSelected( const OUString& /*rCommand*/ )
3620 {
3621 }
3622 
getImplementationName()3623 OUString SvxColorToolBoxControl::getImplementationName()
3624 {
3625     return "com.sun.star.comp.svx.ColorToolBoxControl";
3626 }
3627 
getSupportedServiceNames()3628 css::uno::Sequence<OUString> SvxColorToolBoxControl::getSupportedServiceNames()
3629 {
3630     return { "com.sun.star.frame.ToolbarController" };
3631 }
3632 
3633 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_svx_ColorToolBoxControl_get_implementation(css::uno::XComponentContext * rContext,css::uno::Sequence<css::uno::Any> const &)3634 com_sun_star_comp_svx_ColorToolBoxControl_get_implementation(
3635     css::uno::XComponentContext* rContext,
3636     css::uno::Sequence<css::uno::Any> const & )
3637 {
3638     return cppu::acquire( new SvxColorToolBoxControl( rContext ) );
3639 }
3640 
3641 // class SvxFrameToolBoxControl --------------------------------------------
3642 
3643 class SvxFrameToolBoxControl : public svt::PopupWindowController
3644 {
3645 public:
3646     explicit SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext );
3647 
3648     // XInitialization
3649     virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override;
3650 
3651     // XServiceInfo
3652     virtual OUString SAL_CALL getImplementationName() override;
3653     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
3654 
3655 private:
3656     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
3657     using svt::ToolboxController::createPopupWindow;
3658 };
3659 
SvxFrameToolBoxControl(const css::uno::Reference<css::uno::XComponentContext> & rContext)3660 SvxFrameToolBoxControl::SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext )
3661     : svt::PopupWindowController( rContext, nullptr, OUString() )
3662 {
3663 }
3664 
initialize(const css::uno::Sequence<css::uno::Any> & rArguments)3665 void SvxFrameToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments )
3666 {
3667     svt::PopupWindowController::initialize( rArguments );
3668     ToolBox* pToolBox = nullptr;
3669     sal_uInt16 nId = 0;
3670     if ( getToolboxId( nId, &pToolBox ) )
3671         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
3672 }
3673 
createPopupWindow(vcl::Window * pParent)3674 VclPtr<vcl::Window> SvxFrameToolBoxControl::createPopupWindow( vcl::Window* pParent )
3675 {
3676     if ( m_aCommandURL == ".uno:LineStyle" )
3677         return VclPtr<SvxLineWindow_Impl>::Create( *this, pParent );
3678 
3679     return VclPtr<SvxFrameWindow_Impl>::Create( *this, pParent );
3680 }
3681 
getImplementationName()3682 OUString SvxFrameToolBoxControl::getImplementationName()
3683 {
3684     return "com.sun.star.comp.svx.FrameToolBoxControl";
3685 }
3686 
getSupportedServiceNames()3687 css::uno::Sequence< OUString > SvxFrameToolBoxControl::getSupportedServiceNames()
3688 {
3689     return { "com.sun.star.frame.ToolbarController" };
3690 }
3691 
3692 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_svx_FrameToolBoxControl_get_implementation(css::uno::XComponentContext * rContext,css::uno::Sequence<css::uno::Any> const &)3693 com_sun_star_comp_svx_FrameToolBoxControl_get_implementation(
3694     css::uno::XComponentContext* rContext,
3695     css::uno::Sequence<css::uno::Any> const & )
3696 {
3697     return cppu::acquire( new SvxFrameToolBoxControl( rContext ) );
3698 }
3699 
SvxSimpleUndoRedoController(sal_uInt16 nSlotId,sal_uInt16 nId,ToolBox & rTbx)3700 SvxSimpleUndoRedoController::SvxSimpleUndoRedoController( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx  )
3701     :SfxToolBoxControl( nSlotId, nId, rTbx )
3702 {
3703     aDefaultText = rTbx.GetItemText( nId );
3704 }
3705 
~SvxSimpleUndoRedoController()3706 SvxSimpleUndoRedoController::~SvxSimpleUndoRedoController()
3707 {
3708 }
3709 
StateChanged(sal_uInt16,SfxItemState eState,const SfxPoolItem * pState)3710 void SvxSimpleUndoRedoController::StateChanged( sal_uInt16, SfxItemState eState, const SfxPoolItem* pState )
3711 {
3712     const SfxStringItem* pItem = dynamic_cast<const SfxStringItem*>( pState  );
3713     ToolBox& rBox = GetToolBox();
3714     if ( pItem && eState != SfxItemState::DISABLED )
3715     {
3716         OUString aNewText( MnemonicGenerator::EraseAllMnemonicChars( pItem->GetValue() ) );
3717         rBox.SetQuickHelpText( GetId(), aNewText );
3718     }
3719     if ( eState == SfxItemState::DISABLED )
3720         rBox.SetQuickHelpText( GetId(), aDefaultText );
3721     rBox.EnableItem( GetId(), eState != SfxItemState::DISABLED );
3722 }
3723 
SvxCurrencyToolBoxControl(const css::uno::Reference<css::uno::XComponentContext> & rContext)3724 SvxCurrencyToolBoxControl::SvxCurrencyToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) :
3725     PopupWindowController( rContext, nullptr, OUString() ),
3726     m_eLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ),
3727     m_nFormatKey( NUMBERFORMAT_ENTRY_NOT_FOUND )
3728 {
3729 }
3730 
~SvxCurrencyToolBoxControl()3731 SvxCurrencyToolBoxControl::~SvxCurrencyToolBoxControl() {}
3732 
initialize(const css::uno::Sequence<css::uno::Any> & rArguments)3733 void SvxCurrencyToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments )
3734 {
3735     PopupWindowController::initialize(rArguments);
3736 
3737     ToolBox* pToolBox = nullptr;
3738     sal_uInt16 nId = 0;
3739     if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL)
3740         pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId));
3741 }
3742 
createPopupWindow(vcl::Window * pParent)3743 VclPtr<vcl::Window> SvxCurrencyToolBoxControl::createPopupWindow( vcl::Window* pParent )
3744 {
3745     return VclPtr<SvxCurrencyList_Impl>::Create(this, pParent, m_aFormatString, m_eLanguage);
3746 }
3747 
execute(sal_Int16 nSelectModifier)3748 void SvxCurrencyToolBoxControl::execute( sal_Int16 nSelectModifier )
3749 {
3750     sal_uInt32 nFormatKey;
3751     if (m_aFormatString.isEmpty())
3752         nFormatKey = NUMBERFORMAT_ENTRY_NOT_FOUND;
3753     else
3754     {
3755         if ( nSelectModifier > 0 )
3756         {
3757             try
3758             {
3759                 uno::Reference< util::XNumberFormatsSupplier > xRef( m_xFrame->getController()->getModel(), uno::UNO_QUERY );
3760                 uno::Reference< util::XNumberFormats > rxNumberFormats( xRef->getNumberFormats(), uno::UNO_SET_THROW );
3761                 css::lang::Locale aLocale = LanguageTag::convertToLocale( m_eLanguage );
3762                 nFormatKey = rxNumberFormats->queryKey( m_aFormatString, aLocale, false );
3763                 if ( nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND )
3764                     nFormatKey = rxNumberFormats->addNew( m_aFormatString, aLocale );
3765                 }
3766                 catch( const uno::Exception& )
3767                 {
3768                     nFormatKey = m_nFormatKey;
3769                 }
3770         }
3771         else
3772             nFormatKey = m_nFormatKey;
3773     }
3774 
3775     if( nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND )
3776     {
3777         Sequence< PropertyValue > aArgs( 1 );
3778         aArgs[0].Name = "NumberFormatCurrency";
3779         aArgs[0].Value <<= nFormatKey;
3780         dispatchCommand( m_aCommandURL, aArgs );
3781         m_nFormatKey = nFormatKey;
3782     }
3783     else
3784         PopupWindowController::execute( nSelectModifier );
3785 }
3786 
getImplementationName()3787 OUString SvxCurrencyToolBoxControl::getImplementationName()
3788 {
3789     return "com.sun.star.comp.svx.CurrencyToolBoxControl";
3790 }
3791 
getSupportedServiceNames()3792 css::uno::Sequence<OUString> SvxCurrencyToolBoxControl::getSupportedServiceNames()
3793 {
3794     return { "com.sun.star.frame.ToolbarController" };
3795 }
3796 
3797 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_svx_CurrencyToolBoxControl_get_implementation(css::uno::XComponentContext * rContext,css::uno::Sequence<css::uno::Any> const &)3798 com_sun_star_comp_svx_CurrencyToolBoxControl_get_implementation(
3799     css::uno::XComponentContext* rContext,
3800     css::uno::Sequence<css::uno::Any> const & )
3801 {
3802     return cppu::acquire( new SvxCurrencyToolBoxControl( rContext ) );
3803 }
3804 
CreateAccessible()3805 Reference< css::accessibility::XAccessible > SvxFontNameBox_Impl::CreateAccessible()
3806 {
3807     FillList();
3808     return FontNameBox::CreateAccessible();
3809 }
3810 
3811 //static
GetCurrencySymbols(std::vector<OUString> & rList,bool bFlag,std::vector<sal_uInt16> & rCurrencyList)3812 void SvxCurrencyToolBoxControl::GetCurrencySymbols( std::vector<OUString>& rList, bool bFlag,
3813                                                     std::vector<sal_uInt16>& rCurrencyList )
3814 {
3815     rCurrencyList.clear();
3816 
3817     const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable();
3818     sal_uInt16 nCount = rCurrencyTable.size();
3819 
3820     sal_uInt16 nStart = 1;
3821 
3822     OUString aString( ApplyLreOrRleEmbedding( rCurrencyTable[0].GetSymbol() ) + " " );
3823     aString += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString(
3824                                        rCurrencyTable[0].GetLanguage() ) );
3825 
3826     rList.push_back( aString );
3827     rCurrencyList.push_back( sal_uInt16(-1) ); // nAuto
3828 
3829     if( bFlag )
3830     {
3831         rList.push_back( aString );
3832         rCurrencyList.push_back( 0 );
3833         ++nStart;
3834     }
3835 
3836     CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() );
3837     aCollator.loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
3838 
3839     const OUString aTwoSpace("  ");
3840 
3841     for( sal_uInt16 i = 1; i < nCount; ++i )
3842     {
3843         OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) );
3844         aStr += aTwoSpace;
3845         aStr += ApplyLreOrRleEmbedding( rCurrencyTable[i].GetSymbol() );
3846         aStr += aTwoSpace;
3847         aStr += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString(
3848                                         rCurrencyTable[i].GetLanguage() ) );
3849 
3850         std::vector<OUString>::size_type j = nStart;
3851         for( ; j < rList.size(); ++j )
3852             if ( aCollator.compareString( aStr, rList[j] ) < 0 )
3853                 break;  // insert before first greater than
3854 
3855         rList.insert( rList.begin() + j, aStr );
3856         rCurrencyList.insert( rCurrencyList.begin() + j, i );
3857     }
3858 
3859     // Append ISO codes to symbol list.
3860     // XXX If this is to be changed, various other places would had to be
3861     // adapted that assume this order!
3862     std::vector<OUString>::size_type nCont = rList.size();
3863 
3864     for ( sal_uInt16 i = 1; i < nCount; ++i )
3865     {
3866         bool bInsert = true;
3867         OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) );
3868 
3869         std::vector<OUString>::size_type j = nCont;
3870         for ( ; j < rList.size() && bInsert; ++j )
3871         {
3872             if( rList[j] == aStr )
3873                 bInsert = false;
3874             else if ( aCollator.compareString( aStr, rList[j] ) < 0 )
3875                 break;  // insert before first greater than
3876         }
3877         if ( bInsert )
3878         {
3879             rList.insert( rList.begin() + j, aStr );
3880             rCurrencyList.insert( rCurrencyList.begin() + j, i );
3881         }
3882     }
3883 }
3884 
SvxListBoxColorWrapper(SvxColorListBox * pControl)3885 SvxListBoxColorWrapper::SvxListBoxColorWrapper(SvxColorListBox* pControl)
3886     : mxControl(pControl)
3887 {
3888 }
3889 
operator ()(const OUString &,const NamedColor & rColor)3890 void SvxListBoxColorWrapper::operator()(const OUString& /*rCommand*/, const NamedColor& rColor)
3891 {
3892     if (!mxControl)
3893         return;
3894     mxControl->Selected(rColor);
3895 }
3896 
dispose()3897 void SvxListBoxColorWrapper::dispose()
3898 {
3899     mxControl.clear();
3900 }
3901 
ListBoxColorWrapper(ColorListBox * pControl)3902 ListBoxColorWrapper::ListBoxColorWrapper(ColorListBox* pControl)
3903     : mpControl(pControl)
3904 {
3905 }
3906 
operator ()(const OUString &,const NamedColor & rColor)3907 void ListBoxColorWrapper::operator()(const OUString& /*rCommand*/, const NamedColor& rColor)
3908 {
3909     mpControl->Selected(rColor);
3910 }
3911 
SvxColorListBox(vcl::Window * pParent,WinBits nStyle)3912 SvxColorListBox::SvxColorListBox(vcl::Window* pParent, WinBits nStyle)
3913     : MenuButton(pParent, nStyle)
3914     , m_aColorWrapper(this)
3915     , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor())
3916     , m_nSlotId(0)
3917     , m_bShowNoneButton(false)
3918 {
3919     m_aSelectedColor = GetAutoColor(m_nSlotId);
3920     LockWidthRequest();
3921     ShowPreview(m_aSelectedColor);
3922     SetActivateHdl(LINK(this, SvxColorListBox, MenuActivateHdl));
3923 }
3924 
EnsurePaletteManager()3925 void SvxColorListBox::EnsurePaletteManager()
3926 {
3927     if (!m_xPaletteManager)
3928     {
3929         m_xPaletteManager.reset(new PaletteManager);
3930         m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper));
3931     }
3932 }
3933 
EnsurePaletteManager()3934 void ColorListBox::EnsurePaletteManager()
3935 {
3936     if (!m_xPaletteManager)
3937     {
3938         m_xPaletteManager.reset(new PaletteManager);
3939         m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper));
3940     }
3941 }
3942 
SetSlotId(sal_uInt16 nSlotId)3943 void SvxColorListBox::SetSlotId(sal_uInt16 nSlotId)
3944 {
3945     m_nSlotId = nSlotId;
3946     m_bShowNoneButton = false;
3947     m_xColorWindow.disposeAndClear();
3948     m_aSelectedColor = GetAutoColor(m_nSlotId);
3949     ShowPreview(m_aSelectedColor);
3950     createColorWindow();
3951 }
3952 
SetSlotId(sal_uInt16 nSlotId,bool bShowNoneButton)3953 void ColorListBox::SetSlotId(sal_uInt16 nSlotId, bool bShowNoneButton)
3954 {
3955     m_nSlotId = nSlotId;
3956     m_bShowNoneButton = bShowNoneButton;
3957     m_xButton->set_popover(nullptr);
3958     m_xColorWindow.reset();
3959     m_aSelectedColor = bShowNoneButton ? GetNoneColor() : GetAutoColor(m_nSlotId);
3960     ShowPreview(m_aSelectedColor);
3961     createColorWindow();
3962 }
3963 
3964 //to avoid the box resizing every time the color is changed to
3965 //the optimal size of the individual color, get the longest
3966 //standard color and stick with that as the size for all
LockWidthRequest()3967 void SvxColorListBox::LockWidthRequest()
3968 {
3969     if (get_width_request() != -1)
3970         return;
3971     NamedColor aLongestColor;
3972     long nMaxStandardColorTextWidth = 0;
3973     XColorListRef const xColorTable = XColorList::CreateStdColorList();
3974     for (long i = 0; i != xColorTable->Count(); ++i)
3975     {
3976         XColorEntry& rEntry = *xColorTable->GetColor(i);
3977         long nColorTextWidth = GetTextWidth(rEntry.GetName());
3978         if (nColorTextWidth > nMaxStandardColorTextWidth)
3979         {
3980             nMaxStandardColorTextWidth = nColorTextWidth;
3981             aLongestColor.second = rEntry.GetName();
3982         }
3983     }
3984     ShowPreview(aLongestColor);
3985     set_width_request(get_preferred_size().Width());
3986 }
3987 
ShowPreview(const NamedColor & rColor)3988 void SvxColorListBox::ShowPreview(const NamedColor &rColor)
3989 {
3990     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
3991     Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize());
3992 
3993     ScopedVclPtrInstance<VirtualDevice> xDevice;
3994     xDevice->SetOutputSize(aImageSize);
3995     const tools::Rectangle aRect(Point(0, 0), aImageSize);
3996     if (m_bShowNoneButton && rColor.first == COL_NONE_COLOR)
3997     {
3998         const Color aW(COL_WHITE);
3999         const Color aG(0xef, 0xef, 0xef);
4000         xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), 8, aW, aG);
4001         xDevice->SetFillColor();
4002     }
4003     else
4004     {
4005         if (rColor.first == COL_AUTO)
4006             xDevice->SetFillColor(m_aAutoDisplayColor);
4007         else
4008             xDevice->SetFillColor(rColor.first);
4009     }
4010 
4011     xDevice->SetLineColor(rStyleSettings.GetDisableColor());
4012     xDevice->DrawRect(aRect);
4013 
4014     BitmapEx aBitmap(xDevice->GetBitmapEx(Point(0, 0), xDevice->GetOutputSize()));
4015     SetImageAlign(ImageAlign::Left);
4016     SetModeImage(Image(aBitmap));
4017     SetText(rColor.second);
4018 }
4019 
IMPL_LINK(SvxColorListBox,WindowEventListener,VclWindowEvent &,rWindowEvent,void)4020 IMPL_LINK(SvxColorListBox, WindowEventListener, VclWindowEvent&, rWindowEvent, void)
4021 {
4022     if (rWindowEvent.GetId() == VclEventId::WindowEndPopupMode)
4023     {
4024         m_xColorWindow.disposeAndClear();
4025         SetPopover(nullptr);
4026     }
4027 }
4028 
IMPL_LINK_NOARG(SvxColorListBox,MenuActivateHdl,MenuButton *,void)4029 IMPL_LINK_NOARG(SvxColorListBox, MenuActivateHdl, MenuButton *, void)
4030 {
4031     if (!m_xColorWindow || m_xColorWindow->isDisposed())
4032         createColorWindow();
4033 }
4034 
createColorWindow()4035 void SvxColorListBox::createColorWindow()
4036 {
4037     const SfxViewFrame* pViewFrame = SfxViewFrame::Current();
4038     const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr;
4039     css::uno::Reference<css::frame::XFrame> xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference<css::frame::XFrame>());
4040 
4041     EnsurePaletteManager();
4042 
4043     m_xColorWindow = VclPtr<SvxColorWindow>::Create(
4044                             OUString() /*m_aCommandURL*/,
4045                             m_xPaletteManager,
4046                             m_aColorStatus,
4047                             m_nSlotId,
4048                             xFrame,
4049                             this,
4050                             true,
4051                             m_aColorWrapper);
4052 
4053     m_xColorWindow->AddEventListener(LINK(this, SvxColorListBox, WindowEventListener));
4054 
4055     SetNoSelection();
4056     if (m_bShowNoneButton)
4057         m_xColorWindow->ShowNoneButton();
4058     m_xColorWindow->SelectEntry(m_aSelectedColor);
4059     SetPopover(m_xColorWindow);
4060 }
4061 
Selected(const NamedColor & rColor)4062 void SvxColorListBox::Selected(const NamedColor& rColor)
4063 {
4064     ShowPreview(rColor);
4065     m_aSelectedColor = rColor;
4066     if (m_aSelectedLink.IsSet())
4067         m_aSelectedLink.Call(*this);
4068 }
4069 
VCL_BUILDER_FACTORY(SvxColorListBox)4070 VCL_BUILDER_FACTORY(SvxColorListBox)
4071 
4072 SvxColorListBox::~SvxColorListBox()
4073 {
4074     disposeOnce();
4075 }
4076 
dispose()4077 void SvxColorListBox::dispose()
4078 {
4079     m_xColorWindow.disposeAndClear();
4080     m_aColorWrapper.dispose();
4081     MenuButton::dispose();
4082 }
4083 
getColorWindow() const4084 VclPtr<SvxColorWindow> const & SvxColorListBox::getColorWindow() const
4085 {
4086     if (!m_xColorWindow || m_xColorWindow->isDisposed())
4087         const_cast<SvxColorListBox*>(this)->createColorWindow();
4088     return m_xColorWindow;
4089 }
4090 
SelectEntry(const NamedColor & rColor)4091 void SvxColorListBox::SelectEntry(const NamedColor& rColor)
4092 {
4093     if (rColor.second.trim().isEmpty())
4094     {
4095         SelectEntry(rColor.first);
4096         return;
4097     }
4098     VclPtr<SvxColorWindow> xColorWindow = getColorWindow();
4099     xColorWindow->SelectEntry(rColor);
4100     m_aSelectedColor = xColorWindow->GetSelectEntryColor();
4101     ShowPreview(m_aSelectedColor);
4102 }
4103 
SelectEntry(const Color & rColor)4104 void SvxColorListBox::SelectEntry(const Color& rColor)
4105 {
4106     VclPtr<SvxColorWindow> xColorWindow = getColorWindow();
4107     xColorWindow->SelectEntry(rColor);
4108     m_aSelectedColor = xColorWindow->GetSelectEntryColor();
4109     ShowPreview(m_aSelectedColor);
4110 }
4111 
ColorListBox(std::unique_ptr<weld::MenuButton> pControl,weld::Window * pTopLevel)4112 ColorListBox::ColorListBox(std::unique_ptr<weld::MenuButton> pControl, weld::Window* pTopLevel)
4113     : m_xButton(std::move(pControl))
4114     , m_pTopLevel(pTopLevel)
4115     , m_aColorWrapper(this)
4116     , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor())
4117     , m_nSlotId(0)
4118     , m_bShowNoneButton(false)
4119 {
4120     m_xButton->connect_toggled(LINK(this, ColorListBox, ToggleHdl));
4121     m_aSelectedColor = GetAutoColor(m_nSlotId);
4122     LockWidthRequest();
4123     ShowPreview(m_aSelectedColor);
4124 }
4125 
IMPL_LINK(ColorListBox,ToggleHdl,weld::ToggleButton &,rButton,void)4126 IMPL_LINK(ColorListBox, ToggleHdl, weld::ToggleButton&, rButton, void)
4127 {
4128     if (rButton.get_active())
4129         getColorWindow()->FocusHdl(*m_xButton);
4130 }
4131 
~ColorListBox()4132 ColorListBox::~ColorListBox()
4133 {
4134 }
4135 
getColorWindow() const4136 ColorWindow* ColorListBox::getColorWindow() const
4137 {
4138     if (!m_xColorWindow)
4139         const_cast<ColorListBox*>(this)->createColorWindow();
4140     return m_xColorWindow.get();
4141 }
4142 
createColorWindow()4143 void ColorListBox::createColorWindow()
4144 {
4145     const SfxViewFrame* pViewFrame = SfxViewFrame::Current();
4146     const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr;
4147     css::uno::Reference<css::frame::XFrame> xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference<css::frame::XFrame>());
4148 
4149     EnsurePaletteManager();
4150 
4151     m_xColorWindow.reset(new ColorWindow(
4152                             m_xPaletteManager,
4153                             m_aColorStatus,
4154                             m_nSlotId,
4155                             xFrame,
4156                             m_pTopLevel,
4157                             m_xButton.get(),
4158                             m_aColorWrapper));
4159 
4160     SetNoSelection();
4161     m_xButton->set_popover(m_xColorWindow->GetWidget());
4162     if (m_bShowNoneButton)
4163         m_xColorWindow->ShowNoneButton();
4164     m_xColorWindow->SelectEntry(m_aSelectedColor);
4165 }
4166 
SelectEntry(const NamedColor & rColor)4167 void ColorListBox::SelectEntry(const NamedColor& rColor)
4168 {
4169     if (rColor.second.trim().isEmpty())
4170     {
4171         SelectEntry(rColor.first);
4172         return;
4173     }
4174     ColorWindow* pColorWindow = getColorWindow();
4175     pColorWindow->SelectEntry(rColor);
4176     m_aSelectedColor = pColorWindow->GetSelectEntryColor();
4177     ShowPreview(m_aSelectedColor);
4178 }
4179 
SelectEntry(const Color & rColor)4180 void ColorListBox::SelectEntry(const Color& rColor)
4181 {
4182     ColorWindow* pColorWindow = getColorWindow();
4183     pColorWindow->SelectEntry(rColor);
4184     m_aSelectedColor = pColorWindow->GetSelectEntryColor();
4185     ShowPreview(m_aSelectedColor);
4186 }
4187 
Selected(const NamedColor & rColor)4188 void ColorListBox::Selected(const NamedColor& rColor)
4189 {
4190     ShowPreview(rColor);
4191     m_aSelectedColor = rColor;
4192     if (m_aSelectedLink.IsSet())
4193         m_aSelectedLink.Call(*this);
4194 }
4195 
4196 //to avoid the box resizing every time the color is changed to
4197 //the optimal size of the individual color, get the longest
4198 //standard color and stick with that as the size for all
LockWidthRequest()4199 void ColorListBox::LockWidthRequest()
4200 {
4201     NamedColor aLongestColor;
4202     long nMaxStandardColorTextWidth = 0;
4203     XColorListRef const xColorTable = XColorList::CreateStdColorList();
4204     for (long i = 0; i != xColorTable->Count(); ++i)
4205     {
4206         XColorEntry& rEntry = *xColorTable->GetColor(i);
4207         auto nColorTextWidth = m_xButton->get_pixel_size(rEntry.GetName()).Width();
4208         if (nColorTextWidth > nMaxStandardColorTextWidth)
4209         {
4210             nMaxStandardColorTextWidth = nColorTextWidth;
4211             aLongestColor.second = rEntry.GetName();
4212         }
4213     }
4214     ShowPreview(aLongestColor);
4215     m_xButton->set_size_request(m_xButton->get_preferred_size().Width(), -1);
4216 }
4217 
ShowPreview(const NamedColor & rColor)4218 void ColorListBox::ShowPreview(const NamedColor &rColor)
4219 {
4220     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
4221     Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize());
4222 
4223     ScopedVclPtrInstance<VirtualDevice> xDevice;
4224     xDevice->SetOutputSize(aImageSize);
4225     const tools::Rectangle aRect(Point(0, 0), aImageSize);
4226     if (m_bShowNoneButton && rColor.first == COL_NONE_COLOR)
4227     {
4228         const Color aW(COL_WHITE);
4229         const Color aG(0xef, 0xef, 0xef);
4230         xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), 8, aW, aG);
4231         xDevice->SetFillColor();
4232     }
4233     else
4234     {
4235         if (rColor.first == COL_AUTO)
4236             xDevice->SetFillColor(m_aAutoDisplayColor);
4237         else
4238             xDevice->SetFillColor(rColor.first);
4239     }
4240 
4241     xDevice->SetLineColor(rStyleSettings.GetDisableColor());
4242     xDevice->DrawRect(aRect);
4243 
4244     m_xButton->set_image(xDevice.get());
4245     m_xButton->set_label(rColor.second);
4246 }
4247 
MenuOrToolMenuButton(weld::MenuButton * pMenuButton)4248 MenuOrToolMenuButton::MenuOrToolMenuButton(weld::MenuButton* pMenuButton)
4249     : m_pMenuButton(pMenuButton)
4250     , m_pToolbar(nullptr)
4251 {
4252 }
4253 
MenuOrToolMenuButton(weld::Toolbar * pToolbar,const OString & rIdent)4254 MenuOrToolMenuButton::MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OString& rIdent)
4255     : m_pMenuButton(nullptr)
4256     , m_pToolbar(pToolbar)
4257     , m_aIdent(rIdent)
4258 {
4259 }
4260 
get_active() const4261 bool MenuOrToolMenuButton::get_active() const
4262 {
4263     if (m_pMenuButton)
4264         return m_pMenuButton->get_active();
4265     return m_pToolbar->get_item_active(m_aIdent);
4266 }
4267 
set_active(bool bActive) const4268 void MenuOrToolMenuButton::set_active(bool bActive) const
4269 {
4270     if (m_pMenuButton)
4271     {
4272         m_pMenuButton->set_active(bActive);
4273         return;
4274     }
4275     m_pToolbar->set_item_active(m_aIdent, bActive);
4276 }
4277 
get_widget() const4278 weld::Widget* MenuOrToolMenuButton::get_widget() const
4279 {
4280     if (m_pMenuButton)
4281         return m_pMenuButton;
4282     return m_pToolbar;
4283 }
4284 
4285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4286