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