Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/view/ToolBarManager.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 <ToolBarManager.hxx>
21
22
#include <DrawViewShell.hxx>
23
#include <NotesPanelViewShell.hxx>
24
#include <EventMultiplexer.hxx>
25
#include <ViewShellBase.hxx>
26
#include <ViewShellManager.hxx>
27
#include <framework/FrameworkHelper.hxx>
28
#include <com/sun/star/beans/XPropertySet.hpp>
29
#include <com/sun/star/frame/XLayoutManager.hpp>
30
31
#include <sal/log.hxx>
32
#include <osl/mutex.hxx>
33
#include <o3tl/deleter.hxx>
34
#include <o3tl/enumrange.hxx>
35
#include <sfx2/docfile.hxx>
36
#include <sfx2/notebookbar/SfxNotebookBar.hxx>
37
#include <sfx2/objsh.hxx>
38
#include <sfx2/toolbarids.hxx>
39
#include <sfx2/viewfrm.hxx>
40
#include <svl/eitem.hxx>
41
#include <svx/svxids.hrc>
42
#include <svx/extrusionbar.hxx>
43
#include <svx/fontworkbar.hxx>
44
#include <tools/debug.hxx>
45
#include <tools/link.hxx>
46
#include <utility>
47
#include <vcl/svapp.hxx>
48
#include <osl/diagnose.h>
49
50
#include <map>
51
#include <memory>
52
#include <string_view>
53
#include <vector>
54
55
using namespace ::com::sun::star;
56
using namespace ::com::sun::star::uno;
57
58
namespace {
59
60
using namespace sd;
61
62
class ToolBarRules;
63
64
/** Lock of the frame::XLayoutManager.
65
*/
66
class LayouterLock
67
{
68
    Reference<frame::XLayoutManager> mxLayouter;
69
public:
70
    explicit LayouterLock (const Reference<frame::XLayoutManager>& rxLayouter);
71
    ~LayouterLock();
72
0
    bool is() const { return mxLayouter.is(); }
73
};
74
75
/** Store a list of tool bars for each of the tool bar groups.  From
76
    this the list of requested tool bars is built.
77
*/
78
class ToolBarList
79
{
80
public:
81
    ToolBarList();
82
83
    void ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup);
84
    void AddToolBar (sd::ToolBarManager::ToolBarGroup eGroup, const OUString& rsName);
85
    bool RemoveToolBar (sd::ToolBarManager::ToolBarGroup eGroup, const OUString& rsName);
86
87
    void GetToolBarsToActivate (std::vector<OUString>& rToolBars) const;
88
    void GetToolBarsToDeactivate (std::vector<OUString>& rToolBars) const;
89
90
    void MarkToolBarAsActive (const OUString& rsName);
91
    void MarkToolBarAsNotActive (const OUString& rsName);
92
    void MarkAllToolBarsAsNotActive();
93
94
private:
95
    typedef ::std::map<sd::ToolBarManager::ToolBarGroup, std::vector<OUString> > Groups;
96
    Groups maGroups;
97
    std::vector<OUString> maActiveToolBars;
98
99
    void MakeRequestedToolBarList (std::vector<OUString>& rToolBars) const;
100
};
101
102
/** Manage tool bars that are implemented as sub shells of a view shell.
103
    The typical procedure of updating the sub shells of a view shell is to
104
    rebuild a list of sub shells that the caller would like to have active.
105
    The methods ClearGroup() and AddShellId() allow the caller to do that.  A
106
    final call to UpdateShells() activates the requested shells that are not
107
    active and deactivates the active shells that are not requested .
108
109
    This is done by maintaining two lists.  One (the current list)
110
    reflects the current state.  The other (the requested list) contains the
111
    currently requested shells.  UpdateShells() makes the requested
112
    list the current list and clears the current list.
113
114
    Each shell belongs to one group.  Different groups can be modified
115
    separately.
116
*/
117
class ToolBarShellList
118
{
119
public:
120
    /** Create a new object with an empty current list and an empty
121
        requested list.
122
    */
123
    ToolBarShellList();
124
125
    /** Remove all shells from a group.  Calling this method should normally
126
        not be necessary because after the construction or after a call to
127
        UpdateShells() the requested list is empty.
128
        @param eGroup
129
            The group to clear. Shells in other groups are not modified.
130
    */
131
    void ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup);
132
133
    /** Add a shell. When the specified shell has already been requested
134
        for another group then it is moved to this group.
135
        @param eGroup
136
            The group to which to add the shell.
137
        @param nId
138
            The id of the shell to add.
139
    */
140
    void AddShellId (sd::ToolBarManager::ToolBarGroup eGroup, sd::ShellId nId);
141
142
    /** Releasing all shells means that the given ToolBarRules object is
143
        informed that every shell managed by the called ToolBarShellList is
144
        about to be removed and that the associated framework tool bars can
145
        be removed as well.  The caller still has to call UpdateShells().
146
    */
147
    void ReleaseAllShells (ToolBarRules& rRules);
148
149
    /** The requested list is made the current list by activating  all
150
        shells in the requested list and by deactivating the shells in the
151
        current list that are not in the requested list.
152
        @param pMainViewShell
153
            The shells that are activated or deactivated are sub shells of
154
            this view shell.
155
        @param rManager
156
            This ViewShellManager is used to activate or deactivate shells.
157
    */
158
    void UpdateShells (
159
        const std::shared_ptr<ViewShell>& rpMainViewShell,
160
        const std::shared_ptr<ViewShellManager>& rpManager);
161
162
private:
163
    class ShellDescriptor
164
    {public:
165
        ShellDescriptor (ShellId nId,sd::ToolBarManager::ToolBarGroup eGroup);
166
        ShellId mnId;
167
        sd::ToolBarManager::ToolBarGroup meGroup;
168
        friend bool operator<(const ShellDescriptor& r1, const ShellDescriptor& r2)
169
0
        { return r1.mnId < r2.mnId; }
170
    };
171
172
    /** The requested list of tool bar shells that will be active after the
173
        next call to UpdateShells().
174
    */
175
    typedef ::std::set<ShellDescriptor> GroupedShellList;
176
    GroupedShellList maNewList;
177
178
    /** The list of tool bar shells that are currently on the shell stack.
179
        Using a GroupedShellList is not strictly necessary but it makes
180
        things easier and does not waste too much memory.
181
    */
182
    GroupedShellList maCurrentList;
183
};
184
185
/** This class concentrates the knowledge about when to show what tool bars
186
    in one place.
187
*/
188
class ToolBarRules
189
{
190
public:
191
    ToolBarRules (
192
        std::shared_ptr<ToolBarManager> pToolBarManager,
193
        std::shared_ptr<ViewShellManager> pViewShellManager);
194
195
    /** This method calls MainViewShellChanged() and SelectionHasChanged()
196
        for the current main view shell and its view.
197
    */
198
    void Update (ViewShellBase const & rBase);
199
200
    /** Reset all tool bars in all groups and add tool bars and tool bar
201
        shells to the ToolBarGroup::Permanent group for the specified ViewShell type.
202
    */
203
    void MainViewShellChanged (ViewShell::ShellType nShellType);
204
205
    /** Reset all tool bars in all groups and add tool bars and tool bar
206
        shells to the ToolBarGroup::Permanent group for the specified ViewShell.
207
    */
208
    void MainViewShellChanged (const ViewShell& rMainViewShell);
209
210
    /** Reset all tool bars in the ToolBarGroup::Function group and add tool bars and tool bar
211
        shells to this group for the current selection.
212
    */
213
    void SelectionHasChanged (
214
        const ::sd::ViewShell& rViewShell,
215
        const SdrView& rView);
216
217
    /** Add a tool bar for the specified tool bar shell.
218
    */
219
    void SubShellAdded (
220
        ::sd::ToolBarManager::ToolBarGroup eGroup,
221
        sd::ShellId nShellId);
222
223
    /** Remove a tool bar for the specified tool bar shell.
224
    */
225
    void SubShellRemoved (
226
        ::sd::ToolBarManager::ToolBarGroup eGroup,
227
        sd::ShellId nShellId);
228
229
private:
230
    std::shared_ptr<ToolBarManager> mpToolBarManager;
231
    std::shared_ptr<ViewShellManager> mpViewShellManager;
232
};
233
234
} // end of anonymous namespace
235
236
namespace sd {
237
238
//===== ToolBarManager::Implementation ========================================
239
240
class ToolBarManager::Implementation
241
{
242
public:
243
    /** This constructor takes three arguments even though the
244
        ToolBarManager could be taken from the ViewShellBase.  This is so to
245
        state explicitly which information has to be present when this
246
        constructor is called.  The ViewShellBase may not have been fully
247
        initialized at this point and must not be asked for this values.
248
    */
249
    Implementation (
250
        ViewShellBase& rBase,
251
        std::shared_ptr<sdtools::EventMultiplexer> pMultiplexer,
252
        const std::shared_ptr<ViewShellManager>& rpViewShellManager,
253
        const std::shared_ptr<ToolBarManager>& rpToolBarManager);
254
    ~Implementation();
255
256
    void SetValid (bool bValid);
257
258
    void ResetToolBars (ToolBarGroup eGroup);
259
    void ResetAllToolBars();
260
    void AddToolBar (ToolBarGroup eGroup, const OUString& rsToolBarName);
261
    void AddToolBarShell (ToolBarGroup eGroup, ShellId nToolBarId);
262
    void RemoveToolBar (ToolBarGroup eGroup, const OUString& rsToolBarName);
263
264
    /** Release all tool bar shells and the associated framework tool bars.
265
        Typically called when the main view shell is being replaced by
266
        another, all tool bar shells are released.  In that process the
267
        shells are destroyed anyway and without calling this method they
268
        would still be referenced.
269
    */
270
    void ReleaseAllToolBarShells();
271
272
    void ToolBarsDestroyed();
273
274
    void RequestUpdate();
275
276
    void PreUpdate();
277
    void PostUpdate();
278
    /** Tell the XLayoutManager about the tool bars that we would like to be
279
        shown.
280
        @param rpLayouterLock
281
            This typically is the mpSynchronousLayouterLock that is used in
282
            this method and that is either released at its end or assigned
283
            to mpAsynchronousLock in order to be unlocked later.
284
    */
285
    void Update (::std::unique_ptr<LayouterLock> pLayouterLock);
286
287
    class UpdateLockImplementation
288
    {
289
    public:
290
        explicit UpdateLockImplementation (Implementation& rImplementation)
291
0
            : mrImplementation(rImplementation) { mrImplementation.LockUpdate();  }
292
0
        ~UpdateLockImplementation() { suppress_fun_call_w_exception(mrImplementation.UnlockUpdate()); }
293
    private:
294
        Implementation& mrImplementation;
295
    };
296
297
    void LockViewShellManager();
298
    void LockUpdate();
299
    void UnlockUpdate();
300
301
0
    ToolBarRules& GetToolBarRules() { return maToolBarRules;}
302
303
private:
304
    mutable ::osl::Mutex maMutex;
305
    ViewShellBase& mrBase;
306
    std::shared_ptr<sdtools::EventMultiplexer> mpEventMultiplexer;
307
    bool mbIsValid;
308
    ToolBarList maToolBarList;
309
    ToolBarShellList maToolBarShellList;
310
    Reference<frame::XLayoutManager> mxLayouter;
311
    sal_Int32 mnLockCount;
312
    bool mbPreUpdatePending;
313
    bool mbPostUpdatePending;
314
    /** The layouter locks manage the locking of the XLayoutManager.  The
315
        lock() and unlock() functions are not called directly because the
316
        (final) unlocking  is usually done asynchronously *after* the
317
        list of requested toolbars is updated.
318
    */
319
    ::std::unique_ptr<LayouterLock> mpSynchronousLayouterLock;
320
    ::std::unique_ptr<LayouterLock> mpAsynchronousLayouterLock;
321
    ::std::unique_ptr<ViewShellManager::UpdateLock, o3tl::default_delete<ViewShellManager::UpdateLock>> mpViewShellManagerLock;
322
    ImplSVEvent * mnPendingUpdateCall;
323
    ImplSVEvent * mnPendingSetValidCall;
324
    ToolBarRules maToolBarRules;
325
326
    static OUString GetToolBarResourceName (std::u16string_view rsBaseName);
327
    bool CheckPlugInMode (std::u16string_view rsName) const;
328
329
    DECL_LINK(UpdateCallback, void *, void);
330
    DECL_LINK(EventMultiplexerCallback, sdtools::EventMultiplexerEvent&, void);
331
    DECL_LINK(SetValidCallback, void*, void);
332
};
333
334
//===== ToolBarManager ========================================================
335
336
std::shared_ptr<ToolBarManager> ToolBarManager::Create (
337
    ViewShellBase& rBase,
338
    const std::shared_ptr<sdtools::EventMultiplexer>& rpMultiplexer,
339
    const std::shared_ptr<ViewShellManager>& rpViewShellManager)
340
0
{
341
0
    std::shared_ptr<ToolBarManager> pManager (new ToolBarManager());
342
0
    pManager->mpImpl.reset(
343
0
        new Implementation(rBase,rpMultiplexer,rpViewShellManager,pManager));
344
0
    return pManager;
345
0
}
346
347
ToolBarManager::ToolBarManager()
348
0
{
349
0
}
350
351
ToolBarManager::~ToolBarManager()
352
0
{
353
0
}
354
355
void ToolBarManager::Shutdown()
356
0
{
357
0
    if (mpImpl != nullptr)
358
0
        mpImpl.reset();
359
0
}
360
361
void ToolBarManager::ResetToolBars (ToolBarGroup eGroup)
362
0
{
363
0
    if (mpImpl != nullptr)
364
0
    {
365
0
        UpdateLock aLock (shared_from_this());
366
0
        mpImpl->ResetToolBars(eGroup);
367
0
    }
368
0
}
369
370
void ToolBarManager::ResetAllToolBars()
371
0
{
372
0
    if (mpImpl != nullptr)
373
0
    {
374
0
        UpdateLock aLock (shared_from_this());
375
0
        mpImpl->ResetAllToolBars();
376
0
    }
377
0
}
378
379
void ToolBarManager::AddToolBar (
380
    ToolBarGroup eGroup,
381
    const OUString& rsToolBarName)
382
0
{
383
0
    if (mpImpl != nullptr)
384
0
    {
385
0
        UpdateLock aLock (shared_from_this());
386
0
        mpImpl->AddToolBar(eGroup,rsToolBarName);
387
0
    }
388
0
}
389
390
void ToolBarManager::AddToolBarShell (
391
    ToolBarGroup eGroup,
392
    ShellId nToolBarId)
393
0
{
394
0
    if (mpImpl != nullptr)
395
0
    {
396
0
        UpdateLock aLock (shared_from_this());
397
0
        mpImpl->AddToolBarShell(eGroup,nToolBarId);
398
0
    }
399
0
}
400
401
void ToolBarManager::RemoveToolBar (
402
    ToolBarGroup eGroup,
403
    const OUString& rsToolBarName)
404
0
{
405
0
    if (mpImpl != nullptr)
406
0
    {
407
0
        UpdateLock aLock (shared_from_this());
408
0
        mpImpl->RemoveToolBar(eGroup,rsToolBarName);
409
0
    }
410
0
}
411
412
void ToolBarManager::SetToolBar (
413
    ToolBarGroup eGroup,
414
    const OUString& rsToolBarName)
415
0
{
416
0
    if (mpImpl != nullptr)
417
0
    {
418
0
        UpdateLock aLock (shared_from_this());
419
0
        mpImpl->ResetToolBars(eGroup);
420
0
        mpImpl->AddToolBar(eGroup,rsToolBarName);
421
0
    }
422
0
}
423
424
void ToolBarManager::SetToolBarShell (
425
    ToolBarGroup eGroup,
426
    ShellId nToolBarId)
427
0
{
428
0
    if (mpImpl != nullptr)
429
0
    {
430
0
        UpdateLock aLock (shared_from_this());
431
0
        mpImpl->ResetToolBars(eGroup);
432
0
        mpImpl->AddToolBarShell(eGroup,nToolBarId);
433
0
    }
434
0
}
435
436
void ToolBarManager::PreUpdate()
437
0
{
438
0
    if (mpImpl != nullptr)
439
0
        mpImpl->PreUpdate();
440
0
}
441
442
void ToolBarManager::RequestUpdate()
443
0
{
444
0
    if (mpImpl != nullptr)
445
0
        mpImpl->RequestUpdate();
446
0
}
447
448
void ToolBarManager::LockViewShellManager()
449
0
{
450
0
    if (mpImpl != nullptr)
451
0
        mpImpl->LockViewShellManager();
452
0
}
453
454
void ToolBarManager::LockUpdate()
455
0
{
456
0
    if (mpImpl != nullptr)
457
0
        mpImpl->LockUpdate();
458
0
}
459
460
void ToolBarManager::UnlockUpdate()
461
0
{
462
0
    if (mpImpl != nullptr)
463
0
        mpImpl->UnlockUpdate();
464
0
}
465
466
void ToolBarManager::MainViewShellChanged ()
467
0
{
468
0
    if (mpImpl != nullptr)
469
0
    {
470
0
        mpImpl->ReleaseAllToolBarShells();
471
0
        mpImpl->GetToolBarRules().MainViewShellChanged(ViewShell::ST_NONE);
472
0
    }
473
0
}
474
475
void ToolBarManager::MainViewShellChanged (const ViewShell& rMainViewShell)
476
0
{
477
0
    if (mpImpl != nullptr)
478
0
    {
479
0
        mpImpl->ReleaseAllToolBarShells();
480
0
        mpImpl->GetToolBarRules().MainViewShellChanged(rMainViewShell);
481
0
    }
482
0
}
483
484
void ToolBarManager::SelectionHasChanged (
485
    const ViewShell& rViewShell,
486
    const SdrView& rView)
487
0
{
488
0
    if (mpImpl != nullptr)
489
0
        mpImpl->GetToolBarRules().SelectionHasChanged(rViewShell,rView);
490
0
}
491
492
void ToolBarManager::ToolBarsDestroyed()
493
0
{
494
0
    if (mpImpl != nullptr)
495
0
        mpImpl->ToolBarsDestroyed();
496
0
}
497
498
//===== ToolBarManager::Implementation =======================================
499
500
ToolBarManager::Implementation::Implementation (
501
    ViewShellBase& rBase,
502
    std::shared_ptr<sdtools::EventMultiplexer> pMultiplexer,
503
    const std::shared_ptr<ViewShellManager>& rpViewShellManager,
504
    const std::shared_ptr<ToolBarManager>& rpToolBarManager)
505
0
    : mrBase(rBase),
506
0
      mpEventMultiplexer(std::move(pMultiplexer)),
507
0
      mbIsValid(false),
508
0
      mnLockCount(0),
509
0
      mbPreUpdatePending(false),
510
0
      mbPostUpdatePending(false),
511
0
      mnPendingUpdateCall(nullptr),
512
0
      mnPendingSetValidCall(nullptr),
513
0
      maToolBarRules(rpToolBarManager,rpViewShellManager)
514
0
{
515
0
    Link<sdtools::EventMultiplexerEvent&,void> aLink (LINK(this,ToolBarManager::Implementation,EventMultiplexerCallback));
516
0
    mpEventMultiplexer->AddEventListener( aLink );
517
0
}
518
519
/** The order of statements is important.
520
    First unregister listeners, which may post user events.
521
    Then remove pending user events.
522
*/
523
ToolBarManager::Implementation::~Implementation()
524
0
{
525
    // Unregister at broadcasters.
526
0
    Link<sdtools::EventMultiplexerEvent&,void> aLink (LINK(this,ToolBarManager::Implementation,EventMultiplexerCallback));
527
0
    mpEventMultiplexer->RemoveEventListener(aLink);
528
529
    // Abort pending user calls.
530
0
    if (mnPendingUpdateCall != nullptr)
531
0
        Application::RemoveUserEvent(mnPendingUpdateCall);
532
0
    if (mnPendingSetValidCall != nullptr)
533
0
        Application::RemoveUserEvent(mnPendingSetValidCall);
534
0
}
535
536
void ToolBarManager::Implementation::ToolBarsDestroyed()
537
0
{
538
0
    maToolBarList.MarkAllToolBarsAsNotActive();
539
0
}
540
541
void ToolBarManager::Implementation::SetValid (bool bValid)
542
0
{
543
0
    ::osl::MutexGuard aGuard(maMutex);
544
545
0
    if (mbIsValid == bValid)
546
0
        return;
547
548
0
    UpdateLockImplementation aUpdateLock (*this);
549
550
0
    mbIsValid = bValid;
551
0
    if (mbIsValid)
552
0
    {
553
0
        Reference<frame::XFrame> xFrame = mrBase.GetViewFrame().GetFrame().GetFrameInterface();
554
0
        try
555
0
        {
556
0
            Reference<beans::XPropertySet> xFrameProperties (xFrame, UNO_QUERY_THROW);
557
0
            Any aValue (xFrameProperties->getPropertyValue(u"LayoutManager"_ustr));
558
0
            aValue >>= mxLayouter;
559
            // tdf#119997 if mpSynchronousLayouterLock was created before mxLayouter was
560
            // set then update it now that its available
561
0
            if (mpSynchronousLayouterLock && !mpSynchronousLayouterLock->is())
562
0
                mpSynchronousLayouterLock.reset(new LayouterLock(mxLayouter));
563
0
        }
564
0
        catch (const RuntimeException&)
565
0
        {
566
0
        }
567
568
0
        GetToolBarRules().Update(mrBase);
569
0
    }
570
0
    else
571
0
    {
572
0
        ResetAllToolBars();
573
0
        mxLayouter = nullptr;
574
0
    }
575
0
}
576
577
void ToolBarManager::Implementation::ResetToolBars (ToolBarGroup eGroup)
578
0
{
579
0
    ::osl::MutexGuard aGuard(maMutex);
580
581
0
    maToolBarList.ClearGroup(eGroup);
582
0
    maToolBarShellList.ClearGroup(eGroup);
583
584
0
    mbPreUpdatePending = true;
585
0
}
586
587
void ToolBarManager::Implementation::ResetAllToolBars()
588
0
{
589
0
    SAL_INFO("sd.view", __func__ << ": resetting all tool bars");
590
0
    for (auto i : o3tl::enumrange<ToolBarGroup>())
591
0
        ResetToolBars(i);
592
0
}
593
594
void ToolBarManager::Implementation::AddToolBar (
595
    ToolBarGroup eGroup,
596
    const OUString& rsToolBarName)
597
0
{
598
0
    ::osl::MutexGuard aGuard(maMutex);
599
600
0
    if (CheckPlugInMode(rsToolBarName))
601
0
    {
602
0
        maToolBarList.AddToolBar(eGroup,rsToolBarName);
603
604
0
        mbPostUpdatePending = true;
605
0
        if (mnLockCount == 0)
606
0
            PostUpdate();
607
0
    }
608
0
}
609
610
void ToolBarManager::Implementation::RemoveToolBar (
611
    ToolBarGroup eGroup,
612
    const OUString& rsToolBarName)
613
0
{
614
0
    ::osl::MutexGuard aGuard(maMutex);
615
616
0
    if (maToolBarList.RemoveToolBar(eGroup,rsToolBarName))
617
0
    {
618
0
        mbPreUpdatePending = true;
619
0
        if (mnLockCount == 0)
620
0
            PreUpdate();
621
0
    }
622
0
}
623
624
void ToolBarManager::Implementation::AddToolBarShell (
625
    ToolBarGroup eGroup,
626
    ShellId nToolBarId)
627
0
{
628
0
    ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
629
0
    if (pMainViewShell != nullptr)
630
0
    {
631
0
        maToolBarShellList.AddShellId(eGroup,nToolBarId);
632
0
        GetToolBarRules().SubShellAdded(eGroup, nToolBarId);
633
0
    }
634
0
}
635
636
void ToolBarManager::Implementation::ReleaseAllToolBarShells()
637
0
{
638
0
    maToolBarShellList.ReleaseAllShells(GetToolBarRules());
639
0
    maToolBarShellList.UpdateShells(mrBase.GetMainViewShell(), mrBase.GetViewShellManager());
640
0
}
641
642
void ToolBarManager::Implementation::RequestUpdate()
643
0
{
644
0
    if (mnPendingUpdateCall == nullptr)
645
0
    {
646
0
        mnPendingUpdateCall = Application::PostUserEvent(
647
0
            LINK(this,ToolBarManager::Implementation,UpdateCallback));
648
0
    }
649
0
}
650
651
void ToolBarManager::Implementation::PreUpdate()
652
0
{
653
0
    ::osl::MutexGuard aGuard(maMutex);
654
655
0
    if (!(mbIsValid
656
0
        && mbPreUpdatePending
657
0
        && mxLayouter.is()))
658
0
        return;
659
660
0
    mbPreUpdatePending = false;
661
662
0
    SAL_INFO("sd.view", __func__ << ": ToolBarManager::PreUpdate [");
663
664
    // Get the list of tool bars that are not used anymore and are to be
665
    // deactivated.
666
0
    std::vector<OUString> aToolBars;
667
0
    maToolBarList.GetToolBarsToDeactivate(aToolBars);
668
669
    // Turn off the tool bars.
670
0
    for (const auto& aToolBar : aToolBars)
671
0
    {
672
0
        OUString sFullName (GetToolBarResourceName(aToolBar));
673
0
        SAL_INFO("sd.view", __func__ << ":    turning off tool bar " << sFullName);
674
0
        mxLayouter->destroyElement(sFullName);
675
0
        maToolBarList.MarkToolBarAsNotActive(aToolBar);
676
0
    }
677
678
0
    SAL_INFO("sd.view", __func__ << ": ToolBarManager::PreUpdate ]");
679
0
}
680
681
void ToolBarManager::Implementation::PostUpdate()
682
0
{
683
0
    ::osl::MutexGuard aGuard(maMutex);
684
685
0
    if (!(mbIsValid
686
0
        && mbPostUpdatePending
687
0
        && mxLayouter.is()))
688
0
        return;
689
690
0
    mbPostUpdatePending = false;
691
692
    // Create the list of requested tool bars.
693
0
    std::vector<OUString> aToolBars;
694
0
    maToolBarList.GetToolBarsToActivate(aToolBars);
695
696
0
    SAL_INFO("sd.view", __func__ << ": ToolBarManager::PostUpdate [");
697
698
    // Turn on the tool bars that are visible in the new context.
699
0
    for (const auto& aToolBar : aToolBars)
700
0
    {
701
0
        OUString sFullName (GetToolBarResourceName(aToolBar));
702
0
        SAL_INFO("sd.view", __func__ << ":    turning on tool bar " << sFullName);
703
0
        mxLayouter->requestElement(sFullName);
704
0
        maToolBarList.MarkToolBarAsActive(aToolBar);
705
0
    }
706
707
0
    SAL_INFO("sd.view", __func__ << ": ToolBarManager::PostUpdate ]");
708
0
}
709
710
void ToolBarManager::Implementation::LockViewShellManager()
711
0
{
712
0
    if (mpViewShellManagerLock == nullptr)
713
0
        mpViewShellManagerLock.reset(
714
0
            new ViewShellManager::UpdateLock(mrBase.GetViewShellManager()));
715
0
}
716
717
void ToolBarManager::Implementation::LockUpdate()
718
0
{
719
0
    SAL_INFO("sd.view", __func__ << ": LockUpdate " << mnLockCount);
720
0
    ::osl::MutexGuard aGuard(maMutex);
721
722
0
    DBG_ASSERT(mnLockCount<100, "ToolBarManager lock count unusually high");
723
0
    if (mnLockCount == 0)
724
0
    {
725
0
        OSL_ASSERT(mpSynchronousLayouterLock == nullptr);
726
727
0
        mpSynchronousLayouterLock.reset(new LayouterLock(mxLayouter));
728
0
    }
729
0
    ++mnLockCount;
730
0
}
731
732
void ToolBarManager::Implementation::UnlockUpdate()
733
0
{
734
0
    SAL_INFO("sd.view", __func__ << ": UnlockUpdate " << mnLockCount);
735
0
    ::osl::MutexGuard aGuard(maMutex);
736
737
0
    OSL_ASSERT(mnLockCount>0);
738
0
    --mnLockCount;
739
0
    if (mnLockCount == 0)
740
0
    {
741
0
        Update(std::move(mpSynchronousLayouterLock));
742
0
    }
743
0
}
744
745
void ToolBarManager::Implementation::Update (
746
    ::std::unique_ptr<LayouterLock> pLocalLayouterLock)
747
0
{
748
    // When the lock is released and there are pending changes to the set of
749
    // tool bars then update this set now.
750
0
    if (mnLockCount != 0)
751
0
        return;
752
753
    // During creation of ViewShellBase we may have the situation that
754
    // the controller has already been created and attached to the frame
755
    // but that the ToolBarManager has not yet completed its
756
    // initialization (by initializing the mxLayouter member.)  We do
757
    // this here so that we do not have to wait for the next Update()
758
    // call to show the tool bars.
759
0
    if (mnPendingSetValidCall != nullptr)
760
0
    {
761
0
        Application::RemoveUserEvent(mnPendingSetValidCall);
762
0
        mnPendingSetValidCall = nullptr;
763
0
        SetValid(true);
764
0
    }
765
766
0
    if (mbIsValid && mxLayouter.is() && (mbPreUpdatePending || mbPostUpdatePending))
767
0
    {
768
        // 1) Release UNO tool bars that are no longer used.  Do this
769
        // now so that they are not updated when the SFX shell stack is
770
        // modified.
771
0
        if (mbPreUpdatePending)
772
0
            PreUpdate();
773
774
        // 2) Update the requested shells that represent tool bar
775
        // functionality. Those that are not used anymore are
776
        // deactivated now.  Those that are missing are activated in the
777
        // next step together with the view shells.
778
0
        if (mpViewShellManagerLock == nullptr)
779
0
            mpViewShellManagerLock.reset(
780
0
                new ViewShellManager::UpdateLock(mrBase.GetViewShellManager()));
781
0
        maToolBarShellList.UpdateShells(
782
0
            mrBase.GetMainViewShell(),
783
0
            mrBase.GetViewShellManager());
784
785
        // 3) Unlock the ViewShellManager::UpdateLock.  This updates the
786
        // shell stack.
787
0
        mpViewShellManagerLock.reset();
788
789
        // 4) Make the UNO tool bars visible.  The outstanding call to
790
        // PostUpdate() is done via PostUserEvent() so that it is
791
        // guaranteed to be executed when the SFX shell stack has been
792
        // updated (under the assumption that our lock to the
793
        // ViewShellManager was the only one open.  If that is not the
794
        // case then all should still be well but not as fast.)
795
796
        // Note that the lock count may have been increased since
797
        // entering this method.  In that case one of the next
798
        // UnlockUpdate() calls will post the UpdateCallback.
799
0
        if (mnLockCount==0)
800
0
        {
801
0
            mpAsynchronousLayouterLock = std::move(pLocalLayouterLock);
802
0
            if (mnPendingUpdateCall==nullptr)
803
0
            {
804
0
                mnPendingUpdateCall = Application::PostUserEvent(
805
0
                    LINK(this,ToolBarManager::Implementation,UpdateCallback));
806
0
            }
807
0
        }
808
0
    }
809
0
    else
810
0
    {
811
0
        mpViewShellManagerLock.reset();
812
0
        pLocalLayouterLock.reset();
813
0
    }
814
0
}
815
816
IMPL_LINK_NOARG(ToolBarManager::Implementation, UpdateCallback, void*, void)
817
0
{
818
0
    mnPendingUpdateCall = nullptr;
819
0
    if (mnLockCount == 0)
820
0
    {
821
0
        if (mbPreUpdatePending)
822
0
            PreUpdate();
823
0
        if (mbPostUpdatePending)
824
0
            PostUpdate();
825
0
        if (mbIsValid && mxLayouter.is())
826
0
            mpAsynchronousLayouterLock.reset();
827
0
    }
828
0
}
829
830
IMPL_LINK(ToolBarManager::Implementation,EventMultiplexerCallback,
831
    sdtools::EventMultiplexerEvent&, rEvent, void)
832
0
{
833
0
    SolarMutexGuard g;
834
0
    switch (rEvent.meEventId)
835
0
    {
836
0
        case EventMultiplexerEventId::ControllerAttached:
837
0
            if (mnPendingSetValidCall == nullptr)
838
0
                mnPendingSetValidCall
839
0
                    = Application::PostUserEvent(LINK(this,Implementation,SetValidCallback));
840
0
            break;
841
842
0
        case EventMultiplexerEventId::ControllerDetached:
843
0
            SetValid(false);
844
0
            break;
845
846
0
        default: break;
847
0
    }
848
0
}
849
850
IMPL_LINK_NOARG(ToolBarManager::Implementation, SetValidCallback, void*, void)
851
0
{
852
0
    mnPendingSetValidCall = nullptr;
853
0
    SetValid(true);
854
0
}
855
856
OUString ToolBarManager::Implementation::GetToolBarResourceName (
857
    std::u16string_view rsBaseName)
858
0
{
859
0
    return OUString::Concat("private:resource/toolbar/") + rsBaseName;
860
0
}
861
862
bool ToolBarManager::Implementation::CheckPlugInMode (std::u16string_view rsName) const
863
0
{
864
0
    bool bValid (false);
865
866
    // Determine the plug in mode.
867
0
    bool bIsPlugInMode (false);
868
0
    do
869
0
    {
870
0
        SfxObjectShell* pObjectShell = mrBase.GetObjectShell();
871
0
        if (pObjectShell == nullptr)
872
0
            break;
873
874
0
        SfxMedium* pMedium = pObjectShell->GetMedium();
875
0
        if (pMedium == nullptr)
876
0
            break;
877
878
0
        const SfxBoolItem* pViewOnlyItem = pMedium->GetItemSet().GetItem(SID_VIEWONLY, false);
879
0
        if (pViewOnlyItem == nullptr)
880
0
            break;
881
882
0
        bIsPlugInMode = pViewOnlyItem->GetValue();
883
0
    }
884
0
    while (false);
885
886
0
    if (rsName == msViewerToolBar)
887
0
        bValid = bIsPlugInMode;
888
0
    else
889
0
        bValid = ! bIsPlugInMode;
890
891
0
    return bValid;
892
0
}
893
894
} // end of namespace sd
895
896
namespace {
897
898
using namespace ::sd;
899
900
//===== LayouterLock ==========================================================
901
902
LayouterLock::LayouterLock (const Reference<frame::XLayoutManager>& rxLayouter)
903
0
    : mxLayouter(rxLayouter)
904
0
{
905
0
    SAL_INFO("sd.view", __func__ << ": LayouterLock " << (mxLayouter.is() ? 1 :0));
906
0
    if (mxLayouter.is())
907
0
        mxLayouter->lock();
908
0
}
909
910
LayouterLock::~LayouterLock()
911
0
{
912
0
    SAL_INFO("sd.view", __func__ << ": ~LayouterLock " << (mxLayouter.is() ? 1 :0));
913
0
    if (mxLayouter.is())
914
0
        mxLayouter->unlock();
915
0
}
916
917
//===== ToolBarRules ==========================================================
918
919
ToolBarRules::ToolBarRules (
920
    std::shared_ptr<sd::ToolBarManager> pToolBarManager,
921
    std::shared_ptr<sd::ViewShellManager> pViewShellManager)
922
0
    : mpToolBarManager(std::move(pToolBarManager)),
923
0
      mpViewShellManager(std::move(pViewShellManager))
924
0
{
925
0
}
926
927
void ToolBarRules::Update (ViewShellBase const & rBase)
928
0
{
929
0
    ViewShell* pMainViewShell = rBase.GetMainViewShell().get();
930
0
    if (pMainViewShell != nullptr)
931
0
    {
932
0
        MainViewShellChanged(pMainViewShell->GetShellType());
933
0
        if (pMainViewShell->GetView())
934
0
            SelectionHasChanged (*pMainViewShell, *pMainViewShell->GetView());
935
0
    }
936
0
    else
937
0
        MainViewShellChanged(ViewShell::ST_NONE);
938
0
}
939
940
void ToolBarRules::MainViewShellChanged (ViewShell::ShellType nShellType)
941
0
{
942
0
    ::sd::ToolBarManager::UpdateLock aToolBarManagerLock (mpToolBarManager);
943
0
    ::sd::ViewShellManager::UpdateLock aViewShellManagerLock (mpViewShellManager);
944
945
0
    mpToolBarManager->ResetAllToolBars();
946
947
0
    switch(nShellType)
948
0
    {
949
0
        case ::sd::ViewShell::ST_IMPRESS:
950
0
        case ::sd::ViewShell::ST_NOTES:
951
0
        case ::sd::ViewShell::ST_HANDOUT:
952
0
        case ::sd::ViewShell::ST_DRAW:
953
0
            mpToolBarManager->AddToolBar(
954
0
                ToolBarManager::ToolBarGroup::Permanent,
955
0
                ToolBarManager::msToolBar);
956
0
            mpToolBarManager->AddToolBar(
957
0
                ToolBarManager::ToolBarGroup::Permanent,
958
0
                ToolBarManager::msOptionsToolBar);
959
0
            mpToolBarManager->AddToolBar(
960
0
                ToolBarManager::ToolBarGroup::Permanent,
961
0
                ToolBarManager::msViewerToolBar);
962
0
            break;
963
964
0
        case ::sd::ViewShell::ST_NOTESPANEL:
965
0
            mpToolBarManager->AddToolBarShell(ToolBarManager::ToolBarGroup::Permanent,
966
0
                                              ToolbarId::Draw_Text_Toolbox_Sd);
967
0
            break;
968
969
0
        case ViewShell::ST_OUTLINE:
970
0
            mpToolBarManager->AddToolBar(
971
0
                ToolBarManager::ToolBarGroup::Permanent,
972
0
                ToolBarManager::msOutlineToolBar);
973
0
            mpToolBarManager->AddToolBar(
974
0
                ToolBarManager::ToolBarGroup::Permanent,
975
0
                ToolBarManager::msViewerToolBar);
976
0
            mpToolBarManager->AddToolBarShell(
977
0
                ToolBarManager::ToolBarGroup::Permanent, ToolbarId::Draw_Text_Toolbox_Sd);
978
0
            break;
979
980
0
        case ViewShell::ST_SLIDE_SORTER:
981
0
            mpToolBarManager->AddToolBar(
982
0
                ToolBarManager::ToolBarGroup::Permanent,
983
0
                ToolBarManager::msViewerToolBar);
984
0
            mpToolBarManager->AddToolBar(
985
0
                ToolBarManager::ToolBarGroup::Permanent,
986
0
                ToolBarManager::msSlideSorterToolBar);
987
0
            mpToolBarManager->AddToolBar(
988
0
                ToolBarManager::ToolBarGroup::Permanent,
989
0
                ToolBarManager::msSlideSorterObjectBar);
990
0
            break;
991
992
0
        case ViewShell::ST_NONE:
993
0
        case ViewShell::ST_PRESENTATION:
994
0
        case ViewShell::ST_SIDEBAR:
995
0
        default:
996
0
            break;
997
0
    }
998
0
}
999
1000
void ToolBarRules::MainViewShellChanged (const ViewShell& rMainViewShell)
1001
0
{
1002
0
    ::sd::ToolBarManager::UpdateLock aToolBarManagerLock (mpToolBarManager);
1003
0
    ::sd::ViewShellManager::UpdateLock aViewShellManagerLock (mpViewShellManager);
1004
1005
0
    MainViewShellChanged(rMainViewShell.GetShellType());
1006
0
    switch(rMainViewShell.GetShellType())
1007
0
    {
1008
0
        case ::sd::ViewShell::ST_IMPRESS:
1009
0
        case ::sd::ViewShell::ST_DRAW:
1010
0
        case ::sd::ViewShell::ST_NOTES:
1011
0
        {
1012
0
            const DrawViewShell* pDrawViewShell
1013
0
                = dynamic_cast<const DrawViewShell*>(&rMainViewShell);
1014
0
            if (pDrawViewShell != nullptr)
1015
0
            {
1016
0
                if (pDrawViewShell->GetEditMode() == EditMode::MasterPage)
1017
0
                    mpToolBarManager->AddToolBar(
1018
0
                        ToolBarManager::ToolBarGroup::MasterMode,
1019
0
                        ToolBarManager::msMasterViewToolBar);
1020
0
                else if ( rMainViewShell.GetShellType() != ::sd::ViewShell::ST_DRAW )
1021
0
                    mpToolBarManager->AddToolBar(
1022
0
                        ToolBarManager::ToolBarGroup::CommonTask,
1023
0
                        ToolBarManager::msCommonTaskToolBar);
1024
0
            }
1025
0
            break;
1026
0
        }
1027
1028
0
        default:
1029
0
            break;
1030
0
    }
1031
0
}
1032
1033
void ToolBarRules::SelectionHasChanged (
1034
    const ::sd::ViewShell& rViewShell,
1035
    const SdrView& rView)
1036
0
{
1037
0
    ::sd::ToolBarManager::UpdateLock aLock (mpToolBarManager);
1038
0
    mpToolBarManager->LockViewShellManager();
1039
0
    bool bTextEdit = rView.IsTextEdit();
1040
1041
0
    mpToolBarManager->ResetToolBars(ToolBarManager::ToolBarGroup::Function);
1042
1043
0
    switch (rView.GetContext())
1044
0
    {
1045
0
        case SdrViewContext::Graphic:
1046
0
            if (!bTextEdit)
1047
0
                mpToolBarManager->SetToolBarShell(ToolBarManager::ToolBarGroup::Function,
1048
0
                                                  ToolbarId::Draw_Graf_Toolbox);
1049
0
            break;
1050
1051
0
        case SdrViewContext::Media:
1052
0
            if (!bTextEdit)
1053
0
                mpToolBarManager->SetToolBarShell(ToolBarManager::ToolBarGroup::Function,
1054
0
                                                  ToolbarId::Draw_Media_Toolbox);
1055
0
            break;
1056
1057
0
        case SdrViewContext::Table:
1058
0
            mpToolBarManager->SetToolBarShell(ToolBarManager::ToolBarGroup::Function,
1059
0
                                              ToolbarId::Draw_Table_Toolbox);
1060
0
            bTextEdit = true;
1061
0
            break;
1062
1063
0
        case SdrViewContext::Standard:
1064
0
        default:
1065
0
            if (!bTextEdit)
1066
0
            {
1067
0
                switch(rViewShell.GetShellType())
1068
0
                {
1069
0
                    case ::sd::ViewShell::ST_IMPRESS:
1070
0
                    case ::sd::ViewShell::ST_DRAW:
1071
0
                    case ::sd::ViewShell::ST_NOTES:
1072
0
                    case ::sd::ViewShell::ST_HANDOUT:
1073
0
                        mpToolBarManager->SetToolBar(ToolBarManager::ToolBarGroup::Function,
1074
0
                                                     ToolBarManager::msDrawingObjectToolBar);
1075
0
                        mpToolBarManager->SetToolBar(ToolBarManager::ToolBarGroup::Permanent,
1076
0
                                                     ToolBarManager::msToolBar);
1077
0
                        break;
1078
0
                    default:
1079
0
                        break;
1080
0
                }
1081
0
                break;
1082
0
            }
1083
0
    }
1084
1085
0
    if( bTextEdit )
1086
0
        mpToolBarManager->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Text_Toolbox_Sd);
1087
1088
0
    SdrView* pView = &const_cast<SdrView&>(rView);
1089
    // Check if the extrusion tool bar and the fontwork tool bar have to
1090
    // be activated.
1091
0
    if (svx::checkForSelectedCustomShapes(pView, true /* bOnlyExtruded */ ))
1092
0
        mpToolBarManager->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Svx_Extrusion_Bar);
1093
1094
0
    if (svx::checkForSelectedFontWork(pView))
1095
0
        mpToolBarManager->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Svx_Fontwork_Bar);
1096
1097
    // Switch on additional context-sensitive tool bars.
1098
0
    if (rView.GetContext() == SdrViewContext::PointEdit)
1099
0
        mpToolBarManager->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Bezier_Toolbox_Sd);
1100
0
}
1101
1102
void ToolBarRules::SubShellAdded (
1103
    ::sd::ToolBarManager::ToolBarGroup eGroup,
1104
    sd::ShellId nShellId)
1105
0
{
1106
    // For some tool bar shells (those defined in sd) we have to add the
1107
    // actual tool bar here.
1108
0
    switch (nShellId)
1109
0
    {
1110
0
        case ToolbarId::Draw_Graf_Toolbox:
1111
0
            mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msGraphicObjectBar);
1112
0
            break;
1113
1114
0
        case ToolbarId::Draw_Media_Toolbox:
1115
0
            mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msMediaObjectBar);
1116
0
            break;
1117
1118
0
        case ToolbarId::Draw_Text_Toolbox_Sd:
1119
0
            mpToolBarManager->RemoveToolBar(ToolBarManager::ToolBarGroup::Permanent, ToolBarManager::msToolBar);
