diff options
Diffstat (limited to 'include/vcl/builder.hxx')
-rw-r--r-- | include/vcl/builder.hxx | 512 |
1 files changed, 512 insertions, 0 deletions
diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx new file mode 100644 index 000000000..b2bc2488b --- /dev/null +++ b/include/vcl/builder.hxx @@ -0,0 +1,512 @@ +/* -*- 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 <vcl/window.hxx> +#include <vcl/vclptr.hxx> +#include <tools/wintypes.hxx> +#include <vcl/EnumContext.hxx> + +#include <memory> +#include <map> +#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 VclExpander; +class VclMultiLineEdit; +struct NotebookBarAddonsItem; +namespace xmlreader { class XmlReader; } +namespace com::sun::star::frame { class XFrame; } + +struct ComboBoxTextItem +{ + OUString m_sItem; + OString m_sId; + ComboBoxTextItem(const OUString& rItem, const OString& rId) + : m_sItem(rItem) + , m_sId(rId) + { + } +}; + +/// Creates a hierarchy of vcl::Windows (widgets) from a .ui file for dialogs, sidebar, etc. +class VCL_DLLPUBLIC VclBuilder +{ +public: + typedef std::map<OString, OUString> stringmap; + typedef std::map<OString, std::pair<OString, OString>> 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, + const OString& sID = OString(), + const css::uno::Reference<css::frame::XFrame>& rFrame + = 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 OString& sID); + + //sID may not exist, but must be of type T if it does + template <typename T = vcl::Window> T* get(const OString& sID); + + vcl::Window* get_widget_root(); + + //sID may not exist + PopupMenu* get_menu(const OString& 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 OString& getUIFile() const + { + return m_sHelpRoot; + } + + /// Pre-loads all modules containing UI information + static void preload(); + +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 + { + OString m_sID; + VclPtr<vcl::Window> m_pWindow; + PackingData m_aPackingData; + WinAndId(const OString &rId, vcl::Window *pWindow, bool bVertical) + : m_sID(rId) + , m_pWindow(pWindow) + , m_aPackingData(bVertical) + { + } + }; + std::vector<WinAndId> m_aChildren; + + struct MenuAndId + { + OString m_sID; + VclPtr<Menu> m_pMenu; + MenuAndId(const OString &rId, Menu *pMenu); + }; + std::vector<MenuAndId> m_aMenus; + + struct StringPair + { + OString m_sID; + OString m_sValue; + StringPair(const OString &rId, const OString &rValue) + : m_sID(rId) + , m_sValue(rValue) + { + } + }; + + struct UStringPair + { + OString m_sID; + OUString m_sValue; + UStringPair(const OString &rId, const OUString &rValue) + : m_sID(rId) + , m_sValue(rValue) + { + } + }; + + typedef StringPair RadioButtonGroupMap; + + struct ButtonImageWidgetMap + { + OString m_sID; + OUString m_sValue; + bool m_bRadio; + ButtonImageWidgetMap(const OString &rId, const OUString &rValue, bool bRadio) + : m_sID(rId) + , m_sValue(rValue) + , m_bRadio(bRadio) + { + } + }; + + typedef UStringPair TextBufferMap; + typedef UStringPair WidgetAdjustmentMap; + typedef UStringPair ButtonMenuMap; + typedef UStringPair MnemonicWidgetMap; + + struct ComboBoxModelMap + { + OString m_sID; + OUString m_sValue; + sal_Int32 m_nActiveId; + ComboBoxModelMap(const OString &rId, const OUString &rValue, sal_Int32 nActiveId) + : m_sID(rId) + , m_sValue(rValue) + , m_nActiveId(nActiveId) + { + } + }; + + struct ListStore + { + typedef std::vector<OUString> row; + std::vector<row> m_aEntries; + }; + + const ListStore* get_model_by_name(const OString& 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 OString& sID) const; + + static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer); + + typedef stringmap Adjustment; + const Adjustment* get_adjustment_by_name(const OString& sID) const; + + static void mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(FormattedField &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(DateField &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(TimeField &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment); + static void mungeAdjustment(Slider &rTarget, const Adjustment &rAdjustment); + + struct stockinfo + { + OUString m_sStock; + int m_nSize; + stockinfo() : m_nSize(4) {} + }; + + typedef std::map<OString, stockinfo> StockMap; + + struct SizeGroup + { + std::vector<OString> m_aWidgets; + stringmap m_aProperties; + SizeGroup() {} + }; + + typedef std::map<VclPtr<vcl::Window>, stringmap> AtkMap; + + struct ParserState + { + std::locale m_aResLocale; + + std::vector<RadioButtonGroupMap> m_aGroupMaps; + + std::vector<ComboBoxModelMap> m_aModelMaps; + std::map<OString, ListStore> m_aModels; + + std::vector<TextBufferMap> m_aTextBufferMaps; + std::map<OString, TextBuffer> m_aTextBuffers; + + std::vector<WidgetAdjustmentMap> m_aNumericFormatterAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aFormattedFormatterAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aTimeFormatterAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aDateFormatterAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aScrollAdjustmentMaps; + std::vector<WidgetAdjustmentMap> m_aSliderAdjustmentMaps; + + std::map<OString, Adjustment> m_aAdjustments; + + std::vector<ButtonImageWidgetMap> m_aButtonImageWidgetMaps; + StockMap m_aStockMap; + + std::vector<ButtonMenuMap> m_aButtonMenuMaps; + + std::map<VclPtr<vcl::Window>, VclPtr<vcl::Window>> m_aRedundantParentWidgets; + + std::vector<SizeGroup> m_aSizeGroups; + + AtkMap m_aAtkInfo; + + std::vector<MnemonicWidgetMap> m_aMnemonicWidgetMaps; + + std::vector< VclPtr<VclExpander> > m_aExpanderWidgets; + + std::vector< VclPtr<MessageDialog> > m_aMessageDialogs; + + sal_uInt16 m_nLastToolbarId; + + sal_uInt16 m_nLastMenuItemId; + + ParserState(); + }; + + OString m_sID; + OString 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(const OString& sID); + void delete_by_name(const OString& 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 OString &rClass, const OString &rID, + stringmap &rProps, stringmap &rPangoAttributes, + stringmap &rAtkProps); + + VclPtr<vcl::Window> makeObject(vcl::Window *pParent, + const OString &rClass, const OString &rID, + stringmap &rVec); + + void connectNumericFormatterAdjustment(const OString &id, const OUString &rAdjustment); + void connectFormattedFormatterAdjustment(const OString &id, const OUString &rAdjustment); + void connectTimeFormatterAdjustment(const OString &id, const OUString &rAdjustment); + void connectDateFormatterAdjustment(const OString &id, const OUString &rAdjustment); + + void extractGroup(const OString &id, stringmap &rVec); + void extractModel(const OString &id, stringmap &rVec); + void extractBuffer(const OString &id, stringmap &rVec); + static bool extractAdjustmentToMap(const OString &id, stringmap &rVec, std::vector<WidgetAdjustmentMap>& rAdjustmentMap); + void extractButtonImage(const OString &id, stringmap &rMap, bool bRadio); + void extractStock(const OString &id, stringmap &rMap); + void extractMnemonicWidget(const OString &id, stringmap &rMap); + + void handleChild(vcl::Window *pParent, xmlreader::XmlReader &reader); + VclPtr<vcl::Window> handleObject(vcl::Window *pParent, 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 OString 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 OString &rClass, + const OString &rID, + stringmap &rProps, + accelmap &rAccels); + + void handleMenuChild(Menu *pParent, xmlreader::XmlReader &reader); + void handleMenuObject(Menu *pParent, xmlreader::XmlReader &reader); + + void handleListStore(xmlreader::XmlReader &reader, const OString &rID, const OString &rClass); + void handleRow(xmlreader::XmlReader &reader, const OString &rID); + void handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader); + VclPtr<Menu> handleMenu(xmlreader::XmlReader &reader, const OString &rID, bool bMenuBar); + std::vector<ComboBoxTextItem> handleItems(xmlreader::XmlReader &reader) const; + + void handleSizeGroup(xmlreader::XmlReader &reader); + + void handleAtkObject(xmlreader::XmlReader &reader, vcl::Window *pWindow); + + 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(const OString& sID, short nResponse); + + OString 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(const OUString &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 OString& roleName); +} + +template <typename T> +inline T* VclBuilder::get(VclPtr<T>& ret, const OString& 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 OString& 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); +} + + +//helper baseclass to ease retro fitting dialogs/tabpages that load a resource +//to load a .ui file instead +// +//vcl requires the Window Children of a Parent Window to be destroyed before +//the Parent Window. VclBuilderContainer owns the VclBuilder which owns the +//Children Window. So the VclBuilderContainer dtor must be called before +//the Parent Window dtor. +// +//i.e. class Dialog : public SystemWindow, public VclBuilderContainer +//not class Dialog : public VclBuilderContainer, public SystemWindow +// +//With the new 'dispose' framework, it is necessary to force the builder +//dispose before the Window dispose; so a Dialog::dispose() method would +//finish: disposeBuilder(); SystemWindow::dispose() to capture this ordering. + +class VCL_DLLPUBLIC VclBuilderContainer +{ +public: + VclBuilderContainer(); + virtual ~VclBuilderContainer(); + void disposeBuilder(); + + static OUString getUIRootDir(); + + template <typename T> T* get(VclPtr<T>& ret, const OString& sID) + { + return m_pUIBuilder->get<T>(ret, sID); + } + template <typename T = vcl::Window> T* get(const OString & sID) + { + return m_pUIBuilder->get<T>(sID); + } + void setDeferredProperties() + { + if (!m_pUIBuilder) + return; + m_pUIBuilder->setDeferredProperties(); + } + OString getUIFile() const + { + if (m_pUIBuilder) + { + return m_pUIBuilder->getUIFile(); + } + + return OString(); + } + +protected: + std::unique_ptr<VclBuilder> m_pUIBuilder; + + friend class ::SalInstanceBuilder; + friend class ::ScreenshotTest; +}; + +/* + * @return true if rValue is "True", "true", "1", etc. + */ +bool toBool(const OUString &rValue); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |