cui/source/dialogs/AdditionsDialog.cxx |   10 +--
 cui/source/inc/AdditionsDialog.hxx     |    4 -
 include/vcl/weld.hxx                   |   15 ++++
 vcl/inc/qt5/QtInstanceBuilder.hxx      |    1 
 vcl/inc/salvtables.hxx                 |   15 ++++
 vcl/qt5/QtInstanceBuilder.cxx          |    6 +
 vcl/source/app/salvtables.cxx          |   46 +++++++++++++++
 vcl/unx/gtk3/gtkinst.cxx               |  101 +++++++++++++++++++++++++++++++++
 8 files changed, 191 insertions(+), 7 deletions(-)

New commits:
commit b7faeb1a70ee57c19531bc0f23538dd0ce6f07d1
Author:     Michael Weghorn <[email protected]>
AuthorDate: Mon Dec 16 11:42:05 2024 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Tue Dec 17 22:54:19 2024 +0100

    weld: Port AdditionsDialog to new weld::Grid API
    
    See previous commit
    
        Change-Id: I67f5ea16b5108e8359820850f0815e34db439ef1
        Author: Michael Weghorn <[email protected]>
        Date:   Mon Dec 16 11:02:00 2024 +0100
    
            weld: Add weld::Grid to handle grid child positions
    
    for more background.
    
    The changed code path can e.g. be triggered in Writer as follows:
    
    * "File" -> "Templates" -> "Manage Templates",
    * click the "Manage" combobox
    * select the "Extensions" entry
    
    Change-Id: I28f258fde8700ade4d5c6ded39d6063f31bc2e30
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178571
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/cui/source/dialogs/AdditionsDialog.cxx 
b/cui/source/dialogs/AdditionsDialog.cxx
index a8eabf6d369c..ed35df71468e 100644
--- a/cui/source/dialogs/AdditionsDialog.cxx
+++ b/cui/source/dialogs/AdditionsDialog.cxx
@@ -433,7 +433,7 @@ AdditionsDialog::AdditionsDialog(weld::Window* pParent, 
const OUString& sAdditio
     , m_xEntrySearch(m_xBuilder->weld_entry(u"entrySearch"_ustr))
     , m_xButtonClose(m_xBuilder->weld_button(u"buttonClose"_ustr))
     , m_xContentWindow(m_xBuilder->weld_scrolled_window(u"contentWindow"_ustr))
-    , m_xContentGrid(m_xBuilder->weld_container(u"contentGrid"_ustr))
+    , m_xContentGrid(m_xBuilder->weld_grid(u"contentGrid"_ustr))
     , m_xLabelProgress(m_xBuilder->weld_label(u"labelProgress"_ustr))
     , m_xGearBtn(m_xBuilder->weld_menu_button(u"buttonGear"_ustr))
 {
@@ -602,9 +602,9 @@ bool AdditionsDialog::sortByDownload(const AdditionInfo& a, 
const AdditionInfo&
     return a.sDownloadNumber.toUInt32() > b.sDownloadNumber.toUInt32();
 }
 
-AdditionsItem::AdditionsItem(weld::Widget* pParent, AdditionsDialog* 
pParentDialog,
+AdditionsItem::AdditionsItem(weld::Grid* pParentGrid, AdditionsDialog* 
pParentDialog,
                              const AdditionInfo& additionInfo)
-    : m_xBuilder(Application::CreateBuilder(pParent, 
u"cui/ui/additionsfragment.ui"_ustr))
+    : m_xBuilder(Application::CreateBuilder(pParentGrid, 
u"cui/ui/additionsfragment.ui"_ustr))
     , m_xContainer(m_xBuilder->weld_widget(u"additionsEntry"_ustr))
     , m_xImageScreenshot(m_xBuilder->weld_image(u"imageScreenshot"_ustr))
     , m_xButtonInstall(m_xBuilder->weld_button(u"buttonInstall"_ustr))
@@ -629,8 +629,8 @@ AdditionsItem::AdditionsItem(weld::Widget* pParent, 
AdditionsDialog* pParentDial
     SolarMutexGuard aGuard;
 
     // AdditionsItem set location
-    m_xContainer->set_grid_left_attach(0);
-    m_xContainer->set_grid_top_attach(pParentDialog->m_aAdditionsItems.size());
+    pParentGrid->set_child_left_attach(*m_xContainer, 0);
+    pParentGrid->set_child_top_attach(*m_xContainer, 
pParentDialog->m_aAdditionsItems.size());
 
     // Set maximum length of the extension title
     OUString sExtensionName;
diff --git a/cui/source/inc/AdditionsDialog.hxx 
b/cui/source/inc/AdditionsDialog.hxx
index 559a4ca911ff..f94eefd3addb 100644
--- a/cui/source/inc/AdditionsDialog.hxx
+++ b/cui/source/inc/AdditionsDialog.hxx
@@ -72,7 +72,7 @@ public:
     std::vector<AdditionInfo> m_aAllExtensionsVector; // Stores the all 
extensions' info
 
     std::unique_ptr<weld::ScrolledWindow> m_xContentWindow;
-    std::unique_ptr<weld::Container> m_xContentGrid;
+    std::unique_ptr<weld::Grid> m_xContentGrid;
 
     std::unique_ptr<weld::Label> m_xLabelProgress;
     std::unique_ptr<weld::MenuButton> m_xGearBtn;
@@ -102,7 +102,7 @@ public:
 class AdditionsItem
 {
 public:
-    AdditionsItem(weld::Widget* pParent, AdditionsDialog* pParentDialog,
+    AdditionsItem(weld::Grid* pParentGrid, AdditionsDialog* pParentDialog,
                   const AdditionInfo& additionInfo);
     bool getExtensionFile(OUString& sExtensionFile);
 
commit 7056ea9c29c7e454c21b525e61cdc1e0c03f7301
Author:     Michael Weghorn <[email protected]>
AuthorDate: Mon Dec 16 11:02:00 2024 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Tue Dec 17 22:54:10 2024 +0100

    weld: Add weld::Grid to handle grid child positions
    
    Currently, weld::Widget provides methods that can
    be used to retrieve and change the position (and column
    span) of widgets that are located inside of a grid
    (parent), e.g. weld::Widget::set_grid_left_attach
    to set the column.
    
    These methods however only make sense for widgets
    that are actually direct children of a grid, not
    for any "random" weld::Widget.
    Generally, it's the grid's responsibility to manage
    child positions, and the gtk3/gtk4 implementations
    actually assume that the parent is a GtkGrid, retrieve
    that parent and then call the corresponding GTK API
    functions for that grid.
    
    Align the weld API more with the concept of the
    grid being responsible for positioning its children
    by introducing a new weld::Grid class with methods
    equivalent to the current weld::Widget ones, but that
    take the child widget as an additional parameter.
    Take over the existing logic from the corresponding
    weld::Widget methods for both, the gtk and vcl implementations
    (e.g. GtkInstanceWidget::set_grid_left_attach
     -> GtkInstanceGrid::set_child_left_attach).
    Add an assert that the passed widget is actually
    a grid child.
    
    Deprecate the existing weld::Widget methods for grid
    position handling. They will be removed once existing code has
    been ported to the new weld::Grid API.
    
    The fact that the vcl implementation, VclGrid
    (used by vcl's new SalInstanceGrid implementation
    of weld::Grid), still relies on its vcl::Window children
    having the corresponding members set correctly remains
    unaffected.
    
    Change-Id: I67f5ea16b5108e8359820850f0815e34db439ef1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178570
    Reviewed-by: Caolán McNamara <[email protected]>
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index ebe2d8a25ef8..32fd70fd575b 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -195,6 +195,10 @@ public:
     virtual OUString get_help_id() const = 0;
     virtual void set_help_id(const OUString& rName) = 0;
 
+    // NOTE: The following 5 methods for handling grid positions
+    // and column span are deprecated and should not be used in new code.
+    // Call the corresponding weld::Grid methods on the parent grid instead.
+    // (These deprecated methods will be dropped once existing code has been 
ported.)
     virtual void set_grid_left_attach(int nAttach) = 0;
     virtual int get_grid_left_attach() const = 0;
     virtual void set_grid_width(int nCols) = 0;
@@ -422,6 +426,16 @@ public:
     virtual void sort_native_button_order() = 0;
 };
 
+class VCL_DLLPUBLIC Grid : virtual public Container
+{
+public:
+    virtual void set_child_left_attach(weld::Widget& rWidget, int nAttach) = 0;
+    virtual int get_child_left_attach(weld::Widget& rWidget) const = 0;
+    virtual void set_child_column_span(weld::Widget& rWidget, int nCols) = 0;
+    virtual void set_child_top_attach(weld::Widget& rWidget, int nAttach) = 0;
+    virtual int get_child_top_attach(weld::Widget& rWidget) const = 0;
+};
+
 class VCL_DLLPUBLIC Paned : virtual public Container
 {
 public:
@@ -2657,6 +2671,7 @@ public:
     virtual std::unique_ptr<Widget> weld_widget(const OUString& id) = 0;
     virtual std::unique_ptr<Container> weld_container(const OUString& id) = 0;
     virtual std::unique_ptr<Box> weld_box(const OUString& id) = 0;
+    virtual std::unique_ptr<Grid> weld_grid(const OUString& id) = 0;
     virtual std::unique_ptr<Paned> weld_paned(const OUString& id) = 0;
     virtual std::unique_ptr<Button> weld_button(const OUString& id) = 0;
     virtual std::unique_ptr<MenuButton> weld_menu_button(const OUString& id) = 
0;
diff --git a/vcl/inc/qt5/QtInstanceBuilder.hxx 
b/vcl/inc/qt5/QtInstanceBuilder.hxx
index fe200913dfdd..3380b8beb571 100644
--- a/vcl/inc/qt5/QtInstanceBuilder.hxx
+++ b/vcl/inc/qt5/QtInstanceBuilder.hxx
@@ -36,6 +36,7 @@ public:
     virtual std::unique_ptr<weld::Widget> weld_widget(const OUString& rId) 
override;
     virtual std::unique_ptr<weld::Container> weld_container(const OUString& 
rId) override;
     virtual std::unique_ptr<weld::Box> weld_box(const OUString&) override;
+    virtual std::unique_ptr<weld::Grid> weld_grid(const OUString& rId) 
override;
     virtual std::unique_ptr<weld::Paned> weld_paned(const OUString&) override;
     virtual std::unique_ptr<weld::Frame> weld_frame(const OUString& rId) 
override;
     virtual std::unique_ptr<weld::ScrolledWindow>
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index 62dc0e8ea8db..c51f2c12a999 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -64,6 +64,8 @@ public:
 
     virtual std::unique_ptr<weld::Box> weld_box(const OUString& id) override;
 
+    virtual std::unique_ptr<weld::Grid> weld_grid(const OUString& id) override;
+
     virtual std::unique_ptr<weld::Paned> weld_paned(const OUString& id) 
override;
 
     virtual std::unique_ptr<weld::Frame> weld_frame(const OUString& id) 
override;
@@ -2137,6 +2139,19 @@ public:
     virtual void sort_native_button_order() override;
 };
 
+class SalInstanceGrid : public SalInstanceContainer, public virtual weld::Grid
+{
+public:
+    SalInstanceGrid(VclGrid* pGrid, SalInstanceBuilder* pBuilder, bool 
bTakeOwnership);
+
+public:
+    virtual void set_child_left_attach(weld::Widget& rWidget, int nAttach) 
override;
+    virtual int get_child_left_attach(weld::Widget& rWidget) const override;
+    virtual void set_child_column_span(weld::Widget& rWidget, int nCols) 
override;
+    virtual void set_child_top_attach(weld::Widget& rWidget, int nAttach) 
override;
+    virtual int get_child_top_attach(weld::Widget& rWidget) const override;
+};
+
 class SalInstanceImage : public SalInstanceWidget, public virtual weld::Image
 {
 private:
diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index 66561985ee94..342986862de4 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -153,6 +153,12 @@ std::unique_ptr<weld::Box> 
QtInstanceBuilder::weld_box(const OUString&)
     return nullptr;
 }
 
+std::unique_ptr<weld::Grid> QtInstanceBuilder::weld_grid(const OUString&)
+{
+    assert(false && "Not implemented yet");
+    return nullptr;
+}
+
 std::unique_ptr<weld::Paned> QtInstanceBuilder::weld_paned(const OUString&)
 {
     assert(false && "Not implemented yet");
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 2533f7def9d5..c8edbc05da2f 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1528,6 +1528,46 @@ void SalInstanceBox::reorder_child(weld::Widget* 
pWidget, int nNewPosition)
 
 void SalInstanceBox::sort_native_button_order() { 
::sort_native_button_order(*m_xBox); }
 
+SalInstanceGrid::SalInstanceGrid(VclGrid* pGrid, SalInstanceBuilder* pBuilder, 
bool bTakeOwnership)
+    : SalInstanceContainer(pGrid, pBuilder, bTakeOwnership)
+{
+}
+
+void SalInstanceGrid::set_child_left_attach(weld::Widget& rWidget, int nAttach)
+{
+    vcl::Window* pChild = 
dynamic_cast<SalInstanceWidget&>(rWidget).getWidget();
+    assert(pChild && pChild->GetParent() == getWidget() && "widget is not a 
grid child");
+    pChild->set_grid_left_attach(nAttach);
+}
+
+int SalInstanceGrid::get_child_left_attach(weld::Widget& rWidget) const
+{
+    vcl::Window* pChild = 
dynamic_cast<SalInstanceWidget&>(rWidget).getWidget();
+    assert(pChild && pChild->GetParent() == getWidget() && "widget is not a 
grid child");
+    return pChild->get_grid_left_attach();
+}
+
+void SalInstanceGrid::set_child_column_span(weld::Widget& rWidget, int nCols)
+{
+    vcl::Window* pChild = 
dynamic_cast<SalInstanceWidget&>(rWidget).getWidget();
+    assert(pChild && pChild->GetParent() == getWidget() && "widget is not a 
grid child");
+    pChild->set_grid_width(nCols);
+}
+
+void SalInstanceGrid::set_child_top_attach(weld::Widget& rWidget, int nAttach)
+{
+    vcl::Window* pChild = 
dynamic_cast<SalInstanceWidget&>(rWidget).getWidget();
+    assert(pChild && pChild->GetParent() == getWidget() && "widget is not a 
grid child");
+    pChild->set_grid_top_attach(nAttach);
+}
+
+int SalInstanceGrid::get_child_top_attach(weld::Widget& rWidget) const
+{
+    vcl::Window* pChild = 
dynamic_cast<SalInstanceWidget&>(rWidget).getWidget();
+    assert(pChild && pChild->GetParent() == getWidget() && "widget is not a 
grid child");
+    return pChild->get_grid_top_attach();
+}
+
 namespace
 {
 void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& 
rTopLeft,
@@ -7262,6 +7302,12 @@ std::unique_ptr<weld::Box> 
SalInstanceBuilder::weld_box(const OUString& id)
     return pContainer ? std::make_unique<SalInstanceBox>(pContainer, this, 
false) : nullptr;
 }
 
+std::unique_ptr<weld::Grid> SalInstanceBuilder::weld_grid(const OUString& id)
+{
+    VclGrid* pGrid = m_xBuilder->get<VclGrid>(id);
+    return pGrid ? std::make_unique<SalInstanceGrid>(pGrid, this, false) : 
nullptr;
+}
+
 std::unique_ptr<weld::Paned> SalInstanceBuilder::weld_paned(const OUString& id)
 {
     VclPaned* pPaned = m_xBuilder->get<VclPaned>(id);
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 729d4dcc93ac..c3042eab5b77 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -6201,6 +6201,98 @@ public:
     }
 };
 
+class GtkInstanceGrid : public GtkInstanceContainer, public virtual weld::Grid
+{
+private:
+    GtkGrid* m_pGrid;
+
+public:
+    GtkInstanceGrid(GtkGrid* pGrid, GtkInstanceBuilder* pBuilder, bool 
bTakeOwnership)
+#if !GTK_CHECK_VERSION(4, 0, 0)
+        : GtkInstanceContainer(GTK_CONTAINER(pGrid), pBuilder, bTakeOwnership)
+#else
+        : GtkInstanceContainer(GTK_WIDGET(pGrid), pBuilder, bTakeOwnership)
+#endif
+        , m_pGrid(pGrid)
+    {
+    }
+
+public:
+    virtual void set_child_left_attach(weld::Widget& rWidget, int nAttach) 
override
+    {
+        GtkWidget* pWidget = 
dynamic_cast<GtkInstanceWidget&>(rWidget).getWidget();
+        assert(gtk_widget_get_parent(pWidget) == GTK_WIDGET(m_pGrid) && 
"widget is not a grid child");
+#if GTK_CHECK_VERSION(4, 0, 0)
+        int row, width, height;
+        gtk_grid_query_child(m_pGrid, pWidget, nullptr, &row, &width, &height);
+        g_object_ref(pWidget);
+        gtk_grid_remove(m_pGrid, pWidget);
+        gtk_grid_attach(m_pGrid, pWidget, nAttach, row, width, height);
+        g_object_unref(pWidget);
+#else
+        gtk_container_child_set(GTK_CONTAINER(m_pGrid), pWidget, 
"left-attach", nAttach, nullptr);
+#endif
+    }
+
+    virtual int get_child_left_attach(weld::Widget& rWidget) const override
+    {
+        GtkWidget* pWidget = 
dynamic_cast<GtkInstanceWidget&>(rWidget).getWidget();
+        assert(gtk_widget_get_parent(pWidget) == GTK_WIDGET(m_pGrid) && 
"widget is not a grid child");
+        gint nAttach(0);
+#if GTK_CHECK_VERSION(4, 0, 0)
+        gtk_grid_query_child(m_pGrid, pWidget, &nAttach, nullptr, nullptr, 
nullptr);
+#else
+        gtk_container_child_get(GTK_CONTAINER(m_pGrid), pWidget, 
"left-attach", &nAttach, nullptr);
+#endif
+        return nAttach;
+    }
+
+    virtual void set_child_column_span(weld::Widget& rWidget, int nCols) 
override
+    {
+        GtkWidget* pWidget = 
dynamic_cast<GtkInstanceWidget&>(rWidget).getWidget();
+        assert(gtk_widget_get_parent(pWidget) == GTK_WIDGET(m_pGrid) && 
"widget is not a grid child");
+#if GTK_CHECK_VERSION(4, 0, 0)
+        int col, row, height;
+        gtk_grid_query_child(m_pGrid, pWidget, &col, &row, nullptr, &height);
+        g_object_ref(pWidget);
+        gtk_grid_remove(m_pGrid, pWidget);
+        gtk_grid_attach(m_pGrid, pWidget, col, row, nCols, height);
+        g_object_unref(pWidget);
+#else
+        gtk_container_child_set(GTK_CONTAINER(m_pGrid), pWidget, "width", 
nCols, nullptr);
+#endif
+    }
+
+    virtual void set_child_top_attach(weld::Widget& rWidget, int nAttach) 
override
+    {
+        GtkWidget* pWidget = 
dynamic_cast<GtkInstanceWidget&>(rWidget).getWidget();
+        assert(gtk_widget_get_parent(pWidget) == GTK_WIDGET(m_pGrid) && 
"widget is not a grid child");
+#if GTK_CHECK_VERSION(4, 0, 0)
+        int col, width, height;
+        gtk_grid_query_child(m_pGrid, pWidget, &col, nullptr, &width, &height);
+        g_object_ref(pWidget);
+        gtk_grid_remove(m_pGrid, pWidget);
+        gtk_grid_attach(m_pGrid, pWidget, col, nAttach, width, height);
+        g_object_unref(pWidget);
+#else
+        gtk_container_child_set(GTK_CONTAINER(m_pGrid), pWidget, "top-attach", 
nAttach, nullptr);
+#endif
+    }
+
+    virtual int get_child_top_attach(weld::Widget& rWidget) const override
+    {
+        GtkWidget* pWidget = 
dynamic_cast<GtkInstanceWidget&>(rWidget).getWidget();
+        assert(gtk_widget_get_parent(pWidget) == GTK_WIDGET(m_pGrid) && 
"widget is not a grid child");
+        gint nAttach(0);
+#if GTK_CHECK_VERSION(4, 0, 0)
+        gtk_grid_query_child(m_pGrid, pWidget, nullptr, &nAttach, nullptr, 
nullptr);
+#else
+        gtk_container_child_get(GTK_CONTAINER(m_pGrid), pWidget, "top-attach", 
&nAttach, nullptr);
+#endif
+        return nAttach;
+    }
+};
+
 }
 
 namespace
@@ -24586,6 +24678,15 @@ public:
         return std::make_unique<GtkInstanceBox>(pBox, this, false);
     }
 
+    virtual std::unique_ptr<weld::Grid> weld_grid(const OUString &id) override
+    {
+        GtkGrid* pGrid = GTK_GRID(gtk_builder_get_object(m_pBuilder, 
OUStringToOString(id, RTL_TEXTENCODING_UTF8).getStr()));
+        if (!pGrid)
+            return nullptr;
+        auto_add_parentless_widgets_to_container(GTK_WIDGET(pGrid));
+        return std::make_unique<GtkInstanceGrid>(pGrid, this, false);
+    }
+
     virtual std::unique_ptr<weld::Paned> weld_paned(const OUString &id) 
override
     {
         GtkPaned* pPaned = GTK_PANED(gtk_builder_get_object(m_pBuilder, 
OUStringToOString(id, RTL_TEXTENCODING_UTF8).getStr()));

Reply via email to