diff options
Diffstat (limited to 'include/sfx2/sidebar')
-rw-r--r-- | include/sfx2/sidebar/AsynchronousCall.hxx | 52 | ||||
-rw-r--r-- | include/sfx2/sidebar/Context.hxx | 58 | ||||
-rw-r--r-- | include/sfx2/sidebar/ControllerItem.hxx | 79 | ||||
-rw-r--r-- | include/sfx2/sidebar/Deck.hxx | 89 | ||||
-rw-r--r-- | include/sfx2/sidebar/FocusManager.hxx | 137 | ||||
-rw-r--r-- | include/sfx2/sidebar/IContextChangeReceiver.hxx | 40 | ||||
-rw-r--r-- | include/sfx2/sidebar/ILayoutableWindow.hxx | 40 | ||||
-rw-r--r-- | include/sfx2/sidebar/Panel.hxx | 122 | ||||
-rw-r--r-- | include/sfx2/sidebar/PanelLayout.hxx | 52 | ||||
-rw-r--r-- | include/sfx2/sidebar/ResourceManager.hxx | 132 | ||||
-rw-r--r-- | include/sfx2/sidebar/Sidebar.hxx | 68 | ||||
-rw-r--r-- | include/sfx2/sidebar/SidebarChildWindow.hxx | 46 | ||||
-rw-r--r-- | include/sfx2/sidebar/SidebarController.hxx | 303 | ||||
-rw-r--r-- | include/sfx2/sidebar/SidebarDockingWindow.hxx | 66 | ||||
-rw-r--r-- | include/sfx2/sidebar/SidebarModelUpdate.hxx | 33 | ||||
-rw-r--r-- | include/sfx2/sidebar/SidebarPanelBase.hxx | 102 | ||||
-rw-r--r-- | include/sfx2/sidebar/TabBar.hxx | 138 | ||||
-rw-r--r-- | include/sfx2/sidebar/Theme.hxx | 184 |
18 files changed, 1741 insertions, 0 deletions
diff --git a/include/sfx2/sidebar/AsynchronousCall.hxx b/include/sfx2/sidebar/AsynchronousCall.hxx new file mode 100644 index 0000000000..c7e522401d --- /dev/null +++ b/include/sfx2/sidebar/AsynchronousCall.hxx @@ -0,0 +1,52 @@ +/* -*- 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 . + */ +#pragma once + +#include <tools/link.hxx> + +#include <functional> + +struct ImplSVEvent; + +namespace sfx2::sidebar +{ +/** A simple asynchronous call via Application::PostUserCall. +*/ +class AsynchronousCall +{ +public: + typedef ::std::function<void()> Action; + + AsynchronousCall(Action aAction); + ~AsynchronousCall(); + + void RequestCall(); + void CancelRequest(); + void Sync(); + +private: + Action maAction; + ImplSVEvent* mnCallId; + + DECL_LINK(HandleUserCall, void*, void); +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/Context.hxx b/include/sfx2/sidebar/Context.hxx new file mode 100644 index 0000000000..c1ea1f5e4a --- /dev/null +++ b/include/sfx2/sidebar/Context.hxx @@ -0,0 +1,58 @@ +/* -*- 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 . + */ +#pragma once + +#include <rtl/ustring.hxx> + +#include <sfx2/dllapi.h> + +namespace sfx2::sidebar +{ +class SFX2_DLLPUBLIC Context +{ +public: + OUString msApplication; + OUString msContext; + + Context(); + Context(OUString sApplication, OUString sContext); + + /** When two contexts are matched against each other, then + application or context name may have the wildcard value 'any'. + In order to prefer matches without wildcards over matches with + wildcards we introduce an integer evaluation for matches. + */ + const static sal_Int32 NoMatch; + const static sal_Int32 OptimalMatch; + const static sal_Int32 ApplicationWildcardMatch; + const static sal_Int32 ContextWildcardMatch; + + /** Return the numeric value that describes how good the match + between two contexts is. + Smaller values represent better matches. + */ + sal_Int32 EvaluateMatch(const Context& rOther) const; + + bool operator==(const Context& rOther) const; + bool operator!=(const Context& rOther) const; +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/ControllerItem.hxx b/include/sfx2/sidebar/ControllerItem.hxx new file mode 100644 index 0000000000..a8f82195a4 --- /dev/null +++ b/include/sfx2/sidebar/ControllerItem.hxx @@ -0,0 +1,79 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/ctrlitem.hxx> + +namespace com::sun::star::lang { class XComponent; } + + +namespace sfx2::sidebar { + +/** The sfx2::sidebar::ControllerItem is a wrapper around the + SfxControllerItem that becomes necessary to allow objects (think + sidebar panels) to receive state changes without having one + SfxControllerItem per supported item as base class (which is not + possible in C++ anyway). + + It also gives access to the label and icon of a slot/command. +*/ +class SFX2_DLLPUBLIC ControllerItem final + : public SfxControllerItem +{ +public: + class SFX2_DLLPUBLIC ItemUpdateReceiverInterface + { + public: + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) = 0; + virtual void GetControlState( + const sal_uInt16 nSId, + boost::property_tree::ptree& rState) = 0; + virtual ~ItemUpdateReceiverInterface(); + }; + + /** This is the simpler constructor variant that still exists for + compatibility reasons. Note that GetLabel() and GetIcon() will + return empty strings/images. + */ + ControllerItem ( + const sal_uInt16 nId, + SfxBindings &rBindings, + ItemUpdateReceiverInterface& rItemUpdateReceiver); + + virtual ~ControllerItem() override; + + /** Force the controller item to call its NotifyItemUpdate + callback with up-to-date data. + */ + void RequestUpdate(); + +private: + + virtual void StateChangedAtToolBoxControl (sal_uInt16 nSId, SfxItemState eState, const SfxPoolItem* pState) override; + virtual void GetControlState (sal_uInt16 nSId, boost::property_tree::ptree& rState) override; + + ItemUpdateReceiverInterface& mrItemUpdateReceiver; +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/Deck.hxx b/include/sfx2/sidebar/Deck.hxx new file mode 100644 index 0000000000..215d3d2156 --- /dev/null +++ b/include/sfx2/sidebar/Deck.hxx @@ -0,0 +1,89 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/sidebar/Panel.hxx> +#include <vcl/InterimItemWindow.hxx> +#include <vcl/weld.hxx> + +namespace sfx2::sidebar +{ +class DeckDescriptor; +class DeckTitleBar; +class SidebarDockingWindow; + +/** This is the parent window of the panels. + It displays the deck title. + + A deck consists of multiple panels. + E.g. Properties, Styles, Navigator. +*/ +class Deck final : public InterimItemWindow +{ +public: + Deck(const DeckDescriptor& rDeckDescriptor, SidebarDockingWindow* pParentWindow, + const std::function<void()>& rCloserAction); + virtual ~Deck() override; + virtual void dispose() override; + + const OUString& GetId() const { return msId; } + + DeckTitleBar* GetTitleBar() const; + tools::Rectangle GetContentArea() const; + void ResetPanels(SharedPanelContainer&& rPanels); + const SharedPanelContainer& GetPanels() const { return maPanels; } + + std::shared_ptr<Panel> GetPanel(std::u16string_view panelId); + + void RequestLayout(); + weld::Widget* GetPanelParentWindow(); + + /** Try to make the panel completely visible. + When the whole panel does not fit then make its top visible + and it off at the bottom. + */ + void ShowPanel(const Panel& rPanel); + + virtual void DataChanged(const DataChangedEvent& rEvent) override; + + virtual void DumpAsPropertyTree(tools::JsonWriter&) override; + + sal_Int32 GetMinimalWidth() const { return mnMinimalWidth; } + + static void LOKSendSidebarFullUpdate(); + +private: + void RequestLayoutInternal(); + +private: + const OUString msId; + sal_Int32 mnMinimalWidth; + sal_Int32 mnScrolledWindowExtraWidth; + sal_Int32 mnMinimalHeight; + SharedPanelContainer maPanels; + + VclPtr<SidebarDockingWindow> mxParentWindow; + std::unique_ptr<DeckTitleBar> mxTitleBar; + std::unique_ptr<weld::ScrolledWindow> mxVerticalScrollBar; + std::unique_ptr<weld::Box> mxContents; +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/FocusManager.hxx b/include/sfx2/sidebar/FocusManager.hxx new file mode 100644 index 0000000000..6eaa877b4d --- /dev/null +++ b/include/sfx2/sidebar/FocusManager.hxx @@ -0,0 +1,137 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/sidebar/Panel.hxx> +#include <tools/link.hxx> +#include <vcl/keycod.hxx> + +namespace weld { +class Widget; +} + +namespace sfx2::sidebar { + +class DeckTitleBar; + +/** Concentrate all focus handling in this class. + + There is one ring of windows that accept the input focus which are + cycled through with the arrow keys: + - the closer in the deck title (present only when docked) + - the panel title bars + - the tab bar items + + When the focus is in a panel title then focus travels over + - the panel title + - the panel closer + - the panel content + + Once the focus is in the panel content then focus cycles through + all controls inside the panel but not back to the title bar of + the panel. Escape places the focus back in the panel title. +*/ +class FocusManager +{ +public: + FocusManager(std::function<void(const Panel&)> aShowPanelFunctor); + ~FocusManager(); + + /** Forget all panels and buttons. Remove all window listeners. + */ + void Clear(); + + /** Transfer the focus into the sidebar tree of windows. This is + typically called from the SidebarChildWindow as result of + pressing the F6 key. + */ + void GrabFocus(); + void GrabFocusPanel(); + + void SetDeck(Deck* pDeck); + void SetPanels(const SharedPanelContainer& rPanels); + void SetButtons(const std::vector<weld::Widget*>& rButtons); + +private: + VclPtr<Deck> mxDeck; + DeckTitleBar* mpDeckTitleBar; + SharedPanelContainer maPanels; + std::vector<weld::Widget*> maButtons; + const std::function<void(const Panel&)> maShowPanelFunctor; + + enum PanelComponent + { + PC_DeckToolBox, + PC_PanelTitle, + PC_PanelToolBox, + PC_PanelContent, + PC_TabBar, + PC_None + }; + class FocusLocation + { + public: + PanelComponent meComponent; + sal_Int32 mnIndex; + FocusLocation(const PanelComponent eComponent, const sal_Int32 nIndex); + }; + + /** Listen for key events for panels and buttons. + */ + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + + void ClearPanels(); + void ClearButtons(); + + /** Let the focus manager listen for window events for the given + window. + */ + void RegisterWindow(weld::Widget& rWidget); + static void UnregisterWindow(weld::Widget& rWidget); + + void FocusDeckTitle(); + bool IsDeckTitleVisible() const; + + /** Set the focus to the title bar of the panel or, if the + title bar is not visible, directly to the panel. + @param nPanelIndex + Index of the panel to focus. + @param bFallbackToDeckTitle + When the panel title bar is not visible then The fallback + bias defines whether to focus the deck (true) or the panel + content (false) will be focused instead. + */ + void FocusPanel(const sal_Int32 nPanelIndex, + const bool bFallbackToDeckTitle); + + void FocusPanelContent(const sal_Int32 nPanelIndex); + void FocusButton(const sal_Int32 nButtonIndex); + void MoveFocusInsidePanel(const FocusLocation& rLocation, + const sal_Int32 nDirection); + + bool HandleKeyEvent(const vcl::KeyCode& rKeyCode, + const FocusLocation& rLocation); + + FocusLocation GetFocusLocation() const; + +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/IContextChangeReceiver.hxx b/include/sfx2/sidebar/IContextChangeReceiver.hxx new file mode 100644 index 0000000000..2667201444 --- /dev/null +++ b/include/sfx2/sidebar/IContextChangeReceiver.hxx @@ -0,0 +1,40 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/dllapi.h> + +namespace vcl +{ +class EnumContext; +} + +namespace sfx2::sidebar +{ +class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") IContextChangeReceiver +{ +public: + virtual ~IContextChangeReceiver(); + + virtual void HandleContextChange(const vcl::EnumContext& rContext) = 0; +}; + +} // end of namespace ::sd::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/ILayoutableWindow.hxx b/include/sfx2/sidebar/ILayoutableWindow.hxx new file mode 100644 index 0000000000..d5124a8983 --- /dev/null +++ b/include/sfx2/sidebar/ILayoutableWindow.hxx @@ -0,0 +1,40 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/dllapi.h> +#include <sal/types.h> +#include <com/sun/star/ui/LayoutSize.hpp> + +namespace sfx2::sidebar +{ +class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") ILayoutableWindow +{ +public: + virtual ~ILayoutableWindow(); + + /** Return the preferred height with the constraint, that the + window will be set to the given width. + */ + virtual css::ui::LayoutSize GetHeightForWidth(const sal_Int32 nWidth) = 0; +}; + +} // end of namespace ::sd::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/Panel.hxx b/include/sfx2/sidebar/Panel.hxx new file mode 100644 index 0000000000..c04c6a53a1 --- /dev/null +++ b/include/sfx2/sidebar/Panel.hxx @@ -0,0 +1,122 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/dllapi.h> +#include <vcl/weld.hxx> +#include <vector> + +namespace com::sun::star::frame +{ +class XFrame; +} +namespace com::sun::star::ui +{ +class XSidebarPanel; +} +namespace com::sun::star::ui +{ +class XUIElement; +} +namespace com::sun::star::awt +{ +class XWindow; +} + +namespace sfx2::sidebar +{ +class Context; +class Deck; +class PanelDescriptor; +class PanelTitleBar; + +/** + * Multiple panels form a single deck. + * E.g. the Properties deck has panels like Styles, Character, paragraph. + */ +class SFX2_DLLPUBLIC Panel final +{ +public: + Panel(const PanelDescriptor& rPanelDescriptor, weld::Widget* pParentWindow, + const bool bIsInitiallyExpanded, Deck* pDeck, std::function<Context()> aContextAccess, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + + ~Panel(); + + PanelTitleBar* GetTitleBar() const; + weld::Box* GetContents() const; + void Show(bool bShow); + bool IsTitleBarOptional() const { return mbIsTitleBarOptional; } + void SetUIElement(const css::uno::Reference<css::ui::XUIElement>& rxElement); + const css::uno::Reference<css::ui::XSidebarPanel>& GetPanelComponent() const + { + return mxPanelComponent; + } + const css::uno::Reference<css::awt::XWindow>& GetElementParentWindow(); + css::uno::Reference<css::awt::XWindow> GetElementWindow(); + void SetExpanded(const bool bIsExpanded); + bool IsExpanded() const { return mbIsExpanded; } + bool HasIdPredicate(std::u16string_view rsId) const; + const OUString& GetId() const { return msPanelId; } + const OUString& GetTitle() const { return msTitle; } + void TriggerDeckLayouting(); + + void SetHeightPixel(int nHeight); + + bool get_extents(tools::Rectangle& rExtents) const; + + /// Set whether a panel should be present but invisible / inactive + void SetLurkMode(bool bLurk); + bool IsLurking() const { return mbLurking; } + + void set_margin_top(int nMargin); + void set_margin_bottom(int nMargin); + void set_vexpand(bool bExpand); + + weld::Window* GetFrameWeld(); + + void DataChanged(); + +private: + std::unique_ptr<weld::Builder> mxBuilder; + const OUString msPanelId; + const OUString msTitle; + const bool mbIsTitleBarOptional; + const bool mbWantsAWT; + css::uno::Reference<css::ui::XUIElement> mxElement; + css::uno::Reference<css::ui::XSidebarPanel> mxPanelComponent; + bool mbIsExpanded; + bool mbLurking; + const std::function<Context()> maContextAccess; + const css::uno::Reference<css::frame::XFrame>& mxFrame; + weld::Widget* mpParentWindow; + VclPtr<Deck> mxDeck; + std::unique_ptr<weld::Box> mxContainer; + std::unique_ptr<PanelTitleBar> mxTitleBar; + std::unique_ptr<weld::Box> mxContents; + css::uno::Reference<css::awt::XWindow> mxXWindow; + + DECL_DLLPRIVATE_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); +}; + +typedef std::vector<std::shared_ptr<Panel>> SharedPanelContainer; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/PanelLayout.hxx b/include/sfx2/sidebar/PanelLayout.hxx new file mode 100644 index 0000000000..3058c9d514 --- /dev/null +++ b/include/sfx2/sidebar/PanelLayout.hxx @@ -0,0 +1,52 @@ +/* -*- 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/. + */ + +#pragma once + +#include <sfx2/dllapi.h> +#include <vcl/weld.hxx> + +class DataChangedEvent; +class VclSimpleEvent; +namespace sfx2 { namespace sidebar { class Panel; } } +namespace tools { class JsonWriter; } + +/// This class is the base for the Widget Layout-based sidebar panels. +class SFX2_DLLPUBLIC PanelLayout +{ +protected: + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + sfx2::sidebar::Panel* m_pPanel; + + virtual void DataChanged(const DataChangedEvent& rEvent); + virtual void DumpAsPropertyTree(tools::JsonWriter&); + + virtual weld::Window* GetFrameWeld() const; + +private: + DECL_DLLPRIVATE_LINK(DataChangedEventListener, VclSimpleEvent&, void); + DECL_DLLPRIVATE_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void); + +public: + PanelLayout(weld::Widget* pParent, const OUString& rID, const OUString& rUIXMLDescription); + + void SetPanel(sfx2::sidebar::Panel* pPanel); + + virtual ~PanelLayout(); + + Size get_preferred_size() const + { + return m_xContainer->get_preferred_size(); + } + + void queue_resize(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/ResourceManager.hxx b/include/sfx2/sidebar/ResourceManager.hxx new file mode 100644 index 0000000000..9ac1130cc2 --- /dev/null +++ b/include/sfx2/sidebar/ResourceManager.hxx @@ -0,0 +1,132 @@ +/* -*- 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 . + */ +#pragma once + +#include <unotools/confignode.hxx> +#include <map> +#include <vector> +#include <set> + +#include <sfx2/dllapi.h> + +namespace com::sun::star::frame { class XController; } +namespace com::sun::star::frame { class XModel; } +namespace sfx2::sidebar { class DeckDescriptor; } +namespace sfx2::sidebar { class PanelDescriptor; } + +namespace sfx2::sidebar { + +class Context; +class ContextList; + +/** Read the content of the Sidebar.xcu file and provide access + methods so that the sidebar can easily decide which content panels + to display for a certain context. +*/ +class SFX2_DLLPUBLIC ResourceManager +{ +public: + + ResourceManager(); + ~ResourceManager(); + + std::shared_ptr<DeckDescriptor> GetDeckDescriptor(std::u16string_view rsDeckId) const; + std::shared_ptr<PanelDescriptor> GetPanelDescriptor(std::u16string_view rsPanelId) const; + + void UpdateModel(const css::uno::Reference<css::frame::XModel>& xModel); + + void InitDeckContext(const Context& rContex); + void SaveDecksSettings(const Context& rContext); + void SaveDeckSettings(const DeckDescriptor* pDeckDesc); + void SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck); + + void disposeDecks(); + + class DeckContextDescriptor + { + public: + OUString msId; + bool mbIsEnabled; + }; + typedef std::vector<DeckContextDescriptor> DeckContextDescriptorContainer; + + class PanelContextDescriptor + { + public: + OUString msId; + OUString msMenuCommand; + bool mbIsInitiallyVisible; + bool mbShowForReadOnlyDocuments; + }; + typedef std::vector<PanelContextDescriptor> PanelContextDescriptorContainer; + + const DeckContextDescriptorContainer& GetMatchingDecks( + DeckContextDescriptorContainer& rDeckDescriptors, + const Context& rContext, + const bool bIsDocumentReadOnly, + const css::uno::Reference<css::frame::XController>& rxController); + + const PanelContextDescriptorContainer& GetMatchingPanels( + PanelContextDescriptorContainer& rPanelDescriptors, + const Context& rContext, + std::u16string_view rsDeckId, + const css::uno::Reference<css::frame::XController>& rxController); + + const OUString& GetLastActiveDeck( const Context& rContext ); + void SetLastActiveDeck( const Context& rContext, const OUString& rsDeckId ); + + /** Remember the expansions state per panel and context. + */ + void StorePanelExpansionState(std::u16string_view rsPanelId, + const bool bExpansionState, + const Context& rContext); + +private: + + + typedef std::vector<std::shared_ptr<DeckDescriptor>> DeckContainer; + DeckContainer maDecks; + + typedef std::vector<std::shared_ptr<PanelDescriptor>> PanelContainer; + PanelContainer maPanels; + mutable std::set<OUString> maProcessedApplications; + std::map<OUString, OUString> maLastActiveDecks; + + void ReadDeckList(); + void ReadPanelList(); + void ReadLastActive(); + static void ReadContextList(const utl::OConfigurationNode& rNode, + ContextList& rContextList, + const OUString& rsDefaultMenuCommand); + + void ReadLegacyAddons(const css::uno::Reference<css::frame::XController>& rxController); + static utl::OConfigurationTreeRoot GetLegacyAddonRootNode(const OUString& rsModuleName); + static void GetToolPanelNodeNames(std::vector<OUString>& rMatchingNames, + const utl::OConfigurationTreeRoot& aRoot); + bool IsDeckEnabled(std::u16string_view rsDeckId, + const Context& rContext, + const css::uno::Reference<css::frame::XController>& rxController); + + std::shared_ptr<DeckDescriptor> ImplGetDeckDescriptor(std::u16string_view rsDeckId) const; + std::shared_ptr<PanelDescriptor> ImplGetPanelDescriptor(std::u16string_view rsPanelId) const; +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/Sidebar.hxx b/include/sfx2/sidebar/Sidebar.hxx new file mode 100644 index 0000000000..f4d0c1cc9b --- /dev/null +++ b/include/sfx2/sidebar/Sidebar.hxx @@ -0,0 +1,68 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sfx2/dllapi.h> +#include <sfx2/viewfrm.hxx> + +#include <string_view> + +namespace com::sun::star::frame { class XFrame; } +namespace com::sun::star::uno { template <typename > class Reference; } + + +namespace sfx2::sidebar { + +/** Accept requests for switching to certain panels or decks. +*/ +class SFX2_DLLPUBLIC Sidebar +{ +public: + static void ShowDeck(std::u16string_view rsDeckId, SfxViewFrame* pViewFrame, + bool bToggle); + + /** Switch to the deck that contains the specified panel and make + sure that the panel is visible (expanded and scrolled into the + visible area.) + Note that most of the work is done asynchronously and that + this function probably returns before the requested panel is visible. + */ + static void ShowPanel ( + std::u16string_view rsPanelId, + const css::uno::Reference<css::frame::XFrame>& rxFrame, bool bFocus = false); + + /** Switch to the deck that contains the specified panel and toggle + the visibility of the panel (expanded and scrolled into the + visible area when visible) + Note that most of the work is done asynchronously and that + this function probably returns before the requested panel is visible. + */ + static void TogglePanel ( + std::u16string_view rsPanelId, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + + static bool IsPanelVisible( + std::u16string_view rsPanelId, + const css::uno::Reference<css::frame::XFrame>& rxFrame); +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/SidebarChildWindow.hxx b/include/sfx2/sidebar/SidebarChildWindow.hxx new file mode 100644 index 0000000000..279aa79b5f --- /dev/null +++ b/include/sfx2/sidebar/SidebarChildWindow.hxx @@ -0,0 +1,46 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/childwin.hxx> + + +namespace sfx2::sidebar { + +/** Outer container of the sidebar window. + + Has to be registered for every application via the + RegisterChildWindow() method from the RegisterControllers() method + of the applications DLL. +*/ +class SFX2_DLLPUBLIC SidebarChildWindow final : public SfxChildWindow +{ +public: + SidebarChildWindow(vcl::Window* pParent, sal_uInt16 nId, + SfxBindings* pBindings, SfxChildWinInfo* pInfo); + + SFX_DECL_CHILDWINDOW_WITHID(SidebarChildWindow); + + static sal_Int32 GetDefaultWidth(vcl::Window const * pWindow); +}; + + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/SidebarController.hxx b/include/sfx2/sidebar/SidebarController.hxx new file mode 100644 index 0000000000..06e092bcee --- /dev/null +++ b/include/sfx2/sidebar/SidebarController.hxx @@ -0,0 +1,303 @@ +/* -*- 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 . + */ +#pragma once + +#include <memory> +#include <sal/config.h> + +#include <sfx2/sidebar/AsynchronousCall.hxx> +#include <sfx2/sidebar/Context.hxx> +#include <sfx2/sidebar/Deck.hxx> +#include <sfx2/sidebar/FocusManager.hxx> +#include <sfx2/sidebar/ResourceManager.hxx> +#include <sfx2/sidebar/TabBar.hxx> +#include <sfx2/viewfrm.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> +#include <com/sun/star/frame/XFrameActionListener.hpp> +#include <com/sun/star/ui/XContextChangeEventListener.hpp> +#include <com/sun/star/ui/XSidebar.hpp> + +#include <optional> +#include <comphelper/compbase.hxx> + +namespace com::sun::star::awt { class XWindow; } +namespace com::sun::star::frame { class XDispatch; } +namespace com::sun::star::ui { class XUIElement; } + +typedef comphelper::WeakComponentImplHelper < + css::ui::XContextChangeEventListener, + css::beans::XPropertyChangeListener, + css::ui::XSidebar, + css::frame::XStatusListener, + css::frame::XFrameActionListener + > SidebarControllerInterfaceBase; + +class SfxSplitWindow; +class SfxViewShell; + +namespace sfx2::sidebar { + +class DeckDescriptor; +class SidebarDockingWindow; + +class SFX2_DLLPUBLIC SidebarController final + : public SidebarControllerInterfaceBase +{ +public: + static rtl::Reference<SidebarController> create(SidebarDockingWindow* pParentWindow, + const SfxViewFrame* pViewFrame); + virtual ~SidebarController() override; + SidebarController(const SidebarController&) = delete; + SidebarController& operator=( const SidebarController& ) = delete; + + /** Return the SidebarController object that is associated with + the given XFrame. + @return + When there is no SidebarController object for the given + XFrame then <NULL/> is returned. + */ + static SidebarController* GetSidebarControllerForFrame ( + const css::uno::Reference<css::frame::XFrame>& rxFrame); + + void registerSidebarForFrame(const css::uno::Reference<css::frame::XController>& xFrame); + + void unregisterSidebarForFrame(const css::uno::Reference<css::frame::XController>& xFrame); + + // ui::XContextChangeEventListener + virtual void SAL_CALL notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent) override; + + // XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEventObject) override; + + // beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange (const css::beans::PropertyChangeEvent& rEvent) override; + + // frame::XStatusListener + virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent) override; + + // frame::XFrameActionListener + virtual void SAL_CALL frameAction (const css::frame::FrameActionEvent& rEvent) override; + + // ui::XSidebar + virtual void SAL_CALL requestLayout() override; + + void NotifyResize(); + + /** In some situations it is necessary to force an update of the + current deck and its panels. One reason is a change of the + view scale. Some panels can handle this only when + constructed. In this case we have to a context change and + also force that all panels are destroyed and created new. + */ + const static sal_Int32 SwitchFlag_NoForce = 0x00; + const static sal_Int32 SwitchFlag_ForceSwitch = 0x01; + const static sal_Int32 SwitchFlag_ForceNewDeck = 0x02; + const static sal_Int32 SwitchFlag_ForceNewPanels = 0x02; + + void OpenThenSwitchToDeck(std::u16string_view rsDeckId); + void OpenThenToggleDeck(const OUString& rsDeckId); + + /** Show only the tab bar, not the deck. + */ + void RequestCloseDeck(); + + /** Open the deck area and restore the parent window to its old width. + */ + void RequestOpenDeck(); + + /** Returns true when the given deck is the currently visible deck + */ + bool IsDeckVisible(std::u16string_view rsDeckId); + + bool IsDeckOpen(const sal_Int32 nIndex = -1); + + FocusManager& GetFocusManager() { return maFocusManager;} + + ResourceManager* GetResourceManager() { return mpResourceManager.get();} + + // std::unique_ptr<ResourceManager> GetResourceManager() { return mpResourceManager;} + + const Context& GetCurrentContext() const { return maCurrentContext;} + bool IsDocumentReadOnly (void) const { return mbIsDocumentReadOnly;} + + void SwitchToDeck(std::u16string_view rsDeckId); + void SwitchToDefaultDeck(); + bool WasFloatingDeckClosed() const { return mbFloatingDeckClosed; } + void SetFloatingDeckClosed(bool bWasClosed) { mbFloatingDeckClosed = bWasClosed; } + + void CreateDeck(std::u16string_view rDeckId); + void CreateDeck(std::u16string_view rDeckId, const Context& rContext, bool bForceCreate = false); + + ResourceManager::DeckContextDescriptorContainer GetMatchingDecks(); + ResourceManager::PanelContextDescriptorContainer GetMatchingPanels(std::u16string_view rDeckId); + + void notifyDeckTitle(std::u16string_view targetDeckId); + + void updateModel(const css::uno::Reference<css::frame::XModel>& xModel); + + void disposeDecks(); + + void FadeIn(); + void FadeOut(); + + tools::Rectangle GetDeckDragArea() const; + + css::uno::Reference<css::frame::XFrame> const & getXFrame() const {return mxFrame;} + + sal_Int32 getMaximumWidth() const { return mnMaximumSidebarWidth; } + void setMaximumWidth(sal_Int32 nMaximumWidth) { mnMaximumSidebarWidth = nMaximumWidth; } + + void saveDeckState(); + + void SyncUpdate(); + + // Used to avoid wrong context update when an embedded object activation is in progress + bool hasChartOrMathContextCurrently() const; + + static SidebarController* GetSidebarControllerForView(const SfxViewShell* pViewShell); + +private: + SidebarController(SidebarDockingWindow* pParentWindow, const SfxViewFrame* pViewFrame); + + VclPtr<Deck> mpCurrentDeck; + VclPtr<SidebarDockingWindow> mpParentWindow; + const SfxViewFrame* mpViewFrame; + css::uno::Reference<css::frame::XFrame> mxFrame; + VclPtr<TabBar> mpTabBar; + Context maCurrentContext; + Context maRequestedContext; + css::uno::Reference<css::frame::XController> mxCurrentController; + /// Use a combination of SwitchFlag_* as value. + sal_Int32 mnRequestedForceFlags; + sal_Int32 mnMaximumSidebarWidth; + bool mbMinimumSidebarWidth; + OUString msCurrentDeckId; + AsynchronousCall maPropertyChangeForwarder; + AsynchronousCall maContextChangeUpdate; + css::uno::Reference<css::beans::XPropertySet> mxThemePropertySet; + + /** Two flags control whether the deck is displayed or if only the + tab bar remains visible. + The mbIsDeckOpen flag stores the current state while + mbIsDeckRequestedOpen stores how this state should be. User + actions like clicking on the deck closer affect the + mbIsDeckRequestedOpen. Normally both flags have the same + value. A document being read-only can prevent the deck from opening. + */ + ::std::optional<bool> mbIsDeckRequestedOpen; + ::std::optional<bool> mbIsDeckOpen; + + bool mbFloatingDeckClosed; + + /** Before the deck is closed the sidebar width is saved into this variable, + so that it can be restored when the deck is reopened. + */ + sal_Int32 mnSavedSidebarWidth; + FocusManager maFocusManager; + css::uno::Reference<css::frame::XDispatch> mxReadOnlyModeDispatch; + bool mbIsDocumentReadOnly; + VclPtr<SfxSplitWindow> mpSplitWindow; + /** When the user moves the splitter then we remember the + width at that time. + */ + sal_Int32 mnWidthOnSplitterButtonDown; + /** Control that is temporarily used as replacement for the deck + to indicate that when the current mouse drag operation ends, the + sidebar will only show the tab bar. + */ + VclPtr<vcl::Window> mpCloseIndicator; + + DECL_DLLPRIVATE_LINK(WindowEventHandler, VclWindowEvent&, void); + /** Make maRequestedContext the current context. + */ + void UpdateConfigurations(); + + css::uno::Reference<css::ui::XUIElement> CreateUIElement ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const OUString& rsImplementationURL, + const bool bWantsCanvas, + const Context& rContext); + + void CreatePanels( + std::u16string_view rDeckId, + const Context& rContext); + std::shared_ptr<Panel> CreatePanel ( + std::u16string_view rsPanelId, + weld::Widget* pParentWindow, + const bool bIsInitiallyExpanded, + const Context& rContext, + const VclPtr<Deck>& pDeck); + + void SwitchToDeck ( + const DeckDescriptor& rDeckDescriptor, + const Context& rContext); + + void ShowPopupMenu ( + weld::Menu& rMainMenu, + weld::Menu& rSubMenu, + const ::std::vector<TabBar::DeckMenuData>& rMenuData) const; + void PopulatePopupMenus( + weld::Menu& rMainButton, + weld::Menu& rSubMenu, + const ::std::vector<TabBar::DeckMenuData>& rMenuData) const; + DECL_DLLPRIVATE_LINK(OnMenuItemSelected, const OUString&, void); + DECL_DLLPRIVATE_LINK(OnSubMenuItemSelected, const OUString&, void); + void BroadcastPropertyChange(); + + /** The close of the deck changes the width of the child window. + That is only possible if there is no other docking window docked above or below the sidebar. + Return whether the width of the child window can be modified. + */ + bool CanModifyChildWindowWidth(); + + /** Set the child window container to a new width. + Return the old width. + */ + sal_Int32 SetChildWindowWidth (const sal_Int32 nNewWidth); + + /** Update the icons displayed in the title bars of the deck and + the panels. This is called once when a deck is created and + every time when a data change event is processed. + */ + void UpdateTitleBarIcons(); + + void UpdateDeckOpenState(); + void RestrictWidth (sal_Int32 nWidth); + SfxSplitWindow* GetSplitWindow(); + void ProcessNewWidth (const sal_Int32 nNewWidth); + void UpdateCloseIndicator (const bool bIsIndicatorVisible); + + /** Typically called when a panel is focused via keyboard. + Tries to scroll the deck up or down to make the given panel + completely visible. + */ + void ShowPanel (const Panel& rPanel); + + virtual void disposing(std::unique_lock<std::mutex>&) override; + + std::unique_ptr<ResourceManager> mpResourceManager; + +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/SidebarDockingWindow.hxx b/include/sfx2/sidebar/SidebarDockingWindow.hxx new file mode 100644 index 0000000000..f433086297 --- /dev/null +++ b/include/sfx2/sidebar/SidebarDockingWindow.hxx @@ -0,0 +1,66 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/dockwin.hxx> + +#include <rtl/ref.hxx> + +class SfxViewShell; + +namespace svt { class AcceleratorExecute; } + +namespace sfx2::sidebar { + +class SidebarChildWindow; + +class SidebarController; + +class SFX2_DLLPUBLIC SidebarDockingWindow final : public SfxDockingWindow +{ +public: + SidebarDockingWindow(SfxBindings* pBindings, SidebarChildWindow& rChildWindow, + vcl::Window* pParent, WinBits nBits); + virtual ~SidebarDockingWindow() override; + virtual void dispose() override; + virtual bool EventNotify(NotifyEvent& rEvent) override; + virtual bool Close() override; + + /// Force generation of all panels by completion. + void SyncUpdate(); + + rtl::Reference<sfx2::sidebar::SidebarController>& GetOrCreateSidebarController(); + using SfxDockingWindow::Close; + +private: + // Window overridables + virtual void GetFocus() override; + + virtual SfxChildAlignment CheckAlignment ( + SfxChildAlignment eCurrentAlignment, + SfxChildAlignment eRequestedAlignment) override; + + ::rtl::Reference<sfx2::sidebar::SidebarController> mpSidebarController; + bool mbIsReadyToDrag; + std::unique_ptr<svt::AcceleratorExecute> mpAccel; +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/SidebarModelUpdate.hxx b/include/sfx2/sidebar/SidebarModelUpdate.hxx new file mode 100644 index 0000000000..33b273f143 --- /dev/null +++ b/include/sfx2/sidebar/SidebarModelUpdate.hxx @@ -0,0 +1,33 @@ +/* -*- 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/. + */ + +#pragma once + +#include <sfx2/dllapi.h> + +namespace com::sun::star::frame +{ +class XModel; +} +namespace com::sun::star::uno +{ +template <typename> class Reference; +} + +namespace sfx2::sidebar +{ +class SFX2_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") SidebarModelUpdate +{ +public: + virtual ~SidebarModelUpdate(); + virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/SidebarPanelBase.hxx b/include/sfx2/sidebar/SidebarPanelBase.hxx new file mode 100644 index 0000000000..c1c99cd24a --- /dev/null +++ b/include/sfx2/sidebar/SidebarPanelBase.hxx @@ -0,0 +1,102 @@ +/* -*- 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 . + */ +#pragma once + +#include <sal/config.h> + +#include <memory> + +#include <sfx2/dllapi.h> + +#include <comphelper/compbase.hxx> + +#include <com/sun/star/ui/XContextChangeEventListener.hpp> +#include <com/sun/star/ui/XUIElement.hpp> +#include <com/sun/star/ui/XToolPanel.hpp> +#include <com/sun/star/ui/XSidebarPanel.hpp> +#include <com/sun/star/ui/XUpdateModel.hpp> + +class PanelLayout; + +namespace sfx2::sidebar { + +class Panel; + +typedef comphelper::WeakComponentImplHelper<css::ui::XContextChangeEventListener, + css::ui::XUIElement, + css::ui::XToolPanel, + css::ui::XSidebarPanel, + css::ui::XUpdateModel> + SidebarPanelBaseInterfaceBase; + +/** Base class for sidebar panels that provides some convenience + functionality. +*/ +class SFX2_DLLPUBLIC SidebarPanelBase final : public SidebarPanelBaseInterfaceBase +{ +public: + static css::uno::Reference<css::ui::XUIElement> Create(const OUString& rsResourceURL, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + std::unique_ptr<PanelLayout> xControl, + const css::ui::LayoutSize& rLayoutSize); + + // XContextChangeEventListener + virtual void SAL_CALL notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent) override; + + // XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override; + + // XUIElement + virtual css::uno::Reference<css::frame::XFrame> SAL_CALL getFrame() override; + virtual OUString SAL_CALL getResourceURL() override; + virtual sal_Int16 SAL_CALL getType() override; + virtual css::uno::Reference<css::uno::XInterface> SAL_CALL getRealInterface() override; + + // XToolPanel + virtual css::uno::Reference<css::accessibility::XAccessible> SAL_CALL createAccessible( + const css::uno::Reference<css::accessibility::XAccessible>& rxParentAccessible) override; + virtual css::uno::Reference<css::awt::XWindow> SAL_CALL getWindow() override; + + // XSidebarPanel + virtual css::ui::LayoutSize SAL_CALL getHeightForWidth(sal_Int32 nWidth) override; + virtual sal_Int32 SAL_CALL getMinimalWidth() override; + + // XUpdateModel + virtual void SAL_CALL updateModel(const css::uno::Reference<css::frame::XModel>& xModel) override; + + void SetParentPanel(sfx2::sidebar::Panel* pPanel); + +private: + SidebarPanelBase(OUString sResourceURL, css::uno::Reference<css::frame::XFrame> xFrame, + std::unique_ptr<PanelLayout> xControl, const css::ui::LayoutSize& rLayoutSize); + virtual ~SidebarPanelBase() override; + SidebarPanelBase(const SidebarPanelBase&) = delete; + SidebarPanelBase& operator=( const SidebarPanelBase& ) = delete; + + virtual void disposing(std::unique_lock<std::mutex>&) override; + + css::uno::Reference<css::frame::XFrame> mxFrame; + std::unique_ptr<PanelLayout> mxControl; + const OUString msResourceURL; + const css::ui::LayoutSize maLayoutSize; +}; + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/TabBar.hxx b/include/sfx2/sidebar/TabBar.hxx new file mode 100644 index 0000000000..6ef0fc9c3d --- /dev/null +++ b/include/sfx2/sidebar/TabBar.hxx @@ -0,0 +1,138 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/sidebar/ResourceManager.hxx> + +#include <vcl/InterimItemWindow.hxx> + +#include <functional> + +namespace com::sun::star::frame { class XFrame; } + +namespace svt { class AcceleratorExecute; } + +namespace weld { class Toolbar; } + +namespace sfx2::sidebar { + +class FocusManager; +class SidebarController; + +/** The tab bar is the container for the individual tabs. +*/ +class TabBar final : public InterimItemWindow +{ + friend class TabBarUIObject; +public: + /** DeckMenuData has entries for display name, and a flag: + - isCurrentDeck for the deck selection data + - isEnabled for the show/hide menu + */ + class DeckMenuData + { + public: + OUString msDisplayName; + bool mbIsCurrentDeck; + bool mbIsActive; + bool mbIsEnabled; + }; + typedef ::std::function<void ( + weld::Menu& rMainMenu, weld::Menu& rSubMenu, + const ::std::vector<DeckMenuData>& rMenuData)> PopupMenuProvider; + TabBar ( + vcl::Window* pParentWindow, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + ::std::function<void (const OUString& rsDeckId)> aDeckActivationFunctor, + PopupMenuProvider aPopupMenuProvider, + SidebarController* rParentSidebarController); + + weld::Container* GetContainer() { return m_xContainer.get(); } + + virtual ~TabBar() override; + virtual void dispose() override; + + virtual void DataChanged (const DataChangedEvent& rDataChangedEvent) override; + virtual bool EventNotify (NotifyEvent& rEvent) override; + + static sal_Int32 GetDefaultWidth(); + + void SetDecks ( + const ResourceManager::DeckContextDescriptorContainer& rDecks); + void HighlightDeck (std::u16string_view rsDeckId); + void RemoveDeckHighlight (); + OUString const & GetDeckIdForIndex (const sal_Int32 nIndex) const; + void ToggleHideFlag (const sal_Int32 nIndex); + void RestoreHideFlags(); + + void UpdateFocusManager (FocusManager& rFocusManager); + + /// Enables/Disables the menu button. Used by LoKit. + void EnableMenuButton(const bool bEnable); + + virtual FactoryFunction GetUITestFactory() const override; +private: + css::uno::Reference<css::frame::XFrame> mxFrame; + + // This unusual auxiliary builder is because without a toplevel GtkWindow + // gtk will warn on loading a .ui with an accelerator defined, so use a + // temporary toplevel to suppress that and move the contents after load + std::unique_ptr<weld::Builder> mxAuxBuilder; + std::unique_ptr<weld::Box> mxTempToplevel; + std::unique_ptr<weld::Widget> mxContents; + + std::unique_ptr<weld::MenuButton> mxMenuButton; + std::unique_ptr<weld::Menu> mxMainMenu; + std::unique_ptr<weld::Menu> mxSubMenu; + std::unique_ptr<weld::Widget> mxMeasureBox; + class Item + { + private: + TabBar& mrTabBar; + std::unique_ptr<weld::Builder> mxBuilder; + public: + Item(TabBar& rTabBar); + ~Item(); + DECL_LINK(HandleClick, const OUString&, void); + std::unique_ptr<weld::Toolbar> mxButton; + OUString msDeckId; + ::std::function<void (const OUString& rsDeckId)> maDeckActivationFunctor; + bool mbIsHidden; + bool mbIsHiddenByDefault; + }; + typedef ::std::vector<std::unique_ptr<Item>> ItemContainer; + ItemContainer maItems; + const ::std::function<void (const OUString& rsDeckId)> maDeckActivationFunctor; + PopupMenuProvider maPopupMenuProvider; + + void CreateTabItem(weld::Toolbar& rButton, const DeckDescriptor& rDeckDescriptor); + css::uno::Reference<css::graphic::XGraphic> GetItemImage(const DeckDescriptor& rDeskDescriptor) const; + void UpdateButtonIcons(); + + DECL_LINK(OnToolboxClicked, weld::Toggleable&, void); + + SidebarController* pParentSidebarController; + std::unique_ptr<svt::AcceleratorExecute> mpAccel; + +}; + + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/sidebar/Theme.hxx b/include/sfx2/sidebar/Theme.hxx new file mode 100644 index 0000000000..a3f827f4a5 --- /dev/null +++ b/include/sfx2/sidebar/Theme.hxx @@ -0,0 +1,184 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/dllapi.h> + +#include <tools/color.hxx> +#include <comphelper/compbase.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <map> +#include <unordered_map> + + +namespace sfx2::sidebar { + +typedef comphelper::WeakComponentImplHelper < + css::beans::XPropertySet, + css::beans::XPropertySetInfo + > ThemeInterfaceBase; + +/** Simple collection of colors, gradients, fonts that define the + look of the sidebar and its controls. +*/ +class SFX2_DLLPUBLIC Theme final + : public ThemeInterfaceBase +{ +public: + enum ThemeItem + { + Begin_, + Pre_Color_ = Begin_, + + AnyItem_ = Pre_Color_, + + Image_Color_, + + Color_Highlight, + Color_HighlightText, + Color_DeckBackground, + Color_DeckTitleBarBackground, + Color_PanelBackground, + Color_PanelTitleBarBackground, + Color_TabBarBackground, + + Color_Int_, + + Int_DeckBorderSize, + Int_DeckSeparatorHeight, + Int_DeckLeftPadding, + Int_DeckTopPadding, + Int_DeckRightPadding, + Int_DeckBottomPadding, + + Int_Bool_, + + Bool_UseSystemColors, + Bool_IsHighContrastModeActive, + + Post_Bool_, + End_=Post_Bool_ + }; + + static Color GetColor (const ThemeItem eItem); + static sal_Int32 GetInteger (const ThemeItem eItem); + + static bool IsHighContrastMode(); + + static void HandleDataChange(); + + void InitializeTheme(); + + Theme(); + virtual ~Theme() override; + Theme(const Theme&) = delete; + Theme& operator=( const Theme& ) = delete; + + virtual void disposing(std::unique_lock<std::mutex>&) override; + + static css::uno::Reference<css::beans::XPropertySet> GetPropertySet(); + + // beans::XPropertySet + virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override; + virtual void SAL_CALL setPropertyValue ( + const OUString& rsPropertyName, + const css::uno::Any& rValue) override; + virtual css::uno::Any SAL_CALL getPropertyValue ( + const OUString& rsPropertyName) override; + virtual void SAL_CALL addPropertyChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XPropertyChangeListener>& rxListener) override; + virtual void SAL_CALL removePropertyChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XPropertyChangeListener>& rxListener) override; + virtual void SAL_CALL addVetoableChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XVetoableChangeListener>& rxListener) override; + virtual void SAL_CALL removeVetoableChangeListener( + const OUString& rsPropertyName, + const css::uno::Reference<css::beans::XVetoableChangeListener>& rxListener) override; + + // beans::XPropertySetInfo + virtual css::uno::Sequence<css::beans::Property> SAL_CALL getProperties() override; + virtual css::beans::Property SAL_CALL getPropertyByName (const OUString& rsName) override; + virtual sal_Bool SAL_CALL hasPropertyByName (const OUString& rsName) override; + +private: + static Theme& GetCurrentTheme(); + + std::vector<Color> maColors; + std::vector<sal_Int32> maIntegers; + std::vector<bool> maBooleans; + bool mbIsHighContrastMode; + bool mbIsHighContrastModeSetManually; + + typedef std::unordered_map<OUString,ThemeItem> PropertyNameToIdMap; + PropertyNameToIdMap maPropertyNameToIdMap; + typedef std::vector<OUString> PropertyIdToNameMap; + PropertyIdToNameMap maPropertyIdToNameMap; + typedef ::std::vector<css::uno::Any> RawValueContainer; + RawValueContainer maRawValues; + + typedef std::vector<css::uno::Reference<css::beans::XPropertyChangeListener> > ChangeListenerContainer; + typedef std::map<ThemeItem,ChangeListenerContainer> ChangeListeners; + ChangeListeners maChangeListeners; + typedef std::vector<css::uno::Reference<css::beans::XVetoableChangeListener> > VetoableListenerContainer; + typedef std::map<ThemeItem,VetoableListenerContainer> VetoableListeners; + VetoableListeners maVetoableListeners; + + enum PropertyType + { + PT_Color, + PT_Integer, + PT_Boolean, + PT_Invalid + }; + + void SetupPropertyMaps(); + void UpdateTheme(); + static PropertyType GetPropertyType (const ThemeItem eItem); + static css::uno::Type const & GetCppuType (const PropertyType eType); + static sal_Int32 GetIndex ( + const ThemeItem eItem, + const PropertyType eType); + + VetoableListenerContainer* GetVetoableListeners ( + const ThemeItem eItem, + const bool bCreate); + ChangeListenerContainer* GetChangeListeners ( + const ThemeItem eItem, + const bool bCreate); + static bool DoVetoableListenersVeto ( + const VetoableListenerContainer* pListeners, + const css::beans::PropertyChangeEvent& rEvent); + static void BroadcastPropertyChange ( + const ChangeListenerContainer* pListeners, + const css::beans::PropertyChangeEvent& rEvent); + void ProcessNewValue ( + const css::uno::Any& rValue, + const ThemeItem eItem, + const PropertyType eType); +}; + + +} // end of namespace sfx2::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |