summaryrefslogtreecommitdiffstats
path: root/sfx2/source/notebookbar
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sfx2/source/notebookbar
parentInitial commit. (diff)
downloadlibreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz
libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sfx2/source/notebookbar')
-rw-r--r--sfx2/source/notebookbar/ContextVBox.cxx76
-rw-r--r--sfx2/source/notebookbar/DropdownBox.cxx126
-rw-r--r--sfx2/source/notebookbar/DropdownBox.hxx49
-rw-r--r--sfx2/source/notebookbar/NotebookbarPopup.cxx159
-rw-r--r--sfx2/source/notebookbar/NotebookbarPopup.hxx57
-rw-r--r--sfx2/source/notebookbar/NotebookbarTabControl.cxx386
-rw-r--r--sfx2/source/notebookbar/PriorityHBox.cxx202
-rw-r--r--sfx2/source/notebookbar/PriorityHBox.hxx64
-rw-r--r--sfx2/source/notebookbar/PriorityMergedHBox.cxx113
-rw-r--r--sfx2/source/notebookbar/SfxNotebookBar.cxx550
10 files changed, 1782 insertions, 0 deletions
diff --git a/sfx2/source/notebookbar/ContextVBox.cxx b/sfx2/source/notebookbar/ContextVBox.cxx
new file mode 100644
index 000000000..b1494340f
--- /dev/null
+++ b/sfx2/source/notebookbar/ContextVBox.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <vcl/NotebookbarContextControl.hxx>
+#include <vcl/builderfactory.hxx>
+#include <vcl/layout.hxx>
+#include <sfx2/dllapi.h>
+
+/*
+ * ContextVBox is a VclVBox which shows own children depending on current context.
+ * This control can be used in the notebookbar .ui files
+ */
+
+class SFX2_DLLPUBLIC ContextVBox : public VclVBox,
+ public NotebookbarContextControl
+{
+public:
+ explicit ContextVBox( vcl::Window *pParent )
+ : VclVBox( pParent )
+ {
+ }
+
+ virtual ~ContextVBox() override
+ {
+ disposeOnce();
+ }
+
+ void SetContext( vcl::EnumContext::Context eContext ) override
+ {
+ for (int nChild = 0; nChild < GetChildCount(); ++nChild)
+ {
+ if ( GetChild( nChild )->GetType() == WindowType::CONTAINER )
+ {
+ VclContainer* pChild = static_cast<VclContainer*>( GetChild( nChild ) );
+
+ if ( pChild->HasContext( eContext ) || pChild->HasContext( vcl::EnumContext::Context::Any ) )
+ {
+ Size aSize( pChild->GetOptimalSize() );
+ aSize.AdjustHeight(6 );
+ pChild->Show();
+ pChild->SetSizePixel( aSize );
+ }
+ else
+ {
+ pChild->Hide();
+ pChild->SetSizePixel( Size( 0, 0 ) );
+ }
+ }
+ }
+ Size aSize( GetOptimalSize() );
+ aSize.AdjustWidth(6 );
+ SetSizePixel( aSize );
+ }
+};
+
+VCL_BUILDER_FACTORY(ContextVBox)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/DropdownBox.cxx b/sfx2/source/notebookbar/DropdownBox.cxx
new file mode 100644
index 000000000..450cae82a
--- /dev/null
+++ b/sfx2/source/notebookbar/DropdownBox.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/builderfactory.hxx>
+#include <vcl/button.hxx>
+#include <vcl/layout.hxx>
+#include "DropdownBox.hxx"
+
+#define NOTEBOOK_HEADER_HEIGHT 30
+
+/*
+ * DropdownBox - shows content or moves it to the popup
+ * which can be opened by clicking on a button
+ */
+
+DropdownBox::DropdownBox(vcl::Window *pParent)
+ : VclHBox(pParent)
+ , IPrioritable()
+ , m_bInFullView(true)
+{
+ m_pButton = VclPtr<PushButton>::Create(this, WB_FLATBUTTON);
+ m_pButton->SetClickHdl(LINK(this, DropdownBox, PBClickHdl));
+ m_pButton->SetSymbol(SymbolType::MENU);
+ m_pButton->set_width_request(15);
+ m_pButton->SetQuickHelpText(GetQuickHelpText());
+ m_pButton->Resize();
+}
+
+DropdownBox::~DropdownBox()
+{
+ disposeOnce();
+}
+
+void DropdownBox::dispose()
+{
+ m_pButton.disposeAndClear();
+ if (m_pPopup)
+ m_pPopup.disposeAndClear();
+
+ VclHBox::dispose();
+}
+
+void DropdownBox::HideContent()
+{
+ if (m_bInFullView)
+ {
+ m_bInFullView = false;
+
+ for (int i = 0; i < GetChildCount(); i++)
+ GetChild(i)->Hide();
+
+ m_pButton->Show();
+ SetOutputSizePixel(Size(m_pButton->GetSizePixel().Width(), GetSizePixel().Height()));
+ }
+}
+
+bool DropdownBox::IsHidden()
+{
+ return !m_bInFullView;
+}
+
+void DropdownBox::ShowContent()
+{
+ if (!m_bInFullView)
+ {
+ m_bInFullView = true;
+
+ for (int i = 0; i < GetChildCount(); i++)
+ GetChild(i)->Show();
+
+ m_pButton->Hide();
+ }
+}
+
+IMPL_LINK(DropdownBox, PBClickHdl, Button*, /*pButton*/, void)
+{
+ if (m_pPopup)
+ m_pPopup.disposeAndClear();
+
+ m_pPopup = VclPtr<NotebookbarPopup>::Create(this);
+
+ for (int i = 0; i < GetChildCount(); i++)
+ {
+ if (GetChild(i) != m_pButton)
+ {
+ Window* pChild = GetChild(i);
+ pChild->Show();
+
+ pChild->SetParent(m_pPopup->getBox());
+ // count is decreased because we moved child
+ i--;
+ }
+ }
+
+ m_pPopup->hideSeparators(true);
+
+ m_pPopup->getBox()->set_height_request(GetSizePixel().Height());
+
+ long x = GetPosPixel().getX();
+ long y = GetPosPixel().getY() + NOTEBOOK_HEADER_HEIGHT + GetSizePixel().Height();
+ tools::Rectangle aRect(x, y, x, y);
+
+ m_pPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down
+ |FloatWinPopupFlags::GrabFocus
+ |FloatWinPopupFlags::AllMouseButtonClose);
+}
+
+VCL_BUILDER_FACTORY(DropdownBox)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/DropdownBox.hxx b/sfx2/source/notebookbar/DropdownBox.hxx
new file mode 100644
index 000000000..769cd2e42
--- /dev/null
+++ b/sfx2/source/notebookbar/DropdownBox.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SFX2_NOTEBOOKBAR_DROPDOWNBOX_HXX
+#define INCLUDED_SFX2_NOTEBOOKBAR_DROPDOWNBOX_HXX
+
+#include <vcl/IPrioritable.hxx>
+#include <vcl/layout.hxx>
+#include "NotebookbarPopup.hxx"
+
+class DropdownBox : public VclHBox, public vcl::IPrioritable
+{
+private:
+ bool m_bInFullView;
+ VclPtr<PushButton> m_pButton;
+ VclPtr<NotebookbarPopup> m_pPopup;
+
+public:
+ explicit DropdownBox(vcl::Window* pParent);
+ virtual ~DropdownBox() override;
+ virtual void dispose() override;
+
+ void HideContent() override;
+ void ShowContent() override;
+ bool IsHidden() override;
+
+private:
+ DECL_LINK(PBClickHdl, Button*, void);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/NotebookbarPopup.cxx b/sfx2/source/notebookbar/NotebookbarPopup.cxx
new file mode 100644
index 000000000..cba325a43
--- /dev/null
+++ b/sfx2/source/notebookbar/NotebookbarPopup.cxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "NotebookbarPopup.hxx"
+#include <vcl/IPrioritable.hxx>
+#include <vcl/layout.hxx>
+
+NotebookbarPopup::NotebookbarPopup(const VclPtr<VclHBox>& pParent)
+ : FloatingWindow(pParent, "Popup", "sfx/ui/notebookbarpopup.ui")
+ , m_pParent(pParent)
+{
+ get(m_pBox, "box");
+ m_pBox->SetSizePixel(Size(100, 75));
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ const BitmapEx& aPersona = rStyleSettings.GetPersonaHeader();
+
+ if (!aPersona.IsEmpty())
+ m_pBox->SetBackground(Wallpaper(aPersona));
+ else
+ m_pBox->SetBackground(rStyleSettings.GetDialogColor());
+}
+
+NotebookbarPopup::~NotebookbarPopup() { disposeOnce(); }
+
+VclHBox* NotebookbarPopup::getBox() { return m_pBox.get(); }
+
+void NotebookbarPopup::PopupModeEnd()
+{
+ hideSeparators(false);
+ while (m_pBox->GetChildCount())
+ {
+ vcl::IPrioritable* pChild = dynamic_cast<vcl::IPrioritable*>(GetChild(0));
+ if (pChild)
+ pChild->HideContent();
+
+ vcl::Window* pWindow = m_pBox->GetChild(0);
+ pWindow->SetParent(m_pParent);
+
+ // resize after all children of box are empty
+ if (m_pParent && !m_pBox->GetChildCount())
+ m_pParent->Resize();
+ }
+
+ FloatingWindow::PopupModeEnd();
+}
+
+void NotebookbarPopup::hideSeparators(bool bHide)
+{
+ // separator on the beginning
+ vcl::Window* pWindow = m_pBox->GetChild(0);
+ while (pWindow && pWindow->GetType() == WindowType::CONTAINER)
+ {
+ pWindow = pWindow->GetChild(0);
+ }
+ if (pWindow && pWindow->GetType() == WindowType::FIXEDLINE)
+ {
+ if (bHide)
+ pWindow->Hide();
+ else
+ pWindow->Show();
+ }
+
+ // separator on the end
+ pWindow = m_pBox->GetChild(m_pBox->GetChildCount() - 1);
+ while (pWindow && pWindow->GetType() == WindowType::CONTAINER)
+ {
+ pWindow = pWindow->GetChild(pWindow->GetChildCount() - 1);
+ }
+ if (pWindow && pWindow->GetType() == WindowType::FIXEDLINE)
+ {
+ if (bHide)
+ pWindow->Hide();
+ else
+ pWindow->Show();
+ }
+
+ if (bHide)
+ {
+ sal_Int32 BoxId = 0;
+ while (BoxId <= m_pBox->GetChildCount() - 1)
+ {
+ if (m_pBox->GetChild(BoxId))
+ {
+ pWindow = m_pBox->GetChild(BoxId);
+ ApplyBackground(pWindow);
+ }
+ BoxId++;
+ }
+ }
+ else
+ {
+ sal_Int32 BoxId = m_pBox->GetChildCount() - 1;
+ while (BoxId >= 0)
+ {
+ if (m_pBox->GetChild(BoxId))
+ {
+ pWindow = m_pBox->GetChild(BoxId);
+ RemoveBackground(pWindow);
+ }
+ BoxId--;
+ }
+ }
+}
+
+void NotebookbarPopup::dispose()
+{
+ PopupModeEnd();
+ m_pBox.disposeAndClear();
+ m_pParent.clear();
+
+ FloatingWindow::dispose();
+}
+
+void NotebookbarPopup::ApplyBackground(vcl::Window* pWindow)
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ const BitmapEx& aPersona = rStyleSettings.GetPersonaHeader();
+
+ if (!aPersona.IsEmpty())
+ pWindow->SetBackground(Wallpaper(aPersona));
+ else
+ pWindow->SetBackground(rStyleSettings.GetDialogColor());
+
+ sal_Int32 nNext = 0;
+ VclPtr<vcl::Window> pChild = pWindow->GetChild(nNext);
+ while (pChild && pWindow->GetType() == WindowType::CONTAINER)
+ {
+ ApplyBackground(pChild);
+ nNext++;
+ if (pWindow->GetChild(nNext) && pWindow->GetType() == WindowType::CONTAINER)
+ pChild = pWindow->GetChild(nNext);
+ else
+ break;
+ }
+}
+
+void NotebookbarPopup::RemoveBackground(vcl::Window* pWindow)
+{
+ pWindow->SetBackground(Wallpaper(COL_TRANSPARENT));
+
+ sal_Int32 nNext = 0;
+ VclPtr<vcl::Window> pChild = pWindow->GetChild(nNext);
+ while (pChild && pWindow->GetType() == WindowType::CONTAINER)
+ {
+ RemoveBackground(pChild);
+ nNext++;
+ if (pWindow->GetChild(nNext) && pWindow->GetType() == WindowType::CONTAINER)
+ pChild = pWindow->GetChild(nNext);
+ else
+ break;
+ }
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/NotebookbarPopup.hxx b/sfx2/source/notebookbar/NotebookbarPopup.hxx
new file mode 100644
index 000000000..c417a75f4
--- /dev/null
+++ b/sfx2/source/notebookbar/NotebookbarPopup.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SFX2_NOTEBOOKBAR_NOTEBOOKBARPOPUP_HXX
+#define INCLUDED_SFX2_NOTEBOOKBAR_NOTEBOOKBARPOPUP_HXX
+
+#include <vcl/layout.hxx>
+#include <vcl/floatwin.hxx>
+
+/*
+ * Popup - shows hidden content, controls are moved to this popup
+ * and after close moved to the original parent
+ */
+
+class NotebookbarPopup : public FloatingWindow
+{
+private:
+ VclPtr<VclHBox> m_pBox;
+ ScopedVclPtr<VclHBox> m_pParent;
+
+public:
+ explicit NotebookbarPopup(const VclPtr<VclHBox>& pParent);
+
+ virtual ~NotebookbarPopup() override;
+
+ VclHBox* getBox();
+
+ virtual void PopupModeEnd() override;
+
+ void hideSeparators(bool bHide);
+
+ void dispose() override;
+
+ void ApplyBackground(vcl::Window* pWindow);
+
+ void RemoveBackground(vcl::Window* pWindow);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/NotebookbarTabControl.cxx b/sfx2/source/notebookbar/NotebookbarTabControl.cxx
new file mode 100644
index 000000000..79f0cd7ef
--- /dev/null
+++ b/sfx2/source/notebookbar/NotebookbarTabControl.cxx
@@ -0,0 +1,386 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/builderfactory.hxx>
+#include <vcl/button.hxx>
+#include <vcl/layout.hxx>
+#include <vcl/notebookbar.hxx>
+#include <vcl/tabpage.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <notebookbar/NotebookbarTabControl.hxx>
+#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/ItemType.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <toolkit/awt/vclxmenu.hxx>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <sfx2/sidebar/SidebarToolBox.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#define ICON_SIZE 25
+#define TOOLBAR_STR "private:resource/toolbar/notebookbarshortcuts"
+
+using namespace css::uno;
+using namespace css::ui;
+using namespace css::frame;
+
+class ChangedUIEventListener : public ::cppu::WeakImplHelper<XUIConfigurationListener>
+{
+ VclPtr<NotebookbarTabControl> m_pParent;
+
+public:
+ explicit ChangedUIEventListener(NotebookbarTabControl *p)
+ : m_pParent(p)
+ {
+ try
+ {
+ if( SfxViewFrame::Current() )
+ {
+ Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
+ const Reference<XModuleManager> xModuleManager = ModuleManager::create( xContext );
+ Reference<XFrame> xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ OUString aModuleName = xModuleManager->identify( xFrame );
+
+ Reference<XUIConfigurationManager> m_xConfigManager;
+ Reference<XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier(
+ theModuleUIConfigurationManagerSupplier::get( xContext ) );
+ m_xConfigManager.set( xModuleCfgMgrSupplier->getUIConfigurationManager( aModuleName ) );
+ css::uno::Reference< css::ui::XUIConfiguration > xConfig( m_xConfigManager, css::uno::UNO_QUERY_THROW );
+ xConfig->addConfigurationListener( this );
+ }
+ }
+ catch( const css::uno::RuntimeException& ) {}
+ }
+
+ // XUIConfigurationListener
+ virtual void SAL_CALL elementInserted( const ConfigurationEvent& rEvent ) override
+ {
+ if( rEvent.ResourceURL == TOOLBAR_STR )
+ {
+ m_pParent->m_bInvalidate = true;
+ m_pParent->StateChanged(StateChangedType::UpdateMode);
+ }
+ }
+
+ virtual void SAL_CALL elementRemoved( const ConfigurationEvent& rEvent ) override
+ {
+ elementInserted( rEvent );
+ }
+
+ virtual void SAL_CALL elementReplaced( const ConfigurationEvent& rEvent ) override
+ {
+ elementInserted( rEvent );
+ }
+
+ virtual void SAL_CALL disposing(const ::css::lang::EventObject&) override
+ {
+ try
+ {
+ if( SfxViewFrame::Current() )
+ {
+ Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
+ const Reference<XModuleManager> xModuleManager = ModuleManager::create( xContext );
+ Reference<XFrame> xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ OUString aModuleName = xModuleManager->identify( xFrame );
+
+ Reference<XUIConfigurationManager> m_xConfigManager;
+ Reference<XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier(
+ theModuleUIConfigurationManagerSupplier::get( xContext ) );
+ m_xConfigManager.set( xModuleCfgMgrSupplier->getUIConfigurationManager( aModuleName ) );
+ css::uno::Reference< css::ui::XUIConfiguration > xConfig( m_xConfigManager, css::uno::UNO_QUERY_THROW );
+ xConfig->removeConfigurationListener( this );
+ }
+ }
+ catch( const css::uno::RuntimeException& ) {}
+
+ m_pParent.clear();
+ }
+};
+
+namespace {
+
+class ShortcutsToolBox : public sfx2::sidebar::SidebarToolBox
+{
+public:
+ ShortcutsToolBox( Window* pParent )
+ : sfx2::sidebar::SidebarToolBox( pParent )
+ {
+ mbUseDefaultButtonSize = false;
+ mbSideBar = false;
+ SetToolboxButtonSize(ToolBoxButtonSize::Small);
+ }
+
+ virtual void KeyInput( const KeyEvent& rKEvt ) override
+ {
+ if ( rKEvt.GetKeyCode().IsMod1() )
+ {
+ sal_uInt16 nCode( rKEvt.GetKeyCode().GetCode() );
+ if ( nCode == KEY_RIGHT || nCode == KEY_LEFT )
+ {
+ GetParent()->KeyInput( rKEvt );
+ return;
+ }
+ }
+ return sfx2::sidebar::SidebarToolBox::KeyInput( rKEvt );
+ }
+};
+
+}
+
+NotebookbarTabControl::NotebookbarTabControl( Window* pParent )
+: NotebookbarTabControlBase( pParent )
+, m_bInitialized( false )
+, m_bInvalidate( true )
+{
+}
+
+NotebookbarTabControl::~NotebookbarTabControl()
+{
+}
+
+void NotebookbarTabControl::ArrowStops( sal_uInt16 nCode )
+{
+ ToolBox* pToolBox( GetToolBox() );
+ PushButton* pOpenMenu( GetOpenMenu() );
+
+ if ( nCode == KEY_LEFT )
+ {
+ if ( HasFocus() )
+ {
+ if ( pToolBox )
+ pToolBox->GrabFocus();
+ else if ( pOpenMenu )
+ pOpenMenu->GrabFocus();
+ }
+ else if ( pToolBox && pToolBox->HasFocus() )
+ {
+ if ( pOpenMenu )
+ pOpenMenu->GrabFocus();
+ else
+ GrabFocus();
+ }
+ else if ( pOpenMenu && pOpenMenu->HasFocus() )
+ {
+ GrabFocus();
+ }
+ }
+ else if ( nCode == KEY_RIGHT )
+ {
+ if ( HasFocus() )
+ {
+ if ( pOpenMenu )
+ pOpenMenu->GrabFocus();
+ else if ( pToolBox )
+ pToolBox->GrabFocus();
+ }
+ else if ( pToolBox && pToolBox->HasFocus() )
+ {
+ GrabFocus();
+ }
+ else if ( pOpenMenu && pOpenMenu->HasFocus() )
+ {
+ if ( pToolBox )
+ pToolBox->GrabFocus();
+ else
+ GrabFocus();
+ }
+ }
+}
+
+void NotebookbarTabControl::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( rKEvt.GetKeyCode().IsMod1() )
+ {
+ sal_uInt16 nCode( rKEvt.GetKeyCode().GetCode() );
+ if ( nCode == KEY_RIGHT || nCode == KEY_LEFT )
+ {
+ ArrowStops( nCode );
+ return;
+ }
+ }
+ return NotebookbarTabControlBase::KeyInput( rKEvt );
+}
+
+bool NotebookbarTabControl::EventNotify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
+ {
+ const vcl::KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
+ sal_uInt16 nCode = rKey.GetCode();
+ if ( rKey.IsMod1() && ( nCode == KEY_RIGHT || nCode == KEY_LEFT ) )
+ {
+ ArrowStops( nCode );
+ return true;
+ }
+ }
+ return NotebookbarTabControlBase::EventNotify( rNEvt );
+}
+
+void NotebookbarTabControl::StateChanged(StateChangedType nStateChange)
+{
+ if( !m_bInitialized && SfxViewFrame::Current() )
+ {
+ VclPtr<ShortcutsToolBox> pShortcuts = VclPtr<ShortcutsToolBox>::Create( this );
+ pShortcuts->Show();
+
+ SetToolBox( static_cast<ToolBox*>( pShortcuts.get() ) );
+ SetIconClickHdl( LINK( this, NotebookbarTabControl, OpenNotebookbarPopupMenu ) );
+
+ m_pListener = new ChangedUIEventListener( this );
+
+ m_bInitialized = true;
+ }
+ if( m_bInitialized && m_bInvalidate && SfxViewFrame::Current() )
+ {
+ ToolBox* pToolBox = GetToolBox();
+ if( !pToolBox )
+ return;
+
+ pToolBox->Clear();
+
+ Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
+ const Reference<XModuleManager> xModuleManager = ModuleManager::create( xContext );
+ m_xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ OUString aModuleName = xModuleManager->identify( m_xFrame );
+
+ FillShortcutsToolBox( xContext, m_xFrame, aModuleName, pToolBox );
+
+ Size aSize( pToolBox->GetOptimalSize() );
+ Point aPos( ICON_SIZE + 10, 0 );
+ pToolBox->SetPosSizePixel( aPos, aSize );
+ ImplPlaceTabs( GetSizePixel().getWidth() );
+
+ m_bInvalidate = false;
+ }
+ NotebookbarTabControlBase::StateChanged( nStateChange );
+}
+
+void NotebookbarTabControl::FillShortcutsToolBox(Reference<XComponentContext> const & xContext,
+ const Reference<XFrame>& xFrame,
+ const OUString& aModuleName,
+ ToolBox* pShortcuts
+)
+{
+ Reference<::com::sun::star::container::XIndexAccess> xIndex;
+
+ try
+ {
+ Reference<XUIConfigurationManager> m_xConfigManager;
+ Reference<XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier(
+ theModuleUIConfigurationManagerSupplier::get( xContext ) );
+ m_xConfigManager.set( xModuleCfgMgrSupplier->getUIConfigurationManager( aModuleName ) );
+ xIndex = m_xConfigManager->getSettings( TOOLBAR_STR, false );
+ }
+ catch( const Exception& ) {}
+
+ if ( !xIndex.is() )
+ return;
+
+ Sequence< css::beans::PropertyValue > aPropSequence;
+ for ( sal_Int32 i = 0; i < xIndex->getCount(); ++i )
+ {
+ try
+ {
+ if ( xIndex->getByIndex( i ) >>= aPropSequence )
+ {
+ OUString aCommandURL;
+ sal_uInt16 nType = ItemType::DEFAULT;
+ bool bVisible = true;
+
+ for ( const auto& aProp: std::as_const(aPropSequence) )
+ {
+ if ( aProp.Name == "CommandURL" )
+ aProp.Value >>= aCommandURL;
+ else if ( aProp.Name == "Type" )
+ aProp.Value >>= nType;
+ else if ( aProp.Name == "IsVisible" )
+ aProp.Value >>= bVisible;
+ }
+ if ( bVisible && ( nType == ItemType::DEFAULT ) )
+ pShortcuts->InsertItem( aCommandURL, xFrame, ToolBoxItemBits::ICON_ONLY, Size( ICON_SIZE, ICON_SIZE ) );
+ }
+ }
+ catch ( const Exception& )
+ {
+ break;
+ }
+ }
+}
+
+IMPL_LINK(NotebookbarTabControl, OpenNotebookbarPopupMenu, NotebookBar*, pNotebookbar, void)
+{
+ if (!pNotebookbar || !m_xFrame.is())
+ return;
+
+ Sequence<Any> aArgs {
+ makeAny(comphelper::makePropertyValue("Value", OUString("notebookbar"))),
+ makeAny(comphelper::makePropertyValue("Frame", m_xFrame)) };
+
+ Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
+ Reference<XPopupMenuController> xPopupController(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext), UNO_QUERY);
+
+ Reference<css::awt::XPopupMenu> xPopupMenu(xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.awt.PopupMenu", xContext), UNO_QUERY);
+
+ if (!xPopupController.is() || !xPopupMenu.is())
+ return;
+
+ xPopupController->setPopupMenu(xPopupMenu);
+ VCLXMenu* pAwtMenu = comphelper::getUnoTunnelImplementation<VCLXMenu>(xPopupMenu);
+ PopupMenu* pVCLMenu = static_cast<PopupMenu*>(pAwtMenu->GetMenu());
+ Point aPos(pNotebookbar->GetSizePixel().getWidth(), NotebookbarTabControl::GetHeaderHeight() - ICON_SIZE + 10);
+ pVCLMenu->Execute(pNotebookbar, tools::Rectangle(aPos, aPos),PopupMenuFlags::ExecuteDown|PopupMenuFlags::NoMouseUpClose);
+
+ Reference<css::lang::XComponent> xComponent(xPopupController, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+}
+
+Size NotebookbarTabControl::calculateRequisition() const
+{
+ Size aSize = NotebookbarTabControlBase::calculateRequisition();
+
+ for (int i = 0; i < GetPageCount(); i++)
+ {
+ vcl::Window* pChild = GetTabPage(TabControl::GetPageId(i));
+
+ if (pChild)
+ {
+ Size aChildSize = VclAlignment::getLayoutRequisition(*pChild);
+
+ if (aChildSize.getWidth() < aSize.getWidth())
+ aSize.setWidth( aChildSize.Width() );
+ }
+ }
+
+ if (aSize.Width() < 400)
+ aSize.setWidth( 400 );
+
+ return aSize;
+}
+
+VCL_BUILDER_FACTORY( NotebookbarTabControl )
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/PriorityHBox.cxx b/sfx2/source/notebookbar/PriorityHBox.cxx
new file mode 100644
index 000000000..763114c72
--- /dev/null
+++ b/sfx2/source/notebookbar/PriorityHBox.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/builderfactory.hxx>
+#include <vcl/layout.hxx>
+#include <sfx2/viewfrm.hxx>
+#include "PriorityHBox.hxx"
+
+namespace
+{
+ bool lcl_comparePriority(const vcl::IPrioritable* a, const vcl::IPrioritable* b)
+ {
+ return a->GetPriority() < b->GetPriority();
+ }
+}
+
+PriorityHBox::PriorityHBox(vcl::Window *pParent)
+ : VclHBox(pParent)
+ , m_bInitialized(false)
+{
+}
+
+PriorityHBox::~PriorityHBox()
+{
+ disposeOnce();
+}
+
+void PriorityHBox::Initialize()
+{
+ m_bInitialized = true;
+
+ GetChildrenWithPriorities();
+ SetSizeFromParent();
+}
+
+int PriorityHBox::GetHiddenCount() const
+{
+ int nCount = 0;
+
+ for (auto pWindow : m_aSortedChildren)
+ if (pWindow->IsHidden())
+ nCount++;
+
+ return nCount;
+}
+
+void PriorityHBox::SetSizeFromParent()
+{
+ vcl::Window* pParent = GetParent();
+ if (pParent)
+ {
+ Size aParentSize = pParent->GetSizePixel();
+ SetSizePixel(Size(aParentSize.getWidth(), aParentSize.getHeight()));
+ }
+}
+
+Size PriorityHBox::calculateRequisition() const
+{
+ if (!m_bInitialized)
+ {
+ return VclHBox::calculateRequisition();
+ }
+
+ sal_uInt16 nVisibleChildren = 0;
+
+ Size aSize;
+ for (vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next))
+ {
+ if (!pChild->IsVisible())
+ continue;
+ ++nVisibleChildren;
+ Size aChildSize = getLayoutRequisition(*pChild);
+
+ bool bAllwaysExpanded = true;
+
+ vcl::IPrioritable* pPrioritable = dynamic_cast<vcl::IPrioritable*>(pChild);
+ if (pPrioritable && pPrioritable->GetPriority() != VCL_PRIORITY_DEFAULT)
+ bAllwaysExpanded = false;
+
+ if (bAllwaysExpanded)
+ {
+ long nPrimaryDimension = getPrimaryDimension(aChildSize);
+ nPrimaryDimension += pChild->get_padding() * 2;
+ setPrimaryDimension(aChildSize, nPrimaryDimension);
+ }
+ else
+ setPrimaryDimension(aChildSize, 0);
+
+ accumulateMaxes(aChildSize, aSize);
+ }
+
+ return finalizeMaxes(aSize, nVisibleChildren);
+}
+
+void PriorityHBox::Resize()
+{
+ if (!m_bInitialized && SfxViewFrame::Current())
+ Initialize();
+
+ if (!m_bInitialized)
+ {
+ return VclHBox::Resize();
+ }
+
+ long nWidth = GetSizePixel().Width();
+ long nCurrentWidth = VclHBox::calculateRequisition().getWidth();
+
+ // Hide lower priority controls
+ for (vcl::IPrioritable* pPrioritable : m_aSortedChildren)
+ {
+ if (nCurrentWidth <= nWidth)
+ break;
+
+ vcl::Window* pWindow = dynamic_cast<vcl::Window*>(pPrioritable);
+
+ if (pWindow && pWindow->GetParent() == this)
+ {
+ nCurrentWidth -= pWindow->GetOutputWidthPixel() + get_spacing();
+ pWindow->Show();
+ pPrioritable->HideContent();
+ nCurrentWidth += pWindow->GetOutputWidthPixel() + get_spacing();
+ }
+ }
+
+ auto pChildR = m_aSortedChildren.rbegin();
+ // Show higher priority controls if we already have enough space
+ while (pChildR != m_aSortedChildren.rend())
+ {
+ vcl::Window* pWindow = dynamic_cast<vcl::Window*>(*pChildR);
+ vcl::IPrioritable* pPrioritable = *pChildR;
+
+ if(pWindow->GetParent() != this)
+ {
+ pChildR++;
+ continue;
+ }
+
+ if (pWindow)
+ {
+ nCurrentWidth -= pWindow->GetOutputWidthPixel() + get_spacing();
+ pWindow->Show();
+ pPrioritable->ShowContent();
+ nCurrentWidth += getLayoutRequisition(*pWindow).Width() + get_spacing();
+
+ if (nCurrentWidth > nWidth)
+ {
+ pPrioritable->HideContent();
+ break;
+ }
+ }
+
+ pChildR++;
+ }
+
+ VclHBox::Resize();
+}
+
+void PriorityHBox::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (!m_bInitialized && SfxViewFrame::Current())
+ Initialize();
+
+ VclHBox::Paint(rRenderContext, rRect);
+}
+
+void PriorityHBox::GetChildrenWithPriorities()
+{
+ for (sal_uInt16 i = 0; i < GetChildCount(); ++i)
+ {
+ vcl::Window* pChild = GetChild(i);
+
+ // Add only containers which have explicitly assigned priority.
+ vcl::IPrioritable* pPrioritable = dynamic_cast<vcl::IPrioritable*>(pChild);
+ if (pPrioritable && pPrioritable->GetPriority() != VCL_PRIORITY_DEFAULT)
+ m_aSortedChildren.push_back(pPrioritable);
+ }
+
+ if (m_aSortedChildren.empty())
+ m_bInitialized = false;
+
+ std::sort(m_aSortedChildren.begin(), m_aSortedChildren.end(), lcl_comparePriority);
+}
+
+VCL_BUILDER_FACTORY(PriorityHBox)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/PriorityHBox.hxx b/sfx2/source/notebookbar/PriorityHBox.hxx
new file mode 100644
index 000000000..04b884ddf
--- /dev/null
+++ b/sfx2/source/notebookbar/PriorityHBox.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/IPrioritable.hxx>
+#include <vcl/layout.hxx>
+
+#include <vector>
+
+#ifndef INCLUDED_SFX2_NOTEBOOKBAR_PRIORITYHBOX_HXX
+#define INCLUDED_SFX2_NOTEBOOKBAR_PRIORITYHBOX_HXX
+
+/*
+ * PriorityHBox is a VclHBox which hides its own children if there is no sufficient space.
+ * Hiding order can be modified using child's priorities. If a control have default
+ * priority assigned (VCL_PRIORITY_DEFAULT), it is always shown.
+ */
+
+class PriorityHBox : public VclHBox
+{
+private:
+ bool m_bInitialized;
+
+ std::vector<vcl::IPrioritable*> m_aSortedChildren;
+
+protected:
+ int GetHiddenCount() const;
+
+public:
+ explicit PriorityHBox(vcl::Window* pParent);
+
+ virtual ~PriorityHBox() override;
+
+ void Initialize();
+
+ void SetSizeFromParent();
+
+ virtual Size calculateRequisition() const override;
+
+ virtual void Resize() override;
+
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+ void GetChildrenWithPriorities();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/PriorityMergedHBox.cxx b/sfx2/source/notebookbar/PriorityMergedHBox.cxx
new file mode 100644
index 000000000..8a5bcd014
--- /dev/null
+++ b/sfx2/source/notebookbar/PriorityMergedHBox.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* This file incorporates work covered by the following license notice:
+*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed
+* with this work for additional information regarding copyright
+* ownership. The ASF licenses this file to you under the Apache
+* License, Version 2.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.apache.org/licenses/LICENSE-2.0 .
+*/
+
+#include <vcl/builderfactory.hxx>
+#include <vcl/button.hxx>
+#include <vcl/layout.hxx>
+#include <bitmaps.hlst>
+#include "PriorityHBox.hxx"
+#include "NotebookbarPopup.hxx"
+
+/*
+* PriorityMergedHBox is a VclHBox which hides its own children if there is no sufficient space.
+*/
+
+namespace
+{
+class PriorityMergedHBox : public PriorityHBox
+{
+private:
+ VclPtr<PushButton> m_pButton;
+ VclPtr<NotebookbarPopup> m_pPopup;
+
+ DECL_LINK(PBClickHdl, Button*, void);
+
+public:
+ explicit PriorityMergedHBox(vcl::Window* pParent)
+ : PriorityHBox(pParent)
+ {
+ m_pButton = VclPtr<PushButton>::Create(this, WB_FLATBUTTON);
+ m_pButton->SetClickHdl(LINK(this, PriorityMergedHBox, PBClickHdl));
+ m_pButton->SetModeImage(Image(StockImage::Yes, CHEVRON));
+ m_pButton->set_width_request(25);
+ m_pButton->set_pack_type(VclPackType::End);
+ m_pButton->Show();
+ }
+
+ virtual ~PriorityMergedHBox() override { disposeOnce(); }
+
+ virtual void Resize() override
+ {
+ PriorityHBox::Resize();
+ if (GetHiddenCount())
+ m_pButton->Show();
+ else
+ m_pButton->Hide();
+ }
+
+ virtual void dispose() override
+ {
+ m_pButton.disposeAndClear();
+ if (m_pPopup)
+ m_pPopup.disposeAndClear();
+ PriorityHBox::dispose();
+ }
+};
+}
+
+IMPL_LINK(PriorityMergedHBox, PBClickHdl, Button*, /*pButton*/, void)
+{
+ if (m_pPopup)
+ m_pPopup.disposeAndClear();
+
+ m_pPopup = VclPtr<NotebookbarPopup>::Create(this);
+
+ for (int i = 0; i < GetChildCount(); i++)
+ {
+ vcl::Window* pWindow = GetChild(i);
+ if (pWindow != m_pButton)
+ {
+ vcl::IPrioritable* pChild = dynamic_cast<vcl::IPrioritable*>(pWindow);
+
+ if (pChild && pChild->IsHidden())
+ {
+ pChild->ShowContent();
+ pWindow->Show();
+ pWindow->SetParent(m_pPopup->getBox());
+ // count is decreased because we moved child
+ i--;
+ }
+ }
+ }
+
+ m_pPopup->hideSeparators(true);
+
+ m_pPopup->getBox()->set_height_request(GetSizePixel().Height());
+
+ long x = m_pButton->GetPosPixel().getX();
+ long y = m_pButton->GetPosPixel().getY() + GetSizePixel().Height();
+ tools::Rectangle aRect(x, y, x, y);
+
+ m_pPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus
+ | FloatWinPopupFlags::AllMouseButtonClose);
+}
+
+VCL_BUILDER_FACTORY(PriorityMergedHBox)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/notebookbar/SfxNotebookBar.cxx b/sfx2/source/notebookbar/SfxNotebookBar.cxx
new file mode 100644
index 000000000..674caf4b0
--- /dev/null
+++ b/sfx2/source/notebookbar/SfxNotebookBar.cxx
@@ -0,0 +1,550 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/notebookbar/SfxNotebookBar.hxx>
+#include <vcl/notebookbar.hxx>
+#include <vcl/syswin.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/frame/UnknownModuleException.hpp>
+#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
+#include <com/sun/star/ui/XContextChangeEventMultiplexer.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <officecfg/Office/UI/ToolbarMode.hxx>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <unotools/confignode.hxx>
+#include <comphelper/types.hxx>
+#include <framework/addonsoptions.hxx>
+#include <vcl/NotebookBarAddonsMerger.hxx>
+#include <vector>
+using namespace sfx2;
+using namespace css::uno;
+using namespace css::ui;
+using namespace css;
+
+#define MENUBAR_STR "private:resource/menubar/menubar"
+
+static const char MERGE_NOTEBOOKBAR_URL[] = "URL";
+static const char MERGE_NOTEBOOKBAR_IMAGEID[] = "ImageIdentifier";
+
+bool SfxNotebookBar::m_bLock = false;
+bool SfxNotebookBar::m_bHide = false;
+
+static void NotebookbarAddonValues(
+ std::vector<Image>& aImageValues,
+ std::vector<css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>>>&
+ aExtensionValues)
+{
+ framework::AddonsOptions aAddonsItems;
+
+ for (int nIdx = 0; nIdx < aAddonsItems.GetAddonsNotebookBarCount(); nIdx++)
+ {
+ const css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> aExtension
+ = aAddonsItems.GetAddonsNotebookBarPart(nIdx);
+ for (const css::uno::Sequence<css::beans::PropertyValue>& rExtensionVal : aExtension)
+ {
+ Image aImage;
+ bool isBigImage = true;
+ for (const auto& rProp : rExtensionVal)
+ {
+ OUString sImage;
+ if (rProp.Name == MERGE_NOTEBOOKBAR_IMAGEID)
+ {
+ rProp.Value >>= sImage;
+ aImage = framework::AddonsOptions().GetImageFromURL(sImage, isBigImage);
+ }
+ }
+ if(!aImage)
+ {
+ for (const auto& rProp : rExtensionVal)
+ {
+ OUString sImage;
+ if (rProp.Name == MERGE_NOTEBOOKBAR_URL)
+ {
+ rProp.Value >>= sImage;
+ aImage = framework::AddonsOptions().GetImageFromURL(sImage, isBigImage);
+ }
+ }
+ }
+ aImageValues.push_back(aImage);
+ }
+ aExtensionValues.push_back(aExtension);
+ }
+}
+
+static Reference<frame::XLayoutManager> lcl_getLayoutManager( const Reference<frame::XFrame>& xFrame )
+{
+ css::uno::Reference<css::frame::XLayoutManager> xLayoutManager;
+
+ if (xFrame.is())
+ {
+ Reference<css::beans::XPropertySet> xPropSet(xFrame, UNO_QUERY);
+
+ if (xPropSet.is())
+ {
+ Any aValue = xPropSet->getPropertyValue("LayoutManager");
+ aValue >>= xLayoutManager;
+ }
+ }
+
+ return xLayoutManager;
+}
+
+static OUString lcl_getAppName( vcl::EnumContext::Application eApp )
+{
+ switch ( eApp )
+ {
+ case vcl::EnumContext::Application::Writer:
+ return "Writer";
+ break;
+ case vcl::EnumContext::Application::Calc:
+ return "Calc";
+ break;
+ case vcl::EnumContext::Application::Impress:
+ return "Impress";
+ break;
+ case vcl::EnumContext::Application::Draw:
+ return "Draw";
+ break;
+ case vcl::EnumContext::Application::Formula:
+ return "Formula";
+ break;
+ default:
+ return OUString();
+ break;
+ }
+}
+
+static void lcl_setNotebookbarFileName( vcl::EnumContext::Application eApp, const OUString& sFileName )
+{
+ std::shared_ptr<comphelper::ConfigurationChanges> aBatch(
+ comphelper::ConfigurationChanges::create( ::comphelper::getProcessComponentContext() ) );
+ switch ( eApp )
+ {
+ case vcl::EnumContext::Application::Writer:
+ officecfg::Office::UI::ToolbarMode::ActiveWriter::set( sFileName, aBatch );
+ break;
+ case vcl::EnumContext::Application::Calc:
+ officecfg::Office::UI::ToolbarMode::ActiveCalc::set( sFileName, aBatch );
+ break;
+ case vcl::EnumContext::Application::Impress:
+ officecfg::Office::UI::ToolbarMode::ActiveImpress::set( sFileName, aBatch );
+ break;
+ case vcl::EnumContext::Application::Draw:
+ officecfg::Office::UI::ToolbarMode::ActiveDraw::set( sFileName, aBatch );
+ break;
+ default:
+ break;
+ }
+ aBatch->commit();
+}
+
+static OUString lcl_getNotebookbarFileName( vcl::EnumContext::Application eApp )
+{
+ switch ( eApp )
+ {
+ case vcl::EnumContext::Application::Writer:
+ return officecfg::Office::UI::ToolbarMode::ActiveWriter::get();
+ break;
+ case vcl::EnumContext::Application::Calc:
+ return officecfg::Office::UI::ToolbarMode::ActiveCalc::get();
+ break;
+ case vcl::EnumContext::Application::Impress:
+ return officecfg::Office::UI::ToolbarMode::ActiveImpress::get();
+ break;
+ case vcl::EnumContext::Application::Draw:
+ return officecfg::Office::UI::ToolbarMode::ActiveDraw::get();
+ break;
+
+ default:
+ break;
+ }
+ return OUString();
+}
+
+static utl::OConfigurationTreeRoot lcl_getCurrentImplConfigRoot()
+{
+ return utl::OConfigurationTreeRoot(::comphelper::getProcessComponentContext(),
+ "org.openoffice.Office.UI.ToolbarMode/",
+ true);
+}
+
+static utl::OConfigurationNode lcl_getCurrentImplConfigNode(const Reference<css::frame::XFrame>& xFrame,
+ utl::OConfigurationTreeRoot const & rNotebookbarNode )
+{
+ if (!rNotebookbarNode.isValid())
+ return utl::OConfigurationNode();
+
+ const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
+
+ vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
+ OUString aActive = lcl_getNotebookbarFileName( eApp );
+
+ const utl::OConfigurationNode aImplsNode = rNotebookbarNode.openNode("Applications/" + lcl_getAppName( eApp) + "/Modes");
+ const Sequence<OUString> aModeNodeNames( aImplsNode.getNodeNames() );
+
+ for ( const auto& rModeNodeName : aModeNodeNames )
+ {
+ const utl::OConfigurationNode aImplNode( aImplsNode.openNode( rModeNodeName ) );
+ if ( !aImplNode.isValid() )
+ continue;
+
+ OUString aCommandArg = comphelper::getString( aImplNode.getNodeValue( "CommandArg" ) );
+
+ if ( aCommandArg == aActive )
+ {
+ return aImplNode;
+ }
+ }
+
+ return utl::OConfigurationNode();
+}
+
+void SfxNotebookBar::CloseMethod(SfxBindings& rBindings)
+{
+ SfxFrame& rFrame = rBindings.GetDispatcher_Impl()->GetFrame()->GetFrame();
+ CloseMethod(rFrame.GetSystemWindow());
+}
+
+void SfxNotebookBar::CloseMethod(SystemWindow* pSysWindow)
+{
+ if (pSysWindow)
+ {
+ RemoveListeners(pSysWindow);
+ if(pSysWindow->GetNotebookBar())
+ pSysWindow->CloseNotebookBar();
+ if (SfxViewFrame::Current())
+ SfxNotebookBar::ShowMenubar(SfxViewFrame::Current(), true);
+ }
+}
+
+void SfxNotebookBar::LockNotebookBar()
+{
+ m_bHide = true;
+ m_bLock = true;
+}
+
+void SfxNotebookBar::UnlockNotebookBar()
+{
+ m_bHide = false;
+ m_bLock = false;
+}
+
+bool SfxNotebookBar::IsActive()
+{
+ if (m_bHide)
+ return false;
+
+ vcl::EnumContext::Application eApp = vcl::EnumContext::Application::Any;
+
+ if (SfxViewFrame::Current())
+ {
+ const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ if (!xFrame.is())
+ return false;
+
+ const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
+ try
+ {
+ eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
+ }
+ catch (css::frame::UnknownModuleException& e)
+ {
+ SAL_WARN("sfx.appl", "SfxNotebookBar::IsActive(): " + e.Message);
+ return false;
+ }
+ }
+ else
+ return false;
+
+ OUString appName(lcl_getAppName( eApp ));
+
+ if (appName.isEmpty())
+ return false;
+
+
+ OUString aPath = "org.openoffice.Office.UI.ToolbarMode/Applications/" + appName;
+
+ const utl::OConfigurationTreeRoot aAppNode(
+ ::comphelper::getProcessComponentContext(),
+ aPath,
+ false);
+ if ( !aAppNode.isValid() )
+ return false;
+
+ OUString aActive = comphelper::getString( aAppNode.getNodeValue( "Active" ) );
+
+ const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes");
+ const Sequence<OUString> aModeNodeNames( aModesNode.getNodeNames() );
+
+ for ( const auto& rModeNodeName : aModeNodeNames )
+ {
+ const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) );
+ if ( !aModeNode.isValid() )
+ continue;
+
+ OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) );
+
+ if ( aCommandArg == aActive )
+ {
+ return comphelper::getBOOL( aModeNode.getNodeValue( "HasNotebookbar" ) );
+ }
+ }
+ return false;
+}
+
+void SfxNotebookBar::ExecMethod(SfxBindings& rBindings, const OUString& rUIName)
+{
+ // Save active UI file name
+ if ( !rUIName.isEmpty() && SfxViewFrame::Current() )
+ {
+ const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ if (xFrame.is())
+ {
+ const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
+ vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
+ lcl_setNotebookbarFileName( eApp, rUIName );
+ }
+ }
+
+ // trigger the StateMethod
+ rBindings.Invalidate(SID_NOTEBOOKBAR);
+ rBindings.Update();
+}
+
+bool SfxNotebookBar::StateMethod(SfxBindings& rBindings, const OUString& rUIFile,
+ bool bReloadNotebookbar)
+{
+ SfxFrame& rFrame = rBindings.GetDispatcher_Impl()->GetFrame()->GetFrame();
+ return StateMethod(rFrame.GetSystemWindow(), rFrame.GetFrameInterface(), rUIFile,
+ bReloadNotebookbar);
+}
+
+bool SfxNotebookBar::StateMethod(SystemWindow* pSysWindow,
+ const Reference<css::frame::XFrame>& xFrame,
+ const OUString& rUIFile, bool bReloadNotebookbar)
+{
+ if (!pSysWindow)
+ {
+ if (SfxViewFrame::Current() && SfxViewFrame::Current()->GetWindow().GetSystemWindow())
+ pSysWindow = SfxViewFrame::Current()->GetWindow().GetSystemWindow();
+ else
+ return false;
+ }
+
+ if (IsActive())
+ {
+ css::uno::Reference<css::uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
+ const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( xContext );
+ OUString aModuleName = xModuleManager->identify( xFrame );
+ vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( aModuleName );
+ OUString sFile = lcl_getNotebookbarFileName( eApp );
+ OUString sNewFile = rUIFile + sFile;
+ OUString sCurrentFile;
+ VclPtr<NotebookBar> pNotebookBar = pSysWindow->GetNotebookBar();
+ if ( pNotebookBar )
+ sCurrentFile = OStringToOUString( pNotebookBar->getUIFile(), RTL_TEXTENCODING_ASCII_US );
+
+ bool bChangedFile = true;
+ if ( sCurrentFile.getLength() && sNewFile.getLength() )
+ {
+ // delete "/"
+ sCurrentFile = sCurrentFile.copy( 0, sCurrentFile.getLength() - 1 );
+ // delete ".ui"
+ sNewFile = sNewFile.copy( 0, sNewFile.getLength() - 3 );
+
+ bChangedFile = sNewFile != sCurrentFile;
+ }
+
+ if ((!sFile.isEmpty() && bChangedFile) || !pNotebookBar || !pNotebookBar->IsVisible()
+ || bReloadNotebookbar)
+ {
+ RemoveListeners(pSysWindow);
+
+ OUString aBuf = rUIFile + sFile;
+
+ //Addons For Notebookbar
+ std::vector<Image> aImageValues;
+ std::vector<css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > > aExtensionValues;
+ NotebookBarAddonsItem aNotebookBarAddonsItem;
+ NotebookbarAddonValues(aImageValues , aExtensionValues);
+ aNotebookBarAddonsItem.aAddonValues = aExtensionValues;
+ aNotebookBarAddonsItem.aImageValues = aImageValues;
+
+ // setup if necessary
+ pSysWindow->SetNotebookBar(aBuf, xFrame, aNotebookBarAddonsItem , bReloadNotebookbar);
+ pNotebookBar = pSysWindow->GetNotebookBar();
+ pNotebookBar->Show();
+ pNotebookBar->GetParent()->Resize();
+
+ utl::OConfigurationTreeRoot aRoot(lcl_getCurrentImplConfigRoot());
+ const utl::OConfigurationNode aModeNode(lcl_getCurrentImplConfigNode(xFrame, aRoot));
+ SfxNotebookBar::ShowMenubar( comphelper::getBOOL( aModeNode.getNodeValue( "HasMenubar" ) ) );
+
+ SfxViewFrame* pView = SfxViewFrame::Current();
+
+ if(pView)
+ {
+ pNotebookBar->ControlListenerForCurrentController(true);
+ }
+ }
+
+ return true;
+ }
+ else if (auto pNotebookBar = pSysWindow->GetNotebookBar())
+ {
+ pNotebookBar->Hide();
+ pNotebookBar->GetParent()->Resize();
+ SfxNotebookBar::ShowMenubar(true);
+ }
+
+ return false;
+}
+
+void SfxNotebookBar::RemoveListeners(SystemWindow const * pSysWindow)
+{
+ if (auto pNotebookBar = pSysWindow->GetNotebookBar())
+ {
+ pNotebookBar->StopListeningAllControllers();
+ }
+}
+
+void SfxNotebookBar::ShowMenubar(bool bShow)
+{
+ if (m_bLock)
+ return;
+
+ m_bLock = true;
+
+ Reference<frame::XFrame> xFrame;
+ vcl::EnumContext::Application eCurrentApp = vcl::EnumContext::Application::NONE;
+ uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
+ const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( xContext );
+
+ if ( SfxViewFrame::Current() )
+ {
+ xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ eCurrentApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
+ }
+
+ SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst();
+ while( pViewFrame )
+ {
+ xFrame = pViewFrame->GetFrame().GetFrameInterface();
+ if ( xFrame.is() )
+ {
+ vcl::EnumContext::Application eApp =
+ vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
+
+ if ( eApp == eCurrentApp )
+ {
+ const Reference<frame::XLayoutManager>& xLayoutManager =
+ lcl_getLayoutManager( xFrame );
+
+ if (xLayoutManager.is())
+ {
+ xLayoutManager->lock();
+
+ if (xLayoutManager->getElement(MENUBAR_STR).is())
+ {
+ if (xLayoutManager->isElementVisible(MENUBAR_STR) && !bShow)
+ xLayoutManager->hideElement(MENUBAR_STR);
+ else if(!xLayoutManager->isElementVisible(MENUBAR_STR) && bShow)
+ xLayoutManager->showElement(MENUBAR_STR);
+ }
+
+ xLayoutManager->unlock();
+ }
+ }
+ }
+
+ pViewFrame = SfxViewFrame::GetNext( *pViewFrame );
+ }
+ m_bLock = false;
+}
+
+void SfxNotebookBar::ShowMenubar(SfxViewFrame const * pViewFrame, bool bShow)
+{
+ if (m_bLock)
+ return;
+
+ m_bLock = true;
+
+ Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
+ if (xFrame.is())
+ {
+ const Reference<frame::XLayoutManager>& xLayoutManager = lcl_getLayoutManager(xFrame);
+ if (xLayoutManager.is())
+ {
+ xLayoutManager->lock();
+
+ if (xLayoutManager->getElement(MENUBAR_STR).is())
+ {
+ if (xLayoutManager->isElementVisible(MENUBAR_STR) && !bShow)
+ xLayoutManager->hideElement(MENUBAR_STR);
+ else if (!xLayoutManager->isElementVisible(MENUBAR_STR) && bShow)
+ xLayoutManager->showElement(MENUBAR_STR);
+ }
+
+ xLayoutManager->unlock();
+ }
+ }
+ m_bLock = false;
+}
+
+void SfxNotebookBar::ToggleMenubar()
+{
+ if (!SfxViewFrame::Current())
+ return;
+
+ const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
+ if (!xFrame.is())
+ return;
+
+ const Reference<frame::XLayoutManager>& xLayoutManager =
+ lcl_getLayoutManager(xFrame);
+
+ bool bShow = true;
+ if (xLayoutManager.is() && xLayoutManager->getElement(MENUBAR_STR).is())
+ {
+ if (xLayoutManager->isElementVisible(MENUBAR_STR))
+ {
+ SfxNotebookBar::ShowMenubar(false);
+ bShow = false;
+ }
+ else
+ SfxNotebookBar::ShowMenubar(true);
+ }
+
+ // Save menubar settings
+ if (IsActive())
+ {
+ utl::OConfigurationTreeRoot aRoot(lcl_getCurrentImplConfigRoot());
+ utl::OConfigurationNode aModeNode(lcl_getCurrentImplConfigNode(xFrame, aRoot));
+ aModeNode.setNodeValue( "HasMenubar", toAny<bool>( bShow ) );
+ aRoot.commit();
+ }
+}
+
+void SfxNotebookBar::ReloadNotebookBar(const OUString& sUIPath)
+{
+ if (SfxNotebookBar::IsActive())
+ {
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ sfx2::SfxNotebookBar::StateMethod(pViewShell->GetViewFrame()->GetBindings(), sUIPath, true);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */