LibreOffice Module sd (master) 1
FormShellManager.cxx
Go to the documentation of this file.
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#include <FormShellManager.hxx>
21
22#include <EventMultiplexer.hxx>
23#include <ViewShell.hxx>
24#include <ViewShellBase.hxx>
25#include <ViewShellManager.hxx>
26#include <Window.hxx>
27#include <vcl/vclevent.hxx>
28#include <svx/fmshell.hxx>
29#include <osl/diagnose.h>
30
31namespace sd {
32
33namespace {
34
37class FormShellManagerFactory
38 : public ::sd::ShellFactory<SfxShell>
39{
40public:
41 FormShellManagerFactory (ViewShell& rViewShell, FormShellManager& rManager);
42 virtual FmFormShell* CreateShell (ShellId nId) override;
43 virtual void ReleaseShell (SfxShell* pShell) override;
44
45private:
47 FormShellManager& mrFormShellManager;
48};
49
50} // end of anonymous namespace
51
53 : mrBase(rBase),
54 mpFormShell(nullptr),
55 mbFormShellAboveViewShell(false),
56 mbIsMainViewChangePending(false),
57 mpMainViewShellWindow(nullptr)
58{
59 // Register at the EventMultiplexer to be informed about changes in the
60 // center pane.
61 Link<sd::tools::EventMultiplexerEvent&,void> aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
62 mrBase.GetEventMultiplexer()->AddEventListener(aLink);
63
65}
66
68{
69 SetFormShell(nullptr);
71
72 // Unregister from the EventMultiplexer.
73 Link<sd::tools::EventMultiplexerEvent&,void> aLink (LINK(this, FormShellManager, ConfigurationUpdateHandler));
74 mrBase.GetEventMultiplexer()->RemoveEventListener(aLink);
75
77 {
78 ViewShell* pShell = mrBase.GetMainViewShell().get();
79 if (pShell != nullptr)
80 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell,mpSubShellFactory);
81 }
82}
83
85{
87}
88
90{
91 if (mpFormShell == pFormShell)
92 return;
93
94 // Disconnect from the old form shell.
95 if (mpFormShell != nullptr)
96 {
99 mpFormShell->SetView(nullptr);
100 }
101
102 mpFormShell = pFormShell;
103
104 // Connect to the new form shell.
105 if (mpFormShell != nullptr)
106 {
108 LINK(
109 this,
111 FormControlActivated));
113
114 ViewShell* pMainViewShell = mrBase.GetMainViewShell().get();
115 if (pMainViewShell != nullptr)
116 {
117 // Prevent setting the view twice at the FmFormShell.
118 FmFormView* pFormView = pMainViewShell->GetView();
119 if (mpFormShell->GetFormView() != pFormView)
120 mpFormShell->SetView(pFormView);
121 }
122 }
123
124 // Tell the ViewShellManager where on the stack to place the form shell.
125 mrBase.GetViewShellManager()->SetFormShell(
126 mrBase.GetMainViewShell().get(),
129}
130
132{
133 ViewShell* pShell = mrBase.GetMainViewShell().get();
134 if (pShell == nullptr)
135 return;
136
137 // No form shell for the slide sorter. Besides that it is not
138 // necessary, using both together results in crashes.
140 return;
141
143 if (mpMainViewShellWindow == nullptr)
144 return;
145
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(
149 LINK(
150 this,
152 WindowEventHandler));
153
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);
159}
160
162{
163 if (mpMainViewShellWindow != nullptr)
164 {
165 // Unregister from the window.
166 mpMainViewShellWindow->RemoveEventListener(
167 LINK(
168 this,
170 WindowEventHandler));
171 mpMainViewShellWindow = nullptr;
172 }
173
174 // Unregister form at the form shell.
175 SetFormShell(nullptr);
176
177 // Deactivate the form shell and destroy the shell factory.
178 ViewShell* pShell = mrBase.GetMainViewShell().get();
179 if (pShell != nullptr)
180 {
181 mrBase.GetViewShellManager()->DeactivateSubShell(*pShell, ToolbarId::FormLayer_Toolbox);
182 mrBase.GetViewShellManager()->RemoveSubShellFactory(pShell, mpSubShellFactory);
183 }
184
185 mpSubShellFactory.reset();
186}
187
188IMPL_LINK_NOARG(FormShellManager, FormControlActivated, LinkParamNone*, void)
189{
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
192 // stack.
193 ViewShell* pShell = mrBase.GetMainViewShell().get();
194 if (pShell!=nullptr && !mbFormShellAboveViewShell)
195 {
196 mbFormShellAboveViewShell = true;
197
198 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
199 mrBase.GetViewShellManager()->SetFormShell(pShell,mpFormShell,mbFormShellAboveViewShell);
200 }
201}
202
203IMPL_LINK(FormShellManager, ConfigurationUpdateHandler, sd::tools::EventMultiplexerEvent&, rEvent, void)
204{
205 switch (rEvent.meEventId)
206 {
208 UnregisterAtCenterPane();
209 break;
210
212 mbIsMainViewChangePending = true;
213 break;
214
216 if (mbIsMainViewChangePending)
217 {
218 mbIsMainViewChangePending = false;
219 RegisterAtCenterPane();
220 }
221 break;
222
223 default:
224 break;
225 }
226}
227
228IMPL_LINK(FormShellManager, WindowEventHandler, VclWindowEvent&, rEvent, void)
229{
230 switch (rEvent.GetId())
231 {
232 case VclEventId::WindowGetFocus:
233 {
234 // The window of the center pane got the focus. Therefore
235 // the form shell is moved to the bottom of the object bar
236 // stack.
237 ViewShell* pShell = mrBase.GetMainViewShell().get();
238 if (pShell!=nullptr && mbFormShellAboveViewShell)
239 {
240 mbFormShellAboveViewShell = false;
241 ViewShellManager::UpdateLock aLock (mrBase.GetViewShellManager());
242 mrBase.GetViewShellManager()->SetFormShell(
243 pShell,
244 mpFormShell,
245 mbFormShellAboveViewShell);
246 }
247 }
248 break;
249
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
255 // one.
256 break;
257
258 case VclEventId::ObjectDying:
259 mpMainViewShellWindow = nullptr;
260 break;
261
262 default: break;
263 }
264}
265
267{
268 if (rHint.GetId()!=SfxHintId::Dying)
269 return;
270
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)
276 {
277 mpFormShell = nullptr;
278 mrBase.GetViewShellManager()->SetFormShell(
279 mrBase.GetMainViewShell().get(),
280 nullptr,
281 false);
282 }
283}
284
285//===== FormShellManagerFactory ===============================================
286
287namespace {
288
289FormShellManagerFactory::FormShellManagerFactory (
290 ::sd::ViewShell& rViewShell,
291 FormShellManager& rManager)
292 : mrViewShell(rViewShell),
293 mrFormShellManager(rManager)
294{
295}
296
297FmFormShell* FormShellManagerFactory::CreateShell( ::sd::ShellId nId )
298{
299 FmFormShell* pShell = nullptr;
300
301 ::sd::View* pView = mrViewShell.GetView();
302 if (nId == ToolbarId::FormLayer_Toolbox)
303 {
304 pShell = new FmFormShell(&mrViewShell.GetViewShellBase(), pView);
305 mrFormShellManager.SetFormShell(pShell);
306 }
307
308 return pShell;
309}
310
311void FormShellManagerFactory::ReleaseShell (SfxShell* pShell)
312{
313 if (pShell != nullptr)
314 {
315 mrFormShellManager.SetFormShell(nullptr);
316 delete pShell;
317 }
318}
319
320} // end of anonymous namespace
321
322} // end of namespace sd
323
324/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ MainViewRemoved
The current MainViewShell (the ViewShell displayed in the center pane) has been removed.
@ MainViewAdded
A new ViewShell has been made the MainViewShell.
@ ConfigurationUpdated
A configuration update has been completed.
SwViewShell & mrViewShell
FmFormView * GetFormView() const
void SetView(FmFormView *pView)
void SetControlActivationHandler(const Link< LinkParamNone *, void > &_rHdl)
SfxHintId GetId() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
This simple class is responsible for putting the form shell above or below the main view shell on the...
virtual ~FormShellManager() override
ViewShellBase & mrBase
FmFormShell * mpFormShell
Ownership of the form shell lies with the ViewShellManager.
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
This method is called by the form shell when that is destroyed.
void ImplDestroy()
dtor body
ViewShellManager::SharedShellFactory mpSubShellFactory
The factory is remembered so that it removed from the ViewShellManager when the FormShellManager is d...
void SetFormShell(FmFormShell *pFormShell)
Typically called by a ShellFactory.
void UnregisterAtCenterPane()
Unregister the listeners that were registered in RegisterAtCenterPane().
FormShellManager(ViewShellBase &rBase)
bool mbFormShellAboveViewShell
Remember whether the form shell is currently above or below the main view shell.
void RegisterAtCenterPane()
Register at window of center pane and at the form shell that represents the form tool bar.
VclPtr< vcl::Window > mpMainViewShellWindow
SfxViewShell descendant that the stacked Draw/Impress shells are based on.
std::shared_ptr< ViewShell > GetMainViewShell() const
Return the main view shell stacked on the called ViewShellBase object.
std::shared_ptr< tools::EventMultiplexer > const & GetEventMultiplexer() const
Return an event multiplexer.
std::shared_ptr< ViewShellManager > const & GetViewShellManager() const
Use this class to safely lock updates of the view shell stack.
Base class of the stacked shell hierarchy.
Definition: ViewShell.hxx:92
::sd::Window * GetActiveWindow() const
The active window is usually the mpContentWindow.
Definition: ViewShell.hxx:155
::sd::View * GetView() const
Definition: ViewShell.hxx:144
SD_DLLPUBLIC ShellType GetShellType() const
Return the type of the shell.
Definition: viewshel.cxx:1402
#define suppress_fun_call_w_exception(expr)
IMPL_LINK_NOARG(MainSequence, onTimerHdl, Timer *, void)
ToolbarId ShellId
IMPL_LINK(SdCharHeightPropertyBox, implMenuSelectHdl, const OUString &, rIdent, void)
ToolbarId