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/.
10 #include <sfx2/bindings.hxx>
11 #include <sfx2/viewsh.hxx>
12 #include <sfx2/dispatch.hxx>
13 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
14 #include <vcl/notebookbar/notebookbar.hxx>
15 #include <vcl/syswin.hxx>
16 #include <sfx2/viewfrm.hxx>
17 #include <sfx2/sfxsids.hrc>
18 #include <comphelper/processfactory.hxx>
19 #include <comphelper/lok.hxx>
20 #include <com/sun/star/frame/UnknownModuleException.hpp>
21 #include <com/sun/star/frame/XLayoutManager.hpp>
22 #include <officecfg/Office/UI/ToolbarMode.hxx>
23 #include <com/sun/star/frame/XModuleManager.hpp>
24 #include <com/sun/star/frame/ModuleManager.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <unotools/confignode.hxx>
27 #include <comphelper/types.hxx>
28 #include <framework/addonsoptions.hxx>
29 #include <vcl/notebookbar/NotebookBarAddonsMerger.hxx>
32 #include <vcl/WeldedTabbedNotebookbar.hxx>
35 using namespace css::uno
;
36 using namespace css::ui
;
39 #define MENUBAR_STR "private:resource/menubar/menubar"
41 const char MERGE_NOTEBOOKBAR_URL
[] = "URL";
43 bool SfxNotebookBar::m_bLock
= false;
44 bool SfxNotebookBar::m_bHide
= false;
45 std::map
<const SfxViewShell
*, std::shared_ptr
<WeldedTabbedNotebookbar
>> SfxNotebookBar::m_pNotebookBarWeldedWrapper
;
47 static void NotebookbarAddonValues(
48 std::vector
<Image
>& aImageValues
,
49 std::vector
<css::uno::Sequence
<css::uno::Sequence
<css::beans::PropertyValue
>>>&
52 framework::AddonsOptions aAddonsItems
;
54 for (int nIdx
= 0; nIdx
< aAddonsItems
.GetAddonsNotebookBarCount(); nIdx
++)
56 const css::uno::Sequence
<css::uno::Sequence
<css::beans::PropertyValue
>> aExtension
57 = aAddonsItems
.GetAddonsNotebookBarPart(nIdx
);
58 for (const css::uno::Sequence
<css::beans::PropertyValue
>& rExtensionVal
: aExtension
)
61 bool isBigImage
= true;
62 for (const auto& rProp
: rExtensionVal
)
64 if (rProp
.Name
== MERGE_NOTEBOOKBAR_URL
)
67 rProp
.Value
>>= sImage
;
68 aImage
= Image(framework::AddonsOptions().GetImageFromURL(sImage
, isBigImage
));
71 aImageValues
.push_back(aImage
);
73 aExtensionValues
.push_back(aExtension
);
77 static Reference
<frame::XLayoutManager
> lcl_getLayoutManager( const Reference
<frame::XFrame
>& xFrame
)
79 css::uno::Reference
<css::frame::XLayoutManager
> xLayoutManager
;
83 Reference
<css::beans::XPropertySet
> xPropSet(xFrame
, UNO_QUERY
);
87 Any aValue
= xPropSet
->getPropertyValue("LayoutManager");
88 aValue
>>= xLayoutManager
;
92 return xLayoutManager
;
95 static OUString
lcl_getAppName( vcl::EnumContext::Application eApp
)
99 case vcl::EnumContext::Application::Writer
:
101 case vcl::EnumContext::Application::Calc
:
103 case vcl::EnumContext::Application::Impress
:
105 case vcl::EnumContext::Application::Draw
:
107 case vcl::EnumContext::Application::Formula
:
114 static void lcl_setNotebookbarFileName( vcl::EnumContext::Application eApp
, const OUString
& sFileName
)
116 std::shared_ptr
<comphelper::ConfigurationChanges
> aBatch(
117 comphelper::ConfigurationChanges::create( ::comphelper::getProcessComponentContext() ) );
120 case vcl::EnumContext::Application::Writer
:
121 officecfg::Office::UI::ToolbarMode::ActiveWriter::set( sFileName
, aBatch
);
123 case vcl::EnumContext::Application::Calc
:
124 officecfg::Office::UI::ToolbarMode::ActiveCalc::set( sFileName
, aBatch
);
126 case vcl::EnumContext::Application::Impress
:
127 officecfg::Office::UI::ToolbarMode::ActiveImpress::set( sFileName
, aBatch
);
129 case vcl::EnumContext::Application::Draw
:
130 officecfg::Office::UI::ToolbarMode::ActiveDraw::set( sFileName
, aBatch
);
138 static OUString
lcl_getNotebookbarFileName( vcl::EnumContext::Application eApp
)
142 case vcl::EnumContext::Application::Writer
:
143 return officecfg::Office::UI::ToolbarMode::ActiveWriter::get();
144 case vcl::EnumContext::Application::Calc
:
145 return officecfg::Office::UI::ToolbarMode::ActiveCalc::get();
146 case vcl::EnumContext::Application::Impress
:
147 return officecfg::Office::UI::ToolbarMode::ActiveImpress::get();
148 case vcl::EnumContext::Application::Draw
:
149 return officecfg::Office::UI::ToolbarMode::ActiveDraw::get();
157 static utl::OConfigurationTreeRoot
lcl_getCurrentImplConfigRoot()
159 return utl::OConfigurationTreeRoot(::comphelper::getProcessComponentContext(),
160 "org.openoffice.Office.UI.ToolbarMode/",
164 static utl::OConfigurationNode
lcl_getCurrentImplConfigNode(const Reference
<css::frame::XFrame
>& xFrame
,
165 utl::OConfigurationTreeRoot
const & rNotebookbarNode
)
167 if (!rNotebookbarNode
.isValid())
168 return utl::OConfigurationNode();
170 const Reference
<frame::XModuleManager
> xModuleManager
= frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
172 vcl::EnumContext::Application eApp
= vcl::EnumContext::GetApplicationEnum( xModuleManager
->identify( xFrame
) );
173 OUString aActive
= lcl_getNotebookbarFileName( eApp
);
175 const utl::OConfigurationNode aImplsNode
= rNotebookbarNode
.openNode("Applications/" + lcl_getAppName( eApp
) + "/Modes");
176 const Sequence
<OUString
> aModeNodeNames( aImplsNode
.getNodeNames() );
178 for ( const auto& rModeNodeName
: aModeNodeNames
)
180 const utl::OConfigurationNode
aImplNode( aImplsNode
.openNode( rModeNodeName
) );
181 if ( !aImplNode
.isValid() )
184 OUString aCommandArg
= comphelper::getString( aImplNode
.getNodeValue( "CommandArg" ) );
186 if ( aCommandArg
== aActive
)
192 return utl::OConfigurationNode();
195 void SfxNotebookBar::CloseMethod(SfxBindings
& rBindings
)
197 SfxFrame
& rFrame
= rBindings
.GetDispatcher_Impl()->GetFrame()->GetFrame();
198 CloseMethod(rFrame
.GetSystemWindow());
201 void SfxNotebookBar::CloseMethod(SystemWindow
* pSysWindow
)
205 RemoveListeners(pSysWindow
);
206 if(pSysWindow
->GetNotebookBar())
207 pSysWindow
->CloseNotebookBar();
208 if (SfxViewFrame::Current())
209 SfxNotebookBar::ShowMenubar(SfxViewFrame::Current(), true);
213 void SfxNotebookBar::LockNotebookBar()
219 void SfxNotebookBar::UnlockNotebookBar()
225 bool SfxNotebookBar::IsActive()
230 vcl::EnumContext::Application eApp
= vcl::EnumContext::Application::Any
;
232 if (SfxViewFrame::Current())
234 const Reference
<frame::XFrame
>& xFrame
= SfxViewFrame::Current()->GetFrame().GetFrameInterface();
238 const Reference
<frame::XModuleManager
> xModuleManager
= frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
241 eApp
= vcl::EnumContext::GetApplicationEnum(xModuleManager
->identify(xFrame
));
243 catch (css::frame::UnknownModuleException
& e
)
245 SAL_WARN("sfx.appl", "SfxNotebookBar::IsActive(): " + e
.Message
);
252 OUString
appName(lcl_getAppName( eApp
));
254 if (appName
.isEmpty())
258 OUString aPath
= "org.openoffice.Office.UI.ToolbarMode/Applications/" + appName
;
260 const utl::OConfigurationTreeRoot
aAppNode(
261 ::comphelper::getProcessComponentContext(),
264 if ( !aAppNode
.isValid() )
267 OUString aActive
= comphelper::getString( aAppNode
.getNodeValue( "Active" ) );
269 if (comphelper::LibreOfficeKit::isActive() && aActive
== "notebookbar_online.ui")
272 const utl::OConfigurationNode aModesNode
= aAppNode
.openNode("Modes");
273 const Sequence
<OUString
> aModeNodeNames( aModesNode
.getNodeNames() );
275 for ( const auto& rModeNodeName
: aModeNodeNames
)
277 const utl::OConfigurationNode
aModeNode( aModesNode
.openNode( rModeNodeName
) );
278 if ( !aModeNode
.isValid() )
281 OUString aCommandArg
= comphelper::getString( aModeNode
.getNodeValue( "CommandArg" ) );
283 if ( aCommandArg
== aActive
)
285 return comphelper::getBOOL( aModeNode
.getNodeValue( "HasNotebookbar" ) );
291 void SfxNotebookBar::ExecMethod(SfxBindings
& rBindings
, const OUString
& rUIName
)
293 // Save active UI file name
294 if ( !rUIName
.isEmpty() && SfxViewFrame::Current() )
296 const Reference
<frame::XFrame
>& xFrame
= SfxViewFrame::Current()->GetFrame().GetFrameInterface();
299 const Reference
<frame::XModuleManager
> xModuleManager
= frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
300 vcl::EnumContext::Application eApp
= vcl::EnumContext::GetApplicationEnum(xModuleManager
->identify(xFrame
));
301 lcl_setNotebookbarFileName( eApp
, rUIName
);
305 // trigger the StateMethod
306 rBindings
.Invalidate(SID_NOTEBOOKBAR
);
310 bool SfxNotebookBar::StateMethod(SfxBindings
& rBindings
, std::u16string_view rUIFile
,
311 bool bReloadNotebookbar
)
313 SfxFrame
& rFrame
= rBindings
.GetDispatcher_Impl()->GetFrame()->GetFrame();
314 return StateMethod(rFrame
.GetSystemWindow(), rFrame
.GetFrameInterface(), rUIFile
,
318 bool SfxNotebookBar::StateMethod(SystemWindow
* pSysWindow
,
319 const Reference
<css::frame::XFrame
>& xFrame
,
320 std::u16string_view rUIFile
, bool bReloadNotebookbar
)
324 if (SfxViewFrame::Current() && SfxViewFrame::Current()->GetWindow().GetSystemWindow())
325 pSysWindow
= SfxViewFrame::Current()->GetWindow().GetSystemWindow();
332 css::uno::Reference
<css::uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
333 const Reference
<frame::XModuleManager
> xModuleManager
= frame::ModuleManager::create( xContext
);
334 OUString aModuleName
= xModuleManager
->identify( xFrame
);
335 vcl::EnumContext::Application eApp
= vcl::EnumContext::GetApplicationEnum( aModuleName
);
336 OUString sFile
= lcl_getNotebookbarFileName( eApp
);
337 if (comphelper::LibreOfficeKit::isActive())
338 sFile
= "notebookbar_online.ui";
339 OUString sNewFile
= rUIFile
+ sFile
;
340 OUString sCurrentFile
;
341 VclPtr
<NotebookBar
> pNotebookBar
= pSysWindow
->GetNotebookBar();
343 sCurrentFile
= pNotebookBar
->GetUIFilePath();
345 bool bChangedFile
= sNewFile
!= sCurrentFile
;
347 if ((!sFile
.isEmpty() && bChangedFile
) || !pNotebookBar
|| !pNotebookBar
->IsVisible()
348 || bReloadNotebookbar
|| comphelper::LibreOfficeKit::isActive())
350 const SfxViewShell
* pViewShell
= SfxViewShell::Current();
352 // Notebookbar was loaded too early what caused:
353 // * in LOK: Paste Special feature was incorrectly initialized
354 // Skip first request so Notebookbar will be initialized after document was loaded
355 static std::map
<const void*, bool> bSkippedFirstInit
;
356 if (comphelper::LibreOfficeKit::isActive() && bSkippedFirstInit
.find(pViewShell
) == bSkippedFirstInit
.end())
358 bSkippedFirstInit
[pViewShell
] = true;
362 RemoveListeners(pSysWindow
);
364 OUString aBuf
= rUIFile
+ sFile
;
366 //Addons For Notebookbar
367 std::vector
<Image
> aImageValues
;
368 std::vector
<css::uno::Sequence
< css::uno::Sequence
< css::beans::PropertyValue
> > > aExtensionValues
;
369 NotebookBarAddonsItem aNotebookBarAddonsItem
;
370 NotebookbarAddonValues(aImageValues
, aExtensionValues
);
371 aNotebookBarAddonsItem
.aAddonValues
= aExtensionValues
;
372 aNotebookBarAddonsItem
.aImageValues
= aImageValues
;
374 // setup if necessary
375 if (comphelper::LibreOfficeKit::isActive())
377 // update the current LOK language and locale for the dialog tunneling
378 comphelper::LibreOfficeKit::setLanguageTag(pViewShell
->GetLOKLanguageTag());
379 comphelper::LibreOfficeKit::setLocale(pViewShell
->GetLOKLocale());
382 pSysWindow
->SetNotebookBar(aBuf
, xFrame
, aNotebookBarAddonsItem
, bReloadNotebookbar
);
383 pNotebookBar
= pSysWindow
->GetNotebookBar();
384 pNotebookBar
->Show();
387 bool hasWeldedWrapper
= m_pNotebookBarWeldedWrapper
.find(pViewShell
) != m_pNotebookBarWeldedWrapper
.end();
388 if ((!hasWeldedWrapper
|| bReloadNotebookbar
) && pNotebookBar
->IsWelded())
390 sal_uInt64 nWindowId
= reinterpret_cast<sal_uInt64
>(pViewShell
);
391 m_pNotebookBarWeldedWrapper
.emplace(std::make_pair(pViewShell
,
392 new WeldedTabbedNotebookbar(pNotebookBar
->GetMainContainer(),
393 pNotebookBar
->GetUIFilePath(),
396 pNotebookBar
->SetDisposeCallback(LINK(nullptr, SfxNotebookBar
, VclDisposeHdl
), pViewShell
);
399 pNotebookBar
->GetParent()->Resize();
401 utl::OConfigurationTreeRoot
aRoot(lcl_getCurrentImplConfigRoot());
402 const utl::OConfigurationNode
aModeNode(lcl_getCurrentImplConfigNode(xFrame
, aRoot
));
403 SfxNotebookBar::ShowMenubar( comphelper::getBOOL( aModeNode
.getNodeValue( "HasMenubar" ) ) );
405 SfxViewFrame
* pView
= SfxViewFrame::Current();
409 pNotebookBar
->ControlListenerForCurrentController(true);
415 else if (auto pNotebookBar
= pSysWindow
->GetNotebookBar())
417 vcl::Window
* pParent
= pNotebookBar
->GetParent();
418 RemoveListeners(pSysWindow
);
419 pSysWindow
->CloseNotebookBar();
421 SfxNotebookBar::ShowMenubar(true);
427 void SfxNotebookBar::RemoveListeners(SystemWindow
const * pSysWindow
)
429 if (auto pNotebookBar
= pSysWindow
->GetNotebookBar())
431 pNotebookBar
->StopListeningAllControllers();
435 void SfxNotebookBar::ShowMenubar(bool bShow
)
442 Reference
<frame::XFrame
> xFrame
;
443 vcl::EnumContext::Application eCurrentApp
= vcl::EnumContext::Application::NONE
;
444 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
445 const Reference
<frame::XModuleManager
> xModuleManager
= frame::ModuleManager::create( xContext
);
447 if ( SfxViewFrame::Current() )
449 xFrame
= SfxViewFrame::Current()->GetFrame().GetFrameInterface();
450 eCurrentApp
= vcl::EnumContext::GetApplicationEnum( xModuleManager
->identify( xFrame
) );
453 SfxViewFrame
* pViewFrame
= SfxViewFrame::GetFirst();
456 xFrame
= pViewFrame
->GetFrame().GetFrameInterface();
459 vcl::EnumContext::Application eApp
=
460 vcl::EnumContext::GetApplicationEnum( xModuleManager
->identify( xFrame
) );
462 if ( eApp
== eCurrentApp
)
464 const Reference
<frame::XLayoutManager
>& xLayoutManager
=
465 lcl_getLayoutManager( xFrame
);
467 if (xLayoutManager
.is())
469 xLayoutManager
->lock();
471 if (xLayoutManager
->getElement(MENUBAR_STR
).is())
473 if (xLayoutManager
->isElementVisible(MENUBAR_STR
) && !bShow
)
474 xLayoutManager
->hideElement(MENUBAR_STR
);
475 else if(!xLayoutManager
->isElementVisible(MENUBAR_STR
) && bShow
)
476 xLayoutManager
->showElement(MENUBAR_STR
);
479 xLayoutManager
->unlock();
484 pViewFrame
= SfxViewFrame::GetNext( *pViewFrame
);
489 void SfxNotebookBar::ShowMenubar(SfxViewFrame
const * pViewFrame
, bool bShow
)
496 Reference
<frame::XFrame
> xFrame
= pViewFrame
->GetFrame().GetFrameInterface();
499 const Reference
<frame::XLayoutManager
>& xLayoutManager
= lcl_getLayoutManager(xFrame
);
500 if (xLayoutManager
.is())
502 xLayoutManager
->lock();
504 if (xLayoutManager
->getElement(MENUBAR_STR
).is())
506 if (xLayoutManager
->isElementVisible(MENUBAR_STR
) && !bShow
)
507 xLayoutManager
->hideElement(MENUBAR_STR
);
508 else if (!xLayoutManager
->isElementVisible(MENUBAR_STR
) && bShow
)
509 xLayoutManager
->showElement(MENUBAR_STR
);
512 xLayoutManager
->unlock();
518 void SfxNotebookBar::ToggleMenubar()
520 if (!SfxViewFrame::Current())
523 const Reference
<frame::XFrame
>& xFrame
= SfxViewFrame::Current()->GetFrame().GetFrameInterface();
527 const Reference
<frame::XLayoutManager
>& xLayoutManager
=
528 lcl_getLayoutManager(xFrame
);
531 if (xLayoutManager
.is() && xLayoutManager
->getElement(MENUBAR_STR
).is())
533 if (xLayoutManager
->isElementVisible(MENUBAR_STR
))
535 SfxNotebookBar::ShowMenubar(false);
539 SfxNotebookBar::ShowMenubar(true);
542 // Save menubar settings
545 utl::OConfigurationTreeRoot
aRoot(lcl_getCurrentImplConfigRoot());
546 utl::OConfigurationNode
aModeNode(lcl_getCurrentImplConfigNode(xFrame
, aRoot
));
547 aModeNode
.setNodeValue( "HasMenubar", toAny
<bool>( bShow
) );
552 void SfxNotebookBar::ReloadNotebookBar(std::u16string_view sUIPath
)
554 if (SfxNotebookBar::IsActive())
556 SfxViewShell
* pViewShell
= SfxViewShell::Current();
557 sfx2::SfxNotebookBar::StateMethod(pViewShell
->GetViewFrame()->GetBindings(), sUIPath
, true);
561 IMPL_STATIC_LINK(SfxNotebookBar
, VclDisposeHdl
, const SfxViewShell
*, pViewShell
, void)
563 m_pNotebookBarWeldedWrapper
.erase(pViewShell
);
566 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */