Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/window/toolbox2.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 <sal/config.h>
21
#include <utility>
22
#include <vcl/uitest/logger.hxx>
23
#include <sal/log.hxx>
24
25
#include <comphelper/base64.hxx>
26
#include <comphelper/processfactory.hxx>
27
#include <boost/property_tree/ptree.hpp>
28
29
#include <vcl/cvtgrf.hxx>
30
#include <vcl/svapp.hxx>
31
#include <vcl/idle.hxx>
32
#include <vcl/bitmap.hxx>
33
#include <vcl/toolkit/floatwin.hxx>
34
#include <vcl/toolbox.hxx>
35
#include <vcl/mnemonic.hxx>
36
#include <vcl/menu.hxx>
37
#include <vcl/settings.hxx>
38
#include <vcl/IconThemeInfo.hxx>
39
#include <vcl/commandinfoprovider.hxx>
40
41
#include <accessibility/vclxaccessibletoolbox.hxx>
42
#include <svdata.hxx>
43
#include <uitest/toolboxuiobject.hxx>
44
#include <brdwin.hxx>
45
#include <toolbox.h>
46
47
#include <unotools/confignode.hxx>
48
#include <tools/json_writer.hxx>
49
50
#include <vcl/uitest/uiobject.hxx>
51
52
#include "impldockingwrapper.hxx"
53
54
using namespace vcl;
55
56
0
#define TB_SEP_SIZE     8  // Separator size
57
58
59
ImplToolBoxPrivateData::ImplToolBoxPrivateData()
60
0
{
61
0
    meButtonSize = ToolBoxButtonSize::DontCare;
62
0
    mpMenu = VclPtr<PopupMenu>::Create();
63
64
0
    maMenuType = ToolBoxMenuType::NONE;
65
0
    maMenubuttonItem.maItemSize = Size( TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET, TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET );
66
0
    maMenubuttonItem.meState = TRISTATE_FALSE;
67
0
    mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
68
69
0
    mbIsLocked = false;
70
0
    mbNativeButtons = false;
71
0
    mbIsPaintLocked = false;
72
0
    mbAssumeDocked = false;
73
0
    mbAssumePopupMode = false;
74
0
    mbAssumeFloating = false;
75
0
    mbKeyInputDisabled = false;
76
0
    mbMenubuttonSelected = false;
77
0
    mbMenubuttonWasLastSelected = false;
78
0
    mbWillUsePopupMode = false;
79
0
    mbDropDownByKeyboard = false;
80
0
}
81
82
ImplToolBoxPrivateData::~ImplToolBoxPrivateData()
83
0
{
84
0
    m_pLayoutData.reset();
85
0
    mpMenu.disposeAndClear();
86
0
}
87
88
void ImplToolItem::init(ToolBoxItemId nItemId, ToolBoxItemBits nItemBits,
89
                        bool bEmptyBtn)
90
0
{
91
0
    mnId            = nItemId;
92
0
    mpWindow        = nullptr;
93
0
    mbNonInteractiveWindow = false;
94
0
    mpUserData      = nullptr;
95
0
    meType          = ToolBoxItemType::BUTTON;
96
0
    mnBits          = nItemBits;
97
0
    meState         = TRISTATE_FALSE;
98
0
    mbEnabled       = true;
99
0
    mbVisible       = true;
100
0
    mbEmptyBtn      = bEmptyBtn;
101
0
    mbShowWindow    = false;
102
0
    mbBreak         = false;
103
0
    mnSepSize       = TB_SEP_SIZE;
104
0
    mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
105
0
    mnImageAngle    = 0_deg10;
106
0
    mbMirrorMode    = false;
107
0
    mbVisibleText   = false;
108
0
    mbExpand        = false;
109
0
}
110
111
ImplToolItem::ImplToolItem()
112
0
{
113
0
    init(ToolBoxItemId(0), ToolBoxItemBits::NONE, true);
114
0
}
115
116
ImplToolItem::ImplToolItem( ToolBoxItemId nItemId, Image aImage,
117
                            ToolBoxItemBits nItemBits ) :
118
0
    maImage(std::move( aImage ))
119
0
{
120
0
    init(nItemId, nItemBits, false);
121
0
}
122
123
ImplToolItem::ImplToolItem( ToolBoxItemId nItemId, OUString aText,
124
                            OUString aCommand, ToolBoxItemBits nItemBits ) :
125
0
    maText(std::move( aText )),
126
0
    maCommandStr(std::move( aCommand ))
127
0
{
128
0
    init(nItemId, nItemBits, false);
129
0
}
130
131
ImplToolItem::ImplToolItem( ToolBoxItemId nItemId, Image aImage,
132
                            OUString aText, ToolBoxItemBits nItemBits ) :
133
0
    maImage(std::move( aImage )),
134
0
    maText(std::move( aText ))
135
0
{
136
0
    init(nItemId, nItemBits, false);
137
0
}
138
139
Size ImplToolItem::GetSize( bool bHorz, bool bCheckMaxWidth, tools::Long maxWidth, const Size& rDefaultSize )
140
0
{
141
0
    Size aSize( rDefaultSize ); // the size of 'standard' toolbox items
142
                                // non-standard items are eg windows or buttons with text
143
144
0
    if ( (meType == ToolBoxItemType::BUTTON) || (meType == ToolBoxItemType::SPACE) )
145
0
    {
146
0
        aSize = maItemSize;
147
148
0
        if ( mpWindow && bHorz )
149
0
        {
150
            // get size of item window and check if it fits
151
            // no windows in vertical toolbars (the default is mbShowWindow=false)
152
0
            Size aWinSize = mpWindow->GetSizePixel();
153
154
0
            if (mpWindow->GetStyle() & WB_NOLABEL)
155
                // Window wants no label? Then don't check width, it'll be just
156
                // clipped.
157
0
                bCheckMaxWidth = false;
158
159
0
            if ( !bCheckMaxWidth || (aWinSize.Width() <= maxWidth) )
160
0
            {
161
0
                aSize.setWidth( aWinSize.Width() );
162
0
                aSize.setHeight( aWinSize.Height() );
163
0
                mbShowWindow = true;
164
0
            }
165
0
            else
166
0
            {
167
0
                if ( mbEmptyBtn )
168
0
                {
169
0
                    aSize.setWidth( 0 );
170
0
                    aSize.setHeight( 0 );
171
0
                }
172
0
            }
173
0
        }
174
0
    }
175
0
    else if ( meType == ToolBoxItemType::SEPARATOR )
176
0
    {
177
0
        if ( bHorz )
178
0
        {
179
0
            aSize.setWidth( mnSepSize );
180
0
            aSize.setHeight( rDefaultSize.Height() );
181
0
        }
182
0
        else
183
0
        {
184
0
            aSize.setWidth( rDefaultSize.Width() );
185
0
            aSize.setHeight( mnSepSize );
186
0
        }
187
0
    }
188
0
    else if ( meType == ToolBoxItemType::BREAK )
189
0
    {
190
0
        aSize.setWidth( 0 );
191
0
        aSize.setHeight( 0 );
192
0
    }
193
194
0
    return aSize;
195
0
}
196
197
void ImplToolItem::DetermineButtonDrawStyle( ButtonType eButtonType, bool& rbImage, bool& rbText ) const
198
0
{
199
0
    if ( meType != ToolBoxItemType::BUTTON )
200
0
    {
201
        // no button -> draw nothing
202
0
        rbImage = rbText = false;
203
0
        return;
204
0
    }
205
206
0
    bool bHasImage;
207
0
    bool bHasText;
208
209
    // check for image and/or text
210
0
    bHasImage = !!maImage;
211
0
    bHasText = !maText.isEmpty();
212
213
    // prefer images if symbolonly buttons are drawn
214
    // prefer texts if textonly buttons are drawn
215
216
0
    if ( eButtonType == ButtonType::SYMBOLONLY )         // drawing icons only
217
0
    {
218
0
        if( bHasImage || !bHasText )
219
0
        {
220
0
            rbImage = true;
221
0
            rbText  = false;
222
0
        }
223
0
        else
224
0
        {
225
0
            rbImage = false;
226
0
            rbText  = true;
227
0
        }
228
0
    }
229
0
    else if ( eButtonType == ButtonType::TEXT )      // drawing text only
230
0
    {
231
0
        if( bHasText || !bHasImage )
232
0
        {
233
0
            rbImage = false;
234
0
            rbText  = true;
235
0
        }
236
0
        else
237
0
        {
238
0
            rbImage = true;
239
0
            rbText  = false;
240
0
        }
241
0
    }
242
0
    else                                        // drawing icons and text both
243
0
    {
244
0
        rbImage = true;
245
0
        rbText  = true;
246
0
    }
247
0
}
248
249
tools::Rectangle ImplToolItem::GetDropDownRect( bool bHorz ) const
250
0
{
251
0
    tools::Rectangle aRect;
252
0
    if( (mnBits & ToolBoxItemBits::DROPDOWN) && !maRect.IsEmpty() )
253
0
    {
254
0
        aRect = maRect;
255
0
        if( mbVisibleText && !bHorz )
256
            // item will be rotated -> place dropdown to the bottom
257
0
            aRect.SetTop( aRect.Bottom() - mnDropDownArrowWidth );
258
0
        else
259
            // place dropdown to the right
260
0
            aRect.SetLeft( aRect.Right() - mnDropDownArrowWidth );
261
0
    }
262
0
    return aRect;
263
0
}
264
265
bool ImplToolItem::IsClipped() const
266
0
{
267
0
    return ( meType == ToolBoxItemType::BUTTON && mbVisible && maRect.IsEmpty() );
268
0
}
269
270
bool ImplToolItem::IsItemHidden() const
271
0
{
272
0
    return ( meType == ToolBoxItemType::BUTTON && !mbVisible );
273
0
}
274
275
void ToolBox::ImplInvalidate( bool bNewCalc, bool bFullPaint )
276
0
{
277
0
    ImplUpdateInputEnable();
278
279
0
    if ( bNewCalc )
280
0
        mbCalc = true;
281
282
0
    if ( bFullPaint )
283
0
    {
284
0
        mbFormat = true;
285
286
        // do we need to redraw?
287
0
        if ( IsReallyVisible() && IsUpdateMode() )
288
0
        {
289
0
            Invalidate( tools::Rectangle( mnLeftBorder, mnTopBorder,
290
0
                                   mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
291
0
            mpIdle->Stop();
292
0
        }
293
0
    }
294
0
    else
295
0
    {
296
0
        if ( !mbFormat )
297
0
        {
298
0
            mbFormat = true;
299
300
            // do we need to redraw?
301
0
            if ( IsReallyVisible() && IsUpdateMode() )
302
0
                mpIdle->Start();
303
0
        }
304
0
    }
305
306
    // request new layout by layoutmanager
307
0
    CallEventListeners( VclEventId::ToolboxFormatChanged );
308
0
}
309
310
void ToolBox::ImplUpdateItem( ImplToolItems::size_type nIndex )
311
0
{
312
    // do we need to redraw?
313
0
    if ( !(IsReallyVisible() && IsUpdateMode()) )
314
0
        return;
315
316
0
    if ( nIndex == ITEM_NOTFOUND )
317
0
    {
318
        // #i52217# no immediate draw as this might lead to paint problems
319
0
        Invalidate( tools::Rectangle( mnLeftBorder, mnTopBorder, mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
320
0
    }
321
0
    else
322
0
    {
323
0
        if ( !mbFormat )
324
0
        {
325
            // #i52217# no immediate draw as this might lead to paint problems
326
0
            Invalidate( mpData->m_aItems[nIndex].maRect );
327
0
        }
328
0
        else
329
0
            maPaintRect.Union( mpData->m_aItems[nIndex].maRect );
330
0
    }
331
0
}
332
333
rtl::Reference<comphelper::OAccessible> ToolBox::CreateAccessible()
334
0
{
335
0
    return new VCLXAccessibleToolBox(this);
336
0
}
337
338
void ToolBox::Click()
339
0
{
340
0
    CallEventListeners( VclEventId::ToolboxClick );
341
0
    maClickHdl.Call( this );
342
0
    UITestLogger::getInstance().logAction( this, VclEventId::ToolboxClick);
343
0
}
344
345
void ToolBox::DoubleClick()
346
0
{
347
0
    CallEventListeners( VclEventId::ToolboxDoubleClick );
348
0
    maDoubleClickHdl.Call( this );
349
0
}
350
351
void ToolBox::Activate()
352
0
{
353
0
    mnActivateCount++;
354
0
    CallEventListeners( VclEventId::ToolboxActivate );
355
0
    maActivateHdl.Call( this );
356
0
}
357
358
void ToolBox::Deactivate()
359
0
{
360
0
    mnActivateCount--;
361
0
    CallEventListeners( VclEventId::ToolboxDeactivate );
362
0
    maDeactivateHdl.Call( this );
363
0
}
364
365
void ToolBox::Highlight()
366
0
{
367
0
    CallEventListeners( VclEventId::ToolboxHighlight );
368
0
}
369
370
FactoryFunction ToolBox::GetUITestFactory() const
371
0
{
372
0
    return ToolBoxUIObject::create;
373
0
}
374
375
void ToolBox::Select()
376
0
{
377
0
    VclPtr<vcl::Window> xWindow = this;
378
379
0
    CallEventListeners( VclEventId::ToolboxSelect );
380
0
    maSelectHdl.Call( this );
381
382
0
    if ( xWindow->isDisposed() )
383
0
        return;
384
385
    // TODO: GetFloatingWindow in DockingWindow is currently inline, change it to check dockingwrapper
386
0
    ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
387
0
    if( pWrapper && pWrapper->GetFloatingWindow() && static_cast<FloatingWindow*>(pWrapper->GetFloatingWindow())->IsInPopupMode() )
388
0
        static_cast<FloatingWindow*>(pWrapper->GetFloatingWindow())->EndPopupMode();
389
0
}
390
391
void ToolBox::InsertItem( ToolBoxItemId nItemId, const Image& rImage, ToolBoxItemBits nBits, ImplToolItems::size_type nPos )
392
0
{
393
0
    SAL_WARN_IF( !nItemId, "vcl", "ToolBox::InsertItem(): ItemId == 0" );
394
0
    SAL_WARN_IF( GetItemPos( nItemId ) != ITEM_NOTFOUND, "vcl",
395
0
                "ToolBox::InsertItem(): ItemId already exists" );
396
397
    // create item and add to list
398
0
    mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(),
399
0
                             ImplToolItem( nItemId, rImage, nBits ) );
400
0
    mpData->ImplClearLayoutData();
401
402
0
    ImplInvalidate( true );
403
404
    // Notify
405
0
    ImplToolItems::size_type nNewPos = ( nPos == APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos;
406
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >(nNewPos ) );
407
0
}
408
409
void ToolBox::InsertItem( ToolBoxItemId nItemId, const Image& rImage, const OUString& rText, ToolBoxItemBits nBits,
410
                          ImplToolItems::size_type nPos )
411
0
{
412
0
    SAL_WARN_IF( !nItemId, "vcl", "ToolBox::InsertItem(): ItemId == 0" );
413
0
    SAL_WARN_IF( GetItemPos( nItemId ) != ITEM_NOTFOUND, "vcl",
414
0
                "ToolBox::InsertItem(): ItemId already exists" );
415
416
    // create item and add to list
417
0
    mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(),
418
0
                             ImplToolItem( nItemId, rImage, MnemonicGenerator::EraseAllMnemonicChars(rText), nBits ) );
419
0
    mpData->ImplClearLayoutData();
420
421
0
    ImplInvalidate( true );
422
423
    // Notify
424
0
    ImplToolItems::size_type nNewPos = ( nPos == APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos;
425
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos ) );
426
0
}
427
428
void ToolBox::InsertItem( ToolBoxItemId nItemId, const OUString& rText, const OUString& rCommand, ToolBoxItemBits nBits,
429
                          ImplToolItems::size_type nPos )
430
0
{
431
0
    SAL_WARN_IF( !nItemId, "vcl", "ToolBox::InsertItem(): ItemId == 0" );
432
0
    SAL_WARN_IF( GetItemPos( nItemId ) != ITEM_NOTFOUND, "vcl",
433
0
                "ToolBox::InsertItem(): ItemId already exists" );
434
435
    // create item and add to list
436
0
    mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(),
437
0
                             ImplToolItem( nItemId, MnemonicGenerator::EraseAllMnemonicChars(rText), rCommand, nBits ) );
438
0
    mpData->ImplClearLayoutData();
439
440
0
    ImplInvalidate( true );
441
442
    // Notify
443
0
    ImplToolItems::size_type nNewPos = ( nPos == APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos;
444
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos ) );
445
0
}
446
447
void ToolBox::InsertItem(const OUString& rCommand, const css::uno::Reference<css::frame::XFrame>& rFrame, ToolBoxItemBits nBits,
448
                         const Size& rRequestedSize, ImplToolItems::size_type nPos)
449
0
{
450
0
    OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(rFrame));
451
0
    auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(rCommand, aModuleName);
452
0
    OUString aLabel(vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
453
0
    OUString aTooltip(vcl::CommandInfoProvider::GetTooltipForCommand(rCommand, aProperties, rFrame));
454
0
    Image aImage(CommandInfoProvider::GetImageForCommand(rCommand, rFrame, GetImageSize()));
455
456
0
    ToolBoxItemId nItemId(GetItemCount() + 1);
457
        //TODO: ImplToolItems::size_type -> sal_uInt16!
458
0
    InsertItem(nItemId, aLabel, rCommand, nBits, nPos);
459
0
    SetItemImage(nItemId, aImage);
460
0
    SetQuickHelpText(nItemId, aTooltip);
461
462
    // set the minimal size
463
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
464
0
    if ( pItem )
465
0
        pItem->maMinimalItemSize = rRequestedSize;
466
0
}
467
468
void ToolBox::InsertWindow( ToolBoxItemId nItemId, vcl::Window* pWindow,
469
                            ToolBoxItemBits nBits, ImplToolItems::size_type nPos )
