summaryrefslogtreecommitdiff
path: root/sd/source/ui/view/FormShellManager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/view/FormShellManager.cxx')
-rw-r--r--sd/source/ui/view/FormShellManager.cxx393
1 files changed, 393 insertions, 0 deletions
diff --git a/sd/source/ui/view/FormShellManager.cxx b/sd/source/ui/view/FormShellManager.cxx
new file mode 100644
index 000000000000..448df20b50cd
--- /dev/null
+++ b/sd/source/ui/view/FormShellManager.cxx
@@ -0,0 +1,393 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "FormShellManager.hxx"
+
+#include "EventMultiplexer.hxx"
+#include "ViewShell.hxx"
+#include "ViewShellBase.hxx"
+#include "ViewShellManager.hxx"
+#include "Window.hxx"
+#include <svx/fmshell.hxx>
+
+namespace sd {
+
+namespace {
+
+/** This factory is responsible for creating and deleting the FmFormShell.
+*/
+class FormShellManagerFactory
+ : public ::sd::ShellFactory<SfxShell>
+{
+public:
+ FormShellManagerFactory (ViewShell& rViewShell, FormShellManager& rManager);
+ virtual FmFormShell* CreateShell (ShellId nId, ::Window* pParentWindow, FrameView* pFrameView);
+ virtual void ReleaseShell (SfxShell* pShell);
+
+private:
+ ::sd::ViewShell& mrViewShell;
+ FormShellManager& mrFormShellManager;
+};
+
+} // end of anonymous namespace
+
+
+FormShellManager::FormShellManager (ViewShellBase& rBase)
+ : mrBase(rBase),
+ mpFormShell(NULL),
+ mbFormShellAboveViewShell(false),
+ mpSubShellFactory(),
+ mbIsMainViewChangePending(false),
+ mpMainViewShellWindow(NULL)
+{
+ // Register at the EventMultiplexer to be informed about changes in the
+ // center pane.
+ Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
+ mrBase.GetEventMultiplexer()->AddEventListener(
+ aLink,
+ sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
+ | sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
+ | sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
+
+ RegisterAtCenterPane();
+}
+
+
+
+
+FormShellManager::~FormShellManager (void)
+{
+ SetFormShell(NULL);
+ UnregisterAtCenterPane();
+
+ // Unregister from the EventMultiplexer.
+ Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
+ mrBase.GetEventMultiplexer()->RemoveEventListener(aLink);
+
+ if (mpSubShellFactory.get() != NULL)
+ {
+ ViewShell* pShell = mrBase.GetMainViewShell().get();
+ if (pShell != NULL)
+ mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell,mpSubShellFactory);
+ }
+}
+
+
+
+
+void FormShellManager::SetFormShell (FmFormShell* pFormShell)
+{
+ if (mpFormShell != pFormShell)
+ {
+ // Disconnect from the old form shell.
+ if (mpFormShell != NULL)
+ {
+ mpFormShell->SetControlActivationHandler(Link());
+ EndListening(*mpFormShell);
+ mpFormShell->SetView(NULL);
+ }
+
+ mpFormShell = pFormShell;
+
+ // Connect to the new form shell.
+ if (mpFormShell != NULL)
+ {
+ mpFormShell->SetControlActivationHandler(
+ LINK(
+ this,
+ FormShellManager,
+ FormControlActivated));
+ StartListening(*mpFormShell);
+
+ ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
+ if (pMainViewShell != NULL)
+ {
+ // Prevent setting the view twice at the FmFormShell.
+ FmFormView* pFormView = static_cast<FmFormView*>(pMainViewShell->GetView());
+ if (mpFormShell->GetFormView() != pFormView)
+ mpFormShell->SetView(pFormView);
+ }
+ }
+
+ // Tell the ViewShellManager where on the stack to place the form shell.
+ mrBase.GetViewShellManager()->SetFormShell(
+ mrBase.GetMainViewShell().get(),
+ mpFormShell,
+ mbFormShellAboveViewShell);
+ }
+}
+
+
+
+
+FmFormShell* FormShellManager::GetFormShell (void)
+{
+ return mpFormShell;
+}
+
+
+
+
+void FormShellManager::RegisterAtCenterPane (void)
+{
+ do
+ {
+ ViewShell* pShell = mrBase.GetMainViewShell().get();
+ if (pShell == NULL)
+ break;
+
+ // No form shell for the slide sorter. Besides that it is not
+ // necessary, using both together results in crashes.
+ if (pShell->GetShellType() == ViewShell::ST_SLIDE_SORTER)
+ break;
+
+ mpMainViewShellWindow = pShell->GetActiveWindow();
+ if (mpMainViewShellWindow == NULL)
+ break;
+
+ // Register at the window to get informed when to move the form
+ // shell to the bottom of the shell stack.
+ mpMainViewShellWindow->AddEventListener(
+ LINK(
+ this,
+ FormShellManager,
+ WindowEventHandler));
+
+ // Create a shell factory and with it activate the form shell.
+ OSL_ASSERT(mpSubShellFactory.get()==NULL);
+ mpSubShellFactory.reset(new FormShellManagerFactory(*pShell, *this));
+ mrBase.GetViewShellManager()->AddSubShellFactory(pShell,mpSubShellFactory);
+ mrBase.GetViewShellManager()->ActivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
+ }
+ while (false);
+}
+
+
+
+
+void FormShellManager::UnregisterAtCenterPane (void)
+{
+ do
+ {
+ if (mpMainViewShellWindow != NULL)
+ {
+ // Unregister from the window.
+ mpMainViewShellWindow->RemoveEventListener(
+ LINK(
+ this,
+ FormShellManager,
+ WindowEventHandler));
+ mpMainViewShellWindow = NULL;
+ }
+
+ // Unregister form at the form shell.
+ SetFormShell(NULL);
+
+ // Deactivate the form shell and destroy the shell factory.
+ ViewShell* pShell = mrBase.GetMainViewShell().get();
+ if (pShell != NULL)
+ {
+ mrBase.GetViewShellManager()->DeactivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
+ mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell, mpSubShellFactory);
+ }
+
+ mpSubShellFactory.reset();
+ }
+ while (false);
+}
+
+
+
+
+IMPL_LINK(FormShellManager, FormControlActivated, FmFormShell*, EMPTYARG)
+{
+ // The form shell has been actived. To give it priority in reacting to
+ // slot calls the form shell is moved to the top of the object bar shell
+ // stack.
+ ViewShell* pShell = mrBase.GetMainViewShell().get();
+ if (pShell!=NULL && !mbFormShellAboveViewShell)
+ {
+ mbFormShellAboveViewShell = true;
+
+ ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
+ mrBase.GetViewShellManager()->SetFormShell(pShell,mpFormShell,mbFormShellAboveViewShell);
+ }
+
+ return 0;
+}
+
+
+
+
+IMPL_LINK(FormShellManager, ConfigurationUpdateHandler, sd::tools::EventMultiplexerEvent*, pEvent)
+{
+ switch (pEvent->meEventId)
+ {
+ case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
+ UnregisterAtCenterPane();
+ break;
+
+ case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
+ mbIsMainViewChangePending = true;
+ break;
+
+ case sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
+ if (mbIsMainViewChangePending)
+ {
+ mbIsMainViewChangePending = false;
+ RegisterAtCenterPane();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+
+
+IMPL_LINK(FormShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
+{
+ if (pEvent != NULL)
+ {
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_GETFOCUS:
+ {
+ // The window of the center pane got the focus. Therefore
+ // the form shell is moved to the bottom of the object bar
+ // stack.
+ ViewShell* pShell = mrBase.GetMainViewShell().get();
+ if (pShell!=NULL && mbFormShellAboveViewShell)
+ {
+ mbFormShellAboveViewShell = false;
+ ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
+ mrBase.GetViewShellManager()->SetFormShell(
+ pShell,
+ mpFormShell,
+ mbFormShellAboveViewShell);
+ }
+ }
+ break;
+
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ // We follow the sloppy focus policy. Losing the focus is
+ // ignored. We wait for the focus to be placed either in
+ // the window or the form shell. The later, however, is
+ // notified over the FormControlActivated handler, not this
+ // one.
+ break;
+
+ case VCLEVENT_OBJECT_DYING:
+ mpMainViewShellWindow = NULL;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+void FormShellManager::Notify(SfxBroadcaster&, const SfxHint& rHint)
+{
+ const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
+ if (pSimpleHint!=NULL && pSimpleHint->GetId()==SFX_HINT_DYING)
+ {
+ // If all goes well this listener is called after the
+ // FormShellManager was notified about the dying form shell by the
+ // FormShellManagerFactory.
+ OSL_ASSERT(mpFormShell==NULL);
+ if (mpFormShell != NULL)
+ {
+ mpFormShell = NULL;
+ mrBase.GetViewShellManager()->SetFormShell(
+ mrBase.GetMainViewShell().get(),
+ NULL,
+ false);
+ }
+ }
+}
+
+
+
+
+
+//===== FormShellManagerFactory ===============================================
+
+namespace {
+
+FormShellManagerFactory::FormShellManagerFactory (
+ ::sd::ViewShell& rViewShell,
+ FormShellManager& rManager)
+ : mrViewShell(rViewShell),
+ mrFormShellManager(rManager)
+{
+}
+
+
+
+
+FmFormShell* FormShellManagerFactory::CreateShell (
+ ::sd::ShellId nId,
+ ::Window*,
+ ::sd::FrameView*)
+{
+ FmFormShell* pShell = NULL;
+
+ ::sd::View* pView = mrViewShell.GetView();
+ if (nId == RID_FORMLAYER_TOOLBOX)
+ {
+ pShell = new FmFormShell(&mrViewShell.GetViewShellBase(), pView);
+ mrFormShellManager.SetFormShell(pShell);
+ }
+
+ return pShell;
+}
+
+
+
+
+void FormShellManagerFactory::ReleaseShell (SfxShell* pShell)
+{
+ if (pShell != NULL)
+ {
+ mrFormShellManager.SetFormShell(NULL);
+ delete pShell;
+ }
+}
+
+} // end of anonymous namespace
+
+} // end of namespace sd