1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <ToolBarManager.hxx>
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>
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>
44 #include <vcl/svapp.hxx>
45 #include <osl/diagnose.h>
49 #include <string_view>
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::uno
;
61 /** Lock of the frame::XLayoutManager.
65 Reference
<frame::XLayoutManager
> mxLayouter
;
67 explicit LayouterLock (const Reference
<frame::XLayoutManager
>& rxLayouter
);
69 bool is() const { return mxLayouter
.is(); }
72 /** Store a list of tool bars for each of the tool bar groups. From
73 this the list of requested tool bars is built.
80 void ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
);
81 void AddToolBar (sd::ToolBarManager::ToolBarGroup eGroup
, const OUString
& rsName
);
82 bool RemoveToolBar (sd::ToolBarManager::ToolBarGroup eGroup
, const OUString
& rsName
);
84 void GetToolBarsToActivate (std::vector
<OUString
>& rToolBars
) const;
85 void GetToolBarsToDeactivate (std::vector
<OUString
>& rToolBars
) const;
87 void MarkToolBarAsActive (const OUString
& rsName
);
88 void MarkToolBarAsNotActive (const OUString
& rsName
);
89 void MarkAllToolBarsAsNotActive();
92 typedef ::std::map
<sd::ToolBarManager::ToolBarGroup
, std::vector
<OUString
> > Groups
;
94 std::vector
<OUString
> maActiveToolBars
;
96 void MakeRequestedToolBarList (std::vector
<OUString
>& rToolBars
) const;
99 /** Manage tool bars that are implemented as sub shells of a view shell.
100 The typical procedure of updating the sub shells of a view shell is to
101 rebuild a list of sub shells that the caller would like to have active.
102 The methods ClearGroup() and AddShellId() allow the caller to do that. A
103 final call to UpdateShells() activates the requested shells that are not
104 active and deactivates the active shells that are not requested .
106 This is done by maintaining two lists. One (the current list)
107 reflects the current state. The other (the requested list) contains the
108 currently requested shells. UpdateShells() makes the requested
109 list the current list and clears the current list.
111 Each shell belongs to one group. Different groups can be modified
114 class ToolBarShellList
117 /** Create a new object with an empty current list and an empty
122 /** Remove all shells from a group. Calling this method should normally
123 not be necessary because after the construction or after a call to
124 UpdateShells() the requested list is empty.
126 The group to clear. Shells in other groups are not modified.
128 void ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
);
130 /** Add a shell. When the specified shell has already been requested
131 for another group then it is moved to this group.
133 The group to which to add the shell.
135 The id of the shell to add.
137 void AddShellId (sd::ToolBarManager::ToolBarGroup eGroup
, sd::ShellId nId
);
139 /** Releasing all shells means that the given ToolBarRules object is
140 informed that every shell managed by the called ToolBarShellList is
141 about to be removed and that the associated framework tool bars can
142 be removed as well. The caller still has to call UpdateShells().
144 void ReleaseAllShells (ToolBarRules
& rRules
);
146 /** The requested list is made the current list by activating all
147 shells in the requested list and by deactivating the shells in the
148 current list that are not in the requested list.
149 @param pMainViewShell
150 The shells that are activated or deactivated are sub shells of
153 This ViewShellManager is used to activate or deactivate shells.
156 const std::shared_ptr
<ViewShell
>& rpMainViewShell
,
157 const std::shared_ptr
<ViewShellManager
>& rpManager
);
160 class ShellDescriptor
162 ShellDescriptor (ShellId nId
,sd::ToolBarManager::ToolBarGroup eGroup
);
164 sd::ToolBarManager::ToolBarGroup meGroup
;
165 friend bool operator<(const ShellDescriptor
& r1
, const ShellDescriptor
& r2
)
166 { return r1
.mnId
< r2
.mnId
; }
169 /** The requested list of tool bar shells that will be active after the
170 next call to UpdateShells().
172 typedef ::std::set
<ShellDescriptor
> GroupedShellList
;
173 GroupedShellList maNewList
;
175 /** The list of tool bar shells that are currently on the shell stack.
176 Using a GroupedShellList is not strictly necessary but it makes
177 things easier and does not waste too much memory.
179 GroupedShellList maCurrentList
;
182 /** This class concentrates the knowledge about when to show what tool bars
189 std::shared_ptr
<ToolBarManager
> pToolBarManager
,
190 std::shared_ptr
<ViewShellManager
> pViewShellManager
);
192 /** This method calls MainViewShellChanged() and SelectionHasChanged()
193 for the current main view shell and its view.
195 void Update (ViewShellBase
const & rBase
);
197 /** Reset all tool bars in all groups and add tool bars and tool bar
198 shells to the ToolBarGroup::Permanent group for the specified ViewShell type.
200 void MainViewShellChanged (ViewShell::ShellType nShellType
);
202 /** Reset all tool bars in all groups and add tool bars and tool bar
203 shells to the ToolBarGroup::Permanent group for the specified ViewShell.
205 void MainViewShellChanged (const ViewShell
& rMainViewShell
);
207 /** Reset all tool bars in the ToolBarGroup::Function group and add tool bars and tool bar
208 shells to this group for the current selection.
210 void SelectionHasChanged (
211 const ::sd::ViewShell
& rViewShell
,
212 const SdrView
& rView
);
214 /** Add a tool bar for the specified tool bar shell.
217 ::sd::ToolBarManager::ToolBarGroup eGroup
,
218 sd::ShellId nShellId
);
220 /** Remove a tool bar for the specified tool bar shell.
222 void SubShellRemoved (
223 ::sd::ToolBarManager::ToolBarGroup eGroup
,
224 sd::ShellId nShellId
);
227 std::shared_ptr
<ToolBarManager
> mpToolBarManager
;
228 std::shared_ptr
<ViewShellManager
> mpViewShellManager
;
231 } // end of anonymous namespace
235 //===== ToolBarManager::Implementation ========================================
237 class ToolBarManager::Implementation
240 /** This constructor takes three arguments even though the
241 ToolBarManager could be taken from the ViewShellBase. This is so to
242 state explicitly which information has to be present when this
243 constructor is called. The ViewShellBase may not have been fully
244 initialized at this point and must not be asked for this values.
247 ViewShellBase
& rBase
,
248 std::shared_ptr
<sd::tools::EventMultiplexer
> pMultiplexer
,
249 const std::shared_ptr
<ViewShellManager
>& rpViewShellManager
,
250 const std::shared_ptr
<ToolBarManager
>& rpToolBarManager
);
253 void SetValid (bool bValid
);
255 void ResetToolBars (ToolBarGroup eGroup
);
256 void ResetAllToolBars();
257 void AddToolBar (ToolBarGroup eGroup
, const OUString
& rsToolBarName
);
258 void AddToolBarShell (ToolBarGroup eGroup
, ShellId nToolBarId
);
259 void RemoveToolBar (ToolBarGroup eGroup
, const OUString
& rsToolBarName
);
261 /** Release all tool bar shells and the associated framework tool bars.
262 Typically called when the main view shell is being replaced by
263 another, all tool bar shells are released. In that process the
264 shells are destroyed anyway and without calling this method they
265 would still be referenced.
267 void ReleaseAllToolBarShells();
269 void ToolBarsDestroyed();
271 void RequestUpdate();
275 /** Tell the XLayoutManager about the tool bars that we would like to be
277 @param rpLayouterLock
278 This typically is the mpSynchronousLayouterLock that is used in
279 this method and that is either released at its end or assigned
280 to mpAsynchronousLock in order to be unlocked later.
282 void Update (::std::unique_ptr
<LayouterLock
> pLayouterLock
);
284 class UpdateLockImplementation
287 explicit UpdateLockImplementation (Implementation
& rImplementation
)
288 : mrImplementation(rImplementation
) { mrImplementation
.LockUpdate(); }
289 ~UpdateLockImplementation() { mrImplementation
.UnlockUpdate(); }
291 Implementation
& mrImplementation
;
294 void LockViewShellManager();
298 ToolBarRules
& GetToolBarRules() { return maToolBarRules
;}
301 mutable ::osl::Mutex maMutex
;
302 ViewShellBase
& mrBase
;
303 std::shared_ptr
<sd::tools::EventMultiplexer
> mpEventMultiplexer
;
305 ToolBarList maToolBarList
;
306 ToolBarShellList maToolBarShellList
;
307 Reference
<frame::XLayoutManager
> mxLayouter
;
308 sal_Int32 mnLockCount
;
309 bool mbPreUpdatePending
;
310 bool mbPostUpdatePending
;
311 /** The layouter locks manage the locking of the XLayoutManager. The
312 lock() and unlock() functions are not called directly because the
313 (final) unlocking is usually done asynchronously *after* the
314 list of requested toolbars is updated.
316 ::std::unique_ptr
<LayouterLock
> mpSynchronousLayouterLock
;
317 ::std::unique_ptr
<LayouterLock
> mpAsynchronousLayouterLock
;
318 ::std::unique_ptr
<ViewShellManager::UpdateLock
, o3tl::default_delete
<ViewShellManager::UpdateLock
>> mpViewShellManagerLock
;
319 ImplSVEvent
* mnPendingUpdateCall
;
320 ImplSVEvent
* mnPendingSetValidCall
;
321 ToolBarRules maToolBarRules
;
323 static OUString
GetToolBarResourceName (std::u16string_view rsBaseName
);
324 bool CheckPlugInMode (std::u16string_view rsName
) const;
326 DECL_LINK(UpdateCallback
, void *, void);
327 DECL_LINK(EventMultiplexerCallback
, sd::tools::EventMultiplexerEvent
&, void);
328 DECL_LINK(SetValidCallback
, void*, void);
331 //===== ToolBarManager ========================================================
333 std::shared_ptr
<ToolBarManager
> ToolBarManager::Create (
334 ViewShellBase
& rBase
,
335 const std::shared_ptr
<sd::tools::EventMultiplexer
>& rpMultiplexer
,
336 const std::shared_ptr
<ViewShellManager
>& rpViewShellManager
)
338 std::shared_ptr
<ToolBarManager
> pManager (new ToolBarManager());
339 pManager
->mpImpl
.reset(
340 new Implementation(rBase
,rpMultiplexer
,rpViewShellManager
,pManager
));
344 ToolBarManager::ToolBarManager()
348 ToolBarManager::~ToolBarManager()
352 void ToolBarManager::Shutdown()
354 if (mpImpl
!= nullptr)
358 void ToolBarManager::ResetToolBars (ToolBarGroup eGroup
)
360 if (mpImpl
!= nullptr)
362 UpdateLock
aLock (shared_from_this());
363 mpImpl
->ResetToolBars(eGroup
);
367 void ToolBarManager::ResetAllToolBars()
369 if (mpImpl
!= nullptr)
371 UpdateLock
aLock (shared_from_this());
372 mpImpl
->ResetAllToolBars();
376 void ToolBarManager::AddToolBar (
378 const OUString
& rsToolBarName
)
380 if (mpImpl
!= nullptr)
382 UpdateLock
aLock (shared_from_this());
383 mpImpl
->AddToolBar(eGroup
,rsToolBarName
);
387 void ToolBarManager::AddToolBarShell (
391 if (mpImpl
!= nullptr)
393 UpdateLock
aLock (shared_from_this());
394 mpImpl
->AddToolBarShell(eGroup
,nToolBarId
);
398 void ToolBarManager::RemoveToolBar (
400 const OUString
& rsToolBarName
)
402 if (mpImpl
!= nullptr)
404 UpdateLock
aLock (shared_from_this());
405 mpImpl
->RemoveToolBar(eGroup
,rsToolBarName
);
409 void ToolBarManager::SetToolBar (
411 const OUString
& rsToolBarName
)
413 if (mpImpl
!= nullptr)
415 UpdateLock
aLock (shared_from_this());
416 mpImpl
->ResetToolBars(eGroup
);
417 mpImpl
->AddToolBar(eGroup
,rsToolBarName
);
421 void ToolBarManager::SetToolBarShell (
425 if (mpImpl
!= nullptr)
427 UpdateLock
aLock (shared_from_this());
428 mpImpl
->ResetToolBars(eGroup
);
429 mpImpl
->AddToolBarShell(eGroup
,nToolBarId
);
433 void ToolBarManager::PreUpdate()
435 if (mpImpl
!= nullptr)
439 void ToolBarManager::RequestUpdate()
441 if (mpImpl
!= nullptr)
442 mpImpl
->RequestUpdate();
445 void ToolBarManager::LockViewShellManager()
447 if (mpImpl
!= nullptr)
448 mpImpl
->LockViewShellManager();
451 void ToolBarManager::LockUpdate()
453 if (mpImpl
!= nullptr)
454 mpImpl
->LockUpdate();
457 void ToolBarManager::UnlockUpdate()
459 if (mpImpl
!= nullptr)
460 mpImpl
->UnlockUpdate();
463 void ToolBarManager::MainViewShellChanged ()
465 if (mpImpl
!= nullptr)
467 mpImpl
->ReleaseAllToolBarShells();
468 mpImpl
->GetToolBarRules().MainViewShellChanged(ViewShell::ST_NONE
);
472 void ToolBarManager::MainViewShellChanged (const ViewShell
& rMainViewShell
)
474 if (mpImpl
!= nullptr)
476 mpImpl
->ReleaseAllToolBarShells();
477 mpImpl
->GetToolBarRules().MainViewShellChanged(rMainViewShell
);
481 void ToolBarManager::SelectionHasChanged (
482 const ViewShell
& rViewShell
,
483 const SdrView
& rView
)
485 if (mpImpl
!= nullptr)
486 mpImpl
->GetToolBarRules().SelectionHasChanged(rViewShell
,rView
);
489 void ToolBarManager::ToolBarsDestroyed()
491 if (mpImpl
!= nullptr)
492 mpImpl
->ToolBarsDestroyed();
495 //===== ToolBarManager::Implementation =======================================
497 ToolBarManager::Implementation::Implementation (
498 ViewShellBase
& rBase
,
499 std::shared_ptr
<sd::tools::EventMultiplexer
> pMultiplexer
,
500 const std::shared_ptr
<ViewShellManager
>& rpViewShellManager
,
501 const std::shared_ptr
<ToolBarManager
>& rpToolBarManager
)
503 mpEventMultiplexer(std::move(pMultiplexer
)),
506 mbPreUpdatePending(false),
507 mbPostUpdatePending(false),
508 mnPendingUpdateCall(nullptr),
509 mnPendingSetValidCall(nullptr),
510 maToolBarRules(rpToolBarManager
,rpViewShellManager
)
512 Link
<tools::EventMultiplexerEvent
&,void> aLink (LINK(this,ToolBarManager::Implementation
,EventMultiplexerCallback
));
513 mpEventMultiplexer
->AddEventListener( aLink
);
516 /** The order of statements is important.
517 First unregister listeners, which may post user events.
518 Then remove pending user events.
520 ToolBarManager::Implementation::~Implementation()
522 // Unregister at broadcasters.
523 Link
<tools::EventMultiplexerEvent
&,void> aLink (LINK(this,ToolBarManager::Implementation
,EventMultiplexerCallback
));
524 mpEventMultiplexer
->RemoveEventListener(aLink
);
526 // Abort pending user calls.
527 if (mnPendingUpdateCall
!= nullptr)
528 Application::RemoveUserEvent(mnPendingUpdateCall
);
529 if (mnPendingSetValidCall
!= nullptr)
530 Application::RemoveUserEvent(mnPendingSetValidCall
);
533 void ToolBarManager::Implementation::ToolBarsDestroyed()
535 maToolBarList
.MarkAllToolBarsAsNotActive();
538 void ToolBarManager::Implementation::SetValid (bool bValid
)
540 ::osl::MutexGuard
aGuard(maMutex
);
542 if (mbIsValid
== bValid
)
545 UpdateLockImplementation
aUpdateLock (*this);
550 Reference
<frame::XFrame
> xFrame
= mrBase
.GetViewFrame().GetFrame().GetFrameInterface();
553 Reference
<beans::XPropertySet
> xFrameProperties (xFrame
, UNO_QUERY_THROW
);
554 Any
aValue (xFrameProperties
->getPropertyValue("LayoutManager"));
555 aValue
>>= mxLayouter
;
556 // tdf#119997 if mpSynchronousLayouterLock was created before mxLayouter was
557 // set then update it now that its available
558 if (mpSynchronousLayouterLock
&& !mpSynchronousLayouterLock
->is())
559 mpSynchronousLayouterLock
.reset(new LayouterLock(mxLayouter
));
561 catch (const RuntimeException
&)
565 GetToolBarRules().Update(mrBase
);
570 mxLayouter
= nullptr;
574 void ToolBarManager::Implementation::ResetToolBars (ToolBarGroup eGroup
)
576 ::osl::MutexGuard
aGuard(maMutex
);
578 maToolBarList
.ClearGroup(eGroup
);
579 maToolBarShellList
.ClearGroup(eGroup
);
581 mbPreUpdatePending
= true;
584 void ToolBarManager::Implementation::ResetAllToolBars()
586 SAL_INFO("sd.view", __func__
<< ": resetting all tool bars");
587 for (auto i
: o3tl::enumrange
<ToolBarGroup
>())
591 void ToolBarManager::Implementation::AddToolBar (
593 const OUString
& rsToolBarName
)
595 ::osl::MutexGuard
aGuard(maMutex
);
597 if (CheckPlugInMode(rsToolBarName
))
599 maToolBarList
.AddToolBar(eGroup
,rsToolBarName
);
601 mbPostUpdatePending
= true;
602 if (mnLockCount
== 0)
607 void ToolBarManager::Implementation::RemoveToolBar (
609 const OUString
& rsToolBarName
)
611 ::osl::MutexGuard
aGuard(maMutex
);
613 if (maToolBarList
.RemoveToolBar(eGroup
,rsToolBarName
))
615 mbPreUpdatePending
= true;
616 if (mnLockCount
== 0)
621 void ToolBarManager::Implementation::AddToolBarShell (
625 ViewShell
* pMainViewShell
= mrBase
.GetMainViewShell().get();
626 if (pMainViewShell
!= nullptr)
628 maToolBarShellList
.AddShellId(eGroup
,nToolBarId
);
629 GetToolBarRules().SubShellAdded(eGroup
, nToolBarId
);
633 void ToolBarManager::Implementation::ReleaseAllToolBarShells()
635 maToolBarShellList
.ReleaseAllShells(GetToolBarRules());
636 maToolBarShellList
.UpdateShells(mrBase
.GetMainViewShell(), mrBase
.GetViewShellManager());
639 void ToolBarManager::Implementation::RequestUpdate()
641 if (mnPendingUpdateCall
== nullptr)
643 mnPendingUpdateCall
= Application::PostUserEvent(
644 LINK(this,ToolBarManager::Implementation
,UpdateCallback
));
648 void ToolBarManager::Implementation::PreUpdate()
650 ::osl::MutexGuard
aGuard(maMutex
);
653 && mbPreUpdatePending
657 mbPreUpdatePending
= false;
659 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PreUpdate [");
661 // Get the list of tool bars that are not used anymore and are to be
663 std::vector
<OUString
> aToolBars
;
664 maToolBarList
.GetToolBarsToDeactivate(aToolBars
);
666 // Turn off the tool bars.
667 for (const auto& aToolBar
: aToolBars
)
669 OUString
sFullName (GetToolBarResourceName(aToolBar
));
670 SAL_INFO("sd.view", __func__
<< ": turning off tool bar " << sFullName
);
671 mxLayouter
->destroyElement(sFullName
);
672 maToolBarList
.MarkToolBarAsNotActive(aToolBar
);
675 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PreUpdate ]");
678 void ToolBarManager::Implementation::PostUpdate()
680 ::osl::MutexGuard
aGuard(maMutex
);
683 && mbPostUpdatePending
687 mbPostUpdatePending
= false;
689 // Create the list of requested tool bars.
690 std::vector
<OUString
> aToolBars
;
691 maToolBarList
.GetToolBarsToActivate(aToolBars
);
693 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PostUpdate [");
695 // Turn on the tool bars that are visible in the new context.
696 for (const auto& aToolBar
: aToolBars
)
698 OUString
sFullName (GetToolBarResourceName(aToolBar
));
699 SAL_INFO("sd.view", __func__
<< ": turning on tool bar " << sFullName
);
700 mxLayouter
->requestElement(sFullName
);
701 maToolBarList
.MarkToolBarAsActive(aToolBar
);
704 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PostUpdate ]");
707 void ToolBarManager::Implementation::LockViewShellManager()
709 if (mpViewShellManagerLock
== nullptr)
710 mpViewShellManagerLock
.reset(
711 new ViewShellManager::UpdateLock(mrBase
.GetViewShellManager()));
714 void ToolBarManager::Implementation::LockUpdate()
716 SAL_INFO("sd.view", __func__
<< ": LockUpdate " << mnLockCount
);
717 ::osl::MutexGuard
aGuard(maMutex
);
719 DBG_ASSERT(mnLockCount
<100, "ToolBarManager lock count unusually high");
720 if (mnLockCount
== 0)
722 OSL_ASSERT(mpSynchronousLayouterLock
== nullptr);
724 mpSynchronousLayouterLock
.reset(new LayouterLock(mxLayouter
));
729 void ToolBarManager::Implementation::UnlockUpdate()
731 SAL_INFO("sd.view", __func__
<< ": UnlockUpdate " << mnLockCount
);
732 ::osl::MutexGuard
aGuard(maMutex
);
734 OSL_ASSERT(mnLockCount
>0);
736 if (mnLockCount
== 0)
738 Update(std::move(mpSynchronousLayouterLock
));
742 void ToolBarManager::Implementation::Update (
743 ::std::unique_ptr
<LayouterLock
> pLocalLayouterLock
)
745 // When the lock is released and there are pending changes to the set of
746 // tool bars then update this set now.
747 if (mnLockCount
!= 0)
750 // During creation of ViewShellBase we may have the situation that
751 // the controller has already been created and attached to the frame
752 // but that the ToolBarManager has not yet completed its
753 // initialization (by initializing the mxLayouter member.) We do
754 // this here so that we do not have to wait for the next Update()
755 // call to show the tool bars.
756 if (mnPendingSetValidCall
!= nullptr)
758 Application::RemoveUserEvent(mnPendingSetValidCall
);
759 mnPendingSetValidCall
= nullptr;
763 if (mbIsValid
&& mxLayouter
.is() && (mbPreUpdatePending
|| mbPostUpdatePending
))
765 // 1) Release UNO tool bars that are no longer used. Do this
766 // now so that they are not updated when the SFX shell stack is
768 if (mbPreUpdatePending
)
771 // 2) Update the requested shells that represent tool bar
772 // functionality. Those that are not used anymore are
773 // deactivated now. Those that are missing are activated in the
774 // next step together with the view shells.
775 if (mpViewShellManagerLock
== nullptr)
776 mpViewShellManagerLock
.reset(
777 new ViewShellManager::UpdateLock(mrBase
.GetViewShellManager()));
778 maToolBarShellList
.UpdateShells(
779 mrBase
.GetMainViewShell(),
780 mrBase
.GetViewShellManager());
782 // 3) Unlock the ViewShellManager::UpdateLock. This updates the
784 mpViewShellManagerLock
.reset();
786 // 4) Make the UNO tool bars visible. The outstanding call to
787 // PostUpdate() is done via PostUserEvent() so that it is
788 // guaranteed to be executed when the SFX shell stack has been
789 // updated (under the assumption that our lock to the
790 // ViewShellManager was the only one open. If that is not the
791 // case then all should still be well but not as fast.)
793 // Note that the lock count may have been increased since
794 // entering this method. In that case one of the next
795 // UnlockUpdate() calls will post the UpdateCallback.
798 mpAsynchronousLayouterLock
= std::move(pLocalLayouterLock
);
799 if (mnPendingUpdateCall
==nullptr)
801 mnPendingUpdateCall
= Application::PostUserEvent(
802 LINK(this,ToolBarManager::Implementation
,UpdateCallback
));
808 mpViewShellManagerLock
.reset();
809 pLocalLayouterLock
.reset();
813 IMPL_LINK_NOARG(ToolBarManager::Implementation
, UpdateCallback
, void*, void)
815 mnPendingUpdateCall
= nullptr;
816 if (mnLockCount
== 0)
818 if (mbPreUpdatePending
)
820 if (mbPostUpdatePending
)
822 if (mbIsValid
&& mxLayouter
.is())
823 mpAsynchronousLayouterLock
.reset();
827 IMPL_LINK(ToolBarManager::Implementation
,EventMultiplexerCallback
,
828 sd::tools::EventMultiplexerEvent
&, rEvent
, void)
831 switch (rEvent
.meEventId
)
833 case EventMultiplexerEventId::ControllerAttached
:
834 if (mnPendingSetValidCall
== nullptr)
835 mnPendingSetValidCall
836 = Application::PostUserEvent(LINK(this,Implementation
,SetValidCallback
));
839 case EventMultiplexerEventId::ControllerDetached
:
847 IMPL_LINK_NOARG(ToolBarManager::Implementation
, SetValidCallback
, void*, void)
849 mnPendingSetValidCall
= nullptr;
853 OUString
ToolBarManager::Implementation::GetToolBarResourceName (
854 std::u16string_view rsBaseName
)
856 return OUString::Concat("private:resource/toolbar/") + rsBaseName
;
859 bool ToolBarManager::Implementation::CheckPlugInMode (std::u16string_view rsName
) const
863 // Determine the plug in mode.
864 bool bIsPlugInMode (false);
867 SfxObjectShell
* pObjectShell
= mrBase
.GetObjectShell();
868 if (pObjectShell
== nullptr)
871 SfxMedium
* pMedium
= pObjectShell
->GetMedium();
872 if (pMedium
== nullptr)
875 const SfxBoolItem
* pViewOnlyItem
= SfxItemSet::GetItem
<SfxBoolItem
>(pMedium
->GetItemSet(), SID_VIEWONLY
, false);
876 if (pViewOnlyItem
== nullptr)
879 bIsPlugInMode
= pViewOnlyItem
->GetValue();
883 if (rsName
== msViewerToolBar
)
884 bValid
= bIsPlugInMode
;
886 bValid
= ! bIsPlugInMode
;
891 } // end of namespace sd
895 using namespace ::sd
;
897 //===== LayouterLock ==========================================================
899 LayouterLock::LayouterLock (const Reference
<frame::XLayoutManager
>& rxLayouter
)
900 : mxLayouter(rxLayouter
)
902 SAL_INFO("sd.view", __func__
<< ": LayouterLock " << (mxLayouter
.is() ? 1 :0));
907 LayouterLock::~LayouterLock()
909 SAL_INFO("sd.view", __func__
<< ": ~LayouterLock " << (mxLayouter
.is() ? 1 :0));
911 mxLayouter
->unlock();
914 //===== ToolBarRules ==========================================================
916 ToolBarRules::ToolBarRules (
917 std::shared_ptr
<sd::ToolBarManager
> pToolBarManager
,
918 std::shared_ptr
<sd::ViewShellManager
> pViewShellManager
)
919 : mpToolBarManager(std::move(pToolBarManager
)),
920 mpViewShellManager(std::move(pViewShellManager
))
924 void ToolBarRules::Update (ViewShellBase
const & rBase
)
926 ViewShell
* pMainViewShell
= rBase
.GetMainViewShell().get();
927 if (pMainViewShell
!= nullptr)
929 MainViewShellChanged(pMainViewShell
->GetShellType());
930 if (pMainViewShell
->GetView())
931 SelectionHasChanged (*pMainViewShell
, *pMainViewShell
->GetView());
934 MainViewShellChanged(ViewShell::ST_NONE
);
937 void ToolBarRules::MainViewShellChanged (ViewShell::ShellType nShellType
)
939 ::sd::ToolBarManager::UpdateLock
aToolBarManagerLock (mpToolBarManager
);
940 ::sd::ViewShellManager::UpdateLock
aViewShellManagerLock (mpViewShellManager
);
942 mpToolBarManager
->ResetAllToolBars();
946 case ::sd::ViewShell::ST_IMPRESS
:
947 case ::sd::ViewShell::ST_NOTES
:
948 case ::sd::ViewShell::ST_HANDOUT
:
949 mpToolBarManager
->AddToolBar(
950 ToolBarManager::ToolBarGroup::Permanent
,
951 ToolBarManager::msToolBar
);
952 mpToolBarManager
->AddToolBar(
953 ToolBarManager::ToolBarGroup::Permanent
,
954 ToolBarManager::msOptionsToolBar
);
955 mpToolBarManager
->AddToolBar(
956 ToolBarManager::ToolBarGroup::Permanent
,
957 ToolBarManager::msViewerToolBar
);
960 case ::sd::ViewShell::ST_DRAW
:
961 mpToolBarManager
->AddToolBar(
962 ToolBarManager::ToolBarGroup::Permanent
,
963 ToolBarManager::msToolBar
);
964 mpToolBarManager
->AddToolBar(
965 ToolBarManager::ToolBarGroup::Permanent
,
966 ToolBarManager::msOptionsToolBar
);
967 mpToolBarManager
->AddToolBar(
968 ToolBarManager::ToolBarGroup::Permanent
,
969 ToolBarManager::msViewerToolBar
);
972 case ViewShell::ST_OUTLINE
:
973 mpToolBarManager
->AddToolBar(
974 ToolBarManager::ToolBarGroup::Permanent
,
975 ToolBarManager::msOutlineToolBar
);
976 mpToolBarManager
->AddToolBar(
977 ToolBarManager::ToolBarGroup::Permanent
,
978 ToolBarManager::msViewerToolBar
);
979 mpToolBarManager
->AddToolBarShell(
980 ToolBarManager::ToolBarGroup::Permanent
, ToolbarId::Draw_Text_Toolbox_Sd
);
983 case ViewShell::ST_SLIDE_SORTER
:
984 mpToolBarManager
->AddToolBar(
985 ToolBarManager::ToolBarGroup::Permanent
,
986 ToolBarManager::msViewerToolBar
);
987 mpToolBarManager
->AddToolBar(
988 ToolBarManager::ToolBarGroup::Permanent
,
989 ToolBarManager::msSlideSorterToolBar
);
990 mpToolBarManager
->AddToolBar(
991 ToolBarManager::ToolBarGroup::Permanent
,
992 ToolBarManager::msSlideSorterObjectBar
);
995 case ViewShell::ST_NONE
:
996 case ViewShell::ST_PRESENTATION
:
997 case ViewShell::ST_SIDEBAR
:
1003 void ToolBarRules::MainViewShellChanged (const ViewShell
& rMainViewShell
)
1005 ::sd::ToolBarManager::UpdateLock
aToolBarManagerLock (mpToolBarManager
);
1006 ::sd::ViewShellManager::UpdateLock
aViewShellManagerLock (mpViewShellManager
);
1008 MainViewShellChanged(rMainViewShell
.GetShellType());
1009 switch(rMainViewShell
.GetShellType())
1011 case ::sd::ViewShell::ST_IMPRESS
:
1012 case ::sd::ViewShell::ST_DRAW
:
1013 case ::sd::ViewShell::ST_NOTES
:
1015 const DrawViewShell
* pDrawViewShell
1016 = dynamic_cast<const DrawViewShell
*>(&rMainViewShell
);
1017 if (pDrawViewShell
!= nullptr)
1019 if (pDrawViewShell
->GetEditMode() == EditMode::MasterPage
)
1020 mpToolBarManager
->AddToolBar(
1021 ToolBarManager::ToolBarGroup::MasterMode
,
1022 ToolBarManager::msMasterViewToolBar
);
1023 else if ( rMainViewShell
.GetShellType() != ::sd::ViewShell::ST_DRAW
)
1024 mpToolBarManager
->AddToolBar(
1025 ToolBarManager::ToolBarGroup::CommonTask
,
1026 ToolBarManager::msCommonTaskToolBar
);
1036 void ToolBarRules::SelectionHasChanged (
1037 const ::sd::ViewShell
& rViewShell
,
1038 const SdrView
& rView
)
1040 ::sd::ToolBarManager::UpdateLock
aLock (mpToolBarManager
);
1041 mpToolBarManager
->LockViewShellManager();
1042 bool bTextEdit
= rView
.IsTextEdit();
1044 mpToolBarManager
->ResetToolBars(ToolBarManager::ToolBarGroup::Function
);
1046 switch (rView
.GetContext())
1048 case SdrViewContext::Graphic
:
1050 mpToolBarManager
->SetToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Draw_Graf_Toolbox
);
1053 case SdrViewContext::Media
:
1055 mpToolBarManager
->SetToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Draw_Media_Toolbox
);
1058 case SdrViewContext::Table
:
1059 mpToolBarManager
->SetToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Draw_Table_Toolbox
);
1063 case SdrViewContext::Standard
:
1067 switch(rViewShell
.GetShellType())
1069 case ::sd::ViewShell::ST_IMPRESS
:
1070 case ::sd::ViewShell::ST_DRAW
:
1071 case ::sd::ViewShell::ST_NOTES
:
1072 case ::sd::ViewShell::ST_HANDOUT
:
1073 mpToolBarManager
->SetToolBar(
1074 ToolBarManager::ToolBarGroup::Function
,
1075 ToolBarManager::msDrawingObjectToolBar
);
1085 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Draw_Text_Toolbox_Sd
);
1087 SdrView
* pView
= &const_cast<SdrView
&>(rView
);
1088 // Check if the extrusion tool bar and the fontwork tool bar have to
1090 if (svx::checkForSelectedCustomShapes(pView
, true /* bOnlyExtruded */ ))
1091 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Svx_Extrusion_Bar
);
1093 if (svx::checkForSelectedFontWork(pView
))
1094 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Svx_Fontwork_Bar
);
1096 // Switch on additional context-sensitive tool bars.
1097 if (rView
.GetContext() == SdrViewContext::PointEdit
)
1098 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Bezier_Toolbox_Sd
);
1101 void ToolBarRules::SubShellAdded (
1102 ::sd::ToolBarManager::ToolBarGroup eGroup
,
1103 sd::ShellId nShellId
)
1105 // For some tool bar shells (those defined in sd) we have to add the
1106 // actual tool bar here.
1109 case ToolbarId::Draw_Graf_Toolbox
:
1110 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msGraphicObjectBar
);
1113 case ToolbarId::Draw_Media_Toolbox
:
1114 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msMediaObjectBar
);
1117 case ToolbarId::Draw_Text_Toolbox_Sd
:
1118 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msTextObjectBar
);
1121 case ToolbarId::Bezier_Toolbox_Sd
:
1122 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msBezierObjectBar
);
1125 case ToolbarId::Draw_Table_Toolbox
:
1126 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msTableObjectBar
);
1134 void ToolBarRules::SubShellRemoved (
1135 ::sd::ToolBarManager::ToolBarGroup eGroup
,
1136 sd::ShellId nShellId
)
1138 // For some tool bar shells (those defined in sd) we have to add the
1139 // actual tool bar here.
1142 case ToolbarId::Draw_Graf_Toolbox
:
1143 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msGraphicObjectBar
);
1146 case ToolbarId::Draw_Media_Toolbox
:
1147 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msMediaObjectBar
);
1150 case ToolbarId::Draw_Text_Toolbox_Sd
:
1151 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msTextObjectBar
);
1154 case ToolbarId::Bezier_Toolbox_Sd
:
1155 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msBezierObjectBar
);
1158 case ToolbarId::Draw_Table_Toolbox
:
1159 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msTableObjectBar
);
1167 //===== ToolBarList ===========================================================
1169 ToolBarList::ToolBarList()
1173 void ToolBarList::ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
)
1175 Groups::iterator
iGroup (maGroups
.find(eGroup
));
1176 if (iGroup
!= maGroups
.end())
1178 iGroup
->second
.clear();
1182 void ToolBarList::AddToolBar (
1183 sd::ToolBarManager::ToolBarGroup eGroup
,
1184 const OUString
& rsName
)
1186 Groups::iterator
iGroup (maGroups
.find(eGroup
));
1187 if (iGroup
== maGroups
.end())
1188 iGroup
= maGroups
.emplace(eGroup
,std::vector
<OUString
>()).first
;
1190 if (iGroup
!= maGroups
.end())
1192 auto iBar (std::find(iGroup
->second
.cbegin(),iGroup
->second
.cend(),rsName
));
1193 if (iBar
== iGroup
->second
.cend())
1195 iGroup
->second
.push_back(rsName
);
1200 bool ToolBarList::RemoveToolBar (
1201 sd::ToolBarManager::ToolBarGroup eGroup
,
1202 const OUString
& rsName
)
1204 Groups::iterator
iGroup (maGroups
.find(eGroup
));
1205 if (iGroup
!= maGroups
.end())
1207 auto iBar (std::find(iGroup
->second
.begin(),iGroup
->second
.end(),rsName
));
1208 if (iBar
!= iGroup
->second
.end())
1210 iGroup
->second
.erase(iBar
);
1217 void ToolBarList::MakeRequestedToolBarList (std::vector
<OUString
>& rRequestedToolBars
) const
1219 for (auto eGroup
: o3tl::enumrange
<sd::ToolBarManager::ToolBarGroup
>())
1221 Groups::const_iterator
iGroup (maGroups
.find(eGroup
));
1222 if (iGroup
!= maGroups
.end())
1223 rRequestedToolBars
.insert( rRequestedToolBars
.end(),
1224 iGroup
->second
.begin(),
1225 iGroup
->second
.end() );
1229 void ToolBarList::GetToolBarsToActivate (std::vector
<OUString
>& rToolBars
) const
1231 std::vector
<OUString
> aRequestedToolBars
;
1232 MakeRequestedToolBarList(aRequestedToolBars
);
1234 for (const auto& aToolBar
: aRequestedToolBars
)
1236 if (::std::find(maActiveToolBars
.begin(),maActiveToolBars
.end(),aToolBar
)
1237 == maActiveToolBars
.end())
1239 rToolBars
.push_back(aToolBar
);
1244 void ToolBarList::GetToolBarsToDeactivate (std::vector
<OUString
>& rToolBars
) const
1246 std::vector
<OUString
> aRequestedToolBars
;
1247 MakeRequestedToolBarList(aRequestedToolBars
);
1249 for (auto& aToolBar
: maActiveToolBars
)
1251 if (::std::find(aRequestedToolBars
.begin(),aRequestedToolBars
.end(),aToolBar
)
1252 == aRequestedToolBars
.end())
1254 rToolBars
.push_back(aToolBar
);
1259 void ToolBarList::MarkToolBarAsActive (const OUString
& rsName
)
1261 maActiveToolBars
.push_back(rsName
);
1264 void ToolBarList::MarkToolBarAsNotActive (const OUString
& rsName
)
1266 maActiveToolBars
.erase(
1267 ::std::find(maActiveToolBars
.begin(),maActiveToolBars
.end(), rsName
));
1270 void ToolBarList::MarkAllToolBarsAsNotActive()
1272 maActiveToolBars
.clear();
1275 //===== ToolBarShellList ======================================================
1277 ToolBarShellList::ShellDescriptor::ShellDescriptor (
1279 sd::ToolBarManager::ToolBarGroup eGroup
)
1285 ToolBarShellList::ToolBarShellList()
1289 void ToolBarShellList::ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
)
1291 for (GroupedShellList::iterator iDescriptor
= maNewList
.begin(); iDescriptor
!= maNewList
.end(); )
1292 if (iDescriptor
->meGroup
== eGroup
)
1293 iDescriptor
= maNewList
.erase(iDescriptor
);
1298 void ToolBarShellList::AddShellId (sd::ToolBarManager::ToolBarGroup eGroup
, sd::ShellId nId
)
1300 // Make sure that the shell is not added twice (and possibly in
1301 // different groups.)
1302 ShellDescriptor
aDescriptor (nId
,eGroup
);
1303 GroupedShellList::iterator
iDescriptor (maNewList
.find(aDescriptor
));
1304 if (iDescriptor
!= maNewList
.end())
1306 // The shell is already requested.
1307 if (iDescriptor
->meGroup
!= eGroup
)
1309 // It is now being requested for another group.
1310 // (Is this an error?)
1311 // Move it to that group.
1312 maNewList
.erase(iDescriptor
);
1313 maNewList
.insert(aDescriptor
);
1315 // else nothing to do.
1318 maNewList
.insert(aDescriptor
);
1321 void ToolBarShellList::ReleaseAllShells (ToolBarRules
& rRules
)
1323 // Release the currently active tool bars.
1324 GroupedShellList
aList (maCurrentList
);
1325 for (const auto& rDescriptor
: aList
)
1327 rRules
.SubShellRemoved(rDescriptor
.meGroup
, rDescriptor
.mnId
);
1330 // Clear the list of requested tool bars.
1334 void ToolBarShellList::UpdateShells (
1335 const std::shared_ptr
<ViewShell
>& rpMainViewShell
,
1336 const std::shared_ptr
<ViewShellManager
>& rpManager
)
1338 if (rpMainViewShell
== nullptr)
1341 GroupedShellList aList
;
1343 // Deactivate shells that are in maCurrentList, but not in
1345 ::std::set_difference(maCurrentList
.begin(), maCurrentList
.end(),
1346 maNewList
.begin(), maNewList
.end(),
1347 std::insert_iterator
<GroupedShellList
>(aList
,aList
.begin()));
1348 for (const auto& rShell
: aList
)
1350 SAL_INFO("sd.view", __func__
<< ": deactivating tool bar shell " << static_cast<sal_uInt32
>(rShell
.mnId
));
1351 rpManager
->DeactivateSubShell(*rpMainViewShell
, rShell
.mnId
);
1354 // Activate shells that are in maNewList, but not in
1357 ::std::set_difference(maNewList
.begin(), maNewList
.end(),
1358 maCurrentList
.begin(), maCurrentList
.end(),
1359 std::insert_iterator
<GroupedShellList
>(aList
,aList
.begin()));
1360 for (const auto& rShell
: aList
)
1362 SAL_INFO("sd.view", __func__
<< ": activating tool bar shell " << static_cast<sal_uInt32
>(rShell
.mnId
));
1363 rpManager
->ActivateSubShell(*rpMainViewShell
, rShell
.mnId
);
1366 // The maNewList now reflects the current state and thus is made
1368 maCurrentList
= maNewList
;
1371 } // end of anonymous namespace
1373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */