[gtkmm] Gtk::Builder: Make get_widget_derived() a variadic template
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm] Gtk::Builder: Make get_widget_derived() a variadic template
- Date: Thu, 28 Jan 2016 09:59:28 +0000 (UTC)
commit 6e98903fc458c96fbf87b2080c9a06a0f221ead3
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date: Thu Jan 28 10:53:18 2016 +0100
Gtk::Builder: Make get_widget_derived() a variadic template
* gtk/src/builder.hg: get_widget_derived() can take extra parameters, which
are forwarded to the constructor of the derived class.
Inspired by a patch by Armin Burgmeier <armin arbur net>.
* tests/builder/main.cc: Add a parameter to the constructor of the derived
class. Bug #134161.
gtk/src/builder.hg | 54 ++++++++++++++++++++++++++++++++----------------
tests/builder/main.cc | 13 +++++++++--
2 files changed, 46 insertions(+), 21 deletions(-)
---
diff --git a/gtk/src/builder.hg b/gtk/src/builder.hg
index 42ab976..db042d6 100644
--- a/gtk/src/builder.hg
+++ b/gtk/src/builder.hg
@@ -19,6 +19,7 @@
#include <gtkmm/widget.h>
#include <giomm/resource.h> //For ResourceError, thrown by create_from_resource().
+#include <utility> //For std::forward()
_DEFS(gtkmm,gtk)
_PINCLUDE(glibmm/private/object_p.h)
@@ -428,7 +429,7 @@ public:
* @newin{2,12}
*
* @param name Name of object to get.
- * @return The object named @a name or <tt>0</tt> if it could not be found in the object tree.
+ * @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.
@@ -436,11 +437,11 @@ public:
* @newin{3,8}
*
* @param name Name of object to get.
- * @return The object named @a name or <tt>0</tt> if it could not be found in the object tree.
+ * @return The object named @a name or <tt>nullptr</tt> if it could not be found in the object tree.
*/
_WRAP_METHOD(Glib::RefPtr<const Glib::Object> get_object(const Glib::ustring& name) const,
gtk_builder_get_object, refreturn, constversion)
- /** Get a widget from the Builder file.
+ /** Gets a widget from the Builder file.
* For instance:
* @code
* Gtk::Grid* pGrid = nullptr;
@@ -456,7 +457,7 @@ public:
* container widget.
*
* @param name The name of the widget.
- * @retval widget A pointer to the widget, or <tt>0</tt> on failure.
+ * @retval widget A pointer to the widget, or <tt>nullptr</tt> on failure.
*/
template <class T_Widget> inline
void get_widget(const Glib::ustring& name, T_Widget*& widget)
@@ -480,31 +481,48 @@ public:
const_cast<Builder*>(this)->get_widget(name, widget);
}
- /** This provides a pointer to a widget whose details are specified in the GtkBuilder file, but which is
implemented
- * by your own derived class. Your class must have a constructor like so:
+ /** Gets a widget whose details are specified in the GtkBuilder file,
+ * but which is implemented by your own derived class.
+ *
+ * Your class must have a constructor like so:
+ * @code
+ * MyDerivedDialog::MyDerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refBuilder)
+ * : Gtk::Dialog(cobject) //Calls the base class constructor
+ * @endcode
+ * or, with additional parameters, for example:
* @code
- * DerivedDialog::DerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refBuilder)
+ * MyDerivedDialog::MyDerivedDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refBuilder,
+ * const Glib::ustring& msg, bool warning)
* : Gtk::Dialog(cobject) //Calls the base class constructor
* @endcode
*
* For instance:
* @code
- * Gtk::DerivedBox* pBox = nullptr;
- * refXml->get_widget_derived("mybox", pBox);
+ * MyDerivedDialog* pDialog1 = nullptr;
+ * MyDerivedDialog* pDialog2 = nullptr;
+ * refBuilder->get_widget_derived("mydialog1", pDialog1);
+ * refBuilder->get_widget_derived("mydialog2", pDialog2, "A storm is imminent!", true);
* @endcode
*
+ * @note
+ * If get_widget_derived() is called more than once for the same widget (the
+ * same @a name), only the first call will call the widget's constructor.
+ * The following calls will return a pointer to the widget instance that
+ * was constructed by the first call.
+ *
* @param name The name of the widget.
- * @retval widget A pointer to the widget, or <tt>0</tt> on failure.
+ * @param args Additional arguments to pass to the constructor of the derived class.
+ * @retval widget A pointer to the widget, or <tt>nullptr</tt> on failure.
*/
- template <class T_Widget> inline
- void get_widget_derived(const Glib::ustring& name, T_Widget*& widget)
+ template <typename T_Widget, typename... Args> inline
+ void get_widget_derived(const Glib::ustring& name, T_Widget*& widget, Args&&... args)
{
// Initialize output parameter:
widget = nullptr;
// Get the widget from the GtkBuilder file.
- typedef typename T_Widget::BaseObjectType cwidget_type;
- cwidget_type* pCWidget = (cwidget_type*)get_cwidget(name);
+ using cwidget_type = typename T_Widget::BaseObjectType;
+ auto pCWidget = (cwidget_type*)get_cwidget(name);
//The error was already reported by get_cwidget().
if(!pCWidget)
@@ -532,7 +550,7 @@ public:
//Set the output variable. We needed to do this because we can not template the return type.
Glib::RefPtr<Gtk::Builder> refThis(this);
refThis->reference(); //take a copy.
- widget = new T_Widget(pCWidget, refThis);
+ widget = new T_Widget(pCWidget, refThis, std::forward<Args>(args)...);
// Don't add reference to widget. That's done only in methods that return
// a Glib::RefPtr<Something>.
}
@@ -541,10 +559,10 @@ public:
/** See the non-const version.
* @newin{3,8}
*/
- template <class T_Widget> inline
- void get_widget_derived(const Glib::ustring& name, const T_Widget*& widget) const
+ template <typename T_Widget, typename... Args> inline
+ void get_widget_derived(const Glib::ustring& name, const T_Widget*& widget, Args&&... args) const
{
- const_cast<Builder*>(this)->get_widget_derived(name, widget);
+ const_cast<Builder*>(this)->get_widget_derived(name, widget, std::forward<Args>(args)...);
}
#m4 _CONVERSION(`GSList*',`std::vector<Glib::RefPtr<Glib::Object>
',`Glib::SListHandler<Glib::RefPtr<Glib::Object> >::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
diff --git a/tests/builder/main.cc b/tests/builder/main.cc
index f3c7f8a..02a8043 100644
--- a/tests/builder/main.cc
+++ b/tests/builder/main.cc
@@ -91,10 +91,17 @@ void* on_orphaned_button_deleted(void* /* data */)
class DerivedButton : public Gtk::Button
{
public:
- DerivedButton(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& /* refBuilder */)
+ DerivedButton(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& /* refBuilder */,
+ const Glib::ustring icon_name = Glib::ustring())
: Gtk::Button(cobject)
{
std::cout << "DerivedButton::ctor" << std::endl;
+
+ if (!icon_name.empty())
+ {
+ set_image_from_icon_name(icon_name);
+ property_always_show_image() = true;
+ }
}
virtual ~DerivedButton()
@@ -112,7 +119,7 @@ public:
std::cout << "MainWindow::ctor" << std::endl;
// Called twice just to see if two calls affect the ref count.
- refBuilder->get_widget_derived("derived_button", m_pDerivedButton);
+ refBuilder->get_widget_derived("derived_button", m_pDerivedButton, "face-smile");
refBuilder->get_widget_derived("derived_button", m_pDerivedButton);
refBuilder->get_widget("standard_button", m_pStandardButton);
refBuilder->get_widget("standard_button", m_pStandardButton);
@@ -171,7 +178,7 @@ int main(int argc, char* argv[])
<< " ref_count(orphaned_button)=" << orphaned_button->ref_count << std::endl;
const int result = app->run(*main_win);
-
+
std::cout << "After app->run(*main_win)" << std::endl
<< " ref_count(MainWindow)=" << window->ref_count << std::endl
<< " ref_count(DerivedButton)=" << derived_button->ref_count << std::endl
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]