xref: /AOO41X/main/sd/source/ui/view/ViewShellManager.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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