[gtkmm/wip/dboles/builder-nicer-4] Builder: Add get_object<Derived>(name) overloads
- From: Daniel Boles <dboles src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm/wip/dboles/builder-nicer-4] Builder: Add get_object<Derived>(name) overloads
- Date: Mon, 17 Dec 2018 18:20:39 +0000 (UTC)
commit b43773fefaa7ed589301f026a2e70e876e7850c2
Author: Daniel Boles <dboles src gnome org>
Date: Mon Dec 17 18:19:39 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.
Also add a g_assert that (A) ensures that the test compiles, i.e. we got
the right type in the RefPtr and (B) checks we get the right :value out.
In case (B) seems frivolous, I did see it not working due to prop order!
Adjustment:value needs set after :lower|:upper as it is clamped by them.
While here, g_assert() the mm pointers/RefPtrs just to be fully paranoid
https://gitlab.gnome.org/GNOME/gtkmm/issues/43
gtk/src/builder.hg | 32 ++++++++++++++++++++++++++++++++
tests/builder/main.cc | 34 ++++++++++++++++++++++++++++++----
2 files changed, 62 insertions(+), 4 deletions(-)
---
diff --git a/gtk/src/builder.hg b/gtk/src/builder.hg
index 09c4707c..def5df1a 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->set_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..3bfda1de 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='lower'>0</property>"
+ "<property name='upper'>100</property>"
+ "<property name='value'>50</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:
@@ -143,24 +155,35 @@ int main(int argc, char* argv[])
}
auto app = Gtk::Application::create();
+ g_assert_nonnull(app);
auto builder = Gtk::Builder::create_from_string(gladefile);
+ g_assert_nonnull(builder);
auto main_win = Gtk::Builder::get_widget_derived<MainWindow>(builder, "main_window");
+ g_assert_nonnull(main_win);
auto orph_button = builder->get_widget<Gtk::Button>("orphaned_button");
+ g_assert_nonnull(orph_button);
orph_button->add_destroy_notify_callback(nullptr, on_orphaned_button_deleted);
+ auto adjustment = builder->get_object<Gtk::Adjustment>("adjustment");
+ g_assert_nonnull(adjustment);
+ g_assert_cmpfloat(adjustment->get_value(), ==, 50);
+ 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 +191,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 +200,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 +212,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]