1120
0
            mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msTextObjectBar);
1121
0
            break;
1122
1123
0
        case ToolbarId::Bezier_Toolbox_Sd:
1124
0
            mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msBezierObjectBar);
1125
0
            break;
1126
1127
0
        case ToolbarId::Draw_Table_Toolbox:
1128
            // tdf#142489 Do not show the table toolbar when the Notebookbar UI is active
1129
0
            if (!sfx2::SfxNotebookBar::IsActive(true))
1130
0
                mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msTableObjectBar);
1131
0
            break;
1132
1133
0
        default:
1134
0
            break;
1135
0
    }
1136
0
}
1137
1138
void ToolBarRules::SubShellRemoved (
1139
    ::sd::ToolBarManager::ToolBarGroup eGroup,
1140
    sd::ShellId nShellId)
1141
0
{
1142
    // For some tool bar shells (those defined in sd) we have to add the
1143
    // actual tool bar here.
1144
0
    switch (nShellId)
1145
0
    {
1146
0
        case ToolbarId::Draw_Graf_Toolbox:
1147
0
            mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msGraphicObjectBar);
1148
0
            break;
1149
1150
0
        case ToolbarId::Draw_Media_Toolbox:
1151
0
            mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msMediaObjectBar);
1152
0
            break;
1153
1154
0
        case ToolbarId::Draw_Text_Toolbox_Sd:
1155
0
            mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msTextObjectBar);
1156
0
            break;
1157
1158
0
        case ToolbarId::Bezier_Toolbox_Sd:
1159
0
            mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msBezierObjectBar);
1160
0
            break;
1161
1162
0
        case ToolbarId::Draw_Table_Toolbox:
1163
0
            mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msTableObjectBar);
1164
0
            break;
1165
1166
0
        default:
1167
0
            break;
1168
0
    }
1169
0
}
1170
1171
//===== ToolBarList ===========================================================
1172
1173
ToolBarList::ToolBarList()
1174
0
{
1175
0
}
1176
1177
void ToolBarList::ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup)
1178
0
{
1179
0
    Groups::iterator iGroup (maGroups.find(eGroup));
1180
0
    if (iGroup != maGroups.end())
1181
0
    {
1182
0
        iGroup->second.clear();
1183
0
    }
1184
0
}
1185
1186
void ToolBarList::AddToolBar (
1187
    sd::ToolBarManager::ToolBarGroup eGroup,
1188
    const OUString& rsName)
1189
0
{
1190
0
    Groups::iterator iGroup (maGroups.find(eGroup));
1191
0
    if (iGroup == maGroups.end())
1192
0
        iGroup = maGroups.emplace(eGroup,std::vector<OUString>()).first;
1193
1194
0
    if (iGroup != maGroups.end())
1195
0
    {
1196
0
        auto iBar (std::find(iGroup->second.cbegin(),iGroup->second.cend(),rsName));
1197
0
        if (iBar == iGroup->second.cend())
1198
0
        {
1199
0
            iGroup->second.push_back(rsName);
1200
0
        }
1201
0
    }
1202
0
}
1203
1204
bool ToolBarList::RemoveToolBar (
1205
    sd::ToolBarManager::ToolBarGroup eGroup,
1206
    const OUString& rsName)
1207
0
{
1208
0
    Groups::iterator iGroup (maGroups.find(eGroup));
1209
0
    if (iGroup != maGroups.end())
1210
0
    {
1211
0
        auto iBar (std::find(iGroup->second.begin(),iGroup->second.end(),rsName));
1212
0
        if (iBar != iGroup->second.end())
1213
0
        {
1214
0
            iGroup->second.erase(iBar);
1215
0
            return true;
1216
0
        }
1217
0
    }
1218
0
    return false;
1219
0
}
1220
1221
void ToolBarList::MakeRequestedToolBarList (std::vector<OUString>& rRequestedToolBars) const
1222
0
{
1223
0
    for (auto eGroup : o3tl::enumrange<sd::ToolBarManager::ToolBarGroup>())
1224
0
    {
1225
0
        Groups::const_iterator iGroup (maGroups.find(eGroup));
1226
0
        if (iGroup != maGroups.end())
1227
0
            rRequestedToolBars.insert( rRequestedToolBars.end(),
1228
0
                iGroup->second.begin(),
1229
0
                iGroup->second.end() );
1230
0
    }
1231
0
}
1232
1233
void ToolBarList::GetToolBarsToActivate (std::vector<OUString>& rToolBars) const
1234
0
{
1235
0
    std::vector<OUString> aRequestedToolBars;
1236
0
    MakeRequestedToolBarList(aRequestedToolBars);
1237
1238
0
    for (const auto& aToolBar : aRequestedToolBars)
1239
0
    {
1240
0
        if (::std::find(maActiveToolBars.begin(),maActiveToolBars.end(),aToolBar)
1241
0
            == maActiveToolBars.end())
1242
0
        {
1243
0
            rToolBars.push_back(aToolBar);
1244
0
        }
1245
0
    }
1246
0
}
1247
1248
void ToolBarList::GetToolBarsToDeactivate (std::vector<OUString>& rToolBars) const
1249
0
{
1250
0
    std::vector<OUString> aRequestedToolBars;
1251
0
    MakeRequestedToolBarList(aRequestedToolBars);
1252
1253
0
    for (auto& aToolBar : maActiveToolBars)
1254
0
    {
1255
0
        if (::std::find(aRequestedToolBars.begin(),aRequestedToolBars.end(),aToolBar)
1256
0
            == aRequestedToolBars.end())
1257
0
        {
1258
0
            rToolBars.push_back(aToolBar);
1259
0
        }
1260
0
    }
1261
0
}
1262
1263
void ToolBarList::MarkToolBarAsActive (const OUString& rsName)
1264
0
{
1265
0
    maActiveToolBars.push_back(rsName);
1266
0
}
1267
1268
void ToolBarList::MarkToolBarAsNotActive (const OUString& rsName)
1269
0
{
1270
0
    maActiveToolBars.erase(
1271
0
        ::std::find(maActiveToolBars.begin(),maActiveToolBars.end(), rsName));
1272
0
}
1273
1274
void ToolBarList::MarkAllToolBarsAsNotActive()
1275
0
{
1276
0
    maActiveToolBars.clear();
1277
0
}
1278
1279
//===== ToolBarShellList ======================================================
1280
1281
ToolBarShellList::ShellDescriptor::ShellDescriptor (
1282
    ShellId nId,
1283
    sd::ToolBarManager::ToolBarGroup eGroup)
