a18672dd3e
In WidgetBuilder::handleChild, pass the child type not only to WidgetBuilder::tweakInsertedChild, but also to WidgetBuilder::handleObject (add a new param for that) and from there down into the virtual WidgetBuilder::insertObject, so it can be evaluated by subclasses when creating new widgets. While it is not used yet, an upcoming commit will make use of it in QtBuilder, in order to distinguish between the two "GtkExpander" children: the label and the actual content child. As described in the "GtkExpander as GtkBuildable" doc [1]: > The GtkExpander implementation of the GtkBuildable interface supports > placing a child in the label position by specifying “label” as the > “type” attribute of a <child> element. A normal content child can be > specified without specifying a <child> type attribute. [1] https://docs.gtk.org/gtk3/class.Expander.html Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177191 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
338 lines
12 KiB
C++
338 lines
12 KiB
C++
/* -*- 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 <typeinfo>
|
|
#include <sal/log.hxx>
|
|
#include <unotools/resmgr.hxx>
|
|
#include <tools/fldunit.hxx>
|
|
#include <vcl/dllapi.h>
|
|
#include <utility>
|
|
#include <vcl/menu.hxx>
|
|
#include <vcl/widgetbuilder.hxx>
|
|
#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 SalInstanceBuilder;
|
|
class ScreenshotTest;
|
|
class ScrollBar;
|
|
class SvTabListBox;
|
|
class Slider;
|
|
class DateField;
|
|
class TimeField;
|
|
class ToolBox;
|
|
class VclExpander;
|
|
class VclMultiLineEdit;
|
|
struct NotebookBarAddonsItem;
|
|
namespace com::sun::star::frame { class XFrame; }
|
|
|
|
/// Creates a hierarchy of vcl::Windows (widgets) from a .ui file for dialogs, sidebar, etc.
|
|
class VCL_DLLPUBLIC VclBuilder : public WidgetBuilder<vcl::Window, VclPtr<vcl::Window>, PopupMenu, VclPtr<PopupMenu>>
|
|
{
|
|
public:
|
|
/// 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, std::u16string_view 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);
|
|
virtual ~VclBuilder();
|
|
///releases references and disposes all children.
|
|
void disposeBuilder();
|
|
|
|
//sID may not exist, but must be of type T if it does
|
|
template <typename T = vcl::Window> T* get(std::u16string_view sID);
|
|
|
|
vcl::Window* get_widget_root();
|
|
|
|
//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();
|
|
|
|
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;
|
|
|
|
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 StringPair TextBufferMap;
|
|
typedef StringPair WidgetAdjustmentMap;
|
|
typedef StringPair ButtonMenuMap;
|
|
|
|
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)
|
|
{
|
|
}
|
|
};
|
|
|
|
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);
|
|
|
|
void insertComboBoxOrListBoxItems(vcl::Window* pWindow, stringmap& rMap,
|
|
const std::vector<ComboBoxTextItem>& rItems) override;
|
|
|
|
static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer);
|
|
|
|
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 VclParserState
|
|
{
|
|
std::vector<RadioButtonGroupMap> m_aGroupMaps;
|
|
|
|
std::vector<ComboBoxModelMap> m_aModelMaps;
|
|
|
|
std::vector<TextBufferMap> m_aTextBufferMaps;
|
|
|
|
std::vector<WidgetAdjustmentMap> m_aNumericFormatterAdjustmentMaps;
|
|
std::vector<WidgetAdjustmentMap> m_aFormattedFormatterAdjustmentMaps;
|
|
std::vector<WidgetAdjustmentMap> m_aScrollAdjustmentMaps;
|
|
std::vector<WidgetAdjustmentMap> m_aSliderAdjustmentMaps;
|
|
|
|
std::vector<ButtonImageWidgetMap> m_aButtonImageWidgetMaps;
|
|
ImageSizeMap m_aImageSizeMap;
|
|
|
|
std::vector<ButtonMenuMap> m_aButtonMenuMaps;
|
|
|
|
std::map<VclPtr<vcl::Window>, VclPtr<vcl::Window>> m_aRedundantParentWidgets;
|
|
|
|
std::map<VclPtr<vcl::Window>, stringmap> m_aAtkInfo;
|
|
|
|
std::vector< VclPtr<VclExpander> > m_aExpanderWidgets;
|
|
|
|
std::vector< VclPtr<MessageDialog> > m_aMessageDialogs;
|
|
|
|
ToolBoxItemId m_nLastToolbarId;
|
|
|
|
sal_uInt16 m_nLastMenuItemId;
|
|
|
|
VclParserState();
|
|
};
|
|
|
|
OUString m_sID;
|
|
VclPtr<vcl::Window> m_pParent;
|
|
bool m_bToplevelHasDeferredInit;
|
|
bool m_bToplevelHasDeferredProperties;
|
|
bool m_bToplevelParentFound;
|
|
std::unique_ptr<VclParserState> m_pVclParserState;
|
|
|
|
virtual void resetParserState() override;
|
|
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:
|
|
// tweak newly inserted child depending on window type
|
|
void tweakInsertedChild(vcl::Window *pParent, vcl::Window* pCurrentChild,
|
|
std::string_view sType, std::string_view sInternalChild) override;
|
|
|
|
VclPtr<vcl::Window> insertObject(vcl::Window* pParent, const OUString& rClass,
|
|
std::string_view sType, const OUString& rID, stringmap& rProps,
|
|
stringmap& rPangoAttributes, stringmap& rAtkProps) override;
|
|
|
|
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 applyPackingProperties(vcl::Window* pCurrent, vcl::Window* pParent,
|
|
const stringmap& rPackingProperties) override;
|
|
virtual void applyTabChildProperties(vcl::Window* pParent, const std::vector<OUString>& rIDs,
|
|
std::vector<vcl::EnumContext::Context>& rContext, stringmap& rProperties,
|
|
stringmap& rAtkProperties) override;
|
|
|
|
void insertMenuObject(PopupMenu* pParent, PopupMenu* pSubMenu, const OUString& rClass,
|
|
const OUString& rID, stringmap& rProps, stringmap& rAtkProps,
|
|
accelmap& rAccels) override;
|
|
|
|
// if bToolbarItem=true, pParent is the ToolBox that the item belongs to, since there's no widget for the item itself
|
|
void applyAtkProperties(vcl::Window* pWindow, const stringmap& rProperties,
|
|
bool bToolbarItem) override;
|
|
|
|
void setMnemonicWidget(const OUString& rLabelId, const OUString& rMnemonicWidgetId) override;
|
|
void setPriority(vcl::Window* pWindow, int nPriority) override;
|
|
void setContext(vcl::Window* pWindow,
|
|
std::vector<vcl::EnumContext::Context>&& aContext) override;
|
|
|
|
virtual bool isHorizontalTabControl(vcl::Window* pWindow) override;
|
|
|
|
virtual VclPtr<PopupMenu> createMenu(const OUString& rID) override;
|
|
|
|
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) override;
|
|
|
|
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
|
|
void set_properties(vcl::Window *pWindow, const VclBuilder::stringmap &rProps);
|
|
|
|
//Convert _ gtk markup to ~ vcl markup
|
|
OUString convertMnemonicMarkup(std::u16string_view rIn);
|
|
|
|
OUString extractCustomProperty(VclBuilder::stringmap &rMap);
|
|
|
|
bool extractDropdown(VclBuilder::stringmap &rMap);
|
|
|
|
//add a default value of 25 width-chars to a map if width-chars not set
|
|
void ensureDefaultWidthChars(VclBuilder::stringmap &rMap);
|
|
|
|
//Helpers to retrofit all the existing code to the builder
|
|
void reorderWithinParent(std::vector< vcl::Window*>& rChilds, bool bIsButtonBox);
|
|
void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition);
|
|
|
|
//Convert an accessibility role name to accessibility role number
|
|
sal_Int16 getRoleFromName(const OUString& roleName);
|
|
}
|
|
|
|
//sID may not exist, but must be of type T if it does
|
|
template <typename T>
|
|
inline T* VclBuilder::get(std::u16string_view sID)
|
|
{
|
|
vcl::Window *w = get_by_name(sID);
|
|
SAL_WARN_IF(w && !dynamic_cast<T*>(w), "vcl.layout",
|
|
".ui widget \"" << OUStringToOString(sID, RTL_TEXTENCODING_UTF8)
|
|
<< "\" 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);
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|