weld SfxRecordingFloat_Impl utility window

we can't abuse action_name anymore as the uno command
are not legal actions

Change-Id: Iaf9306c6e3eec852d2a50df9161bd20383881a04
Reviewed-on: https://gerrit.libreoffice.org/81902
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/bin/gla11y b/bin/gla11y
index 0120326..aff0a13 100755
--- a/bin/gla11y
+++ b/bin/gla11y
@@ -785,6 +785,11 @@ def is_orphan_widget(filename, tree, root, obj, orphan, orphan_root, doprint = F
            # Has a <property name="action_name">
            return False

        # Uses id as an action_name
        if 'id' in obj.attrib:
            if obj.attrib['id'].startswith(".uno:"):
                return False

        gtklabels = obj.findall(".//object[@class='GtkLabel']") + obj.findall(".//object[@class='GtkAccelLabel']")
        if len(gtklabels) >= 1:
            # Has a custom label
diff --git a/include/sfx2/childwin.hxx b/include/sfx2/childwin.hxx
index 60eb832..f5e64fd 100644
--- a/include/sfx2/childwin.hxx
+++ b/include/sfx2/childwin.hxx
@@ -280,6 +280,14 @@ public:
            static_cast<SfxFloatingWindow*>(GetWindow())->FillInfo( aInfo );  \
            return aInfo; }

#define SFX_IMPL_MODELESSDIALOGCONTOLLER(Class, MyID)    \
        SFX_IMPL_CHILDWINDOW(Class, MyID)       \
        SfxChildWinInfo Class::GetInfo() const \
        {                                       \
            SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();     \
            static_cast<const SfxModelessDialogController*>(GetController().get())->FillInfo( aInfo );  \
            return aInfo; }

#define SFX_IMPL_MODELESSDIALOGCONTOLLER_WITHID(Class, MyID)    \
        SFX_IMPL_CHILDWINDOW_WITHID(Class, MyID)       \
        SfxChildWinInfo Class::GetInfo() const \
diff --git a/include/vcl/image.hxx b/include/vcl/image.hxx
index 07ea7a7..f01c174 100644
--- a/include/vcl/image.hxx
+++ b/include/vcl/image.hxx
@@ -23,6 +23,7 @@
#include <vcl/dllapi.h>
#include <tools/gen.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/vclenum.hxx>
#include <vcl/outdev.hxx>

#include <memory>
@@ -32,18 +33,6 @@ class ImplImage;
namespace com::sun::star::graphic { class XGraphic; }
namespace com::sun::star::uno { template <class interface_type> class Reference; }

namespace vcl
{
    enum class ImageType
    {
        Size16,
        Size26,
        Size32,
        Small = Size16,
        LAST = Size32,
    };
}

#define IMAGELIST_IMAGE_NOTFOUND (sal_uInt16(0xFFFF))

enum class StockImage { Yes };
diff --git a/include/vcl/vclenum.hxx b/include/vcl/vclenum.hxx
index 90bfa99..95650b2 100644
--- a/include/vcl/vclenum.hxx
+++ b/include/vcl/vclenum.hxx
@@ -314,6 +314,18 @@ namespace o3tl
    template<> struct typed_flags<WindowStateState> : is_typed_flags<WindowStateState, 0xffff> {};
}

namespace vcl
{
    enum class ImageType
    {
        Size16,
        Size26,
        Size32,
        Small = Size16,
        LAST = Size32,
    };
}

#endif // INCLUDED_VCL_VCLENUM_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index e7dce76..ac92646 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -1920,6 +1920,15 @@ public:
    virtual void insert_separator(int pos, const OUString& rId) = 0;
    void append_separator(const OUString& rId) { insert_separator(-1, rId); }

    virtual int get_n_items() const = 0;
    virtual OString get_item_ident(int nIndex) const = 0;
    virtual void set_item_label(int nIndex, const OUString& rLabel) = 0;
    virtual void set_item_icon(int nIndex, const css::uno::Reference<css::graphic::XGraphic>& rIcon)
        = 0;
    virtual void set_item_tooltip_text(int nIndex, const OUString& rTip) = 0;

    virtual vcl::ImageType get_icon_size() const = 0;

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

diff --git a/include/vcl/weldutils.hxx b/include/vcl/weldutils.hxx
new file mode 100644
index 0000000..4144803
--- /dev/null
+++ b/include/vcl/weldutils.hxx
@@ -0,0 +1,36 @@
/* -*- 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_WELDUTILS_HXX
#define INCLUDED_VCL_WELDUTILS_HXX

#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <tools/link.hxx>
#include <vcl/dllapi.h>

namespace weld
{
class Toolbar;

class VCL_DLLPUBLIC ToolbarUnoDispatcher
{
private:
    css::uno::Reference<css::frame::XFrame> m_xFrame;
    DECL_LINK(SelectHdl, const OString&, void);

public:
    // fill in the label and icons for actions and dispatch the action on item click
    ToolbarUnoDispatcher(Toolbar& rToolbar, const css::uno::Reference<css::frame::XFrame>& rFrame);
};
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/dialog/recfloat.cxx b/sfx2/source/dialog/recfloat.cxx
index bfc6d11..b431cc6 100644
--- a/sfx2/source/dialog/recfloat.cxx
+++ b/sfx2/source/dialog/recfloat.cxx
@@ -22,6 +22,7 @@
#include <svl/eitem.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <vcl/weldutils.hxx>

#include <recfloat.hxx>
#include <sfx2/strings.hrc>
@@ -33,18 +34,35 @@
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>

SFX_IMPL_FLOATINGWINDOW( SfxRecordingFloatWrapper_Impl, SID_RECORDING_FLOATWINDOW );
SFX_IMPL_MODELESSDIALOGCONTOLLER(SfxRecordingFloatWrapper_Impl, SID_RECORDING_FLOATWINDOW);

SfxRecordingFloatWrapper_Impl::SfxRecordingFloatWrapper_Impl( vcl::Window* pParentWnd ,
                                                sal_uInt16 nId ,
                                                SfxBindings* pBind ,
                                                SfxChildWinInfo const * pInfo )
                    : SfxChildWindow( pParentWnd, nId )
                    , pBindings( pBind )
SfxRecordingFloatWrapper_Impl::SfxRecordingFloatWrapper_Impl(vcl::Window* pParentWnd,
                                                             sal_uInt16 nId,
                                                             SfxBindings* pBind,
                                                             SfxChildWinInfo const * pInfo)
    : SfxChildWindow(pParentWnd, nId)
    , pBindings(pBind)
{
    SetWindow( VclPtr<SfxRecordingFloat_Impl>::Create( pBindings, this, pParentWnd ) );
    SetWantsFocus( false );
    static_cast<SfxFloatingWindow*>(GetWindow())->Initialize( pInfo );
    SetController(std::make_shared<SfxRecordingFloat_Impl>(pBindings, this, pParentWnd->GetFrameWeld()));
    SetWantsFocus(false);
    SfxRecordingFloat_Impl* pFloatDlg = static_cast<SfxRecordingFloat_Impl*>(GetController().get());

    weld::Dialog* pDlg = pFloatDlg->getDialog();

    SfxViewFrame *pFrame = pBind->GetDispatcher_Impl()->GetFrame();
    vcl::Window* pEditWin = pFrame->GetViewShell()->GetWindow();

    Point aPos = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
    aPos.AdjustX(20);
    aPos.AdjustY(10);

    WindowStateData aState;
    aState.SetMask(WindowStateMask::Pos);
    aState.SetX(aPos.X());
    aState.SetY(aPos.Y());
    pDlg->set_window_state(aState.ToStr());

    pFloatDlg->Initialize(pInfo);
}

SfxRecordingFloatWrapper_Impl::~SfxRecordingFloatWrapper_Impl()
@@ -76,14 +94,12 @@ bool SfxRecordingFloatWrapper_Impl::QueryClose()
    return bRet;
}

SfxRecordingFloat_Impl::SfxRecordingFloat_Impl(
    SfxBindings* pBind ,
    SfxChildWindow* pChildWin ,
    vcl::Window* pParent )
    : SfxFloatingWindow( pBind,
                         pChildWin,
                         pParent,
                         "FloatingRecord", "sfx/ui/floatingrecord.ui", pBind->GetActiveFrame() )
SfxRecordingFloat_Impl::SfxRecordingFloat_Impl(SfxBindings* pBind, SfxChildWindow* pChildWin,
                                               weld::Window* pParent)
    : SfxModelessDialogController(pBind, pChildWin, pParent, "sfx/ui/floatingrecord.ui",
                                  "FloatingRecord")
    , m_xToolbar(m_xBuilder->weld_toolbar("toolbar"))
    , m_aDispatcher(*m_xToolbar, pBind->GetActiveFrame())
{
    // start recording
    SfxBoolItem aItem( SID_RECORDMACRO, true );
@@ -93,30 +109,12 @@ SfxRecordingFloat_Impl::SfxRecordingFloat_Impl(

SfxRecordingFloat_Impl::~SfxRecordingFloat_Impl()
{
    disposeOnce();
}

void SfxRecordingFloat_Impl::FillInfo( SfxChildWinInfo& rInfo ) const
{
    SfxFloatingWindow::FillInfo( rInfo );
    SfxModelessDialogController::FillInfo( rInfo );
    rInfo.bVisible = false;
}

void SfxRecordingFloat_Impl::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == StateChangedType::InitShow )
    {
        SfxViewFrame *pFrame = GetBindings().GetDispatcher_Impl()->GetFrame();
        vcl::Window* pEditWin = pFrame->GetViewShell()->GetWindow();

        Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
        aPoint = GetParent()->ScreenToOutputPixel( aPoint );
        aPoint.AdjustX(20 );
        aPoint.AdjustY(10 );
        SetPosPixel( aPoint );
    }

    SfxFloatingWindow::StateChanged( nStateChange );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/inc/recfloat.hxx b/sfx2/source/inc/recfloat.hxx
index 7fc02c9..e9d2dd7 100644
--- a/sfx2/source/inc/recfloat.hxx
+++ b/sfx2/source/inc/recfloat.hxx
@@ -22,6 +22,7 @@

#include <sfx2/childwin.hxx>
#include <sfx2/basedlgs.hxx>
#include <vcl/weldutils.hxx>

class SfxRecordingFloatWrapper_Impl : public SfxChildWindow
{
@@ -37,18 +38,18 @@ public:
    virtual bool        QueryClose() override;
};

class SfxRecordingFloat_Impl : public SfxFloatingWindow
class SfxRecordingFloat_Impl : public SfxModelessDialogController
{
    std::unique_ptr<weld::Toolbar> m_xToolbar;
    weld::ToolbarUnoDispatcher m_aDispatcher;
public:
                        SfxRecordingFloat_Impl( SfxBindings* pBindings ,
                            SfxChildWindow* pChildWin ,
                            vcl::Window* pParent );
    virtual             ~SfxRecordingFloat_Impl() override;
    virtual void        FillInfo( SfxChildWinInfo& rInfo ) const override;
    virtual void        StateChanged( StateChangedType nStateChange ) override;
    SfxRecordingFloat_Impl(SfxBindings* pBindings,
                           SfxChildWindow* pChildWin,
                           weld::Window* pParent);
    virtual ~SfxRecordingFloat_Impl() override;
    virtual void FillInfo(SfxChildWinInfo& rInfo) const override;
};

#endif


/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/uiconfig/ui/floatingrecord.ui b/sfx2/uiconfig/ui/floatingrecord.ui
index d91f3b0..66fe08d 100644
--- a/sfx2/uiconfig/ui/floatingrecord.ui
+++ b/sfx2/uiconfig/ui/floatingrecord.ui
@@ -1,23 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<!-- Generated with glade 3.22.1 -->
<interface domain="sfx">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkWindow" id="FloatingRecord">
  <object class="GtkDialog" id="FloatingRecord">
    <property name="can_focus">False</property>
    <property name="no_show_all">True</property>
    <property name="border_width">6</property>
    <property name="title" translatable="yes" context="floatingrecord|FloatingRecord">Record Macro</property>
    <property name="default_width">0</property>
    <property name="default_height">0</property>
    <property name="type_hint">utility</property>
    <property name="deletable">False</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can_focus">False</property>
        <property name="hexpand">True</property>
        <property name="vexpand">True</property>
        <property name="orientation">vertical</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can_focus">False</property>
            <property name="no_show_all">True</property>
            <property name="layout_style">end</property>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="sfxlo-SidebarToolBox" id="toolbar">
          <object class="GtkToolbar" id="toolbar">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
@@ -25,12 +40,11 @@
            <property name="toolbar_style">text</property>
            <property name="show_arrow">False</property>
            <child>
              <object class="GtkToolButton" id="stop">
              <object class="GtkToolButton" id=".uno:StopRecording">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="hexpand">True</property>
                <property name="vexpand">True</property>
                <property name="action_name">.uno:StopRecording</property>
                <property name="use_underline">True</property>
              </object>
              <packing>
@@ -42,7 +56,7 @@
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index c2701e4..2a1c38d 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1025,6 +1025,36 @@ public:
        m_xToolBox->InsertSeparator(nInsertPos, 5);
    }

    virtual int get_n_items() const override
    {
        return m_xToolBox->GetItemCount();
    }

    virtual OString get_item_ident(int nIndex) const override
    {
        return m_xToolBox->GetItemCommand(m_xToolBox->GetItemId(nIndex)).toUtf8();
    }

    virtual void set_item_label(int nIndex, const OUString& rLabel) override
    {
        m_xToolBox->SetItemText(m_xToolBox->GetItemId(nIndex), rLabel);
    }

    virtual void set_item_icon(int nIndex, const css::uno::Reference<css::graphic::XGraphic>& rIcon) override
    {
        m_xToolBox->SetItemImage(m_xToolBox->GetItemId(nIndex), Image(rIcon));
    }

    virtual void set_item_tooltip_text(int nIndex, const OUString& rTip) override
    {
        m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(nIndex), rTip);
    }

    virtual vcl::ImageType get_icon_size() const override
    {
        return m_xToolBox->GetImageSize();
    }

    virtual ~SalInstanceToolbar() override
    {
        m_xToolBox->SetDropdownClickHdl(Link<ToolBox*, void>());
diff --git a/vcl/source/app/weldutils.cxx b/vcl/source/app/weldutils.cxx
index 9db82c2..9e20d7f 100644
--- a/vcl/source/app/weldutils.cxx
+++ b/vcl/source/app/weldutils.cxx
@@ -7,8 +7,11 @@
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <comphelper/dispatchcommand.hxx>
#include <vcl/builderpage.hxx>
#include <vcl/commandinfoprovider.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weldutils.hxx>

BuilderPage::BuilderPage(weld::Widget* pParent, weld::DialogController* pController,
                         const OUString& rUIXMLDescription, const OString& rID)
@@ -102,6 +105,34 @@ void TriStateEnabled::ButtonToggled(weld::ToggleButton& rToggle)
    }
    eState = rToggle.get_state();
}

ToolbarUnoDispatcher::ToolbarUnoDispatcher(Toolbar& rToolbar,
                                           const css::uno::Reference<css::frame::XFrame>& rFrame)
    : m_xFrame(rFrame)
{
    OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(rFrame));
    vcl::ImageType eSize = rToolbar.get_icon_size();

    for (int i = 0, nItems = rToolbar.get_n_items(); i < nItems; ++i)
    {
        OUString sCommand = OUString::fromUtf8(rToolbar.get_item_ident(i));

        OUString aLabel(vcl::CommandInfoProvider::GetLabelForCommand(sCommand, aModuleName));
        rToolbar.set_item_label(i, aLabel);
        OUString aTooltip(vcl::CommandInfoProvider::GetTooltipForCommand(sCommand, rFrame));
        rToolbar.set_item_tooltip_text(i, aTooltip);
        auto xImage(vcl::CommandInfoProvider::GetXGraphicForCommand(sCommand, rFrame, eSize));
        rToolbar.set_item_icon(i, xImage);
    }

    rToolbar.connect_clicked(LINK(this, ToolbarUnoDispatcher, SelectHdl));
}

IMPL_LINK(ToolbarUnoDispatcher, SelectHdl, const OString&, rCommand, void)
{
    comphelper::dispatchCommand(OUString::fromUtf8(rCommand), m_xFrame,
                                css::uno::Sequence<css::beans::PropertyValue>());
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 1823601..e0fcb5d 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -3696,11 +3696,14 @@ VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window *pParent, xmlreader::Xm
        {
            name = reader.getAttributeValue(false);
            sID = OString(name.begin, name.length);
            sal_Int32 nDelim = sID.indexOf(':');
            if (nDelim != -1)
            if (m_bLegacy)
            {
                sCustomProperty = OUString::fromUtf8(sID.copy(nDelim+1));
                sID = sID.copy(0, nDelim);
                sal_Int32 nDelim = sID.indexOf(':');
                if (nDelim != -1)
                {
                    sCustomProperty = OUString::fromUtf8(sID.copy(nDelim+1));
                    sID = sID.copy(0, nDelim);
                }
            }
        }
    }
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 1c22533..aec86f2 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -6751,8 +6751,7 @@ public:
        GtkWidget* pImage = nullptr;
        if (pIconName)
        {
            GdkPixbuf* pixbuf = load_icon_by_name(*pIconName);
            if (!pixbuf)
            if (GdkPixbuf* pixbuf = load_icon_by_name(*pIconName))
            {
                pImage = gtk_image_new_from_pixbuf(pixbuf);
                g_object_unref(pixbuf);
@@ -6797,6 +6796,34 @@ public:
    }
};

namespace
{
    vcl::ImageType GtkToVcl(GtkIconSize eSize)
    {
        vcl::ImageType eRet;
        switch (eSize)
        {
            case GTK_ICON_SIZE_MENU:
            case GTK_ICON_SIZE_SMALL_TOOLBAR:
            case GTK_ICON_SIZE_BUTTON:
                eRet = vcl::ImageType::Size16;
                break;
            case GTK_ICON_SIZE_LARGE_TOOLBAR:
                eRet = vcl::ImageType::Size26;
                break;
            case GTK_ICON_SIZE_DND:
            case GTK_ICON_SIZE_DIALOG:
                eRet = vcl::ImageType::Size32;
                break;
            default:
            case GTK_ICON_SIZE_INVALID:
                eRet = vcl::ImageType::Small;
                break;
        }
        return eRet;
    }
}

void GtkInstanceMenuButton::set_menu(weld::Menu* pMenu)
{
    GtkInstanceMenu* pPopoverWidget = dynamic_cast<GtkInstanceMenu*>(pMenu);
@@ -6941,6 +6968,49 @@ public:
        m_aMenuButtonMap[rIdent]->set_menu(pMenu);
    }

    virtual int get_n_items() const override
    {
        return gtk_toolbar_get_n_items(m_pToolbar);
    }

    virtual OString get_item_ident(int nIndex) const override
    {
        GtkToolItem* pItem = gtk_toolbar_get_nth_item(m_pToolbar, nIndex);
        const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pItem));
        return OString(pStr, pStr ? strlen(pStr) : 0);
    }

    virtual void set_item_label(int nIndex, const OUString& rLabel) override
    {
        GtkToolItem* pItem = gtk_toolbar_get_nth_item(m_pToolbar, nIndex);
        gtk_tool_button_set_label(GTK_TOOL_BUTTON(pItem), MapToGtkAccelerator(rLabel).getStr());
    }

    virtual void set_item_icon(int nIndex, const css::uno::Reference<css::graphic::XGraphic>& rIcon) override
    {
        GtkToolItem* pItem = gtk_toolbar_get_nth_item(m_pToolbar, nIndex);

        GtkWidget* pImage = nullptr;
        if (GdkPixbuf* pixbuf = getPixbuf(rIcon))
        {
            pImage = gtk_image_new_from_pixbuf(pixbuf);
            g_object_unref(pixbuf);
        }

        gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(pItem), pImage);
    }

    virtual void set_item_tooltip_text(int nIndex, const OUString& rTip) override
    {
        GtkToolItem* pItem = gtk_toolbar_get_nth_item(m_pToolbar, nIndex);
        gtk_widget_set_tooltip_text(GTK_WIDGET(pItem), OUStringToOString(rTip, RTL_TEXTENCODING_UTF8).getStr());
    }

    virtual vcl::ImageType get_icon_size() const override
    {
        return GtkToVcl(gtk_toolbar_get_icon_size(m_pToolbar));
    }

    virtual ~GtkInstanceToolbar() override
    {
        for (auto& a : m_aMap)