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 <NotesPanelViewShell.hxx>
24 #include <EventMultiplexer.hxx>
25 #include <ViewShellBase.hxx>
26 #include <ViewShellManager.hxx>
27 #include <framework/FrameworkHelper.hxx>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/frame/XLayoutManager.hpp>
31 #include <sal/log.hxx>
32 #include <osl/mutex.hxx>
33 #include <o3tl/deleter.hxx>
34 #include <o3tl/enumrange.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
37 #include <sfx2/objsh.hxx>
38 #include <sfx2/toolbarids.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <svl/eitem.hxx>
41 #include <svx/svxids.hrc>
42 #include <svx/extrusionbar.hxx>
43 #include <svx/fontworkbar.hxx>
44 #include <tools/debug.hxx>
45 #include <tools/link.hxx>
47 #include <vcl/svapp.hxx>
48 #include <osl/diagnose.h>
52 #include <string_view>
55 using namespace ::com::sun::star
;
56 using namespace ::com::sun::star::uno
;
64 /** Lock of the frame::XLayoutManager.
68 Reference
<frame::XLayoutManager
> mxLayouter
;
70 explicit LayouterLock (const Reference
<frame::XLayoutManager
>& rxLayouter
);
72 bool is() const { return mxLayouter
.is(); }
75 /** Store a list of tool bars for each of the tool bar groups. From
76 this the list of requested tool bars is built.
83 void ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
);
84 void AddToolBar (sd::ToolBarManager::ToolBarGroup eGroup
, const OUString
& rsName
);
85 bool RemoveToolBar (sd::ToolBarManager::ToolBarGroup eGroup
, const OUString
& rsName
);
87 void GetToolBarsToActivate (std::vector
<OUString
>& rToolBars
) const;
88 void GetToolBarsToDeactivate (std::vector
<OUString
>& rToolBars
) const;
90 void MarkToolBarAsActive (const OUString
& rsName
);
91 void MarkToolBarAsNotActive (const OUString
& rsName
);
92 void MarkAllToolBarsAsNotActive();
95 typedef ::std::map
<sd::ToolBarManager::ToolBarGroup
, std::vector
<OUString
> > Groups
;
97 std::vector
<OUString
> maActiveToolBars
;
99 void MakeRequestedToolBarList (std::vector
<OUString
>& rToolBars
) const;
102 /** Manage tool bars that are implemented as sub shells of a view shell.
103 The typical procedure of updating the sub shells of a view shell is to
104 rebuild a list of sub shells that the caller would like to have active.
105 The methods ClearGroup() and AddShellId() allow the caller to do that. A
106 final call to UpdateShells() activates the requested shells that are not
107 active and deactivates the active shells that are not requested .
109 This is done by maintaining two lists. One (the current list)
110 reflects the current state. The other (the requested list) contains the
111 currently requested shells. UpdateShells() makes the requested
112 list the current list and clears the current list.
114 Each shell belongs to one group. Different groups can be modified
117 class ToolBarShellList
120 /** Create a new object with an empty current list and an empty
125 /** Remove all shells from a group. Calling this method should normally
126 not be necessary because after the construction or after a call to
127 UpdateShells() the requested list is empty.
129 The group to clear. Shells in other groups are not modified.
131 void ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
);
133 /** Add a shell. When the specified shell has already been requested
134 for another group then it is moved to this group.
136 The group to which to add the shell.
138 The id of the shell to add.
140 void AddShellId (sd::ToolBarManager::ToolBarGroup eGroup
, sd::ShellId nId
);
142 /** Releasing all shells means that the given ToolBarRules object is
143 informed that every shell managed by the called ToolBarShellList is
144 about to be removed and that the associated framework tool bars can
145 be removed as well. The caller still has to call UpdateShells().
147 void ReleaseAllShells (ToolBarRules
& rRules
);
149 /** The requested list is made the current list by activating all
150 shells in the requested list and by deactivating the shells in the
151 current list that are not in the requested list.
152 @param pMainViewShell
153 The shells that are activated or deactivated are sub shells of
156 This ViewShellManager is used to activate or deactivate shells.
159 const std::shared_ptr
<ViewShell
>& rpMainViewShell
,
160 const std::shared_ptr
<ViewShellManager
>& rpManager
);
163 class ShellDescriptor
165 ShellDescriptor (ShellId nId
,sd::ToolBarManager::ToolBarGroup eGroup
);
167 sd::ToolBarManager::ToolBarGroup meGroup
;
168 friend bool operator<(const ShellDescriptor
& r1
, const ShellDescriptor
& r2
)
169 { return r1
.mnId
< r2
.mnId
; }
172 /** The requested list of tool bar shells that will be active after the
173 next call to UpdateShells().
175 typedef ::std::set
<ShellDescriptor
> GroupedShellList
;
176 GroupedShellList maNewList
;
178 /** The list of tool bar shells that are currently on the shell stack.
179 Using a GroupedShellList is not strictly necessary but it makes
180 things easier and does not waste too much memory.
182 GroupedShellList maCurrentList
;
185 /** This class concentrates the knowledge about when to show what tool bars
192 std::shared_ptr
<ToolBarManager
> pToolBarManager
,
193 std::shared_ptr
<ViewShellManager
> pViewShellManager
);
195 /** This method calls MainViewShellChanged() and SelectionHasChanged()
196 for the current main view shell and its view.
198 void Update (ViewShellBase
const & rBase
);
200 /** Reset all tool bars in all groups and add tool bars and tool bar
201 shells to the ToolBarGroup::Permanent group for the specified ViewShell type.
203 void MainViewShellChanged (ViewShell::ShellType nShellType
);
205 /** Reset all tool bars in all groups and add tool bars and tool bar
206 shells to the ToolBarGroup::Permanent group for the specified ViewShell.
208 void MainViewShellChanged (const ViewShell
& rMainViewShell
);
210 /** Reset all tool bars in the ToolBarGroup::Function group and add tool bars and tool bar
211 shells to this group for the current selection.
213 void SelectionHasChanged (
214 const ::sd::ViewShell
& rViewShell
,
215 const SdrView
& rView
);
217 /** Add a tool bar for the specified tool bar shell.
220 ::sd::ToolBarManager::ToolBarGroup eGroup
,
221 sd::ShellId nShellId
);
223 /** Remove a tool bar for the specified tool bar shell.
225 void SubShellRemoved (
226 ::sd::ToolBarManager::ToolBarGroup eGroup
,
227 sd::ShellId nShellId
);
230 std::shared_ptr
<ToolBarManager
> mpToolBarManager
;
231 std::shared_ptr
<ViewShellManager
> mpViewShellManager
;
234 } // end of anonymous namespace
238 //===== ToolBarManager::Implementation ========================================
240 class ToolBarManager::Implementation
243 /** This constructor takes three arguments even though the
244 ToolBarManager could be taken from the ViewShellBase. This is so to
245 state explicitly which information has to be present when this
246 constructor is called. The ViewShellBase may not have been fully
247 initialized at this point and must not be asked for this values.
250 ViewShellBase
& rBase
,
251 std::shared_ptr
<sd::tools::EventMultiplexer
> pMultiplexer
,
252 const std::shared_ptr
<ViewShellManager
>& rpViewShellManager
,
253 const std::shared_ptr
<ToolBarManager
>& rpToolBarManager
);
256 void SetValid (bool bValid
);
258 void ResetToolBars (ToolBarGroup eGroup
);
259 void ResetAllToolBars();
260 void AddToolBar (ToolBarGroup eGroup
, const OUString
& rsToolBarName
);
261 void AddToolBarShell (ToolBarGroup eGroup
, ShellId nToolBarId
, bool bAddBar
= true);
262 void RemoveToolBar (ToolBarGroup eGroup
, const OUString
& rsToolBarName
);
264 /** Release all tool bar shells and the associated framework tool bars.
265 Typically called when the main view shell is being replaced by
266 another, all tool bar shells are released. In that process the
267 shells are destroyed anyway and without calling this method they
268 would still be referenced.
270 void ReleaseAllToolBarShells();
272 void ToolBarsDestroyed();
274 void RequestUpdate();
278 /** Tell the XLayoutManager about the tool bars that we would like to be
280 @param rpLayouterLock
281 This typically is the mpSynchronousLayouterLock that is used in
282 this method and that is either released at its end or assigned
283 to mpAsynchronousLock in order to be unlocked later.
285 void Update (::std::unique_ptr
<LayouterLock
> pLayouterLock
);
287 class UpdateLockImplementation
290 explicit UpdateLockImplementation (Implementation
& rImplementation
)
291 : mrImplementation(rImplementation
) { mrImplementation
.LockUpdate(); }
292 ~UpdateLockImplementation() { suppress_fun_call_w_exception(mrImplementation
.UnlockUpdate()); }
294 Implementation
& mrImplementation
;
297 void LockViewShellManager();
301 ToolBarRules
& GetToolBarRules() { return maToolBarRules
;}
304 mutable ::osl::Mutex maMutex
;
305 ViewShellBase
& mrBase
;
306 std::shared_ptr
<sd::tools::EventMultiplexer
> mpEventMultiplexer
;
308 ToolBarList maToolBarList
;
309 ToolBarShellList maToolBarShellList
;
310 Reference
<frame::XLayoutManager
> mxLayouter
;
311 sal_Int32 mnLockCount
;
312 bool mbPreUpdatePending
;
313 bool mbPostUpdatePending
;
314 /** The layouter locks manage the locking of the XLayoutManager. The
315 lock() and unlock() functions are not called directly because the
316 (final) unlocking is usually done asynchronously *after* the
317 list of requested toolbars is updated.
319 ::std::unique_ptr
<LayouterLock
> mpSynchronousLayouterLock
;
320 ::std::unique_ptr
<LayouterLock
> mpAsynchronousLayouterLock
;
321 ::std::unique_ptr
<ViewShellManager::UpdateLock
, o3tl::default_delete
<ViewShellManager::UpdateLock
>> mpViewShellManagerLock
;
322 ImplSVEvent
* mnPendingUpdateCall
;
323 ImplSVEvent
* mnPendingSetValidCall
;
324 ToolBarRules maToolBarRules
;
326 static OUString
GetToolBarResourceName (std::u16string_view rsBaseName
);
327 bool CheckPlugInMode (std::u16string_view rsName
) const;
329 DECL_LINK(UpdateCallback
, void *, void);
330 DECL_LINK(EventMultiplexerCallback
, sd::tools::EventMultiplexerEvent
&, void);
331 DECL_LINK(SetValidCallback
, void*, void);
334 //===== ToolBarManager ========================================================
336 std::shared_ptr
<ToolBarManager
> ToolBarManager::Create (
337 ViewShellBase
& rBase
,
338 const std::shared_ptr
<sd::tools::EventMultiplexer
>& rpMultiplexer
,
339 const std::shared_ptr
<ViewShellManager
>& rpViewShellManager
)
341 std::shared_ptr
<ToolBarManager
> pManager (new ToolBarManager());
342 pManager
->mpImpl
.reset(
343 new Implementation(rBase
,rpMultiplexer
,rpViewShellManager
,pManager
));
347 ToolBarManager::ToolBarManager()
351 ToolBarManager::~ToolBarManager()
355 void ToolBarManager::Shutdown()
357 if (mpImpl
!= nullptr)
361 void ToolBarManager::ResetToolBars (ToolBarGroup eGroup
)
363 if (mpImpl
!= nullptr)
365 UpdateLock
aLock (shared_from_this());
366 mpImpl
->ResetToolBars(eGroup
);
370 void ToolBarManager::ResetAllToolBars()
372 if (mpImpl
!= nullptr)
374 UpdateLock
aLock (shared_from_this());
375 mpImpl
->ResetAllToolBars();
379 void ToolBarManager::AddToolBar (
381 const OUString
& rsToolBarName
)
383 if (mpImpl
!= nullptr)
385 UpdateLock
aLock (shared_from_this());
386 mpImpl
->AddToolBar(eGroup
,rsToolBarName
);
390 void ToolBarManager::AddToolBarShell (
394 if (mpImpl
!= nullptr)
396 UpdateLock
aLock (shared_from_this());
397 mpImpl
->AddToolBarShell(eGroup
,nToolBarId
,/*bAddBar*/true);
401 void ToolBarManager::RemoveToolBar (
403 const OUString
& rsToolBarName
)
405 if (mpImpl
!= nullptr)
407 UpdateLock
aLock (shared_from_this());
408 mpImpl
->RemoveToolBar(eGroup
,rsToolBarName
);
412 void ToolBarManager::SetToolBar (
414 const OUString
& rsToolBarName
)
416 if (mpImpl
!= nullptr)
418 UpdateLock
aLock (shared_from_this());
419 mpImpl
->ResetToolBars(eGroup
);
420 mpImpl
->AddToolBar(eGroup
,rsToolBarName
);
424 void ToolBarManager::SetToolBarShell (
428 if (mpImpl
!= nullptr)
430 UpdateLock
aLock (shared_from_this());
431 mpImpl
->ResetToolBars(eGroup
);
432 mpImpl
->AddToolBarShell(eGroup
,nToolBarId
);
436 void ToolBarManager::PreUpdate()
438 if (mpImpl
!= nullptr)
442 void ToolBarManager::RequestUpdate()
444 if (mpImpl
!= nullptr)
445 mpImpl
->RequestUpdate();
448 void ToolBarManager::LockViewShellManager()
450 if (mpImpl
!= nullptr)
451 mpImpl
->LockViewShellManager();
454 void ToolBarManager::LockUpdate()
456 if (mpImpl
!= nullptr)
457 mpImpl
->LockUpdate();
460 void ToolBarManager::UnlockUpdate()
462 if (mpImpl
!= nullptr)
463 mpImpl
->UnlockUpdate();
466 void ToolBarManager::MainViewShellChanged ()
468 if (mpImpl
!= nullptr)
470 mpImpl
->ReleaseAllToolBarShells();
471 mpImpl
->GetToolBarRules().MainViewShellChanged(ViewShell::ST_NONE
);
475 void ToolBarManager::MainViewShellChanged (const ViewShell
& rMainViewShell
)
477 if (mpImpl
!= nullptr)
479 mpImpl
->ReleaseAllToolBarShells();
480 mpImpl
->GetToolBarRules().MainViewShellChanged(rMainViewShell
);
484 void ToolBarManager::SelectionHasChanged (
485 const ViewShell
& rViewShell
,
486 const SdrView
& rView
)
488 if (mpImpl
!= nullptr)
489 mpImpl
->GetToolBarRules().SelectionHasChanged(rViewShell
,rView
);
492 void ToolBarManager::ToolBarsDestroyed()
494 if (mpImpl
!= nullptr)
495 mpImpl
->ToolBarsDestroyed();
498 //===== ToolBarManager::Implementation =======================================
500 ToolBarManager::Implementation::Implementation (
501 ViewShellBase
& rBase
,
502 std::shared_ptr
<sd::tools::EventMultiplexer
> pMultiplexer
,
503 const std::shared_ptr
<ViewShellManager
>& rpViewShellManager
,
504 const std::shared_ptr
<ToolBarManager
>& rpToolBarManager
)
506 mpEventMultiplexer(std::move(pMultiplexer
)),
509 mbPreUpdatePending(false),
510 mbPostUpdatePending(false),
511 mnPendingUpdateCall(nullptr),
512 mnPendingSetValidCall(nullptr),
513 maToolBarRules(rpToolBarManager
,rpViewShellManager
)
515 Link
<tools::EventMultiplexerEvent
&,void> aLink (LINK(this,ToolBarManager::Implementation
,EventMultiplexerCallback
));
516 mpEventMultiplexer
->AddEventListener( aLink
);
519 /** The order of statements is important.
520 First unregister listeners, which may post user events.
521 Then remove pending user events.
523 ToolBarManager::Implementation::~Implementation()
525 // Unregister at broadcasters.
526 Link
<tools::EventMultiplexerEvent
&,void> aLink (LINK(this,ToolBarManager::Implementation
,EventMultiplexerCallback
));
527 mpEventMultiplexer
->RemoveEventListener(aLink
);
529 // Abort pending user calls.
530 if (mnPendingUpdateCall
!= nullptr)
531 Application::RemoveUserEvent(mnPendingUpdateCall
);
532 if (mnPendingSetValidCall
!= nullptr)
533 Application::RemoveUserEvent(mnPendingSetValidCall
);
536 void ToolBarManager::Implementation::ToolBarsDestroyed()
538 maToolBarList
.MarkAllToolBarsAsNotActive();
541 void ToolBarManager::Implementation::SetValid (bool bValid
)
543 ::osl::MutexGuard
aGuard(maMutex
);
545 if (mbIsValid
== bValid
)
548 UpdateLockImplementation
aUpdateLock (*this);
553 Reference
<frame::XFrame
> xFrame
= mrBase
.GetViewFrame().GetFrame().GetFrameInterface();
556 Reference
<beans::XPropertySet
> xFrameProperties (xFrame
, UNO_QUERY_THROW
);
557 Any
aValue (xFrameProperties
->getPropertyValue(u
"LayoutManager"_ustr
));
558 aValue
>>= mxLayouter
;
559 // tdf#119997 if mpSynchronousLayouterLock was created before mxLayouter was
560 // set then update it now that its available
561 if (mpSynchronousLayouterLock
&& !mpSynchronousLayouterLock
->is())
562 mpSynchronousLayouterLock
.reset(new LayouterLock(mxLayouter
));
564 catch (const RuntimeException
&)
568 GetToolBarRules().Update(mrBase
);
573 mxLayouter
= nullptr;
577 void ToolBarManager::Implementation::ResetToolBars (ToolBarGroup eGroup
)
579 ::osl::MutexGuard
aGuard(maMutex
);
581 maToolBarList
.ClearGroup(eGroup
);
582 maToolBarShellList
.ClearGroup(eGroup
);
584 mbPreUpdatePending
= true;
587 void ToolBarManager::Implementation::ResetAllToolBars()
589 SAL_INFO("sd.view", __func__
<< ": resetting all tool bars");
590 for (auto i
: o3tl::enumrange
<ToolBarGroup
>())
594 void ToolBarManager::Implementation::AddToolBar (
596 const OUString
& rsToolBarName
)
598 ::osl::MutexGuard
aGuard(maMutex
);
600 if (CheckPlugInMode(rsToolBarName
))
602 maToolBarList
.AddToolBar(eGroup
,rsToolBarName
);
604 mbPostUpdatePending
= true;
605 if (mnLockCount
== 0)
610 void ToolBarManager::Implementation::RemoveToolBar (
612 const OUString
& rsToolBarName
)
614 ::osl::MutexGuard
aGuard(maMutex
);
616 if (maToolBarList
.RemoveToolBar(eGroup
,rsToolBarName
))
618 mbPreUpdatePending
= true;
619 if (mnLockCount
== 0)
624 void ToolBarManager::Implementation::AddToolBarShell (
629 ViewShell
* pMainViewShell
= mrBase
.GetMainViewShell().get();
630 if (pMainViewShell
!= nullptr)
632 maToolBarShellList
.AddShellId(eGroup
,nToolBarId
);
635 GetToolBarRules().SubShellAdded(eGroup
, nToolBarId
);
639 mbPostUpdatePending
= true;
640 if (mnLockCount
== 0)
646 void ToolBarManager::Implementation::ReleaseAllToolBarShells()
648 maToolBarShellList
.ReleaseAllShells(GetToolBarRules());
649 maToolBarShellList
.UpdateShells(mrBase
.GetMainViewShell(), mrBase
.GetViewShellManager());
652 void ToolBarManager::Implementation::RequestUpdate()
654 if (mnPendingUpdateCall
== nullptr)
656 mnPendingUpdateCall
= Application::PostUserEvent(
657 LINK(this,ToolBarManager::Implementation
,UpdateCallback
));
661 void ToolBarManager::Implementation::PreUpdate()
663 ::osl::MutexGuard
aGuard(maMutex
);
666 && mbPreUpdatePending
670 mbPreUpdatePending
= false;
672 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PreUpdate [");
674 // Get the list of tool bars that are not used anymore and are to be
676 std::vector
<OUString
> aToolBars
;
677 maToolBarList
.GetToolBarsToDeactivate(aToolBars
);
679 // Turn off the tool bars.
680 for (const auto& aToolBar
: aToolBars
)
682 OUString
sFullName (GetToolBarResourceName(aToolBar
));
683 SAL_INFO("sd.view", __func__
<< ": turning off tool bar " << sFullName
);
684 mxLayouter
->destroyElement(sFullName
);
685 maToolBarList
.MarkToolBarAsNotActive(aToolBar
);
688 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PreUpdate ]");
691 void ToolBarManager::Implementation::PostUpdate()
693 ::osl::MutexGuard
aGuard(maMutex
);
696 && mbPostUpdatePending
700 mbPostUpdatePending
= false;
702 // Create the list of requested tool bars.
703 std::vector
<OUString
> aToolBars
;
704 maToolBarList
.GetToolBarsToActivate(aToolBars
);
706 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PostUpdate [");
708 // Turn on the tool bars that are visible in the new context.
709 for (const auto& aToolBar
: aToolBars
)
711 OUString
sFullName (GetToolBarResourceName(aToolBar
));
712 SAL_INFO("sd.view", __func__
<< ": turning on tool bar " << sFullName
);
713 mxLayouter
->requestElement(sFullName
);
714 maToolBarList
.MarkToolBarAsActive(aToolBar
);
717 SAL_INFO("sd.view", __func__
<< ": ToolBarManager::PostUpdate ]");
720 void ToolBarManager::Implementation::LockViewShellManager()
722 if (mpViewShellManagerLock
== nullptr)
723 mpViewShellManagerLock
.reset(
724 new ViewShellManager::UpdateLock(mrBase
.GetViewShellManager()));
727 void ToolBarManager::Implementation::LockUpdate()
729 SAL_INFO("sd.view", __func__
<< ": LockUpdate " << mnLockCount
);
730 ::osl::MutexGuard
aGuard(maMutex
);
732 DBG_ASSERT(mnLockCount
<100, "ToolBarManager lock count unusually high");
733 if (mnLockCount
== 0)
735 OSL_ASSERT(mpSynchronousLayouterLock
== nullptr);
737 mpSynchronousLayouterLock
.reset(new LayouterLock(mxLayouter
));
742 void ToolBarManager::Implementation::UnlockUpdate()
744 SAL_INFO("sd.view", __func__
<< ": UnlockUpdate " << mnLockCount
);
745 ::osl::MutexGuard
aGuard(maMutex
);
747 OSL_ASSERT(mnLockCount
>0);
749 if (mnLockCount
== 0)
751 Update(std::move(mpSynchronousLayouterLock
));
755 void ToolBarManager::Implementation::Update (
756 ::std::unique_ptr
<LayouterLock
> pLocalLayouterLock
)
758 // When the lock is released and there are pending changes to the set of
759 // tool bars then update this set now.
760 if (mnLockCount
!= 0)
763 // During creation of ViewShellBase we may have the situation that
764 // the controller has already been created and attached to the frame
765 // but that the ToolBarManager has not yet completed its
766 // initialization (by initializing the mxLayouter member.) We do
767 // this here so that we do not have to wait for the next Update()
768 // call to show the tool bars.
769 if (mnPendingSetValidCall
!= nullptr)
771 Application::RemoveUserEvent(mnPendingSetValidCall
);
772 mnPendingSetValidCall
= nullptr;
776 if (mbIsValid
&& mxLayouter
.is() && (mbPreUpdatePending
|| mbPostUpdatePending
))
778 // 1) Release UNO tool bars that are no longer used. Do this
779 // now so that they are not updated when the SFX shell stack is
781 if (mbPreUpdatePending
)
784 // 2) Update the requested shells that represent tool bar
785 // functionality. Those that are not used anymore are
786 // deactivated now. Those that are missing are activated in the
787 // next step together with the view shells.
788 if (mpViewShellManagerLock
== nullptr)
789 mpViewShellManagerLock
.reset(
790 new ViewShellManager::UpdateLock(mrBase
.GetViewShellManager()));
791 maToolBarShellList
.UpdateShells(
792 mrBase
.GetMainViewShell(),
793 mrBase
.GetViewShellManager());
795 // 3) Unlock the ViewShellManager::UpdateLock. This updates the
797 mpViewShellManagerLock
.reset();
799 // 4) Make the UNO tool bars visible. The outstanding call to
800 // PostUpdate() is done via PostUserEvent() so that it is
801 // guaranteed to be executed when the SFX shell stack has been
802 // updated (under the assumption that our lock to the
803 // ViewShellManager was the only one open. If that is not the
804 // case then all should still be well but not as fast.)
806 // Note that the lock count may have been increased since
807 // entering this method. In that case one of the next
808 // UnlockUpdate() calls will post the UpdateCallback.
811 mpAsynchronousLayouterLock
= std::move(pLocalLayouterLock
);
812 if (mnPendingUpdateCall
==nullptr)
814 mnPendingUpdateCall
= Application::PostUserEvent(
815 LINK(this,ToolBarManager::Implementation
,UpdateCallback
));
821 mpViewShellManagerLock
.reset();
822 pLocalLayouterLock
.reset();
826 IMPL_LINK_NOARG(ToolBarManager::Implementation
, UpdateCallback
, void*, void)
828 mnPendingUpdateCall
= nullptr;
829 if (mnLockCount
== 0)
831 if (mbPreUpdatePending
)
833 if (mbPostUpdatePending
)
835 if (mbIsValid
&& mxLayouter
.is())
836 mpAsynchronousLayouterLock
.reset();
840 IMPL_LINK(ToolBarManager::Implementation
,EventMultiplexerCallback
,
841 sd::tools::EventMultiplexerEvent
&, rEvent
, void)
844 switch (rEvent
.meEventId
)
846 case EventMultiplexerEventId::ControllerAttached
:
847 if (mnPendingSetValidCall
== nullptr)
848 mnPendingSetValidCall
849 = Application::PostUserEvent(LINK(this,Implementation
,SetValidCallback
));
852 case EventMultiplexerEventId::ControllerDetached
:
860 IMPL_LINK_NOARG(ToolBarManager::Implementation
, SetValidCallback
, void*, void)
862 mnPendingSetValidCall
= nullptr;
866 OUString
ToolBarManager::Implementation::GetToolBarResourceName (
867 std::u16string_view rsBaseName
)
869 return OUString::Concat("private:resource/toolbar/") + rsBaseName
;
872 bool ToolBarManager::Implementation::CheckPlugInMode (std::u16string_view rsName
) const
876 // Determine the plug in mode.
877 bool bIsPlugInMode (false);
880 SfxObjectShell
* pObjectShell
= mrBase
.GetObjectShell();
881 if (pObjectShell
== nullptr)
884 SfxMedium
* pMedium
= pObjectShell
->GetMedium();
885 if (pMedium
== nullptr)
888 const SfxBoolItem
* pViewOnlyItem
= pMedium
->GetItemSet().GetItem(SID_VIEWONLY
, false);
889 if (pViewOnlyItem
== nullptr)
892 bIsPlugInMode
= pViewOnlyItem
->GetValue();
896 if (rsName
== msViewerToolBar
)
897 bValid
= bIsPlugInMode
;
899 bValid
= ! bIsPlugInMode
;
904 } // end of namespace sd
908 using namespace ::sd
;
910 //===== LayouterLock ==========================================================
912 LayouterLock::LayouterLock (const Reference
<frame::XLayoutManager
>& rxLayouter
)
913 : mxLayouter(rxLayouter
)
915 SAL_INFO("sd.view", __func__
<< ": LayouterLock " << (mxLayouter
.is() ? 1 :0));
920 LayouterLock::~LayouterLock()
922 SAL_INFO("sd.view", __func__
<< ": ~LayouterLock " << (mxLayouter
.is() ? 1 :0));
924 mxLayouter
->unlock();
927 //===== ToolBarRules ==========================================================
929 ToolBarRules::ToolBarRules (
930 std::shared_ptr
<sd::ToolBarManager
> pToolBarManager
,
931 std::shared_ptr
<sd::ViewShellManager
> pViewShellManager
)
932 : mpToolBarManager(std::move(pToolBarManager
)),
933 mpViewShellManager(std::move(pViewShellManager
))
937 void ToolBarRules::Update (ViewShellBase
const & rBase
)
939 ViewShell
* pMainViewShell
= rBase
.GetMainViewShell().get();
940 if (pMainViewShell
!= nullptr)
942 MainViewShellChanged(pMainViewShell
->GetShellType());
943 if (pMainViewShell
->GetView())
944 SelectionHasChanged (*pMainViewShell
, *pMainViewShell
->GetView());
947 MainViewShellChanged(ViewShell::ST_NONE
);
950 void ToolBarRules::MainViewShellChanged (ViewShell::ShellType nShellType
)
952 ::sd::ToolBarManager::UpdateLock
aToolBarManagerLock (mpToolBarManager
);
953 ::sd::ViewShellManager::UpdateLock
aViewShellManagerLock (mpViewShellManager
);
955 mpToolBarManager
->ResetAllToolBars();
959 case ::sd::ViewShell::ST_IMPRESS
:
960 case ::sd::ViewShell::ST_NOTES
:
961 case ::sd::ViewShell::ST_HANDOUT
:
962 case ::sd::ViewShell::ST_DRAW
:
963 mpToolBarManager
->AddToolBar(
964 ToolBarManager::ToolBarGroup::Permanent
,
965 ToolBarManager::msToolBar
);
966 mpToolBarManager
->AddToolBar(
967 ToolBarManager::ToolBarGroup::Permanent
,
968 ToolBarManager::msOptionsToolBar
);
969 mpToolBarManager
->AddToolBar(
970 ToolBarManager::ToolBarGroup::Permanent
,
971 ToolBarManager::msViewerToolBar
);
974 case ::sd::ViewShell::ST_NOTESPANEL
:
975 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Permanent
,
976 ToolbarId::Draw_Text_Toolbox_Sd
);
979 case ViewShell::ST_OUTLINE
:
980 mpToolBarManager
->AddToolBar(
981 ToolBarManager::ToolBarGroup::Permanent
,
982 ToolBarManager::msOutlineToolBar
);
983 mpToolBarManager
->AddToolBar(
984 ToolBarManager::ToolBarGroup::Permanent
,
985 ToolBarManager::msViewerToolBar
);
986 mpToolBarManager
->AddToolBarShell(
987 ToolBarManager::ToolBarGroup::Permanent
, ToolbarId::Draw_Text_Toolbox_Sd
);
990 case ViewShell::ST_SLIDE_SORTER
:
991 mpToolBarManager
->AddToolBar(
992 ToolBarManager::ToolBarGroup::Permanent
,
993 ToolBarManager::msViewerToolBar
);
994 mpToolBarManager
->AddToolBar(
995 ToolBarManager::ToolBarGroup::Permanent
,
996 ToolBarManager::msSlideSorterToolBar
);
997 mpToolBarManager
->AddToolBar(
998 ToolBarManager::ToolBarGroup::Permanent
,
999 ToolBarManager::msSlideSorterObjectBar
);
1002 case ViewShell::ST_NONE
:
1003 case ViewShell::ST_PRESENTATION
:
1004 case ViewShell::ST_SIDEBAR
:
1010 void ToolBarRules::MainViewShellChanged (const ViewShell
& rMainViewShell
)
1012 ::sd::ToolBarManager::UpdateLock
aToolBarManagerLock (mpToolBarManager
);
1013 ::sd::ViewShellManager::UpdateLock
aViewShellManagerLock (mpViewShellManager
);
1015 MainViewShellChanged(rMainViewShell
.GetShellType());
1016 switch(rMainViewShell
.GetShellType())
1018 case ::sd::ViewShell::ST_IMPRESS
:
1019 case ::sd::ViewShell::ST_DRAW
:
1020 case ::sd::ViewShell::ST_NOTES
:
1022 const DrawViewShell
* pDrawViewShell
1023 = dynamic_cast<const DrawViewShell
*>(&rMainViewShell
);
1024 if (pDrawViewShell
!= nullptr)
1026 if (pDrawViewShell
->GetEditMode() == EditMode::MasterPage
)
1027 mpToolBarManager
->AddToolBar(
1028 ToolBarManager::ToolBarGroup::MasterMode
,
1029 ToolBarManager::msMasterViewToolBar
);
1030 else if ( rMainViewShell
.GetShellType() != ::sd::ViewShell::ST_DRAW
)
1031 mpToolBarManager
->AddToolBar(
1032 ToolBarManager::ToolBarGroup::CommonTask
,
1033 ToolBarManager::msCommonTaskToolBar
);
1043 void ToolBarRules::SelectionHasChanged (
1044 const ::sd::ViewShell
& rViewShell
,
1045 const SdrView
& rView
)
1047 ::sd::ToolBarManager::UpdateLock
aLock (mpToolBarManager
);
1048 mpToolBarManager
->LockViewShellManager();
1049 bool bTextEdit
= rView
.IsTextEdit();
1051 mpToolBarManager
->ResetToolBars(ToolBarManager::ToolBarGroup::Function
);
1053 switch (rView
.GetContext())
1055 case SdrViewContext::Graphic
:
1057 mpToolBarManager
->SetToolBarShell(ToolBarManager::ToolBarGroup::Function
,
1058 ToolbarId::Draw_Graf_Toolbox
);
1061 case SdrViewContext::Media
:
1063 mpToolBarManager
->SetToolBarShell(ToolBarManager::ToolBarGroup::Function
,
1064 ToolbarId::Draw_Media_Toolbox
);
1067 case SdrViewContext::Table
:
1068 mpToolBarManager
->SetToolBarShell(ToolBarManager::ToolBarGroup::Function
,
1069 ToolbarId::Draw_Table_Toolbox
);
1073 case SdrViewContext::Standard
:
1077 switch(rViewShell
.GetShellType())
1079 case ::sd::ViewShell::ST_IMPRESS
:
1080 case ::sd::ViewShell::ST_DRAW
:
1081 case ::sd::ViewShell::ST_NOTES
:
1082 case ::sd::ViewShell::ST_HANDOUT
:
1083 mpToolBarManager
->SetToolBar(ToolBarManager::ToolBarGroup::Function
,
1084 ToolBarManager::msDrawingObjectToolBar
);
1085 mpToolBarManager
->SetToolBar(ToolBarManager::ToolBarGroup::Permanent
,
1086 ToolBarManager::msToolBar
);
1096 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Draw_Text_Toolbox_Sd
);
1098 SdrView
* pView
= &const_cast<SdrView
&>(rView
);
1099 // Check if the extrusion tool bar and the fontwork tool bar have to
1101 if (svx::checkForSelectedCustomShapes(pView
, true /* bOnlyExtruded */ ))
1102 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Svx_Extrusion_Bar
);
1104 if (svx::checkForSelectedFontWork(pView
))
1105 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Svx_Fontwork_Bar
);
1107 // Switch on additional context-sensitive tool bars.
1108 if (rView
.GetContext() == SdrViewContext::PointEdit
)
1109 mpToolBarManager
->AddToolBarShell(ToolBarManager::ToolBarGroup::Function
, ToolbarId::Bezier_Toolbox_Sd
);
1112 void ToolBarRules::SubShellAdded (
1113 ::sd::ToolBarManager::ToolBarGroup eGroup
,
1114 sd::ShellId nShellId
)
1116 // For some tool bar shells (those defined in sd) we have to add the
1117 // actual tool bar here.
1120 case ToolbarId::Draw_Graf_Toolbox
:
1121 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msGraphicObjectBar
);
1124 case ToolbarId::Draw_Media_Toolbox
:
1125 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msMediaObjectBar
);
1128 case ToolbarId::Draw_Text_Toolbox_Sd
:
1129 mpToolBarManager
->RemoveToolBar(ToolBarManager::ToolBarGroup::Permanent
, ToolBarManager::msToolBar
);
1130 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msTextObjectBar
);
1133 case ToolbarId::Bezier_Toolbox_Sd
:
1134 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msBezierObjectBar
);
1137 case ToolbarId::Draw_Table_Toolbox
:
1138 // tdf#142489 Do not show the table toolbar when the Notebookbar UI is active
1139 if (!sfx2::SfxNotebookBar::IsActive(true))
1140 mpToolBarManager
->AddToolBar(eGroup
, ToolBarManager::msTableObjectBar
);
1148 void ToolBarRules::SubShellRemoved (
1149 ::sd::ToolBarManager::ToolBarGroup eGroup
,
1150 sd::ShellId nShellId
)
1152 // For some tool bar shells (those defined in sd) we have to add the
1153 // actual tool bar here.
1156 case ToolbarId::Draw_Graf_Toolbox
:
1157 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msGraphicObjectBar
);
1160 case ToolbarId::Draw_Media_Toolbox
:
1161 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msMediaObjectBar
);
1164 case ToolbarId::Draw_Text_Toolbox_Sd
:
1165 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msTextObjectBar
);
1168 case ToolbarId::Bezier_Toolbox_Sd
:
1169 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msBezierObjectBar
);
1172 case ToolbarId::Draw_Table_Toolbox
:
1173 mpToolBarManager
->RemoveToolBar(eGroup
, ToolBarManager::msTableObjectBar
);
1181 //===== ToolBarList ===========================================================
1183 ToolBarList::ToolBarList()
1187 void ToolBarList::ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
)
1189 Groups::iterator
iGroup (maGroups
.find(eGroup
));
1190 if (iGroup
!= maGroups
.end())
1192 iGroup
->second
.clear();
1196 void ToolBarList::AddToolBar (
1197 sd::ToolBarManager::ToolBarGroup eGroup
,
1198 const OUString
& rsName
)
1200 Groups::iterator
iGroup (maGroups
.find(eGroup
));
1201 if (iGroup
== maGroups
.end())
1202 iGroup
= maGroups
.emplace(eGroup
,std::vector
<OUString
>()).first
;
1204 if (iGroup
!= maGroups
.end())
1206 auto iBar (std::find(iGroup
->second
.cbegin(),iGroup
->second
.cend(),rsName
));
1207 if (iBar
== iGroup
->second
.cend())
1209 iGroup
->second
.push_back(rsName
);
1214 bool ToolBarList::RemoveToolBar (
1215 sd::ToolBarManager::ToolBarGroup eGroup
,
1216 const OUString
& rsName
)
1218 Groups::iterator
iGroup (maGroups
.find(eGroup
));
1219 if (iGroup
!= maGroups
.end())
1221 auto iBar (std::find(iGroup
->second
.begin(),iGroup
->second
.end(),rsName
));
1222 if (iBar
!= iGroup
->second
.end())
1224 iGroup
->second
.erase(iBar
);
1231 void ToolBarList::MakeRequestedToolBarList (std::vector
<OUString
>& rRequestedToolBars
) const
1233 for (auto eGroup
: o3tl::enumrange
<sd::ToolBarManager::ToolBarGroup
>())
1235 Groups::const_iterator
iGroup (maGroups
.find(eGroup
));
1236 if (iGroup
!= maGroups
.end())
1237 rRequestedToolBars
.insert( rRequestedToolBars
.end(),
1238 iGroup
->second
.begin(),
1239 iGroup
->second
.end() );
1243 void ToolBarList::GetToolBarsToActivate (std::vector
<OUString
>& rToolBars
) const
1245 std::vector
<OUString
> aRequestedToolBars
;
1246 MakeRequestedToolBarList(aRequestedToolBars
);
1248 for (const auto& aToolBar
: aRequestedToolBars
)
1250 if (::std::find(maActiveToolBars
.begin(),maActiveToolBars
.end(),aToolBar
)
1251 == maActiveToolBars
.end())
1253 rToolBars
.push_back(aToolBar
);
1258 void ToolBarList::GetToolBarsToDeactivate (std::vector
<OUString
>& rToolBars
) const
1260 std::vector
<OUString
> aRequestedToolBars
;
1261 MakeRequestedToolBarList(aRequestedToolBars
);
1263 for (auto& aToolBar
: maActiveToolBars
)
1265 if (::std::find(aRequestedToolBars
.begin(),aRequestedToolBars
.end(),aToolBar
)
1266 == aRequestedToolBars
.end())
1268 rToolBars
.push_back(aToolBar
);
1273 void ToolBarList::MarkToolBarAsActive (const OUString
& rsName
)
1275 maActiveToolBars
.push_back(rsName
);
1278 void ToolBarList::MarkToolBarAsNotActive (const OUString
& rsName
)
1280 maActiveToolBars
.erase(
1281 ::std::find(maActiveToolBars
.begin(),maActiveToolBars
.end(), rsName
));
1284 void ToolBarList::MarkAllToolBarsAsNotActive()
1286 maActiveToolBars
.clear();
1289 //===== ToolBarShellList ======================================================
1291 ToolBarShellList::ShellDescriptor::ShellDescriptor (
1293 sd::ToolBarManager::ToolBarGroup eGroup
)
1299 ToolBarShellList::ToolBarShellList()
1303 void ToolBarShellList::ClearGroup (sd::ToolBarManager::ToolBarGroup eGroup
)
1305 for (GroupedShellList::iterator iDescriptor
= maNewList
.begin(); iDescriptor
!= maNewList
.end(); )
1306 if (iDescriptor
->meGroup
== eGroup
)
1307 iDescriptor
= maNewList
.erase(iDescriptor
);
1312 void ToolBarShellList::AddShellId (sd::ToolBarManager::ToolBarGroup eGroup
, sd::ShellId nId
)
1314 // Make sure that the shell is not added twice (and possibly in
1315 // different groups.)
1316 ShellDescriptor
aDescriptor (nId
,eGroup
);
1317 GroupedShellList::iterator
iDescriptor (maNewList
.find(aDescriptor
));
1318 if (iDescriptor
!= maNewList
.end())
1320 // The shell is already requested.
1321 if (iDescriptor
->meGroup
!= eGroup
)
1323 // It is now being requested for another group.
1324 // (Is this an error?)
1325 // Move it to that group.
1326 maNewList
.erase(iDescriptor
);
1327 maNewList
.insert(aDescriptor
);
1329 // else nothing to do.
1332 maNewList
.insert(aDescriptor
);
1335 void ToolBarShellList::ReleaseAllShells (ToolBarRules
& rRules
)
1337 // Release the currently active tool bars.
1338 GroupedShellList
aList (maCurrentList
);
1339 for (const auto& rDescriptor
: aList
)
1341 rRules
.SubShellRemoved(rDescriptor
.meGroup
, rDescriptor
.mnId
);
1344 // Clear the list of requested tool bars.
1348 void ToolBarShellList::UpdateShells (
1349 const std::shared_ptr
<ViewShell
>& rpMainViewShell
,
1350 const std::shared_ptr
<ViewShellManager
>& rpManager
)
1352 if (rpMainViewShell
== nullptr)
1355 const std::shared_ptr
<ViewShell
> pCurrentMainViewShell
1356 = rpManager
->GetOverridingMainShell() ? rpManager
->GetOverridingMainShell() : rpMainViewShell
;
1358 GroupedShellList aList
;
1360 // Deactivate shells that are in maCurrentList, but not in
1362 ::std::set_difference(maCurrentList
.begin(), maCurrentList
.end(),
1363 maNewList
.begin(), maNewList
.end(),
1364 std::insert_iterator
<GroupedShellList
>(aList
,aList
.begin()));
1365 for (const auto& rShell
: aList
)
1367 SAL_INFO("sd.view", __func__
<< ": deactivating tool bar shell " << static_cast<sal_uInt32
>(rShell
.mnId
));
1368 rpManager
->DeactivateSubShell(*pCurrentMainViewShell
, rShell
.mnId
);
1371 // Activate shells that are in maNewList, but not in
1374 ::std::set_difference(maNewList
.begin(), maNewList
.end(),
1375 maCurrentList
.begin(), maCurrentList
.end(),
1376 std::insert_iterator
<GroupedShellList
>(aList
,aList
.begin()));
1377 for (const auto& rShell
: aList
)
1379 SAL_INFO("sd.view", __func__
<< ": activating tool bar shell " << static_cast<sal_uInt32
>(rShell
.mnId
));
1380 rpManager
->ActivateSubShell(*pCurrentMainViewShell
, rShell
.mnId
);
1383 // The maNewList now reflects the current state and thus is made
1385 maCurrentList
= maNewList
;
1388 } // end of anonymous namespace
1390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */