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 <vcl/help.hxx>
21 #include <svl/eitem.hxx>
22 #include <unotools/viewoptions.hxx>
23 #include <vcl/idle.hxx>
25 #include <sfx2/basedlgs.hxx>
26 #include <sfx2/tabdlg.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/childwin.hxx>
30 #include <sfx2/viewsh.hxx>
31 #include <workwin.hxx>
32 #include <comphelper/lok.hxx>
34 using namespace ::com::sun::star::uno
;
36 constexpr OUString USERITEM_NAME
= u
"UserItem"_ustr
;
38 class SfxModelessDialog_Impl
: public SfxListener
44 void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
) override
;
46 Idle aMoveIdle
{ "SfxModelessDialog_Impl aMoveIdle" };
49 void SfxModelessDialog_Impl::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
51 if (pMgr
&& rHint
.GetId() == SfxHintId::Dying
) {
56 void SfxModelessDialogController::Initialize(SfxChildWinInfo
const *pInfo
)
60 Initialization of the class SfxModelessDialog via a SfxChildWinInfo.
61 The initialization is done only in a 2nd step after the constructor, this
62 constructor should be called from the derived class or from the
69 m_xImpl
->aWinState
= pInfo
->aWinState
;
70 if (m_xImpl
->aWinState
.isEmpty())
72 m_xDialog
->set_window_state(m_xImpl
->aWinState
);
75 SfxModelessDialogController::SfxModelessDialogController(SfxBindings
* pBindinx
,
76 SfxChildWindow
*pCW
, weld::Window
*pParent
, const OUString
& rUIXMLDescription
,
78 : SfxDialogController(pParent
, rUIXMLDescription
, rID
)
85 Fills a SfxChildWinInfo with specific data from SfxModelessDialog,
86 so that it can be written in the INI file. It is assumed that rinfo
87 receives all other possible relevant data in the ChildWindow class.
88 ModelessDialogs have no specific information, so that the base
89 implementation does nothing and therefore must not be called.
91 void SfxModelessDialogController::FillInfo(SfxChildWinInfo
& rInfo
) const
93 rInfo
.aSize
= m_xDialog
->get_size();
96 void SfxModelessDialogController::Init(SfxBindings
*pBindinx
, SfxChildWindow
*pCW
)
98 m_pBindings
= pBindinx
;
99 m_xImpl
.reset(new SfxModelessDialog_Impl
);
101 m_xImpl
->bClosing
= false;
103 m_xImpl
->StartListening( *pBindinx
);
108 If a ModelessDialog is enabled its ViewFrame will be activated.
109 This is necessary by PluginInFrames.
111 IMPL_LINK_NOARG(SfxDialogController
, FocusChangeHdl
, weld::Container
&, void)
113 if (m_xDialog
->has_toplevel_focus())
119 void SfxModelessDialogController::Activate()
121 if (!m_xImpl
|| !m_xImpl
->pMgr
)
123 m_pBindings
->SetActiveFrame(m_xImpl
->pMgr
->GetFrame());
124 m_xImpl
->pMgr
->Activate_Impl();
127 void SfxModelessDialogController::Deactivate()
131 m_pBindings
->SetActiveFrame(css::uno::Reference
< css::frame::XFrame
>());
134 SfxModelessDialogController::~SfxModelessDialogController()
138 auto xFrame
= m_xImpl
->pMgr
->GetFrame();
141 if (xFrame
== m_pBindings
->GetActiveFrame())
142 m_pBindings
->SetActiveFrame(nullptr);
145 void SfxDialogController::EndDialog(int nResponse
)
147 if (!m_xDialog
->get_visible())
152 bool SfxModelessDialogController::IsClosing() const
154 return m_xImpl
->bClosing
;
157 void SfxModelessDialogController::EndDialog(int nResponse
)
159 if (m_xImpl
->bClosing
)
161 // In the case of async dialogs, the call to SfxDialogController::EndDialog
162 // may delete this object, so keep myself alive for the duration of this
164 auto aHoldSelf
= shared_from_this();
165 m_xImpl
->bClosing
= true;
166 SfxDialogController::EndDialog(nResponse
);
169 m_xImpl
->bClosing
= false;
172 void SfxModelessDialogController::ChildWinDispose()
176 vcl::WindowDataMask nMask
= vcl::WindowDataMask::Pos
| vcl::WindowDataMask::State
;
177 if (m_xDialog
->get_resizable())
178 nMask
|= vcl::WindowDataMask::Size
;
179 m_xImpl
->aWinState
= m_xDialog
->get_window_state(nMask
);
180 GetBindings().GetWorkWindow_Impl()->ConfigChild_Impl( SfxChildIdentifier::DOCKINGWINDOW
, SfxDockingConfig::ALIGNDOCKINGWINDOW
, m_xImpl
->pMgr
->GetType() );
183 m_xImpl
->pMgr
= nullptr;
188 The window is closed when the ChildWindow is destroyed by running the
191 void SfxModelessDialogController::Close()
193 if (m_xImpl
->bClosing
)
195 // Execute with Parameters, since Toggle is ignored by some ChildWindows.
196 SfxBoolItem
aValue(m_xImpl
->pMgr
->GetType(), false);
197 m_pBindings
->GetDispatcher_Impl()->ExecuteList(
198 m_xImpl
->pMgr
->GetType(),
199 SfxCallMode::RECORD
|SfxCallMode::SYNCHRON
, { &aValue
} );
200 SfxDialogController::Close();
203 static bool isLOKMobilePhone()
205 if (!comphelper::LibreOfficeKit::isActive())
207 const SfxViewShell
* pCurrentShell
= SfxViewShell::Current();
208 return pCurrentShell
&& pCurrentShell
->isLOKMobilePhone();
211 SfxDialogController::SfxDialogController(weld::Widget
* pParent
, const OUString
& rUIFile
,
212 const OUString
& rDialogId
)
213 : GenericDialogController(pParent
, rUIFile
, rDialogId
, isLOKMobilePhone())
215 m_xDialog
->SetInstallLOKNotifierHdl(LINK(this, SfxDialogController
, InstallLOKNotifierHdl
));
216 m_xDialog
->connect_container_focus_changed(LINK(this, SfxDialogController
, FocusChangeHdl
));
219 void SfxDialogController::Close()
221 // tdf3146571 ignore focus changes after we've closed
222 m_xDialog
->connect_container_focus_changed(Link
<weld::Container
&, void>());
225 IMPL_STATIC_LINK_NOARG(SfxDialogController
, InstallLOKNotifierHdl
, void*, vcl::ILibreOfficeKitNotifier
*)
227 return SfxViewShell::Current();
230 SfxSingleTabDialogController::SfxSingleTabDialogController(weld::Widget
*pParent
, const SfxItemSet
* pSet
,
231 const OUString
& rUIXMLDescription
, const OUString
& rID
)
232 : SfxOkDialogController(pParent
, rUIXMLDescription
, rID
)
234 , m_xContainer(m_xDialog
->weld_content_area())
235 , m_xOKBtn(m_xBuilder
->weld_button(u
"ok"_ustr
))
237 m_xOKBtn
->connect_clicked(LINK(this, SfxSingleTabDialogController
, OKHdl_Impl
));
240 SfxSingleTabDialogController::SfxSingleTabDialogController(weld::Widget
*pParent
, const SfxItemSet
* pSet
,
241 const OUString
& rContainerId
, const OUString
& rUIXMLDescription
, const OUString
& rID
)
242 : SfxOkDialogController(pParent
, rUIXMLDescription
, rID
)
244 , m_xContainer(m_xBuilder
->weld_container(rContainerId
))
245 , m_xOKBtn(m_xBuilder
->weld_button(u
"ok"_ustr
))
247 m_xOKBtn
->connect_clicked(LINK(this, SfxSingleTabDialogController
, OKHdl_Impl
));
250 SfxSingleTabDialogController::~SfxSingleTabDialogController()
256 Insert a (new) TabPage; an existing page is deleted.
257 The passed on page is initialized with the initially given Itemset
258 through calling Reset().
260 void SfxSingleTabDialogController::SetTabPage(std::unique_ptr
<SfxTabPage
> xTabPage
)
262 m_xSfxPage
= std::move(xTabPage
);
266 // First obtain the user data, only then Reset()
267 OUString sConfigId
= m_xSfxPage
->GetConfigId();
268 SvtViewOptions
aPageOpt(EViewType::TabPage
, sConfigId
);
269 Any aUserItem
= aPageOpt
.GetUserItem( USERITEM_NAME
);
271 aUserItem
>>= sUserData
;
272 m_xSfxPage
->SetUserData(sUserData
);
273 m_xSfxPage
->Reset(GetInputItemSet());
275 // Set TabPage text in the Dialog if there is any
276 OUString
sTitle(m_xSfxPage
->GetPageTitle());
277 if (!sTitle
.isEmpty())
278 m_xDialog
->set_title(sTitle
);
280 // Dialog receives the HelpId of TabPage if there is any
281 OUString
sHelpId(m_xSfxPage
->GetHelpId());
282 if (!sHelpId
.isEmpty())
283 m_xDialog
->set_help_id(sHelpId
);
288 Ok_Handler; FillItemSet() is called for setting of Page.
290 IMPL_LINK_NOARG(SfxSingleTabDialogController
, OKHdl_Impl
, weld::Button
&, void)
292 const SfxItemSet
* pInputSet
= GetInputItemSet();
295 // TabPage without ItemSet
296 m_xDialog
->response(RET_OK
);
300 if (!GetOutputItemSet())
302 CreateOutputItemSet(*pInputSet
);
305 bool bModified
= false;
307 if (m_xSfxPage
->HasExchangeSupport())
309 DeactivateRC nRet
= m_xSfxPage
->DeactivatePage(m_xOutputSet
.get());
310 if (nRet
!= DeactivateRC::LeavePage
)
313 bModified
= m_xOutputSet
->Count() > 0;
316 bModified
= m_xSfxPage
->FillItemSet(m_xOutputSet
.get());
320 // Save user data in IniManager.
321 m_xSfxPage
->FillUserData();
322 OUString
sData(m_xSfxPage
->GetUserData());
324 OUString sConfigId
= m_xSfxPage
->GetConfigId();
325 SvtViewOptions
aPageOpt(EViewType::TabPage
, sConfigId
);
326 aPageOpt
.SetUserItem( USERITEM_NAME
, Any( sData
) );
327 m_xDialog
->response(RET_OK
);
330 m_xDialog
->response(RET_CANCEL
);
333 void SfxSingleTabDialogController::CreateOutputItemSet(const SfxItemSet
& rSet
)
335 assert(!m_xOutputSet
&& "Double creation of OutputSet!");
336 m_xOutputSet
.reset(new SfxItemSet(rSet
));
337 m_xOutputSet
->ClearItem();
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */