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