1284
0
    : mnId(nId),
1285
0
      meGroup(eGroup)
1286
0
{
1287
0
}
1288
1289
ToolBarShellList::ToolBarShellList()
1290
0
{
1291
0
}
1292
1293
void ToolBarShellList::ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup)
1294
0
{
1295
0
    for (GroupedShellList::iterator iDescriptor = maNewList.begin(); iDescriptor != maNewList.end(); )
1296
0
        if (iDescriptor->meGroup == eGroup)
1297
0
            iDescriptor = maNewList.erase(iDescriptor);
1298
0
        else
1299
0
            ++iDescriptor;
1300
0
}
1301
1302
void ToolBarShellList::AddShellId (sd::ToolBarManager::ToolBarGroup eGroup, sd::ShellId nId)
1303
0
{
1304
    // Make sure that the shell is not added twice (and possibly in
1305
    // different groups.)
1306
0
    ShellDescriptor aDescriptor (nId,eGroup);
1307
0
    GroupedShellList::iterator iDescriptor (maNewList.find(aDescriptor));
1308
0
    if (iDescriptor != maNewList.end())
1309
0
    {
1310
        // The shell is already requested.
1311
0
        if (iDescriptor->meGroup != eGroup)
1312
0
        {
1313
            // It is now being requested for another group.
1314
            // (Is this an error?)
1315
            // Move it to that group.
1316
0
            maNewList.erase(iDescriptor);
1317
0
            maNewList.insert(aDescriptor);
1318
0
        }
1319
        // else nothing to do.
1320
0
    }
1321
0
    else
1322
0
        maNewList.insert(aDescriptor);
1323
0
}
1324
1325
void ToolBarShellList::ReleaseAllShells (ToolBarRules& rRules)
1326
0
{
1327
    // Release the currently active tool bars.
1328
0
    GroupedShellList aList (maCurrentList);
1329
0
    for (const auto& rDescriptor : aList)
1330
0
    {
1331
0
        rRules.SubShellRemoved(rDescriptor.meGroup, rDescriptor.mnId);
1332
0
    }
1333
1334
    // Clear the list of requested tool bars.
1335
0
    maNewList.clear();
1336
0
}
1337
1338
void ToolBarShellList::UpdateShells (
1339
    const std::shared_ptr<ViewShell>& rpMainViewShell,
1340
    const std::shared_ptr<ViewShellManager>& rpManager)
1341
0
{
1342
0
    if (rpMainViewShell == nullptr)
1343
0
        return;
1344
1345
0
    const std::shared_ptr<ViewShell> pCurrentMainViewShell
1346
0
        = rpManager->GetOverridingMainShell() ? rpManager->GetOverridingMainShell() : rpMainViewShell;
1347
1348
0
    GroupedShellList aList;
1349
1350
    // Deactivate shells that are in maCurrentList, but not in
1351
    // maNewList.
1352
0
    ::std::set_difference(maCurrentList.begin(), maCurrentList.end(),
1353
0
        maNewList.begin(), maNewList.end(),
1354
0
        std::insert_iterator<GroupedShellList>(aList,aList.begin()));
1355
0
    for (const auto& rShell : aList)
1356
0
    {
1357
0
        SAL_INFO("sd.view", __func__ << ": deactivating tool bar shell " << static_cast<sal_uInt32>(rShell.mnId));
1358
0
        rpManager->DeactivateSubShell(*pCurrentMainViewShell, rShell.mnId);
1359
0
    }
1360
1361
    // Activate shells that are in maNewList, but not in
1362
    // maCurrentList.
1363
0
    aList.clear();
1364
0
    ::std::set_difference(maNewList.begin(), maNewList.end(),
1365
0
        maCurrentList.begin(), maCurrentList.end(),
1366
0
        std::insert_iterator<GroupedShellList>(aList,aList.begin()));
1367
0
    for (const auto& rShell : aList)
1368
0
    {
1369
0
        SAL_INFO("sd.view", __func__ << ": activating tool bar shell " << static_cast<sal_uInt32>(rShell.mnId));
1370
0
        rpManager->ActivateSubShell(*pCurrentMainViewShell, rShell.mnId);
1371
0
    }
1372
1373
    // The maNewList now reflects the current state and thus is made
1374
    // maCurrentList.
1375
0
    maCurrentList = maNewList;
1376
0
}
1377
1378
} // end of anonymous namespace
1379
1380
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */