1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
27 #include <vcl/vclevent.hxx>
28 #include <svx/fmshell.hxx>
29 #include <osl/diagnose.h>
35 /** This factory is responsible for creating and deleting the FmFormShell.
37 class FormShellManagerFactory
38 : public ::sd::ShellFactory
<SfxShell
>
41 FormShellManagerFactory (ViewShell
& rViewShell
, FormShellManager
& rManager
);
42 virtual FmFormShell
* CreateShell (ShellId nId
) override
;
43 virtual void ReleaseShell (SfxShell
* pShell
) override
;
46 ::sd::ViewShell
& mrViewShell
;
47 FormShellManager
& mrFormShellManager
;
50 } // end of anonymous namespace
52 FormShellManager::FormShellManager (ViewShellBase
& rBase
)
55 mbFormShellAboveViewShell(false),
56 mbIsMainViewChangePending(false),
57 mpMainViewShellWindow(nullptr)
59 // Register at the EventMultiplexer to be informed about changes in the
61 Link
<sd::tools::EventMultiplexerEvent
&,void> aLink (LINK(this, FormShellManager
, ConfigurationUpdateHandler
));
62 mrBase
.GetEventMultiplexer()->AddEventListener(aLink
);
64 RegisterAtCenterPane();
67 void FormShellManager::ImplDestroy()
69 SetFormShell(nullptr);
70 UnregisterAtCenterPane();
72 // Unregister from the EventMultiplexer.
73 Link
<sd::tools::EventMultiplexerEvent
&,void> aLink (LINK(this, FormShellManager
, ConfigurationUpdateHandler
));
74 mrBase
.GetEventMultiplexer()->RemoveEventListener(aLink
);
76 if (mpSubShellFactory
)
78 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
79 if (pShell
!= nullptr)
80 mrBase
.GetViewShellManager()->RemoveSubShellFactory(pShell
,mpSubShellFactory
);
84 FormShellManager::~FormShellManager()
86 suppress_fun_call_w_exception(ImplDestroy());
89 void FormShellManager::SetFormShell (FmFormShell
* pFormShell
)
91 if (mpFormShell
== pFormShell
)
94 // Disconnect from the old form shell.
95 if (mpFormShell
!= nullptr)
97 mpFormShell
->SetControlActivationHandler(Link
<LinkParamNone
*,void>());
98 EndListening(*mpFormShell
);
99 mpFormShell
->SetView(nullptr);
102 mpFormShell
= pFormShell
;
104 // Connect to the new form shell.
105 if (mpFormShell
!= nullptr)
107 mpFormShell
->SetControlActivationHandler(
111 FormControlActivated
));
112 StartListening(*mpFormShell
);
114 ViewShell
* pMainViewShell
= mrBase
.GetMainViewShell().get();
115 if (pMainViewShell
!= nullptr)
117 // Prevent setting the view twice at the FmFormShell.
118 FmFormView
* pFormView
= pMainViewShell
->GetView();
119 if (mpFormShell
->GetFormView() != pFormView
)
120 mpFormShell
->SetView(pFormView
);
124 // Tell the ViewShellManager where on the stack to place the form shell.
125 mrBase
.GetViewShellManager()->SetFormShell(
126 mrBase
.GetMainViewShell().get(),
128 mbFormShellAboveViewShell
);
131 void FormShellManager::RegisterAtCenterPane()
133 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
134 if (pShell
== nullptr)
137 // No form shell for the slide sorter. Besides that it is not
138 // necessary, using both together results in crashes.
139 if (pShell
->GetShellType() == ViewShell::ST_SLIDE_SORTER
)
142 mpMainViewShellWindow
= pShell
->GetActiveWindow();
143 if (mpMainViewShellWindow
== nullptr)
146 // Register at the window to get informed when to move the form
147 // shell to the bottom of the shell stack.
148 mpMainViewShellWindow
->AddEventListener(
152 WindowEventHandler
));
154 // Create a shell factory and with it activate the form shell.
155 OSL_ASSERT(!mpSubShellFactory
);
156 mpSubShellFactory
= std::make_shared
<FormShellManagerFactory
>(*pShell
, *this);
157 mrBase
.GetViewShellManager()->AddSubShellFactory(pShell
,mpSubShellFactory
);
158 mrBase
.GetViewShellManager()->ActivateSubShell(*pShell
, ToolbarId::FormLayer_Toolbox
);
161 void FormShellManager::UnregisterAtCenterPane()
163 if (mpMainViewShellWindow
!= nullptr)
165 // Unregister from the window.
166 mpMainViewShellWindow
->RemoveEventListener(
170 WindowEventHandler
));
171 mpMainViewShellWindow
= nullptr;
174 // Unregister form at the form shell.
175 SetFormShell(nullptr);
177 // Deactivate the form shell and destroy the shell factory.
178 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
179 if (pShell
!= nullptr)
181 mrBase
.GetViewShellManager()->DeactivateSubShell(*pShell
, ToolbarId::FormLayer_Toolbox
);
182 mrBase
.GetViewShellManager()->RemoveSubShellFactory(pShell
, mpSubShellFactory
);
185 mpSubShellFactory
.reset();
188 IMPL_LINK_NOARG(FormShellManager
, FormControlActivated
, LinkParamNone
*, void)
190 // The form shell has been activated. To give it priority in reacting to
191 // slot calls the form shell is moved to the top of the object bar shell
193 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
194 if (pShell
!=nullptr && !mbFormShellAboveViewShell
)
196 mbFormShellAboveViewShell
= true;
198 ViewShellManager::UpdateLock
aLock (mrBase
.GetViewShellManager());
199 mrBase
.GetViewShellManager()->SetFormShell(pShell
,mpFormShell
,mbFormShellAboveViewShell
);
203 IMPL_LINK(FormShellManager
, ConfigurationUpdateHandler
, sd::tools::EventMultiplexerEvent
&, rEvent
, void)
205 switch (rEvent
.meEventId
)
207 case EventMultiplexerEventId::MainViewRemoved
:
208 UnregisterAtCenterPane();
211 case EventMultiplexerEventId::MainViewAdded
:
212 mbIsMainViewChangePending
= true;
215 case EventMultiplexerEventId::ConfigurationUpdated
:
216 if (mbIsMainViewChangePending
)
218 mbIsMainViewChangePending
= false;
219 RegisterAtCenterPane();
228 IMPL_LINK(FormShellManager
, WindowEventHandler
, VclWindowEvent
&, rEvent
, void)
230 switch (rEvent
.GetId())
232 case VclEventId::WindowGetFocus
:
234 // The window of the center pane got the focus. Therefore
235 // the form shell is moved to the bottom of the object bar
237 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
238 if (pShell
!=nullptr && mbFormShellAboveViewShell
)
240 mbFormShellAboveViewShell
= false;
241 ViewShellManager::UpdateLock
aLock (mrBase
.GetViewShellManager());
242 mrBase
.GetViewShellManager()->SetFormShell(
245 mbFormShellAboveViewShell
);
250 case VclEventId::WindowLoseFocus
:
251 // We follow the sloppy focus policy. Losing the focus is
252 // ignored. We wait for the focus to be placed either in
253 // the window or the form shell. The later, however, is
254 // notified over the FormControlActivated handler, not this
258 case VclEventId::ObjectDying
:
259 mpMainViewShellWindow
= nullptr;
266 void FormShellManager::Notify(SfxBroadcaster
&, const SfxHint
& rHint
)
268 if (rHint
.GetId()!=SfxHintId::Dying
)
271 // If all goes well this listener is called after the
272 // FormShellManager was notified about the dying form shell by the
273 // FormShellManagerFactory.
274 OSL_ASSERT(mpFormShell
==nullptr);
275 if (mpFormShell
!= nullptr)
277 mpFormShell
= nullptr;
278 mrBase
.GetViewShellManager()->SetFormShell(
279 mrBase
.GetMainViewShell().get(),
285 //===== FormShellManagerFactory ===============================================
289 FormShellManagerFactory::FormShellManagerFactory (
290 ::sd::ViewShell
& rViewShell
,
291 FormShellManager
& rManager
)
292 : mrViewShell(rViewShell
),
293 mrFormShellManager(rManager
)
297 FmFormShell
* FormShellManagerFactory::CreateShell( ::sd::ShellId nId
)
299 FmFormShell
* pShell
= nullptr;
301 ::sd::View
* pView
= mrViewShell
.GetView();
302 if (nId
== ToolbarId::FormLayer_Toolbox
)
304 pShell
= new FmFormShell(&mrViewShell
.GetViewShellBase(), pView
);
305 mrFormShellManager
.SetFormShell(pShell
);
311 void FormShellManagerFactory::ReleaseShell (SfxShell
* pShell
)
313 if (pShell
!= nullptr)
315 mrFormShellManager
.SetFormShell(nullptr);
320 } // end of anonymous namespace
322 } // end of namespace sd
324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */