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

Generated by: LCOV version 1.10