Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/tbxctrls/fillctrl.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 <sfx2/dispatch.hxx>
21
#include <sfx2/objsh.hxx>
22
#include <sfx2/viewsh.hxx>
23
#include <rtl/ustring.hxx>
24
#include <tools/mapunit.hxx>
25
#include <vcl/event.hxx>
26
#include <vcl/settings.hxx>
27
#include <vcl/toolbox.hxx>
28
#include <vcl/virdev.hxx>
29
#include <vcl/weld/Builder.hxx>
30
#include <vcl/weld/Container.hxx>
31
#include <svl/itemset.hxx>
32
#include <svx/svxids.hrc>
33
#include <tools/json_writer.hxx>
34
35
constexpr OUString TMP_STR_BEGIN = u"["_ustr;
36
constexpr OUString TMP_STR_END = u"]"_ustr;
37
38
#include <svx/drawitem.hxx>
39
#include <svx/xfillit0.hxx>
40
#include <svx/xtable.hxx>
41
#include <svx/fillctrl.hxx>
42
#include <svx/itemwin.hxx>
43
#include <svx/xflclit.hxx>
44
#include <svx/xflgrit.hxx>
45
#include <svx/xflhtit.hxx>
46
#include <svx/xbtmpit.hxx>
47
#include <memory>
48
49
using namespace ::com::sun::star;
50
using namespace ::com::sun::star::uno;
51
using namespace ::com::sun::star::util;
52
53
namespace {
54
55
enum eFillStyle
56
{
57
    NONE,
58
    SOLID,
59
    GRADIENT,
60
    HATCH,
61
    BITMAP,
62
    PATTERN
63
};
64
65
drawing::FillStyle toCssFillStyle( eFillStyle eXFS )
66
0
{
67
0
    if (eXFS == PATTERN)
68
0
    {
69
0
        return drawing::FillStyle_BITMAP;
70
0
    }
71
72
0
    return static_cast<drawing::FillStyle>(eXFS);
73
0
}
74
75
}
76
77
SFX_IMPL_TOOLBOX_CONTROL( SvxFillToolBoxControl, XFillStyleItem );
78
79
SvxFillToolBoxControl::SvxFillToolBoxControl(
80
    sal_uInt16 nSlotId,
81
    ToolBoxItemId nId,
82
    ToolBox& rTbx )
83
0
    : SfxToolBoxControl( nSlotId, nId, rTbx )
84
0
    , mxFillControl(nullptr)
85
0
    , mpLbFillType(nullptr)
86
0
    , mpToolBoxColor(nullptr)
87
0
    , mpLbFillAttr(nullptr)
88
0
    , mnLastXFS(-1)
89
0
    , mnLastPosGradient(0)
90
0
    , mnLastPosHatch(0)
91
0
    , mnLastPosBitmap(0)
92
0
    , mnLastPosPattern(0)
93
0
{
94
0
    addStatusListener( u".uno:FillColor"_ustr);
95
0
    addStatusListener( u".uno:FillGradient"_ustr);
96
0
    addStatusListener( u".uno:FillHatch"_ustr);
97
0
    addStatusListener( u".uno:FillBitmap"_ustr);
98
0
    addStatusListener( u".uno:ColorTableState"_ustr);
99
0
    addStatusListener( u".uno:GradientListState"_ustr);
100
0
    addStatusListener( u".uno:HatchListState"_ustr);
101
0
    addStatusListener( u".uno:BitmapListState"_ustr);
102
0
}
Unexecuted instantiation: SvxFillToolBoxControl::SvxFillToolBoxControl(unsigned short, o3tl::strong_int<unsigned short, ToolBoxItemIdTag>, ToolBox&)
Unexecuted instantiation: SvxFillToolBoxControl::SvxFillToolBoxControl(unsigned short, o3tl::strong_int<unsigned short, ToolBoxItemIdTag>, ToolBox&)
103
104
SvxFillToolBoxControl::~SvxFillToolBoxControl()
105
0
{
106
0
}
107
108
void SvxFillToolBoxControl::StateChangedAtToolBoxControl(
109
    sal_uInt16 nSID,
110
    SfxItemState eState,
111
    const SfxPoolItem* pState)
112
0
{
113
0
    const bool bDisabled(SfxItemState::DISABLED == eState);
114
115
0
    switch(nSID)
116
0
    {
117
0
        case SID_ATTR_FILL_STYLE:
118
0
        {
119
0
            if(bDisabled)
120
0
            {
121
0
                mpLbFillType->set_sensitive(false);
122
0
                mpLbFillType->set_active(-1);
123
0
                mpLbFillAttr->show();
124
0
                mpLbFillAttr->set_sensitive(false);
125
0
                mpLbFillAttr->set_active(-1);
126
0
                mpToolBoxColor->hide();
127
0
                mnLastXFS = -1;
128
0
                mpStyleItem.reset();
129
0
            }
130
131
0
            if(eState >= SfxItemState::DEFAULT)
132
0
            {
133
0
                const XFillStyleItem* pItem = dynamic_cast< const XFillStyleItem* >(pState);
134
135
0
                if(pItem)
136
0
                {
137
0
                    mpStyleItem.reset(pItem->Clone());
138
0
                    mpLbFillType->set_sensitive(true);
139
0
                    drawing::FillStyle eXFS = mpStyleItem->GetValue();
140
0
                    mnLastXFS = sal::static_int_cast< sal_Int32 >(eXFS);
141
0
                    mpLbFillType->set_active(mnLastXFS);
142
143
0
                    if(drawing::FillStyle_NONE == eXFS)
144
0
                    {
145
0
                        mpLbFillAttr->set_active(-1);
146
0
                        mpLbFillAttr->set_sensitive(false);
147
0
                    }
148
149
0
                    Update();
150
0
                    break;
151
0
                }
152
0
            }
153
154
0
            mpLbFillType->set_active(-1);
155
0
            mpLbFillAttr->show();
156
0
            mpLbFillAttr->set_sensitive(false);
157
0
            mpLbFillAttr->set_active(-1);
158
0
            mpToolBoxColor->hide();
159
0
            mnLastXFS = -1;
160
0
            mpStyleItem.reset();
161
0
            mxFillControl->Resize();
162
0
            break;
163
0
        }
164
0
        case SID_ATTR_FILL_COLOR:
165
0
        {
166
0
            if(SfxItemState::DEFAULT == eState)
167
0
            {
168
0
                mpColorItem.reset(pState ? static_cast<XFillColorItem*>(pState->Clone()) : nullptr);
169
0
            }
170
171
0
            if(mpStyleItem && drawing::FillStyle_SOLID == mpStyleItem->GetValue())
172
0
            {
173
0
                mpLbFillAttr->hide();
174
0
                mpToolBoxColor->show();
175
0
                mxFillControl->Resize();
176
177
0
                Update();
178
0
            }
179
0
            break;
180
0
        }
181
0
        case SID_ATTR_FILL_GRADIENT:
182
0
        {
183
0
            if(SfxItemState::DEFAULT == eState)
184
0
            {
185
0
                mpFillGradientItem.reset(pState ? static_cast<XFillGradientItem*>(pState->Clone()) : nullptr);
186
0
            }
187
188
0
            if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue())
189
0
            {
190
0
                mpLbFillAttr->show();
191
0
                mpToolBoxColor->hide();
192
0
                mxFillControl->Resize();
193
194
0
                if(SfxItemState::DEFAULT == eState)
195
0
                {
196
0
                    mpLbFillAttr->set_sensitive(true);
197
0
                    Update();
198
0
                }
199
0
                else if(SfxItemState::DISABLED == eState )
200
0
                {
201
0
                    mpLbFillAttr->set_sensitive(false);
202
0
                    mpLbFillAttr->set_active(-1);
203
0
                }
204
0
                else
205
0
                {
206
0
                    mpLbFillAttr->set_active(-1);
207
0
                }
208
0
            }
209
0
            break;
210
0
        }
211
0
        case SID_ATTR_FILL_HATCH:
212
0
        {
213
0
            if(SfxItemState::DEFAULT == eState)
214
0
            {
215
0
                mpHatchItem.reset(pState ? static_cast<XFillHatchItem*>(pState->Clone()) : nullptr);
216
0
            }
217
218
0
            if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue())
219
0
            {
220
0
                mpLbFillAttr->show();
221
0
                mpToolBoxColor->hide();
222
0
                mxFillControl->Resize();
223
224
0
                if(SfxItemState::DEFAULT == eState)
225
0
                {
226
0
                    mpLbFillAttr->set_sensitive(true);
227
0
                    Update();
228
0
                }
229
0
                else if(SfxItemState::DISABLED == eState )
230
0
                {
231
0
                    mpLbFillAttr->set_sensitive(false);
232
0
                    mpLbFillAttr->set_active(-1);
233
0
                }
234
0
                else
235
0
                {
236
0
                    mpLbFillAttr->set_active(-1);
237
0
                }
238
0
            }
239
0
            break;
240
0
        }
241
0
        case SID_ATTR_FILL_BITMAP:
242
0
        {
243
0
            if(SfxItemState::DEFAULT == eState)
244
0
            {
245
0
                mpBitmapItem.reset(pState ? static_cast<XFillBitmapItem*>(pState->Clone()) : nullptr);
246
0
            }
247
248
0
            if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue())
249
0
            {
250
0
                mpLbFillAttr->show();
251
0
                mpToolBoxColor->hide();
252
0
                mxFillControl->Resize();
253
254
0
                if(SfxItemState::DEFAULT == eState)
255
0
                {
256
0
                    mpLbFillAttr->set_sensitive(true);
257
0
                    Update();
258
0
                }
259
0
                else if(SfxItemState::DISABLED == eState )
260
0
                {
261
0
                    mpLbFillAttr->set_sensitive(false);
262
0
                    mpLbFillAttr->set_active(-1);
263
0
                }
264
0
                else
265
0
                {
266
0
                    mpLbFillAttr->set_active(-1);
267
0
                }
268
0
            }
269
0
            break;
270
0
        }
271
0
        case SID_GRADIENT_LIST:
272
0
        {
273
0
            if(SfxItemState::DEFAULT == eState)
274
0
            {
275
0
                if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue())
276
0
                {
277
0
                    if(mpFillGradientItem)
278
0
                    {
279
0
                        const OUString aString( mpFillGradientItem->GetName() );
280
0
                        mpLbFillAttr->clear();
281
0
                        if (const SfxObjectShell* pSh = SfxObjectShell::Current())
282
0
                        {
283
0
                            mpLbFillAttr->set_sensitive(true);
284
0
                            SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
285
0
                        }
286
0
                        mpLbFillAttr->set_active_text(aString);
287
0
                    }
288
0
                    else
289
0
                    {
290
0
                        mpLbFillAttr->set_active(-1);
291
0
                    }
292
0
                }
293
0
            }
294
0
            break;
295
0
        }
296
0
        case SID_HATCH_LIST:
297
0
        {
298
0
            if(SfxItemState::DEFAULT == eState)
299
0
            {
300
0
                if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue())
301
0
                {
302
0
                    if(mpHatchItem)
303
0
                    {
304
0
                        const OUString aString( mpHatchItem->GetName() );
305
0
                        mpLbFillAttr->clear();
306
0
                        if (const SfxObjectShell* pSh = SfxObjectShell::Current())
307
0
                        {
308
0
                            mpLbFillAttr->set_sensitive(true);
309
0
                            SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
310
0
                        }
311
0
                        mpLbFillAttr->set_active_text(aString);
312
0
                    }
313
0
                    else
314
0
                    {
315
0
                        mpLbFillAttr->set_active(-1);
316
0
                    }
317
0
                }
318
0
            }
319
0
            break;
320
0
        }
321
0
        case SID_BITMAP_LIST:
322
0
        {
323
0
            if(SfxItemState::DEFAULT == eState)
324
0
            {
325
0
                if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue())
326
0
                {
327
0
                    if(mpBitmapItem)
328
0
                    {
329
0
                        const OUString aString( mpBitmapItem->GetName() );
330
0
                        mpLbFillAttr->clear();
331
0
                        if (const SfxObjectShell* pSh = SfxObjectShell::Current())
332
0
                        {
333
0
                            mpLbFillAttr->set_sensitive(true);
334
0
                            SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
335
0
                        }
336
0
                        mpLbFillAttr->set_active_text(aString);
337
0
                    }
338
0
                    else
339
0
                    {
340
0
                        mpLbFillAttr->set_active(-1);
341
0
                    }
342
0
                }
343
0
            }
344
0
            break;
345
0
        }
346
0
    }
347
0
}
348
349
void SvxFillToolBoxControl::Update()
350
0
{
351
0
    if(!mpStyleItem)
352
0
        return;
353
354
0
    const drawing::FillStyle eXFS = mpStyleItem->GetValue();
355
0
    SfxObjectShell* pSh = SfxObjectShell::Current();
356
357
0
    switch( eXFS )
358
0
    {
359
0
        case drawing::FillStyle_NONE:
360
0
        {
361
0
            mpLbFillAttr->show();
362
0
            mpToolBoxColor->hide();
363
0
            mxFillControl->Resize();
364
0
            break;
365
0
        }
366
0
        case drawing::FillStyle_SOLID:
367
0
        {
368
0
            if(mpColorItem)
369
0
            {
370
0
                mpLbFillAttr->hide();
371
0
                mpToolBoxColor->show();
372
0
                mxFillControl->Resize();
373
0
            }
374
0
            break;
375
0
        }
376
0
        case drawing::FillStyle_GRADIENT:
377
0
        {
378
0
            mpLbFillAttr->show();
379
0
            mpToolBoxColor->hide();
380
0
            mxFillControl->Resize();
381
382
0
            if(pSh && pSh->GetItem(SID_GRADIENT_LIST))
383
0
            {
384
0
                mpLbFillAttr->set_sensitive(true);
385
0
                mpLbFillAttr->clear();
386
0
                SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
387
388
0
                if(mpFillGradientItem)
389
0
                {
390
0
                    const OUString aString(mpFillGradientItem->GetName());
391
392
0
                    mpLbFillAttr->set_active_text(aString);
393
394
                    // Check if the entry is not in the list
395
0
                    if (mpLbFillAttr->get_active_text() != aString)
396
0
                    {
397
0
                        sal_Int32 nCount = mpLbFillAttr->get_count();
398
0
                        OUString aTmpStr;
399
0
                        if( nCount > 0 )
400
0
                        {
401
                            // Last entry gets tested against temporary entry
402
0
                            aTmpStr = mpLbFillAttr->get_text( nCount - 1 );
403
0
                            if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
404
0
                                aTmpStr.endsWith(TMP_STR_END) )
405
0
                            {
406
0
                                mpLbFillAttr->remove(nCount - 1);
407
0
                            }
408
0
                        }
409
0
                        aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
410
411
0
                        rtl::Reference<XGradientList> xGradientList = new XGradientList( u""_ustr, u""_ustr/*TODO?*/ );
412
0
                        xGradientList->Insert(std::make_unique<XGradientEntry>(mpFillGradientItem->GetGradientValue(), aTmpStr));
413
0
                        xGradientList->SetDirty( false );
414
0
                        const Bitmap aBmp = xGradientList->GetUiBitmap( 0 );
415
416
0
                        if (!aBmp.IsEmpty())
417
0
                        {
418
0
                            ScopedVclPtrInstance< VirtualDevice > pVD;
419
0
                            const Size aBmpSize(aBmp.GetSizePixel());
420
0
                            pVD->SetOutputSizePixel(aBmpSize, false);
421
0
                            pVD->DrawBitmap(Point(), aBmp);
422
0
                            mpLbFillAttr->append(u""_ustr, xGradientList->Get(0)->GetName(), *pVD);
423
0
                            mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1);
424
0
                        }
425
0
                    }
426
427
0
                }
428
0
                else
429
0
                {
430
0
                    mpLbFillAttr->set_active(-1);
431
0
                }
432
0
            }
433
0
            else
434
0
            {
435
0
                mpLbFillAttr->set_active(-1);
436
0
            }
437
0
            break;
438
0
        }
