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