[Libreoffice-commits] core.git: formula/source include/formula include/sfx2 include/vcl reportdesign/source sc/inc sc/source sc/uiconfig solenv/sanitizers vcl/source vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Wed Apr 10 19:23:50 UTC 2019


 formula/source/ui/dlg/formula.cxx                              |   21 
 formula/source/ui/dlg/funcutl.cxx                              |  180 ++++++
 include/formula/IControlReferenceHandler.hxx                   |    4 
 include/formula/formula.hxx                                    |    4 
 include/formula/funcutl.hxx                                    |  102 +++
 include/sfx2/basedlgs.hxx                                      |    3 
 include/vcl/weld.hxx                                           |    5 
 reportdesign/source/ui/dlg/Formula.cxx                         |    9 
 reportdesign/source/ui/inc/Formula.hxx                         |    2 
 sc/inc/scmod.hxx                                               |    5 
 sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx           |   10 
 sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx   |   71 ++
 sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx |  277 ++++++++++
 sc/source/ui/app/scmod.cxx                                     |  112 +++-
 sc/source/ui/formdlg/formula.cxx                               |   16 
 sc/source/ui/inc/ChildWindowWrapper.hxx                        |   61 ++
 sc/source/ui/inc/CorrelationDialog.hxx                         |    6 
 sc/source/ui/inc/IAnyRefDialog.hxx                             |    1 
 sc/source/ui/inc/MatrixComparisonGenerator.hxx                 |   18 
 sc/source/ui/inc/StatisticsInputOutputDialog.hxx               |   72 ++
 sc/source/ui/inc/anyrefdg.hxx                                  |   88 +++
 sc/source/ui/inc/formula.hxx                                   |    3 
 sc/source/ui/inc/reffact.hxx                                   |    2 
 sc/source/ui/inc/tabvwsh.hxx                                   |    4 
 sc/source/ui/inc/validate.hxx                                  |    5 
 sc/source/ui/miscdlgs/anyrefdg.cxx                             |  235 ++++++--
 sc/source/ui/view/tabvwshc.cxx                                 |   45 +
 sc/uiconfig/scalc/ui/correlationdialog.ui                      |   19 
 solenv/sanitizers/ui/modules/scalc.suppr                       |    2 
 vcl/source/app/salvtables.cxx                                  |   94 +++
 vcl/unx/gtk3/gtk3gtkinst.cxx                                   |  109 +++
 31 files changed, 1498 insertions(+), 87 deletions(-)

New commits:
commit 3d648f76ac90fe8e28691313d0d4e78a8278e511
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Apr 9 11:23:48 2019 +0100
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Wed Apr 10 21:23:21 2019 +0200

    weld ScCorrelationDialog
    
    this is first of the calc dialogs with a range selector, so some temp
    scaffolding is required during interim case of both welded/unwelded
    in existence
    
    Change-Id: I5480179092da7b56864cef066af781b35f735ebc
    Reviewed-on: https://gerrit.libreoffice.org/70474
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx
index 68120f6bbd51..e7c5fede138d 100644
--- a/formula/source/ui/dlg/formula.cxx
+++ b/formula/source/ui/dlg/formula.cxx
@@ -77,6 +77,8 @@ class FormulaDlg_Impl
 public:
     ::std::pair<RefButton*, RefEdit*>
         RefInputStartBefore( RefEdit* pEdit, RefButton* pButton );
+    static ::std::pair<WeldRefButton*, WeldRefEdit*>
+        RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton );
     void            RefInputStartAfter();
     void            RefInputDoneAfter( bool bForced );
     bool            CalcValue( const OUString& rStrExp, OUString& rStrResult, bool bForceMatrixFormula = false );
@@ -1522,6 +1524,15 @@ void FormulaDlg_Impl::UpdateSelection()
     return aPair;
 }
 
+::std::pair<WeldRefButton*, WeldRefEdit*> FormulaDlg_Impl::RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton )
+{
+    assert(!pEdit && !pButton);
+    ::std::pair<WeldRefButton*, WeldRefEdit*> aPair;
+    aPair.first = pButton;
+    aPair.second = pEdit;
+    return aPair;
+}
+
 void FormulaDlg_Impl::RefInputStartAfter()
 {
     m_pRefBtn->SetEndImage();
@@ -1779,6 +1790,11 @@ void FormulaModalDialog::Update()
     return m_pImpl->RefInputStartBefore( pEdit, pButton );
 }
 
+::std::pair<WeldRefButton*, WeldRefEdit*> FormulaModalDialog::RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton )
+{
+    return formula::FormulaDlg_Impl::RefInputStartBefore(pEdit, pButton);
+}
+
 void FormulaModalDialog::RefInputStartAfter()
 {
     m_pImpl->RefInputStartAfter();
@@ -1868,6 +1884,11 @@ void FormulaDlg::DoEnter()
     return m_pImpl->RefInputStartBefore( pEdit, pButton );
 }
 
+::std::pair<WeldRefButton*, WeldRefEdit*> FormulaDlg::RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton )
+{
+    return formula::FormulaDlg_Impl::RefInputStartBefore(pEdit, pButton);
+}
+
 void FormulaDlg::RefInputStartAfter()
 {
     m_pImpl->RefInputStartAfter();
diff --git a/formula/source/ui/dlg/funcutl.cxx b/formula/source/ui/dlg/funcutl.cxx
index 9499992b6b7e..47c3d408d63e 100644
--- a/formula/source/ui/dlg/funcutl.cxx
+++ b/formula/source/ui/dlg/funcutl.cxx
@@ -517,6 +517,112 @@ IMPL_LINK_NOARG(RefEdit, UpdateHdl, Timer *, void)
         pAnyRefDlg->ShowReference( GetText() );
 }
 
+// class RefEdit
+
+WeldRefEdit::WeldRefEdit(std::unique_ptr<weld::Entry> xControl)
+    : xEntry(std::move(xControl))
+    , aIdle("formula RefEdit Idle")
+    , pAnyRefDlg(nullptr)
+    , pLabelWidget(nullptr)
+{
+    xEntry->connect_focus_in(LINK(this, WeldRefEdit, GetFocus));
+    xEntry->connect_focus_out(LINK(this, WeldRefEdit, LoseFocus));
+    xEntry->connect_key_press(LINK(this, WeldRefEdit, KeyInput));
+    xEntry->connect_changed(LINK(this, WeldRefEdit, Modify));
+    aIdle.SetInvokeHandler( LINK( this, WeldRefEdit, UpdateHdl ) );
+}
+
+WeldRefEdit::~WeldRefEdit()
+{
+    aIdle.ClearInvokeHandler();
+    aIdle.Stop();
+}
+
+void WeldRefEdit::SetRefString( const OUString& rStr )
+{
+    // Prevent unwanted side effects by setting only a differing string.
+    // See commit message for reasons.
+    if (xEntry->get_text() != rStr)
+        xEntry->set_text(rStr);
+}
+
+void WeldRefEdit::SetRefValid(bool bValid)
+{
+    xEntry->set_error(!bValid);
+}
+
+void WeldRefEdit::SetText(const OUString& rStr)
+{
+    xEntry->set_text(rStr);
+    UpdateHdl( &aIdle );
+}
+
+void WeldRefEdit::StartUpdateData()
+{
+    aIdle.Start();
+}
+
+void WeldRefEdit::SetReferences(IControlReferenceHandler* pDlg, weld::Label* pLabel)
+{
+    pAnyRefDlg = pDlg;
+    pLabelWidget = pLabel;
+
+    if( pDlg )
+    {
+        aIdle.SetInvokeHandler(LINK(this, WeldRefEdit, UpdateHdl));
+    }
+    else
+    {
+        aIdle.ClearInvokeHandler();
+        aIdle.Stop();
+    }
+}
+
+IMPL_LINK_NOARG(WeldRefEdit, Modify, weld::Entry&, void)
+{
+    maModifyHdl.Call(*this);
+    if (pAnyRefDlg)
+        pAnyRefDlg->HideReference();
+}
+
+IMPL_LINK(WeldRefEdit, KeyInput, const KeyEvent&, rKEvt, bool)
+{
+    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+    if (pAnyRefDlg && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_F2)
+    {
+        pAnyRefDlg->ReleaseFocus( this );
+        return true;
+    }
+
+    switch (rKeyCode.GetCode())
+    {
+        case KEY_RETURN:
+        case KEY_ESCAPE:
+            return maActivateHdl.Call(*GetWidget());
+    }
+
+    return false;
+}
+
+IMPL_LINK_NOARG(WeldRefEdit, GetFocus, weld::Widget&, void)
+{
+    maGetFocusHdl.Call(*this);
+    StartUpdateData();
+}
+
+IMPL_LINK_NOARG(WeldRefEdit, LoseFocus, weld::Widget&, void)
+{
+    maLoseFocusHdl.Call(*this);
+    if( pAnyRefDlg )
+        pAnyRefDlg->HideReference();
+}
+
+IMPL_LINK_NOARG(WeldRefEdit, UpdateHdl, Timer *, void)
+{
+    if( pAnyRefDlg )
+        pAnyRefDlg->ShowReference(xEntry->get_text());
+}
+
 //class RefButton
 RefButton::RefButton( vcl::Window* _pParent, WinBits nStyle ) :
     ImageButton(_pParent, nStyle),
@@ -590,6 +696,80 @@ void RefButton::LoseFocus()
         pRefEdit->Modify();
 }
 
+//class RefButton
+WeldRefButton::WeldRefButton(std::unique_ptr<weld::Button> xControl)
+    : xButton(std::move(xControl))
+    , pAnyRefDlg( nullptr )
+    , pRefEdit( nullptr )
+{
+    xButton->connect_focus_in(LINK(this, WeldRefButton, GetFocus));
+    xButton->connect_focus_out(LINK(this, WeldRefButton, LoseFocus));
+    xButton->connect_key_press(LINK(this, WeldRefButton, KeyInput));
+    xButton->connect_clicked(LINK(this, WeldRefButton, Click));
+    SetStartImage();
+}
+
+WeldRefButton::~WeldRefButton()
+{
+}
+
+void WeldRefButton::SetStartImage()
+{
+    xButton->set_from_icon_name(RID_BMP_REFBTN1);
+    xButton->set_tooltip_text(ForResId(RID_STR_SHRINK));
+}
+
+void WeldRefButton::SetEndImage()
+{
+    xButton->set_from_icon_name(RID_BMP_REFBTN2);
+    xButton->set_tooltip_text(ForResId(RID_STR_EXPAND));
+}
+
+void WeldRefButton::SetReferences( IControlReferenceHandler* pDlg, WeldRefEdit* pEdit )
+{
+    pAnyRefDlg = pDlg;
+    pRefEdit = pEdit;
+}
+
+IMPL_LINK_NOARG(WeldRefButton, Click, weld::Button&, void)
+{
+    if( pAnyRefDlg )
+        pAnyRefDlg->ToggleCollapsed( pRefEdit, this );
+}
+
+IMPL_LINK(WeldRefButton, KeyInput, const KeyEvent&, rKEvt, bool)
+{
+    const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+    if (pAnyRefDlg && !rKeyCode.GetModifier() && rKeyCode.GetCode() == KEY_F2)
+    {
+        pAnyRefDlg->ReleaseFocus( pRefEdit );
+        return true;
+    }
+
+    switch (rKeyCode.GetCode())
+    {
+        case KEY_RETURN:
+        case KEY_ESCAPE:
+            return maActivateHdl.Call(*GetWidget());
+    }
+
+    return false;
+}
+
+IMPL_LINK_NOARG(WeldRefButton, GetFocus, weld::Widget&, void)
+{
+    maGetFocusHdl.Call(*this);
+    if (pRefEdit)
+        pRefEdit->StartUpdateData();
+}
+
+IMPL_LINK_NOARG(WeldRefButton, LoseFocus, weld::Widget&, void)
+{
+    maLoseFocusHdl.Call(*this);
+    if (pRefEdit)
+        pRefEdit->DoModify();
+}
+
 } // formula
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/formula/IControlReferenceHandler.hxx b/include/formula/IControlReferenceHandler.hxx
index e1096c47ae38..f73a7618d346 100644
--- a/include/formula/IControlReferenceHandler.hxx
+++ b/include/formula/IControlReferenceHandler.hxx
@@ -26,14 +26,18 @@
 namespace formula
 {
     class RefEdit;
+    class WeldRefEdit;
     class RefButton;
+    class WeldRefButton;
     class FORMULA_DLLPUBLIC SAL_NO_VTABLE IControlReferenceHandler
     {
     public:
         virtual void ShowReference(const OUString& _sRef) = 0;
         virtual void HideReference( bool bDoneRefMode = true ) = 0;
         virtual void ReleaseFocus( RefEdit* pEdit ) = 0;
+        virtual void ReleaseFocus( WeldRefEdit* pEdit ) = 0;
         virtual void ToggleCollapsed( RefEdit* pEdit, RefButton* pButton ) = 0;
+        virtual void ToggleCollapsed( WeldRefEdit* pEdit, WeldRefButton* pButton ) = 0;
 
     protected:
         ~IControlReferenceHandler() {}
diff --git a/include/formula/formula.hxx b/include/formula/formula.hxx
index 201a598891e4..defd1ecfd1a8 100644
--- a/include/formula/formula.hxx
+++ b/include/formula/formula.hxx
@@ -56,7 +56,9 @@ class FormulaDlg_Impl;
 class IControlReferenceHandler;
 class FormulaHelper;
 class RefEdit;
+class WeldRefEdit;
 class RefButton;
+class WeldRefButton;
 class FormEditData;
 
 class FORMULA_DLLPUBLIC FormulaModalDialog :   public ModalDialog, public formula::IFormulaEditorHelper
@@ -76,6 +78,7 @@ protected:
 
     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
     ::std::pair<RefButton*,RefEdit*> RefInputStartBefore( RefEdit* pEdit, RefButton* pButton );
+    static ::std::pair<WeldRefButton*,WeldRefEdit*> RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton );
     void            RefInputStartAfter();
     void            RefInputDoneAfter();
 
@@ -110,6 +113,7 @@ protected:
 
     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
     ::std::pair<RefButton*,RefEdit*> RefInputStartBefore( RefEdit* pEdit, RefButton* pButton );
+    static ::std::pair<WeldRefButton*,WeldRefEdit*> RefInputStartBefore( WeldRefEdit* pEdit, WeldRefButton* pButton );
     void            RefInputStartAfter();
     void            RefInputDoneAfter( bool bForced );
 
diff --git a/include/formula/funcutl.hxx b/include/formula/funcutl.hxx
index 0a4c25d1236c..5a6c095db77e 100644
--- a/include/formula/funcutl.hxx
+++ b/include/formula/funcutl.hxx
@@ -28,6 +28,7 @@
 #include <vcl/edit.hxx>
 #include <vcl/idle.hxx>
 #include <vcl/image.hxx>
+#include <vcl/weld.hxx>
 #include <vcl/vclptr.hxx>
 
 class KeyEvent;
@@ -83,6 +84,74 @@ public:
     }
 };
 
+class FORMULA_DLLPUBLIC WeldRefEdit
+{
+private:
+    std::unique_ptr<weld::Entry> xEntry;
+    Idle aIdle;
+    IControlReferenceHandler* pAnyRefDlg; // parent dialog
+    weld::Label* pLabelWidget;
+    Link<WeldRefEdit&,void> maGetFocusHdl;
+    Link<WeldRefEdit&,void> maLoseFocusHdl;
+    Link<WeldRefEdit&,void> maModifyHdl;
+    Link<weld::Widget&,bool> maActivateHdl;
+
+    DECL_LINK( UpdateHdl, Timer*, void );
+
+protected:
+    DECL_LINK(KeyInput, const KeyEvent&, bool);
+    DECL_LINK(GetFocus, weld::Widget&, void);
+    DECL_LINK(LoseFocus, weld::Widget&, void);
+    DECL_LINK(Modify, weld::Entry&, void);
+
+public:
+    WeldRefEdit(std::unique_ptr<weld::Entry> xControl);
+    weld::Widget* GetWidget() const { return xEntry.get(); }
+    ~WeldRefEdit();
+
+    void SetRefString( const OUString& rStr );
+
+    /**
+     * Flag reference valid or invalid, which in turn changes the visual
+     * appearance of the control accordingly.
+     */
+    void SetRefValid(bool bValid);
+
+    void SetText(const OUString& rStr);
+    OUString GetText() const
+    {
+        return xEntry->get_text();
+    }
+
+    void StartUpdateData();
+
+    void SetReferences( IControlReferenceHandler* pDlg, weld::Label *pLabelWidget );
+
+    void DoModify()
+    {
+        Modify(*xEntry);
+    }
+
+    void GrabFocus()
+    {
+        xEntry->grab_focus();
+    }
+
+    void SelectAll()
+    {
+        xEntry->select_region(0, -1);
+    }
+
+    weld::Label* GetLabelWidgetForShrinkMode()
+    {
+        return pLabelWidget;
+    }
+
+    void SetGetFocusHdl(const Link<WeldRefEdit&,void>& rLink) { maGetFocusHdl = rLink; }
+    void SetLoseFocusHdl(const Link<WeldRefEdit&,void>& rLink) { maLoseFocusHdl = rLink; }
+    void SetModifyHdl(const Link<WeldRefEdit&,void>& rLink) { maModifyHdl = rLink; }
+    void SetActivateHdl(const Link<weld::Widget&,bool>& rLink) { maActivateHdl = rLink; }
+};
 
 class FORMULA_DLLPUBLIC RefButton : public ImageButton
 {
@@ -113,6 +182,39 @@ public:
     }
 };
 
+class FORMULA_DLLPUBLIC WeldRefButton
+{
+private:
+    std::unique_ptr<weld::Button> xButton;
+    IControlReferenceHandler* pAnyRefDlg;   // parent dialog
+    WeldRefEdit*              pRefEdit;     // associated Edit-Control
+    Link<WeldRefButton&,void> maGetFocusHdl;
+    Link<WeldRefButton&,void> maLoseFocusHdl;
+    Link<weld::Widget&,bool> maActivateHdl;
+
+protected:
+    DECL_LINK(Click, weld::Button&, void);
+    DECL_LINK(KeyInput, const KeyEvent&, bool);
+    DECL_LINK(GetFocus, weld::Widget&, void);
+    DECL_LINK(LoseFocus, weld::Widget&, void);
+
+public:
+    WeldRefButton(std::unique_ptr<weld::Button> xControl);
+    weld::Widget* GetWidget() const { return xButton.get(); }
+    ~WeldRefButton();
+    void SetReferences(IControlReferenceHandler* pDlg, WeldRefEdit* pEdit);
+    void SetStartImage();
+    void SetEndImage();
+    void DoRef()
+    {
+        Click(*xButton);
+    }
+    void SetGetFocusHdl(const Link<WeldRefButton&,void>& rLink) { maGetFocusHdl = rLink; }
+    void SetLoseFocusHdl(const Link<WeldRefButton&,void>& rLink) { maLoseFocusHdl = rLink; }
+    void SetActivateHdl(const Link<weld::Widget&,bool>& rLink) { maActivateHdl = rLink; }
+};
+
+
 } // formula
 
 #endif // INCLUDED_FORMULA_FUNCUTL_HXX
diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx
index 7a29b9f1bd02..6706010c6c51 100644
--- a/include/sfx2/basedlgs.hxx
+++ b/include/sfx2/basedlgs.hxx
@@ -139,9 +139,10 @@ class SFX2_DLLPUBLIC SfxModelessDialogController : public SfxDialogController
 protected:
     SfxModelessDialogController(SfxBindings*, SfxChildWindow* pChildWin,
         weld::Window* pParent, const OUString& rUIXMLDescription, const OString& rID);
-    virtual ~SfxModelessDialogController() override;
 
 public:
+    virtual ~SfxModelessDialogController() override;
+
     void                    Initialize (SfxChildWinInfo const * pInfo);
     bool                    IsClosing() const;
     virtual void            Close() override;
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 3b2fea407aec..2a7511b419fc 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -383,6 +383,11 @@ public:
     virtual Button* get_widget_for_response(int response) = 0;
     virtual 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*>& rLink)
         = 0;
 };
diff --git a/reportdesign/source/ui/dlg/Formula.cxx b/reportdesign/source/ui/dlg/Formula.cxx
index 3e3d5f03206f..ac91552c351d 100644
--- a/reportdesign/source/ui/dlg/Formula.cxx
+++ b/reportdesign/source/ui/dlg/Formula.cxx
@@ -201,6 +201,10 @@ void FormulaDialog::ReleaseFocus( RefEdit* /*pEdit*/)
 {
 }
 
+void FormulaDialog::ReleaseFocus( WeldRefEdit* /*pEdit*/)
+{
+}
+
 void FormulaDialog::ToggleCollapsed( RefEdit* _pEdit, RefButton* _pButton)
 {
     ::std::pair<RefButton*,RefEdit*> aPair = RefInputStartBefore( _pEdit, _pButton );
@@ -228,6 +232,11 @@ void FormulaDialog::ToggleCollapsed( RefEdit* _pEdit, RefButton* _pButton)
 
 }
 
+void FormulaDialog::ToggleCollapsed( WeldRefEdit* /*_pEdit*/, WeldRefButton* /*_pButton*/)
+{
+    assert(false);
+}
+
 IMPL_LINK( FormulaDialog, OnClickHdl, OAddFieldWindow& ,_rAddFieldDlg, void)
 {
     const uno::Sequence< beans::PropertyValue > aArgs = _rAddFieldDlg.getSelectedFieldDescriptors();
diff --git a/reportdesign/source/ui/inc/Formula.hxx b/reportdesign/source/ui/inc/Formula.hxx
index 68c20917af4f..e28438325329 100644
--- a/reportdesign/source/ui/inc/Formula.hxx
+++ b/reportdesign/source/ui/inc/Formula.hxx
@@ -101,7 +101,9 @@ public:
     virtual void ShowReference(const OUString& _sRef) override;
     virtual void HideReference( bool bDoneRefMode = true ) override;
     virtual void ReleaseFocus( formula::RefEdit* pEdit ) override;
+    virtual void ReleaseFocus( formula::WeldRefEdit* pEdit ) override;
     virtual void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override;
+    virtual void ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) override;
 };
 
 
diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx
index 883da0ba9be6..2a3fbc04b748 100644
--- a/sc/inc/scmod.hxx
+++ b/sc/inc/scmod.hxx
@@ -75,6 +75,7 @@ class ScSelectionTransferObj;
 class ScFormEditData;
 class ScMarkData;
 struct ScDragData;
+class SfxModelessDialogController;
 
 class ScModule: public SfxModule, public SfxListener, public utl::ConfigurationListener
 {
@@ -108,6 +109,7 @@ class ScModule: public SfxModule, public SfxListener, public utl::ConfigurationL
     bool                m_bIsInSharedDocSaving:1;
 
     std::map<sal_uInt16, std::vector<VclPtr<vcl::Window> > > m_mapRefWindow;
+    std::map<sal_uInt16, std::vector<SfxModelessDialogController*>> m_mapRefController;
 
     css::uno::Reference< ooo::vba::XSinkCaller > mxAutomationApplicationEventsCaller;
 
@@ -250,6 +252,9 @@ public:
     SC_DLLPUBLIC void   UnregisterRefWindow( sal_uInt16 nSlotId, vcl::Window *pWnd );
     SC_DLLPUBLIC vcl::Window * Find1RefWindow( sal_uInt16 nSlotId, vcl::Window *pWndAncestor );
 
+    SC_DLLPUBLIC void   RegisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd );
+    SC_DLLPUBLIC void   UnregisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd );
+
     SC_DLLPUBLIC void RegisterAutomationApplicationEventsCaller(css::uno::Reference< ooo::vba::XSinkCaller > const& xCaller);
     SC_DLLPUBLIC void CallAutomationApplicationEventSinks(const OUString& Method, css::uno::Sequence< css::uno::Any >& Arguments);
 };
diff --git a/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx b/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx
index c7a8a7be932e..d1463f608b3d 100644
--- a/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/CorrelationDialog.cxx
@@ -15,15 +15,15 @@
 
 ScCorrelationDialog::ScCorrelationDialog(
                         SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
-                        vcl::Window* pParent, ScViewData* pViewData ) :
-    ScMatrixComparisonGenerator(
+                        weld::Window* pParent, ScViewData* pViewData ) :
+    ScMatrixComparisonGeneratorController(
             pSfxBindings, pChildWindow, pParent, pViewData,
-            "CorrelationDialog", "modules/scalc/ui/correlationdialog.ui" )
+            "modules/scalc/ui/correlationdialog.ui", "CorrelationDialog")
 {}
 
-bool ScCorrelationDialog::Close()
+void ScCorrelationDialog::Close()
 {
-    return DoClose( ScCorrelationDialogWrapper::GetChildWindowId() );
+    DoClose(ScCorrelationDialogWrapper::GetChildWindowId());
 }
 
 const OUString ScCorrelationDialog::getLabel()
diff --git a/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx b/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx
index d5aa05933f24..487602fe8a1a 100644
--- a/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx
+++ b/sc/source/ui/StatisticsDialogs/MatrixComparisonGenerator.cxx
@@ -109,4 +109,75 @@ ScRange ScMatrixComparisonGenerator::ApplyOutput(ScDocShell* pDocShell)
     return ScRange(output.mMinimumAddress, output.mMaximumAddress);
 }
 
+ScMatrixComparisonGeneratorController::ScMatrixComparisonGeneratorController(
+                                    SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
+                                    weld::Window* pParent, ScViewData* pViewData,
+                                    const OUString& rUiXmlDescription,
+                                    const OString& rID)
+    : ScStatisticsInputOutputDialogController(pSfxBindings, pChildWindow, pParent, pViewData, rUiXmlDescription, rID)
+{}
+
+ScMatrixComparisonGeneratorController::~ScMatrixComparisonGeneratorController()
+{}
+
+const char* ScMatrixComparisonGeneratorController::GetUndoNameId()
+{
+    return STR_CORRELATION_UNDO_NAME;
+}
+
+ScRange ScMatrixComparisonGeneratorController::ApplyOutput(ScDocShell* pDocShell)
+{
+    AddressWalkerWriter output(mOutputAddress, pDocShell, mDocument,
+            formula::FormulaGrammar::mergeToGrammar( formula::FormulaGrammar::GRAM_ENGLISH, mAddressDetails.eConv));
+    FormulaTemplate aTemplate(mDocument);
+
+    SCTAB inTab = mInputRange.aStart.Tab();
+
+    ScRangeList aRangeList = (mGroupedBy == BY_COLUMN) ?
+        MakeColumnRangeList(inTab, mInputRange.aStart, mInputRange.aEnd) :
+        MakeRowRangeList(inTab, mInputRange.aStart, mInputRange.aEnd);
+
+    // labels
+    output.writeString(getLabel());
+    output.nextColumn();
+
+    const OUString strWildcardNumber("%NUMBER%");
+
+    // write labels to columns
+    for (size_t i = 0; i < aRangeList.size(); i++)
+    {
+        if (mGroupedBy == BY_COLUMN)
+            aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE));
+        else
+            aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE));
+
+        aTemplate.applyNumber(strWildcardNumber, i + 1);
+        output.writeString(aTemplate.getTemplate());
+        output.nextColumn();
+    }
+
+    // write labels to rows
+    output.resetColumn();
+    output.nextRow();
+    for (size_t i = 0; i < aRangeList.size(); i++)
+    {
+        if (mGroupedBy == BY_COLUMN)
+            aTemplate.setTemplate(ScResId(STR_COLUMN_LABEL_TEMPLATE));
+        else
+            aTemplate.setTemplate(ScResId(STR_ROW_LABEL_TEMPLATE));
+
+        aTemplate.applyNumber(strWildcardNumber, i + 1);
+        output.writeString(aTemplate.getTemplate());
+        output.nextRow();
+    }
+
+    // write correlation formulas
+    output.reset();
+    output.push(1, 1);
+
+    lclWriteCorrelationFormulas(output, aTemplate, aRangeList, getTemplate());
+
+    return ScRange(output.mMinimumAddress, output.mMaximumAddress);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx b/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx
index 8d630ebc7e63..a55e34092edc 100644
--- a/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/StatisticsInputOutputDialog.cxx
@@ -296,4 +296,281 @@ void ScStatisticsInputOutputDialog::ValidateDialogInput()
         mpButtonOk->Disable();
 }
 
+ScRangeList ScStatisticsInputOutputDialogController::MakeColumnRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd)
+{
+    ScRangeList aRangeList;
+    for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
+    {
+        ScRange aColumnRange (
+            ScAddress(inCol, aStart.Row(), aTab),
+            ScAddress(inCol, aEnd.Row(),   aTab) );
+
+        aRangeList.push_back(aColumnRange);
+    }
+    return aRangeList;
+}
+
+ScRangeList ScStatisticsInputOutputDialogController::MakeRowRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd)
+{
+    ScRangeList aRangeList;
+    for (SCROW inRow = aStart.Row(); inRow <= aEnd.Row(); inRow++)
+    {
+        ScRange aRowRange (
+            ScAddress(aStart.Col(), inRow, aTab),
+            ScAddress(aEnd.Col(),   inRow, aTab) );
+
+        aRangeList.push_back(aRowRange);
+    }
+    return aRangeList;
+}
+
+ScStatisticsInputOutputDialogController::ScStatisticsInputOutputDialogController(
+                    SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
+                    weld::Window* pParent, ScViewData* pViewData, const OUString& rUIXMLDescription, const OString& rID)
+    : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, rUIXMLDescription, rID)
+    , mxInputRangeLabel(m_xBuilder->weld_label("input-range-label"))
+    , mxInputRangeEdit(new formula::WeldRefEdit(m_xBuilder->weld_entry("input-range-edit")))
+    , mxInputRangeButton(new formula::WeldRefButton(m_xBuilder->weld_button("input-range-button")))
+    , mxOutputRangeLabel(m_xBuilder->weld_label("output-range-label"))
+    , mxOutputRangeEdit(new formula::WeldRefEdit(m_xBuilder->weld_entry("output-range-edit")))
+    , mxOutputRangeButton(new formula::WeldRefButton(m_xBuilder->weld_button("output-range-button")))
+    , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button("groupedby-columns-radio"))
+    , mxGroupByRowsRadio(m_xBuilder->weld_radio_button("groupedby-rows-radio"))
+    , mViewData(pViewData)
+    , mDocument(pViewData->GetDocument())
+    , mInputRange(ScAddress::INITIALIZE_INVALID)
+    , mAddressDetails(mDocument->GetAddressConvention(), 0, 0)
+    , mOutputAddress(ScAddress::INITIALIZE_INVALID)
+    , mGroupedBy(BY_COLUMN)
+    , mxButtonOk(m_xBuilder->weld_button("ok"))
+    , mpActiveEdit(nullptr)
+    , mCurrentAddress(pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo())
+    , mDialogLostFocus(false)
+{
+    mxInputRangeEdit->SetReferences(this, mxInputRangeLabel.get());
+    mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get());
+
+    mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
+    mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
+
+    Init();
+    GetRangeFromSelection();
+}
+
+ScStatisticsInputOutputDialogController::~ScStatisticsInputOutputDialogController()
+{
+}
+
+void ScStatisticsInputOutputDialogController::Init()
+{
+    mxButtonOk->connect_clicked( LINK( this, ScStatisticsInputOutputDialogController, OkClicked ) );
+    mxButtonOk->set_sensitive(false);
+
+    Link<formula::WeldRefEdit&,void> aEditLink = LINK( this, ScStatisticsInputOutputDialogController, GetEditFocusHandler );
+    mxInputRangeEdit->SetGetFocusHdl( aEditLink );
+    mxOutputRangeEdit->SetGetFocusHdl( aEditLink );
+    Link<formula::WeldRefButton&,void> aButtonLink = LINK( this, ScStatisticsInputOutputDialogController, GetButtonFocusHandler );
+    mxInputRangeButton->SetGetFocusHdl( aButtonLink );
+    mxOutputRangeButton->SetGetFocusHdl( aButtonLink );
+
+    aEditLink = LINK( this, ScStatisticsInputOutputDialogController, LoseEditFocusHandler );
+    mxInputRangeEdit->SetLoseFocusHdl( aEditLink );
+    mxOutputRangeEdit->SetLoseFocusHdl( aEditLink );
+    aButtonLink = LINK( this, ScStatisticsInputOutputDialogController, LoseButtonFocusHandler );
+    mxInputRangeButton->SetLoseFocusHdl( aButtonLink );
+    mxOutputRangeButton->SetLoseFocusHdl( aButtonLink );
+
+    Link<formula::WeldRefEdit&,void> aLink2 = LINK( this, ScStatisticsInputOutputDialogController, RefInputModifyHandler);
+    mxInputRangeEdit->SetModifyHdl( aLink2);
+    mxOutputRangeEdit->SetModifyHdl( aLink2);
+
+    mxOutputRangeEdit->GrabFocus();
+
+    mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialogController, GroupByChanged ) );
+    mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialogController, GroupByChanged ) );
+
+    mxGroupByColumnsRadio->set_active(true);
+    mxGroupByRowsRadio->set_active(false);
+}
+
+void ScStatisticsInputOutputDialogController::GetRangeFromSelection()
+{
+    mViewData->GetSimpleArea(mInputRange);
+    OUString aCurrentString(mInputRange.Format(ScRefFlags::RANGE_ABS_3D, mDocument, mAddressDetails));
+    mxInputRangeEdit->SetText(aCurrentString);
+}
+
+void ScStatisticsInputOutputDialogController::SetActive()
+{
+    if ( mDialogLostFocus )
+    {
+        mDialogLostFocus = false;
+        if( mpActiveEdit )
+            mpActiveEdit->GrabFocus();
+    }
+    else
+    {
+        m_xDialog->grab_focus();
+    }
+    RefInputDone();
+}
+
+void ScStatisticsInputOutputDialogController::SetReference( const ScRange& rReferenceRange, ScDocument* pDocument )
+{
+    if ( mpActiveEdit )
+    {
+        if ( rReferenceRange.aStart != rReferenceRange.aEnd )
+            RefInputStart( mpActiveEdit );
+
+        OUString aReferenceString;
+
+        if (mpActiveEdit == mxInputRangeEdit.get())
+        {
+            mInputRange = rReferenceRange;
+            aReferenceString = mInputRange.Format(ScRefFlags::RANGE_ABS_3D, pDocument, mAddressDetails);
+            mxInputRangeEdit->SetRefString( aReferenceString );
+        }
+        else if (mpActiveEdit == mxOutputRangeEdit.get())
+        {
+            mOutputAddress = rReferenceRange.aStart;
+
+            ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
+                                                             ScRefFlags::ADDR_ABS :
+                                                             ScRefFlags::ADDR_ABS_3D;
+            aReferenceString = mOutputAddress.Format(nFormat, pDocument, pDocument->GetAddressConvention());
+            mxOutputRangeEdit->SetRefString( aReferenceString );
+        }
+    }
+
+    ValidateDialogInput();
+}
+
+IMPL_LINK_NOARG( ScStatisticsInputOutputDialogController, OkClicked, weld::Button&, void )
+{
+    CalculateInputAndWriteToOutput();
+    response(RET_OK);
+}
+
+IMPL_LINK(ScStatisticsInputOutputDialogController, GetEditFocusHandler, formula::WeldRefEdit&, rCtrl, void)
+{
+    mpActiveEdit = nullptr;
+
+    if (&rCtrl == mxInputRangeEdit.get())
+        mpActiveEdit = mxInputRangeEdit.get();
+    if (&rCtrl == mxOutputRangeEdit.get())
+        mpActiveEdit = mxOutputRangeEdit.get();
+
+    if (mpActiveEdit)
+        mpActiveEdit->SelectAll();
+}
+
+IMPL_LINK(ScStatisticsInputOutputDialogController, GetButtonFocusHandler, formula::WeldRefButton&, rCtrl, void)
+{
+    mpActiveEdit = nullptr;
+
+    if (&rCtrl == mxInputRangeButton.get())
+        mpActiveEdit = mxInputRangeEdit.get();
+    else if (&rCtrl == mxOutputRangeButton.get())
+        mpActiveEdit = mxOutputRangeEdit.get();
+
+    if (mpActiveEdit)
+        mpActiveEdit->SelectAll();
+}
+
+IMPL_LINK_NOARG(ScStatisticsInputOutputDialogController, LoseEditFocusHandler, formula::WeldRefEdit&, void)
+{
+    mDialogLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(ScStatisticsInputOutputDialogController, LoseButtonFocusHandler, formula::WeldRefButton&, void)
+{
+    mDialogLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG( ScStatisticsInputOutputDialogController, GroupByChanged, weld::ToggleButton&, void )
+{
+    if (mxGroupByColumnsRadio->get_active())
+        mGroupedBy = BY_COLUMN;
+    else if (mxGroupByRowsRadio->get_active())
+        mGroupedBy = BY_ROW;
+
+    ValidateDialogInput();
+}
+
+IMPL_LINK_NOARG( ScStatisticsInputOutputDialogController, RefInputModifyHandler, formula::WeldRefEdit&, void )
+{
+    if ( mpActiveEdit )
+    {
+        if (mpActiveEdit == mxInputRangeEdit.get())
+        {
+            ScRangeList aRangeList;
+            bool bValid = ParseWithNames( aRangeList, mxInputRangeEdit->GetText(), mDocument);
+            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
+            if (pRange)
+            {
+                mInputRange = *pRange;
+                // Highlight the resulting range.
+                mxInputRangeEdit->StartUpdateData();
+            }
+            else
+            {
+                mInputRange = ScRange( ScAddress::INITIALIZE_INVALID);
+            }
+        }
+        else if (mpActiveEdit == mxOutputRangeEdit.get())
+        {
+            ScRangeList aRangeList;
+            bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument);
+            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
+            if (pRange)
+            {
+                mOutputAddress = pRange->aStart;
+
+                // Crop output range to top left address for Edit field.
+                if (pRange->aStart != pRange->aEnd)
+                {
+                    ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
+                                                                     ScRefFlags::ADDR_ABS :
+                                                                     ScRefFlags::ADDR_ABS_3D;
+                    OUString aReferenceString = mOutputAddress.Format(nFormat, mDocument, mDocument->GetAddressConvention());
+                    mxOutputRangeEdit->SetRefString( aReferenceString );
+                }
+
+                // Highlight the resulting range.
+                mxOutputRangeEdit->StartUpdateData();
+            }
+            else
+            {
+                mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
+            }
+        }
+    }
+
+    ValidateDialogInput();
+}
+
+void ScStatisticsInputOutputDialogController::CalculateInputAndWriteToOutput()
+{
+    OUString aUndo(ScResId(GetUndoNameId()));
+    ScDocShell* pDocShell = mViewData->GetDocShell();
+    SfxUndoManager* pUndoManager = pDocShell->GetUndoManager();
+    pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData->GetViewShell()->GetViewShellId() );
+
+    ScRange aOutputRange = ApplyOutput(pDocShell);
+
+    pUndoManager->LeaveListAction();
+    pDocShell->PostPaint( aOutputRange, PaintPartFlags::Grid );
+}
+
+bool ScStatisticsInputOutputDialogController::InputRangesValid()
+{
+    return mInputRange.IsValid() && mOutputAddress.IsValid();
+}
+
+void ScStatisticsInputOutputDialogController::ValidateDialogInput()
+{
+    // Enable OK button if all inputs are ok.
+    mxButtonOk->set_sensitive(InputRangesValid());
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx
index dcae91f597b8..7235c02076fb 100644
--- a/sc/source/ui/app/scmod.cxx
+++ b/sc/source/ui/app/scmod.cxx
@@ -1567,10 +1567,20 @@ bool ScModule::IsModalMode(SfxObjectShell* pDocSh)
         SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId );
         if ( pChildWnd )
         {
-            IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
-            assert(pRefDlg);
-            bIsModal = pChildWnd->IsVisible() && pRefDlg &&
-                !( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) );
+            if (pChildWnd->GetWindow())
+            {
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
+                assert(pRefDlg);
+                bIsModal = pChildWnd->IsVisible() && pRefDlg &&
+                    !( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) );
+            }
+            if (pChildWnd->GetController())
+            {
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
+                assert(pRefDlg);
+                bIsModal = pChildWnd->IsVisible() && pRefDlg &&
+                    !( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) );
+            }
         }
     }
     else if (pDocSh)
@@ -1642,9 +1652,18 @@ bool ScModule::IsFormulaMode()
         SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId );
         if ( pChildWnd )
         {
-            IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
-            assert(pRefDlg);
-            bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode();
+            if (pChildWnd->GetWindow())
+            {
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
+                assert(pRefDlg);
+                bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode();
+            }
+            if (pChildWnd->GetController())
+            {
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
+                assert(pRefDlg);
+                bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode();
+            }
         }
     }
     else
@@ -1694,14 +1713,29 @@ void ScModule::SetReference( const ScRange& rRef, ScDocument* pDoc,
                 aNew.aEnd.SetTab(nEndTab);
             }
 
-            IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
-            assert(pRefDlg);
-            if(pRefDlg)
+            if (pChildWnd->GetWindow())
             {
-                // hide the (color) selection now instead of later from LoseFocus,
-                // don't abort the ref input that causes this call (bDoneRefMode = sal_False)
-                pRefDlg->HideReference( false );
-                pRefDlg->SetReference( aNew, pDoc );
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
+                assert(pRefDlg);
+                if(pRefDlg)
+                {
+                    // hide the (color) selection now instead of later from LoseFocus,
+                    // don't abort the ref input that causes this call (bDoneRefMode = sal_False)
+                    pRefDlg->HideReference( false );
+                    pRefDlg->SetReference( aNew, pDoc );
+                }
+            }
+            if (pChildWnd->GetController())
+            {
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
+                assert(pRefDlg);
+                if(pRefDlg)
+                {
+                    // hide the (color) selection now instead of later from LoseFocus,
+                    // don't abort the ref input that causes this call (bDoneRefMode = sal_False)
+                    pRefDlg->HideReference( false );
+                    pRefDlg->SetReference( aNew, pDoc );
+                }
             }
         }
     }
@@ -1760,11 +1794,23 @@ void ScModule::EndReference()
         OSL_ENSURE( pChildWnd, "NoChildWin" );
         if ( pChildWnd )
         {
-            IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
-            assert(pRefDlg);
-            if(pRefDlg)
+            if (pChildWnd->GetWindow())
             {
-                pRefDlg->SetActive();
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
+                assert(pRefDlg);
+                if(pRefDlg)
+                {
+                    pRefDlg->SetActive();
+                }
+            }
+            if (pChildWnd->GetController())
+            {
+                IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
+                assert(pRefDlg);
+                if(pRefDlg)
+                {
+                    pRefDlg->SetActive();
+                }
             }
         }
     }
@@ -2161,6 +2207,36 @@ void  ScModule::UnregisterRefWindow( sal_uInt16 nSlotId, vcl::Window *pWnd )
         m_mapRefWindow.erase( nSlotId );
 }
 
+void ScModule::RegisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd )
+{
+    std::vector<SfxModelessDialogController*> & rlRefWindow = m_mapRefController[nSlotId];
+
+    if( std::find( rlRefWindow.begin(), rlRefWindow.end(), pWnd ) == rlRefWindow.end() )
+    {
+        rlRefWindow.emplace_back(pWnd );
+    }
+}
+
+void  ScModule::UnregisterRefController( sal_uInt16 nSlotId, SfxModelessDialogController *pWnd )
+{
+    auto iSlot = m_mapRefController.find( nSlotId );
+
+    if( iSlot == m_mapRefController.end() )
+        return;
+
+    std::vector<SfxModelessDialogController* > & rlRefWindow = iSlot->second;
+
+    auto i = std::find( rlRefWindow.begin(), rlRefWindow.end(), pWnd );
+
+    if( i == rlRefWindow.end() )
+        return;
+
+    rlRefWindow.erase( i );
+
+    if( rlRefWindow.empty() )
+        m_mapRefController.erase( nSlotId );
+}
+
 vcl::Window *  ScModule::Find1RefWindow( sal_uInt16 nSlotId, vcl::Window *pWndAncestor )
 {
     if (!pWndAncestor)
diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx
index 56d96a456ea9..4dd504d7d809 100644
--- a/sc/source/ui/formdlg/formula.cxx
+++ b/sc/source/ui/formdlg/formula.cxx
@@ -393,6 +393,14 @@ void ScFormulaDlg::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* p
     RefInputStartAfter();
 }
 
+void ScFormulaDlg::RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton )
+{
+    pEdit->SelectAll();
+    ::std::pair<formula::WeldRefButton*,formula::WeldRefEdit*> aPair = RefInputStartBefore( pEdit, pButton );
+    m_aHelper.RefInputStart( aPair.second, aPair.first);
+    RefInputStartAfter();
+}
+
 void ScFormulaDlg::RefInputDone( bool bForced )
 {
     m_aHelper.RefInputDone( bForced );
@@ -531,10 +539,18 @@ void ScFormulaDlg::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton*
 {
     m_aHelper.ToggleCollapsed(pEdit,pButton);
 }
+void ScFormulaDlg::ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton)
+{
+    m_aHelper.ToggleCollapsed(pEdit,pButton);
+}
 void ScFormulaDlg::ReleaseFocus( formula::RefEdit* pEdit)
 {
     m_aHelper.ReleaseFocus(pEdit);
 }
+void ScFormulaDlg::ReleaseFocus( formula::WeldRefEdit* pEdit)
+{
+    m_aHelper.ReleaseFocus(pEdit);
+}
 void ScFormulaDlg::dispatch(bool _bOK, bool _bMatrixChecked)
 {
     SfxBoolItem   aRetItem( SID_DLG_RETOK, _bOK );
diff --git a/sc/source/ui/inc/ChildWindowWrapper.hxx b/sc/source/ui/inc/ChildWindowWrapper.hxx
index 60382774de03..1ad232a7b91b 100644
--- a/sc/source/ui/inc/ChildWindowWrapper.hxx
+++ b/sc/source/ui/inc/ChildWindowWrapper.hxx
@@ -88,6 +88,67 @@ private:
     }
 };
 
+template <sal_Int16 WindowID>
+class ChildControllerWrapper : public SfxChildWindow
+{
+public:
+    ChildControllerWrapper(vcl::Window* pParentP, sal_uInt16 nId,
+                           SfxBindings* pBindings, const SfxChildWinInfo* pInfo)
+        : SfxChildWindow(pParentP, nId)
+    {
+        ScTabViewShell* pViewShell = getTabViewShell( pBindings );
+        if (!pViewShell)
+            pViewShell = dynamic_cast< ScTabViewShell *>( SfxViewShell::Current() );
+        OSL_ENSURE(pViewShell, "Missing view shell!");
+
+        if (pViewShell)
+            SetController(pViewShell->CreateRefDialogController(pBindings, this, pInfo, pParentP->GetFrameWeld(), WindowID));
+
+        if (pViewShell && !GetController())
+            pViewShell->GetViewFrame()->SetChildWindow( nId, false );
+    }
+
+    static std::unique_ptr<SfxChildWindow> CreateImpl(
+                vcl::Window *pParent, sal_uInt16 nId,
+                SfxBindings *pBindings, SfxChildWinInfo* pInfo )
+    {
+        return std::make_unique<ChildControllerWrapper>(pParent, nId, pBindings, pInfo);
+    }
+
+    static void RegisterChildWindow (
+                    bool   bVisible = false,
+                    SfxModule* pModule  = nullptr,
+                    SfxChildWindowFlags nFlags = SfxChildWindowFlags::NONE)
+    {
+        auto pFactory = std::make_unique<SfxChildWinFactory>(ChildControllerWrapper::CreateImpl, WindowID, CHILDWIN_NOPOS );
+        pFactory->aInfo.nFlags |= nFlags;
+        pFactory->aInfo.bVisible = bVisible;
+        SfxChildWindow::RegisterChildWindow(pModule, std::move(pFactory));
+    }
+
+    static sal_uInt16 GetChildWindowId()
+    {
+        return WindowID;
+    }
+
+private:
+    static ScTabViewShell* getTabViewShell( const SfxBindings *pBindings )
+    {
+        if( !pBindings )
+            return nullptr;
+        SfxDispatcher* pDispacher = pBindings ->GetDispatcher();
+        if( !pDispacher )
+            return nullptr;
+        SfxViewFrame* pFrame = pDispacher->GetFrame();
+        if( !pFrame )
+            return nullptr;
+        SfxViewShell* pViewShell = pFrame->GetViewShell();
+        if( !pViewShell )
+            return nullptr;
+        return dynamic_cast<ScTabViewShell*>( pViewShell );
+    }
+};
+
 #endif // INCLUDED_SC_SOURCE_UI_INC_CHILDWINDOWWRAPPER_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/CorrelationDialog.hxx b/sc/source/ui/inc/CorrelationDialog.hxx
index ee2f433ed35d..2a98da43881f 100644
--- a/sc/source/ui/inc/CorrelationDialog.hxx
+++ b/sc/source/ui/inc/CorrelationDialog.hxx
@@ -13,14 +13,14 @@
 
 #include "MatrixComparisonGenerator.hxx"
 
-class ScCorrelationDialog : public ScMatrixComparisonGenerator
+class ScCorrelationDialog : public ScMatrixComparisonGeneratorController
 {
 public:
     ScCorrelationDialog(
         SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
-        vcl::Window* pParent, ScViewData* pViewData);
+        weld::Window* pParent, ScViewData* pViewData);
 
-    virtual bool Close() override;
+    virtual void Close() override;
 
 protected:
     virtual const OUString getLabel() override;
diff --git a/sc/source/ui/inc/IAnyRefDialog.hxx b/sc/source/ui/inc/IAnyRefDialog.hxx
index 0e4f81f41572..486322936ba8 100644
--- a/sc/source/ui/inc/IAnyRefDialog.hxx
+++ b/sc/source/ui/inc/IAnyRefDialog.hxx
@@ -36,6 +36,7 @@ public:
 
     virtual void SetReference( const ScRange& rRef, ScDocument* pDoc ) = 0;
     virtual void RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton = nullptr ) = 0;
+    virtual void RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton = nullptr ) = 0;
     virtual void RefInputDone( bool bForced = false ) = 0;
     virtual bool IsTableLocked() const = 0;
     virtual bool IsRefInputMode() const = 0;
diff --git a/sc/source/ui/inc/MatrixComparisonGenerator.hxx b/sc/source/ui/inc/MatrixComparisonGenerator.hxx
index cce103291a51..0923042120e6 100644
--- a/sc/source/ui/inc/MatrixComparisonGenerator.hxx
+++ b/sc/source/ui/inc/MatrixComparisonGenerator.hxx
@@ -34,6 +34,24 @@ protected:
     virtual const OUString getTemplate() = 0;
 };
 
+class ScMatrixComparisonGeneratorController : public ScStatisticsInputOutputDialogController
+{
+public:
+    ScMatrixComparisonGeneratorController(
+        SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
+        weld::Window* pParent, ScViewData* pViewData,
+        const OUString& rUiXmlDescription, const OString& rID);
+
+    virtual ~ScMatrixComparisonGeneratorController() override;
+
+protected:
+    virtual const char* GetUndoNameId() override;
+    virtual ScRange ApplyOutput(ScDocShell* pDocShell) override;
+
+    virtual const OUString getLabel() = 0;
+    virtual const OUString getTemplate() = 0;
+};
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/StatisticsInputOutputDialog.hxx b/sc/source/ui/inc/StatisticsInputOutputDialog.hxx
index b63ccd35c78e..6a18855851a4 100644
--- a/sc/source/ui/inc/StatisticsInputOutputDialog.hxx
+++ b/sc/source/ui/inc/StatisticsInputOutputDialog.hxx
@@ -86,6 +86,78 @@ private:
     DECL_LINK( RefInputModifyHandler, Edit&, void );
 };
 
+class ScStatisticsInputOutputDialogController : public ScAnyRefDlgController
+{
+public:
+    enum GroupedBy {
+        BY_COLUMN,
+        BY_ROW
+    };
+
+    ScStatisticsInputOutputDialogController(
+        SfxBindings* pB, SfxChildWindow* pCW,
+        weld::Window* pParent, ScViewData* pViewData,
+        const OUString& rUIXMLDescription,
+        const OString& rID);
+
+    virtual ~ScStatisticsInputOutputDialogController() override;
+
+    virtual void        SetReference( const ScRange& rRef, ScDocument* pDoc ) override;
+    virtual void        SetActive() override;
+
+protected:
+    void CalculateInputAndWriteToOutput();
+
+    virtual ScRange ApplyOutput(ScDocShell* pDocShell) = 0;
+    virtual const char* GetUndoNameId() = 0;
+    virtual bool InputRangesValid();
+    void ValidateDialogInput();
+
+    // Widgets
+    std::unique_ptr<weld::Label> mxInputRangeLabel;
+    std::unique_ptr<formula::WeldRefEdit> mxInputRangeEdit;
+    std::unique_ptr<formula::WeldRefButton> mxInputRangeButton;
+
+    std::unique_ptr<weld::Label> mxOutputRangeLabel;
+    std::unique_ptr<formula::WeldRefEdit> mxOutputRangeEdit;
+    std::unique_ptr<formula::WeldRefButton> mxOutputRangeButton;
+
+    std::unique_ptr<weld::RadioButton> mxGroupByColumnsRadio;
+    std::unique_ptr<weld::RadioButton> mxGroupByRowsRadio;
+
+    // Data
+    ScViewData* const         mViewData;
+    ScDocument* const         mDocument;
+
+    ScRange                   mInputRange;
+    ScAddress::Details const  mAddressDetails;
+    ScAddress                 mOutputAddress;
+    GroupedBy                 mGroupedBy;
+
+    static ScRangeList MakeColumnRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd);
+    static ScRangeList MakeRowRangeList(SCTAB aTab, ScAddress const & aStart, ScAddress const & aEnd);
+
+private:
+    // Widgets
+    std::unique_ptr<weld::Button>       mxButtonOk;
+
+    formula::WeldRefEdit*      mpActiveEdit;
+    ScAddress const            mCurrentAddress;
+    bool                       mDialogLostFocus;
+
+    void Init();
+    void GetRangeFromSelection();
+
+    DECL_LINK( GroupByChanged, weld::ToggleButton&, void );
+    DECL_LINK( OkClicked, weld::Button&, void );
+    DECL_LINK( GetEditFocusHandler,  formula::WeldRefEdit&, void );
+    DECL_LINK( GetButtonFocusHandler,  formula::WeldRefButton&, void );
+    DECL_LINK( LoseEditFocusHandler, formula::WeldRefEdit&, void );
+    DECL_LINK( LoseButtonFocusHandler, formula::WeldRefButton&, void );
+    DECL_LINK( RefInputModifyHandler, formula::WeldRefEdit&, void );
+};
+
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/anyrefdg.hxx b/sc/source/ui/inc/anyrefdg.hxx
index 069bc2650ee5..3a5726123654 100644
--- a/sc/source/ui/inc/anyrefdg.hxx
+++ b/sc/source/ui/inc/anyrefdg.hxx
@@ -40,7 +40,10 @@ class ScFormulaReferenceHelper
     ::std::unique_ptr<ScCompiler>         m_pRefComp;
     VclPtr<formula::RefEdit>    m_pRefEdit;               // active input field
     VclPtr<formula::RefButton>  m_pRefBtn;                // associated button
+    formula::WeldRefEdit*       m_pWeldRefEdit;           // active input field
+    formula::WeldRefButton*     m_pWeldRefBtn;            // associated button
     VclPtr<vcl::Window>         m_pWindow;
+    weld::Dialog*               m_pDialog;
     SfxBindings* const          m_pBindings;
     ::std::unique_ptr<Accelerator>
                         m_pAccel;                 // for Enter/Escape
@@ -63,6 +66,7 @@ class ScFormulaReferenceHelper
     bool                m_bAccInserted;
 
     DECL_LINK( AccelSelectHdl, Accelerator&, void );
+    DECL_LINK( ActivateHdl, weld::Widget&, bool );
 
 public:
     ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindings* _pBindings);
@@ -76,12 +80,16 @@ public:
 
     void                ShowReference(const OUString& rStr);
     void                ReleaseFocus( formula::RefEdit* pEdit );
+    void                ReleaseFocus( formula::WeldRefEdit* pEdit );
     void                HideReference( bool bDoneRefMode = true );
     void                RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton );
+    void                RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton );
     void                RefInputDone( bool bForced );
     void                ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton );
+    void                ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton );
 
-    void         SetWindow(vcl::Window* _pWindow) { m_pWindow = _pWindow; }
+    void                SetWindow(vcl::Window* _pWindow) { m_pWindow = _pWindow; }
+    void                SetDialog(weld::Dialog* pDialog) { m_pDialog = pDialog; }
     void                DoClose( sal_uInt16 nId );
     void                SetDispatcherLock( bool bLock );
     static void         EnableSpreadsheets( bool bFlag = true );
@@ -91,13 +99,14 @@ public:
 
 public:
     static bool         CanInputStart( const formula::RefEdit *pEdit ){ return !!pEdit; }
-    bool                CanInputDone( bool bForced ){   return m_pRefEdit && (bForced || !m_pRefBtn);   }
+    bool                CanInputDone( bool bForced ){   return (m_pRefEdit || m_pWeldRefEdit) && (bForced || !(m_pRefBtn || m_pWeldRefBtn));   }
 };
 
 class SC_DLLPUBLIC ScRefHandler :
                     public IAnyRefDialog
 {
     VclPtr<vcl::Window>  m_rWindow;
+    weld::DialogController* m_pController;
     bool                 m_bInRefMode;
 
 public:
@@ -118,12 +127,14 @@ protected:
     void                SetDispatcherLock( bool bLock );
 
     virtual void        RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton = nullptr ) override;
+    virtual void        RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton = nullptr ) override;
     virtual void        RefInputDone( bool bForced = false ) override;
 
     bool                ParseWithNames( ScRangeList& rRanges, const OUString& rStr, const ScDocument* pDoc );
 
 public:
                         ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef );
+                        ScRefHandler( SfxModelessDialogController &rController, SfxBindings* pB, bool bBindRef );
     virtual             ~ScRefHandler() override;
 
     virtual void        SetReference( const ScRange& rRef, ScDocument* pDoc ) override = 0;
@@ -137,7 +148,9 @@ public:
     virtual void        HideReference( bool bDoneRefMode = true ) override;
 
     virtual void        ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override;
+    virtual void        ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) override;
     virtual void        ReleaseFocus( formula::RefEdit* pEdit ) override;
+    virtual void        ReleaseFocus( formula::WeldRefEdit* pEdit ) override;
 
     virtual void        ViewShellChanged() override;
     void                SwitchToDocument();
@@ -228,6 +241,77 @@ struct ScAnyRefDlg : ::ScRefHdlrImpl< ScAnyRefDlg, SfxModelessDialog>
     }
 };
 
+template<  class TWindow, bool bBindRef = true >
+class ScRefHdlrControllerImplBase: public TWindow, public ScRefHandler
+{
+private:
+    template<class TBindings, class TChildWindow, class TParentWindow >
+    ScRefHdlrControllerImplBase( TBindings* pB, TChildWindow* pCW,
+        TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID );
+
+    template<class TParentWindow, class TArg>
+    ScRefHdlrControllerImplBase(TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID, const TArg &rArg, SfxBindings *pB);
+
+    virtual ~ScRefHdlrControllerImplBase() override;
+
+    template<class, class, bool> friend struct ScRefHdlrControllerImpl;
+};
+
+template<class TWindow, bool bBindRef >
+ScRefHdlrControllerImplBase<TWindow,bBindRef>::~ScRefHdlrControllerImplBase(){}
+
+template<class TWindow, bool bBindRef>
+template<class TBindings, class TChildWindow, class TParentWindow>
+ScRefHdlrControllerImplBase<TWindow, bBindRef>::ScRefHdlrControllerImplBase(TBindings* pB, TChildWindow* pCW,
+                 TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID)
+    : TWindow(pB, pCW, pParent, rUIXMLDescription, rID)
+    , ScRefHandler( *static_cast<TWindow*>(this), pB, bBindRef )
+{
+}
+
+template<class TWindow, bool bBindRef >
+template<class TParentWindow, class TArg>
+ScRefHdlrControllerImplBase<TWindow,bBindRef>::ScRefHdlrControllerImplBase(TParentWindow* pParent, const OUString& rUIXMLDescription, const OString& rID,
+                                                                           const TArg &rArg, SfxBindings *pB)
+    : TWindow(pParent, rUIXMLDescription, rID, rArg)
+    , ScRefHandler( *static_cast<TWindow*>(this), pB, bBindRef )
+{
+}
+
+template<class TDerived, class TBase, bool bBindRef = true>
+struct ScRefHdlrControllerImpl: ScRefHdlrControllerImplBase< TBase, bBindRef >
+{
+    enum { UNKNOWN_SLOTID = 0U, SLOTID = UNKNOWN_SLOTID };
+
+    template<class T1, class T2, class T3, class T4>
+    ScRefHdlrControllerImpl( const T1 & rt1, const T2 & rt2, const T3& rt3, const T4& rt4 )
+        : ScRefHdlrControllerImplBase<TBase, bBindRef >(rt1, rt2, rt3, rt4)
+    {
+        SC_MOD()->RegisterRefController( static_cast<sal_uInt16>( TDerived::SLOTID ), this );
+    }
+
+    template<class T1, class T2, class T3, class T4, class T5>
+    ScRefHdlrControllerImpl( const T1 & rt1, const T2 & rt2, const T3& rt3, const T4& rt4, const T5& rt5 )
+        : ScRefHdlrControllerImplBase<TBase, bBindRef >(rt1, rt2, rt3, rt4, rt5)
+    {
+        SC_MOD()->RegisterRefController( static_cast<sal_uInt16>( TDerived::SLOTID ), this );
+    }
+
+    ~ScRefHdlrControllerImpl()
+    {
+        SC_MOD()->UnregisterRefController( static_cast<sal_uInt16>( TDerived::SLOTID ), this );
+    }
+};
+
+struct ScAnyRefDlgController : ::ScRefHdlrControllerImpl<ScAnyRefDlgController, SfxModelessDialogController>
+{
+    template<class T1, class T2, class T3, class T4, class T5>
+    ScAnyRefDlgController( const T1 & rt1, const T2 & rt2, const T3& rt3, const T4& rt4, const T5& rt5 )
+        : ScRefHdlrControllerImpl<ScAnyRefDlgController, SfxModelessDialogController>(rt1, rt2, rt3, rt4, rt5)
+    {
+    }
+};
+
 inline bool ScRefHandler::CanInputStart( const formula::RefEdit *pEdit )
 {
     return ScFormulaReferenceHelper::CanInputStart( pEdit );
diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx
index a40b55ecb9e1..97737e7c4af9 100644
--- a/sc/source/ui/inc/formula.hxx
+++ b/sc/source/ui/inc/formula.hxx
@@ -83,7 +83,9 @@ public:
     virtual void SetReference( const ScRange& rRef, ScDocument* pD ) override;
 
     virtual void ReleaseFocus( formula::RefEdit* pEdit ) override;
+    virtual void ReleaseFocus( formula::WeldRefEdit* pEdit ) override;
     virtual void ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton ) override;
+    virtual void ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton ) override;
     virtual void RefInputDone( bool bForced = false ) override;
     virtual bool IsTableLocked() const override;
     virtual bool IsRefInputMode() const override;
@@ -95,6 +97,7 @@ public:
 
 private:
     virtual void RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton = nullptr ) override;
+    virtual void RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton = nullptr ) override;
     static void  SaveLRUEntry(const ScFuncDesc* pFuncDesc);
 
     static bool  IsInputHdl(const ScInputHandler* pHdl);
diff --git a/sc/source/ui/inc/reffact.hxx b/sc/source/ui/inc/reffact.hxx
index a49f80c0de97..28c42f089a38 100644
--- a/sc/source/ui/inc/reffact.hxx
+++ b/sc/source/ui/inc/reffact.hxx
@@ -79,7 +79,7 @@ private:
 };
 
 class ScCorrelationDialogWrapper :
-    public ChildWindowWrapper<SID_CORRELATION_DIALOG>
+    public ChildControllerWrapper<SID_CORRELATION_DIALOG>
 {
 private:
     ScCorrelationDialogWrapper() = delete;
diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index d60cb0e388e0..f2a260030206 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -328,6 +328,10 @@ public:
                                                const SfxChildWinInfo* pInfo,
                                                vcl::Window* pParent, sal_uInt16 nSlotId );
 
+    std::unique_ptr<SfxModelessDialogController> CreateRefDialogController(SfxBindings* pB, SfxChildWindow* pCW,
+                                                    const SfxChildWinInfo* pInfo,
+                                                    weld::Window* pParent, sal_uInt16 nSlotId);
+
     void            UpdateOleZoom();
 
     virtual const FmFormShell* GetFormShell() const override { return pFormShell.get(); }
diff --git a/sc/source/ui/inc/validate.hxx b/sc/source/ui/inc/validate.hxx
index 62b4388272e1..c29d8b6c7335 100644
--- a/sc/source/ui/inc/validate.hxx
+++ b/sc/source/ui/inc/validate.hxx
@@ -228,6 +228,11 @@ public:
         ScValidationDlgBase::RefInputStart( pEdit, pButton );
     }
 
+    virtual void        RefInputStart( formula::WeldRefEdit* /*pEdit*/, formula::WeldRefButton* /*pButton*/ = nullptr ) override
+    {
+        assert(false);
+    }
+
     virtual void        RefInputDone( bool bForced = false ) override
     {
         if( !CanInputDone( bForced ) )
diff --git a/sc/source/ui/miscdlgs/anyrefdg.cxx b/sc/source/ui/miscdlgs/anyrefdg.cxx
index b108d4487acd..29c05945b30c 100644
--- a/sc/source/ui/miscdlgs/anyrefdg.cxx
+++ b/sc/source/ui/miscdlgs/anyrefdg.cxx
@@ -47,7 +47,10 @@ ScFormulaReferenceHelper::ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindi
  : m_pDlg(_pDlg)
  , m_pRefEdit (nullptr)
  , m_pRefBtn (nullptr)
+ , m_pWeldRefEdit (nullptr)
+ , m_pWeldRefBtn (nullptr)
  , m_pWindow(nullptr)
+ , m_pDialog(nullptr)
  , m_pBindings(_pBindings)
  , m_nOldBorderWidth (0)
  , m_nRefTab(0)
@@ -85,6 +88,7 @@ void ScFormulaReferenceHelper::dispose()
 
     m_pOldEditParent.clear();
     m_pWindow.clear();
+    m_pDialog = nullptr;
     m_pRefBtn.clear();
     m_pRefEdit.clear();
 }
@@ -321,6 +325,39 @@ void ScFormulaReferenceHelper::ReleaseFocus( formula::RefEdit* pEdit )
     }
 }
 
+void ScFormulaReferenceHelper::ReleaseFocus( formula::WeldRefEdit* pEdit )
+{
+    if( !m_pWeldRefEdit && pEdit )
+    {
+        m_pDlg->RefInputStart( pEdit );
+    }
+
+    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+    if( pViewShell )
+    {
+        pViewShell->ActiveGrabFocus();
+        if( m_pWeldRefEdit )
+        {
+            const ScViewData& rViewData = pViewShell->GetViewData();
+            ScDocument* pDoc = rViewData.GetDocument();
+            ScRangeList aRangeList;
+            if( ParseWithNames( aRangeList, m_pWeldRefEdit->GetText(), pDoc ) )
+            {
+                if ( !aRangeList.empty() )
+                {
+                    const ScRange & rRange = aRangeList.front();
+                    pViewShell->SetTabNo( rRange.aStart.Tab() );
+                    pViewShell->MoveCursorAbs(  rRange.aStart.Col(),
+                        rRange.aStart.Row(), SC_FOLLOW_JUMP, false, false );
+                    pViewShell->MoveCursorAbs( rRange.aEnd.Col(),
+                        rRange.aEnd.Row(), SC_FOLLOW_JUMP, true, false );
+                    m_pDlg->SetReference( rRange, pDoc );
+                }
+            }
+        }
+    }
+}
+
 void ScFormulaReferenceHelper::Init()
 {
     ScViewData* pViewData=ScDocShell::GetViewData();    //! use pScViewShell?
@@ -353,6 +390,14 @@ IMPL_LINK( ScFormulaReferenceHelper, AccelSelectHdl, Accelerator&, rSelAccel, vo
     }
 }
 
+IMPL_LINK_NOARG(ScFormulaReferenceHelper, ActivateHdl, weld::Widget&, bool)
+{
+    if (m_pWeldRefEdit)
+        m_pWeldRefEdit->GrabFocus();
+    m_pDlg->RefInputDone(true);
+    return true;
+}
+
 void ScFormulaReferenceHelper::RefInputDone( bool bForced )
 {
     if ( CanInputDone( bForced ) )
@@ -363,62 +408,86 @@ void ScFormulaReferenceHelper::RefInputDone( bool bForced )
             m_bAccInserted = false;
         }
 
-        //get rid of all this junk when we can
-        if (!m_bOldDlgLayoutEnabled)
+        if (m_pDialog)
         {
-            m_pWindow->SetOutputSizePixel(m_aOldDialogSize);
+            // Adjust window title
+            m_pDialog->set_title(m_sOldDialogText);
 
-            // restore the parent of the edit field
-            m_pRefEdit->SetParent(m_pOldEditParent);
+            if (m_pWeldRefEdit)
+                m_pWeldRefEdit->SetActivateHdl(Link<weld::Widget&, bool>());
 
-            // the window is at the old size again
-            m_pWindow->SetOutputSizePixel(m_aOldDialogSize);
-
-            // set button parent
-            if( m_pRefBtn )
+            // set button image
+            if (m_pWeldRefBtn)
             {
-                m_pRefBtn->SetParent(m_pWindow);
+                m_pWeldRefBtn->SetActivateHdl(Link<weld::Widget&, bool>());
+                m_pWeldRefBtn->SetStartImage();
             }
+
+            m_pDialog->undo_collapse();
+
+            m_pWeldRefEdit = nullptr;
+            m_pWeldRefBtn = nullptr;
         }
 
-        if (!m_bOldEditParentLayoutEnabled)
+        if (m_pWindow)
         {
-            // set pEditCell to old position
-            m_pRefEdit->SetPosSizePixel(m_aOldEditPos, m_aOldEditSize);
+            //get rid of all this junk when we can
+            if (!m_bOldDlgLayoutEnabled)
+            {
+                m_pWindow->SetOutputSizePixel(m_aOldDialogSize);
 
-            // set button position
-            if( m_pRefBtn )
+                // restore the parent of the edit field
+                m_pRefEdit->SetParent(m_pOldEditParent);
+
+                // the window is at the old size again
+                m_pWindow->SetOutputSizePixel(m_aOldDialogSize);
+
+                // set button parent
+                if( m_pRefBtn )
+                {
+                    m_pRefBtn->SetParent(m_pWindow);
+                }
+            }
+
+            if (!m_bOldEditParentLayoutEnabled)
             {
-                m_pRefBtn->SetPosPixel( m_aOldButtonPos );
+                // set pEditCell to old position
+                m_pRefEdit->SetPosSizePixel(m_aOldEditPos, m_aOldEditSize);
+
+                // set button position
+                if( m_pRefBtn )
+                {
+                    m_pRefBtn->SetPosPixel( m_aOldButtonPos );
+                }
             }
-        }
 
-        // Adjust window title
-        m_pWindow->SetText(m_sOldDialogText);
+            // Adjust window title
+            m_pWindow->SetText(m_sOldDialogText);
 
-        // set button image
-        if( m_pRefBtn )
-            m_pRefBtn->SetStartImage();
+            // set button image
+            if( m_pRefBtn )
+                m_pRefBtn->SetStartImage();
 
-        // All others: Show();
-        for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets)
-        {
-            pWindow->Show();
-        }
-        m_aHiddenWidgets.clear();
+            // All others: Show();
+            for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets)
+            {
+                pWindow->Show();
+            }
+            m_aHiddenWidgets.clear();
 
-        if (m_bOldDlgLayoutEnabled)
-        {
-            m_pRefEdit->set_width_request(m_nOldEditWidthReq);
-            Dialog* pResizeDialog = m_pRefEdit->GetParentDialog();
-            pResizeDialog->set_border_width(m_nOldBorderWidth);
-            if (vcl::Window *pActionArea = pResizeDialog->get_action_area())
-                pActionArea->Show();
-            pResizeDialog->setOptimalLayoutSize();
-        }
+            if (m_bOldDlgLayoutEnabled)
+            {
+                m_pRefEdit->set_width_request(m_nOldEditWidthReq);
+                Dialog* pResizeDialog = m_pRefEdit->GetParentDialog();
+                pResizeDialog->set_border_width(m_nOldBorderWidth);
+                if (vcl::Window *pActionArea = pResizeDialog->get_action_area())
+                    pActionArea->Show();
+                pResizeDialog->setOptimalLayoutSize();
+            }
 
-        m_pRefEdit = nullptr;
-        m_pRefBtn = nullptr;
+            m_pRefEdit = nullptr;
+            m_pRefBtn = nullptr;
+        }
     }
 }
 
@@ -591,6 +660,37 @@ void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula::
     }
 }
 
+void ScFormulaReferenceHelper::RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton )
+{
+    if (!m_pWeldRefEdit)
+    {
+        m_pWeldRefEdit = pEdit;
+        m_pWeldRefBtn  = pButton;
+
+        // Save and adjust window title
+        m_sOldDialogText = m_pDialog->get_title();
+        if (weld::Label *pLabel = m_pWeldRefEdit->GetLabelWidgetForShrinkMode())
+        {
+            const OUString sLabel = pLabel->get_label();
+            if (!sLabel.isEmpty())
+            {
+                const OUString sNewDialogText = m_sOldDialogText + ": " + comphelper::string::stripEnd(sLabel, ':');
+                m_pDialog->set_title(pLabel->strip_mnemonic(sNewDialogText));
+            }
+        }
+
+        m_pDialog->collapse(pEdit->GetWidget(), pButton ? pButton->GetWidget() : nullptr);
+
+        // set button image
+        if (pButton)
+            pButton->SetEndImage();
+
+        m_pWeldRefEdit->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl));
+        if (m_pWeldRefBtn)
+            m_pWeldRefBtn->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl));
+    }
+}
+
 void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
 {
     if( pEdit )
@@ -611,6 +711,26 @@ void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula
     }
 }
 
+void ScFormulaReferenceHelper::ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton )
+{
+    if( pEdit )
+    {
+        if( m_pWeldRefEdit == pEdit )                 // is this the active ref edit field?
+        {
+            m_pWeldRefEdit->GrabFocus();              // before RefInputDone()
+            m_pDlg->RefInputDone( true );               // finish ref input
+        }
+        else
+        {
+            m_pDlg->RefInputDone( true );               // another active ref edit?
+            m_pDlg->RefInputStart( pEdit, pButton );    // start ref input
+            // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg)
+            if( m_pWeldRefEdit )
+                m_pWeldRefEdit->GrabFocus();
+        }
+    }
+}
+
 void ScFormulaReferenceHelper::DoClose( sal_uInt16 nId )
 {
     SfxApplication* pSfxApp = SfxGetpApp();
@@ -747,11 +867,9 @@ static void lcl_HideAllReferences()
     }
 }
 
-//The class of ScAnyRefDlg is rewritten by PengYunQuan for Validity Cell Range Picker
-//  class ScRefHandler
-
 ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef ):
         m_rWindow( &rWindow ),
+        m_pController( nullptr ),
         m_bInRefMode( false ),
         m_aHelper(this,pB),
         m_pMyBindings( pB )
@@ -761,6 +879,17 @@ ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef
     if( bBindRef ) EnterRefMode();
 }
 
+ScRefHandler::ScRefHandler(SfxModelessDialogController& rController, SfxBindings* pB, bool bBindRef)
+    : m_pController(&rController)
+    , m_bInRefMode(false)
+    , m_aHelper(this, pB)
+    , m_pMyBindings(pB)
+{
+    m_aHelper.SetDialog(rController.getDialog());
+
+    if( bBindRef ) EnterRefMode();
+}
+
 bool ScRefHandler::EnterRefMode()
 {
     if( m_bInRefMode ) return false;
@@ -819,6 +948,7 @@ ScRefHandler::~ScRefHandler()
 void ScRefHandler::disposeRefHandler()
 {
     m_rWindow.clear();
+    m_pController = nullptr;
     LeaveRefMode();
     m_aHelper.dispose();
 }
@@ -831,6 +961,8 @@ bool ScRefHandler::LeaveRefMode()
 
     if( Dialog *pDlg = dynamic_cast<Dialog*>( m_rWindow.get() ) )
         pDlg->SetModalInputMode(false);
+    if (m_pController)
+        m_pController->getDialog()->set_modal(false);
     SetDispatcherLock( false );         //! here and in DoClose ?
 
     ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
@@ -885,6 +1017,8 @@ bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const   // pDocSh may be
 
 bool ScRefHandler::IsRefInputMode() const
 {
+    if (m_pController)
+        return m_pController->getDialog()->get_visible();
     return m_rWindow->IsVisible(); // references can only be input to visible windows
 }
 
@@ -924,11 +1058,21 @@ void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* p
     m_aHelper.RefInputStart( pEdit, pButton );
 }
 
+void ScRefHandler::RefInputStart( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton )
+{
+    m_aHelper.RefInputStart( pEdit, pButton );
+}
+
 void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
 {
     m_aHelper.ToggleCollapsed( pEdit, pButton );
 }
 
+void ScRefHandler::ToggleCollapsed( formula::WeldRefEdit* pEdit, formula::WeldRefButton* pButton )
+{
+    m_aHelper.ToggleCollapsed( pEdit, pButton );
+}
+
 bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, const OUString& rStr, const ScDocument* pDoc )
 {
     return m_aHelper.ParseWithNames( rRanges, rStr, pDoc );
@@ -949,6 +1093,11 @@ void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit )
     m_aHelper.ReleaseFocus( pEdit );
 }
 
+void ScRefHandler::ReleaseFocus( formula::WeldRefEdit* pEdit )
+{
+    m_aHelper.ReleaseFocus( pEdit );
+}
+
 void ScRefHandler::RefInputDone( bool bForced )
 {
     m_aHelper.RefInputDone( bForced );
diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx
index 649af1829361..c826234e3da0 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -348,12 +348,6 @@ VclPtr<SfxModelessDialog> ScTabViewShell::CreateRefDialog(
         }
         break;
 
-        case SID_CORRELATION_DIALOG:
-        {
-            pResult = VclPtr<ScCorrelationDialog>::Create( pB, pCW, pParent, &GetViewData() );
-        }
-        break;
-
         case SID_COVARIANCE_DIALOG:
         {
             pResult = VclPtr<ScCovarianceDialog>::Create( pB, pCW, pParent, &GetViewData() );
@@ -512,6 +506,45 @@ VclPtr<SfxModelessDialog> ScTabViewShell::CreateRefDialog(
     return pResult;
 }
 
+std::unique_ptr<SfxModelessDialogController> ScTabViewShell::CreateRefDialogController(
+                                SfxBindings* pB, SfxChildWindow* pCW,
+                                const SfxChildWinInfo* pInfo,
+                                weld::Window* pParent, sal_uInt16 nSlotId)
+{
+    // only open dialog when called through ScModule::SetRefDialog,
+    // so that it does not re appear for instance after a crash (#42341#).
+
+    if ( SC_MOD()->GetCurRefDlgId() != nSlotId )
+        return nullptr;
+
+    if ( nCurRefDlgId != nSlotId )
+    {
+        //  the dialog has been opened in a different view
+        //  -> lock the dispatcher for this view (modal mode)
+
+        GetViewData().GetDispatcher().Lock( true );    // lock is reset when closing dialog
+        return nullptr;
+    }
+
+    std::unique_ptr<SfxModelessDialogController> xResult;
+
+    if(pCW)
+        pCW->SetHideNotDelete(true);
+
+    switch( nSlotId )
+    {
+        case SID_CORRELATION_DIALOG:
+        {
+            xResult.reset(new ScCorrelationDialog(pB, pCW, pParent, &GetViewData()));
+        }
+        break;
+    }
+
+    if (xResult)
+        xResult->Initialize( pInfo );
+    return xResult;
+}
+
 int ScTabViewShell::getPart() const
 {
     return GetViewData().GetTabNo();
diff --git a/sc/uiconfig/scalc/ui/correlationdialog.ui b/sc/uiconfig/scalc/ui/correlationdialog.ui
index 378875bec5ec..7fff92fa924d 100644
--- a/sc/uiconfig/scalc/ui/correlationdialog.ui
+++ b/sc/uiconfig/scalc/ui/correlationdialog.ui
@@ -1,14 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.22.1 -->
 <interface domain="sc">
   <requires lib="gtk+" version="3.18"/>
-  <requires lib="LibreOffice" version="1.0"/>
   <object class="GtkDialog" id="CorrelationDialog">
     <property name="can_focus">False</property>
     <property name="border_width">6</property>
     <property name="title" translatable="yes" context="correlationdialog|CorrelationDialog">Correlation</property>
     <property name="resizable">False</property>
     <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox1">
         <property name="can_focus">False</property>
@@ -96,10 +98,10 @@
                       <object class="GtkLabel" id="input-range-label">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
                         <property name="label" translatable="yes" context="correlationdialog|input-range-label">Input range:</property>
                         <property name="use_underline">True</property>
                         <property name="mnemonic_widget">input-range-edit</property>
+                        <property name="xalign">0</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -110,10 +112,10 @@
                       <object class="GtkLabel" id="output-range-label">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
                         <property name="label" translatable="yes" context="correlationdialog|output-range-label">Results to:</property>
                         <property name="use_underline">True</property>
                         <property name="mnemonic_widget">output-range-edit</property>
+                        <property name="xalign">0</property>
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
@@ -121,7 +123,7 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="foruilo-RefEdit" id="input-range-edit">
+                      <object class="GtkEntry" id="input-range-edit">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="valign">center</property>
@@ -134,7 +136,7 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="foruilo-RefEdit" id="output-range-edit">
+                      <object class="GtkEntry" id="output-range-edit">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="valign">center</property>
@@ -147,7 +149,7 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="foruilo-RefButton" id="input-range-button">
+                      <object class="GtkButton" id="input-range-button">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
@@ -158,7 +160,7 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="foruilo-RefButton" id="output-range-button">
+                      <object class="GtkButton" id="output-range-button">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
@@ -266,6 +268,7 @@
     </child>
     <action-widgets>
       <action-widget response="-5">ok</action-widget>
+      <action-widget response="-6">cancel</action-widget>
       <action-widget response="-11">help</action-widget>
     </action-widgets>
   </object>
diff --git a/solenv/sanitizers/ui/modules/scalc.suppr b/solenv/sanitizers/ui/modules/scalc.suppr
index f15bbf423067..c3ae37462c58 100644
--- a/solenv/sanitizers/ui/modules/scalc.suppr
+++ b/solenv/sanitizers/ui/modules/scalc.suppr
@@ -31,6 +31,8 @@ sc/uiconfig/scalc/ui/conflictsdialog.ui://GtkLabel[@id='label1'] orphan-label
 sc/uiconfig/scalc/ui/conflictsdialog.ui://svtlo-SvSimpleTableContainer[@id='container:border'] no-labelled-by
 sc/uiconfig/scalc/ui/consolidatedialog.ui://foruilo-RefEdit[@id='eddataarea'] no-labelled-by
 sc/uiconfig/scalc/ui/consolidatedialog.ui://foruilo-RefEdit[@id='eddestarea'] no-labelled-by
+sc/uiconfig/scalc/ui/correlationdialog.ui://GtkButton[@id='input-range-button'] button-no-label
+sc/uiconfig/scalc/ui/correlationdialog.ui://GtkButton[@id='output-range-button'] button-no-label
 sc/uiconfig/scalc/ui/dapiservicedialog.ui://GtkLabel[@id='label2'] orphan-label
 sc/uiconfig/scalc/ui/dapiservicedialog.ui://GtkLabel[@id='label3'] orphan-label
 sc/uiconfig/scalc/ui/dapiservicedialog.ui://GtkLabel[@id='label4'] orphan-label
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 0926dac611fb..74716b18aa35 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1016,15 +1016,48 @@ IMPL_LINK_NOARG(SalInstanceWindow, HelpHdl, vcl::Window&, bool)
     return false;
 }
 
+typedef std::set<VclPtr<vcl::Window> > winset;
+
+namespace
+{
+    void hideUnless(const vcl::Window *pTop, const winset& rVisibleWidgets,
+        std::vector<VclPtr<vcl::Window> > &rWasVisibleWidgets)
+    {
+        for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild;
+            pChild = pChild->GetWindow(GetWindowType::Next))
+        {
+            if (!pChild->IsVisible())
+                continue;
+            if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
+            {
+                rWasVisibleWidgets.emplace_back(pChild);
+                pChild->Hide();
+            }
+            else if (isContainerWindow(pChild))
+            {
+                hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
+            }
+        }
+    }
+}
+
 class SalInstanceDialog : public SalInstanceWindow, public virtual weld::Dialog
 {
 private:
     VclPtr<::Dialog> m_xDialog;
 
+    // for calc ref dialog that shrink to range selection widgets and resize back
+    VclPtr<vcl::Window> m_xRefEdit;
+    std::vector<VclPtr<vcl::Window> > m_aHiddenWidgets;    // vector of hidden Controls
+    long m_nOldEditWidthReq; // Original width request of the input field
+    sal_Int32 m_nOldBorderWidth; // border width for expanded dialog
+
 public:
     SalInstanceDialog(::Dialog* pDialog, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
         : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership)
         , m_xDialog(pDialog)
+        , m_nOldEditWidthReq(0)
+        , m_nOldBorderWidth(0)
     {
     }
 
@@ -1044,6 +1077,67 @@ public:
         return m_xDialog->StartExecuteAsync(aCtx);
     }
 
+    virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override
+    {
+        SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit);
+        SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton);
+
+        vcl::Window* pRefEdit = pVclEdit->getWidget();
+        vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr;
+
+        auto nOldEditWidth = pRefEdit->GetSizePixel().Width();
+        m_nOldEditWidthReq = pRefEdit->get_width_request();
+
+        //We want just pRefBtn and pRefEdit to be shown
+        //mark widgets we want to be visible, starting with pRefEdit
+        //and all its direct parents.
+        winset aVisibleWidgets;
+        vcl::Window *pContentArea = m_xDialog->get_content_area();
+        for (vcl::Window *pCandidate = pRefEdit;
+            pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
+            pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
+        {
+            aVisibleWidgets.insert(pCandidate);
+        }
+        //same again with pRefBtn, except stop if there's a
+        //shared parent in the existing widgets
+        for (vcl::Window *pCandidate = pRefBtn;
+            pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
+            pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
+        {
+            if (aVisibleWidgets.insert(pCandidate).second)
+                break;
+        }
+
+        //hide everything except the aVisibleWidgets
+        hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets);
+
+        pRefEdit->set_width_request(nOldEditWidth);
+        m_nOldBorderWidth = m_xDialog->get_border_width();
+        m_xDialog->set_border_width(0);
+        if (vcl::Window *pActionArea = m_xDialog->get_action_area())
+            pActionArea->Hide();
+        m_xDialog->setOptimalLayoutSize();
+        m_xRefEdit = pRefEdit;
+    }
+
+    virtual void undo_collapse() override
+    {
+        // All others: Show();
+        for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets)
+        {
+            pWindow->Show();
+        }
+        m_aHiddenWidgets.clear();
+
+        m_xRefEdit->set_width_request(m_nOldEditWidthReq);
+        m_xRefEdit.clear();
+        m_xDialog->set_border_width(m_nOldBorderWidth);
+        if (vcl::Window *pActionArea = m_xDialog->get_action_area())
+            pActionArea->Show();
+        m_xDialog->setOptimalLayoutSize();
+    }
+
     virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink) override
     {
         m_xDialog->SetInstallLOKNotifierHdl(rLink);
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 7f294bae8c21..f7d138f5f538 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -2761,6 +2761,34 @@ struct DialogRunner
     }
 };
 
+typedef std::set<GtkWidget*> winset;
+
+namespace
+{
+    void hideUnless(GtkContainer *pTop, const winset& rVisibleWidgets,
+        std::vector<GtkWidget*> &rWasVisibleWidgets)
+    {
+        GList* pChildren = gtk_container_get_children(pTop);
+        for (GList* pEntry = g_list_first(pChildren); pEntry; pEntry = g_list_next(pEntry))
+        {
+            GtkWidget* pChild = static_cast<GtkWidget*>(pEntry->data);
+            if (!gtk_widget_get_visible(pChild))
+                continue;
+            if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
+            {
+                g_object_ref(pChild);
+                rWasVisibleWidgets.emplace_back(pChild);
+                gtk_widget_hide(pChild);
+            }
+            else if (GTK_IS_CONTAINER(pChild))
+            {
+                hideUnless(GTK_CONTAINER(pChild), rVisibleWidgets, rWasVisibleWidgets);
+            }
+        }
+        g_list_free(pChildren);
+    }
+}
+
 class GtkInstanceDialog : public GtkInstanceWindow, public virtual weld::Dialog
 {
 private:
@@ -2773,6 +2801,13 @@ private:
     gulong m_nCloseSignalId;
     gulong m_nResponseSignalId;
 
+    // for calc ref dialog that shrink to range selection widgets and resize back
+    GtkWidget* m_pRefEdit;
+    std::vector<GtkWidget*> m_aHiddenWidgets;    // vector of hidden Controls
+    int m_nOldEditWidth;  // Original width of the input field
+    int m_nOldEditWidthReq; // Original width request of the input field
+    int m_nOldBorderWidth; // border width for expanded dialog
+
     static void signalClose(GtkWidget*, gpointer widget)
     {
         GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget);
@@ -2828,6 +2863,10 @@ public:
         , m_aDialogRun(pDialog)
         , m_nCloseSignalId(g_signal_connect(m_pDialog, "close", G_CALLBACK(signalClose), this))
         , m_nResponseSignalId(0)
+        , m_pRefEdit(nullptr)
+        , m_nOldEditWidth(0)
+        , m_nOldEditWidthReq(0)
+        , m_nOldBorderWidth(0)
     {
     }
 
@@ -2948,6 +2987,69 @@ public:
         return new GtkInstanceContainer(GTK_CONTAINER(gtk_dialog_get_content_area(m_pDialog)), m_pBuilder, false);
     }
 
+    virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override
+    {
+        GtkInstanceWidget* pVclEdit = dynamic_cast<GtkInstanceWidget*>(pEdit);
+        GtkInstanceWidget* pVclButton = dynamic_cast<GtkInstanceWidget*>(pButton);
+
+        GtkWidget* pRefEdit = pVclEdit->getWidget();
+        GtkWidget* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr;
+
+        m_nOldEditWidth = gtk_widget_get_allocated_width(pRefEdit);
+
+        gtk_widget_get_size_request(pRefEdit, &m_nOldEditWidthReq, nullptr);
+
+        //We want just pRefBtn and pRefEdit to be shown
+        //mark widgets we want to be visible, starting with pRefEdit
+        //and all its direct parents.
+        winset aVisibleWidgets;
+        GtkWidget *pContentArea = gtk_dialog_get_content_area(m_pDialog);
+        for (GtkWidget *pCandidate = pRefEdit;
+            pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate);
+            pCandidate = gtk_widget_get_parent(pCandidate))
+        {
+            aVisibleWidgets.insert(pCandidate);
+        }
+        //same again with pRefBtn, except stop if there's a
+        //shared parent in the existing widgets
+        for (GtkWidget *pCandidate = pRefBtn;
+            pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate);
+            pCandidate = gtk_widget_get_parent(pCandidate))
+        {
+            if (aVisibleWidgets.insert(pCandidate).second)
+                break;
+        }
+
+        //hide everything except the aVisibleWidgets
+        hideUnless(GTK_CONTAINER(pContentArea), aVisibleWidgets, m_aHiddenWidgets);
+
+        gtk_widget_set_size_request(pRefEdit, m_nOldEditWidth, -1);
+        m_nOldBorderWidth = gtk_container_get_border_width(GTK_CONTAINER(m_pDialog));
+        gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), 0);
+        if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog))
+            gtk_widget_hide(pActionArea);
+        resize_to_request();
+        m_pRefEdit = pRefEdit;
+    }
+
+    virtual void undo_collapse() override
+    {
+        // All others: Show();
+        for (GtkWidget* pWindow : m_aHiddenWidgets)
+        {
+            gtk_widget_show(pWindow);
+            g_object_unref(pWindow);
+        }
+        m_aHiddenWidgets.clear();
+
+        gtk_widget_set_size_request(m_pRefEdit, m_nOldEditWidthReq, -1);
+        m_pRefEdit = nullptr;
+        gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), m_nOldBorderWidth);
+        if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog))
+            gtk_widget_show(pActionArea);
+        resize_to_request();
+    }
+
     virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>&) override
     {
         //not implemented for the gtk variant
@@ -2955,6 +3057,13 @@ public:
 
     virtual ~GtkInstanceDialog() override
     {
+        if (!m_aHiddenWidgets.empty())
+        {
+            for (GtkWidget* pWindow : m_aHiddenWidgets)
+                g_object_unref(pWindow);
+            m_aHiddenWidgets.clear();
+        }
+
         g_signal_handler_disconnect(m_pDialog, m_nCloseSignalId);
         if (m_nResponseSignalId)
             g_signal_handler_disconnect(m_pDialog, m_nResponseSignalId);


More information about the Libreoffice-commits mailing list