439
0
        case drawing::FillStyle_HATCH:
440
0
        {
441
0
            mpLbFillAttr->show();
442
0
            mpToolBoxColor->hide();
443
0
            mxFillControl->Resize();
444
445
0
            if(pSh && pSh->GetItem(SID_HATCH_LIST))
446
0
            {
447
0
                mpLbFillAttr->set_sensitive(true);
448
0
                mpLbFillAttr->clear();
449
0
                SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
450
451
0
                if(mpHatchItem)
452
0
                {
453
0
                    const OUString aString(mpHatchItem->GetName());
454
455
0
                    mpLbFillAttr->set_active_text( aString );
456
457
                    // Check if the entry is not in the list
458
0
                    if( mpLbFillAttr->get_active_text() != aString )
459
0
                    {
460
0
                        const sal_Int32 nCount = mpLbFillAttr->get_count();
461
0
                        OUString aTmpStr;
462
0
                        if( nCount > 0 )
463
0
                        {
464
                            // Last entry gets tested against temporary entry
465
0
                            aTmpStr = mpLbFillAttr->get_text( nCount - 1 );
466
0
                            if(  aTmpStr.startsWith(TMP_STR_BEGIN) &&
467
0
                                 aTmpStr.endsWith(TMP_STR_END) )
468
0
                            {
469
0
                                mpLbFillAttr->remove( nCount - 1 );
470
0
                            }
471
0
                        }
472
0
                        aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
473
474
0
                        rtl::Reference<XHatchList> xHatchList = new XHatchList( u""_ustr, u""_ustr/*TODO?*/ );
475
0
                        xHatchList->Insert(std::make_unique<XHatchEntry>(mpHatchItem->GetHatchValue(), aTmpStr));
476
0
                        xHatchList->SetDirty( false );
477
0
                        const Bitmap aBmp = xHatchList->GetUiBitmap( 0 );
478
479
0
                        if( !aBmp.IsEmpty() )
480
0
                        {
481
0
                            ScopedVclPtrInstance< VirtualDevice > pVD;
482
0
                            const Size aBmpSize(aBmp.GetSizePixel());
483
0
                            pVD->SetOutputSizePixel(aBmpSize, false);
484
0
                            pVD->DrawBitmap(Point(), aBmp);
485
0
                            mpLbFillAttr->append(u""_ustr, xHatchList->GetHatch(0)->GetName(), *pVD);
486
0
                            mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1);
487
0
                        }
488
0
                    }
489
0
                }
490
0
                else
491
0
                {
492
0
                    mpLbFillAttr->set_active(-1);
493
0
                }
494
0
            }
495
0
            else
496
0
            {
497
0
                mpLbFillAttr->set_active(-1);
498
0
            }
499
0
            break;
500
0
        }
501
0
        case drawing::FillStyle_BITMAP:
502
0
        {
503
0
            mpLbFillAttr->show();
504
0
            mpToolBoxColor->hide();
505
0
            mxFillControl->Resize();
506
507
0
            if(pSh)
508
0
            {
509
0
                mpLbFillAttr->set_sensitive(true);
510
0
                mpLbFillAttr->clear();
511
512
0
                if(mpBitmapItem && !mpBitmapItem->isPattern() && pSh->GetItem(SID_BITMAP_LIST))
513
0
                {
514
0
                    SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
515
516
0
                    const OUString aString(mpBitmapItem->GetName());
517
518
0
                    mpLbFillAttr->set_active_text(aString);
519
520
                    // Check if the entry is not in the list
521
0
                    if (mpLbFillAttr->get_active_text() != aString)
522
0
                    {
523
0
                        sal_Int32 nCount = mpLbFillAttr->get_count();
524
0
                        OUString aTmpStr;
525
0
                        if( nCount > 0 )
526
0
                        {
527
                            // Last entry gets tested against temporary entry
528
0
                            aTmpStr = mpLbFillAttr->get_text(nCount - 1);
529
0
                            if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
530
0
                                aTmpStr.endsWith(TMP_STR_END) )
531
0
                            {
532
0
                                mpLbFillAttr->remove(nCount - 1);
533
0
                            }
534
0
                        }
535
0
                        aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
536
537
0
                        XBitmapListRef xBitmapList =
538
0
                            XPropertyList::AsBitmapList(
539
0
                                XPropertyList::CreatePropertyList(
540
0
                                    XPropertyListType::Bitmap, u"TmpList"_ustr, u""_ustr/*TODO?*/));
541
0
                        xBitmapList->Insert(std::make_unique<XBitmapEntry>(mpBitmapItem->GetGraphicObject(), aTmpStr));
542
0
                        xBitmapList->SetDirty( false );
543
0
                        SvxFillAttrBox::Fill(*mpLbFillAttr, xBitmapList);
544
0
                        mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1);
545
0
                    }
546
547
0
                }
548
0
                else if (mpBitmapItem && mpBitmapItem->isPattern() && pSh->GetItem(SID_PATTERN_LIST))
549
0
                {
550
0
                    mnLastXFS = sal::static_int_cast<sal_Int32>(PATTERN);
551
0
                    mpLbFillType->set_active(mnLastXFS);
552
553
0
                    SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
554
0
                    const OUString aString(mpBitmapItem->GetName());
555
556
0
                    mpLbFillAttr->set_active_text(aString);
557
0
                }
558
0
                else
559
0
                {
560
0
                    mpLbFillAttr->set_active(-1);
561
0
                }
562
0
            }
563
0
            else
564
0
            {
565
0
                mpLbFillAttr->set_active(-1);
566
0
            }
567
0
            break;
568
0
        }
569
0
        default:
570
0
            OSL_ENSURE(false, "Non supported FillType (!)");
571
0
        break;
572
0
    }
573
574
0
}
575
576
VclPtr<InterimItemWindow> SvxFillToolBoxControl::CreateItemWindow(vcl::Window *pParent)
577
0
{
578
0
    if(GetSlotId() == SID_ATTR_FILL_STYLE)
579
0
    {
580
0
        mxFillControl.reset(VclPtr<FillControl>::Create(pParent, m_xFrame));
581
582
0
        mpLbFillType = mxFillControl->mxLbFillType.get();
583
0
        mpLbFillAttr = mxFillControl->mxLbFillAttr.get();
584
0
        mpToolBoxColor = mxFillControl->mxToolBoxColor.get();
585
586
0
        mpLbFillType->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillTypeHdl));
587
0
        mpLbFillAttr->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillAttrHdl));
588
589
590
0
        return mxFillControl;
591
0
    }
592
0
    return VclPtr<InterimItemWindow>();
593
0
}
594
595
FillControl::FillControl(vcl::Window* pParent, const css::uno::Reference<css::frame::XFrame>& rFrame)
596
0
    : InterimItemWindow(pParent, u"svx/ui/fillctrlbox.ui"_ustr, u"FillCtrlBox"_ustr)
597
0
    , mxLbFillType(m_xBuilder->weld_combo_box(u"type"_ustr))
598
0
    , mxToolBoxColor(m_xBuilder->weld_toolbar(u"color"_ustr))
599
0
    , mxColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxColor, *m_xBuilder, rFrame))
600
0
    , mxLbFillAttr(m_xBuilder->weld_combo_box(u"attr"_ustr))
601
0
    , mnTypeCurPos(0)
602
0
    , mnAttrCurPos(0)
