Coverage Report

Created: 2026-03-31 11:00

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