Line data Source code
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 :
21 : #include "ViewShellManager.hxx"
22 : #include "ViewShell.hxx"
23 : #include "ViewShellBase.hxx"
24 : #include "Window.hxx"
25 : #include "DrawDocShell.hxx"
26 : #include "FormShellManager.hxx"
27 :
28 : #include <sfx2/dispatch.hxx>
29 : #include <svx/svxids.hrc>
30 : #include <svx/fmshell.hxx>
31 :
32 : #include <boost/unordered_map.hpp>
33 : #include <iterator>
34 :
35 : namespace sd {
36 :
37 : namespace {
38 :
39 : /** The ShellDescriptor class is used to shells together with their ids and
40 : the factory that was used to create the shell.
41 :
42 : The shell pointer may be NULL. In that case the shell is created on
43 : demand by a factory.
44 :
45 : The factory pointer may be NULL. In that case the shell pointer is
46 : given to the ViewShellManager.
47 :
48 : Shell pointer and factory pointer can but should not be NULL at the same
49 : time.
50 : */
51 1085 : class ShellDescriptor {
52 : public:
53 : SfxShell* mpShell;
54 : ShellId mnId;
55 : ViewShellManager::SharedShellFactory mpFactory;
56 : bool mbIsListenerAddedToWindow;
57 :
58 : ShellDescriptor ();
59 : ShellDescriptor (SfxShell* pShell, ShellId nId);
60 : ShellDescriptor (const ShellDescriptor& rDescriptor);
61 : ShellDescriptor& operator= (const ShellDescriptor& rDescriptor);
62 : bool IsMainViewShell (void) const;
63 : ::Window* GetWindow (void) const;
64 : };
65 :
66 :
67 :
68 :
69 : /** This functor can be used to search for a shell in an STL container when the
70 : shell pointer is given.
71 : */
72 : class IsShell : public ::std::unary_function<ShellDescriptor,bool>
73 : {
74 : public:
75 367 : IsShell (const SfxShell* pShell) : mpShell(pShell) {}
76 477 : bool operator() (const ShellDescriptor& rDescriptor)
77 477 : { return rDescriptor.mpShell == mpShell; }
78 : private:
79 : const SfxShell* mpShell;
80 : };
81 :
82 :
83 :
84 :
85 : /** This functor can be used to search for a shell in an STL container when the
86 : id of the shell is given.
87 : */
88 : class IsId : public ::std::unary_function<ShellDescriptor,bool>
89 : {
90 : public:
91 7005 : IsId (ShellId nId) : mnId(nId) {}
92 14834 : bool operator() (const ShellDescriptor& rDescriptor)
93 14834 : { return rDescriptor.mnId == mnId; }
94 : private:
95 : ShellId mnId;
96 : };
97 :
98 : } // end of anonymous namespace
99 :
100 :
101 :
102 :
103 : class ViewShellManager::Implementation
104 : {
105 : public:
106 : Implementation (
107 : ViewShellManager& rManager,
108 : ViewShellBase& rBase);
109 : ~Implementation (void);
110 :
111 : void AddShellFactory (
112 : const SfxShell* pViewShell,
113 : const SharedShellFactory& rpFactory);
114 : void RemoveShellFactory (
115 : const SfxShell* pViewShell,
116 : const SharedShellFactory& rpFactory);
117 : void ActivateViewShell (
118 : ViewShell* pViewShell);
119 : void DeactivateViewShell (const ViewShell& rShell);
120 : void ActivateShell (SfxShell& rShell);
121 : void DeactivateShell (const SfxShell& rShell);
122 : void ActivateShell (const ShellDescriptor& rDescriptor);
123 : void SetFormShell (const ViewShell* pViewShell, FmFormShell* pFormShell, bool bAbove);
124 : void ActivateSubShell (const SfxShell& rParentShell, ShellId nId);
125 : void DeactivateSubShell (const SfxShell& rParentShell, ShellId nId);
126 : void MoveSubShellToTop (const SfxShell& rParentShell, ShellId nId);
127 : void MoveToTop (const SfxShell& rParentShell);
128 : SfxShell* GetShell (ShellId nId) const;
129 : SfxShell* GetTopShell (void) const;
130 : void Shutdown (void);
131 : void InvalidateAllSubShells (const SfxShell* pParentShell);
132 :
133 : /** Remove all shells from the SFX stack above and including the given
134 : shell.
135 : */
136 : void TakeShellsFromStack (const SfxShell* pShell);
137 :
138 : class UpdateLock
139 : {
140 : public:
141 497 : UpdateLock (Implementation& rImpl) : mrImpl(rImpl) {mrImpl.LockUpdate();}
142 497 : ~UpdateLock (void) {mrImpl.UnlockUpdate();};
143 : private:
144 : Implementation& mrImpl;
145 : };
146 :
147 :
148 :
149 : /** Prevent updates of the shell stack. While the sub shell manager is
150 : locked it will update its internal data structures but not alter the
151 : shell stack. Use this method when there are several modifications
152 : to the shell stack to prevent multiple rebuilds of the shell stack
153 : and resulting broadcasts.
154 : */
155 : void LockUpdate (void);
156 :
157 : /** Allow updates of the shell stack. This method has to be called the
158 : same number of times as LockUpdate() to really allow a rebuild of
159 : the shell stack.
160 : */
161 : void UnlockUpdate (void);
162 :
163 : private:
164 : ViewShellBase& mrBase;
165 : mutable ::osl::Mutex maMutex;
166 :
167 2856 : class ShellHash{public: size_t operator()(const SfxShell* p) const { return (size_t)p;} };
168 : typedef ::boost::unordered_multimap<const SfxShell*,SharedShellFactory,ShellHash>
169 : FactoryList;
170 : FactoryList maShellFactories;
171 :
172 : /** List of the active view shells. In order to create gather all shells
173 : to put on the shell stack each view shell in this list is asked for
174 : its sub-shells (typically toolbars).
175 : */
176 : typedef ::std::list<ShellDescriptor> ActiveShellList;
177 : ActiveShellList maActiveViewShells;
178 :
179 : typedef ::std::list<ShellDescriptor> SubShellSubList;
180 : typedef ::boost::unordered_map<const SfxShell*,SubShellSubList,ShellHash> SubShellList;
181 : SubShellList maActiveSubShells;
182 :
183 : /** In this member we remember what shells we have pushed on the shell
184 : stack.
185 : */
186 : typedef ::std::vector<SfxShell*> ShellStack;
187 :
188 : int mnUpdateLockCount;
189 :
190 : /** When this flag is set then the main view shell is always kept at the
191 : top of the shell stack.
192 : */
193 : bool mbKeepMainViewShellOnTop;
194 :
195 : /** The UpdateShellStack() method can be called recursively. This flag
196 : is used to communicate between different levels of invocation: if
197 : the stack has been updated in an inner call the outer call can (has
198 : to) stop and return immediately.
199 : */
200 : bool mbShellStackIsUpToDate;
201 :
202 : SfxShell* mpFormShell;
203 : const ViewShell* mpFormShellParent;
204 : bool mbFormShellAboveParent;
205 :
206 : SfxShell* mpTopShell;
207 :
208 : void GatherActiveShells (ShellStack& rShellList);
209 :
210 : void UpdateShellStack (void);
211 :
212 : void CreateShells (void);
213 :
214 : /** This method rebuilds the stack of shells that are stacked upon the
215 : view shell base.
216 : */
217 : void CreateTargetStack (ShellStack& rStack) const;
218 :
219 : DECL_LINK(WindowEventHandler, VclWindowEvent*);
220 :
221 : #if OSL_DEBUG_LEVEL >= 2
222 : void DumpShellStack (const ShellStack& rStack);
223 : void DumpSfxShellStack (void);
224 : #endif
225 :
226 : /** To be called before a shell is taken fom the SFX shell stack. This
227 : method deactivates an active text editing to avoid problems with
228 : undo managers.
229 : Afterwards the Deactivate() of the shell is called.
230 : */
231 : void Deactivate (SfxShell* pShell);
232 :
233 : ShellDescriptor CreateSubShell (
234 : SfxShell* pShell,
235 : ShellId nShellId,
236 : ::Window* pParentWindow,
237 : FrameView* pFrameView);
238 : void DestroyViewShell (ShellDescriptor& rDescriptor);
239 : void DestroySubShell (
240 : const SfxShell& rViewShell,
241 : const ShellDescriptor& rDescriptor);
242 : };
243 :
244 :
245 :
246 :
247 : //===== ViewShellManager ======================================================
248 :
249 65 : ViewShellManager::ViewShellManager (ViewShellBase& rBase)
250 65 : : mpImpl(new Implementation(*this,rBase)),
251 130 : mbValid(true)
252 : {
253 65 : }
254 :
255 :
256 :
257 :
258 65 : ViewShellManager::~ViewShellManager (void)
259 : {
260 65 : }
261 :
262 :
263 :
264 :
265 221 : void ViewShellManager::AddSubShellFactory (
266 : ViewShell* pViewShell,
267 : const SharedShellFactory& rpFactory)
268 : {
269 221 : if (mbValid)
270 221 : mpImpl->AddShellFactory(pViewShell, rpFactory);
271 221 : }
272 :
273 :
274 :
275 :
276 156 : void ViewShellManager::RemoveSubShellFactory (
277 : ViewShell* pViewShell,
278 : const SharedShellFactory& rpFactory)
279 : {
280 156 : if (mbValid)
281 0 : mpImpl->RemoveShellFactory(pViewShell, rpFactory);
282 156 : }
283 :
284 :
285 :
286 :
287 143 : void ViewShellManager::ActivateViewShell (ViewShell* pViewShell)
288 : {
289 143 : if (mbValid)
290 143 : return mpImpl->ActivateViewShell(pViewShell);
291 : }
292 :
293 :
294 :
295 :
296 143 : void ViewShellManager::DeactivateViewShell (const ViewShell* pShell)
297 : {
298 143 : if (mbValid && pShell!=NULL)
299 0 : mpImpl->DeactivateViewShell(*pShell);
300 143 : }
301 :
302 :
303 :
304 :
305 0 : void ViewShellManager::MoveSubShellToTop (
306 : const ViewShell& rParentShell,
307 : ShellId nId)
308 : {
309 0 : if (mbValid)
310 0 : mpImpl->MoveSubShellToTop(rParentShell, nId);
311 0 : }
312 :
313 :
314 :
315 :
316 130 : void ViewShellManager::SetFormShell (
317 : const ViewShell* pParentShell,
318 : FmFormShell* pFormShell,
319 : bool bAbove)
320 : {
321 130 : if (mbValid)
322 130 : mpImpl->SetFormShell(pParentShell,pFormShell,bAbove);
323 130 : }
324 :
325 :
326 :
327 :
328 81 : void ViewShellManager::ActivateSubShell (const ViewShell& rViewShell, ShellId nId)
329 : {
330 81 : if (mbValid)
331 81 : mpImpl->ActivateSubShell(rViewShell,nId);
332 81 : }
333 :
334 :
335 :
336 :
337 8 : void ViewShellManager::DeactivateSubShell (const ViewShell& rViewShell, ShellId nId)
338 : {
339 8 : if (mbValid)
340 0 : mpImpl->DeactivateSubShell(rViewShell,nId);
341 8 : }
342 :
343 :
344 :
345 :
346 66 : void ViewShellManager::InvalidateAllSubShells (ViewShell* pViewShell)
347 : {
348 66 : if (mbValid)
349 66 : mpImpl->InvalidateAllSubShells(pViewShell);
350 66 : }
351 :
352 :
353 :
354 :
355 78 : void ViewShellManager::ActivateShell (SfxShell* pShell)
356 : {
357 78 : if (mbValid && pShell!=NULL)
358 78 : mpImpl->ActivateShell(*pShell);
359 78 : }
360 :
361 :
362 :
363 :
364 0 : void ViewShellManager::DeactivateShell (const SfxShell* pShell)
365 : {
366 0 : if (mbValid && pShell!=NULL)
367 0 : mpImpl->DeactivateShell(*pShell);
368 0 : }
369 :
370 :
371 :
372 :
373 130 : void ViewShellManager::MoveToTop (const ViewShell& rParentShell)
374 : {
375 130 : if (mbValid)
376 130 : mpImpl->MoveToTop(rParentShell);
377 130 : }
378 :
379 :
380 :
381 :
382 3280 : SfxShell* ViewShellManager::GetShell (ShellId nId) const
383 : {
384 3280 : if (mbValid)
385 3280 : return mpImpl->GetShell(nId);
386 : else
387 0 : return NULL;
388 : }
389 :
390 :
391 :
392 :
393 0 : SfxShell* ViewShellManager::GetTopShell (void) const
394 : {
395 0 : if (mbValid)
396 0 : return mpImpl->GetTopShell();
397 : else
398 0 : return NULL;
399 : }
400 :
401 :
402 :
403 :
404 130 : void ViewShellManager::Shutdown (void)
405 : {
406 130 : if (mbValid)
407 : {
408 65 : mpImpl->Shutdown();
409 65 : mbValid = false;
410 : }
411 130 : }
412 :
413 :
414 :
415 754 : void ViewShellManager::LockUpdate (void)
416 : {
417 754 : mpImpl->LockUpdate();
418 754 : }
419 :
420 :
421 :
422 :
423 754 : void ViewShellManager::UnlockUpdate (void)
424 : {
425 754 : mpImpl->UnlockUpdate();
426 754 : }
427 :
428 :
429 :
430 :
431 : //===== ViewShellManager::Implementation ======================================
432 :
433 65 : ViewShellManager::Implementation::Implementation (
434 : ViewShellManager& rManager,
435 : ViewShellBase& rBase)
436 : : mrBase(rBase),
437 : maMutex(),
438 : maShellFactories(),
439 : maActiveViewShells(),
440 : mnUpdateLockCount(0),
441 : mbKeepMainViewShellOnTop(false),
442 : mbShellStackIsUpToDate(true),
443 : mpFormShell(NULL),
444 : mpFormShellParent(NULL),
445 : mbFormShellAboveParent(true),
446 65 : mpTopShell(NULL)
447 : {
448 : (void)rManager;
449 65 : }
450 :
451 :
452 :
453 :
454 130 : ViewShellManager::Implementation::~Implementation (void)
455 : {
456 65 : Shutdown();
457 65 : }
458 :
459 :
460 :
461 :
462 221 : void ViewShellManager::Implementation::AddShellFactory (
463 : const SfxShell* pViewShell,
464 : const SharedShellFactory& rpFactory)
465 : {
466 221 : bool bAlreadyAdded (false);
467 :
468 : // Check that the given factory has not already been added.
469 : ::std::pair<FactoryList::iterator,FactoryList::iterator> aRange(
470 221 : maShellFactories.equal_range(pViewShell));
471 299 : for (FactoryList::const_iterator iFactory=aRange.first; iFactory!=aRange.second; ++iFactory)
472 78 : if (iFactory->second == rpFactory)
473 : {
474 0 : bAlreadyAdded = true;
475 0 : break;
476 : }
477 :
478 : // Add the factory if it is not already present.
479 221 : if ( ! bAlreadyAdded)
480 221 : maShellFactories.insert(FactoryList::value_type(pViewShell, rpFactory));
481 221 : }
482 :
483 :
484 :
485 :
486 0 : void ViewShellManager::Implementation::RemoveShellFactory (
487 : const SfxShell* pViewShell,
488 : const SharedShellFactory& rpFactory)
489 : {
490 : ::std::pair<FactoryList::iterator,FactoryList::iterator> aRange(
491 0 : maShellFactories.equal_range(pViewShell));
492 0 : for (FactoryList::iterator iFactory=aRange.first; iFactory!=aRange.second; ++iFactory)
493 0 : if (iFactory->second == rpFactory)
494 : {
495 0 : maShellFactories.erase(iFactory);
496 0 : break;
497 : }
498 0 : }
499 :
500 :
501 :
502 :
503 143 : void ViewShellManager::Implementation::ActivateViewShell (ViewShell* pViewShell)
504 : {
505 143 : ::osl::MutexGuard aGuard (maMutex);
506 :
507 286 : ShellDescriptor aResult;
508 143 : aResult.mpShell = pViewShell;
509 :
510 : // Register as window listener so that the shells of the current
511 : // window can be moved to the top of the shell stack.
512 143 : if (aResult.mpShell != NULL)
513 : {
514 143 : ::Window* pWindow = aResult.GetWindow();
515 143 : if (pWindow != NULL)
516 : {
517 : pWindow->AddEventListener(
518 143 : LINK(this, ViewShellManager::Implementation, WindowEventHandler));
519 143 : aResult.mbIsListenerAddedToWindow = true;
520 : }
521 : else
522 : {
523 : DBG_ASSERT(false,
524 : "ViewShellManager::ActivateViewShell: "
525 : "new view shell has no active window");
526 : }
527 : }
528 :
529 286 : ActivateShell(aResult);
530 143 : }
531 :
532 :
533 :
534 :
535 143 : void ViewShellManager::Implementation::DeactivateViewShell (const ViewShell& rShell)
536 : {
537 143 : ::osl::MutexGuard aGuard (maMutex);
538 :
539 : ActiveShellList::iterator iShell (::std::find_if (
540 : maActiveViewShells.begin(),
541 : maActiveViewShells.end(),
542 143 : IsShell(&rShell)));
543 143 : if (iShell != maActiveViewShells.end())
544 : {
545 143 : UpdateLock aLocker (*this);
546 :
547 286 : ShellDescriptor aDescriptor(*iShell);
548 143 : mrBase.GetDocShell()->Disconnect(dynamic_cast<ViewShell*>(aDescriptor.mpShell));
549 143 : maActiveViewShells.erase(iShell);
550 143 : TakeShellsFromStack(aDescriptor.mpShell);
551 :
552 : // Deactivate sub shells.
553 143 : SubShellList::iterator iList (maActiveSubShells.find(&rShell));
554 143 : if (iList != maActiveSubShells.end())
555 : {
556 73 : SubShellSubList& rList (iList->second);
557 219 : while ( ! rList.empty())
558 73 : DeactivateSubShell(rShell, rList.front().mnId);
559 : }
560 :
561 286 : DestroyViewShell(aDescriptor);
562 143 : }
563 143 : }
564 :
565 :
566 :
567 :
568 78 : void ViewShellManager::Implementation::ActivateShell (SfxShell& rShell)
569 : {
570 78 : ::osl::MutexGuard aGuard (maMutex);
571 :
572 : // Create a new shell or recycle on in the cache.
573 156 : ShellDescriptor aDescriptor;
574 78 : aDescriptor.mpShell = &rShell;
575 :
576 156 : ActivateShell(aDescriptor);
577 78 : }
578 :
579 :
580 :
581 :
582 221 : void ViewShellManager::Implementation::ActivateShell (const ShellDescriptor& rDescriptor)
583 : {
584 : // Put shell on top of the active view shells.
585 221 : if (rDescriptor.mpShell != NULL)
586 : {
587 : // Determine where to put the view shell on the stack. By default
588 : // it is put on top of the stack. When the view shell of the center
589 : // pane is to be kept top most and the new view shell is not
590 : // displayed in the center pane then it is inserted at the position
591 : // one below the top.
592 221 : ActiveShellList::iterator iInsertPosition (maActiveViewShells.begin());
593 663 : if (iInsertPosition != maActiveViewShells.end()
594 156 : && mbKeepMainViewShellOnTop
595 0 : && ! rDescriptor.IsMainViewShell()
596 663 : && iInsertPosition->IsMainViewShell())
597 : {
598 0 : ++iInsertPosition;
599 : }
600 : maActiveViewShells.insert(
601 : iInsertPosition,
602 221 : rDescriptor);
603 : }
604 221 : }
605 :
606 :
607 :
608 :
609 78 : void ViewShellManager::Implementation::DeactivateShell (const SfxShell& rShell)
610 : {
611 78 : ::osl::MutexGuard aGuard (maMutex);
612 :
613 : ActiveShellList::iterator iShell (::std::find_if (
614 : maActiveViewShells.begin(),
615 : maActiveViewShells.end(),
616 78 : IsShell(&rShell)));
617 78 : if (iShell != maActiveViewShells.end())
618 : {
619 78 : UpdateLock aLocker (*this);
620 :
621 156 : ShellDescriptor aDescriptor(*iShell);
622 78 : mrBase.GetDocShell()->Disconnect(dynamic_cast<ViewShell*>(aDescriptor.mpShell));
623 78 : maActiveViewShells.erase(iShell);
624 78 : TakeShellsFromStack(aDescriptor.mpShell);
625 :
626 : // Deactivate sub shells.
627 78 : SubShellList::iterator iList (maActiveSubShells.find(&rShell));
628 78 : if (iList != maActiveSubShells.end())
629 : {
630 0 : SubShellSubList& rList (iList->second);
631 0 : while ( ! rList.empty())
632 0 : DeactivateSubShell(rShell, rList.front().mnId);
633 : }
634 :
635 156 : DestroyViewShell(aDescriptor);
636 78 : }
637 78 : }
638 :
639 :
640 :
641 :
642 81 : void ViewShellManager::Implementation::ActivateSubShell (
643 : const SfxShell& rParentShell,
644 : ShellId nId)
645 : {
646 81 : ::osl::MutexGuard aGuard (maMutex);
647 :
648 : // Check that the given view shell is active.
649 : ActiveShellList::iterator iShell (::std::find_if (
650 : maActiveViewShells.begin(),
651 : maActiveViewShells.end(),
652 81 : IsShell(&rParentShell)));
653 81 : if (iShell == maActiveViewShells.end())
654 0 : return;
655 :
656 : // Create the sub shell list if it does not yet exist.
657 81 : SubShellList::iterator iList (maActiveSubShells.find(&rParentShell));
658 81 : if (iList == maActiveSubShells.end())
659 : iList = maActiveSubShells.insert(
660 73 : SubShellList::value_type(&rParentShell,SubShellSubList())).first;
661 :
662 : // Do not activate an object bar that is already active. Requesting
663 : // this is not exactly an error but may be an indication of one.
664 81 : SubShellSubList& rList (iList->second);
665 81 : if (::std::find_if(rList.begin(),rList.end(), IsId(nId)) != rList.end())
666 8 : return;
667 :
668 : // Add just the id of the sub shell. The actual shell is created
669 : // later in CreateShells().
670 146 : UpdateLock aLock (*this);
671 146 : rList.push_back(ShellDescriptor(NULL, nId));
672 : }
673 :
674 :
675 :
676 :
677 73 : void ViewShellManager::Implementation::DeactivateSubShell (
678 : const SfxShell& rParentShell,
679 : ShellId nId)
680 : {
681 73 : ::osl::MutexGuard aGuard (maMutex);
682 :
683 : // Check that the given view shell is active.
684 73 : SubShellList::iterator iList (maActiveSubShells.find(&rParentShell));
685 73 : if (iList == maActiveSubShells.end())
686 0 : return;
687 :
688 : // Look up the sub shell.
689 73 : SubShellSubList& rList (iList->second);
690 : SubShellSubList::iterator iShell (
691 73 : ::std::find_if(rList.begin(),rList.end(), IsId(nId)));
692 73 : if (iShell == rList.end())
693 0 : return;
694 73 : SfxShell* pShell = iShell->mpShell;
695 73 : if (pShell == NULL)
696 0 : return;
697 :
698 146 : UpdateLock aLock (*this);
699 :
700 146 : ShellDescriptor aDescriptor(*iShell);
701 : // Remove the sub shell from both the internal structure as well as the
702 : // SFX shell stack above and including the sub shell.
703 73 : rList.erase(iShell);
704 73 : TakeShellsFromStack(pShell);
705 :
706 146 : DestroySubShell(rParentShell, aDescriptor);
707 : }
708 :
709 :
710 :
711 :
712 0 : void ViewShellManager::Implementation::MoveSubShellToTop (
713 : const SfxShell& rParentShell,
714 : ShellId nId)
715 : {
716 0 : SubShellList::iterator iList (maActiveSubShells.find(&rParentShell));
717 0 : if (iList != maActiveSubShells.end())
718 : {
719 : // Look up the sub shell.
720 0 : SubShellSubList& rList (iList->second);
721 : SubShellSubList::iterator iShell (
722 0 : ::std::find_if(rList.begin(),rList.end(), IsId(nId)));
723 0 : if (iShell!=rList.end() && iShell!=rList.begin())
724 : {
725 0 : SubShellSubList::value_type aEntry (*iShell);
726 0 : rList.erase(iShell);
727 0 : rList.push_front(aEntry);
728 : }
729 : }
730 : else
731 : {
732 : // Ignore this call when there are no sub shells for the given
733 : // parent shell. We could remember the sub shell to move to the top
734 : // but we do not. Do call this method at a later time instead.
735 : }
736 0 : }
737 :
738 :
739 :
740 130 : void ViewShellManager::Implementation::MoveToTop (const SfxShell& rShell)
741 : {
742 130 : ::osl::MutexGuard aGuard (maMutex);
743 :
744 : // Check that we have access to a dispatcher. If not, then we are
745 : // (probably) called while the view shell is still being created or
746 : // initialized. Without dispatcher we can not rebuild the shell stack
747 : // to move the requested shell to the top. So return right away instead
748 : // of making a mess without being able to clean up afterwards.
749 130 : if (mrBase.GetDispatcher() == NULL)
750 195 : return;
751 :
752 : ActiveShellList::iterator iShell (::std::find_if (
753 : maActiveViewShells.begin(),
754 : maActiveViewShells.end(),
755 65 : IsShell(&rShell)));
756 65 : bool bMove = true;
757 65 : if (iShell != maActiveViewShells.end())
758 : {
759 : // Is the shell already at the top of the stack? We have to keep
760 : // the case in mind that mbKeepMainViewShellOnTop is true. Shells
761 : // that are not the main view shell are placed on the second-to-top
762 : // position in this case.
763 195 : if (iShell == maActiveViewShells.begin()
764 195 : && (iShell->IsMainViewShell() || ! mbKeepMainViewShellOnTop))
765 : {
766 : // The shell is at the top position and is either a) the main
767 : // view shell or b) another shell but the main view shell is not
768 : // kept at the top position. We do not have to move the shell.
769 0 : bMove = false;
770 : }
771 195 : else if (iShell == ++maActiveViewShells.begin()
772 52 : && ! iShell->IsMainViewShell()
773 195 : && mbKeepMainViewShellOnTop)
774 : {
775 : // The shell is a the second-to-top position, not the main view
776 : // shell and the main view shell is kept at the top position.
777 : // Therefore we do not have to move the shell.
778 0 : bMove = false;
779 : }
780 : }
781 : else
782 : {
783 : // The shell is not on the stack. Therefore it can not be moved.
784 : // We could insert it but we don't. Use ActivateViewShell() for
785 : // that.
786 0 : bMove = false;
787 : }
788 :
789 : // When the shell is not at the right position it is removed from the
790 : // internal list of shells and inserted at the correct position.
791 65 : if (bMove)
792 : {
793 65 : UpdateLock aLock (*this);
794 :
795 130 : ShellDescriptor aDescriptor(*iShell);
796 :
797 65 : TakeShellsFromStack(&rShell);
798 65 : maActiveViewShells.erase(iShell);
799 :
800 : // Find out whether to insert at the top or one below.
801 65 : ActiveShellList::iterator aInsertPosition (maActiveViewShells.begin());
802 65 : if (mbKeepMainViewShellOnTop && ! aDescriptor.IsMainViewShell())
803 : {
804 0 : if (maActiveViewShells.back().IsMainViewShell())
805 0 : ++aInsertPosition;
806 : }
807 :
808 130 : maActiveViewShells.insert(aInsertPosition, aDescriptor);
809 65 : }
810 : }
811 :
812 :
813 :
814 :
815 3280 : SfxShell* ViewShellManager::Implementation::GetShell (ShellId nId) const
816 : {
817 3280 : ::osl::MutexGuard aGuard (maMutex);
818 :
819 3280 : SfxShell* pShell = NULL;
820 :
821 : // First search the active view shells.
822 : ActiveShellList::const_iterator iShell (
823 : ::std::find_if (
824 : maActiveViewShells.begin(),
825 : maActiveViewShells.end(),
826 3280 : IsId(nId)));
827 3280 : if (iShell != maActiveViewShells.end())
828 0 : pShell = iShell->mpShell;
829 : else
830 : {
831 : // Now search the active sub shells of every active view shell.
832 3280 : SubShellList::const_iterator iList;
833 6851 : for (iList=maActiveSubShells.begin(); iList!=maActiveSubShells.end(); ++iList)
834 : {
835 3571 : const SubShellSubList& rList (iList->second);
836 : SubShellSubList::const_iterator iSubShell(
837 3571 : ::std::find_if(rList.begin(),rList.end(), IsId(nId)));
838 3571 : if (iSubShell != rList.end())
839 : {
840 0 : pShell = iSubShell->mpShell;
841 0 : break;
842 : }
843 : }
844 : }
845 :
846 3280 : return pShell;
847 : }
848 :
849 :
850 :
851 :
852 0 : SfxShell* ViewShellManager::Implementation::GetTopShell (void) const
853 : {
854 : OSL_ASSERT(mpTopShell == mrBase.GetSubShell(0));
855 0 : return mpTopShell;
856 : }
857 :
858 :
859 :
860 :
861 1251 : void ViewShellManager::Implementation::LockUpdate (void)
862 : {
863 1251 : mnUpdateLockCount++;
864 1251 : }
865 :
866 :
867 :
868 :
869 1251 : void ViewShellManager::Implementation::UnlockUpdate (void)
870 : {
871 1251 : ::osl::MutexGuard aGuard (maMutex);
872 :
873 1251 : mnUpdateLockCount--;
874 1251 : if (mnUpdateLockCount < 0)
875 : {
876 : // This should not happen.
877 : OSL_ASSERT (mnUpdateLockCount>=0);
878 0 : mnUpdateLockCount = 0;
879 : }
880 1251 : if (mnUpdateLockCount == 0)
881 421 : UpdateShellStack();
882 1251 : }
883 :
884 :
885 :
886 :
887 : /** Update the SFX shell stack (the portion that is visible to us) so that
888 : it matches the internal shell stack. This is done in six steps:
889 : 1. Create the missing view shells and sub shells.
890 : 2. Set up the internal shell stack.
891 : 3. Get the SFX shell stack.
892 : 4. Find the lowest shell in which the two stacks differ.
893 : 5. Remove all shells above and including that shell from the SFX stack.
894 : 6. Push all shells of the internal stack on the SFX shell stack that are
895 : not already present on the later.
896 : */
897 421 : void ViewShellManager::Implementation::UpdateShellStack (void)
898 : {
899 421 : ::osl::MutexGuard aGuard (maMutex);
900 :
901 : // Remember the undo manager from the top-most shell on the stack.
902 421 : SfxShell* pTopMostShell = mrBase.GetSubShell(0);
903 : ::svl::IUndoManager* pUndoManager = (pTopMostShell!=NULL)
904 226 : ? pTopMostShell->GetUndoManager()
905 647 : : NULL;
906 :
907 : // 1. Create the missing shells.
908 421 : CreateShells();
909 :
910 :
911 : // 2. Create the internal target stack.
912 842 : ShellStack aTargetStack;
913 421 : CreateTargetStack(aTargetStack);
914 :
915 :
916 : // 3. Get SFX shell stack.
917 842 : ShellStack aSfxShellStack;
918 421 : sal_uInt16 nIndex (0);
919 1528 : while (mrBase.GetSubShell(nIndex)!=NULL)
920 686 : ++nIndex;
921 421 : aSfxShellStack.reserve(nIndex);
922 1528 : while (nIndex-- > 0)
923 686 : aSfxShellStack.push_back(mrBase.GetSubShell(nIndex));
924 :
925 :
926 : #if OSL_DEBUG_LEVEL >= 2
927 : SAL_INFO("sd.view", OSL_THIS_FUNC << ": Current SFX Stack");
928 : DumpShellStack(aSfxShellStack);
929 : SAL_INFO("sd.view", OSL_THIS_FUNC << ": Target Stack");
930 : DumpShellStack(aTargetStack);
931 : #endif
932 :
933 :
934 : // 4. Find the lowest shell in which the two stacks differ.
935 421 : ShellStack::iterator iSfxShell (aSfxShellStack.begin());
936 421 : ShellStack::iterator iTargetShell (aTargetStack.begin());
937 4233 : while (iSfxShell != aSfxShellStack.end()
938 1623 : && iTargetShell!=aTargetStack.end()
939 3529 : && (*iSfxShell)==(*iTargetShell))
940 : {
941 532 : ++iSfxShell;
942 532 : ++iTargetShell;
943 : }
944 :
945 :
946 : // 5. Remove all shells above and including the differing shell from the
947 : // SFX stack starting with the shell on top of the stack.
948 575 : for (std::reverse_iterator<ShellStack::const_iterator> i(aSfxShellStack.end()), iLast(iSfxShell);
949 : i != iLast; ++i)
950 : {
951 154 : SfxShell* const pShell = *i;
952 : SAL_INFO("sd.view", OSL_THIS_FUNC << ": removing shell " << pShell << " from stack");
953 154 : mrBase.RemoveSubShell(pShell);
954 : }
955 421 : aSfxShellStack.erase(iSfxShell, aSfxShellStack.end());
956 :
957 :
958 : // 6. Push shells from the given stack onto the SFX stack.
959 421 : mbShellStackIsUpToDate = false;
960 1342 : while (iTargetShell != aTargetStack.end())
961 : {
962 : SAL_INFO("sd.view", OSL_THIS_FUNC << ": pushing shell " << *iTargetShell << " on stack");
963 513 : mrBase.AddSubShell(**iTargetShell);
964 513 : ++iTargetShell;
965 :
966 : // The pushing of the shell on to the shell stack may have lead to
967 : // another invocation of this method. In this case we have to abort
968 : // pushing shells on the stack and return immediately.
969 513 : if (mbShellStackIsUpToDate)
970 13 : break;
971 : }
972 421 : if (mrBase.GetDispatcher() != NULL)
973 291 : mrBase.GetDispatcher()->Flush();
974 :
975 : // Update the pointer to the top-most shell and set its undo manager
976 : // to the one of the previous top-most shell.
977 421 : mpTopShell = mrBase.GetSubShell(0);
978 421 : if (mpTopShell!=NULL && pUndoManager!=NULL && mpTopShell->GetUndoManager()==NULL)
979 0 : mpTopShell->SetUndoManager(pUndoManager);
980 :
981 : // Finally tell an invocation of this method on a higher level that it can (has
982 : // to) abort and return immediately.
983 842 : mbShellStackIsUpToDate = true;
984 :
985 : #if OSL_DEBUG_LEVEL >= 2
986 : SAL_INFO("sd.view", OSL_THIS_FUNC << ": New current stack");
987 : DumpSfxShellStack();
988 : #endif
989 421 : }
990 :
991 :
992 :
993 :
994 359 : void ViewShellManager::Implementation::TakeShellsFromStack (const SfxShell* pShell)
995 : {
996 359 : ::osl::MutexGuard aGuard (maMutex);
997 :
998 : // Remember the undo manager from the top-most shell on the stack.
999 359 : SfxShell* pTopMostShell = mrBase.GetSubShell(0);
1000 : ::svl::IUndoManager* pUndoManager = (pTopMostShell!=NULL)
1001 359 : ? pTopMostShell->GetUndoManager()
1002 718 : : NULL;
1003 :
1004 : #if OSL_DEBUG_LEVEL >= 2
1005 : SAL_INFO("sd.view", OSL_THIS_FUNC << "TakeShellsFromStack( " << pShell << ")");
1006 : DumpSfxShellStack();
1007 : #endif
1008 :
1009 : // 0.Make sure that the given shell is on the stack. This is a
1010 : // preparation for the following assertion.
1011 383 : for (sal_uInt16 nIndex=0; true; nIndex++)
1012 : {
1013 383 : SfxShell* pShellOnStack = mrBase.GetSubShell(nIndex);
1014 383 : if (pShellOnStack == NULL)
1015 : {
1016 : // Set pShell to NULL to indicate the following code that the
1017 : // shell is not on the stack.
1018 8 : pShell = NULL;
1019 8 : break;
1020 : }
1021 375 : else if (pShellOnStack == pShell)
1022 351 : break;
1023 24 : }
1024 :
1025 359 : if (pShell != NULL)
1026 : {
1027 : // 1. Deactivate our shells on the stack before they are removed so
1028 : // that during the Deactivation() calls the stack is still intact.
1029 359 : for (sal_uInt16 nIndex=0; true; nIndex++)
1030 : {
1031 359 : SfxShell* pShellOnStack = mrBase.GetSubShell(nIndex);
1032 359 : Deactivate(pShellOnStack);
1033 359 : if (pShellOnStack == pShell)
1034 351 : break;
1035 8 : }
1036 :
1037 : // 2. Remove the shells from the stack.
1038 : while (true)
1039 : {
1040 359 : SfxShell* pShellOnStack = mrBase.GetSubShell(0);
1041 : SAL_INFO("sd.view", OSL_THIS_FUNC << "removing shell " << pShellOnStack << " from stack");
1042 359 : mrBase.RemoveSubShell(pShellOnStack);
1043 359 : if (pShellOnStack == pShell)
1044 351 : break;
1045 : }
1046 :
1047 : // 3. Update the stack.
1048 702 : if (mrBase.GetDispatcher() != NULL)
1049 351 : mrBase.GetDispatcher()->Flush();
1050 :
1051 : // Update the pointer to the top-most shell and set its undo manager
1052 : // to the one of the previous top-most shell.
1053 351 : mpTopShell = mrBase.GetSubShell(0);
1054 351 : if (mpTopShell!=NULL && pUndoManager!=NULL && mpTopShell->GetUndoManager()==NULL)
1055 99 : mpTopShell->SetUndoManager(pUndoManager);
1056 359 : }
1057 :
1058 :
1059 : #if OSL_DEBUG_LEVEL >= 2
1060 : SAL_INFO("sd.view", OSL_THIS_FUNC << "Sfx shell stack is:");
1061 : DumpSfxShellStack();
1062 : #endif
1063 359 : }
1064 :
1065 :
1066 :
1067 :
1068 421 : void ViewShellManager::Implementation::CreateShells (void)
1069 : {
1070 421 : ::osl::MutexGuard aGuard (maMutex);
1071 :
1072 : // Iterate over all view shells.
1073 421 : ActiveShellList::reverse_iterator iShell;
1074 1224 : for (iShell=maActiveViewShells.rbegin(); iShell!=maActiveViewShells.rend(); ++iShell)
1075 : {
1076 : // Get the list of associated sub shells.
1077 803 : SubShellList::iterator iList (maActiveSubShells.find(iShell->mpShell));
1078 803 : if (iList != maActiveSubShells.end())
1079 : {
1080 242 : SubShellSubList& rList (iList->second);
1081 :
1082 : // Iterate over all sub shells of the current view shell.
1083 242 : SubShellSubList::iterator iSubShell;
1084 484 : for (iSubShell=rList.begin(); iSubShell!=rList.end(); ++iSubShell)
1085 : {
1086 242 : if (iSubShell->mpShell == NULL)
1087 : {
1088 73 : *iSubShell = CreateSubShell(iShell->mpShell,iSubShell->mnId,NULL,NULL);
1089 : }
1090 : }
1091 : }
1092 421 : }
1093 421 : }
1094 :
1095 :
1096 :
1097 :
1098 421 : void ViewShellManager::Implementation::CreateTargetStack (ShellStack& rStack) const
1099 : {
1100 : // Create a local stack of the shells that are to push on the shell
1101 : // stack. We can thus safly create the required shells wile still
1102 : // having a valid shell stack.
1103 3672 : for (ActiveShellList::const_reverse_iterator iViewShell (maActiveViewShells.rbegin());
1104 2448 : iViewShell != maActiveViewShells.rend();
1105 : ++iViewShell)
1106 : {
1107 : // Possibly place the form shell below the current view shell.
1108 1606 : if ( ! mbFormShellAboveParent
1109 660 : && mpFormShell!=NULL
1110 1463 : && iViewShell->mpShell==mpFormShellParent)
1111 : {
1112 226 : rStack.push_back(mpFormShell);
1113 : }
1114 :
1115 : // Put the view shell itself on the local stack.
1116 803 : rStack.push_back (iViewShell->mpShell);
1117 :
1118 : // Possibly place the form shell above the current view shell.
1119 803 : if (mbFormShellAboveParent
1120 143 : && mpFormShell!=NULL
1121 803 : && iViewShell->mpShell==mpFormShellParent)
1122 : {
1123 0 : rStack.push_back(mpFormShell);
1124 : }
1125 :
1126 : // Add all other sub shells.
1127 803 : SubShellList::const_iterator iList (maActiveSubShells.find(iViewShell->mpShell));
1128 803 : if (iList != maActiveSubShells.end())
1129 : {
1130 242 : const SubShellSubList& rList (iList->second);
1131 242 : SubShellSubList::const_reverse_iterator iSubShell;
1132 484 : for (iSubShell=rList.rbegin(); iSubShell!=rList.rend(); ++iSubShell)
1133 242 : if (iSubShell->mpShell != mpFormShell)
1134 16 : rStack.push_back(iSubShell->mpShell);
1135 : }
1136 : }
1137 421 : }
1138 :
1139 :
1140 :
1141 :
1142 1244 : IMPL_LINK(ViewShellManager::Implementation, WindowEventHandler, VclWindowEvent*, pEvent)
1143 : {
1144 622 : if (pEvent != NULL)
1145 : {
1146 : ::Window* pEventWindow
1147 622 : = static_cast<VclWindowEvent*>(pEvent)->GetWindow();
1148 :
1149 622 : switch (pEvent->GetId())
1150 : {
1151 : case VCLEVENT_WINDOW_GETFOCUS:
1152 : {
1153 0 : for (ActiveShellList::iterator aI(maActiveViewShells.begin());
1154 0 : aI!=maActiveViewShells.end();
1155 : aI++)
1156 : {
1157 0 : if (pEventWindow == static_cast< ::Window*>(aI->GetWindow()))
1158 : {
1159 0 : MoveToTop(*aI->mpShell);
1160 0 : break;
1161 : }
1162 : }
1163 : }
1164 0 : break;
1165 :
1166 : case VCLEVENT_WINDOW_LOSEFOCUS:
1167 0 : break;
1168 :
1169 : case VCLEVENT_OBJECT_DYING:
1170 : // Remember that we do not have to remove the window
1171 : // listener for this window.
1172 0 : for (ActiveShellList::iterator
1173 0 : iShell(maActiveViewShells.begin()),
1174 0 : iEnd(maActiveViewShells.end());
1175 : iShell!=iEnd;
1176 : ++iShell)
1177 : {
1178 0 : if (iShell->GetWindow() == pEventWindow)
1179 : {
1180 0 : iShell->mbIsListenerAddedToWindow = false;
1181 0 : break;
1182 : }
1183 : }
1184 0 : break;
1185 : }
1186 : }
1187 622 : return sal_True;
1188 : }
1189 :
1190 :
1191 :
1192 :
1193 73 : ShellDescriptor ViewShellManager::Implementation::CreateSubShell (
1194 : SfxShell* pParentShell,
1195 : ShellId nShellId,
1196 : ::Window* pParentWindow,
1197 : FrameView* pFrameView)
1198 : {
1199 73 : ::osl::MutexGuard aGuard (maMutex);
1200 73 : ShellDescriptor aResult;
1201 :
1202 : // Look up the factories for the parent shell.
1203 : ::std::pair<FactoryList::iterator,FactoryList::iterator> aRange(
1204 73 : maShellFactories.equal_range(pParentShell));
1205 :
1206 : // Try all factories to create the shell.
1207 146 : for (FactoryList::const_iterator iFactory=aRange.first; iFactory!=aRange.second; ++iFactory)
1208 : {
1209 146 : SharedShellFactory pFactory = iFactory->second;
1210 146 : if (pFactory != 0)
1211 146 : aResult.mpShell = pFactory->CreateShell(nShellId, pParentWindow, pFrameView);
1212 :
1213 : // Exit the loop when the shell has been successfully created.
1214 146 : if (aResult.mpShell != NULL)
1215 : {
1216 73 : aResult.mpFactory = pFactory;
1217 73 : aResult.mnId = nShellId;
1218 73 : break;
1219 : }
1220 73 : }
1221 :
1222 73 : return aResult;
1223 : }
1224 :
1225 :
1226 :
1227 :
1228 221 : void ViewShellManager::Implementation::DestroyViewShell (
1229 : ShellDescriptor& rDescriptor)
1230 : {
1231 : OSL_ASSERT(rDescriptor.mpShell != NULL);
1232 :
1233 221 : if (rDescriptor.mbIsListenerAddedToWindow)
1234 : {
1235 143 : rDescriptor.mbIsListenerAddedToWindow = false;
1236 143 : ::Window* pWindow = rDescriptor.GetWindow();
1237 143 : if (pWindow != NULL)
1238 : {
1239 : pWindow->RemoveEventListener(
1240 143 : LINK(this, ViewShellManager::Implementation, WindowEventHandler));
1241 : }
1242 : }
1243 :
1244 : // Destroy the sub shell factories.
1245 : ::std::pair<FactoryList::iterator,FactoryList::iterator> aRange(
1246 221 : maShellFactories.equal_range(rDescriptor.mpShell));
1247 221 : if (aRange.first != maShellFactories.end())
1248 143 : maShellFactories.erase(aRange.first, aRange.second);
1249 :
1250 : // Release the shell.
1251 221 : if (rDescriptor.mpFactory.get() != NULL)
1252 0 : rDescriptor.mpFactory->ReleaseShell(rDescriptor.mpShell);
1253 221 : }
1254 :
1255 :
1256 :
1257 :
1258 73 : void ViewShellManager::Implementation::DestroySubShell (
1259 : const SfxShell& rParentShell,
1260 : const ShellDescriptor& rDescriptor)
1261 : {
1262 : (void)rParentShell;
1263 : OSL_ASSERT(rDescriptor.mpFactory.get() != NULL);
1264 73 : rDescriptor.mpFactory->ReleaseShell(rDescriptor.mpShell);
1265 73 : }
1266 :
1267 :
1268 :
1269 :
1270 66 : void ViewShellManager::Implementation::InvalidateAllSubShells (const SfxShell* pParentShell)
1271 : {
1272 66 : ::osl::MutexGuard aGuard (maMutex);
1273 :
1274 66 : SubShellList::iterator iList (maActiveSubShells.find(pParentShell));
1275 66 : if (iList != maActiveSubShells.end())
1276 : {
1277 1 : SubShellSubList& rList (iList->second);
1278 1 : SubShellSubList::iterator iShell;
1279 2 : for (iShell=rList.begin(); iShell!=rList.end(); ++iShell)
1280 1 : if (iShell->mpShell != NULL)
1281 1 : iShell->mpShell->Invalidate();
1282 66 : }
1283 66 : }
1284 :
1285 :
1286 :
1287 :
1288 130 : void ViewShellManager::Implementation::Shutdown (void)
1289 : {
1290 130 : ::osl::MutexGuard aGuard (maMutex);
1291 :
1292 : // Take stacked shells from stack.
1293 130 : if ( ! maActiveViewShells.empty())
1294 : {
1295 65 : UpdateLock aLock (*this);
1296 :
1297 :
1298 351 : while ( ! maActiveViewShells.empty())
1299 : {
1300 221 : SfxShell* pShell = maActiveViewShells.front().mpShell;
1301 221 : if (pShell != NULL)
1302 : {
1303 221 : ViewShell* pViewShell = dynamic_cast<ViewShell*>(pShell);
1304 221 : if (pViewShell != NULL)
1305 143 : DeactivateViewShell(*pViewShell);
1306 : else
1307 78 : DeactivateShell(*pShell);
1308 : }
1309 : else
1310 : {
1311 : DBG_ASSERT(false,
1312 : "ViewShellManager::Implementation::Shutdown(): empty active shell descriptor");
1313 0 : maActiveViewShells.pop_front();
1314 : }
1315 65 : }
1316 : }
1317 130 : mrBase.RemoveSubShell (NULL);
1318 :
1319 130 : maShellFactories.clear();
1320 130 : }
1321 :
1322 :
1323 :
1324 :
1325 : #if OSL_DEBUG_LEVEL >= 2
1326 : void ViewShellManager::Implementation::DumpShellStack (const ShellStack& rStack)
1327 : {
1328 : ShellStack::const_reverse_iterator iEntry;
1329 : for (iEntry=rStack.rbegin(); iEntry!=rStack.rend(); ++iEntry)
1330 : if (*iEntry != NULL)
1331 : SAL_INFO("sd.view", OSL_THIS_FUNC << ": " <<
1332 : *iEntry << " : " <<
1333 : OUStringToOString((*iEntry)->GetName(),RTL_TEXTENCODING_UTF8).getStr());
1334 : else
1335 : SAL_INFO("sd.view", OSL_THIS_FUNC << " null");
1336 : }
1337 :
1338 :
1339 :
1340 :
1341 : void ViewShellManager::Implementation::DumpSfxShellStack (void)
1342 : {
1343 : ShellStack aSfxShellStack;
1344 : sal_uInt16 nIndex (0);
1345 : while (mrBase.GetSubShell(nIndex)!=NULL)
1346 : ++nIndex;
1347 : aSfxShellStack.reserve(nIndex);
1348 : while (nIndex-- > 0)
1349 : aSfxShellStack.push_back(mrBase.GetSubShell(nIndex));
1350 : DumpShellStack(aSfxShellStack);
1351 : }
1352 : #endif
1353 :
1354 :
1355 :
1356 359 : void ViewShellManager::Implementation::Deactivate (SfxShell* pShell)
1357 : {
1358 : OSL_ASSERT(pShell!=NULL);
1359 :
1360 : // We have to end a text edit for view shells that are to be taken from
1361 : // the shell stack.
1362 359 : ViewShell* pViewShell = dynamic_cast<ViewShell*>(pShell);
1363 359 : if (pViewShell != NULL)
1364 : {
1365 208 : sd::View* pView = pViewShell->GetView();
1366 208 : if (pView!=NULL && pView->IsTextEdit())
1367 : {
1368 0 : pView->SdrEndTextEdit();
1369 0 : pView->UnmarkAll();
1370 : pViewShell->GetViewFrame()->GetDispatcher()->Execute(
1371 : SID_OBJECT_SELECT,
1372 0 : SFX_CALLMODE_ASYNCHRON);
1373 : }
1374 : }
1375 :
1376 : // Now we can deactivate the shell.
1377 359 : pShell->Deactivate(sal_True);
1378 359 : }
1379 :
1380 :
1381 :
1382 :
1383 130 : void ViewShellManager::Implementation::SetFormShell (
1384 : const ViewShell* pFormShellParent,
1385 : FmFormShell* pFormShell,
1386 : bool bFormShellAboveParent)
1387 : {
1388 130 : ::osl::MutexGuard aGuard (maMutex);
1389 :
1390 130 : mpFormShellParent = pFormShellParent;
1391 130 : mpFormShell = pFormShell;
1392 130 : mbFormShellAboveParent = bFormShellAboveParent;
1393 130 : }
1394 :
1395 :
1396 :
1397 :
1398 : namespace {
1399 :
1400 294 : ShellDescriptor::ShellDescriptor (void)
1401 : : mpShell(NULL),
1402 : mnId(0),
1403 : mpFactory(),
1404 294 : mbIsListenerAddedToWindow(false)
1405 : {
1406 294 : }
1407 :
1408 :
1409 :
1410 :
1411 73 : ShellDescriptor::ShellDescriptor (
1412 : SfxShell* pShell,
1413 : ShellId nId)
1414 : : mpShell(pShell),
1415 : mnId(nId),
1416 : mpFactory(),
1417 73 : mbIsListenerAddedToWindow(false)
1418 : {
1419 73 : }
1420 :
1421 :
1422 :
1423 :
1424 718 : ShellDescriptor::ShellDescriptor (const ShellDescriptor& rDescriptor)
1425 : : mpShell(rDescriptor.mpShell),
1426 : mnId(rDescriptor.mnId),
1427 : mpFactory(rDescriptor.mpFactory),
1428 718 : mbIsListenerAddedToWindow(rDescriptor.mbIsListenerAddedToWindow)
1429 : {
1430 718 : }
1431 :
1432 :
1433 :
1434 :
1435 73 : ShellDescriptor& ShellDescriptor::operator= (const ShellDescriptor& rDescriptor)
1436 : {
1437 73 : if (this != &rDescriptor)
1438 : {
1439 73 : mpShell = rDescriptor.mpShell;
1440 73 : mnId = rDescriptor.mnId;
1441 73 : mpFactory = rDescriptor.mpFactory;
1442 73 : mbIsListenerAddedToWindow = rDescriptor.mbIsListenerAddedToWindow;
1443 : }
1444 73 : return *this;
1445 : }
1446 :
1447 :
1448 :
1449 :
1450 52 : bool ShellDescriptor::IsMainViewShell (void) const
1451 : {
1452 52 : ViewShell* pViewShell = dynamic_cast<ViewShell*>(mpShell);
1453 52 : if (pViewShell != NULL)
1454 52 : return pViewShell->IsMainViewShell();
1455 : else
1456 0 : return false;
1457 : }
1458 :
1459 :
1460 :
1461 :
1462 286 : ::Window* ShellDescriptor::GetWindow (void) const
1463 : {
1464 286 : ViewShell* pViewShell = dynamic_cast<ViewShell*>(mpShell);
1465 286 : if (pViewShell != NULL)
1466 286 : return pViewShell->GetActiveWindow();
1467 : else
1468 0 : return NULL;
1469 : }
1470 :
1471 :
1472 :
1473 : } // end of anonymous namespace
1474 :
1475 33 : } // end of namespace sd
1476 :
1477 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|