[gtkmm/wip/dboles/builder-nicer-4: 4/4] Builder: Add get_object<Derived>(name) overloads



commit 0b82479971b4d34968bc3dac21e5b009b4960e8c
Author: Daniel Boles <dboles src gnome org>
Date:   Sun Dec 16 23:46:07 2018 +0000

    Builder: Add get_object<Derived>(name) overloads
    
    Allow getting and casting to a subclass of Glib::Object in one line,
    thus making it nicer to deal with non-widget objects in Builder files.
    
    The non-template and template member functions act as distinct
    overloads, meaning the new ones can be named get_object() also.
    
    Add a Gtk::Adjustment to tests/builder, and check its refcounts are OK.
    
    https://gitlab.gnome.org/GNOME/gtkmm/issues/43

 gtk/src/builder.hg    | 32 ++++++++++++++++++++++++++++++++
 tests/builder/main.cc | 28 ++++++++++++++++++++++++----
 2 files changed, 56 insertions(+), 4 deletions(-)
---
diff --git a/gtk/src/builder.hg b/gtk/src/builder.hg
index 73028e1f..77275a7e 100644
--- a/gtk/src/builder.hg
+++ b/gtk/src/builder.hg
@@ -57,6 +57,7 @@ _WRAP_GERROR(BuilderError,GtkBuilderError,GTK_BUILDER_ERROR)
  * not have to worry about their lifecycle), or without a parent, in which
  * case they have to be added to some container before the builder is deleted
  * to make use of them.
+ *
  * Non-widget objects need to be fetched with get_object() or get_objects()
  * to keep them beyond the lifespan of the builder.
  *
@@ -424,6 +425,7 @@ public:
   //TODO: Custom-implement this and prevent it from being used with GTK_WIDGET-derived types?
   // A Builder can contain objects that don't derive from Buildable,
   // for instance if objects have been added with expose_object().
+
   /** Gets the object named @a name.
    *
    * @newin{2,12}
@@ -432,6 +434,7 @@ public:
    * @return The object named @a name or <tt>nullptr</tt> if it could not be found in the object tree.
    */
   _WRAP_METHOD(Glib::RefPtr<Glib::Object> get_object(const Glib::ustring& name), gtk_builder_get_object, 
refreturn)
+
   /** Gets the object named @a name.
    *
    * @newin{3,8}
@@ -441,6 +444,35 @@ public:
    */
   _WRAP_METHOD(Glib::RefPtr<const Glib::Object> get_object(const Glib::ustring& name) const, 
gtk_builder_get_object, refreturn, constversion)
 
+  /** Gets the object named @a name, cast to a specific derived type.
+   *
+   * For instance:
+   * @code
+   * auto adjustment = refBuilder->get_object<Gtk::Adjustment>("adjustment_id");
+   * adjustment->get_value(42);
+   * @endcode
+   *
+   * @newin{3,94}
+   *
+   * @param name Name of object to get.
+   * @return The object named @a name or <tt>nullptr</tt> if it could not be
+   *   found in the object tree or could not be cast to the specified type.
+   */
+  template <class T_Object> inline
+  Glib::RefPtr<T_Object> get_object(const Glib::ustring& name)
+  {
+    return std::dynamic_pointer_cast<T_Object>(get_object(name));
+  }
+
+  /** See the non-const version.
+   * @newin{3,94}
+   */
+  template <class T_Object> inline
+  Glib::RefPtr<const T_Object> get_object(const Glib::ustring& name) const
+  {
+    return const_cast<Builder*>(this)->get_object<const T_Object>(name);
+  }
+
   /** Gets a widget from the Builder file.
    * For instance:
    * @code
diff --git a/tests/builder/main.cc b/tests/builder/main.cc
index 39bde307..204297f5 100644
--- a/tests/builder/main.cc
+++ b/tests/builder/main.cc
@@ -66,6 +66,13 @@ const char gladefile[] =
     "<property name='can_focus'>True</property>"
     "<property name='receives_default'>True</property>"
   "</object>"
+  "<object class='GtkAdjustment' id='adjustment'>"
+    "<property name='value'>50</property>"
+    "<property name='lower'>0</property>"
+    "<property name='upper'>100</property>"
+    "<property name='step-increment'>1</property>"
+    "<property name='page-increment'>10</property>"
+  "</object>"
 "</interface>";
 
 void on_managed_button_deleted(sigc::notifiable* /* data */)
@@ -78,6 +85,11 @@ void on_orphaned_button_deleted(sigc::notifiable* /* data */)
   std::cout << "Orphaned Gtk::Button deleted" << std::endl;
 }
 
+void on_adjustment_deleted(sigc::notifiable* /* data */)
+{
+  std::cout << "Gtk::Adjustment deleted" << std::endl;
+}
+
 class DerivedButton : public Gtk::Button
 {
 public:
@@ -151,16 +163,21 @@ int main(int argc, char* argv[])
   auto orph_button = builder->get_widget<Gtk::Button>("orphaned_button");
   orph_button->add_destroy_notify_callback(nullptr, on_orphaned_button_deleted);
 
+  auto adjustment = builder->get_object<Gtk::Adjustment>("adjustment");
+  adjustment->add_destroy_notify_callback(nullptr, on_adjustment_deleted);
+
   const GObject* const window = (GObject*)main_win->gobj();
   const GObject* const orphaned_button = (GObject*)orph_button->gobj();
   const GObject* const derived_button = (GObject*)main_win->get_derived_button()->gobj();
   const GObject* const standard_button = (GObject*)main_win->get_standard_button()->gobj();
+  const GObject* const adjustment_gobj = (GObject*)adjustment->gobj();
 
   std::cout << "Before app->run(*main_win, argc1, argv)" << std::endl
     << "  ref_count(MainWindow)=" << window->ref_count << std::endl
     << "  ref_count(DerivedButton)=" << derived_button->ref_count << std::endl
     << "  ref_count(Gtk::Button)=" << standard_button->ref_count << std::endl
-    << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl;
+    << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl
+    << "  ref_count(adjustment)=" << adjustment_gobj->ref_count << std::endl;
 
   const int result = app->run(*main_win, argc1, argv);
 
@@ -168,7 +185,8 @@ int main(int argc, char* argv[])
     << "  ref_count(MainWindow)=" << window->ref_count << std::endl
     << "  ref_count(DerivedButton)=" << derived_button->ref_count << std::endl
     << "  ref_count(Gtk::Button)=" << standard_button->ref_count << std::endl
-    << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl;
+    << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl
+    << "  ref_count(adjustment)=" << adjustment_gobj->ref_count << std::endl;
 
   delete main_win;
 
@@ -176,7 +194,8 @@ int main(int argc, char* argv[])
     << "  ref_count(MainWindow)=" << window->ref_count << std::endl
     << "  ref_count(DerivedButton)=" << derived_button->ref_count << std::endl
     << "  ref_count(Gtk::Button)=" << standard_button->ref_count << std::endl
-    << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl;
+    << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl
+    << "  ref_count(adjustment)=" << adjustment_gobj->ref_count << std::endl;
 
   builder.reset();
 
@@ -187,7 +206,8 @@ int main(int argc, char* argv[])
       << "  ref_count(MainWindow)=" << window->ref_count << std::endl
       << "  ref_count(DerivedButton)=" << derived_button->ref_count << std::endl
       << "  ref_count(Gtk::Button)=" << standard_button->ref_count << std::endl
-      << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl;
+      << "  ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl
+      << "  ref_count(adjustment)=" << adjustment_gobj->ref_count << std::endl;
   }
 
   return result;


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