Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include "FormShellManager.hxx"
22 :
23 : #include "EventMultiplexer.hxx"
24 : #include "ViewShell.hxx"
25 : #include "ViewShellBase.hxx"
26 : #include "ViewShellManager.hxx"
27 : #include "Window.hxx"
28 : #include <svx/fmshell.hxx>
29 :
30 : namespace sd {
31 :
32 : namespace {
33 :
34 : /** This factory is responsible for creating and deleting the FmFormShell.
35 : */
36 0 : class FormShellManagerFactory
37 : : public ::sd::ShellFactory<SfxShell>
38 : {
39 : public:
40 : FormShellManagerFactory (ViewShell& rViewShell, FormShellManager& rManager);
41 : virtual FmFormShell* CreateShell (ShellId nId, ::Window* pParentWindow, FrameView* pFrameView) SAL_OVERRIDE;
42 : virtual void ReleaseShell (SfxShell* pShell) SAL_OVERRIDE;
43 :
44 : private:
45 : ::sd::ViewShell& mrViewShell;
46 : FormShellManager& mrFormShellManager;
47 : };
48 :
49 : } // end of anonymous namespace
50 :
51 :
52 0 : FormShellManager::FormShellManager (ViewShellBase& rBase)
53 : : mrBase(rBase),
54 : mpFormShell(NULL),
55 : mbFormShellAboveViewShell(false),
56 : mpSubShellFactory(),
57 : mbIsMainViewChangePending(false),
58 0 : mpMainViewShellWindow(NULL)
59 : {
60 : // Register at the EventMultiplexer to be informed about changes in the
61 : // center pane.
62 0 : Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
63 : mrBase.GetEventMultiplexer()->AddEventListener(
64 : aLink,
65 : sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
66 : | sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
67 0 : | sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
68 :
69 0 : RegisterAtCenterPane();
70 0 : }
71 :
72 :
73 :
74 :
75 0 : FormShellManager::~FormShellManager (void)
76 : {
77 0 : SetFormShell(NULL);
78 0 : UnregisterAtCenterPane();
79 :
80 : // Unregister from the EventMultiplexer.
81 0 : Link aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
82 0 : mrBase.GetEventMultiplexer()->RemoveEventListener(aLink);
83 :
84 0 : if (mpSubShellFactory.get() != NULL)
85 : {
86 0 : ViewShell* pShell = mrBase.GetMainViewShell().get();
87 0 : if (pShell != NULL)
88 0 : mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell,mpSubShellFactory);
89 : }
90 0 : }
91 :
92 :
93 :
94 :
95 0 : void FormShellManager::SetFormShell (FmFormShell* pFormShell)
96 : {
97 0 : if (mpFormShell != pFormShell)
98 : {
99 : // Disconnect from the old form shell.
100 0 : if (mpFormShell != NULL)
101 : {
102 0 : mpFormShell->SetControlActivationHandler(Link());
103 0 : EndListening(*mpFormShell);
104 0 : mpFormShell->SetView(NULL);
105 : }
106 :
107 0 : mpFormShell = pFormShell;
108 :
109 : // Connect to the new form shell.
110 0 : if (mpFormShell != NULL)
111 : {
112 : mpFormShell->SetControlActivationHandler(
113 : LINK(
114 : this,
115 : FormShellManager,
116 0 : FormControlActivated));
117 0 : StartListening(*mpFormShell);
118 :
119 0 : ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
120 0 : if (pMainViewShell != NULL)
121 : {
122 : // Prevent setting the view twice at the FmFormShell.
123 0 : FmFormView* pFormView = static_cast<FmFormView*>(pMainViewShell->GetView());
124 0 : if (mpFormShell->GetFormView() != pFormView)
125 0 : mpFormShell->SetView(pFormView);
126 : }
127 : }
128 :
129 : // Tell the ViewShellManager where on the stack to place the form shell.
130 : mrBase.GetViewShellManager()->SetFormShell(
131 0 : mrBase.GetMainViewShell().get(),
132 : mpFormShell,
133 0 : mbFormShellAboveViewShell);
134 : }
135 0 : }
136 :
137 :
138 :
139 :
140 0 : FmFormShell* FormShellManager::GetFormShell (void)
141 : {
142 0 : return mpFormShell;
143 : }
144 :
145 :
146 :
147 :
148 0 : void FormShellManager::RegisterAtCenterPane (void)
149 : {
150 0 : ViewShell* pShell = mrBase.GetMainViewShell().get();
151 0 : if (pShell == NULL)
152 0 : return;
153 :
154 : // No form shell for the slide sorter. Besides that it is not
155 : // necessary, using both together results in crashes.
156 0 : if (pShell->GetShellType() == ViewShell::ST_SLIDE_SORTER)
157 0 : return;
158 :
159 0 : mpMainViewShellWindow = pShell->GetActiveWindow();
160 0 : if (mpMainViewShellWindow == NULL)
161 0 : return;
162 :
163 : // Register at the window to get informed when to move the form
164 : // shell to the bottom of the shell stack.
165 : mpMainViewShellWindow->AddEventListener(
166 : LINK(
167 : this,
168 : FormShellManager,
169 0 : WindowEventHandler));
170 :
171 : // Create a shell factory and with it activate the form shell.
172 : OSL_ASSERT(mpSubShellFactory.get()==NULL);
173 0 : mpSubShellFactory.reset(new FormShellManagerFactory(*pShell, *this));
174 0 : mrBase.GetViewShellManager()->AddSubShellFactory(pShell,mpSubShellFactory);
175 0 : mrBase.GetViewShellManager()->ActivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
176 : }
177 :
178 :
179 :
180 :
181 0 : void FormShellManager::UnregisterAtCenterPane (void)
182 : {
183 0 : if (mpMainViewShellWindow != NULL)
184 : {
185 : // Unregister from the window.
186 : mpMainViewShellWindow->RemoveEventListener(
187 : LINK(
188 : this,
189 : FormShellManager,
190 0 : WindowEventHandler));
191 0 : mpMainViewShellWindow = NULL;
192 : }
193 :
194 : // Unregister form at the form shell.
195 0 : SetFormShell(NULL);
196 :
197 : // Deactivate the form shell and destroy the shell factory.
198 0 : ViewShell* pShell = mrBase.GetMainViewShell().get();
199 0 : if (pShell != NULL)
200 : {
201 0 : mrBase.GetViewShellManager()->DeactivateSubShell(*pShell, RID_FORMLAYER_TOOLBOX);
202 0 : mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell, mpSubShellFactory);
203 : }
204 :
205 0 : mpSubShellFactory.reset();
206 0 : }
207 :
208 :
209 :
210 :
211 0 : IMPL_LINK_NOARG(FormShellManager, FormControlActivated)
212 : {
213 : // The form shell has been actived. To give it priority in reacting to
214 : // slot calls the form shell is moved to the top of the object bar shell
215 : // stack.
216 0 : ViewShell* pShell = mrBase.GetMainViewShell().get();
217 0 : if (pShell!=NULL && !mbFormShellAboveViewShell)
218 : {
219 0 : mbFormShellAboveViewShell = true;
220 :
221 0 : ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
222 0 : mrBase.GetViewShellManager()->SetFormShell(pShell,mpFormShell,mbFormShellAboveViewShell);
223 : }
224 :
225 0 : return 0;
226 : }
227 :
228 :
229 :
230 :
231 0 : IMPL_LINK(FormShellManager, ConfigurationUpdateHandler, sd::tools::EventMultiplexerEvent*, pEvent)
232 : {
233 0 : switch (pEvent->meEventId)
234 : {
235 : case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
236 0 : UnregisterAtCenterPane();
237 0 : break;
238 :
239 : case sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
240 0 : mbIsMainViewChangePending = true;
241 0 : break;
242 :
243 : case sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
244 0 : if (mbIsMainViewChangePending)
245 : {
246 0 : mbIsMainViewChangePending = false;
247 0 : RegisterAtCenterPane();
248 : }
249 0 : break;
250 :
251 : default:
252 0 : break;
253 : }
254 :
255 0 : return 0;
256 : }
257 :
258 :
259 :
260 :
261 0 : IMPL_LINK(FormShellManager, WindowEventHandler, VclWindowEvent*, pEvent)
262 : {
263 0 : if (pEvent != NULL)
264 : {
265 0 : switch (pEvent->GetId())
266 : {
267 : case VCLEVENT_WINDOW_GETFOCUS:
268 : {
269 : // The window of the center pane got the focus. Therefore
270 : // the form shell is moved to the bottom of the object bar
271 : // stack.
272 0 : ViewShell* pShell = mrBase.GetMainViewShell().get();
273 0 : if (pShell!=NULL && mbFormShellAboveViewShell)
274 : {
275 0 : mbFormShellAboveViewShell = false;
276 0 : ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
277 : mrBase.GetViewShellManager()->SetFormShell(
278 : pShell,
279 : mpFormShell,
280 0 : mbFormShellAboveViewShell);
281 : }
282 : }
283 0 : break;
284 :
285 : case VCLEVENT_WINDOW_LOSEFOCUS:
286 : // We follow the sloppy focus policy. Losing the focus is
287 : // ignored. We wait for the focus to be placed either in
288 : // the window or the form shell. The later, however, is
289 : // notified over the FormControlActivated handler, not this
290 : // one.
291 0 : break;
292 :
293 : case VCLEVENT_OBJECT_DYING:
294 0 : mpMainViewShellWindow = NULL;
295 0 : break;
296 : }
297 : }
298 :
299 0 : return 0;
300 : }
301 :
302 :
303 :
304 :
305 0 : void FormShellManager::Notify(SfxBroadcaster&, const SfxHint& rHint)
306 : {
307 0 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
308 0 : if (pSimpleHint!=NULL && pSimpleHint->GetId()==SFX_HINT_DYING)
309 : {
310 : // If all goes well this listener is called after the
311 : // FormShellManager was notified about the dying form shell by the
312 : // FormShellManagerFactory.
313 : OSL_ASSERT(mpFormShell==NULL);
314 0 : if (mpFormShell != NULL)
315 : {
316 0 : mpFormShell = NULL;
317 : mrBase.GetViewShellManager()->SetFormShell(
318 0 : mrBase.GetMainViewShell().get(),
319 : NULL,
320 0 : false);
321 : }
322 : }
323 0 : }
324 :
325 :
326 :
327 :
328 :
329 : //===== FormShellManagerFactory ===============================================
330 :
331 : namespace {
332 :
333 0 : FormShellManagerFactory::FormShellManagerFactory (
334 : ::sd::ViewShell& rViewShell,
335 : FormShellManager& rManager)
336 : : mrViewShell(rViewShell),
337 0 : mrFormShellManager(rManager)
338 : {
339 0 : }
340 :
341 :
342 :
343 :
344 0 : FmFormShell* FormShellManagerFactory::CreateShell (
345 : ::sd::ShellId nId,
346 : ::Window*,
347 : ::sd::FrameView*)
348 : {
349 0 : FmFormShell* pShell = NULL;
350 :
351 0 : ::sd::View* pView = mrViewShell.GetView();
352 0 : if (nId == RID_FORMLAYER_TOOLBOX)
353 : {
354 0 : pShell = new FmFormShell(&mrViewShell.GetViewShellBase(), pView);
355 0 : mrFormShellManager.SetFormShell(pShell);
356 : }
357 :
358 0 : return pShell;
359 : }
360 :
361 :
362 :
363 :
364 0 : void FormShellManagerFactory::ReleaseShell (SfxShell* pShell)
365 : {
366 0 : if (pShell != NULL)
367 : {
368 0 : mrFormShellManager.SetFormShell(NULL);
369 0 : delete pShell;
370 : }
371 0 : }
372 :
373 : } // end of anonymous namespace
374 :
375 : } // end of namespace sd
376 :
377 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|