diff options
Diffstat (limited to 'include/vcl/builder.hxx')
-rw-r--r-- | include/vcl/builder.hxx | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx new file mode 100644 index 0000000000..64538f8127 --- /dev/null +++ b/include/vcl/builder.hxx @@ -0,0 +1,451 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_VCL_BUILDER_HXX +#define INCLUDED_VCL_BUILDER_HXX + +#include <typeinfo> +#include <sal/log.hxx> +#include <unotools/resmgr.hxx> +#include <tools/fldunit.hxx> +#include <vcl/dllapi.h> +#include <utility> +#include <vcl/window.hxx> +#include <vcl/vclptr.hxx> +#include <vcl/toolboxid.hxx> +#include <vcl/wintypes.hxx> +#include <vcl/EnumContext.hxx> + +#include <memory> +#include <map> +#include <string_view> +#include <vector> +#ifdef check +# //some problem with MacOSX and a check define +# undef check +#endif + +class Button; +class ComboBox; +class FormattedField; +class ListBox; +class Menu; +class MessageDialog; +class NumericFormatter; +class PopupMenu; +class SalInstanceBuilder; +class ScreenshotTest; +class ScrollBar; +class SvTabListBox; +class Slider; +class DateField; +class TimeField; +class ToolBox; +class VclExpander; +class VclMultiLineEdit; +struct NotebookBarAddonsItem; +namespace xmlreader { class XmlReader; } +namespace com::sun::star::frame { class XFrame; } + +struct ComboBoxTextItem +{ + OUString m_sItem; + OUString m_sId; + ComboBoxTextItem(OUString sItem, OUString sId) + : m_sItem(std::move(sItem)) + , m_sId(std::move(sId)) + { + } +}; + +/// Creates a hierarchy of vcl::Windows (widgets) from a .ui file for dialogs, sidebar, etc. +class VCL_DLLPUBLIC VclBuilder +{ +public: + typedef std::map<OUString, OUString> stringmap; + typedef std::map<OUString, std::pair<OUString, OUString>> accelmap; + /// These functions create a new widget with parent pParent and return it in rRet + typedef void (*customMakeWidget)(VclPtr<vcl::Window> &rRet, const VclPtr<vcl::Window> &pParent, stringmap &rVec); + +public: + VclBuilder(vcl::Window* pParent, const OUString& sUIRootDir, const OUString& sUIFile, + OUString sID = {}, + css::uno::Reference<css::frame::XFrame> xFrame + = css::uno::Reference<css::frame::XFrame>(), + bool bLegacy = true, + const NotebookBarAddonsItem* pNotebookBarAddonsItem = nullptr); + ~VclBuilder(); + ///releases references and disposes all children. + void disposeBuilder(); + //sID must exist and be of type T + template <typename T> T* get(VclPtr<T>& ret, const OUString& sID); + + //sID may not exist, but must be of type T if it does + template <typename T = vcl::Window> T* get(const OUString& sID); + + vcl::Window* get_widget_root(); + + //sID may not exist + PopupMenu* get_menu(std::u16string_view sID); + + //release ownership of pWindow, i.e. don't delete it + void drop_ownership(const vcl::Window *pWindow); + + //see m_aDeferredProperties, you need this for toplevel dialogs + //which build themselves from their ctor. The properties on + //the top level are stored in m_aDeferredProperties and need + //to be applied post ctor + void setDeferredProperties(); + + /// return UI-File name (without '.ui') + const OUString& getUIFile() const + { + return m_sHelpRoot; + } + + static SymbolType mapStockToSymbol(std::u16string_view icon_name); + +private: + VclBuilder(const VclBuilder&) = delete; + VclBuilder& operator=(const VclBuilder&) = delete; + + // owner for ListBox/ComboBox UserData + std::vector<std::unique_ptr<OUString>> m_aUserData; + + //If the toplevel window has any properties which need to be set on it, + //but the toplevel is the owner of the builder, then its ctor + //has not been completed during the building, so properties for it + //are collected here and need to be set afterwards, e.g. during + //Show or Execute + stringmap m_aDeferredProperties; + + std::unique_ptr<NotebookBarAddonsItem> m_pNotebookBarAddonsItem; + + struct PackingData + { + bool m_bVerticalOrient; + sal_Int32 m_nPosition; + PackingData(bool bVerticalOrient = false) + : m_bVerticalOrient(bVerticalOrient) + , m_nPosition(-1) + { + } + }; + + struct WinAndId + { + OUString m_sID; + VclPtr<vcl::Window> m_pWindow; + PackingData m_aPackingData; + WinAndId(OUString sId, vcl::Window *pWindow, bool bVertical) + : m_sID(std::move(sId)) + , m_pWindow(pWindow) + , m_aPackingData(bVertical) + { + } + }; + std::vector<WinAndId> m_aChildren; + + struct MenuAndId + { + OUString m_sID; + VclPtr<Menu> m_pMenu; + MenuAndId(OUString sId, Menu *pMenu); + }; + std::vector<MenuAndId> m_aMenus; + + struct StringPair + { + OUString m_sID; + OUString m_sValue; + StringPair(OUString sId, OUString sValue) + : m_sID(std::move(sId)) + , m_sValue(std::move(sValue)) + { + } + }; + + struct UStringPair + { + OUString m_sID; + OUString m_sValue; + UStringPair(OUString sId, OUString sValue) + : m_sID(std::move(sId)) + , m_sValue(std::move(sValue)) + { + } + }; + + typedef StringPair RadioButtonGroupMap; + + struct ButtonImageWidgetMap + { + OUString m_sID; + OUString m_sValue; + bool m_bRadio; + ButtonImageWidgetMap(OUString sId, OUString sValue, bool bRadio) + : m_sID(std::move(sId)) + , m_sValue(std::move(sValue)) + , m_bRadio(bRadio) + { + } + }; + + typedef UStringPair TextBufferMap; + typedef UStringPair WidgetAdjustmentMap; + typedef UStringPair ButtonMenuMap; + typedef UStringPair MnemonicWidgetMap; + + struct ComboBoxModelMap + { + OUString m_sID; + OUString m_sValue; + sal_Int32 m_nActiveId; + ComboBoxModelMap(OUString sId, OUString sValue, sal_Int32 nActiveId) + : m_sID(std::move(sId)) + , m_sValue(std::move(sValue)) + , m_nActiveId(nActiveId) + { + } + }; + + struct ListStore + { + typedef std::vector<OUString> row; + std::vector<row> m_aEntries; + }; + + const ListStore* get_model_by_name(const OUString& sID) const; + void mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); + void mungeModel(ComboBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); + void mungeModel(SvTabListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); + + typedef stringmap TextBuffer; + const TextBuffer* get_buffer_by_name(const OUString& sID) const; + + static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer); + + typedef stringmap Adjustment; + const Adjustment* get_adjustment_by_name(const OUString& sID) const; + + static void mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(FormattedField &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(Slider &rTarget, const Adjustment &rAdjustment); + + typedef std::map<OUString, int> ImageSizeMap; + + struct SizeGroup + { + std::vector<OUString> m_aWidgets; + stringmap m_aProperties; + SizeGroup() {} + }; + + + struct ParserState + { + std::locale m_aResLocale; + + std::vector<RadioButtonGroupMap> m_aGroupMaps; + + std::vector<ComboBoxModelMap> m_aModelMaps; + std::map<OUString, ListStore> m_aModels; + + std::vector<TextBufferMap> m_aTextBufferMaps; + std::map<OUString, TextBuffer> m_aTextBuffers; + + std::vector<WidgetAdjustmentMap> m_aNumericFormatterAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aFormattedFormatterAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aScrollAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aSliderAdjustmentMaps; + + std::map<OUString, Adjustment> m_aAdjustments; + + std::vector<ButtonImageWidgetMap> m_aButtonImageWidgetMaps; + ImageSizeMap m_aImageSizeMap; + + std::vector<ButtonMenuMap> m_aButtonMenuMaps; + + std::map<VclPtr<vcl::Window>, VclPtr<vcl::Window>> m_aRedundantParentWidgets; + + std::vector<SizeGroup> m_aSizeGroups; + + std::map<VclPtr<vcl::Window>, stringmap> m_aAtkInfo; + + std::vector<MnemonicWidgetMap> m_aMnemonicWidgetMaps; + + std::vector< VclPtr<VclExpander> > m_aExpanderWidgets; + + std::vector< VclPtr<MessageDialog> > m_aMessageDialogs; + + ToolBoxItemId m_nLastToolbarId; + + sal_uInt16 m_nLastMenuItemId; + + ParserState(); + }; + + OUString m_sID; + OUString m_sHelpRoot; + ResHookProc m_pStringReplace; + VclPtr<vcl::Window> m_pParent; + bool m_bToplevelHasDeferredInit; + bool m_bToplevelHasDeferredProperties; + bool m_bToplevelParentFound; + bool m_bLegacy; + std::unique_ptr<ParserState> m_pParserState; + + vcl::Window *get_by_name(std::u16string_view sID); + void delete_by_name(const OUString& sID); + + class sortIntoBestTabTraversalOrder + { + public: + sortIntoBestTabTraversalOrder(VclBuilder *pBuilder) + : m_pBuilder(pBuilder) {} + + bool operator()(const vcl::Window *pA, const vcl::Window *pB) const; + + private: + VclBuilder *m_pBuilder; + }; + + /// XFrame to be able to extract labels and other properties of the UNO commands (like of .uno:Bold). + css::uno::Reference<css::frame::XFrame> m_xFrame; + +private: + VclPtr<vcl::Window> insertObject(vcl::Window *pParent, + const OUString &rClass, const OUString &rID, + stringmap &rProps, stringmap &rPangoAttributes, + stringmap &rAtkProps); + + VclPtr<vcl::Window> makeObject(vcl::Window *pParent, + const OUString &rClass, const OUString &rID, + stringmap &rVec); + + void connectNumericFormatterAdjustment(const OUString &id, const OUString &rAdjustment); + void connectFormattedFormatterAdjustment(const OUString &id, const OUString &rAdjustment); + + static int getImageSize(const stringmap &rMap); + + void extractGroup(const OUString &id, stringmap &rVec); + void extractModel(const OUString &id, stringmap &rVec); + void extractBuffer(const OUString &id, stringmap &rVec); + static bool extractAdjustmentToMap(const OUString &id, stringmap &rVec, std::vector<WidgetAdjustmentMap>& rAdjustmentMap); + void extractButtonImage(const OUString &id, stringmap &rMap, bool bRadio); + void extractMnemonicWidget(const OUString &id, stringmap &rMap); + + // either pParent or pAtkProps must be set, pParent for a child of a widget, pAtkProps for + // collecting the atk info for a GtkMenuItem + void handleChild(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader); + VclPtr<vcl::Window> handleObject(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader); + void handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader); + static std::vector<vcl::EnumContext::Context> handleStyle(xmlreader::XmlReader &reader, int &nPriority); + static OUString getStyleClass(xmlreader::XmlReader &reader); + void applyPackingProperty(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader); + void collectProperty(xmlreader::XmlReader &reader, stringmap &rVec) const; + static void collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap); + static void collectAtkRelationAttribute(xmlreader::XmlReader &reader, stringmap &rMap); + static void collectAtkRoleAttribute(xmlreader::XmlReader &reader, stringmap &rMap); + static void collectAccelerator(xmlreader::XmlReader &reader, accelmap &rMap); + + void insertMenuObject( + Menu *pParent, + PopupMenu *pSubMenu, + const OUString &rClass, + const OUString &rID, + stringmap &rProps, + stringmap &rAtkProps, + accelmap &rAccels); + + void handleMenuChild(Menu *pParent, xmlreader::XmlReader &reader); + void handleMenuObject(Menu *pParent, xmlreader::XmlReader &reader); + + void handleListStore(xmlreader::XmlReader &reader, const OUString &rID, std::u16string_view rClass); + void handleRow(xmlreader::XmlReader &reader, const OUString &rID); + void handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader); + VclPtr<Menu> handleMenu(xmlreader::XmlReader &reader, const OUString &rID, bool bMenuBar); + std::vector<ComboBoxTextItem> handleItems(xmlreader::XmlReader &reader) const; + + void handleSizeGroup(xmlreader::XmlReader &reader); + + stringmap handleAtkObject(xmlreader::XmlReader &reader) const; + + static void applyAtkProperties(vcl::Window *pWindow, const stringmap& rProperties); + + void handleActionWidget(xmlreader::XmlReader &reader); + + PackingData get_window_packing_data(const vcl::Window *pWindow) const; + void set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition); + + static vcl::Window* prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle); + void cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap); + + void set_response(std::u16string_view sID, short nResponse); + + OUString get_by_window(const vcl::Window *pWindow) const; + void delete_by_window(vcl::Window *pWindow); +}; + +namespace BuilderUtils +{ + //apply the properties of rProps to pWindow + VCL_DLLPUBLIC void set_properties(vcl::Window *pWindow, const VclBuilder::stringmap &rProps); + + //Convert _ gtk markup to ~ vcl markup + VCL_DLLPUBLIC OUString convertMnemonicMarkup(std::u16string_view rIn); + + VCL_DLLPUBLIC OUString extractCustomProperty(VclBuilder::stringmap &rMap); + + VCL_DLLPUBLIC bool extractDropdown(VclBuilder::stringmap &rMap); + + //add a default value of 25 width-chars to a map if width-chars not set + VCL_DLLPUBLIC void ensureDefaultWidthChars(VclBuilder::stringmap &rMap); + + //Helpers to retrofit all the existing code to the builder + VCL_DLLPUBLIC void reorderWithinParent(std::vector< vcl::Window*>& rChilds, bool bIsButtonBox); + VCL_DLLPUBLIC void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition); + + //Convert an accessibility role name to accessibility role number + VCL_DLLPUBLIC sal_Int16 getRoleFromName(const OUString& roleName); +} + +template <typename T> +inline T* VclBuilder::get(VclPtr<T>& ret, const OUString& sID) +{ + vcl::Window *w = get_by_name(sID); + SAL_WARN_IF(!w, "vcl.layout", "widget \"" << sID << "\" not found in .ui"); + SAL_WARN_IF(!dynamic_cast<T*>(w), + "vcl.layout", ".ui widget \"" << sID << "\" needs to correspond to vcl type " << typeid(T).name()); + assert(w); + assert(dynamic_cast<T*>(w)); + ret = static_cast<T*>(w); + return ret.get(); +} + +//sID may not exist, but must be of type T if it does +template <typename T> +inline T* VclBuilder::get(const OUString& sID) +{ + vcl::Window *w = get_by_name(sID); + SAL_WARN_IF(w && !dynamic_cast<T*>(w), + "vcl.layout", ".ui widget \"" << sID << "\" needs to correspond to vcl type " << typeid(T).name()); + assert(!w || dynamic_cast<T*>(w)); + return static_cast<T*>(w); +} + +/* + * @return true if rValue is "True", "true", "1", etc. + */ +VCL_DLLPUBLIC bool toBool(std::u16string_view rValue); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |