Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  weld.hxx   Sprache: 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/.
 */


#ifndef INCLUDED_VCL_WELD_HXX
#define INCLUDED_VCL_WELD_HXX

#include <basegfx/range/b2irange.hxx>
#include <rtl/ustring.hxx>
#include <tools/color.hxx>
#include <tools/date.hxx>
#include <tools/fldunit.hxx>
#include <tools/gen.hxx>
#include <tools/link.hxx>
#include <vcl/dllapi.h>
#include <utility>
#include <vcl/vclenum.hxx>
#include <vcl/font.hxx>
#include <vcl/vclptr.hxx>
#include <vcl/uitest/factory.hxx>
#include <vcl/windowstate.hxx>

#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
#include <com/sun/star/accessibility/XAccessible.hpp>

#include <assert.h>
#include <memory>
#include <vector>

namespace com::sun::star::awt
{
class XWindow;
}
namespace com::sun::star::datatransfer::clipboard
{
class XClipboard;
}
namespace com::sun::star::datatransfer::dnd
{
class XDropTarget;
}
namespace com::sun::star::graphic
{
class XGraphic;
}
typedef css::uno::Reference<css::accessibility::XAccessible> a11yref;
typedef css::uno::Reference<css::accessibility::XAccessibleRelationSet> a11yrelationset;
enum class PointerStyle;
class CommandEvent;
class Formatter;
class InputContext;
class KeyEvent;
class MouseEvent;
class TransferDataContainer;
class OutputDevice;
class VirtualDevice;
struct SystemEnvData;
class BitmapEx;

namespace vcl
{
class ILibreOfficeKitNotifier;
typedef OutputDevice RenderContext;
}
namespace tools
{
class JsonWriter;
}

class LOKTrigger;

namespace weld
{
class Container;
class DialogController;

class VCL_DLLPUBLIC Widget
{
    friend class ::LOKTrigger;

protected:
    Link<Widget&, void> m_aFocusInHdl;
    Link<Widget&, void> m_aFocusOutHdl;
    Link<Widget&, bool> m_aMnemonicActivateHdl;
    Link<Widget&, void> m_aStyleUpdatedHdl;
    Link<const Size&, void> m_aSizeAllocateHdl;
    Link<const KeyEvent&, bool> m_aKeyPressHdl;
    Link<const KeyEvent&, bool> m_aKeyReleaseHdl;
    Link<const MouseEvent&, bool> m_aMousePressHdl;
    Link<const MouseEvent&, bool> m_aMouseMotionHdl;
    Link<const MouseEvent&, bool> m_aMouseReleaseHdl;

    void signal_focus_in() { m_aFocusInHdl.Call(*this); }
    void signal_focus_out() { m_aFocusOutHdl.Call(*this); }
    bool signal_mnemonic_activate() { return m_aMnemonicActivateHdl.Call(*this); }
    void signal_style_updated() { m_aStyleUpdatedHdl.Call(*this); }
    void signal_size_allocate(const Size& rSize) { m_aSizeAllocateHdl.Call(rSize); }
    bool signal_key_press(const KeyEvent& rKeyEvent) { return m_aKeyPressHdl.Call(rKeyEvent); }
    bool signal_key_release(const KeyEvent& rKeyEvent) { return m_aKeyReleaseHdl.Call(rKeyEvent); }
    bool signal_mouse_press(const MouseEvent& rMouseEvent)
    {
        return m_aMousePressHdl.Call(rMouseEvent);
    }
    bool signal_mouse_motion(const MouseEvent& rMouseEvent)
    {
        return m_aMouseMotionHdl.Call(rMouseEvent);
    }
    bool signal_mouse_release(const MouseEvent& rMouseEvent)
    {
        return m_aMouseReleaseHdl.Call(rMouseEvent);
    }

public:
    virtual void set_sensitive(bool sensitive) = 0;
    virtual bool get_sensitive() const = 0;

    /* visibility */

    virtual void show() = 0;
    virtual void hide() = 0;

    // This function simply calls show() or hide() but is convenient when the
    // visibility depends on some condition
    virtual void set_visible(bool visible)
    {
        if (visible)
            show();
        else
            hide();
    }

    // return if this widget's visibility is true
    virtual bool get_visible() const = 0;

    // return if this widget's visibility and that of all its parents is true
    virtual bool is_visible() const = 0;

    /* focus */

    // sets if this widget can own the keyboard focus
    virtual void set_can_focus(bool bCanFocus) = 0;

    // causes this widget to have the keyboard focus
    virtual void grab_focus() = 0;

    // returns if this widget has the keyboard focus
    virtual bool has_focus() const = 0;

    // if the widget that has focus is a child, which includes toplevel popup
    // children, of this widget. So an Entry with an active popup (or dialog)
    // has has_child_focus of true, but has_focus of false, while its popup is
    // shown
    virtual bool has_child_focus() const = 0;

    // return if this widget has the keyboard focus within the active window
    // TODO: review if this has any practical difference from has_focus()
    virtual bool is_active() const = 0;

    /* size */
    virtual void set_size_request(int nWidth, int nHeight) = 0;
    virtual Size get_size_request() const = 0;
    virtual Size get_preferred_size() const = 0;

    /* measure */
    virtual float get_approximate_digit_width() const = 0;
    virtual int get_text_height() const = 0;
    virtual Size get_pixel_size(const OUString& rText) const = 0;

    // The name of the widget in the GtkBuilder UI definition used to construct it.
    virtual OUString get_buildable_name() const = 0;
    /*
       Typically there is no need to change the buildable name at runtime, changing
       the id in .ui file itself is preferred.

       But for ui-testing purposes it can sometimes be useful to rename
       different widgets, that were loaded from the same .ui, to unique names
       in order to distinguish between them
    */

    virtual void set_buildable_name(const OUString& rName) = 0;

    /*
      The help id of the widget used to identify help for this widget.

      By default the help id of a widget is a path-like sequence of (load-time)
      buildable-names from the widgets UI definition ancestor to this widget,
      e.g. grandparent/parent/widget.

      The default can be overwritten with set_help_id
    */

    virtual OUString get_help_id() const = 0;
    virtual void set_help_id(const OUString& rName) = 0;

    virtual void set_hexpand(bool bExpand) = 0;
    virtual bool get_hexpand() const = 0;
    virtual void set_vexpand(bool bExpand) = 0;
    virtual bool get_vexpand() const = 0;

    virtual void set_margin_top(int nMargin) = 0;
    virtual void set_margin_bottom(int nMargin) = 0;
    virtual void set_margin_start(int nMargin) = 0;
    virtual void set_margin_end(int nMargin) = 0;

    virtual int get_margin_top() const = 0;
    virtual int get_margin_bottom() const = 0;
    virtual int get_margin_start() const = 0;
    virtual int get_margin_end() const = 0;

    /*
     * Report the extents of this widget relative to the rRelative target widget.
     *
     * To succeed, both widgets must be realized, and must share a common toplevel.
     *
     * returns false if the relative extents could not be determined, e.g. if
     * either widget was not realized, or there was no common ancestor.
     * Otherwise true.
     */

    virtual bool get_extents_relative_to(const Widget& rRelative, int& x, int& yint& width,
                                         int& height) const = 0;

    virtual void set_accessible_name(const OUString& rName) = 0;
    virtual void set_accessible_description(const OUString& rDescription) = 0;
    virtual OUString get_accessible_name() const = 0;

    virtual OUString get_accessible_description() const = 0;

    virtual OUString get_accessible_id() const = 0;

    // After this call this widget is only accessibility labelled by pLabel and
    // pLabel only accessibility labels this widget
    virtual void set_accessible_relation_labeled_by(weld::Widget* pLabel) = 0;

    virtual void set_tooltip_text(const OUString& rTip) = 0;
    virtual OUString get_tooltip_text() const = 0;

    virtual void set_cursor_data(void* pData) = 0;

    virtual void connect_focus_in(const Link<Widget&, void>& rLink)
    {
        assert(!m_aFocusInHdl.IsSet() || !rLink.IsSet());
        m_aFocusInHdl = rLink;
    }

    virtual void connect_focus_out(const Link<Widget&, void>& rLink)
    {
        assert(!m_aFocusOutHdl.IsSet() || !rLink.IsSet());
        m_aFocusOutHdl = rLink;
    }

    // rLink is called when the mnemonic for the Widget is called.
    // If rLink returns true the Widget will not automatically gain
    // focus as normally occurs
    virtual void connect_mnemonic_activate(const Link<Widget&, bool>& rLink)
    {
        assert(!m_aMnemonicActivateHdl.IsSet() || !rLink.IsSet());
        m_aMnemonicActivateHdl = rLink;
    }

    virtual void connect_size_allocate(const Link<const Size&, void>& rLink)
    {
        assert(!m_aSizeAllocateHdl.IsSet() || !rLink.IsSet());
        m_aSizeAllocateHdl = rLink;
    }

    virtual void connect_key_press(const Link<const KeyEvent&, bool>& rLink)
    {
        assert(!m_aKeyPressHdl.IsSet() || !rLink.IsSet());
        m_aKeyPressHdl = rLink;
    }

    virtual void connect_key_release(const Link<const KeyEvent&, bool>& rLink)
    {
        assert(!m_aKeyReleaseHdl.IsSet() || !rLink.IsSet());
        m_aKeyReleaseHdl = rLink;
    }

    virtual void connect_mouse_press(const Link<const MouseEvent&, bool>& rLink)
    {
        assert(!m_aMousePressHdl.IsSet() || !rLink.IsSet());
        m_aMousePressHdl = rLink;
    }

    virtual void connect_mouse_move(const Link<const MouseEvent&, bool>& rLink)
    {
        assert(!m_aMouseMotionHdl.IsSet() || !rLink.IsSet());
        m_aMouseMotionHdl = rLink;
    }

    virtual void connect_mouse_release(const Link<const MouseEvent&, bool>& rLink)
    {
        assert(!m_aMouseReleaseHdl.IsSet() || !rLink.IsSet());
        m_aMouseReleaseHdl = rLink;
    }

    virtual void connect_style_updated(const Link<Widget&, void>& rLink)
    {
        assert(!m_aStyleUpdatedHdl.IsSet() || !rLink.IsSet());
        m_aStyleUpdatedHdl = rLink;
    }

    virtual void grab_mouse() = 0;
    virtual bool has_mouse_grab() const = 0;
    virtual void release_mouse() = 0;

    // font size is in points, not pixels, e.g. see Window::[G]etPointFont
    virtual vcl::Font get_font() = 0;

    //true for rtl, false otherwise
    virtual bool get_direction() const = 0;
    virtual void set_direction(bool bRTL) = 0;

    /* Increases the freeze count on widget.

       If the freeze count is non-zero, emission of the widget's notifications
       is stopped. The notifications are queued until the freeze count is
       decreased to zero. Duplicate notifications may be squashed together.
    */

    virtual void freeze() = 0;

    /* Reverts the effect of a previous call to freeze.

       The freeze count is decreased on the widget and when it reaches zero,
       queued notifications are emitted.
    */

    virtual void thaw() = 0;

    /* push/pop busy mouse cursor state

      bBusy of true to push a busy state onto the stack and false
      to pop it off, calls to this should balance.

      see weld::WaitObject */

    virtual void set_busy_cursor(bool bBusy) = 0;

    virtual void queue_resize() = 0;

    virtual std::unique_ptr<Container> weld_parent() const = 0;

    //iterate upwards through the hierarchy starting at this widgets parent,
    //calling func with their helpid until func returns true or we run out of
    //parents
    virtual void help_hierarchy_foreach(const std::function<bool(const OUString&)>& func) = 0;

    virtual OUString strip_mnemonic(const OUString& rLabel) const = 0;

    /* Escapes string contents which are interpreted by the UI.

       Should be overwritten by each VCL implementation to account for the
       string contents which are interpreted by its ui.
    */

    virtual OUString escape_ui_str(const OUString& rLabel) const = 0;

    virtual VclPtr<VirtualDevice> create_virtual_device() const = 0;

    //do something transient to attract the attention of the user to the widget
    virtual void call_attention_to() = 0;

    //make this widget look like a page in a notebook
    virtual void set_stack_background() = 0;
    //make this widget look like it has a highlighted background
    virtual void set_highlight_background() = 0;
    //make this widget suitable as parent for a title
    virtual void set_title_background() = 0;
    //make this widget suitable for use in a toolbar
    virtual void set_toolbar_background() = 0;
    //trying to use a custom color for a background is generally a bad idea. If your need
    //fits one of the above categories then that's a somewhat better choice
    virtual void set_background(const Color& rBackColor) = 0;
    // reset to default background
    virtual void set_background() = 0;

    virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() = 0;
    virtual css::uno::Reference<css::datatransfer::clipboard::XClipboard> get_clipboard(const = 0;

    virtual void connect_get_property_tree(const Link<tools::JsonWriter&, void>& rLink) = 0;
    virtual void get_property_tree(tools::JsonWriter& rJsonWriter) = 0;

    // render the widget to an output device
    virtual void draw(OutputDevice& rOutput, const Point& rPos, const Size& rSizePixel) = 0;

    virtual ~Widget() {}
};

class VCL_DLLPUBLIC Container : virtual public Widget
{
    Link<Container&, void> m_aContainerFocusChangedHdl;

protected:
    void signal_container_focus_changed() { m_aContainerFocusChangedHdl.Call(*this); }

public:
    // remove from old container and add to new container in one go
    // new container can be null to just remove from old container
    virtual void move(weld::Widget* pWidget, weld::Container* pNewParent) = 0;
    // create an XWindow as a child of this container. The XWindow is
    // suitable to contain css::awt::XControl items
    virtual css::uno::Reference<css::awt::XWindow> CreateChildFrame() = 0;
    // rLink is called when the focus transitions from a widget outside the container
    // to a widget inside the container or vice versa
    virtual void connect_container_focus_changed(const Link<Container&, void>& rLink)
    {
        m_aContainerFocusChangedHdl = rLink;
    }
    // causes a child of the container to have the keyboard focus
    virtual void child_grab_focus() = 0;
};

class VCL_DLLPUBLIC Box : virtual public Container
{
public:
    // Moves child to a new position in the list of children
    virtual void reorder_child(weld::Widget* pWidget, int position) = 0;
    // Sort ok/cancel etc buttons in platform order
    virtual void sort_native_button_order() = 0;
};

class VCL_DLLPUBLIC Grid : virtual public Container
{
public:
    virtual void set_child_left_attach(weld::Widget& rWidget, int nAttach) = 0;
    virtual int get_child_left_attach(weld::Widget& rWidget) const = 0;
    virtual void set_child_column_span(weld::Widget& rWidget, int nCols) = 0;
    virtual void set_child_top_attach(weld::Widget& rWidget, int nAttach) = 0;
    virtual int get_child_top_attach(weld::Widget& rWidget) const = 0;
};

class VCL_DLLPUBLIC Paned : virtual public Container
{
public:
    // set pixel position of divider
    virtual void set_position(int nPos) = 0;
    // get pixel position of divider
    virtual int get_position() const = 0;
};

class VCL_DLLPUBLIC ScrolledWindow : virtual public Container
{
    friend class ::LOKTrigger;

    Link<ScrolledWindow&, void> m_aVChangeHdl;
    Link<ScrolledWindow&, void> m_aHChangeHdl;

protected:
    void signal_vadjustment_changed() { m_aVChangeHdl.Call(*this); }
    void signal_hadjustment_changed() { m_aHChangeHdl.Call(*this); }

public:
    virtual void hadjustment_configure(int value, int lower, int upper, int step_increment,
                                       int page_increment, int page_size)
        = 0;
    virtual int hadjustment_get_value() const = 0;
    virtual void hadjustment_set_value(int value) = 0;
    virtual int hadjustment_get_upper() const = 0;
    virtual void hadjustment_set_upper(int upper) = 0;
    virtual int hadjustment_get_page_size() const = 0;
    virtual void hadjustment_set_page_size(int size) = 0;
    virtual void hadjustment_set_page_increment(int size) = 0;
    virtual void hadjustment_set_step_increment(int size) = 0;
    virtual void set_hpolicy(VclPolicyType eHPolicy) = 0;
    virtual VclPolicyType get_hpolicy() const = 0;
    void connect_hadjustment_changed(const Link<ScrolledWindow&, void>& rLink)
    {
        m_aHChangeHdl = rLink;
    }

    virtual void vadjustment_configure(int value, int lower, int upper, int step_increment,
                                       int page_increment, int page_size)
        = 0;
    virtual int vadjustment_get_value() const = 0;
    virtual void vadjustment_set_value(int value) = 0;
    virtual int vadjustment_get_upper() const = 0;
    virtual void vadjustment_set_upper(int upper) = 0;
    virtual int vadjustment_get_page_size() const = 0;
    virtual void vadjustment_set_page_size(int size) = 0;
    virtual void vadjustment_set_page_increment(int size) = 0;
    virtual void vadjustment_set_step_increment(int size) = 0;
    virtual int vadjustment_get_lower() const = 0;
    virtual void vadjustment_set_lower(int lower) = 0;
    virtual void set_vpolicy(VclPolicyType eVPolicy) = 0;
    virtual VclPolicyType get_vpolicy() const = 0;
    void connect_vadjustment_changed(const Link<ScrolledWindow&, void>& rLink)
    {
        m_aVChangeHdl = rLink;
    }
    virtual int get_scroll_thickness() const = 0;
    virtual void set_scroll_thickness(int nThickness) = 0;

    //trying to use custom color for a scrollbar is generally a bad idea.
    virtual void customize_scrollbars(const Color& rBackgroundColor, const Color& rShadowColor,
                                      const Color& rFaceColor)
        = 0;
};

class Label;

class VCL_DLLPUBLIC Frame : virtual public Container
{
public:
    virtual void set_label(const OUString& rText) = 0;
    virtual OUString get_label() const = 0;
    virtual std::unique_ptr<Label> weld_label_widget() const = 0;
};

class VCL_DLLPUBLIC Notebook : virtual public Widget
{
    friend class ::LOKTrigger;

protected:
    Link<const OUString&, bool> m_aLeavePageHdl;
    Link<const OUString&, void> m_aEnterPageHdl;

public:
    virtual int get_current_page() const = 0;
    virtual int get_page_index(const OUString& rIdent) const = 0;
    virtual OUString get_page_ident(int nPage) const = 0;
    virtual OUString get_current_page_ident() const = 0;
    virtual void set_current_page(int nPage) = 0;
    virtual void set_current_page(const OUString& rIdent) = 0;
    virtual void remove_page(const OUString& rIdent) = 0;
    virtual void insert_page(const OUString& rIdent, const OUString& rLabel, int nPos) = 0;
    void append_page(const OUString& rIdent, const OUString& rLabel)
    {
        insert_page(rIdent, rLabel, -1);
    }
    virtual void set_tab_label_text(const OUString& rIdent, const OUString& rLabel) = 0;
    virtual OUString get_tab_label_text(const OUString& rIdent) const = 0;
    virtual void set_show_tabs(bool bShow) = 0;
    virtual int get_n_pages() const = 0;
    virtual weld::Container* get_page(const OUString& rIdent) const = 0;

    void connect_leave_page(const Link<const OUString&, bool>& rLink) { m_aLeavePageHdl = rLink; }
    void connect_enter_page(const Link<const OUString&, void>& rLink) { m_aEnterPageHdl = rLink; }
};

class VCL_DLLPUBLIC ScreenShotEntry
{
public:
    ScreenShotEntry(OUString aHelpId, const basegfx::B2IRange& rB2IRange)
        : msHelpId(std::move(aHelpId))
        , maB2IRange(rB2IRange)
    {
    }

    const basegfx::B2IRange& getB2IRange() const { return maB2IRange; }

    const OUString& GetHelpId() const { return msHelpId; }

private:
    OUString msHelpId;
    basegfx::B2IRange maB2IRange;
};

typedef std::vector<ScreenShotEntry> ScreenShotCollection;

class VCL_DLLPUBLIC Window : virtual public Container
{
protected:
    Link<Widget&, bool> m_aHelpRequestHdl;

public:
    virtual void set_title(const OUString& rTitle) = 0;
    virtual OUString get_title() const = 0;
    virtual void window_move(int x, int y) = 0;
    virtual bool get_resizable() const = 0;
    virtual Size get_size() const = 0;
    virtual Point get_position() const = 0;
    virtual AbsoluteScreenPixelRectangle get_monitor_workarea() const = 0;

    // returns whether the widget that has focus is within this Window
    // (its very possible to move this to weld::Container if that becomes
    // desirable)
    virtual bool has_toplevel_focus() const = 0;
    virtual void present() = 0;

    // with pOld of null, automatically find the old default widget and unset
    // it, otherwise use as hint to the old default
    virtual void change_default_widget(weld::Widget* pOld, weld::Widget* pNew) = 0;
    virtual bool is_default_widget(const weld::Widget* pCandidate) const = 0;

    virtual void set_window_state(const OUString& rStr) = 0;
    virtual OUString get_window_state(vcl::WindowDataMask nMask) const = 0;

    virtual css::uno::Reference<css::awt::XWindow> GetXWindow() = 0;

    void connect_help(const Link<Widget&, bool>& rLink) { m_aHelpRequestHdl = rLink; }

    virtual SystemEnvData get_system_data() const = 0;

    virtual void resize_to_request() = 0;

    // collect positions of widgets and their help ids for screenshot purposes
    virtual ScreenShotCollection collect_screenshot_data() = 0;

    // render the widget to an output device
    virtual VclPtr<VirtualDevice> screenshot() = 0;

    virtual const vcl::ILibreOfficeKitNotifier* GetLOKNotifier() = 0;
};

class VCL_DLLPUBLIC WaitObject
{
private:
    weld::Widget* m_pWindow;

public:
    WaitObject(weld::Widget* pWindow)
        : m_pWindow(pWindow)
    {
        if (m_pWindow)
            m_pWindow->set_busy_cursor(true);
    }
    ~WaitObject()
    {
        if (m_pWindow)
            m_pWindow->set_busy_cursor(false);
    }
};

class Button;

class VCL_DLLPUBLIC Dialog : virtual public Window
{
private:
    friend DialogController;
    virtual bool runAsync(std::shared_ptr<DialogController> const& rxOwner,
                          const std::function<void(sal_Int32)>& func)
        = 0;

public:
    virtual void set_modal(bool bModal) = 0;
    virtual bool get_modal() const = 0;

    // center dialog on its parent
    //
    // bTrackGeometryRequests set to true tries to ensure the dialog will end
    // up still centered on its parent windows final size, taking into account
    // that there may currently be pending geometry requests for the parent not
    // yet processed by the underlying toolkit
    //
    // for e.g gtk this will means the dialog is always centered even when
    // resized, calling set_centered_on_parent with false will turn this
    // off again.
    virtual void set_centered_on_parent(bool bTrackGeometryRequests) = 0;

    virtual int run() = 0;
    // Run async without a controller
    // @param self - must point to this, to enforce that the dialog was created/held by a shared_ptr
    virtual bool runAsync(std::shared_ptr<Dialog> const& rxSelf,
                          const std::function<void(sal_Int32)>& func)
        = 0;
    virtual void response(int response) = 0;
    virtual void add_button(const OUString& rText, int response, const OUString& rHelpId = {}) = 0;
    virtual void set_default_response(int response) = 0;
    virtual std::unique_ptr<Button> weld_button_for_response(int response) = 0;
    virtual std::unique_ptr<weld::Container> weld_content_area() = 0;

    // shrink the dialog down to shown just these widgets
    virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) = 0;
    // undo previous dialog collapse
    virtual void undo_collapse() = 0;

    virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>&&nbsp;rLink)
        = 0;
};

class VCL_DLLPUBLIC MessageDialog : virtual public Dialog
{
public:
    virtual void set_primary_text(const OUString& rText) = 0;
    virtual OUString get_primary_text() const = 0;
    virtual void set_secondary_text(const OUString& rText) = 0;
    virtual OUString get_secondary_text() const = 0;
    virtual std::unique_ptr<Container> weld_message_area() = 0;
};

class VCL_DLLPUBLIC Assistant : virtual public Dialog
{
    Link<const OUString&, bool> m_aJumpPageHdl;

protected:
    bool signal_jump_page(const OUString& rIdent) { return m_aJumpPageHdl.Call(rIdent); }

public:
    virtual int get_current_page() const = 0;
    virtual int get_n_pages() const = 0;
    virtual OUString get_page_ident(int nPage) const = 0;
    virtual OUString get_current_page_ident() const = 0;
    virtual void set_current_page(int nPage) = 0;
    virtual void set_current_page(const OUString& rIdent) = 0;
    // move the page rIdent to position nIndex
    virtual void set_page_index(const OUString& rIdent, int nIndex) = 0;
    virtual void set_page_title(const OUString& rIdent, const OUString& rTitle) = 0;
    virtual OUString get_page_title(const OUString& rIdent) const = 0;
    virtual void set_page_sensitive(const OUString& rIdent, bool bSensitive) = 0;
    virtual weld::Container* append_page(const OUString& rIdent) = 0;

    virtual void set_page_side_help_id(const OUString& rHelpId) = 0;

    virtual void set_page_side_image(const OUString& rImage) = 0;

    void connect_jump_page(const Link<const OUString&, bool>& rLink) { m_aJumpPageHdl = rLink; }
};

inline OUString toId(const void* pValue)
{
    return OUString::number(reinterpret_cast<sal_uIntPtr>(pValue));
}

template <typename T> T fromId(const OUString& rValue)
{
    return reinterpret_cast<T>(rValue.toUInt64());
}

struct VCL_DLLPUBLIC ComboBoxEntry
{
    OUString sString;
    OUString sId;
    OUString sImage;
    ComboBoxEntry(OUString _aString)
        : sString(std::move(_aString))
    {
    }
    ComboBoxEntry(OUString _aString, OUString _aId)
        : sString(std::move(_aString))
        , sId(std::move(_aId))
    {
    }
    ComboBoxEntry(OUString _aString, OUString _aId, OUString _aImage)
        : sString(std::move(_aString))
        , sId(std::move(_aId))
        , sImage(std::move(_aImage))
    {
    }
};

enum class EntryMessageType
{
    Normal,
    Warning,
    Error,
};

class Menu;

/// A widget used to choose from a list of items.
class VCL_DLLPUBLIC ComboBox : virtual public Widget
{
private:
    OUString m_sSavedValue;
    std::vector<OUString> m_aSavedValues;

public:
    // OUString is the id of the row, it may be null to measure the height of a generic line
    typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, boolconst OUString&>
        render_args;

protected:
    Link<ComboBox&, void> m_aChangeHdl;
    Link<ComboBox&, void> m_aPopupToggledHdl;
    Link<ComboBox&, bool> m_aEntryActivateHdl;
    Link<OUString&, bool> m_aEntryInsertTextHdl;

    friend class ::LOKTrigger;

    void signal_changed() { m_aChangeHdl.Call(*this); }

    virtual void signal_popup_toggled() { m_aPopupToggledHdl.Call(*this); }

    Link<render_args, void> m_aRenderHdl;
    void signal_custom_render(vcl::RenderContext& rDevice, const tools::Rectangle&&nbsp;rRect,
                              bool bSelected, const OUString& rId)
    {
        m_aRenderHdl.Call(render_args(rDevice, rRect, bSelected, rId));
    }

    Link<vcl::RenderContext&, Size> m_aGetSizeHdl;
    Size signal_custom_get_size(vcl::RenderContext& rDevice) { return m_aGetSizeHdl.Call(rDevice); }

public:
    virtual void insert(int pos, const OUString& rStr, const OUString* pId,
                        const OUString* pIconName, VirtualDevice* pImageSurface)
        = 0;
    virtual void insert_vector(const std::vector<weld::ComboBoxEntry>& rItems, bool bKeepExisting)
        = 0;
    void insert(int pos, const weld::ComboBoxEntry& rItem)
    {
        insert(pos, rItem.sString, rItem.sId.isEmpty() ? nullptr : &rItem.sId,
               rItem.sImage.isEmpty() ? nullptr : &rItem.sImage, nullptr);
    }
    void insert_text(int pos, const OUString& rStr)
    {
        insert(pos, rStr, nullptr, nullptr, nullptr);
    }
    void append(const weld::ComboBoxEntry& rItem) { insert(-1, rItem); }
    void append_text(const OUString& rStr) { insert(-1, rStr, nullptr, nullptr, nullptr); }
    void append(const OUString& rId, const OUString& rStr)
    {
        insert(-1, rStr, &rId, nullptr, nullptr);
    }
    void append(const OUString& rId, const OUString& rStr, const OUString& rImage)
    {
        insert(-1, rStr, &rId, &rImage, nullptr);
    }
    void append(const OUString& rId, const OUString& rStr, VirtualDevice& rImage)
    {
        insert(-1, rStr, &rId, nullptr, &rImage);
    }
    void append(int pos, const OUString& rId, const OUString& rStr)
    {
        insert(pos, rStr, &rId, nullptr, nullptr);
    }
    virtual void insert_separator(int pos, const OUString& rId) = 0;
    void append_separator(const OUString& rId) { insert_separator(-1, rId); }

    virtual int get_count() const = 0;
    virtual void make_sorted() = 0;
    virtual void clear() = 0;

    //by index, returns -1 if nothing is selected
    virtual int get_active() const = 0;
    virtual void set_active(int pos) = 0;
    virtual void remove(int pos) = 0;

    //by text
    virtual OUString get_active_text() const = 0;
    void set_active_text(const OUString& rStr) { set_active(find_text(rStr)); }
    virtual OUString get_text(int pos) const = 0;
    virtual int find_text(const OUString& rStr) const = 0;
    void remove_text(const OUString& rText) { remove(find_text(rText)); }

    //by id
    virtual OUString get_active_id() const = 0;
    virtual void set_active_id(const OUString& rStr) = 0;
    virtual OUString get_id(int pos) const = 0;
    virtual void set_id(int row, const OUString& rId) = 0;
    virtual int find_id(const OUString& rId) const = 0;
    void remove_id(const OUString& rId) { remove(find_id(rId)); }

    /* m_aChangeHdl is called when the active item is changed. The can be due
       to the user selecting a different item from the list or while typing
       into the entry of a combo box with an entry.

       Use changed_by_direct_pick() to discover whether an item was actually explicitly
       selected, e.g. from the menu.
     */

    void connect_changed(const Link<ComboBox&, void>& rLink) { m_aChangeHdl = rLink; }

    virtual bool changed_by_direct_pick() const = 0;

    virtual void connect_popup_toggled(const Link<ComboBox&, void>& rLink)
    {
        m_aPopupToggledHdl = rLink;
    }

    //entry related
    virtual bool has_entry() const = 0;
    virtual void set_entry_message_type(EntryMessageType eType) = 0;
    virtual void set_entry_text(const OUString& rStr) = 0;
    virtual void set_entry_width_chars(int nChars) = 0;
    virtual void set_entry_max_length(int nChars) = 0;
    virtual void select_entry_region(int nStartPos, int nEndPos) = 0;
    virtual bool get_entry_selection_bounds(int& rStartPos, int& rEndPos) = 0;
    virtual void set_entry_completion(bool bEnable, bool bCaseSensitive = false) = 0;
    virtual void set_entry_placeholder_text(const OUString& rText) = 0;
    virtual void set_entry_editable(bool bEditable) = 0;
    virtual void cut_entry_clipboard() = 0;
    virtual void copy_entry_clipboard() = 0;
    virtual void paste_entry_clipboard() = 0;

    // font size is in points, not pixels, e.g. see Window::[G]etPointFont
    virtual void set_font(const vcl::Font& rFont) = 0;

    // font size is in points, not pixels, e.g. see Window::[G]etPointFont
    virtual void set_entry_font(const vcl::Font& rFont) = 0;
    virtual vcl::Font get_entry_font() = 0;

    virtual bool get_popup_shown() const = 0;

    void connect_entry_insert_text(const Link<OUString&, bool>& rLink)
    {
        m_aEntryInsertTextHdl = rLink;
    }

    // callback returns true to indicated no further processing of activate wanted
    void connect_entry_activate(const Link<ComboBox&, bool>& rLink) { m_aEntryActivateHdl = rLink; }

    void save_value() { m_sSavedValue = get_active_text(); }

    void save_values_by_id(const OUString& rId)
    {
        m_aSavedValues.push_back(get_text(find_id(rId)));
    }

    OUString const& get_saved_value() const { return m_sSavedValue; }
    OUString const& get_saved_values(int pos) const { return m_aSavedValues[pos]; }
    bool get_value_changed_from_saved() const { return m_sSavedValue != get_active_text(); }
    bool get_values_changed_from_saved() const
    {
        return !m_aSavedValues.empty()
               && std::find(m_aSavedValues.begin(), m_aSavedValues.end(), get_active_text())
                      == m_aSavedValues.end();
    }

    void removeSavedValues() { m_aSavedValues.clear(); }

    // for custom rendering a row
    void connect_custom_get_size(const Link<vcl::RenderContext&, Size>& rLink)
    {
        m_aGetSizeHdl = rLink;
    }
    void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; }
    // call set_custom_renderer after setting custom callbacks
    virtual void set_custom_renderer(bool bOn) = 0;
    // create a virtual device compatible with the device passed in render_args wrt alpha
    virtual VclPtr<VirtualDevice> create_render_virtual_device() const = 0;
    // set a sub menu for a entry, only works with custom rendering
    virtual void set_item_menu(const OUString& rIdent, weld::Menu* pMenu) = 0;
    // get the width needed to show the menu launcher in a custom row
    virtual int get_menu_button_width() const = 0;

    // for mru support
    virtual int get_max_mru_count() const = 0;
    virtual void set_max_mru_count(int nCount) = 0;
    virtual OUString get_mru_entries() const = 0;
    virtual void set_mru_entries(const OUString& rEntries) = 0;

    // Backwards compatibility, should be avoided to allow
    // UI consistency.
    virtual void set_max_drop_down_rows(int nRows) = 0;
};

enum class ColumnToggleType
{
    Check,
    Radio
};

class VCL_DLLPUBLIC TreeIter
{
private:
    TreeIter(const TreeIter&) = delete;
    TreeIter& operator=(const TreeIter&) = delete;

public:
    TreeIter() {}
    virtual bool equal(const TreeIter& rOther) const = 0;
    virtual ~TreeIter() {}
};

/* Model column indexes are considered to begin at 0, but with special columns
   before index 0. A expander image column (and an additional optional toggle
   button column when enable_toggle_buttons is used). Column index -1 is
   reserved to access those columns.
*/

class VCL_DLLPUBLIC TreeView : virtual public Widget
{
    friend class ::LOKTrigger;

public:
    typedef std::pair<const TreeIter&, int> iter_col;
    typedef std::pair<const TreeIter&, OUString> iter_string;
    // OUString is the id of the row, it may be null to measure the height of a generic line
    typedef std::pair<vcl::RenderContext&, const OUString&> get_size_args;
    typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, boolconst OUString&>
        render_args;

private:
    OUString m_sSavedValue;

protected:
    Link<TreeView&, void> m_aSelectionChangedHdl;
    Link<TreeView&, bool> m_aRowActivatedHdl;
    Link<intvoid> m_aColumnClickedHdl;
    Link<const iter_col&, void> m_aRadioToggleHdl;
    Link<const TreeIter&, bool> m_aEditingStartedHdl;
    Link<const iter_string&, bool> m_aEditingDoneHdl;
    // if handler returns false, the expansion of the row is refused
    Link<const TreeIter&, bool> m_aExpandingHdl;
    // if handler returns false, the collapse of the row is refused
    Link<const TreeIter&, bool> m_aCollapsingHdl;
    Link<TreeView&, void> m_aVisibleRangeChangedHdl;
    Link<TreeView&, void> m_aModelChangedHdl;
    // if handler returns true, then menu has been show and event is consumed
    Link<const CommandEvent&, bool> m_aPopupMenuHdl;
    // if handler returns true, drag is disallowed, consumer can change bool
    // arg to false to disable the treeview default dnd icon
    Link<bool&, bool> m_aDragBeginHdl;
    std::function<int(const weld::TreeIter&, const weld::TreeIter&)> m_aCustomSort;

protected:
    void signal_selection_changed() { m_aSelectionChangedHdl.Call(*this); }
    bool signal_row_activated() { return m_aRowActivatedHdl.Call(*this); }
    void signal_column_clicked(int nColumn) { m_aColumnClickedHdl.Call(nColumn); }
    bool signal_expanding(const TreeIter& rIter)
    {
        return !m_aExpandingHdl.IsSet() || m_aExpandingHdl.Call(rIter);
    }
    bool signal_collapsing(const TreeIter& rIter)
    {
        return !m_aCollapsingHdl.IsSet() || m_aCollapsingHdl.Call(rIter);
    }
    void signal_visible_range_changed() { m_aVisibleRangeChangedHdl.Call(*this); }
    void signal_model_changed() { m_aModelChangedHdl.Call(*this); }

    void signal_toggled(const iter_col& rIterCol) { m_aRadioToggleHdl.Call(rIterCol); }

    bool signal_editing_started(const TreeIter& rIter) { return m_aEditingStartedHdl.Call(rIter); }

    bool signal_editing_done(const iter_string& rIterText)
    {
        return m_aEditingDoneHdl.Call(rIterText);
    }

    void signal_popup_menu(const CommandEvent& rCommand) { m_aPopupMenuHdl.Call(rCommand); }

    Link<const TreeIter&, OUString> m_aQueryTooltipHdl;
    OUString signal_query_tooltip(const TreeIter& rIter) { return m_aQueryTooltipHdl.Call(rIter); }

    Link<render_args, void> m_aRenderHdl;
    void signal_custom_render(vcl::RenderContext& rDevice, const tools::Rectangle&&nbsp;rRect,
                              bool bSelected, const OUString& rId)
    {
        m_aRenderHdl.Call(render_args(rDevice, rRect, bSelected, rId));
    }

    Link<get_size_args, Size> m_aGetSizeHdl;
    Size signal_custom_get_size(vcl::RenderContext& rDevice, const OUString& rId)
    {
        return m_aGetSizeHdl.Call(get_size_args(rDevice, rId));
    }

public:
    virtual void connect_query_tooltip(const Link<const TreeIter&, OUString>& rLink)
    {
        assert(!m_aQueryTooltipHdl.IsSet() || !rLink.IsSet());
        m_aQueryTooltipHdl = rLink;
    }

    // see 'expanding on-demand node details' for bChildrenOnDemand of true
    virtual void insert(const TreeIter* pParent, int pos, const OUString* pStr, const OUString* pId,
                        const OUString* pIconName, VirtualDevice* pImageSurface,
                        bool bChildrenOnDemand, TreeIter* pRet)
        = 0;

    void insert(int nRow, TreeIter* pRet = nullptr)
    {
        insert(nullptr, nRow, nullptr, nullptr, nullptr, nullptr, false, pRet);
    }

    void append(TreeIter* pRet = nullptr) { insert(-1, pRet); }

    void insert(int pos, const OUString& rStr, const OUString* pId, const OUString* pIconName,
                VirtualDevice* pImageSurface)
    {
        insert(nullptr, pos, &rStr, pId, pIconName, pImageSurface, false, nullptr);
    }
    void insert_text(int pos, const OUString& rStr)
    {
        insert(nullptr, pos, &rStr, nullptr, nullptr, nullptr, false, nullptr);
    }
    void append_text(const OUString& rStr)
    {
        insert(nullptr, -1, &rStr, nullptr, nullptr, nullptr, false, nullptr);
    }
    void append(const OUString& rId, const OUString& rStr)
    {
        insert(nullptr, -1, &rStr, &rId, nullptr, nullptr, false, nullptr);
    }
    void append(const OUString& rId, const OUString& rStr, const OUString& rImage)
    {
        insert(nullptr, -1, &rStr, &rId, &rImage, nullptr, false, nullptr);
    }
    void append(const TreeIter* pParent, const OUString& rStr)
    {
        insert(pParent, -1, &rStr, nullptr, nullptr, nullptr, false, nullptr);
    }

    virtual void insert_separator(int pos, const OUString& rId) = 0;
    void append_separator(const OUString& rId) { insert_separator(-1, rId); }

    void connect_selection_changed(const Link<TreeView&, void>& rLink)
    {
        m_aSelectionChangedHdl = rLink;
    }

    /* A row is "activated" when the user double clicks a treeview row. It may
       also be emitted when a row is selected and Space or Enter is pressed.

       a return of "true" means the activation has been handled, a "false" propagates
       the activation to the default handler which expands/collapses the row, if possible.
    */

    void connect_row_activated(const Link<TreeView&, bool>& rLink) { m_aRowActivatedHdl = rLink; }

    // Argument is a pair of iter, col describing the toggled node
    void connect_toggled(const Link<const iter_col&, void>& rLink) { m_aRadioToggleHdl = rLink; }

    void connect_column_clicked(const Link<intvoid>& rLink) { m_aColumnClickedHdl = rLink; }
    void connect_model_changed(const Link<TreeView&, void>& rLink) { m_aModelChangedHdl = rLink; }

    virtual OUString get_selected_text() const = 0;
    virtual OUString get_selected_id() const = 0;

    // call before inserting any content and connecting to toggle signals,
    // an pre-inserted checkbutton column will exist at the start of every row
    // inserted after this call which can be accessed with col index -1
    virtual void enable_toggle_buttons(ColumnToggleType eType) = 0;

    virtual void set_clicks_to_toggle(int nToggleBehavior) = 0;

    //by index
    virtual int get_selected_index() const = 0;
    //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    virtual void select(int pos) = 0;
    virtual void unselect(int pos) = 0;
    virtual void remove(int pos) = 0;
    // col index -1 gets the first text column
    virtual OUString get_text(int row, int col = -1) const = 0;
    // col index -1 sets the first text column
    virtual void set_text(int row, const OUString& rText, int col = -1) = 0;
    // col index -1 sets all columns
    virtual void set_sensitive(int row, bool bSensitive, int col = -1) = 0;
    virtual bool get_sensitive(int row, int col) const = 0;
    virtual void set_id(int row, const OUString& rId) = 0;
    // col index -1 sets the expander toggle, enable_toggle_buttons must have been called to create that column
    virtual void set_toggle(int row, TriState eState, int col = -1) = 0;
    // col index -1 gets the expander toggle, enable_toggle_buttons must have been called to create that column
    virtual TriState get_toggle(int row, int col = -1) const = 0;
    // col index -1 sets the expander image
    virtual void set_image(int row, const OUString& rImage, int col = -1) = 0;
    // col index -1 sets the expander image
    virtual void set_image(int row, VirtualDevice& rImage, int col = -1) = 0;
    // col index -1 sets the expander image
    virtual void set_image(int row, const css::uno::Reference<css::graphic::XGraphic>& rImage,
                           int col = -1)
        = 0;
    virtual void set_text_emphasis(int row, bool bOn, int col) = 0;
    virtual bool get_text_emphasis(int row, int col) const = 0;
    virtual void set_text_align(int row, double fAlign, int col) = 0;
    virtual void swap(int pos1, int pos2) = 0;
    virtual std::vector<int> get_selected_rows() const = 0;
    virtual void set_font_color(int pos, const Color& rColor) = 0;
    // scroll to make 'row' visible, this will also expand all parent rows of 'row' as necessary to
    // make 'row' visible
    virtual void scroll_to_row(int row) = 0;
    virtual bool is_selected(int pos) const = 0;
    virtual int get_cursor_index() const = 0;
    virtual void set_cursor(int pos) = 0;

    //by text
    virtual int find_text(const OUString& rText) const = 0;
    //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    void select_text(const OUString& rText) { select(find_text(rText)); }
    void remove_text(const OUString& rText) { remove(find_text(rText)); }
    std::vector<OUString> get_selected_rows_text() const
    {
        std::vector<int> aRows(get_selected_rows());
        std::vector<OUString> aRet;
        aRet.reserve(aRows.size());
        for (auto a : aRows)
            aRet.push_back(get_text(a));
        return aRet;
    }

    //by id
    virtual OUString get_id(int pos) const = 0;
    virtual int find_id(const OUString& rId) const = 0;
    //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    void select_id(const OUString& rId) { select(find_id(rId)); }
    void remove_id(const OUString& rText) { remove(find_id(rText)); }

    //via iter
    virtual std::unique_ptr<TreeIter> make_iterator(const TreeIter* pOrig = nullptr) const = 0;
    virtual void copy_iterator(const TreeIter& rSource, TreeIter& rDest) const = 0;
    virtual bool get_selected(TreeIter* pIter) const = 0;
    virtual bool get_cursor(TreeIter* pIter) const = 0;
    virtual void set_cursor(const TreeIter& rIter) = 0;
    virtual bool get_iter_first(TreeIter& rIter) const = 0;
    // set iter to point to next node at the current level
    virtual bool iter_next_sibling(TreeIter& rIter) const = 0;
    // set iter to point to previous node at the current level
    virtual bool iter_previous_sibling(TreeIter& rIter) const = 0;
    // set iter to point to next node, depth first, then sibling
    virtual bool iter_next(TreeIter& rIter) const = 0;
    // set iter to point to previous node, sibling first then depth
    virtual bool iter_previous(TreeIter& rIter) const = 0;
    // set iter to point to first child node
    virtual bool iter_children(TreeIter& rIter) const = 0;
    bool iter_nth_sibling(TreeIter& rIter, int nChild) const
    {
        bool bRet = true;
        for (int i = 0; i < nChild && bRet; ++i)
            bRet = iter_next_sibling(rIter);
        return bRet;
    }
    bool iter_nth_child(TreeIter& rIter, int nChild) const
    {
        if (!iter_children(rIter))
            return false;
        return iter_nth_sibling(rIter, nChild);
    }
    virtual bool iter_parent(TreeIter& rIter) const = 0;
    virtual int get_iter_depth(const TreeIter& rIter) const = 0;
    virtual int get_iter_index_in_parent(const TreeIter& rIter) const = 0;
    /* Compares two paths. If a appears before b in a tree, then -1 is returned.
       If b appears before a , then 1 is returned. If the two nodes are equal,
       then 0 is returned.
    */

    virtual int iter_compare(const TreeIter& a, const TreeIter& b) const = 0;
    virtual bool iter_has_child(const TreeIter& rIter) const = 0;
    // returns the number of direct children rIter has
    virtual int iter_n_children(const TreeIter& rIter) const = 0;
    virtual void remove(const TreeIter& rIter) = 0;
    //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    virtual void select(const TreeIter& rIter) = 0;
    virtual void unselect(const TreeIter& rIter) = 0;
    //visually indent this row as if it was at get_iter_depth() + nIndentLevel
    virtual void set_extra_row_indent(const TreeIter& rIter, int nIndentLevel) = 0;
    // col index -1 sets the first text column
    virtual void set_text(const TreeIter& rIter, const OUString& rStr, int col = -1) = 0;
    // col index -1 sets all columns
    virtual void set_sensitive(const TreeIter& rIter, bool bSensitive, int col = -1) = 0;
    virtual bool get_sensitive(const TreeIter& rIter, int col) const = 0;
    virtual void set_text_emphasis(const TreeIter& rIter, bool bOn, int col) = 0;
    virtual bool get_text_emphasis(const TreeIter& rIter, int col) const = 0;
    virtual void set_text_align(const TreeIter& rIter, double fAlign, int col) = 0;
    // col index -1 sets the expander toggle, enable_toggle_buttons must have been called to create that column
    virtual void set_toggle(const TreeIter& rIter, TriState bOn, int col = -1) = 0;
    // col index -1 gets the expander toggle, enable_toggle_buttons must have been called to create that column
    virtual TriState get_toggle(const TreeIter& rIter, int col = -1) const = 0;
    // col index -1 gets the first text column
    virtual OUString get_text(const TreeIter& rIter, int col = -1) const = 0;
    virtual void set_id(const TreeIter& rIter, const OUString& rId) = 0;
    virtual OUString get_id(const TreeIter& rIter) const = 0;
    // col index -1 sets the expander image
    virtual void set_image(const TreeIter& rIter, const OUString& rImage, int col = -1) = 0;
    // col index -1 sets the expander image
    virtual void set_image(const TreeIter& rIter, VirtualDevice& rImage, int col = -1) = 0;
    // col index -1 sets the expander image
    virtual void set_image(const TreeIter& rIter,
                           const css::uno::Reference<css::graphic::XGraphic>& rImage, int col = -1)
        = 0;
    virtual void set_font_color(const TreeIter& rIter, const Color& rColor) = 0;
    // scroll to make rIter visible, this will also expand all parent rows of rIter as necessary to
    // make rIter visible
    virtual void scroll_to_row(const TreeIter& rIter) = 0;
    virtual bool is_selected(const TreeIter& rIter) const = 0;

    virtual void move_subtree(TreeIter& rNode, const TreeIter* pNewParent, int nIndexInNewParent)
        = 0;

    // call func on each element until func returns true or we run out of elements
    virtual void all_foreach(const std::function<bool(TreeIter&)>& func) = 0;
    // call func on each selected element until func returns true or we run out of elements
    virtual void selected_foreach(const std::function<bool(TreeIter&)>& func) = 0;
    // call func on each visible element until func returns true or we run out of elements
    virtual void visible_foreach(const std::function<bool(TreeIter&)>& func) = 0;
    // clear the children of pParent (whole tree if nullptr),
    // then add nSourceCount rows under pParent, call func on each row
    // inserted with an arg of the index that this row will be when bulk insert
    // ends.
    //
    // this enables inserting the entries backwards in models where that is faster,
    //
    // pFixedWidths is optional, when present each matching entry col text
    // width will not be measured, and the fixed width used instead. Use
    // sparingly because wider text than the fixed width is clipped and cannot
    // be scrolled into view horizontally.
    // @param bGoingToSetText needs to be true, if you plan to call set_text inside the insert func.
    virtual void bulk_insert_for_each(int nSourceCount,
                                      const std::function<void(TreeIter&, int nSourceIndex)>& func,
                                      const weld::TreeIter* pParent = nullptr,
                                      const std::vector<int>* pFixedWidths = nullptr,
                                      bool bGoingToSetText = false)
        = 0;

    /* expanding on-demand node details

    When a node is added with children-on-demand (typically via 'insert' with
    bChildrenOnDemand of true), then initially in reality the
    children-on-demand node is given a 'placeholder' child entry to indicate
    the load-on-demand state.

    The 'placeholder' needs to be there for the expander indicator to be
    drawn/shown even when there are no "real" entries yet. This child doesn't
    exist for the purposes of any of the iterator methods, e.g. iter_has_child
    on an on-demand node which hasn't been expanded yet is false. Likewise the
    rest of the iterator methods skip over or otherwise ignore that node.

    Normal usage is the user clicks on the expander, the expansion mechanism
    removes the 'placeholder' entry (set_children_on_demand(false)) and calls
    any installed expanding-callback (installable via connect_expanding) which
    has the opportunity to populate the node with children.

    If you decide to directly populate the children of an on-demand node
    outside of the expanding-callback then you also need to explicitly remove
    the 'placeholder' with set_children_on_demand(false) otherwise the treeview
    is in an inconsistent state.  */


    virtual bool get_row_expanded(const TreeIter& rIter) const = 0;
    // expand row will first trigger the callback set via connect_expanding before expanding
    virtual void expand_row(const TreeIter& rIter) = 0;
    // collapse row will first trigger the callback set via connect_collapsing before collapsing
    virtual void collapse_row(const TreeIter& rIter) = 0;
    // set the empty node to appear as if it has children, true is equivalent
    // to 'insert' with a bChildrenOnDemand of true. See notes above.
    virtual void set_children_on_demand(const TreeIter& rIter, bool bChildrenOnDemand) = 0;
    // return if the node is configured to be populated on-demand
    virtual bool get_children_on_demand(const TreeIter& rIter) const = 0;
    // set if the expanders are shown or not
    virtual void set_show_expanders(bool bShow) = 0;

    void connect_expanding(const Link<const TreeIter&, bool>& rLink) { m_aExpandingHdl = rLink; }
    void connect_collapsing(const Link<const TreeIter&, bool>& rLink) { m_aCollapsingHdl = rLink; }

    // rStartLink returns true to allow editing, false to disallow
    // rEndLink returns true to accept the edit, false to reject
    virtual void connect_editing(const Link<const TreeIter&, bool>& rStartLink,
                                 const Link<const iter_string&, bool>& rEndLink)
    {
        assert(rStartLink.IsSet() == rEndLink.IsSet() && "should be both on or both off");
        m_aEditingStartedHdl = rStartLink;
        m_aEditingDoneHdl = rEndLink;
    }

    virtual void start_editing(const weld::TreeIter& rEntry) = 0;
    virtual void end_editing() = 0;

    virtual void connect_visible_range_changed(const Link<TreeView&, void>& rLink)
    {
        assert(!m_aVisibleRangeChangedHdl.IsSet() || !rLink.IsSet());
        m_aVisibleRangeChangedHdl = rLink;
    }

    virtual void connect_popup_menu(const Link<const CommandEvent&, bool>& rLink)
    {
        m_aPopupMenuHdl = rLink;
    }

    virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rTransferable,
                                    sal_uInt8 eDNDConstants)
        = 0;

    void connect_drag_begin(const Link<bool&, bool>& rLink) { m_aDragBeginHdl = rLink; }

    //all of them. Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    virtual void select_all() = 0;
    virtual void unselect_all() = 0;

    // return the number of toplevel nodes
    virtual int n_children() const = 0;

    // afterwards, entries will be in default ascending sort order
    virtual void make_sorted() = 0;
    virtual void make_unsorted() = 0;
    virtual bool get_sort_order() const = 0;
    virtual void set_sort_order(bool bAscending) = 0;

    // TRUE ascending, FALSE, descending, INDET, neither (off)
    virtual void set_sort_indicator(TriState eState, int nColumn) = 0;
    virtual TriState get_sort_indicator(int nColumn) const = 0;

    virtual int get_sort_column() const = 0;
    virtual void set_sort_column(int nColumn) = 0;

    virtual void
    set_sort_func(const std::function<int(const weld::TreeIter&, const weld::TreeIter&)&gt;& func)
    {
        m_aCustomSort = func;
    }

    virtual void clear() = 0;
    virtual int get_height_rows(int nRows) const = 0;

    virtual void columns_autosize() = 0;
    virtual void set_column_fixed_widths(const std::vector<int>& rWidths) = 0;
    virtual void set_column_editables(const std::vector<bool>& rEditables) = 0;
    virtual int get_column_width(int nCol) const = 0;
    virtual void set_centered_column(int nCol) = 0;
    virtual OUString get_column_title(int nColumn) const = 0;
    virtual void set_column_title(int nColumn, const OUString& rTitle) = 0;

    int get_checkbox_column_width() const { return get_approximate_digit_width() * 3 + 6; }

    virtual void set_selection_mode(SelectionMode eMode) = 0;
    virtual int count_selected_rows() const = 0;
    // remove the selected nodes
    virtual void remove_selection() = 0;

    // only meaningful is call this from a "changed" callback, true if the change
    // was due to mouse hovering over the entry
    virtual bool changed_by_hover() const = 0;

    virtual void vadjustment_set_value(int value) = 0;
    virtual int vadjustment_get_value() const = 0;

    void save_value() { m_sSavedValue = get_selected_text(); }
    OUString const& get_saved_value() const { return m_sSavedValue; }
    bool get_value_changed_from_saved() const { return m_sSavedValue != get_selected_text(); }

    // for custom rendering a cell
    void connect_custom_get_size(const Link<get_size_args, Size>& rLink) { m_aGetSizeHdl = rLink; }
    void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; }
    // call set_column_custom_renderer after setting custom callbacks
    virtual void set_column_custom_renderer(int nColumn, bool bEnable) = 0;
    // redraw all rows, typically only useful with custom rendering to redraw due to external
    // state change
    virtual void queue_draw() = 0;

    /* with bDnDMode false simply return the row under the point
     *
     * with bDnDMode true:
     * a) return the row which should be dropped on, which may
     *    be different from the row the mouse is over in some backends where
     *    positioning the mouse on the bottom half of a row indicates to drop
     *    after the row
     * b) dnd highlight the dest row
     */

    virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode,
                                     bool bAutoScroll = true)
        = 0;
    virtual void unset_drag_dest_row() = 0;
    virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const = 0;
    // for dragging and dropping between TreeViews, return the active source
    virtual TreeView* get_drag_source() const = 0;

    using Widget::set_sensitive;
    using Widget::get_sensitive;
};

typedef std::tuple<OUString&, const TreeIter&> encoded_image_query;

class VCL_DLLPUBLIC IconView : virtual public Widget
{
    friend class ::LOKTrigger;

private:
    OUString m_sSavedValue;

protected:
    Link<IconView&, void> m_aSelectionChangeHdl;
    Link<IconView&, bool> m_aItemActivatedHdl;
    Link<const CommandEvent&, bool> m_aCommandHdl;
    Link<const TreeIter&, OUString> m_aQueryTooltipHdl;
    Link<const encoded_image_query&, bool> m_aGetPropertyTreeElemHdl;

    void signal_selection_changed() { m_aSelectionChangeHdl.Call(*this); }
    bool signal_item_activated() { return m_aItemActivatedHdl.Call(*this); }
    OUString signal_query_tooltip(const TreeIter& rIter) const
    {
        return m_aQueryTooltipHdl.Call(rIter);
    }

public:
    virtual int get_item_width() const = 0;
    virtual void set_item_width(int width) = 0;

    virtual void insert(int pos, const OUString* pStr, const OUString* pId,
                        const OUString* pIconName, TreeIter* pRet)
        = 0;

    virtual void insert(int pos, const OUString* pStr, const OUString* pId, const BitmapEx* pIcon,
                        TreeIter* pRet)
        = 0;

    virtual void insert_separator(int pos, const OUString* pId) = 0;

    void append(const OUString& rId, const OUString& rStr, const OUString& rImage)
    {
        insert(-1, &rStr, &rId, &rImage, nullptr);
    }

    void append(const OUString& rId, const OUString& rStr, const BitmapEx* pImage)
    {
        insert(-1, &rStr, &rId, pImage, nullptr);
    }

    void append_separator(const OUString& rId) { insert_separator(-1, &rId); }

    void connect_selection_changed(const Link<IconView&, void>& rLink)
    {
        m_aSelectionChangeHdl = rLink;
    }

    /* A row is "activated" when the user double clicks a treeview row. It may
       also be emitted when a row is selected and Space or Enter is pressed.

       a return of "true" means the activation has been handled, a "false" propagates
       the activation to the default handler which expands/collapses the row, if possible.
    */

    void connect_item_activated(const Link<IconView&, bool>& rLink) { m_aItemActivatedHdl = rLink; }

    void connect_command(const Link<const CommandEvent&, bool>& rLink) { m_aCommandHdl = rLink; }

    virtual void connect_query_tooltip(const Link<const TreeIter&, OUString>& rLink)
    {
        m_aQueryTooltipHdl = rLink;
    }

    // 0: OUString, 1: TreeIter, returns true if supported
    virtual void connect_get_image(const Link<const encoded_image_query&, bool>& rLink)
    {
        m_aGetPropertyTreeElemHdl = rLink;
    }

    virtual OUString get_selected_id() const = 0;

    virtual void clear() = 0;

    virtual int count_selected_items() const = 0;

    virtual OUString get_selected_text() const = 0;

    //by index. Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    virtual OUString get_id(int pos) const = 0;
    virtual void select(int pos) = 0;
    virtual void unselect(int pos) = 0;
    virtual void set_image(int pos, VirtualDevice& rDevice) = 0;
    virtual void set_text(int pos, const OUString& rText) = 0;
    virtual void set_id(int pos, const OUString& rId) = 0;
    virtual void set_item_accessible_name(int pos, const OUString& rName) = 0;
    virtual void remove(int pos) = 0;
    virtual tools::Rectangle get_rect(int pos) const = 0;

    //via iter
    virtual std::unique_ptr<TreeIter> make_iterator(const TreeIter* pOrig = nullptr) const = 0;
    virtual bool get_selected(TreeIter* pIter) const = 0;
    virtual bool get_cursor(TreeIter* pIter) const = 0;
    virtual void set_cursor(const TreeIter& rIter) = 0;
    virtual bool get_iter_first(TreeIter& rIter) const = 0;
    virtual OUString get_id(const TreeIter& rIter) const = 0;
    virtual OUString get_text(const TreeIter& rIter) const = 0;
    virtual bool iter_next_sibling(TreeIter& rIter) const = 0;
    virtual void scroll_to_item(const TreeIter& rIter) = 0;

    // call func on each selected element until func returns true or we run out of elements
    virtual void selected_foreach(const std::function<bool(TreeIter&)>& func) = 0;

    //all of them. Don't select when frozen, select after thaw. Note selection doesn't survive a freeze.
    virtual void select_all() = 0;
    virtual void unselect_all() = 0;

    // return the number of toplevel nodes
    virtual int n_children() const = 0;

    void save_value() { m_sSavedValue = get_selected_text(); }
    OUString const& get_saved_value() const { return m_sSavedValue; }
    bool get_value_changed_from_saved() const { return m_sSavedValue != get_selected_text(); }
};

class VCL_DLLPUBLIC Button : virtual public Widget
{
    friend class ::LOKTrigger;

protected:
    Link<Button&, void> m_aClickHdl;

    void signal_clicked() { m_aClickHdl.Call(*this); }

public:
    virtual void set_label(const OUString& rText) = 0;
    // pDevice, the image for the button, or nullptr to unset
    virtual void set_image(VirtualDevice* pDevice) = 0;
    virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) = 0;
    virtual void set_from_icon_name(const OUString& rIconName) = 0;
    virtual OUString get_label() const = 0;
    void clicked() { signal_clicked(); }
    bool is_custom_handler_set() { return m_aClickHdl.IsSet(); }

    // font size is in points, not pixels, e.g. see Window::[G]etPointFont
    virtual void set_font(const vcl::Font& rFont) = 0;

    /* Sometimes, a widget should behave like a button (activate on click,
       accept keyboard focus, etc), but look entirely different.

       pDevice, the custom look to use, or nullptr to unset.

       Typically doing this is ill advised. Consider using
       set_accessible_name if you do. */

    virtual void set_custom_button(VirtualDevice* pDevice) = 0;

    virtual void connect_clicked(const Link<Button&, void>& rLink) { m_aClickHdl = rLink; }
};

class VCL_DLLPUBLIC Toggleable : virtual public Widget
{
    friend class ::LOKTrigger;

protected:
    Link<Toggleable&, void> m_aToggleHdl;
    TriState m_eSavedValue = TRISTATE_FALSE;

    void signal_toggled() { m_aToggleHdl.Call(*this); }

public:
    virtual void set_active(bool active) = 0;
    virtual bool get_active() const = 0;

    virtual void set_inconsistent(bool inconsistent) = 0;
    virtual bool get_inconsistent() const = 0;

    TriState get_state() const
    {
        if (get_inconsistent())
            return TRISTATE_INDET;
        else if (get_active())
            return TRISTATE_TRUE;
        return TRISTATE_FALSE;
    }

    void set_state(TriState eState)
    {
        switch (eState)
        {
            case TRISTATE_INDET:
                set_inconsistent(true);
                break;
            case TRISTATE_TRUE:
                set_inconsistent(false);
                set_active(true);
                break;
            case TRISTATE_FALSE:
                set_inconsistent(false);
                set_active(false);
                break;
        }
    }

    void save_state() { m_eSavedValue = get_state(); }
    TriState get_saved_state() const { return m_eSavedValue; }
    bool get_state_changed_from_saved() const { return m_eSavedValue != get_state(); }

    virtual void connect_toggled(const Link<Toggleable&, void>& rLink) { m_aToggleHdl = rLink; }
};

class VCL_DLLPUBLIC ToggleButton : virtual public Button, virtual public Toggleable
{
    friend class ::LOKTrigger;
};

struct VCL_DLLPUBLIC TriStateEnabled
{
    TriState eState;
    bool bTriStateEnabled;
    TriStateEnabled()
        : eState(TRISTATE_INDET)
        , bTriStateEnabled(true)
    {
    }
    void ButtonToggled(Toggleable& rToggle);
};

class VCL_DLLPUBLIC MenuButton : virtual public ToggleButton
{
    friend class ::LOKTrigger;

    Link<const OUString&, void> m_aSelectHdl;

protected:
    void signal_selected(const OUString& rIdent) { m_aSelectHdl.Call(rIdent); }

public:
    void connect_selected(const Link<const OUString&, void>& rLink) { m_aSelectHdl = rLink; }

    virtual void insert_item(int pos, const OUString& rId, const OUString& rStr,
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=89 H=100 G=94

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge