bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / view / FormShellManager.cxx
blobad6354b9610550bddb0b0ae9aa3125322c3dcf7f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "FormShellManager.hxx"
22 #include "EventMultiplexer.hxx"
23 #include "ViewShell.hxx"
24 #include "ViewShellBase.hxx"
25 #include "ViewShellManager.hxx"
26 #include "Window.hxx"
27 #include <svx/fmshell.hxx>
29 namespace sd {
31 namespace {
33 /** This factory is responsible for creating and deleting the FmFormShell.
35 class FormShellManagerFactory
36 : public ::sd::ShellFactory<SfxShell>
38 public:
39 FormShellManagerFactory (ViewShell& rViewShell, FormShellManager& rManager);
40 virtual FmFormShell* CreateShell (ShellId nId, vcl::Window* pParentWindow, FrameView* pFrameView) SAL_OVERRIDE;
41 virtual void ReleaseShell (SfxShell* pShell) SAL_OVERRIDE;
43 private:
44 ::sd::ViewShell& mrViewShell;
45 FormShellManager& mrFormShellManager;
48 } // end of anonymous namespace
50 FormShellManager::FormShellManager (ViewShellBase& rBase)
51 : mrBase(rBase),
52 mpFormShell(NULL),
53 mbFormShellAboveViewShell(false),
54 mpSubShellFactory(),
55 mbIsMainViewChangePending(false),
56 mpMainViewShellWindow(NULL)
58 // Register at the EventMultiplexer to be informed about changes in the
59 // center pane.
60 Link<> aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
61 mrBase.GetEventMultiplexer()->AddEventListener(
62 aLink,
63 sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
64 | sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
65 | sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
67 RegisterAtCenterPane();
70 FormShellManager::~FormShellManager()
72 SetFormShell(NULL);
73 UnregisterAtCenterPane();
75 // Unregister from the EventMultiplexer.
76 Link<> aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
77 mrBase.GetEventMultiplexer()->RemoveEventListener(aLink);
79 if (mpSubShellFactory.get() != NULL)
81 ViewShell* pShell = mrBase.GetMainViewShell().get();
82 if (pShell != NULL)
83 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell,mpSubShellFactory);
87 void FormShellManager::SetFormShell (FmFormShell* pFormShell)
89 if (mpFormShell != pFormShell)
91 // Disconnect from the old form shell.
92 if (mpFormShell != NULL)
94 mpFormShell->SetControlActivationHandler(Link<>());
95 EndListening(*mpFormShell);
96 mpFormShell->SetView(NULL);
99 mpFormShell = pFormShell;
101 // Connect to the new form shell.
102 if (mpFormShell != NULL)
104 mpFormShell->SetControlActivationHandler(
105 LINK(
106 this,
107 FormShellManager,
108 FormControlActivated));
109 StartListening(*mpFormShell);
111 ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
112 if (pMainViewShell != NULL)
114 // Prevent setting the view twice at the FmFormShell.
115 FmFormView* pFormView = static_cast<FmFormView*>(pMainViewShell->GetView());
116 if (mpFormShell->GetFormView() != pFormView)
117 mpFormShell->SetView(pFormView);
121 // Tell the ViewShellManager where on the stack to place the form shell.
122 mrBase.GetViewShellManager()->SetFormShell(
123 mrBase.GetMainViewShell().get(),
124 mpFormShell,
125 mbFormShellAboveViewShell);
129 void FormShellManager::RegisterAtCenterPane()
131 ViewShell* pShell = mrBase.GetMainViewShell().get();
132 if (pShell == NULL)
133 return;
135 // No form shell for the slide sorter. Besides that it is not
136 // necessary, using both together results in crashes.
137 if (pShell->GetShellType() == ViewShell::ST_SLIDE_SORTER)
138 return;
140 mpMainViewShellWindow = pShell->GetActiveWindow();
141 if (mpMainViewShellWindow == nullptr)
142 return;
144 // Register at the window to get informed when to move the form
145 // shell to the bottom of the shell stack.
146 mpMainViewShellWindow->AddEventListener(
147 LINK(
148 this,
149 FormShellManager,
150 WindowEventHandler));
152 // Create a shell factory and with it activate the form shell.
153 OSL_ASSERT(mpSubShellFactory.get()==NULL);
154 mpSubShellFactory.reset(new FormShellManagerFactory(*pShell, *this));
155 mrBase.GetViewShellManager()->AddSubShellFactory(pShell,mpSubShellFactory);
156 mrBase.GetViewShellManager()->ActivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
159 void FormShellManager::UnregisterAtCenterPane()
161 if (mpMainViewShellWindow != nullptr)
163 // Unregister from the window.
164 mpMainViewShellWindow->RemoveEventListener(
165 LINK(
166 this,
167 FormShellManager,
168 WindowEventHandler));
169 mpMainViewShellWindow = NULL;
172 // Unregister form at the form shell.
173 SetFormShell(NULL);
175 // Deactivate the form shell and destroy the shell factory.
176 ViewShell* pShell = mrBase.GetMainViewShell().get();
177 if (pShell != NULL)
179 mrBase.GetViewShellManager()->DeactivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
180 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell, mpSubShellFactory);
183 mpSubShellFactory.reset();
186 IMPL_LINK_NOARG(FormShellManager, FormControlActivated)
188 // The form shell has been activated. To give it priority in reacting to
189 // slot calls the form shell is moved to the top of the object bar shell
190 // stack.
191 ViewShell* pShell = mrBase.GetMainViewShell().get();
192 if (pShell!=NULL && !mbFormShellAboveViewShell)
194 mbFormShellAboveViewShell = true;
196 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
197 mrBase.GetViewShellManager()->SetFormShell(pShell,mpFormShell,mbFormShellAboveViewShell);
200 return 0;
203 IMPL_LINK(FormShellManager, ConfigurationUpdateHandler, sd::tools::EventMultiplexerEvent*, pEvent)
205 switch (pEvent->meEventId)
207 case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
208 UnregisterAtCenterPane();
209 break;
211 case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
212 mbIsMainViewChangePending = true;
213 break;
215 case sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
216 if (mbIsMainViewChangePending)
218 mbIsMainViewChangePending = false;
219 RegisterAtCenterPane();
221 break;
223 default:
224 break;
227 return 0;
230 IMPL_LINK(FormShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
232 if (pEvent != NULL)
234 switch (pEvent->GetId())
236 case VCLEVENT_WINDOW_GETFOCUS:
238 // The window of the center pane got the focus. Therefore
239 // the form shell is moved to the bottom of the object bar
240 // stack.
241 ViewShell* pShell = mrBase.GetMainViewShell().get();
242 if (pShell!=NULL && mbFormShellAboveViewShell)
244 mbFormShellAboveViewShell = false;
245 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
246 mrBase.GetViewShellManager()->SetFormShell(
247 pShell,
248 mpFormShell,
249 mbFormShellAboveViewShell);
252 break;
254 case VCLEVENT_WINDOW_LOSEFOCUS:
255 // We follow the sloppy focus policy. Losing the focus is
256 // ignored. We wait for the focus to be placed either in
257 // the window or the form shell. The later, however, is
258 // notified over the FormControlActivated handler, not this
259 // one.
260 break;
262 case VCLEVENT_OBJECT_DYING:
263 mpMainViewShellWindow = NULL;
264 break;
268 return 0;
271 void FormShellManager::Notify(SfxBroadcaster&, const SfxHint& rHint)
273 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
274 if (pSimpleHint!=NULL && pSimpleHint->GetId()==SFX_HINT_DYING)
276 // If all goes well this listener is called after the
277 // FormShellManager was notified about the dying form shell by the
278 // FormShellManagerFactory.
279 OSL_ASSERT(mpFormShell==NULL);
280 if (mpFormShell != NULL)
282 mpFormShell = NULL;
283 mrBase.GetViewShellManager()->SetFormShell(
284 mrBase.GetMainViewShell().get(),
285 NULL,
286 false);
291 //===== FormShellManagerFactory ===============================================
293 namespace {
295 FormShellManagerFactory::FormShellManagerFactory (
296 ::sd::ViewShell& rViewShell,
297 FormShellManager& rManager)
298 : mrViewShell(rViewShell),
299 mrFormShellManager(rManager)
303 FmFormShell* FormShellManagerFactory::CreateShell (
304 ::sd::ShellId nId,
305 vcl::Window*,
306 ::sd::FrameView*)
308 FmFormShell* pShell = NULL;
310 ::sd::View* pView = mrViewShell.GetView();
311 if (nId == RID_FORMLAYER_TOOLBOX)
313 pShell = new FmFormShell(&mrViewShell.GetViewShellBase(), pView);
314 mrFormShellManager.SetFormShell(pShell);
317 return pShell;
320 void FormShellManagerFactory::ReleaseShell (SfxShell* pShell)
322 if (pShell != NULL)
324 mrFormShellManager.SetFormShell(NULL);
325 delete pShell;
329 } // end of anonymous namespace
331 } // end of namespace sd
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */