android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / ui / view / ToolBarManager.cxx
blobedd39c73110ba8fcfb1ad2bc7e011fc49bf6c39c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
43 #include <utility>
44 #include <vcl/svapp.hxx>
45 #include <osl/diagnose.h>
47 #include <map>
48 #include <memory>
49 #include <string_view>
50 #include <vector>
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
55 namespace {
57 using namespace sd;
59 class ToolBarRules;
61 /** Lock of the frame::XLayoutManager.
63 class LayouterLock
65 Reference<frame::XLayoutManager> mxLayouter;
66 public:
67 explicit LayouterLock (const Reference<frame::XLayoutManager>& rxLayouter);
68 ~LayouterLock();
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.
75 class ToolBarList
77 public:
78 ToolBarList();
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();
91 private:
92 typedef ::std::map<sd::ToolBarManager::ToolBarGroup, std::vector<OUString> > Groups;
93 Groups maGroups;
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
112 separately.
114 class ToolBarShellList
116 public:
117 /** Create a new object with an empty current list and an empty
118 requested list.
120 ToolBarShellList();
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.
125 @param eGroup
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.
132 @param eGroup
133 The group to which to add the shell.
134 @param nId
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
151 this view shell.
152 @param rManager
153 This ViewShellManager is used to activate or deactivate shells.
155 void UpdateShells (
156 const std::shared_ptr<ViewShell>& rpMainViewShell,
157 const std::shared_ptr<ViewShellManager>& rpManager);
159 private:
160 class ShellDescriptor
161 {public:
162 ShellDescriptor (ShellId nId,sd::ToolBarManager::ToolBarGroup eGroup);
163 ShellId mnId;
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
183 in one place.
185 class ToolBarRules
187 public:
188 ToolBarRules (
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.
216 void SubShellAdded (
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);
226 private:
227 std::shared_ptr<ToolBarManager> mpToolBarManager;
228 std::shared_ptr<ViewShellManager> mpViewShellManager;
231 } // end of anonymous namespace
233 namespace sd {
235 //===== ToolBarManager::Implementation ========================================
237 class ToolBarManager::Implementation
239 public:
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.
246 Implementation (
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);
251 ~Implementation();
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();
273 void PreUpdate();
274 void PostUpdate();
275 /** Tell the XLayoutManager about the tool bars that we would like to be
276 shown.
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
286 public:
287 explicit UpdateLockImplementation (Implementation& rImplementation)
288 : mrImplementation(rImplementation) { mrImplementation.LockUpdate(); }
289 ~UpdateLockImplementation() { mrImplementation.UnlockUpdate(); }
290 private:
291 Implementation& mrImplementation;
294 void LockViewShellManager();
295 void LockUpdate();
296 void UnlockUpdate();
298 ToolBarRules& GetToolBarRules() { return maToolBarRules;}
300 private:
301 mutable ::osl::Mutex maMutex;
302 ViewShellBase& mrBase;
303 std::shared_ptr<sd::tools::EventMultiplexer> mpEventMultiplexer;
304 bool mbIsValid;
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));
341 return pManager;
344 ToolBarManager::ToolBarManager()
348 ToolBarManager::~ToolBarManager()
352 void ToolBarManager::Shutdown()
354 if (mpImpl != nullptr)
355 mpImpl.reset();
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 (
377 ToolBarGroup eGroup,
378 const OUString& rsToolBarName)
380 if (mpImpl != nullptr)
382 UpdateLock aLock (shared_from_this());
383 mpImpl->AddToolBar(eGroup,rsToolBarName);
387 void ToolBarManager::AddToolBarShell (
388 ToolBarGroup eGroup,
389 ShellId nToolBarId)
391 if (mpImpl != nullptr)
393 UpdateLock aLock (shared_from_this());
394 mpImpl->AddToolBarShell(eGroup,nToolBarId);
398 void ToolBarManager::RemoveToolBar (
399 ToolBarGroup eGroup,
400 const OUString& rsToolBarName)
402 if (mpImpl != nullptr)
404 UpdateLock aLock (shared_from_this());
405 mpImpl->RemoveToolBar(eGroup,rsToolBarName);
409 void ToolBarManager::SetToolBar (
410 ToolBarGroup eGroup,
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 (
422 ToolBarGroup eGroup,
423 ShellId nToolBarId)
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)
436 mpImpl->PreUpdate();
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)
502 : mrBase(rBase),
503 mpEventMultiplexer(std::move(pMultiplexer)),
504 mbIsValid(false),
505 mnLockCount(0),
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)
543 return;
545 UpdateLockImplementation aUpdateLock (*this);
547 mbIsValid = bValid;
548 if (mbIsValid)
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);
567 else
569 ResetAllToolBars();
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>())
588 ResetToolBars(i);
591 void ToolBarManager::Implementation::AddToolBar (
592 ToolBarGroup eGroup,
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)
603 PostUpdate();
607 void ToolBarManager::Implementation::RemoveToolBar (
608 ToolBarGroup eGroup,
609 const OUString& rsToolBarName)
611 ::osl::MutexGuard aGuard(maMutex);
613 if (maToolBarList.RemoveToolBar(eGroup,rsToolBarName))
615 mbPreUpdatePending = true;
616 if (mnLockCount == 0)
617 PreUpdate();
621 void ToolBarManager::Implementation::AddToolBarShell (
622 ToolBarGroup eGroup,
623 ShellId nToolBarId)
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);
652 if (!(mbIsValid
653 && mbPreUpdatePending
654 && mxLayouter.is()))
655 return;
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
662 // deactivated.
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);
682 if (!(mbIsValid
683 && mbPostUpdatePending
684 && mxLayouter.is()))
685 return;
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));
726 ++mnLockCount;
729 void ToolBarManager::Implementation::UnlockUpdate()
731 SAL_INFO("sd.view", __func__ << ": UnlockUpdate " << mnLockCount);
732 ::osl::MutexGuard aGuard(maMutex);
734 OSL_ASSERT(mnLockCount>0);
735 --mnLockCount;
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)
748 return;
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;
760 SetValid(true);
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
767 // modified.
768 if (mbPreUpdatePending)
769 PreUpdate();
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
783 // shell stack.
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.
796 if (mnLockCount==0)
798 mpAsynchronousLayouterLock = std::move(pLocalLayouterLock);
799 if (mnPendingUpdateCall==nullptr)
801 mnPendingUpdateCall = Application::PostUserEvent(
802 LINK(this,ToolBarManager::Implementation,UpdateCallback));
806 else
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)
819 PreUpdate();
820 if (mbPostUpdatePending)
821 PostUpdate();
822 if (mbIsValid && mxLayouter.is())
823 mpAsynchronousLayouterLock.reset();
827 IMPL_LINK(ToolBarManager::Implementation,EventMultiplexerCallback,
828 sd::tools::EventMultiplexerEvent&, rEvent, void)
830 SolarMutexGuard g;
831 switch (rEvent.meEventId)
833 case EventMultiplexerEventId::ControllerAttached:
834 if (mnPendingSetValidCall == nullptr)
835 mnPendingSetValidCall
836 = Application::PostUserEvent(LINK(this,Implementation,SetValidCallback));
837 break;
839 case EventMultiplexerEventId::ControllerDetached:
840 SetValid(false);
841 break;
843 default: break;
847 IMPL_LINK_NOARG(ToolBarManager::Implementation, SetValidCallback, void*, void)
849 mnPendingSetValidCall = nullptr;
850 SetValid(true);
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
861 bool bValid (false);
863 // Determine the plug in mode.
864 bool bIsPlugInMode (false);
867 SfxObjectShell* pObjectShell = mrBase.GetObjectShell();
868 if (pObjectShell == nullptr)
869 break;
871 SfxMedium* pMedium = pObjectShell->GetMedium();
872 if (pMedium == nullptr)
873 break;
875 const SfxBoolItem* pViewOnlyItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_VIEWONLY, false);
876 if (pViewOnlyItem == nullptr)
877 break;
879 bIsPlugInMode = pViewOnlyItem->GetValue();
881 while (false);
883 if (rsName == msViewerToolBar)
884 bValid = bIsPlugInMode;
885 else
886 bValid = ! bIsPlugInMode;
888 return bValid;
891 } // end of namespace sd
893 namespace {
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));
903 if (mxLayouter.is())
904 mxLayouter->lock();
907 LayouterLock::~LayouterLock()
909 SAL_INFO("sd.view", __func__ << ": ~LayouterLock " << (mxLayouter.is() ? 1 :0));
910 if (mxLayouter.is())
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());
933 else
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();
944 switch(nShellType)
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);
958 break;
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);
970 break;
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);
981 break;
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);
993 break;
995 case ViewShell::ST_NONE:
996 case ViewShell::ST_PRESENTATION:
997 case ViewShell::ST_SIDEBAR:
998 default:
999 break;
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);
1028 break;
1031 default:
1032 break;
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:
1049 if( !bTextEdit )
1050 mpToolBarManager->SetToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Graf_Toolbox);
1051 break;
1053 case SdrViewContext::Media:
1054 if( !bTextEdit )
1055 mpToolBarManager->SetToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Media_Toolbox);
1056 break;
1058 case SdrViewContext::Table:
1059 mpToolBarManager->SetToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Table_Toolbox);
1060 bTextEdit = true;
1061 break;
1063 case SdrViewContext::Standard:
1064 default:
1065 if( !bTextEdit )
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);
1076 break;
1077 default:
1078 break;
1080 break;
1084 if( bTextEdit )
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
1089 // be activated.
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.
1107 switch (nShellId)
1109 case ToolbarId::Draw_Graf_Toolbox:
1110 mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msGraphicObjectBar);
1111 break;
1113 case ToolbarId::Draw_Media_Toolbox:
1114 mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msMediaObjectBar);
1115 break;
1117 case ToolbarId::Draw_Text_Toolbox_Sd:
1118 mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msTextObjectBar);
1119 break;
1121 case ToolbarId::Bezier_Toolbox_Sd:
1122 mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msBezierObjectBar);
1123 break;
1125 case ToolbarId::Draw_Table_Toolbox:
1126 mpToolBarManager->AddToolBar(eGroup, ToolBarManager::msTableObjectBar);
1127 break;
1129 default:
1130 break;
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.
1140 switch (nShellId)
1142 case ToolbarId::Draw_Graf_Toolbox:
1143 mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msGraphicObjectBar);
1144 break;
1146 case ToolbarId::Draw_Media_Toolbox:
1147 mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msMediaObjectBar);
1148 break;
1150 case ToolbarId::Draw_Text_Toolbox_Sd:
1151 mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msTextObjectBar);
1152 break;
1154 case ToolbarId::Bezier_Toolbox_Sd:
1155 mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msBezierObjectBar);
1156 break;
1158 case ToolbarId::Draw_Table_Toolbox:
1159 mpToolBarManager->RemoveToolBar(eGroup, ToolBarManager::msTableObjectBar);
1160 break;
1162 default:
1163 break;
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);
1211 return true;
1214 return false;
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 (
1278 ShellId nId,
1279 sd::ToolBarManager::ToolBarGroup eGroup)
1280 : mnId(nId),
1281 meGroup(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);
1294 else
1295 ++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.
1317 else
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.
1331 maNewList.clear();
1334 void ToolBarShellList::UpdateShells (
1335 const std::shared_ptr<ViewShell>& rpMainViewShell,
1336 const std::shared_ptr<ViewShellManager>& rpManager)
1338 if (rpMainViewShell == nullptr)
1339 return;
1341 GroupedShellList aList;
1343 // Deactivate shells that are in maCurrentList, but not in
1344 // maNewList.
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
1355 // maCurrentList.
1356 aList.clear();
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
1367 // maCurrentList.
1368 maCurrentList = maNewList;
1371 } // end of anonymous namespace
1373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */