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