summaryrefslogtreecommitdiff
path: root/sd/source/ui/view/ViewShellManager.cxx
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2005-01-28 15:33:16 +0000
committerOliver Bolte <obo@openoffice.org>2005-01-28 15:33:16 +0000
commit07c49e9c4dbd21f29be8530127d85d4b61d3dbf9 (patch)
treefc0e5bbb848f74998fca4c96d5a05a63cec633db /sd/source/ui/view/ViewShellManager.cxx
parent6f3f44a132b773802c175fec00a656be66afeff9 (diff)
INTEGRATION: CWS impress20 (1.4.28); FILE MERGED
2005/01/12 14:23:33 af 1.4.28.9: RESYNC: (1.7-1.8); FILE MERGED 2004/12/17 11:12:57 af 1.4.28.8: #118543# Added #ifdefs around OSL_TRACEs. 2004/12/16 17:26:22 af 1.4.28.7: #i37354# Reverted mbKeepMainViewShellOnTop to correct 'false' default value. 2004/12/16 17:04:49 af 1.4.28.6: #i33487# Corrected order of shells pushed on stack to remove merge problem. 2004/12/16 14:52:19 af 1.4.28.5: Resolved merge problem. 2004/12/10 15:35:06 af 1.4.28.4: RESYNC: (1.6-1.7); FILE MERGED 2004/12/10 15:16:43 af 1.4.28.3: Resolved merge problems. 2004/12/07 17:27:42 af 1.4.28.2: RESYNC: (1.4-1.6); FILE MERGED 2004/11/23 17:46:47 af 1.4.28.1: #118543# Introduction of inner Implementation class. Major modification of how the internal and the SFX shell stacks are synchronized.
Diffstat (limited to 'sd/source/ui/view/ViewShellManager.cxx')
-rwxr-xr-xsd/source/ui/view/ViewShellManager.cxx725
1 files changed, 520 insertions, 205 deletions
diff --git a/sd/source/ui/view/ViewShellManager.cxx b/sd/source/ui/view/ViewShellManager.cxx
index ae0f05400776..fb322f6a95b4 100755
--- a/sd/source/ui/view/ViewShellManager.cxx
+++ b/sd/source/ui/view/ViewShellManager.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: ViewShellManager.cxx,v $
*
- * $Revision: 1.9 $
+ * $Revision: 1.10 $
*
- * last change: $Author: obo $ $Date: 2005-01-25 15:19:43 $
+ * last change: $Author: obo $ $Date: 2005-01-28 16:33:16 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -77,23 +77,20 @@
#include <hash_map>
+#undef VERBOSE
namespace sd {
-class ViewShellManager::SpecializedFactoryList
- : public ::std::hash_map<ShellId, ViewShellFactory*>{};
+namespace {
+
class ActiveShellDescriptor {
public:
ActiveShellDescriptor (ViewShell* pViewShell, ShellId nId)
- : mpViewShell(pViewShell), mnId(nId), mbIsOnStack(false) {}
+ : mpViewShell(pViewShell), mnId(nId) {}
ViewShell* mpViewShell;
ShellId mnId;
- bool mbIsOnStack;
};
-class ViewShellManager::ActiveShellList
- : public ::std::list<ActiveShellDescriptor>{};
-namespace {
class IsShell
{
public:
@@ -104,6 +101,7 @@ public:
}
const ViewShell* mpShell;
};
+
class IsId
{
public:
@@ -115,31 +113,117 @@ public:
ShellId mnId;
};
-#define TRACE_ACTIVE_SHELLS \
- {ActiveShellList::const_iterator aI (mpActiveViewShells->begin());\
- for (; aI!=mpActiveViewShells->end(); ++aI) { \
- OSL_TRACE (" %d %p", aI->mnId, aI->mpViewShell); } }
+} // end of anonymous namespace
-}
+class ViewShellManager::Implementation
+{
+public:
+ Implementation (
+ ViewShellManager& rManager,
+ ViewShellBase& rBase);
+ ~Implementation (void);
+
+ void RegisterDefaultFactory (::std::auto_ptr<ViewShellFactory> pFactory);
+ void RegisterFactory (
+ ShellId nId,
+ ::std::auto_ptr<ViewShellFactory> pFactory);
+ ViewShell* ActivateViewShell (
+ ShellId nId,
+ ::Window* pParentWindow,
+ FrameView* pFrameView);
+ void DeactivateViewShell (const ViewShell* pShell);
+ void MoveToTop (const ViewShell* pShell);
+ ViewShell* GetShell (ShellId nId);
+ ShellId GetShellId (const ViewShell* pShell);
+ ViewShellBase& GetViewShellBase (void) const;
+ void Shutdown (void);
+ ViewShell* CreateViewShell (
+ ShellId nShellId,
+ ::Window* pParentWindow,
+ FrameView* pFrameView);
+
+ /** Remove all shells from the SFX stack above and including the given
+ shell.
+ */
+ void TakeShellsFromStack (const SfxShell* pShell);
+
+ /** Prevent updates of the shell stack. While the sub shell manager is
+ locked it will update its internal data structures but not alter the
+ shell stack. Use this method when there are several modifications
+ to the shell stack to prevent multiple rebuilds of the shell stack
+ and resulting broadcasts.
+ */
+ void LockUpdate (void);
+
+ /** Allow updates of the shell stack. This method has to be called the
+ same number of times as LockUpdate() to really allow a rebuild of
+ the shell stack.
+ */
+ void UnlockUpdate (void);
+
+private:
+ ViewShellBase& mrBase;
+
+ ::std::auto_ptr<ViewShellFactory> mpDefaultFactory;
+
+ typedef ::std::hash_map<ShellId,ViewShellFactory*> SpecializedFactoryList;
+ SpecializedFactoryList maSpecializedFactories;
+
+ /** List of the active view shells. In order to create gather all shells
+ to put on the shell stack each view shell in this list is asked for
+ its sub-shells (typically toolbars).
+ */
+ typedef ::std::list<ActiveShellDescriptor> ActiveShellList;
+ ActiveShellList maActiveViewShells;
+
+ /** In this member we remember what shells we have pushed on the shell
+ stack.
+ */
+ typedef ::std::vector<SfxShell*> ShellStack;
+
+ ViewShellCache maCache;
+
+ int mnUpdateLockCount;
+
+ /** When this flag is set then the main view shell is always kept at the
+ top of the shell stack.
+ */
+ bool mbKeepMainViewShellOnTop;
+
+ /** The PushShellsOnStack() method can be called recursively. This flag
+ is used to communicate between different levels of invocation: if
+ the stack has been updated in an inner call the outer call can (has
+ to) stop and return immediately.
+ */
+ bool mbShellStackIsUpToDate;
+
+ void GatherActiveShells (ShellStack& rShellList);
+
+ /** This method rebuilds the stack of shells that are stacked upon the
+ view shell base.
+ */
+ void PushShellsOnStack (void);
+
+ DECL_LINK(WindowEventHandler, VclWindowEvent*);
+
+ void DumpActiveShell (const ActiveShellList& rList);
+ void DumpShellStack (const ShellStack& rStack);
+ void DumpSfxShellStack (void);
+
+ void UpdateShellStack (ShellStack& rRequestedStack);
+};
+
+
+
+
+//===== ViewShellManager ======================================================
ViewShellManager::ViewShellManager (ViewShellBase& rBase)
- : mrBase(rBase),
- mpDefaultFactory (NULL),
- mpSpecializedFactories (
- ::std::auto_ptr<SpecializedFactoryList>(
- new SpecializedFactoryList())),
- mpActiveViewShells(
- ::std::auto_ptr<ActiveShellList>(
- new ActiveShellList())),
- mpCache (new ViewShellCache(*this)),
- mnUpdateLockCount(0),
- mbKeepMainViewShellOnTop(false),
- mbIsValid (true),
- mbTakeShellsFromStackPending(false),
- mbShellStackIsUpToDate(true)
+ : mpImpl(new Implementation(*this,rBase)),
+ mbValid(true)
{
}
@@ -148,49 +232,155 @@ ViewShellManager::ViewShellManager (ViewShellBase& rBase)
ViewShellManager::~ViewShellManager (void)
{
- // Shutdown() should have been called by now but since it is safe to be
- // called twice we call it again just in case. It is, however, unlikely
- // that this does work without crashing.
- DBG_ASSERT (mpCache.get()==NULL,
- "ViewShellManager::Shutdown() has to be called prior to destructor");
- Shutdown();
}
-void ViewShellManager::Shutdown (void)
+void ViewShellManager::RegisterDefaultFactory (
+ ::std::auto_ptr<ViewShellFactory> pFactory)
{
- // Take stacked shells from stack.
- if ( ! mpActiveViewShells->empty())
- {
- UpdateLocker aLock (*this);
+ if (mbValid)
+ mpImpl->RegisterDefaultFactory(pFactory);
+}
- while ( ! mpActiveViewShells->empty())
- {
- DeactivateViewShell(mpActiveViewShells->front().mpViewShell);
- }
- }
- mrBase.RemoveSubShell (NULL);
- // We have the ownership of the factories and because they can not be
- // auto_ptrs in an stl list we have to delete them now by hand.
- for (SpecializedFactoryList::iterator aI (mpSpecializedFactories->begin());
- aI!=mpSpecializedFactories->end();
- aI++)
+
+
+void ViewShellManager::RegisterFactory (
+ ShellId nId,
+ ::std::auto_ptr<ViewShellFactory> pFactory)
+{
+ if (mbValid)
+ mpImpl->RegisterFactory(nId,pFactory);
+}
+
+
+
+
+ViewShell* ViewShellManager::ActivateViewShell (
+ ShellId nShellId,
+ ::Window* pParentWindow,
+ FrameView* pFrameView)
+{
+ if (mbValid)
+ return mpImpl->ActivateViewShell(nShellId,pParentWindow,pFrameView);
+ else
+ return NULL;
+}
+
+
+
+
+void ViewShellManager::DeactivateViewShell (const ViewShell* pShell)
+{
+ if (mbValid)
+ mpImpl->DeactivateViewShell(pShell);
+}
+
+
+
+
+void ViewShellManager::InvalidateShellStack (const SfxShell* pShell)
+{
+ if (mbValid)
+ mpImpl->TakeShellsFromStack(pShell);
+}
+
+
+
+
+void ViewShellManager::MoveToTop (const ViewShell* pShell)
+{
+ if (mbValid)
+ mpImpl->MoveToTop(pShell);
+}
+
+
+
+
+ViewShell* ViewShellManager::GetShell (ShellId nId)
+{
+ if (mbValid)
+ return mpImpl->GetShell(nId);
+ else
+ return NULL;
+}
+
+
+
+
+ShellId ViewShellManager::GetShellId (const ViewShell* pShell)
+{
+ if (mbValid)
+ return mpImpl->GetShellId(pShell);
+ else
+ return snInvalidShellId;
+}
+
+
+
+
+ViewShellBase& ViewShellManager::GetViewShellBase (void) const
+{
+ return mpImpl->GetViewShellBase();
+}
+
+
+
+
+void ViewShellManager::Shutdown (void)
+{
+ if (mbValid)
{
- delete aI->second;
+ mpImpl->Shutdown();
+ mbValid = false;
}
+}
- // Destroy members.
- mpCache.reset();
- mpDefaultFactory.reset();
+
+
+
+ViewShell* ViewShellManager::CreateViewShell (
+ ShellId nShellId,
+ ::Window* pParentWindow,
+ FrameView* pFrameView)
+{
+ if (mbValid)
+ return mpImpl->CreateViewShell(nShellId,pParentWindow,pFrameView);
+ else
+ return NULL;
}
-void ViewShellManager::RegisterDefaultFactory (
+//===== ViewShellManager::Implementation ======================================
+
+ViewShellManager::Implementation::Implementation (
+ ViewShellManager& rManager,
+ ViewShellBase& rBase)
+ : mrBase(rBase),
+ mpDefaultFactory (NULL),
+ maSpecializedFactories (),
+ maActiveViewShells(),
+ maCache (rManager),
+ mnUpdateLockCount(0),
+ mbKeepMainViewShellOnTop(false),
+ mbShellStackIsUpToDate(true)
+{
+}
+
+
+
+
+ViewShellManager::Implementation::~Implementation (void)
+{
+ Shutdown();
+}
+
+
+void ViewShellManager::Implementation::RegisterDefaultFactory (
::std::auto_ptr<ViewShellFactory> pFactory)
{
mpDefaultFactory = pFactory;
@@ -199,26 +389,24 @@ void ViewShellManager::RegisterDefaultFactory (
-void ViewShellManager::RegisterFactory (
+void ViewShellManager::Implementation::RegisterFactory (
ShellId nId,
::std::auto_ptr<ViewShellFactory> pFactory)
{
- (*mpSpecializedFactories)[nId] = pFactory.get();
+ maSpecializedFactories[nId] = pFactory.get();
pFactory.release();
}
-ViewShell* ViewShellManager::ActivateViewShell (
+ViewShell* ViewShellManager::Implementation::ActivateViewShell (
ShellId nShellId,
::Window* pParentWindow,
FrameView* pFrameView)
{
- PrepareStackModification();
-
// Create a new shell or recycle on in the cache.
- ViewShell* pViewShell = mpCache->GetViewShell (
+ ViewShell* pViewShell = maCache.GetViewShell (
nShellId,
pParentWindow,
pFrameView);
@@ -231,7 +419,7 @@ ViewShell* ViewShellManager::ActivateViewShell (
pWindow->AddEventListener(
LINK(
this,
- ViewShellManager,
+ ViewShellManager::Implementation,
WindowEventHandler));
else
{
@@ -245,15 +433,15 @@ ViewShell* ViewShellManager::ActivateViewShell (
// displayed in the center pane then it is inserted at the position
// one below the top.
ActiveShellList::iterator iInsertPosition (
- mpActiveViewShells->begin());
- if (iInsertPosition != mpActiveViewShells->end()
+ maActiveViewShells.begin());
+ if (iInsertPosition != maActiveViewShells.end()
&& mbKeepMainViewShellOnTop
&& ! pViewShell->IsMainViewShell()
&& iInsertPosition->mpViewShell->IsMainViewShell())
{
++iInsertPosition;
}
- mpActiveViewShells->insert(
+ maActiveViewShells.insert(
iInsertPosition,
ActiveShellDescriptor(pViewShell, nShellId));
}
@@ -264,58 +452,46 @@ ViewShell* ViewShellManager::ActivateViewShell (
-void ViewShellManager::DeactivateViewShell (const ViewShell* pShell)
+void ViewShellManager::Implementation::DeactivateViewShell (const ViewShell* pShell)
{
- PrepareStackModification ();
-
ActiveShellList::iterator aI (::std::find_if (
- mpActiveViewShells->begin(),
- mpActiveViewShells->end(),
+ maActiveViewShells.begin(),
+ maActiveViewShells.end(),
IsShell(pShell)));
- if (aI != mpActiveViewShells->end())
+ if (aI != maActiveViewShells.end())
{
- UpdateLocker aLocker (*this);
+ UpdateLock aLocker (*this);
ViewShell* pViewShell = aI->mpViewShell;
pViewShell->GetObjectBarManager().Clear();
- mpActiveViewShells->erase (aI);
+ maActiveViewShells.erase (aI);
pViewShell->GetActiveWindow()->RemoveEventListener(
LINK(
this,
- ViewShellManager,
+ ViewShellManager::Implementation,
WindowEventHandler));
- mrBase.RemoveSubShell(pViewShell);
- mpCache->ReleaseViewShell (pViewShell);
+ TakeShellsFromStack(pViewShell);
+ maCache.ReleaseViewShell (pViewShell);
}
}
-void ViewShellManager::InvalidateShellStack (void)
-{
- // Call PrepareStackModification() to force a PushShellsOnStack() at the
- // next UnlockUpdate() to lock level 0.
- PrepareStackModification ();
-}
-
-
-
-
-void ViewShellManager::MoveToTop (const ViewShell* pShell)
+void ViewShellManager::Implementation::MoveToTop (const ViewShell* pShell)
{
ActiveShellList::iterator aI (::std::find_if (
- mpActiveViewShells->begin(),
- mpActiveViewShells->end(),
+ maActiveViewShells.begin(),
+ maActiveViewShells.end(),
IsShell(pShell)));
bool bMove = true;
- if (aI != mpActiveViewShells->end())
+ if (aI != maActiveViewShells.end())
{
// Is the shell already at the top of the stack? We have to keep
// the case in mind that mbKeepMainViewShellOnTop is true. Shells
// that are not the main view shell are placed on the second-to-top
// position in this case.
- if (aI == mpActiveViewShells->begin()
+ if (aI == maActiveViewShells.begin()
&& (aI->mpViewShell->IsMainViewShell() || ! mbKeepMainViewShellOnTop))
{
// The shell is at the top position and is either a) the main
@@ -323,7 +499,7 @@ void ViewShellManager::MoveToTop (const ViewShell* pShell)
// kept at the top position. We do not have to move the shell.
bMove = false;
}
- else if (aI == ++mpActiveViewShells->begin()
+ else if (aI == ++maActiveViewShells.begin()
&& ! aI->mpViewShell->IsMainViewShell()
&& mbKeepMainViewShellOnTop)
{
@@ -343,24 +519,23 @@ void ViewShellManager::MoveToTop (const ViewShell* pShell)
// internal list of shells and inserted at the correct position.
if (bMove)
{
- UpdateLocker aLock (*this);
- InvalidateShellStack();
+ UpdateLock aLock (*this);
+ TakeShellsFromStack(pShell);
ViewShell* pNonConstViewShell = aI->mpViewShell;
ShellId nId = aI->mnId;
- mpActiveViewShells->erase (aI);
+ maActiveViewShells.erase(aI);
// Find out whether to insert at the top or one below.
ActiveShellList::iterator aInsertPosition (
- mpActiveViewShells->begin());
+ maActiveViewShells.begin());
if (mbKeepMainViewShellOnTop && ! aI->mpViewShell->IsMainViewShell())
{
- if (mpActiveViewShells->back().mpViewShell->IsMainViewShell())
+ if (maActiveViewShells.back().mpViewShell->IsMainViewShell())
aInsertPosition++;
}
- PrepareStackModification();
- mpActiveViewShells->insert (
+ maActiveViewShells.insert (
aInsertPosition,
ActiveShellDescriptor(pNonConstViewShell,nId));
}
@@ -369,13 +544,13 @@ void ViewShellManager::MoveToTop (const ViewShell* pShell)
-ViewShell* ViewShellManager::GetShell (ShellId nId)
+ViewShell* ViewShellManager::Implementation::GetShell (ShellId nId)
{
ActiveShellList::iterator aI (::std::find_if (
- mpActiveViewShells->begin(),
- mpActiveViewShells->end(),
+ maActiveViewShells.begin(),
+ maActiveViewShells.end(),
IsId(nId)));
- if (aI != mpActiveViewShells->end())
+ if (aI != maActiveViewShells.end())
return aI->mpViewShell;
else
return NULL;
@@ -384,13 +559,13 @@ ViewShell* ViewShellManager::GetShell (ShellId nId)
-ShellId ViewShellManager::GetShellId (const ViewShell* pShell)
+ShellId ViewShellManager::Implementation::GetShellId (const ViewShell* pShell)
{
ActiveShellList::iterator aI (::std::find_if (
- mpActiveViewShells->begin(),
- mpActiveViewShells->end(),
+ maActiveViewShells.begin(),
+ maActiveViewShells.end(),
IsShell(pShell)));
- if (aI != mpActiveViewShells->end())
+ if (aI != maActiveViewShells.end())
return aI->mnId;
else
return snInvalidShellId;
@@ -399,17 +574,15 @@ ShellId ViewShellManager::GetShellId (const ViewShell* pShell)
-void ViewShellManager::LockUpdate (void)
+void ViewShellManager::Implementation::LockUpdate (void)
{
- if (mnUpdateLockCount == 0)
- mbTakeShellsFromStackPending = true;
mnUpdateLockCount++;
}
-void ViewShellManager::UnlockUpdate (void)
+void ViewShellManager::Implementation::UnlockUpdate (void)
{
mnUpdateLockCount--;
if (mnUpdateLockCount < 0)
@@ -419,117 +592,197 @@ void ViewShellManager::UnlockUpdate (void)
mnUpdateLockCount = 0;
}
if (mnUpdateLockCount == 0)
- if ( ! mbTakeShellsFromStackPending)
- PushShellsOnStack();
+ PushShellsOnStack();
}
-void ViewShellManager::GatherActiveShells (
- ::std::vector<SfxShell*>& rShellList)
+void ViewShellManager::Implementation::PushShellsOnStack (void)
{
- for (ActiveShellList::iterator aI (mpActiveViewShells->begin());
- aI!=mpActiveViewShells->end();
- aI++)
+ // Create a local stack of the shells that are to push on the shell
+ // stack. We can thus safly create the required shells wile still
+ // having a valid shell stack.
+ ShellStack aShellStack;
+ for (ActiveShellList::reverse_iterator aI (maActiveViewShells.rbegin());
+ aI!=maActiveViewShells.rend();
+ ++aI)
{
- // Get all its sub shells that are placed above the shell.
- aI->mpViewShell->GetUpperShellList (rShellList);
+ // Get all its sub shells that are placed below the shell.
+ aI->mpViewShell->GetLowerShellList (aShellStack);
// Put the shell itself on the local stack.
- rShellList.push_back (aI->mpViewShell);
+ aShellStack.push_back (aI->mpViewShell);
- // Get all its sub shells that are placed below the shell.
- aI->mpViewShell->GetLowerShellList (rShellList);
+ // Get all its sub shells that are placed above the shell.
+ aI->mpViewShell->GetUpperShellList (aShellStack);
}
- OSL_TRACE ("gathered shell list:");
- ::std::vector<SfxShell*>::iterator iShell;
- for (iShell=rShellList.begin(); iShell!=rShellList.end(); iShell++)
- OSL_TRACE (" %p: %s",
- *iShell,
- ::rtl::OUStringToOString((*iShell)->GetName(),
- RTL_TEXTENCODING_UTF8).getStr());
+ // Now update the SFX stack to look like the local stack.
+ UpdateShellStack (aShellStack);
}
-void ViewShellManager::TakeShellsFromStack (void)
+/** Update the SFX shell stack (the portion that is visible to us) so that
+ it matches the internal shell stack. Since we can not look at the
+ shells on the SFX stack directly we use the copy that we created the
+ last time when we rebuilt the SFX stack. This is done in three steps:
+ 1. Find the lowest shell in which the two stack differ.
+ 2. Remove all shells above and including that shell from the SFX stack.
+ This should not be necessary because deactivated shells should have been
+ removed already.
+ 3. Push all shells of the internal stack on the SFX shell stack that are
+ not already present on the later.
+*/
+void ViewShellManager::Implementation::UpdateShellStack (ShellStack& rRequestedStack)
{
- // Now do the actual removing.
- if (mbIsValid)
- {
- ::std::vector<SfxShell*> aShellsToRemove;
- GatherActiveShells (aShellsToRemove);
+ ShellStack aSfxShellStack;
+ ShellStack::const_iterator iSfxShell;
+ ShellStack::iterator iRequestedShell;
- ::std::vector<SfxShell*>::iterator iShell;
- // Deactivate our shells on the stack before they are removed so
- // that during the Deactivation() calls the stack is still intact.
- for (iShell=aShellsToRemove.begin();
- iShell!=aShellsToRemove.end();
- iShell++)
- {
- (*iShell)->Deactivate(TRUE);
- }
- for (iShell=aShellsToRemove.begin();
- iShell!=aShellsToRemove.end();
- iShell++)
+ mbShellStackIsUpToDate = false;
+
+#ifdef VERBOSE
+ OSL_TRACE("UpdateShellStack");
+ OSL_TRACE("Current SFX Stack");
+ DumpSfxShellStack();
+ OSL_TRACE("Requested Stack");
+ DumpShellStack(rRequestedStack);
+#endif
+
+ // 1. Put the SFX shell stack in a local data structure so that it can
+ // be searched properly.
+ for (USHORT nIndex=0; true; nIndex++)
+ {
+ if (mrBase.GetSubShell(nIndex)==NULL)
{
- mrBase.RemoveSubShell (*iShell);
+ aSfxShellStack.reserve(nIndex);
+ while (nIndex-- > 0)
+ aSfxShellStack.push_back(mrBase.GetSubShell(nIndex));
+ break;
}
- if (mrBase.GetDispatcher() != NULL)
- mrBase.GetDispatcher()->Flush();
}
+
+ // 2. Find the lowest shell in which the two stacks differ.
+ iSfxShell = aSfxShellStack.begin();
+ iRequestedShell = rRequestedStack.begin();
+ while (iSfxShell != aSfxShellStack.end()
+ && iRequestedShell!=rRequestedStack.end()
+ && (*iSfxShell)==(*iRequestedShell))
+ {
+ ++iSfxShell;
+ ++iRequestedShell;
+ }
+
+ // 3. Remove all shells above and including the differing shell from the
+ // SFX stack starting with the shell on top of the stack.
+ while (iSfxShell != aSfxShellStack.end())
+ {
+ SfxShell* pShell = aSfxShellStack.back();
+ aSfxShellStack.pop_back();
+#ifdef VERBOSE
+ OSL_TRACE("removing shell %p from stack", pShell);
+#endif
+ mrBase.RemoveSubShell(pShell);
+ }
+
+ // 4. Push shells from the given stack onto the SFX stack.
+ while (iRequestedShell != rRequestedStack.end())
+ {
+#ifdef VERBOSE
+ OSL_TRACE("pushing shell %p on stack", *iRequestedShell);
+#endif
+ mrBase.AddSubShell(**iRequestedShell);
+ ++iRequestedShell;
+
+ // The pushing of the shell on to the shell stack may have lead to
+ // another invocation of this method. In this case we have to abort
+ // pushing shells on the stack and return immediately.
+ if (mbShellStackIsUpToDate)
+ break;
+ }
+
+ // 5. Tell the dispatcher to update the SFX shell.
+ if (mrBase.GetDispatcher() != NULL)
+ mrBase.GetDispatcher()->Flush();
+
+ // 6. Finally Tell an invocation of this method on a higher level that it can (has
+ // to) abort and return immediately.
+ mbShellStackIsUpToDate = true;
+
+#ifdef VERBOSE
+ OSL_TRACE("New current stack");
+ DumpSfxShellStack();
+#endif
}
-void ViewShellManager::PushShellsOnStack (void)
+void ViewShellManager::Implementation::TakeShellsFromStack (const SfxShell* pShell)
{
- mbShellStackIsUpToDate = false;
+#ifdef VERBOSE
+ OSL_TRACE("TakeShellsFromStack(%p)", pShell);
+ DumpSfxShellStack();
+#endif
- // Remove all stacked shells.
- mrBase.RemoveSubShell (NULL);
+ // 0.Make sure that the given shell is on the stack. This is a
+ // preparation for the following assertion.
+ for (USHORT nIndex=0; true; nIndex++)
+ {
+ SfxShell* pShellOnStack = mrBase.GetSubShell(nIndex);
+ if (pShellOnStack == NULL)
+ {
+ // Set pShell to NULL to indicate the following code that the
+ // shell is not on the stack.
+ pShell = NULL;
+ break;
+ }
+ else if (pShellOnStack == pShell)
+ break;
+ }
- // Create a local stack of the shells that are to push on the shell
- // stack. We can thus safly create the required shells wile still
- // having a valid shell stack.
- if (mbIsValid)
+ if (pShell != NULL)
{
- ::std::vector<SfxShell*> aShellsToPush;
- GatherActiveShells (aShellsToPush);
-
- // Now do the actual pushing.
- ::std::vector<SfxShell*>::reverse_iterator iShell;
- for (iShell=aShellsToPush.rbegin();
- iShell!=aShellsToPush.rend();
- iShell++)
+ // 1. Deactivate our shells on the stack before they are removed so
+ // that during the Deactivation() calls the stack is still intact.
+ for (USHORT nIndex=0; true; nIndex++)
{
- OSL_TRACE (" putting %s on stack",
- ::rtl::OUStringToOString((*iShell)->GetName(),RTL_TEXTENCODING_UTF8).getStr());
- mrBase.AddSubShell (**iShell);
-
- // The pushing of the shell on to the shell stack may have lead
- // to another invocation of this method. In this case we have
- // to abort pushing shells on the stack and return immediately.
- if (mbShellStackIsUpToDate)
+ SfxShell* pShellOnStack = mrBase.GetSubShell(nIndex);
+ pShellOnStack->Deactivate(TRUE);
+ if (pShellOnStack == pShell)
+ break;
+ }
+
+ // 2. Remove the shells from the stack.
+ while (true)
+ {
+ SfxShell* pShellOnStack = mrBase.GetSubShell(0);
+#ifdef VERBOSE
+ OSL_TRACE("removing shell %p from stack", pShellOnStack);
+#endif
+ mrBase.RemoveSubShell(pShellOnStack);
+ if (pShellOnStack == pShell)
break;
}
+
+ // 3. Update the stack.
if (mrBase.GetDispatcher() != NULL)
mrBase.GetDispatcher()->Flush();
}
- // Tell an invocation of this method on a higher level that it can (has
- // to) abort and return immediately.
- mbShellStackIsUpToDate = true;
+#ifdef VERBOSE
+ OSL_TRACE("Sfx shell stack is:");
+ DumpSfxShellStack();
+#endif
}
-ViewShellBase& ViewShellManager::GetViewShellBase (void) const
+ViewShellBase& ViewShellManager::Implementation::GetViewShellBase (void) const
{
return mrBase;
}
@@ -537,15 +790,7 @@ ViewShellBase& ViewShellManager::GetViewShellBase (void) const
-void ViewShellManager::ShutDown (void)
-{
- mbIsValid = false;
-}
-
-
-
-
-IMPL_LINK(ViewShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
+IMPL_LINK(ViewShellManager::Implementation, WindowEventHandler, VclWindowEvent*, pEvent)
{
if (pEvent != NULL)
{
@@ -556,8 +801,8 @@ IMPL_LINK(ViewShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
{
case VCLEVENT_WINDOW_GETFOCUS:
{
- for (ActiveShellList::iterator aI(mpActiveViewShells->begin());
- aI!=mpActiveViewShells->end();
+ for (ActiveShellList::iterator aI(maActiveViewShells.begin());
+ aI!=maActiveViewShells.end();
aI++)
{
if (pEventWindow == static_cast< ::Window*>(
@@ -580,7 +825,7 @@ IMPL_LINK(ViewShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
-ViewShell* ViewShellManager::CreateViewShell (
+ViewShell* ViewShellManager::Implementation::CreateViewShell (
ShellId nShellId,
::Window* pParentWindow,
FrameView* pFrameView)
@@ -591,12 +836,11 @@ ViewShell* ViewShellManager::CreateViewShell (
ViewShellFactory* pFactory = mpDefaultFactory.get();
// Look up a specialized factory.
- SpecializedFactoryList::iterator aI (
- mpSpecializedFactories->find(nShellId));
- if (aI != mpSpecializedFactories->end())
+ SpecializedFactoryList::iterator aI (maSpecializedFactories.find(nShellId));
+ if (aI != maSpecializedFactories.end())
pFactory = aI->second;
- UpdateLocker aLocker (*this);
+ UpdateLock aLocker (*this);
if (pFactory!=NULL && pParentWindow!=NULL)
{
@@ -613,32 +857,103 @@ ViewShell* ViewShellManager::CreateViewShell (
-void ViewShellManager::PrepareStackModification (void)
+void ViewShellManager::Implementation::Shutdown (void)
{
- if (mbTakeShellsFromStackPending)
+ // Take stacked shells from stack.
+ if ( ! maActiveViewShells.empty())
+ {
+ UpdateLock aLock (*this);
+
+ while ( ! maActiveViewShells.empty())
+ {
+ DeactivateViewShell(maActiveViewShells.front().mpViewShell);
+ }
+ }
+ mrBase.RemoveSubShell (NULL);
+
+ // We have the ownership of the factories and because they can not be
+ // auto_ptrs in an stl list we have to delete them now by hand.
+ for (SpecializedFactoryList::iterator aI (maSpecializedFactories.begin());
+ aI!=maSpecializedFactories.end();
+ aI++)
{
- mbTakeShellsFromStackPending = false;
- TakeShellsFromStack();
+ delete aI->second;
+ }
+
+ // Destroy members.
+ maCache.Shutdown();
+ mpDefaultFactory.reset();
+}
+
+
+
+
+void ViewShellManager::Implementation::DumpActiveShell (const ActiveShellList& rList)
+{
+ ActiveShellList::const_iterator aI;
+ for (aI=rList.begin(); aI!=rList.end(); ++aI)
+ {
+ OSL_TRACE (" %d %p",
+ aI->mnId,
+ aI->mpViewShell);
+ }
+}
+
+
+
+
+void ViewShellManager::Implementation::DumpShellStack (const ShellStack& rStack)
+{
+ ShellStack::const_reverse_iterator iEntry;
+ for (iEntry=rStack.rbegin(); iEntry!=rStack.rend(); ++iEntry)
+ OSL_TRACE (" %p: %s",
+ *iEntry,
+ ::rtl::OUStringToOString((*iEntry)->GetName(),RTL_TEXTENCODING_UTF8).getStr());
+}
+
+
+
+
+void ViewShellManager::Implementation::DumpSfxShellStack (void)
+{
+ USHORT nIndex;
+ for (nIndex=0; true; nIndex++)
+ {
+ SfxShell* pShell = mrBase.GetSubShell(nIndex);
+ if (pShell == NULL)
+ break;
+ OSL_TRACE (" %d : %p: %s",
+ nIndex,
+ pShell,
+ ::rtl::OUStringToOString(pShell->GetName(),RTL_TEXTENCODING_UTF8).getStr());
}
}
+//===== ViewShellManager::UpdateLock ==========================================
+
+ViewShellManager::UpdateLock::UpdateLock (ViewShellManager& rManager)
+ : mrManagerImplementation(*rManager.mpImpl.get())
+{
+ mrManagerImplementation.LockUpdate();
+}
+
+
-//===== ViewShellManager::UpdateLocker ========================================
-ViewShellManager::UpdateLocker::UpdateLocker (ViewShellManager& rManager)
- : mrManager(rManager)
+ViewShellManager::UpdateLock::UpdateLock (ViewShellManager::Implementation& rManagerImplementation)
+ : mrManagerImplementation(rManagerImplementation)
{
- mrManager.LockUpdate();
+ mrManagerImplementation.LockUpdate();
}
-ViewShellManager::UpdateLocker::~UpdateLocker (void)
+ViewShellManager::UpdateLock::~UpdateLock (void)
{
- mrManager.UnlockUpdate();
+ mrManagerImplementation.UnlockUpdate();
}