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

Generated by: LCOV version 1.11