LCOV - code coverage report
Current view: top level - sd/source/ui/view - ViewShellManager.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 393 466 84.3 %
Date: 2014-11-03 Functions: 58 63 92.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10