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