603
0
{
604
0
    InitControlBase(mxLbFillType.get());
605
606
0
    mxLbFillAttr->connect_key_press(LINK(this, FillControl, AttrKeyInputHdl));
607
0
    mxLbFillType->connect_key_press(LINK(this, FillControl, TypeKeyInputHdl));
608
0
    mxToolBoxColor->connect_key_press(LINK(this, FillControl, ColorKeyInputHdl));
609
610
0
    mxLbFillType->connect_focus_in(LINK(this, FillControl, TypeFocusHdl));
611
0
    mxLbFillAttr->connect_focus_in(LINK(this, FillControl, AttrFocusHdl));
612
613
0
    SvxFillTypeBox::Fill(*mxLbFillType);
614
615
0
    SetOptimalSize();
616
0
}
Unexecuted instantiation: FillControl::FillControl(vcl::Window*, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&)
Unexecuted instantiation: FillControl::FillControl(vcl::Window*, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&)
617
618
void FillControl::ReleaseFocus_Impl()
619
0
{
620
0
    SfxViewShell* pCurSh = SfxViewShell::Current();
621
0
    if (pCurSh)
622
0
    {
623
0
        vcl::Window* pShellWnd = pCurSh->GetWindow();
624
0
        if (pShellWnd)
625
0
            pShellWnd->GrabFocus();
626
0
    }
627
0
}
628
629
IMPL_LINK(FillControl, TypeKeyInputHdl, const KeyEvent&, rKEvt, bool)
630
0
{
631
0
    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
632
0
    sal_uInt16 nCode = rKeyCode.GetCode();
633
634
0
    if (nCode == KEY_ESCAPE)
635
0
    {
636
0
        mxLbFillType->set_active(mnTypeCurPos);
637
0
        ReleaseFocus_Impl();
638
0
        return true;
639
0
    }
640
641
0
    if (nCode != KEY_TAB)
642
0
        return false;
643
0
    if (rKeyCode.IsShift())
644
0
        return ChildKeyInput(rKEvt);
645
0
    if (mxLbFillAttr->get_visible() && !mxLbFillAttr->get_sensitive())
646
0
        return ChildKeyInput(rKEvt);
647
0
    return false;
648
0
}
649
650
IMPL_LINK_NOARG(FillControl, TypeFocusHdl, weld::Widget&, void)
651
0
{
652
0
    mnTypeCurPos = mxLbFillType->get_active();
653
0
}
654
655
IMPL_LINK_NOARG(FillControl, AttrFocusHdl, weld::Widget&, void)
656
0
{
657
0
    mnAttrCurPos = mxLbFillAttr->get_active();
658
0
}
659
660
IMPL_LINK(FillControl, AttrKeyInputHdl, const KeyEvent&, rKEvt, bool)
661
0
{
662
0
    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
663
0
    sal_uInt16 nCode = rKeyCode.GetCode();
664
665
0
    if (nCode == KEY_ESCAPE)
666
0
    {
667
0
        mxLbFillAttr->set_active(mnAttrCurPos);
668
0
        ReleaseFocus_Impl();
669
0
        return true;
670
0
    }
671
672
0
    return ChildKeyInput(rKEvt);
673
0
}
674
675
IMPL_LINK(FillControl, ColorKeyInputHdl, const KeyEvent&, rKEvt, bool)
676
0
{
677
0
    return ChildKeyInput(rKEvt);
678
0
}
679
680
FillControl::~FillControl()
681
0
{
682
0
    disposeOnce();
683
0
}
684
685
void FillControl::dispose()
686
0
{
687
0
    mxLbFillAttr.reset();
688
0
    mxColorDispatch.reset();
689
0
    mxToolBoxColor.reset();
690
0
    mxLbFillType.reset();
691
0
    InterimItemWindow::dispose();
692
0
}
693
694
IMPL_LINK_NOARG(SvxFillToolBoxControl, SelectFillTypeHdl, weld::ComboBox&, void)
695
0
{
696
0
    sal_Int32 nXFS = mpLbFillType->get_active();
697
698
0
    if(mnLastXFS == nXFS)
699
0
        return;
700
701
0
    eFillStyle eXFS = static_cast<eFillStyle>(nXFS);
702
0
    mpLbFillAttr->clear();
703
0
    SfxObjectShell* pSh = SfxObjectShell::Current();
704
0
    const XFillStyleItem aXFillStyleItem(toCssFillStyle(eXFS));
705
706
    // #i122676# Do no longer trigger two Execute calls, one for SID_ATTR_FILL_STYLE
707
    // and one for setting the fill attribute itself, but add two SfxPoolItems to the
708
    // call to get just one action at the SdrObject and to create only one Undo action, too.
709
    // Checked that this works in all apps.
710
0
    switch( eXFS )
711
0
    {
712
0
        default:
713
0
        case NONE:
714
0
        {
715
0
            mpLbFillAttr->show();
716
0
            mpToolBoxColor->hide();
717
0
            mpLbFillAttr->set_sensitive(false);
718
0
            if (pSh)
719
0
            {
720
                // #i122676# need to call a single SID_ATTR_FILL_STYLE change
721
0
                pSh->GetDispatcher()->ExecuteList(
722
0
                    SID_ATTR_FILL_STYLE, SfxCallMode::RECORD,
723
0
                    { &aXFillStyleItem });
724
0
            }
725
0
            break;
726
0
        }
727
0
        case SOLID:
728
0
        {
729
0
            mpLbFillAttr->hide();
730
0
            mpToolBoxColor->show();
731
0
            if (pSh)
732
0
            {
733
0
                const ::Color aColor = mpColorItem ? mpColorItem->GetColorValue() : COL_AUTO;
734
0
                const XFillColorItem aXFillColorItem( u""_ustr, aColor );
735
736
                // #i122676# change FillStyle and Color in one call
737
0
                pSh->GetDispatcher()->ExecuteList(
738
0
                    SID_ATTR_FILL_COLOR, SfxCallMode::RECORD,
739
0
                    { &aXFillColorItem, &aXFillStyleItem });
740
0
            }
741
0
            break;
742
0
        }
743
0
        case GRADIENT:
744
0
        {
745
0
            mpLbFillAttr->show();
746
0
            mpToolBoxColor->hide();
747
748
0
            if(pSh && pSh->GetItem(SID_GRADIENT_LIST))
749
0
            {
750
0
                if(!mpLbFillAttr->get_count())
751
0
                {
752
0
                    mpLbFillAttr->set_sensitive(true);
753
0
                    mpLbFillAttr->clear();
754
0
                    SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
755
0
                }
756
757
0
                if (mnLastPosGradient != -1)
758
0
                {
759
0
                    const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST);
760
761
0
                    if(mnLastPosGradient < pItem->GetGradientList()->Count())
762
0
                    {
763
0
                        const basegfx::BGradient aGradient = pItem->GetGradientList()->GetGradient(mnLastPosGradient)->GetGradient();
764
0
                        const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_text(mnLastPosGradient), aGradient);
765
766
                        // #i122676# change FillStyle and Gradient in one call
767
0
                        pSh->GetDispatcher()->ExecuteList(
768
0
                            SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD,
769
0
                            { &aXFillGradientItem, &aXFillStyleItem });
770
0
                        mpLbFillAttr->set_active(mnLastPosGradient);
771
0
                    }
772
0
                }
773
0
            }
774
0
            else
775
0
            {
776
0
                mpLbFillAttr->set_sensitive(false);
777
0
            }
778
0
            break;
779
0
        }
780
0
        case HATCH:
781
0
        {
782
0
            mpLbFillAttr->show();
783
0
            mpToolBoxColor->hide();
784
785
0
            if(pSh && pSh->GetItem(SID_HATCH_LIST))
786
0
            {
787
0
                if(!mpLbFillAttr->get_count())
788
0
                {
789
0
                    mpLbFillAttr->set_sensitive(true);
790
0
                    mpLbFillAttr->clear();
791
0
                    SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
792
0
                }
793
794
0
                if (mnLastPosHatch != -1)
795
0
                {
796
0
                    const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST);
797
798
0
                    if(mnLastPosHatch < pItem->GetHatchList()->Count())
799
0
                    {
800
0
                        const XHatch aHatch = pItem->GetHatchList()->GetHatch(mnLastPosHatch)->GetHatch();
801
0
                        const XFillHatchItem aXFillHatchItem(mpLbFillAttr->get_active_text(), aHatch);
802
803
                        // #i122676# change FillStyle and Hatch in one call
804
0
                        pSh->GetDispatcher()->ExecuteList(
805
0
                            SID_ATTR_FILL_HATCH, SfxCallMode::RECORD,
806
0
                            { &aXFillHatchItem, &aXFillStyleItem });
807
0
                        mpLbFillAttr->set_active(mnLastPosHatch);
808
0
                    }
809
0
                }
810
0
            }
811
0
            else
812
0
            {
813
0
                mpLbFillAttr->set_sensitive(false);
814
0
            }
815
0
            break;
816
0
        }
817
0
        case BITMAP:
818
0
        {
819
0
            mpLbFillAttr->show();
820
0
            mpToolBoxColor->hide();
821
822
0
            if(pSh && pSh->GetItem(SID_BITMAP_LIST))
823
0
            {
824
0
                if(!mpLbFillAttr->get_count())
825
0
                {
826
0
                    mpLbFillAttr->set_sensitive(true);
827
0
                    mpLbFillAttr->clear();
828
0
                    SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
829
0
                }
830
831
0
                if (mnLastPosBitmap != -1)
832
0
                {
833
0
                    const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST);
834
835
0
                    if(mnLastPosBitmap < pItem->GetBitmapList()->Count())
836
0
                    {
837
0
                        const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(mnLastPosBitmap);
838
0
                        const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
839
840
                        // #i122676# change FillStyle and Bitmap in one call
841
0
                        pSh->GetDispatcher()->ExecuteList(
842
0
                            SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
843
0
                            { &aXFillBitmapItem, &aXFillStyleItem });
844
0
                        mpLbFillAttr->set_active(mnLastPosBitmap);
845
0
                    }
846
0
                }
847
0
            }
848
0
            else
849
0
            {
850
0
                mpLbFillAttr->set_sensitive(false);
851
0
            }
852
0
            break;
853
0
        }
854
0
        case PATTERN:
855
0
        {
856
0
            mpLbFillAttr->show();
857
0
            mpToolBoxColor->hide();
858
859
0
            if(pSh && pSh->GetItem(SID_PATTERN_LIST))
860
0
            {
861
0
                if(!mpLbFillAttr->get_count())
862
0
                {
863
0
                    mpLbFillAttr->set_sensitive(true);
864
0
                    mpLbFillAttr->clear();
865
0
                    SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
866
0
                }
867
868
0
                if (mnLastPosPattern != -1)
869
0
                {
870
0
                    const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST);
871
872
0
                    if(mnLastPosPattern < pItem->GetPatternList()->Count())
873
0
                    {
874
0
                        const XBitmapEntry* pXBitmapEntry = pItem->GetPatternList()->GetBitmap(mnLastPosPattern);
875
0
                        const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
876
877
                        // #i122676# change FillStyle and Bitmap in one call
878
0
                        pSh->GetDispatcher()->ExecuteList(
879
0
                            SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
880
0
                            { &aXFillBitmapItem, &aXFillStyleItem });
881
0
                        mpLbFillAttr->set_active(mnLastPosPattern);
882
0
                    }
883
0
                }
884
0
            }
885
0
            else
886
0
            {
887
0
                mpLbFillAttr->set_sensitive(false);
888
0
            }
889
0
            break;
890
0
        }
891
892
0
    }
893
894
0
    mnLastXFS = nXFS;
895
896
0
    mxFillControl->Resize();
897
0
}
898
899
IMPL_LINK_NOARG(SvxFillToolBoxControl, SelectFillAttrHdl, weld::ComboBox&, void)
900
0
{
901
0
    sal_Int32 nXFS = mpLbFillType->get_active();
902
0
    eFillStyle eXFS = static_cast<eFillStyle>(nXFS);
903
904
0
    const XFillStyleItem aXFillStyleItem(toCssFillStyle(eXFS));
905
0
    SfxObjectShell* pSh = SfxObjectShell::Current();
906
907
    // #i122676# dependent from bFillStyleChange, do execute a single or two
908
    // changes in one Execute call
909
0
    const bool bFillStyleChange(mnLastXFS != nXFS);
910
911
0
    switch (eXFS)
912
0
    {
913
0
        case SOLID:
914
0
        {
915
0
            if (bFillStyleChange && pSh)
916
0
            {
917
                // #i122676# Single FillStyle change call needed here
918
0
                pSh->GetDispatcher()->ExecuteList(
919
0
                    SID_ATTR_FILL_STYLE, SfxCallMode::RECORD,
920
0
                    { &aXFillStyleItem });
921
0
            }
922
0
            break;
923
0
        }
924
0
        case GRADIENT:
925
0
        {
926
0
            sal_Int32 nPos = mpLbFillAttr->get_active();
927
928
0
            if (nPos == -1)
929
0
            {
930
0
                nPos = mnLastPosGradient;
931
0
            }
932
933
0
            if (nPos != -1 && pSh && pSh->GetItem(SID_GRADIENT_LIST))
934
0
            {
935
0
                const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST);
936
937
0
                if(nPos < pItem->GetGradientList()->Count())
938
0
                {
939
0
                    const basegfx::BGradient aGradient = pItem->GetGradientList()->GetGradient(nPos)->GetGradient();
940
0
                    const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_active_text(), aGradient);
941
942
                    // #i122676# Change FillStyle and Gradient in one call
943
0
                    pSh->GetDispatcher()->ExecuteList(
944
0
                        SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD,
945
0
                        bFillStyleChange
946
0
                            ? std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem, &aXFillStyleItem }
947
0
                            : std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem });
948
0
                }
949
0
            }
950
951
0
            if (nPos != -1)
952
0
            {
953
0
                mnLastPosGradient = nPos;
954
0
            }
955
0
            break;
956
0
        }
957
0
        case HATCH:
958
0
        {
959
0
            sal_Int32 nPos = mpLbFillAttr->get_active();
960
961
0
            if (nPos == -1)
962
0
            {
963
0
                nPos = mnLastPosHatch;
964
0
            }
965
966
0
            if (nPos != -1 && pSh && pSh->GetItem(SID_HATCH_LIST))
967
0
            {
968
0
                const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST);
969
970
0
                if(nPos < pItem->GetHatchList()->Count())
971
0
                {
972
0
                    const XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch();
973
0
                    const XFillHatchItem aXFillHatchItem( mpLbFillAttr->get_active_text(), aHatch);
974
975
                    // #i122676# Change FillStyle and Hatch in one call
976
0
                    pSh->GetDispatcher()->ExecuteList(
977
0
                        SID_ATTR_FILL_HATCH, SfxCallMode::RECORD,
978
0
                        bFillStyleChange
979
0
                            ? std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem, &aXFillStyleItem }
980
0
                            : std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem });
981
0
                }
982
0
            }
983
984
0
            if (nPos != -1)
985
0
            {
986
0
                mnLastPosHatch = nPos;
987
0
            }
988
0
            break;
989
0
        }
990
0
        case BITMAP:
991
0
        {
992
0
            sal_Int32 nPos = mpLbFillAttr->get_active();
993
994
0
            if (nPos == -1)
995
0
            {
996
0
                nPos = mnLastPosBitmap;
997
0
            }
998
999
0
            if (nPos != -1 && pSh && pSh->GetItem(SID_BITMAP_LIST))
1000
0
            {
1001
0
                const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST);
1002
1003
0
                if(nPos < pItem->GetBitmapList()->Count())
1004
0
                {
1005
0
                    const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos);
1006
0
                    const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
1007
1008
                    // #i122676# Change FillStyle and Bitmap in one call
1009
0
                    pSh->GetDispatcher()->ExecuteList(
1010
0
                        SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
1011
0
                        bFillStyleChange
1012
0
                            ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem }
1013
0
                            : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem });
1014
0
                }
1015
0
            }
1016
1017
0
            if (nPos != -1)
1018
0
            {
1019
0
                mnLastPosBitmap = nPos;
1020
0
            }
1021
0
            break;
1022
0
        }
1023
0
        case PATTERN:
1024
0
        {
1025
0
            sal_Int32 nPos = mpLbFillAttr->get_active();
1026
1027
0
            if (nPos == -1)
1028
0
            {
1029
0
                nPos = mnLastPosPattern;
1030
0
            }
1031
1032
0
            if (nPos != -1 && pSh && pSh->GetItem(SID_PATTERN_LIST))
1033
0
            {
1034
0
                const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST);
1035
1036
0
                if(nPos < pItem->GetPatternList()->Count())
1037
0
                {
1038
0
                    const XBitmapEntry* pXBitmapEntry = pItem->GetPatternList()->GetBitmap(nPos);
1039
0
                    const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
1040
1041
                    // #i122676# Change FillStyle and Bitmap in one call
1042
0
                    pSh->GetDispatcher()->ExecuteList(
1043
0
                        SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
1044
0
                        bFillStyleChange
1045
0
                            ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem }
1046
0
                            : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem });
1047
0
                }
1048
0
            }
1049
1050
0
            if (nPos != -1)
1051
0
            {
1052
0
                mnLastPosPattern = nPos;
1053
0
            }
1054
0
            break;
1055
0
        }
1056
1057
0
        default: break;
1058
0
    }
1059
0
}
1060
1061
void FillControl::SetOptimalSize()
1062
0
{
1063
0
    Size aSize(mxLbFillType->get_preferred_size());
1064
0
    Size aFirstSize(mxToolBoxColor->get_preferred_size());
1065
0
    auto nWidth = std::max(aFirstSize.Width(), LogicToPixel(Size(55, 0), MapMode(MapUnit::MapAppFont)).Width());
1066
0
    auto nHeight = std::max(aSize.Height(), aFirstSize.Height());
1067
0
    mxToolBoxColor->set_size_request(nWidth, -1);
1068
0
    mxLbFillAttr->set_size_request(42, -1); //something narrow so the toolbar sets the overall size of this column
1069
0
    SetSizePixel(Size(m_xContainer->get_preferred_size().Width(), nHeight));
1070
0
}
1071
1072
void FillControl::DataChanged(const DataChangedEvent& rDCEvt)
1073
0
{
1074
0
    if((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1075
0
        (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1076
0
    {
1077
0
        SetOptimalSize();
1078
0
    }
1079
0
    InterimItemWindow::DataChanged(rDCEvt);
1080
0
}
1081
1082
void FillControl::GetFocus()
1083
0
{
1084
    // tdf#148047 if the dropdown is active then leave the focus
1085
    // there and don't grab back to a different widget
1086
0
    if (mxToolBoxColor->get_menu_item_active(u".uno:FillColor"_ustr))
1087
0
        return;
1088
0
    InterimItemWindow::GetFocus();
1089
0
}
1090
1091
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */