[gtkmm] Gtk: Add LayoutManager and LayoutChild



commit 6946fb2d1550f7b2a367ca5710ab5fe60b600c71
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Mon Apr 1 19:06:13 2019 +0200

    Gtk: Add LayoutManager and LayoutChild

 .gitignore                |   4 ++
 gtk/gtkmm.h               |   2 +
 gtk/src/filelist.am       |   2 +
 gtk/src/layoutchild.ccg   |  19 ++++++++
 gtk/src/layoutchild.hg    |  68 +++++++++++++++++++++++++++++
 gtk/src/layoutmanager.ccg |  74 ++++++++++++++++++++++++++++++++
 gtk/src/layoutmanager.hg  | 107 ++++++++++++++++++++++++++++++++++++++++++++++
 gtk/src/widget.ccg        |  14 ++++++
 gtk/src/widget.hg         |  12 ++++++
 tools/m4/convert_gtk.m4   |   9 ++++
 10 files changed, 311 insertions(+)
---
diff --git a/.gitignore b/.gitignore
index 2b6c8714..b4d07944 100644
--- a/.gitignore
+++ b/.gitignore
@@ -317,6 +317,10 @@ gtk/gtkmm/label.cc
 gtk/gtkmm/label.h
 gtk/gtkmm/layout.cc
 gtk/gtkmm/layout.h
+gtk/gtkmm/layoutchild.cc
+gtk/gtkmm/layoutchild.h
+gtk/gtkmm/layoutmanager.cc
+gtk/gtkmm/layoutmanager.h
 gtk/gtkmm/levelbar.cc
 gtk/gtkmm/levelbar.h
 gtk/gtkmm/linkbutton.cc
diff --git a/gtk/gtkmm.h b/gtk/gtkmm.h
index b39535a0..e95703dc 100644
--- a/gtk/gtkmm.h
+++ b/gtk/gtkmm.h
@@ -178,6 +178,8 @@ extern const int gtkmm_micro_version;
 #include <gtkmm/calendar.h>
 #include <gtkmm/label.h>
 #include <gtkmm/layout.h>
+#include <gtkmm/layoutchild.h>
+#include <gtkmm/layoutmanager.h>
 #include <gtkmm/levelbar.h>
 #include <gtkmm/listbox.h>
 #include <gtkmm/listboxrow.h>
diff --git a/gtk/src/filelist.am b/gtk/src/filelist.am
index 769c1854..e86f8a9f 100644
--- a/gtk/src/filelist.am
+++ b/gtk/src/filelist.am
@@ -105,6 +105,8 @@ gtkmm_files_any_hg =                \
        infobar.hg              \
        label.hg                \
        layout.hg               \
+       layoutchild.hg \
+       layoutmanager.hg \
        levelbar.hg             \
        linkbutton.hg           \
        listbox.hg \
diff --git a/gtk/src/layoutchild.ccg b/gtk/src/layoutchild.ccg
new file mode 100644
index 00000000..48ec443e
--- /dev/null
+++ b/gtk/src/layoutchild.ccg
@@ -0,0 +1,19 @@
+/* Copyright (C) 2019 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtkmm/layoutmanager.h>
+#include <gtkmm/widget.h>
+#include <gtk/gtk.h>
diff --git a/gtk/src/layoutchild.hg b/gtk/src/layoutchild.hg
new file mode 100644
index 00000000..f6a8fd4a
--- /dev/null
+++ b/gtk/src/layoutchild.hg
@@ -0,0 +1,68 @@
+/* Copyright (C) 2019 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/object.h>
+#include <glibmm/refptr.h>
+
+_DEFS(gtkmm,gtk)
+_PINCLUDE(glibmm/private/object_p.h)
+
+namespace Gtk
+{
+class LayoutManager;
+class Widget;
+
+/** An object containing layout properties.
+ *
+ * %Gtk:LayoutChild is the base class for objects that are meant to hold
+ * layout properties. If a Gtk::LayoutManager has per-child properties,
+ * like their packing type, or the horizontal and vertical span, or the
+ * icon name, then the layout manager should use a %Gtk::LayoutChild
+ * implementation to store those properties.
+ *
+ * A %Gtk::LayoutChild instance is only ever valid while a widget is part
+ * of a layout.
+ *
+ * @newin{3,96}
+ */
+class LayoutChild : public Glib::Object
+{
+  _CLASS_GOBJECT(LayoutChild, GtkLayoutChild, GTK_LAYOUT_CHILD, Glib::Object, GObject)
+
+protected:
+  /** There is no create() method that corresponds to this constructor,
+   * because only derived classes shall be created.
+   */
+  _CTOR_DEFAULT
+
+public:
+  // No create() because only derived classes shall be instantiated.
+
+  _WRAP_METHOD(Glib::RefPtr<LayoutManager> get_layout_manager(),
+    gtk_layout_child_get_layout_manager, refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const LayoutManager> get_layout_manager() const,
+    gtk_layout_child_get_layout_manager, refreturn, constversion)
+
+  _WRAP_METHOD(Widget* get_child_widget(), gtk_layout_child_get_child_widget)
+  _WRAP_METHOD(const Widget* get_child_widget() const, gtk_layout_child_get_child_widget, constversion)
+
+  _WRAP_PROPERTY("layout-manager", Glib::RefPtr<LayoutManager>)
+  _WRAP_PROPERTY("child-widget", Widget*)
+
+  // There are no signals or vfuncs.
+};
+
+} // namespace Gtk
diff --git a/gtk/src/layoutmanager.ccg b/gtk/src/layoutmanager.ccg
new file mode 100644
index 00000000..d9c5d3aa
--- /dev/null
+++ b/gtk/src/layoutmanager.ccg
@@ -0,0 +1,74 @@
+/* Copyright (C) 2019 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtkmm/layoutchild.h>
+#include <gtkmm/widget.h>
+#include <gtk/gtk.h>
+
+namespace Gtk
+{
+// This vfunc callback is custom implemented because we want the output
+// arguments of the C++ vfunc to be int& (not int*), and the vfunc_callback
+// function may be called from gtk with NULL pointers.
+void LayoutManager_Class::measure_vfunc_callback(GtkLayoutManager* self,
+  GtkWidget* widget, GtkOrientation orientation, int for_size,
+  int* minimum, int* natural, int* minimum_baseline, int* natural_baseline)
+{
+  const auto obj_base = static_cast<Glib::ObjectBase*>(
+      Glib::ObjectBase::_get_current_wrapper((GObject*)self));
+
+  // Non-gtkmmproc-generated custom classes implicitly call the default
+  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
+  // generated classes can use this optimisation, which avoids the unnecessary
+  // parameter conversions if there is no possibility of the virtual function
+  // being overridden:
+  if (obj_base && obj_base->is_derived_())
+  {
+    const auto obj = dynamic_cast<CppObjectType* const>(obj_base);
+    if (obj) // This can be NULL during destruction.
+    {
+      try // Trap C++ exceptions which would normally be lost because this is a C callback.
+      {
+        // Call the virtual member method, which derived classes might override.
+        int no_minimum = 0;
+        int no_natural = 0;
+        int no_minimum_baseline = 0;
+        int no_natural_baseline = 0;
+        obj->measure_vfunc(*Glib::wrap(widget),
+          static_cast<Orientation>(orientation), for_size,
+          (minimum ? *minimum : no_minimum),
+          (natural ? *natural : no_natural),
+          (minimum_baseline ? *minimum_baseline : no_minimum_baseline),
+          (natural_baseline ? *natural_baseline : no_natural_baseline));
+        return;
+      }
+      catch (...)
+      {
+        Glib::exception_handlers_invoke();
+      }
+    }
+  }
+
+  BaseClassType *const base = static_cast<BaseClassType*>(
+      g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The 
original underlying C class).
+  );
+
+  // Call the original underlying C function:
+  if(base && base->measure)
+    (*base->measure)(self, widget, orientation, for_size, minimum, natural, minimum_baseline, 
natural_baseline);
+}
+
+} // namespace Gtk
diff --git a/gtk/src/layoutmanager.hg b/gtk/src/layoutmanager.hg
new file mode 100644
index 00000000..2d57c3cb
--- /dev/null
+++ b/gtk/src/layoutmanager.hg
@@ -0,0 +1,107 @@
+/* Copyright (C) 2019 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/object.h>
+#include <glibmm/refptr.h>
+#include <gtkmm/enums.h>
+
+_DEFS(gtkmm,gtk)
+_PINCLUDE(glibmm/private/object_p.h)
+
+namespace Gtk
+{
+class LayoutChild;
+class Widget;
+
+/** Base class for layout manager.
+ *
+ * Layout managers are delegate classes that handle the preferred size
+ * and the allocation of a container widget.
+ *
+ * You typically subclass %Gtk::LayoutManager if you want to implement a
+ * layout policy for the children of a widget, or if you want to determine
+ * the size of a widget depending on its contents.
+ *
+ * Each Gtk::Widget can only have one %Gtk::LayoutManager instance associated to it
+ * at any given time; it is possible, though, to replace the layout manager
+ * instance using Gtk::Widget::set_layout_manager().
+ *
+ * ## Layout properties
+ *
+ * A layout manager can expose properties for controlling the layout of
+ * each child, by creating an object type derived from Gtk::LayoutChild
+ * and installing the properties on it as normal GObject properties.
+ *
+ * Each Gtk::LayoutChild instance storing the layout properties for a
+ * specific child is created through the get_layout_child()
+ * method; a %Gtk::LayoutManager controls the creation of its Gtk::LayoutChild
+ * instances by overriding the create_layout_child_vfunc() virtual function.
+ *
+ * The Gtk::LayoutChild::property_layout_manager() and Gtk::LayoutChild::property_child_widget()
+ * properties on the newly created Gtk::LayoutChild instance are mandatory. The
+ * %Gtk::LayoutManager will cache the newly created Gtk::LayoutChild instance until
+ * the widget is removed from its parent, or the parent removes the layout manager.
+ *
+ * Each %Gtk::LayoutManager instance creating a Gtk::LayoutChild should use
+ * get_layout_child() every time it needs to query the
+ * layout properties; each Gtk::LayoutChild instance should call
+ * layout_changed() every time a property is updated, in
+ * order to queue a new size measuring and allocation.
+ *
+ * @newin{3,96}
+ */
+class LayoutManager : public Glib::Object
+{
+  _CLASS_GOBJECT(LayoutManager, GtkLayoutManager, GTK_LAYOUT_MANAGER, Glib::Object, GObject)
+
+protected:
+  /** There is no create() method that corresponds to this constructor,
+   * because only derived classes shall be created.
+   */
+  _CTOR_DEFAULT
+
+public:
+  // No create() because only derived classes shall be instantiated.
+
+  _WRAP_METHOD(void measure(Widget& widget, Orientation orientation, int for_size,
+    int& minimum, int& natural, int& minimum_baseline, int& natural_baseline) const,
+    gtk_layout_manager_measure)
+  _WRAP_METHOD(void allocate(Widget& widget, int width, int height, int baseline),
+     gtk_layout_manager_allocate)
+  _WRAP_METHOD(SizeRequestMode get_request_mode() const, gtk_layout_manager_get_request_mode)
+  _WRAP_METHOD(Widget* get_widget(), gtk_layout_manager_get_widget)
+  _WRAP_METHOD(const Widget* get_widget() const, gtk_layout_manager_get_widget, constversion)
+  _WRAP_METHOD(void layout_changed() const, gtk_layout_manager_layout_changed)
+  _WRAP_METHOD(Glib::RefPtr<LayoutChild> get_layout_child(Widget& child),
+    gtk_layout_manager_get_layout_child, refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const LayoutChild> get_layout_child(Widget& child) const,
+    gtk_layout_manager_get_layout_child, refreturn, constversion)
+
+protected:
+  _WRAP_VFUNC(SizeRequestMode get_request_mode(const Widget& widget) const, get_request_mode)
+  _WRAP_VFUNC(void measure(const Widget& widget, Orientation orientation, int for_size,
+    int& minimum, int& natural, int& minimum_baseline, int& natural_baseline) const,
+    measure, custom_vfunc_callback)
+  _WRAP_VFUNC(void allocate(const Widget& widget, int width, int height, int baseline),
+    allocate)
+#m4 _CONVERSION(`Glib::RefPtr<LayoutChild>', `GtkLayoutChild*', __CONVERT_REFPTR_TO_P)
+  _WRAP_VFUNC(Glib::RefPtr<LayoutChild> create_layout_child(const Widget& widget,
+    const Widget& for_child), create_layout_child, refreturn)
+
+  // There are no signals or properties.
+};
+
+} // namespace Gtk
diff --git a/gtk/src/widget.ccg b/gtk/src/widget.ccg
index 48f20f80..b50faf3b 100644
--- a/gtk/src/widget.ccg
+++ b/gtk/src/widget.ccg
@@ -31,6 +31,7 @@
 #include <gtkmm/selectiondata_private.h>
 #include <gtkmm/tooltip.h>
 #include <gtkmm/snapshot.h>
+#include <gtkmm/layoutmanager.h>
 #include <gtk/gtk.h>
 
 
@@ -319,6 +320,19 @@ void Widget::reparent(Container& new_parent)
   }
 }
 
+void Widget::set_layout_manager(const Glib::RefPtr<LayoutManager>& layout_manager)
+{
+  // gtk_widget_set_layout_manager() does not take a ref.
+  if (layout_manager)
+    layout_manager->reference();
+  gtk_widget_set_layout_manager(gobj(), Glib::unwrap(layout_manager));
+}
+
+void Widget::unset_layout_manager()
+{
+  gtk_widget_set_layout_manager(gobj(), nullptr);
+}
+
 void Widget::unset_name()
 {
   gtk_widget_set_name(gobj(), nullptr);
diff --git a/gtk/src/widget.hg b/gtk/src/widget.hg
index 12b81c95..969e2225 100644
--- a/gtk/src/widget.hg
+++ b/gtk/src/widget.hg
@@ -71,6 +71,7 @@ class Window;
 class Root;
 class Container;
 class EventController;
+class LayoutManager;
 class Settings;
 class Snapshot;
 class Tooltip;
@@ -132,6 +133,16 @@ public:
     int& minimum_baseline, int& natural_baseline) const, gtk_widget_measure)
   _WRAP_METHOD(void get_preferred_size(Requisition& minimum_size, Requisition& natural_size) const, 
gtk_widget_get_preferred_size)
 
+  _WRAP_METHOD_DOCS_ONLY(gtk_widget_set_layout_manager)
+  void set_layout_manager(const Glib::RefPtr<LayoutManager>& layout_manager);
+  /** Undoes the effect of a previous call to set_layout_manager().
+   */
+  void unset_layout_manager();
+  _WRAP_METHOD(Glib::RefPtr<LayoutManager> get_layout_manager(),
+    gtk_widget_get_layout_manager, refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const LayoutManager> get_layout_manager() const,
+    gtk_widget_get_layout_manager, refreturn, constversion)
+
   _WRAP_METHOD(void add_accelerator(const Glib::ustring& accel_signal, const Glib::RefPtr<AccelGroup>& 
accel_group,
                guint accel_key, Gdk::ModifierType accel_mods, AccelFlags accel_flags), 
gtk_widget_add_accelerator)
 
@@ -752,6 +763,7 @@ dnl
   _WRAP_PROPERTY("overflow", Overflow, newin "3,96")
   _WRAP_PROPERTY("scale-factor", int)
   _WRAP_PROPERTY("css-name", Glib::ustring)
+  _WRAP_PROPERTY("layout-manager", Glib::RefPtr<LayoutManager>)
 
 protected:
 
diff --git a/tools/m4/convert_gtk.m4 b/tools/m4/convert_gtk.m4
index 161a3a3e..369d4f93 100644
--- a/tools/m4/convert_gtk.m4
+++ b/tools/m4/convert_gtk.m4
@@ -250,6 +250,7 @@ _CONVERSION(`RadioButton&',`GtkRadioButton*',`($3).gobj()')
 
 # Ptr (gtk+) -> Ref (Gtkmm)
 _CONVERSION(`GtkWidget*', `Widget&', `*Glib::wrap($3)')
+_CONVERSION(`GtkWidget*', `const Widget&', `*Glib::wrap($3)')
 
 # Ref (Gtkmm) -> GtkWidget* Ptr (gtk+)
 define(`__FR2PD',`($`'3).Gtk::Widget::gobj()')
@@ -581,6 +582,14 @@ _CONVERSION(`GtkWidgetPath*',`WidgetPath',`Glib::wrap($3, true)')
 _CONVERSION(`const GtkWidgetPath*',`WidgetPath',`Glib::wrap(const_cast<GtkWidgetPath*>($3), true)')
 _CONVERSION(`const WidgetPath&',`GtkWidgetPath*',`const_cast<WidgetPath&>($3).gobj()')
 
+# LayoutChild, LayoutManager
+_CONVERSION(`GtkLayoutManager*',`Glib::RefPtr<LayoutManager>',`Glib::wrap($3)')
+_CONVERSION(`GtkLayoutManager*',`Glib::RefPtr<const LayoutManager>',`Glib::wrap($3)')
+_CONVERSION(`const Glib::RefPtr<LayoutManager>&',`GtkLayoutManager*',__CONVERT_REFPTR_TO_P)
+
+_CONVERSION(`GtkLayoutChild*',`Glib::RefPtr<LayoutChild>',`Glib::wrap($3)')
+_CONVERSION(`GtkLayoutChild*',`Glib::RefPtr<const LayoutChild>',`Glib::wrap($3)')
+
 # Used by LockButton
 _CONVERSION(`Glib::RefPtr<Gio::Permission>&',`GPermission*',__CONVERT_REFPTR_TO_P)
 _CONVERSION(`const Glib::RefPtr<const 
Gio::Permission>&',`GPermission*',__CONVERT_CONST_REFPTR_TO_P_SUN(Gio::Permission))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]