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