Related: tdf#130035 let SvxLineEndWindow have a menubutton parent

Change-Id: Id658dc0ac88d98ade67bdeb233eca6c912a3b253
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87133
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/svx/colorwindow.hxx b/include/svx/colorwindow.hxx
index 8a2f427..e87b601 100644
--- a/include/svx/colorwindow.hxx
+++ b/include/svx/colorwindow.hxx
@@ -22,6 +22,7 @@

#include <svtools/toolbarmenu.hxx>
#include <rtl/ustring.hxx>
#include <svx/dlgctrl.hxx>
#include <svx/SvxColorValueSet.hxx>
#include <svx/Palette.hxx>
#include <vcl/lstbox.hxx>
@@ -109,34 +110,6 @@ public:

class SvxColorToolBoxControl;

class SVX_DLLPUBLIC MenuOrToolMenuButton
{
private:
    // either
    weld::MenuButton* m_pMenuButton;
    // or
    weld::Toolbar* m_pToolbar;
    OString m_aIdent;
    // or
    SvxColorToolBoxControl* m_pControl;
    VclPtr<ToolBox> m_xToolBox;
    sal_uInt16 m_nId;
public:
    MenuOrToolMenuButton(weld::MenuButton* pMenuButton);
    MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OString& rIdent);
    MenuOrToolMenuButton(SvxColorToolBoxControl* pControl, ToolBox* pToolbar, sal_uInt16 nId);
    ~MenuOrToolMenuButton();

    MenuOrToolMenuButton(MenuOrToolMenuButton const &) = default;
    MenuOrToolMenuButton(MenuOrToolMenuButton &&) = default;
    MenuOrToolMenuButton & operator =(MenuOrToolMenuButton const &) = default;
    MenuOrToolMenuButton & operator =(MenuOrToolMenuButton &&) = default;

    bool get_active() const;
    void set_inactive() const;
    weld::Widget* get_widget() const;
};

class SVX_DLLPUBLIC ColorWindow final : public WeldToolbarPopup
{
private:
diff --git a/include/svx/dlgctrl.hxx b/include/svx/dlgctrl.hxx
index eaa31a5..88f6b00 100644
--- a/include/svx/dlgctrl.hxx
+++ b/include/svx/dlgctrl.hxx
@@ -20,6 +20,7 @@
#define INCLUDED_SVX_DLGCTRL_HXX

#include <sfx2/tabdlg.hxx>
#include <svtools/toolbarmenu.hxx>
#include <svx/svxdllapi.h>
#include <svx/rectenum.hxx>
#include <vcl/customweld.hxx>
@@ -36,6 +37,13 @@ namespace com { namespace sun { namespace star { namespace awt {
    struct Point;
} } } }

namespace svt {
    class PopupWindowController;
}

class SvtValueSet;
class ToolBox;

/*************************************************************************
|* Derived from SfxTabPage for being able to get notified through the
|* virtual method from the control.
@@ -211,6 +219,34 @@ public:
    virtual void        LoseFocus() override;
};

class SVX_DLLPUBLIC MenuOrToolMenuButton
{
private:
    // either
    weld::MenuButton* m_pMenuButton;
    // or
    weld::Toolbar* m_pToolbar;
    OString m_aIdent;
    // or
    svt::PopupWindowController* m_pControl;
    VclPtr<ToolBox> m_xToolBox;
    sal_uInt16 m_nId;
public:
    MenuOrToolMenuButton(weld::MenuButton* pMenuButton);
    MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OString& rIdent);
    MenuOrToolMenuButton(svt::PopupWindowController* pControl, ToolBox* pToolbar, sal_uInt16 nId);
    ~MenuOrToolMenuButton();

    MenuOrToolMenuButton(MenuOrToolMenuButton const &) = default;
    MenuOrToolMenuButton(MenuOrToolMenuButton &&) = default;
    MenuOrToolMenuButton & operator =(MenuOrToolMenuButton const &) = default;
    MenuOrToolMenuButton & operator =(MenuOrToolMenuButton &&) = default;

    bool get_active() const;
    void set_inactive() const;
    weld::Widget* get_widget() const;
};

/************************************************************************/

class SAL_WARN_UNUSED SVX_DLLPUBLIC FillTypeLB : public ListBox
@@ -288,6 +324,31 @@ public:
    bool get_sensitive() const { return m_xControl->get_sensitive(); }
};

typedef std::function<void(const css::uno::Sequence<css::beans::PropertyValue>&)> LineEndSelectFunction;

class SvxLineEndWindow final : public WeldToolbarPopup
{
private:
    XLineEndListRef mpLineEndList;
    MenuOrToolMenuButton maMenuButton;
    LineEndSelectFunction maLineEndSelectFunction;
    std::unique_ptr<SvtValueSet> mxLineEndSet;
    std::unique_ptr<weld::CustomWeld> mxLineEndSetWin;
    sal_uInt16 mnLines;
    Size maBmpSize;

    DECL_LINK(SelectHdl, SvtValueSet*, void);
    void FillValueSet();
    void SetSize();

    virtual void GrabFocus() override;

public:
    SvxLineEndWindow(const css::uno::Reference< css::frame::XFrame >& rFrame, weld::Window* pParent,
                     const MenuOrToolMenuButton &rMenuButton, const LineEndSelectFunction& rLineEndSelectFunction);
    virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
};

class SdrObject;
class SdrPathObj;
class SdrModel;
diff --git a/svx/source/tbxctrls/linectrl.cxx b/svx/source/tbxctrls/linectrl.cxx
index 80c36be..bb4ef33 100644
--- a/svx/source/tbxctrls/linectrl.cxx
+++ b/svx/source/tbxctrls/linectrl.cxx
@@ -19,6 +19,7 @@

#include <string>

#include <vcl/svapp.hxx>
#include <vcl/toolbox.hxx>
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
@@ -263,39 +264,20 @@ public:
private:
    virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
    virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override;
};

class SvxLineEndWindow final : public WeldToolbarPopup
{
private:
    XLineEndListRef mpLineEndList;
    rtl::Reference<SvxLineEndToolBoxControl> mxControl;
    std::unique_ptr<SvtValueSet> mxLineEndSet;
    std::unique_ptr<weld::CustomWeld> mxLineEndSetWin;
    sal_uInt16 mnLines;
    Size maBmpSize;

    DECL_LINK( SelectHdl, SvtValueSet*, void );
    void FillValueSet();
    void SetSize();

    virtual void GrabFocus() override
    {
        mxLineEndSet->GrabFocus();
    }

public:
    SvxLineEndWindow(SvxLineEndToolBoxControl* pControl, weld::Widget* pParent);
    virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
    void dispatch(const Sequence<PropertyValue>& rArgs);
};

}

static constexpr sal_uInt16 gnCols = 2;

SvxLineEndWindow::SvxLineEndWindow(SvxLineEndToolBoxControl* pControl, weld::Widget* pParent)
    : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatinglineend.ui", "FloatingLineEnd")
    , mxControl(pControl)
SvxLineEndWindow::SvxLineEndWindow(const Reference<XFrame>& rFrame, weld::Window* pParent,
                                   const MenuOrToolMenuButton &rMenuButton,
                                   const LineEndSelectFunction& rLineEndSelectFunction)
    : WeldToolbarPopup(rFrame, pParent, "svx/ui/floatinglineend.ui", "FloatingLineEnd")
    , maMenuButton(rMenuButton)
    , maLineEndSelectFunction(rLineEndSelectFunction)
    , mxLineEndSet(new SvtValueSet(m_xBuilder->weld_scrolled_window("valuesetwin")))
    , mxLineEndSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxLineEndSet))
    , mnLines(12)
@@ -322,6 +304,11 @@ SvxLineEndWindow::SvxLineEndWindow(SvxLineEndToolBoxControl* pControl, weld::Wid
    AddStatusListener( ".uno:LineEndListState");
}

void SvxLineEndWindow::GrabFocus()
{
    mxLineEndSet->GrabFocus();
}

IMPL_LINK_NOARG(SvxLineEndWindow, SelectHdl, SvtValueSet*, void)
{
    std::unique_ptr<XLineEndItem> pLineEndItem;
@@ -368,9 +355,9 @@ IMPL_LINK_NOARG(SvxLineEndWindow, SelectHdl, SvtValueSet*, void)
        while in Dispatch()), accessing members will crash in this case. */
    mxLineEndSet->SetNoSelection();

    mxControl->dispatchCommand(mxControl->getCommandURL(), aArgs);
    maLineEndSelectFunction(aArgs);

    mxControl->EndPopupMode();
    maMenuButton.set_inactive();
}

void SvxLineEndWindow::FillValueSet()
@@ -478,6 +465,11 @@ void SAL_CALL SvxLineEndToolBoxControl::execute(sal_Int16 /*KeyModifier*/)
    }
}

void SvxLineEndToolBoxControl::dispatch(const Sequence<PropertyValue>& rArgs)
{
    dispatchCommand(getCommandURL(), rArgs);
}

void SvxLineEndToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments )
{
    svt::PopupWindowController::initialize( rArguments );
@@ -496,13 +488,29 @@ void SvxLineEndToolBoxControl::initialize( const css::uno::Sequence<css::uno::An

std::unique_ptr<WeldToolbarPopup> SvxLineEndToolBoxControl::weldPopupWindow()
{
    return std::make_unique<SvxLineEndWindow>(this, m_pToolbar);
    const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow();
    weld::Window* pParentFrame = Application::GetFrameWeld(xParent);

    const OString aId(m_aCommandURL.toUtf8());
    return std::make_unique<SvxLineEndWindow>(m_xFrame, pParentFrame,
            MenuOrToolMenuButton(m_pToolbar, aId),
            std::bind(&SvxLineEndToolBoxControl::dispatch, this, std::placeholders::_1));
}

VclPtr<vcl::Window> SvxLineEndToolBoxControl::createVclPopupWindow( vcl::Window* pParent )
{
    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
        std::make_unique<SvxLineEndWindow>(this, pParent->GetFrameWeld()));
    ToolBox* pToolBox = nullptr;
    sal_uInt16 nId = 0;
    if (!getToolboxId(nId, &pToolBox))
        return nullptr;

    const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow();
    weld::Window* pParentFrame = Application::GetFrameWeld(xParent);

    mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(m_xFrame, pParent,
        std::make_unique<SvxLineEndWindow>(m_xFrame, pParentFrame,
            MenuOrToolMenuButton(this, pToolBox, nId),
            std::bind(&SvxLineEndToolBoxControl::dispatch, this, std::placeholders::_1)));

    mxInterimPopover->Show();

diff --git a/svx/source/tbxctrls/tbcontrl.cxx b/svx/source/tbxctrls/tbcontrl.cxx
index fcd99c9..129e2b9 100644
--- a/svx/source/tbxctrls/tbcontrl.cxx
+++ b/svx/source/tbxctrls/tbcontrl.cxx
@@ -4363,7 +4363,7 @@ MenuOrToolMenuButton::MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OStrin
{
}

MenuOrToolMenuButton::MenuOrToolMenuButton(SvxColorToolBoxControl* pControl, ToolBox* pToolbar, sal_uInt16 nId)
MenuOrToolMenuButton::MenuOrToolMenuButton(svt::PopupWindowController* pControl, ToolBox* pToolbar, sal_uInt16 nId)
    : m_pMenuButton(nullptr)
    , m_pToolbar(nullptr)
    , m_pControl(pControl)