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