merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / view / FormShellManager.cxx
blob16774a2d7aa566499c329db7e85b83e94ce323a0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FormShellManager.cxx,v $
10 * $Revision: 1.12.34.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "FormShellManager.hxx"
36 #include "EventMultiplexer.hxx"
37 #include "ViewShell.hxx"
38 #include "ViewShellBase.hxx"
39 #include "ViewShellManager.hxx"
40 #include "Window.hxx"
41 #include <svx/fmshell.hxx>
43 namespace sd {
45 namespace {
47 /** This factory is responsible for creating and deleting the FmFormShell.
49 class FormShellManagerFactory
50 : public ::sd::ShellFactory<SfxShell>
52 public:
53 FormShellManagerFactory (ViewShell& rViewShell, FormShellManager& rManager);
54 virtual FmFormShell* CreateShell (ShellId nId, ::Window* pParentWindow, FrameView* pFrameView);
55 virtual void ReleaseShell (SfxShell* pShell);
57 private:
58 ::sd::ViewShell& mrViewShell;
59 FormShellManager& mrFormShellManager;
62 } // end of anonymous namespace
65 FormShellManager::FormShellManager (ViewShellBase& rBase)
66 : mrBase(rBase),
67 mpFormShell(NULL),
68 mbFormShellAboveViewShell(false),
69 mpSubShellFactory(),
70 mbIsMainViewChangePending(false),
71 mpMainViewShellWindow(NULL)
73 // Register at the EventMultiplexer to be informed about changes in the
74 // center pane.
75 Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
76 mrBase.GetEventMultiplexer()->AddEventListener(
77 aLink,
78 sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
79 | sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
80 | sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
82 RegisterAtCenterPane();
88 FormShellManager::~FormShellManager (void)
90 SetFormShell(NULL);
91 UnregisterAtCenterPane();
93 // Unregister from the EventMultiplexer.
94 Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
95 mrBase.GetEventMultiplexer()->RemoveEventListener(aLink);
97 if (mpSubShellFactory.get() != NULL)
99 ViewShell* pShell = mrBase.GetMainViewShell().get();
100 if (pShell != NULL)
101 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell,mpSubShellFactory);
108 void FormShellManager::SetFormShell (FmFormShell* pFormShell)
110 if (mpFormShell != pFormShell)
112 // Disconnect from the old form shell.
113 if (mpFormShell != NULL)
115 mpFormShell->SetControlActivationHandler(Link());
116 EndListening(*mpFormShell);
117 mpFormShell->SetView(NULL);
120 mpFormShell = pFormShell;
122 // Connect to the new form shell.
123 if (mpFormShell != NULL)
125 mpFormShell->SetControlActivationHandler(
126 LINK(
127 this,
128 FormShellManager,
129 FormControlActivated));
130 StartListening(*mpFormShell);
132 ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
133 if (pMainViewShell != NULL)
135 // Prevent setting the view twice at the FmFormShell.
136 FmFormView* pFormView = static_cast<FmFormView*>(pMainViewShell->GetView());
137 if (mpFormShell->GetFormView() != pFormView)
138 mpFormShell->SetView(pFormView);
142 // Tell the ViewShellManager where on the stack to place the form shell.
143 mrBase.GetViewShellManager()->SetFormShell(
144 mrBase.GetMainViewShell().get(),
145 mpFormShell,
146 mbFormShellAboveViewShell);
153 FmFormShell* FormShellManager::GetFormShell (void)
155 return mpFormShell;
161 void FormShellManager::RegisterAtCenterPane (void)
165 ViewShell* pShell = mrBase.GetMainViewShell().get();
166 if (pShell == NULL)
167 break;
169 // No form shell for the slide sorter. Besides that it is not
170 // necessary, using both together results in crashes.
171 if (pShell->GetShellType() == ViewShell::ST_SLIDE_SORTER)
172 break;
174 mpMainViewShellWindow = pShell->GetActiveWindow();
175 if (mpMainViewShellWindow == NULL)
176 break;
178 // Register at the window to get informed when to move the form
179 // shell to the bottom of the shell stack.
180 mpMainViewShellWindow->AddEventListener(
181 LINK(
182 this,
183 FormShellManager,
184 WindowEventHandler));
186 // Create a shell factory and with it activate the form shell.
187 OSL_ASSERT(mpSubShellFactory.get()==NULL);
188 mpSubShellFactory.reset(new FormShellManagerFactory(*pShell, *this));
189 mrBase.GetViewShellManager()->AddSubShellFactory(pShell,mpSubShellFactory);
190 mrBase.GetViewShellManager()->ActivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
192 while (false);
198 void FormShellManager::UnregisterAtCenterPane (void)
202 if (mpMainViewShellWindow != NULL)
204 // Unregister from the window.
205 mpMainViewShellWindow->RemoveEventListener(
206 LINK(
207 this,
208 FormShellManager,
209 WindowEventHandler));
210 mpMainViewShellWindow = NULL;
213 // Unregister form at the form shell.
214 SetFormShell(NULL);
216 // Deactivate the form shell and destroy the shell factory.
217 ViewShell* pShell = mrBase.GetMainViewShell().get();
218 if (pShell != NULL)
220 mrBase.GetViewShellManager()->DeactivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
221 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell, mpSubShellFactory);
224 mpSubShellFactory.reset();
226 while (false);
232 IMPL_LINK(FormShellManager, FormControlActivated, FmFormShell*, EMPTYARG)
234 // The form shell has been actived. To give it priority in reacting to
235 // slot calls the form shell is moved to the top of the object bar shell
236 // stack.
237 ViewShell* pShell = mrBase.GetMainViewShell().get();
238 if (pShell!=NULL && !mbFormShellAboveViewShell)
240 mbFormShellAboveViewShell = true;
242 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
243 mrBase.GetViewShellManager()->SetFormShell(pShell,mpFormShell,mbFormShellAboveViewShell);
246 return 0;
252 IMPL_LINK(FormShellManager, ConfigurationUpdateHandler, sd::tools::EventMultiplexerEvent*, pEvent)
254 switch (pEvent->meEventId)
256 case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
257 UnregisterAtCenterPane();
258 break;
260 case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
261 mbIsMainViewChangePending = true;
262 break;
264 case sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
265 if (mbIsMainViewChangePending)
267 mbIsMainViewChangePending = false;
268 RegisterAtCenterPane();
270 break;
272 default:
273 break;
276 return 0;
282 IMPL_LINK(FormShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
284 if (pEvent != NULL)
286 switch (pEvent->GetId())
288 case VCLEVENT_WINDOW_GETFOCUS:
290 // The window of the center pane got the focus. Therefore
291 // the form shell is moved to the bottom of the object bar
292 // stack.
293 ViewShell* pShell = mrBase.GetMainViewShell().get();
294 if (pShell!=NULL && mbFormShellAboveViewShell)
296 mbFormShellAboveViewShell = false;
297 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
298 mrBase.GetViewShellManager()->SetFormShell(
299 pShell,
300 mpFormShell,
301 mbFormShellAboveViewShell);
304 break;
306 case VCLEVENT_WINDOW_LOSEFOCUS:
307 // We follow the sloppy focus policy. Losing the focus is
308 // ignored. We wait for the focus to be placed either in
309 // the window or the form shell. The later, however, is
310 // notified over the FormControlActivated handler, not this
311 // one.
312 break;
314 case VCLEVENT_OBJECT_DYING:
315 mpMainViewShellWindow = NULL;
316 break;
320 return 0;
326 void FormShellManager::Notify(SfxBroadcaster&, const SfxHint& rHint)
328 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
329 if (pSimpleHint!=NULL && pSimpleHint->GetId()==SFX_HINT_DYING)
331 // If all goes well this listener is called after the
332 // FormShellManager was notified about the dying form shell by the
333 // FormShellManagerFactory.
334 OSL_ASSERT(mpFormShell==NULL);
335 if (mpFormShell != NULL)
337 mpFormShell = NULL;
338 mrBase.GetViewShellManager()->SetFormShell(
339 mrBase.GetMainViewShell().get(),
340 NULL,
341 false);
350 //===== FormShellManagerFactory ===============================================
352 namespace {
354 FormShellManagerFactory::FormShellManagerFactory (
355 ::sd::ViewShell& rViewShell,
356 FormShellManager& rManager)
357 : mrViewShell(rViewShell),
358 mrFormShellManager(rManager)
365 FmFormShell* FormShellManagerFactory::CreateShell (
366 ::sd::ShellId nId,
367 ::Window*,
368 ::sd::FrameView*)
370 FmFormShell* pShell = NULL;
372 ::sd::View* pView = mrViewShell.GetView();
373 if (nId == RID_FORMLAYER_TOOLBOX)
375 pShell = new FmFormShell(&mrViewShell.GetViewShellBase(), pView);
376 mrFormShellManager.SetFormShell(pShell);
379 return pShell;
385 void FormShellManagerFactory::ReleaseShell (SfxShell* pShell)
387 if (pShell != NULL)
389 mrFormShellManager.SetFormShell(NULL);
390 delete pShell;
394 } // end of anonymous namespace
396 } // end of namespace sd