470
0
{
471
0
    SAL_WARN_IF( !nItemId, "vcl", "ToolBox::InsertWindow(): ItemId == 0" );
472
0
    SAL_WARN_IF( GetItemPos( nItemId ) != ITEM_NOTFOUND, "vcl",
473
0
                "ToolBox::InsertWindow(): ItemId already exists" );
474
475
    // create item and add to list
476
0
    ImplToolItem aItem;
477
0
    aItem.mnId       = nItemId;
478
0
    aItem.meType     = ToolBoxItemType::BUTTON;
479
0
    aItem.mnBits     = nBits;
480
0
    aItem.mpWindow   = pWindow;
481
0
    mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
482
0
    mpData->ImplClearLayoutData();
483
484
0
    if ( pWindow )
485
0
        pWindow->Hide();
486
487
0
    ImplInvalidate( true );
488
489
    // Notify
490
0
    ImplToolItems::size_type nNewPos = ( nPos == APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos;
491
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos ) );
492
0
}
493
494
void ToolBox::InsertSpace()
495
0
{
496
    // create item and add to list
497
0
    ImplToolItem aItem;
498
0
    aItem.meType     = ToolBoxItemType::SPACE;
499
0
    aItem.mbEnabled  = false;
500
0
    mpData->m_aItems.push_back(std::move(aItem));
501
0
    mpData->ImplClearLayoutData();
502
503
0
    ImplInvalidate();
504
505
    // Notify
506
0
    ImplToolItems::size_type nNewPos = mpData->m_aItems.size() - 1;
507
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos ) );
508
0
}
509
510
void ToolBox::InsertSeparator( ImplToolItems::size_type nPos, sal_uInt16 nPixSize )
511
0
{
512
    // create item and add to list
513
0
    ImplToolItem aItem;
514
0
    aItem.meType     = ToolBoxItemType::SEPARATOR;
515
0
    aItem.mbEnabled  = false;
516
0
    if ( nPixSize )
517
0
        aItem.mnSepSize = nPixSize;
518
0
    mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
519
0
    mpData->ImplClearLayoutData();
520
521
0
    ImplInvalidate();
522
523
    // Notify
524
0
    ImplToolItems::size_type nNewPos = ( nPos == APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos;
525
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos ) );
526
0
}
527
528
void ToolBox::InsertBreak( ImplToolItems::size_type nPos )
529
0
{
530
    // create item and add to list
531
0
    ImplToolItem aItem;
532
0
    aItem.meType     = ToolBoxItemType::BREAK;
533
0
    aItem.mbEnabled  = false;
534
0
    mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
535
0
    mpData->ImplClearLayoutData();
536
537
0
    ImplInvalidate();
538
539
    // Notify
540
0
    ImplToolItems::size_type nNewPos = ( nPos == APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos;
541
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos ) );
542
0
}
543
544
void ToolBox::RemoveItem( ImplToolItems::size_type nPos )
545
0
{
546
0
    if( nPos >= mpData->m_aItems.size() )
547
0
        return;
548
549
0
    bool bMustCalc;
550
0
    bMustCalc = mpData->m_aItems[nPos].meType == ToolBoxItemType::BUTTON;
551
552
0
    if ( mpData->m_aItems[nPos].mpWindow )
553
0
        mpData->m_aItems[nPos].mpWindow->Hide();
554
555
    // add the removed item to PaintRect
556
0
    maPaintRect.Union( mpData->m_aItems[nPos].maRect );
557
558
    // ensure not to delete in the Select-Handler
559
0
    if ( mpData->m_aItems[nPos].mnId == mnCurItemId )
560
0
        mnCurItemId = ToolBoxItemId(0);
561
0
    if ( mpData->m_aItems[nPos].mnId == mnHighItemId )
562
0
        mnHighItemId = ToolBoxItemId(0);
563
564
0
    ImplInvalidate( bMustCalc );
565
566
0
    mpData->m_aItems.erase( mpData->m_aItems.begin()+nPos );
567
0
    mpData->ImplClearLayoutData();
568
569
    // Notify
570
0
    CallEventListeners( VclEventId::ToolboxItemRemoved, reinterpret_cast< void* >( nPos ) );
571
0
}
572
573
void ToolBox::CopyItem( const ToolBox& rToolBox, ToolBoxItemId nItemId )
574
0
{
575
0
    SAL_WARN_IF( GetItemPos( nItemId ) != ITEM_NOTFOUND, "vcl",
576
0
                "ToolBox::CopyItem(): ItemId already exists" );
577
578
0
    ImplToolItems::size_type nPos = rToolBox.GetItemPos( nItemId );
579
580
    // found item
581
0
    if ( nPos == ITEM_NOTFOUND )
582
0
        return;
583
584
    // push ToolBox item onto the list
585
0
    ImplToolItem aNewItem = rToolBox.mpData->m_aItems[nPos];
586
    // reset state
587
0
    aNewItem.mpWindow      = nullptr;
588
0
    aNewItem.mbShowWindow = false;
589
590
0
    mpData->m_aItems.push_back(std::move(aNewItem));
591
0
    mpData->ImplClearLayoutData();
592
    // redraw ToolBox
593
0
    ImplInvalidate();
594
595
    // Notify
596
0
    ImplToolItems::size_type nNewPos2 = mpData->m_aItems.size() - 1;
597
0
    CallEventListeners( VclEventId::ToolboxItemAdded, reinterpret_cast< void* >( nNewPos2 ) );
598
0
}
599
600
void ToolBox::Clear()
601
0
{
602
0
    mpData->m_aItems.clear();
603
0
    mpData->ImplClearLayoutData();
604
605
    // ensure not to delete in the Select-Handler
606
0
    mnCurItemId = ToolBoxItemId(0);
607
0
    mnHighItemId = ToolBoxItemId(0);
608
609
0
    ImplInvalidate( true, true );
610
611
    // Notify
612
0
    CallEventListeners( VclEventId::ToolboxAllItemsChanged );
613
0
}
614
615
void ToolBox::SetButtonType( ButtonType eNewType )
616
0
{
617
0
    if ( meButtonType != eNewType )
618
0
    {
619
0
        meButtonType = eNewType;
620
621
        // better redraw everything, as otherwise there might be problems
622
        // with regions that were copied with CopyBits
623
0
        ImplInvalidate( true );
624
0
    }
625
0
}
626
627
void ToolBox::SetToolboxButtonSize( ToolBoxButtonSize eSize )
628
0
{
629
0
    if( mpData->meButtonSize != eSize )
630
0
    {
631
0
        mpData->meButtonSize = eSize;
632
0
        mbCalc = true;
633
0
        mbFormat = true;
634
0
    }
635
0
}
636
637
ToolBoxButtonSize ToolBox::GetToolboxButtonSize() const
638
0
{
639
0
    return mpData->meButtonSize;
640
0
}
641
642
ImageType ToolBox::GetImageSize() const
643
0
{
644
0
    ImageType eImageType = ImageType::Size16;
645
0
    if (mpData->meButtonSize == ToolBoxButtonSize::Large)
646
0
        eImageType = ImageType::Size26;
647
0
    else if (mpData->meButtonSize == ToolBoxButtonSize::Size32)
648
0
        eImageType = ImageType::Size32;
649
650
0
    return eImageType;
651
0
}
652
653
/*static*/ Size ToolBox::GetDefaultImageSize(ToolBoxButtonSize eToolBoxButtonSize)
654
0
{
655
0
    OutputDevice *pDefault = Application::GetDefaultDevice();
656
0
    float fScaleFactor = pDefault ? pDefault->GetDPIScaleFactor() : 1.0;
657
658
0
    Size aUnscaledSize(16, 16);
659
660
0
    if (eToolBoxButtonSize == ToolBoxButtonSize::Large)
661
0
    {
662
0
        OUString iconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
663
0
        aUnscaledSize = vcl::IconThemeInfo::SizeByThemeName(iconTheme);
664
0
    }
665
0
    else if (eToolBoxButtonSize == ToolBoxButtonSize::Size32)
666
0
    {
667
0
        aUnscaledSize = Size(32, 32);
668
0
    }
669
0
    return Size(aUnscaledSize.Width()  * fScaleFactor,
670
0
                aUnscaledSize.Height() * fScaleFactor);
671
0
}
672
673
Size ToolBox::GetDefaultImageSize() const
674
0
{
675
0
    return GetDefaultImageSize(GetToolboxButtonSize());
676
0
}
677
678
void ToolBox::SetAlign( WindowAlign eNewAlign )
679
0
{
680
0
    if ( meAlign == eNewAlign )
681
0
        return;
682
683
0
    meAlign = eNewAlign;
684
685
0
    if ( ImplIsFloatingMode() )
686
0
        return;
687
688
    // set horizontal/vertical alignment
689
0
    if ( (eNewAlign == WindowAlign::Left) || (eNewAlign == WindowAlign::Right) )
690
0
        mbHorz = false;
691
0
    else
692
0
        mbHorz = true;
693
694
    // Update the background according to Persona if necessary
695
0
    ImplInitSettings( false, false, true );
696
697
    // redraw everything, as the border has changed
698
0
    mbCalc = true;
699
0
    mbFormat = true;
700
0
    if ( IsReallyVisible() && IsUpdateMode() )
701
0
        Invalidate();
702
0
}
703
704
void ToolBox::SetLineCount( ImplToolItems::size_type nNewLines )
705
0
{
706
0
    if ( !nNewLines )
707
0
        nNewLines = 1;
708
709
0
    if ( mnLines != nNewLines )
710
0
    {
711
0
        mnLines = nNewLines;
712
713
        // better redraw everything, as otherwise there might be problems
714
        // with regions that were copied with CopyBits
715
0
        Invalidate();
716
0
    }
717
0
}
718
719
ToolBox::ImplToolItems::size_type ToolBox::GetItemCount() const
720
0
{
721
0
    return mpData ? mpData->m_aItems.size() : 0;
722
0
}
723
724
ToolBoxItemType ToolBox::GetItemType( ImplToolItems::size_type nPos ) const
725
0
{
726
0
    return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].meType : ToolBoxItemType::DONTKNOW;
727
0
}
728
729
ToolBox::ImplToolItems::size_type ToolBox::GetItemPos( ToolBoxItemId nItemId ) const
730
0
{
731
0
    if (mpData)
732
0
    {
733
0
        ImplToolItems::size_type nCount = mpData->m_aItems.size();
734
0
        for( ImplToolItems::size_type nPos = 0; nPos < nCount; nPos++ )
735
0
            if( mpData->m_aItems[nPos].mnId == nItemId )
736
0
                return nPos;
737
0
    }
738
0
    return ITEM_NOTFOUND;
739
0
}
740
741
ToolBox::ImplToolItems::size_type ToolBox::GetItemPos( const Point& rPos ) const
742
0
{
743
    // search the item position on the given point
744
0
    auto it = std::find_if(mpData->m_aItems.begin(), mpData->m_aItems.end(),
745
0
        [&rPos](const ImplToolItem& rItem) { return rItem.maRect.Contains( rPos ); });
746
747
0
    if( it != mpData->m_aItems.end() )
748
0
        return std::distance(mpData->m_aItems.begin(), it);
749
750
0
    return ITEM_NOTFOUND;
751
0
}
752
753
ToolBoxItemId ToolBox::GetItemId( ImplToolItems::size_type nPos ) const
754
0
{
755
0
    return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].mnId : ToolBoxItemId(0);
756
0
}
757
758
ToolBoxItemId ToolBox::GetItemId( const Point& rPos ) const
759
0
{
760
    // find item that was clicked
761
0
    auto it = std::find_if(mpData->m_aItems.begin(), mpData->m_aItems.end(),
762
0
        [&rPos](const ImplToolItem& rItem) { return rItem.maRect.Contains( rPos ); });
763
764
0
    if( (it != mpData->m_aItems.end()) && (it->meType == ToolBoxItemType::BUTTON) )
765
0
        return it->mnId;
766
767
0
    return ToolBoxItemId(0);
768
0
}
769
770
Size ToolBox::GetItemContentSize( ToolBoxItemId nItemId )
771
0
{
772
0
    if ( mbCalc || mbFormat )
773
0
        ImplFormat();
774
775
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
776
0
    if ( nPos < mpData->m_aItems.size() )
777
0
        return mpData->m_aItems[nPos].maContentSize;
778
0
    else
779
0
        return Size();
780
0
}
781
782
ToolBoxItemId ToolBox::GetItemId(const OUString &rCommand) const
783
0
{
784
0
    if (!mpData)
785
0
        return ToolBoxItemId(0);
786
787
0
    auto it = std::find_if(mpData->m_aItems.begin(), mpData->m_aItems.end(),
788
0
        [&rCommand](const ImplToolItem& rItem) { return rItem.maCommandStr == rCommand; });
789
0
    if (it != mpData->m_aItems.end())
790
0
        return it->mnId;
791
792
0
    return ToolBoxItemId(0);
793
0
}
794
795
Point ToolBox::ImplGetPopupPosition( const tools::Rectangle& rRect ) const
796
0
{
797
0
    Point aPos;
798
0
    if( !rRect.IsEmpty() )
799
0
    {
800
0
        AbsoluteScreenPixelRectangle aScreen = GetDesktopRectPixel();
801
802
        // the popup should be positioned so that it will not cover
803
        // the item rect and that it fits the desktop
804
        // the preferred direction is always towards the center of
805
        // the application window
806
807
0
        AbsoluteScreenPixelPoint devPos; // the position in device coordinates for screen comparison
808
0
        switch( meAlign )
809
0
        {
810
0
            case WindowAlign::Top:
811
0
                aPos = rRect.BottomLeft();
812
0
                aPos.AdjustY( 1 );
813
0
                devPos = OutputToAbsoluteScreenPixel( aPos );
814
0
                if( devPos.Y() >= aScreen.Bottom() )
815
0
                    aPos.setY( rRect.Top() );
816
0
                break;
817
0
            case WindowAlign::Bottom:
818
0
                aPos = rRect.TopLeft();
819
0
                aPos.AdjustY( -1 );
820
0
                devPos = OutputToAbsoluteScreenPixel( aPos );
821
0
                if( devPos.Y() <= aScreen.Top() )
822
0
                    aPos.setY( rRect.Bottom() );
823
0
                break;
824
0
            case WindowAlign::Left:
825
0
                aPos = rRect.TopRight();
826
0
                aPos.AdjustX( 1 );
827
0
                devPos = OutputToAbsoluteScreenPixel( aPos );
828
0
                if( devPos.X() >= aScreen.Right() )
829
0
                    aPos.setX( rRect.Left() );
830
0
                break;
831
0
            case WindowAlign::Right:
832
0
                aPos = rRect.TopLeft();
833
0
                aPos.AdjustX( -1 );
834
0
                devPos = OutputToAbsoluteScreenPixel( aPos );
835
0
                if( devPos.X() <= aScreen.Left() )
836
0
                    aPos.setX( rRect.Right() );
837
0
                break;
838
0
            default:
839
0
                break;
840
0
        }
841
0
    }
842
0
    return aPos;
843
0
}
844
845
tools::Rectangle ToolBox::GetItemRect( ToolBoxItemId nItemId )
846
0
{
847
0
    if ( mbCalc || mbFormat )
848
0
        ImplFormat();
849
850
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
851
0
    return GetItemPosRect( nPos );
852
0
}
853
854
tools::Rectangle ToolBox::GetItemPosRect( ImplToolItems::size_type nPos )
855
0
{
856
0
    if ( mbCalc || mbFormat )
857
0
        ImplFormat();
858
859
0
    if ( nPos < mpData->m_aItems.size() )
860
0
        return mpData->m_aItems[nPos].maRect;
861
0
    else
862
0
        return tools::Rectangle();
863
0
}
864
865
tools::Rectangle const & ToolBox::GetOverflowRect() const
866
0
{
867
0
    return mpData->maMenubuttonItem.maRect;
868
0
}
869
870
bool ToolBox::ImplHasExternalMenubutton() const
871
0
{
872
    // check if the borderwindow (i.e. the decoration) provides the menu button
873
0
    bool bRet = false;
874
0
    if( ImplIsFloatingMode() )
875
0
    {
876
        // custom menu is placed in the decoration
877
0
        ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( GetWindowType::Border ) );
878
0
        if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
879
0
            bRet = true;
880
0
    }
881
0
    return bRet;
882
0
}
883
884
void ToolBox::SetItemBits( ToolBoxItemId nItemId, ToolBoxItemBits nBits )
885
0
{
886
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
887
888
0
    if ( nPos < GetItemCount() )
889
0
    {
890
0
        ToolBoxItemBits nOldBits = mpData->m_aItems[nPos].mnBits;
891
0
        mpData->m_aItems[nPos].mnBits = nBits;
892
0
        nBits &= ToolBoxItemBits::LEFT | ToolBoxItemBits::AUTOSIZE | ToolBoxItemBits::DROPDOWN;
893
0
        nOldBits &= ToolBoxItemBits::LEFT | ToolBoxItemBits::AUTOSIZE | ToolBoxItemBits::DROPDOWN;
894
        // trigger reformat when the item width has changed (dropdown arrow)
895
0
        bool bFormat = ToolBoxItemBits(nBits & ToolBoxItemBits::DROPDOWN) != ToolBoxItemBits(nOldBits & ToolBoxItemBits::DROPDOWN);
896
0
        if ( nBits != nOldBits )
897
0
            ImplInvalidate( true, bFormat );
898
0
    }
899
0
}
900
901
void ToolBox::SetItemWindowNonInteractive(ToolBoxItemId nItemId, bool bNonInteractive)
902
0
{
903
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
904
905
0
    if ( nPos < GetItemCount() )
906
0
    {
907
0
        mpData->m_aItems[nPos].mbNonInteractiveWindow = bNonInteractive;
908
0
    }
909
0
}
910
911
ToolBoxItemBits ToolBox::GetItemBits( ToolBoxItemId nItemId ) const
912
0
{
913
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
914
915
0
    if ( pItem )
916
0
        return pItem->mnBits;
917
0
    else
918
0
        return ToolBoxItemBits::NONE;
919
0
}
920
921
void ToolBox::SetItemExpand( ToolBoxItemId nItemId, bool bExpand )
922
0
{
923
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
924
0
    if (!pItem)
925
0
        return;
926
927
0
    if (pItem->mbExpand != bExpand)
928
0
    {
929
0
        pItem->mbExpand = bExpand;
930
0
        ImplInvalidate(true, true);
931
0
    }
932
0
}
933
934
void ToolBox::SetItemData( ToolBoxItemId nItemId, void* pNewData )
935
0
{
936
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
937
938
0
    if ( nPos < mpData->m_aItems.size() )
939
0
    {
940
0
        mpData->m_aItems[nPos].mpUserData = pNewData;
941
0
        ImplUpdateItem( nPos );
942
0
    }
943
0
}
944
945
void* ToolBox::GetItemData( ToolBoxItemId nItemId ) const
946
0
{
947
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
948
949
0
    if ( pItem )
950
0
        return pItem->mpUserData;
951
0
    else
952
0
        return nullptr;
953
0
}
954
955
static Image ImplMirrorImage( const Image& rImage )
956
0
{
957
0
    Bitmap aMirrBitmap( rImage.GetBitmap() );
958
959
0
    aMirrBitmap.Mirror( BmpMirrorFlags::Horizontal );
960
961
0
    return Image( aMirrBitmap );
962
0
}
963
964
static Image ImplRotImage( const Image& rImage, Degree10 nAngle10 )
965
0
{
966
0
    Bitmap aRotBitmap( rImage.GetBitmap() );
967
968
0
    aRotBitmap.Rotate( nAngle10, COL_WHITE );
969
970
0
    return Image( aRotBitmap );
971
0
}
972
973
void ToolBox::SetItemImage( ToolBoxItemId nItemId, const Image& rImage )
974
0
{
975
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
976
977
0
    if ( nPos == ITEM_NOTFOUND )
978
0
        return;
979
980
0
    ImplToolItem* pItem = &mpData->m_aItems[nPos];
981
0
    Size aOldSize = pItem->maImage.GetSizePixel();
982
983
0
    pItem->maImage = pItem->mbMirrorMode ? ImplMirrorImage(rImage) : rImage;
984
0
    if (pItem->mnImageAngle != 0_deg10)
985
0
        pItem->maImage = ImplRotImage(pItem->maImage, pItem->mnImageAngle);
986
987
    // only once all is calculated, do extra work
988
0
    if (!mbCalc)
989
0
    {
990
0
        if (aOldSize != pItem->maImage.GetSizePixel())
991
0
            ImplInvalidate( true );
992
0
        else
993
0
            ImplUpdateItem( nPos );
994
0
    }
995
0
}
996
997
void ToolBox::SetItemImageAngle( ToolBoxItemId nItemId, Degree10 nAngle10 )
998
0
{
999
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1000
1001
0
    if ( nPos == ITEM_NOTFOUND )
1002
0
        return;
1003
1004
0
    ImplToolItem* pItem = &mpData->m_aItems[nPos];
1005
0
    pItem->mnImageAngle = nAngle10;
1006
0
}
1007
1008
void ToolBox::SetItemImageMirrorMode( ToolBoxItemId nItemId, bool bMirror )
1009
0
{
1010
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1011
1012
0
    if ( nPos == ITEM_NOTFOUND )
1013
0
        return;
1014
1015
0
    ImplToolItem* pItem = &mpData->m_aItems[nPos];
1016
0
    pItem->mbMirrorMode = bMirror;
1017
0
}
1018
1019
Image ToolBox::GetItemImage(ToolBoxItemId nItemId) const
1020
0
{
1021
0
    ImplToolItem* pItem = ImplGetItem(nItemId);
1022
0
    return pItem ? pItem->maImage : Image();
1023
0
}
1024
1025
void ToolBox::SetItemText( ToolBoxItemId nItemId, const OUString& rText )
1026
0
{
1027
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1028
1029
0
    if ( nPos == ITEM_NOTFOUND )
1030
0
        return;
1031
1032
0
    ImplToolItem* pItem = &mpData->m_aItems[nPos];
1033
    // only once all is calculated, do extra work
1034
0
    if ( !mbCalc &&
1035
0
         ((meButtonType != ButtonType::SYMBOLONLY) || !pItem->maImage) )
1036
0
    {
1037
0
        tools::Long nOldWidth = GetOutDev()->GetCtrlTextWidth( pItem->maText );
1038
0
        pItem->maText = MnemonicGenerator::EraseAllMnemonicChars(rText);
1039
0
        mpData->ImplClearLayoutData();
1040
0
        if ( nOldWidth != GetOutDev()->GetCtrlTextWidth( pItem->maText ) )
1041
0
            ImplInvalidate( true );
1042
0
        else
1043
0
            ImplUpdateItem( nPos );
1044
0
    }
1045
0
    else
1046
0
        pItem->maText = MnemonicGenerator::EraseAllMnemonicChars(rText);
1047
1048
    // Notify
1049
0
    CallEventListeners( VclEventId::ToolboxItemTextChanged, reinterpret_cast< void* >( nPos ) );
1050
0
}
1051
1052
const OUString& ToolBox::GetItemText( ToolBoxItemId nItemId ) const
1053
0
{
1054
1055
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1056
1057
0
    assert( pItem );
1058
1059
0
    return pItem->maText;
1060
0
}
1061
1062
void ToolBox::SetItemWindow( ToolBoxItemId nItemId, vcl::Window* pNewWindow )
1063
0
{
1064
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1065
1066
0
    if ( nPos != ITEM_NOTFOUND )
1067
0
    {
1068
0
        ImplToolItem* pItem = &mpData->m_aItems[nPos];
1069
0
        pItem->mpWindow = pNewWindow;
1070
0
        if ( pNewWindow )
1071
0
            pNewWindow->Hide();
1072
0
        ImplInvalidate( true );
1073
0
        CallEventListeners( VclEventId::ToolboxItemWindowChanged, reinterpret_cast< void* >( nPos ) );
1074
0
    }
1075
0
}
1076
1077
vcl::Window* ToolBox::GetItemWindow( ToolBoxItemId nItemId ) const
1078
0
{
1079
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1080
1081
0
    if ( pItem )
1082
0
        return pItem->mpWindow;
1083
0
    else
1084
0
        return nullptr;
1085
0
}
1086
1087
void ToolBox::EndSelection()
1088
0
{
1089
0
    if ( mbDrag )
1090
0
    {
1091
        // reset
1092
0
        mbDrag = false;
1093
0
        if (mnCurPos != ITEM_NOTFOUND)
1094
0
            InvalidateItem(mnCurPos);
1095
0
        EndTracking();
1096
0
        if (IsMouseCaptured())
1097
0
            ReleaseMouse();
1098
0
        Deactivate();
1099
0
    }
1100
1101
0
    mnCurPos        = ITEM_NOTFOUND;
1102
0
    mnCurItemId     = ToolBoxItemId(0);
1103
0
    mnDownItemId    = ToolBoxItemId(0);
1104
0
    mnMouseModifier = 0;
1105
0
}
1106
1107
void ToolBox::SetItemDown( ToolBoxItemId nItemId, bool bDown )
1108
0
{
1109
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1110
1111
0
    if ( nPos == ITEM_NOTFOUND )
1112
0
        return;
1113
1114
0
    if ( bDown )
1115
0
    {
1116
0
        if ( nPos != mnCurPos )
1117
0
        {
1118
0
            mnCurPos = nPos;
1119
0
            InvalidateItem(mnCurPos);
1120
0
            GetOutDev()->Flush();
1121
0
        }
1122
0
    }
1123
0
    else
1124
0
    {
1125
0
        if ( nPos == mnCurPos )
1126
0
        {
1127
0
            InvalidateItem(mnCurPos);
1128
0
            GetOutDev()->Flush();
1129
0
            mnCurPos = ITEM_NOTFOUND;
1130
0
        }
1131
0
    }
1132
1133
0
    if ( mbDrag )
1134
0
    {
1135
0
        mbDrag = false;
1136
0
        EndTracking();
1137
0
        if (IsMouseCaptured())
1138
0
            ReleaseMouse();
1139
0
        Deactivate();
1140
0
    }
1141
1142
0
    mnCurItemId     = ToolBoxItemId(0);
1143
0
    mnDownItemId    = ToolBoxItemId(0);
1144
0
    mnMouseModifier = 0;
1145
0
}
1146
1147
void ToolBox::SetItemState( ToolBoxItemId nItemId, TriState eState )
1148
0
{
1149
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1150
1151
0
    if ( nPos == ITEM_NOTFOUND )
1152
0
        return;
1153
1154
0
    ImplToolItem* pItem = &mpData->m_aItems[nPos];
1155
1156
    // the state has changed
1157
0
    if ( pItem->meState == eState )
1158
0
        return;
1159
1160
    // if RadioCheck, un-check the previous
1161
0
    if ( (eState == TRISTATE_TRUE) && (pItem->mnBits & ToolBoxItemBits::AUTOCHECK) &&
1162
0
         (pItem->mnBits & ToolBoxItemBits::RADIOCHECK) )
1163
0
    {
1164
0
        ImplToolItem*    pGroupItem;
1165
0
        ImplToolItems::size_type nGroupPos;
1166
0
        ImplToolItems::size_type nItemCount = GetItemCount();
1167
1168
0
        nGroupPos = nPos;
1169
0
        while ( nGroupPos )
1170
0
        {
1171
0
            pGroupItem = &mpData->m_aItems[nGroupPos-1];
1172
0
            if ( pGroupItem->mnBits & ToolBoxItemBits::RADIOCHECK )
1173
0
            {
1174
0
                if ( pGroupItem->meState != TRISTATE_FALSE )
1175
0
                    SetItemState( pGroupItem->mnId, TRISTATE_FALSE );
1176
0
            }
1177
0
            else
1178
0
                break;
1179
0
            nGroupPos--;
1180
0
        }
1181
1182
0
        nGroupPos = nPos+1;
1183
0
        while ( nGroupPos < nItemCount )
1184
0
        {
1185
0
            pGroupItem = &mpData->m_aItems[nGroupPos];
1186
0
            if ( pGroupItem->mnBits & ToolBoxItemBits::RADIOCHECK )
1187
0
            {
1188
0
                if ( pGroupItem->meState != TRISTATE_FALSE )
1189
0
                    SetItemState( pGroupItem->mnId, TRISTATE_FALSE );
1190
0
            }
1191
0
            else
1192
0
                break;
1193
0
            nGroupPos++;
1194
0
        }
1195
0
    }
1196
1197
0
    pItem->meState = eState;
1198
0
    ImplUpdateItem( nPos );
1199
1200
    // Call accessible listener to notify state_changed event
1201
0
    CallEventListeners( VclEventId::ToolboxItemUpdated, reinterpret_cast< void* >(nPos) );
1202
0
}
1203
1204
TriState ToolBox::GetItemState( ToolBoxItemId nItemId ) const
1205
0
{
1206
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1207
1208
0
    if ( pItem )
1209
0
        return pItem->meState;
1210
0
    else
1211
0
        return TRISTATE_FALSE;
1212
0
}
1213
1214
void ToolBox::EnableItem( ToolBoxItemId nItemId, bool bEnable )
1215
0
{
1216
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1217
1218
0
    if ( nPos == ITEM_NOTFOUND )
1219
0
        return;
1220
1221
0
    ImplToolItem* pItem = &mpData->m_aItems[nPos];
1222
0
    if ( pItem->mbEnabled == bEnable )
1223
0
        return;
1224
1225
0
    pItem->mbEnabled = bEnable;
1226
1227
    // if existing, also redraw the window
1228
0
    if ( pItem->mpWindow )
1229
0
        pItem->mpWindow->Enable( pItem->mbEnabled );
1230
1231
    // update item
1232
0
    ImplUpdateItem( nPos );
1233
1234
0
    ImplUpdateInputEnable();
1235
1236
0
    CallEventListeners( bEnable ? VclEventId::ToolboxItemEnabled : VclEventId::ToolboxItemDisabled, reinterpret_cast< void* >( nPos ) );
1237
0
}
1238
1239
bool ToolBox::IsItemEnabled( ToolBoxItemId nItemId ) const
1240
0
{
1241
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1242
1243
0
    if ( pItem )
1244
0
        return pItem->mbEnabled;
1245
0
    else
1246
0
        return false;
1247
0
}
1248
1249
void ToolBox::ShowItem( ToolBoxItemId nItemId, bool bVisible )
1250
0
{
1251
0
    ImplToolItems::size_type nPos = GetItemPos( nItemId );
1252
0
    mpData->ImplClearLayoutData();
1253
1254
0
    if ( nPos != ITEM_NOTFOUND )
1255
0
    {
1256
0
        ImplToolItem* pItem = &mpData->m_aItems[nPos];
1257
0
        if ( pItem->mbVisible != bVisible )
1258
0
        {
1259
0
            pItem->mbVisible = bVisible;
1260
0
            ImplInvalidate();
1261
0
        }
1262
0
    }
1263
0
}
1264
1265
bool ToolBox::IsItemClipped( ToolBoxItemId nItemId ) const
1266
0
{
1267
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1268
1269
0
    if ( pItem )
1270
0
        return pItem->IsClipped();
1271
0
    else
1272
0
        return false;
1273
0
}
1274
1275
bool ToolBox::IsItemVisible( ToolBoxItemId nItemId ) const
1276
0
{
1277
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1278
1279
0
    if ( pItem )
1280
0
        return pItem->mbVisible;
1281
0
    else
1282
0
        return false;
1283
0
}
1284
1285
bool ToolBox::IsItemReallyVisible( ToolBoxItemId nItemId ) const
1286
0
{
1287
    // is the item on the visible area of the toolbox?
1288
0
    bool bRet = false;
1289
0
    tools::Rectangle aRect( mnLeftBorder, mnTopBorder, mnDX-mnRightBorder, mnDY-mnBottomBorder );
1290
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1291
1292
0
    if ( pItem && pItem->mbVisible &&
1293
0
         !pItem->maRect.IsEmpty() && aRect.Overlaps( pItem->maRect ) )
1294
0
    {
1295
0
        bRet = true;
1296
0
    }
1297
1298
0
    return bRet;
1299
0
}
1300
1301
void ToolBox::SetItemCommand(ToolBoxItemId nItemId, const OUString& rCommand)
1302
0
{
1303
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1304
1305
0
    if (pItem)
1306
0
        pItem->maCommandStr = rCommand;
1307
0
}
1308
1309
OUString ToolBox::GetItemCommand( ToolBoxItemId nItemId ) const
1310
0
{
1311
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1312
1313
0
    if (pItem)
1314
0
        return pItem->maCommandStr;
1315
1316
0
    return OUString();
1317
0
}
1318
1319
void ToolBox::SetQuickHelpText( ToolBoxItemId nItemId, const OUString& rText )
1320
0
{
1321
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1322
1323
0
    if ( pItem )
1324
0
        pItem->maQuickHelpText = rText;
1325
0
}
1326
1327
OUString ToolBox::GetQuickHelpText( ToolBoxItemId nItemId ) const
1328
0
{
1329
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1330
1331
0
    if ( pItem )
1332
0
        return pItem->maQuickHelpText;
1333
0
    else
1334
0
        return OUString();
1335
0
}
1336
1337
void ToolBox::SetHelpText( ToolBoxItemId nItemId, const OUString& rText )
1338
0
{
1339
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1340
1341
0
    if ( pItem )
1342
0
        pItem->maHelpText = rText;
1343
0
}
1344
1345
const OUString& ToolBox::GetHelpText( ToolBoxItemId nItemId ) const
1346
0
{
1347
0
    return ImplGetHelpText( nItemId );
1348
0
}
1349
1350
void ToolBox::SetAccessibleName(ToolBoxItemId nItemId, const OUString& rText)
1351
0
{
1352
0
    ImplToolItem* pItem = ImplGetItem(nItemId);
1353
1354
0
    if (pItem)
1355
0
        pItem->maAccessibleName = rText;
1356
0
}
1357
1358
OUString ToolBox::GetAccessibleName(ToolBoxItemId nItemId) const
1359
0
{
1360
0
    ImplToolItem* pItem = ImplGetItem(nItemId);
1361
0
    if (pItem)
1362
0
        return pItem->maAccessibleName;
1363
1364
0
    return OUString();
1365
0
}
1366
1367
void ToolBox::SetHelpId( ToolBoxItemId nItemId, const OUString& rHelpId )
1368
0
{
1369
0
    ImplToolItem* pItem = ImplGetItem( nItemId );
1370
1371
0
    if ( pItem )
1372
0
        pItem->maHelpId = rHelpId;
1373
0
}
1374
1375
// disable key input if all items are disabled
1376
void ToolBox::ImplUpdateInputEnable()
1377
0
{
1378
0
    mpData->mbKeyInputDisabled = std::none_of(mpData->m_aItems.begin(), mpData->m_aItems.end(),
1379
0
        [](const ImplToolItem& rItem) {
1380
            // at least one useful entry
1381
0
            return rItem.mbEnabled;
1382
0
        });
1383
0
}
1384
1385
void ToolBox::ImplFillLayoutData()
1386
0
{
1387
0
    mpData->m_pLayoutData.emplace();
1388
1389
0
    ImplToolItems::size_type nCount = mpData->m_aItems.size();
1390
0
    for( ImplToolItems::size_type i = 0; i < nCount; i++ )
1391
0
    {
1392
0
        ImplToolItem* pItem = &mpData->m_aItems[i];
1393
1394
        // only draw, if the rectangle is within PaintRectangle
1395
0
        if (!pItem->maRect.IsEmpty())
1396
0
            InvalidateItem(i);
1397
0
    }
1398
0
}
1399
1400
OUString ToolBox::GetDisplayText() const
1401
0
{
1402
0
    if( ! mpData->m_pLayoutData )
1403
0
        const_cast<ToolBox *>(this)->ImplFillLayoutData();
1404
0
    return mpData->m_pLayoutData ? mpData->m_pLayoutData->m_aDisplayText : OUString();
1405
0
}
1406
1407
tools::Rectangle ToolBox::GetCharacterBounds( ToolBoxItemId nItemID, tools::Long nIndex )
1408
0
{
1409
0
    tools::Long nItemIndex = -1;
1410
0
    if( ! mpData->m_pLayoutData )
1411
0
        ImplFillLayoutData();
1412
0
    if( mpData->m_pLayoutData )
1413
0
    {
1414
0
        for( size_t i = 0; i < mpData->m_pLayoutData->m_aLineItemIds.size(); i++ )
1415
0
        {
1416
0
            if( mpData->m_pLayoutData->m_aLineItemIds[i] == nItemID )
1417
0
            {
1418
0
                nItemIndex = mpData->m_pLayoutData->m_aLineIndices[i];
1419
0
                break;
1420
0
            }
1421
0
        }
1422
0
    }
1423
0
    return (mpData->m_pLayoutData && nItemIndex != -1) ? mpData->m_pLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : tools::Rectangle();
1424
0
}
1425
1426
tools::Long ToolBox::GetIndexForPoint( const Point& rPoint, ToolBoxItemId& rItemID )
1427
0
{
1428
0
    tools::Long nIndex = -1;
1429
0
    rItemID = ToolBoxItemId(0);
1430
0
    if( ! mpData->m_pLayoutData )
1431
0
        ImplFillLayoutData();
1432
0
    if( mpData->m_pLayoutData )
1433
0
    {
1434
0
        nIndex = mpData->m_pLayoutData->GetIndexForPoint( rPoint );
1435
0
        for( size_t i = 0; i < mpData->m_pLayoutData->m_aLineIndices.size(); i++ )
1436
0
        {
1437
0
            if( mpData->m_pLayoutData->m_aLineIndices[i] <= nIndex &&
1438
0
                (i == mpData->m_pLayoutData->m_aLineIndices.size()-1 || mpData->m_pLayoutData->m_aLineIndices[i+1] > nIndex) )
1439
0
            {
1440
0
                rItemID = mpData->m_pLayoutData->m_aLineItemIds[i];
1441
0
                break;
1442
0
            }
1443
0
        }
1444
0
    }
1445
0
    return nIndex;
1446
0
}
1447
1448
void ToolBox::SetDropdownClickHdl( const Link<ToolBox *, void>& rLink )
1449
0
{
1450
0
    if (mpData != nullptr) {
1451
0
        mpData->maDropdownClickHdl = rLink;
1452
0
    }
1453
0
}
1454
1455
void ToolBox::SetMenuType( ToolBoxMenuType aType )
1456
0
{
1457
0
    if( aType == mpData->maMenuType )
1458
0
        return;
1459
1460
0
    mpData->maMenuType = aType;
1461
0
    if( IsFloatingMode() )
1462
0
    {
1463
        // the menu button may have to be moved into the decoration which changes the layout
1464
0
        ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1465
0
        if( pWrapper )
1466
0
            pWrapper->ShowMenuTitleButton( bool( aType & ToolBoxMenuType::Customize) );
1467
1468
0
        mbFormat = true;
1469
0
        ImplFormat();
1470
0
        ImplSetMinMaxFloatSize();
1471
0
    }
1472
0
    else
1473
0
    {
1474
        // trigger redraw of menu button
1475
0
        if( !mpData->maMenubuttonItem.maRect.IsEmpty() )
1476
0
            Invalidate(mpData->maMenubuttonItem.maRect);
1477
0
    }
1478
0
}
1479
1480
ToolBoxMenuType ToolBox::GetMenuType() const
1481
0
{
1482
0
    return mpData->maMenuType;
1483
0
}
1484
1485
bool ToolBox::IsMenuEnabled() const
1486
0
{
1487
0
    return mpData->maMenuType != ToolBoxMenuType::NONE;
1488
0
}
1489
1490
PopupMenu* ToolBox::GetMenu() const
1491
0
{
1492
0
    return mpData ? mpData->mpMenu : nullptr;
1493
0
}
1494
1495
void ToolBox::SetMenuExecuteHdl( const Link<ToolBox *, void>& rLink )
1496
0
{
1497
0
    mpData->maMenuButtonHdl = rLink;
1498
0
}
1499
1500
bool ToolBox::ImplHasClippedItems()
1501
0
{
1502
    // are any items currently clipped ?
1503
0
    ImplFormat();
1504
0
    return std::any_of(mpData->m_aItems.begin(), mpData->m_aItems.end(),
1505
0
        [](const ImplToolItem& rItem) { return rItem.IsClipped(); });
1506
0
}
1507
1508
namespace
1509
{
1510
    MenuItemBits ConvertBitsFromToolBoxToMenu(ToolBoxItemBits nToolItemBits)
1511
0
    {
1512
0
        MenuItemBits nMenuItemBits = MenuItemBits::NONE;
1513
0
        if ((nToolItemBits & ToolBoxItemBits::CHECKABLE) ||
1514
0
            (nToolItemBits & ToolBoxItemBits::DROPDOWN))
1515
0
        {
1516
0
            nMenuItemBits |= MenuItemBits::CHECKABLE;
1517
0
        }
1518
0
        return nMenuItemBits;
1519
0
    }
1520
}
1521
1522
void ToolBox::UpdateCustomMenu(PopupMenu* pMenu)
1523
0
{
1524
    // fill clipped items into menu
1525
0
    pMenu->Clear();
1526
1527
    // add menu items: first the overflow items, then hidden items, both in the
1528
    // order they would usually appear in the toolbar. Separators that would be
1529
    // in the toolbar are ignored as they would introduce too much clutter,
1530
    // instead we have a single separator to help distinguish between overflow
1531
    // and hidden items.
1532
0
    if ( mpData->m_aItems.empty() )
1533
0
        return;
1534
1535
    // nStartPos will hold the number of clipped items appended from first loop
1536
0
    for ( const auto& rItem : mpData->m_aItems )
1537
0
    {
1538
0
        if( rItem.IsClipped() )
1539
0
        {
1540
0
            sal_uInt16 id = sal_uInt16(rItem.mnId) + TOOLBOX_MENUITEM_START;
1541
0
            MenuItemBits nMenuItemBits = ConvertBitsFromToolBoxToMenu(rItem.mnBits);
1542
0
            pMenu->InsertItem( id, rItem.maText, rItem.maImage, nMenuItemBits);
1543
0
            pMenu->SetItemCommand( id, rItem.maCommandStr );
1544
0
            pMenu->EnableItem( id, rItem.mbEnabled );
1545
0
            pMenu->CheckItem ( id, rItem.meState == TRISTATE_TRUE );
1546
0
        }
1547
0
    }
1548
1549
    // add a separator below the inserted clipped-items
1550
0
    pMenu->InsertSeparator();
1551
1552
    // now append the items that are explicitly disabled
1553
0
    for ( const auto& rItem : mpData->m_aItems )
1554
0
    {
1555
0
        if( rItem.IsItemHidden() )
1556
0
        {
1557
0
            sal_uInt16 id = sal_uInt16(rItem.mnId) + TOOLBOX_MENUITEM_START;
1558
0
            MenuItemBits nMenuItemBits = ConvertBitsFromToolBoxToMenu(rItem.mnBits);
1559
0
            pMenu->InsertItem( id, rItem.maText, rItem.maImage, nMenuItemBits );
1560
0
            pMenu->SetItemCommand( id, rItem.maCommandStr );
1561
0
            pMenu->EnableItem( id, rItem.mbEnabled );
1562
0
            pMenu->CheckItem( id, rItem.meState == TRISTATE_TRUE );
1563
0
        }
1564
0
    }
1565
0
}
1566
1567
IMPL_LINK( ToolBox, ImplCustomMenuListener, VclMenuEvent&, rEvent, void )
1568
0
{
1569
0
    PopupMenu *pMenu = GetMenu();
1570
0
    if( pMenu && rEvent.GetMenu() == pMenu && rEvent.GetId() == VclEventId::MenuSelect )
1571
0
    {
1572
0
        sal_uInt16 id = pMenu->GetItemId( rEvent.GetItemPos() );
1573
0
        if( id >= TOOLBOX_MENUITEM_START )
1574
0
            TriggerItem( ToolBoxItemId(id - TOOLBOX_MENUITEM_START) );
1575
0
    }
1576
0
}
1577
1578
void ToolBox::ExecuteCustomMenu( const tools::Rectangle& rRect )
1579
0
{
1580
0
    if ( !IsMenuEnabled() || ImplIsInPopupMode() )
1581
0
        return;
1582
1583
0
    PopupMenu *pMenu = GetMenu();
1584
0
    if (!pMenu)
1585
0
        return;
1586
0
    UpdateCustomMenu(pMenu);
1587
1588
0
    if( GetMenuType() & ToolBoxMenuType::Customize )
1589
        // call button handler to allow for menu customization
1590
0
        mpData->maMenuButtonHdl.Call( this );
1591
1592
0
    pMenu->AddEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
1593
1594
    // make sure all disabled entries will be shown
1595
0
    pMenu->SetMenuFlags(
1596
0
        pMenu->GetMenuFlags() | MenuFlags::AlwaysShowDisabledEntries );
1597
1598
    // toolbox might be destroyed during execute
1599
0
    bool bBorderDel = false;
1600
1601
0
    VclPtr<vcl::Window> pWin = this;
1602
0
    tools::Rectangle aMenuRect = rRect;
1603
0
    VclPtr<ImplBorderWindow> pBorderWin;
1604
0
    if( aMenuRect.IsEmpty() && IsFloatingMode() )
1605
0
    {
1606
        // custom menu is placed in the decoration
1607
0
        pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( GetWindowType::Border ) );
1608
0
        if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
1609
0
        {
1610
0
            pWin = pBorderWin;
1611
0
            aMenuRect = pBorderWin->GetMenuRect();
1612
0
            bBorderDel = true;
1613
0
        }
1614
0
    }
1615
1616
0
    sal_uInt16 uId = pMenu->Execute( pWin, tools::Rectangle( ImplGetPopupPosition( aMenuRect ), Size() ),
1617
0
                            PopupMenuFlags::ExecuteDown | PopupMenuFlags::NoMouseUpClose );
1618
1619
0
    if ( pWin->isDisposed() )
1620
0
        return;
1621
1622
0
    pMenu->RemoveEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
1623
0
    if( bBorderDel )
1624
0
    {
1625
0
        if( pBorderWin->isDisposed() )
1626
0
            return;
1627
0
    }
1628
1629
0
    pWin->Invalidate( aMenuRect );
1630
1631
0
    if( uId )
1632
0
        GrabFocusToDocument();
1633
0
}
1634
1635
// checks override first, useful during calculation of sizes
1636
bool ToolBox::ImplIsFloatingMode() const
1637
0
{
1638
0
    SAL_WARN_IF( mpData->mbAssumeDocked && mpData->mbAssumeFloating, "vcl",
1639
0
        "cannot assume docked and floating" );
1640
1641
0
    if( mpData->mbAssumeDocked )
1642
0
        return false;
1643
0
    else if( mpData->mbAssumeFloating )
1644
0
        return true;
1645
0
    else
1646
0
        return IsFloatingMode();
1647
0
}
1648
1649
// checks override first, useful during calculation of sizes
1650
bool ToolBox::ImplIsInPopupMode() const
1651
0
{
1652
0
    if( mpData->mbAssumePopupMode )
1653
0
        return true;
1654
0
    else
1655
0
    {
1656
0
        ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1657
0
        return ( pWrapper && pWrapper->GetFloatingWindow() && static_cast<FloatingWindow*>(pWrapper->GetFloatingWindow())->IsInPopupMode() );
1658
0
    }
1659
0
}
1660
1661
void ToolBox::Lock( bool bLock )
1662
0
{
1663
0
    ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1664
0
    if( !pWrapper )
1665
0
        return;
1666
0
    if( mpData->mbIsLocked != bLock )
1667
0
    {
1668
0
        mpData->mbIsLocked = bLock;
1669
0
        if( !ImplIsFloatingMode() )
1670
0
        {
1671
0
            mbCalc = true;
1672
0
            mbFormat = true;
1673
0
            SetSizePixel( CalcWindowSizePixel(1) );
1674
0
            Invalidate();
1675
0
        }
1676
0
    }
1677
0
}
1678
1679
bool ToolBox::AlwaysLocked()
1680
0
{
1681
    // read config item to determine toolbox behaviour, used for subtoolbars
1682
1683
0
    static int nAlwaysLocked = -1;
1684
1685
0
    if( nAlwaysLocked == -1 )
1686
0
    {
1687
0
        nAlwaysLocked = 0; // ask configuration only once
1688
1689
0
        utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithComponentContext(
1690
0
            comphelper::getProcessComponentContext(),
1691
0
            u"/org.openoffice.Office.UI.GlobalSettings/Toolbars"_ustr );    // note: case sensitive !
1692
0
        if ( aNode.isValid() )
1693
0
        {
1694
            // feature enabled ?
1695
0
            bool bStatesEnabled = bool();
1696
0
            css::uno::Any aValue = aNode.getNodeValue( u"StatesEnabled"_ustr );
1697
0
            if( aValue >>= bStatesEnabled )
1698
0
            {
1699
0
                if( bStatesEnabled )
1700
0
                {
1701
                    // now read the locking state
1702
0
                    utl::OConfigurationNode aNode2 = utl::OConfigurationTreeRoot::tryCreateWithComponentContext(
1703
0
                        comphelper::getProcessComponentContext(),
1704
0
                        u"/org.openoffice.Office.UI.GlobalSettings/Toolbars/States"_ustr );    // note: case sensitive !
1705
1706
0
                    bool bLocked = bool();
1707
0
                    css::uno::Any aValue2 = aNode2.getNodeValue( u"Locked"_ustr );
1708
0
                    if( aValue2 >>= bLocked )
1709
0
                        nAlwaysLocked = bLocked ? 1 : 0;
1710
0
                }
1711
0
            }
1712
0
        }
1713
0
    }
1714
1715
0
    return nAlwaysLocked == 1;
1716
0
}
1717
1718
bool ToolBox::WillUsePopupMode() const
1719
0
{
1720
0
    return mpData->mbWillUsePopupMode;
1721
0
}
1722
1723
void ToolBox::WillUsePopupMode( bool b )
1724
0
{
1725
0
    mpData->mbWillUsePopupMode = b;
1726
0
}
1727
1728
void ToolBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
1729
0
{
1730
0
    DockingWindow::DumpAsPropertyTree(rJsonWriter);
1731
1732
0
    auto childrenNode = rJsonWriter.startArray("children");
1733
0
    for (ToolBox::ImplToolItems::size_type i = 0; i < GetItemCount(); ++i)
1734
0
    {
1735
0
        auto childNode = rJsonWriter.startStruct();
1736
0
        ToolBoxItemId nId = GetItemId(i);
1737
1738
0
        vcl::Window* pWindow = GetItemWindow(nId);
1739
0
        if (pWindow)
1740
0
        {
1741
0
            pWindow->DumpAsPropertyTree(rJsonWriter);
1742
0
        }
1743
0
        else
1744
0
        {
1745
0
            OUString sCommand = GetItemCommand(nId);
1746
0
            rJsonWriter.put("type", "toolitem");
1747
0
            rJsonWriter.put("text", GetItemText(nId));
1748
0
            rJsonWriter.put("command", sCommand);
1749
0
            if (const OUString tooltip = GetQuickHelpText(nId); !tooltip.isEmpty())
1750
0
                rJsonWriter.put("tooltip", tooltip);
1751
0
            if (IsItemChecked(nId))
1752
0
                rJsonWriter.put("selected", true);
1753
0
            if (!IsItemVisible(nId))
1754
0
                rJsonWriter.put("visible", false);
1755
0
            if (GetItemBits(nId) & ToolBoxItemBits::DROPDOWN)
1756
0
                rJsonWriter.put("dropdown", true);
1757
0
            if (!IsItemEnabled(nId))
1758
0
                rJsonWriter.put("enabled", false);
1759
1760
0
            OUString sAccName = GetAccessibleName(nId);
1761
0
            OUString sAccDesc = GetAccessibleDescription();
1762
1763
0
            if (!sAccName.isEmpty() || !sAccDesc.isEmpty())
1764
0
            {
1765
0
                auto aAria = rJsonWriter.startNode("aria");
1766
0
                if (!sAccName.isEmpty())
1767
0
                    rJsonWriter.put("label", sAccName);
1768
0
                if (!sAccDesc.isEmpty())
1769
0
                    rJsonWriter.put("description", sAccDesc);
1770
0
            }
1771
1772
0
            if (!sCommand.startsWith(".uno:") || sCommand == u".uno:ChartColorPalette"_ustr)
1773
0
            {
1774
0
                Image aImage = GetItemImage(nId);
1775
0
                if (!!aImage)
1776
0
                {
1777
0
                    SvMemoryStream aOStm(6535, 6535);
1778
0
                    if (GraphicConverter::Export(aOStm, aImage.GetBitmap(),
1779
0
                                                 ConvertDataFormat::PNG)
1780
0
                        == ERRCODE_NONE)
1781
0
                    {
1782
0
                        css::uno::Sequence<sal_Int8> aSeq(
1783
0
                            static_cast<sal_Int8 const*>(aOStm.GetData()), aOStm.Tell());
1784
0
                        OStringBuffer aBuffer("data:image/png;base64,");
1785
0
                        ::comphelper::Base64::encode(aBuffer, aSeq);
1786
0
                        rJsonWriter.put("image", aBuffer);
1787
0
                    }
1788
0
                }
1789
0
            }
1790
0
        }
1791
0
    }
1792
0
}
1793
1794
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */