[libgd] Introduce GdHeaderButton



commit a07a3a82e978b719d6a07329a56ea013329688a9
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Tue Feb 19 14:09:11 2013 -0500

    Introduce GdHeaderButton
    
    GdHeaderButton is a simple interface for buttons on header bars and main
    toolbars.
    The interface allows to get/set a label, a symbolic icon name, and
    control whether the label should use Pango markup.
    
    Three base classes are available, for simple, toggle and menu buttons,
    which will automatically set appropriate style classes according to the
    property values and the type of button.

 Makefile.am              |   10 +
 libgd.m4                 |    8 +
 libgd/gd-header-button.c |  465 ++++++++++++++++++++++++++++++++++++++++++++++
 libgd/gd-header-button.h |   56 ++++++
 libgd/gd.h               |    4 +
 5 files changed, 543 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4cfcbb2..a6f2533 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -113,6 +113,16 @@ test_header_bar_LDADD =                            \
        $(NULL)
 endif
 
+if LIBGD__HEADER_BUTTON
+header_button_sources =                                \
+       libgd/gd-header-button.c                \
+       libgd/gd-header-button.h                \
+       $(NULL)
+
+nodist_libgd_la_SOURCES += $(header_button_sources)
+EXTRA_DIST += $(header_button_sources)
+endif
+
 if LIBGD_MARGIN_CONTAINER
 margin_container_sources =                     \
        libgd/gd-margin-container.c             \
diff --git a/libgd.m4 b/libgd.m4
index 55ecb5f..9a1369b 100644
--- a/libgd.m4
+++ b/libgd.m4
@@ -81,15 +81,23 @@ AC_DEFUN([LIBGD_INIT], [
     # main-toolbar:
     AM_CONDITIONAL([LIBGD_MAIN_TOOLBAR],[_LIBGD_IF_OPTION_SET([main-toolbar],[true],[false])])
     _LIBGD_IF_OPTION_SET([main-toolbar],[
+        _LIBGD_SET_OPTION([_header-button])
         AC_DEFINE([LIBGD_MAIN_TOOLBAR], [1], [Description])
     ])
 
     # header-bar:
     AM_CONDITIONAL([LIBGD_HEADER_BAR],[_LIBGD_IF_OPTION_SET([header-bar],[true],[false])])
     _LIBGD_IF_OPTION_SET([header-bar],[
+        _LIBGD_SET_OPTION([_header-button])
         AC_DEFINE([LIBGD_HEADER_BAR], [1], [Description])
     ])
 
+    # _header-button:
+    AM_CONDITIONAL([LIBGD__HEADER_BUTTON],[_LIBGD_IF_OPTION_SET([_header-button],[true],[false])])
+    _LIBGD_IF_OPTION_SET([_header-button],[
+        AC_DEFINE([LIBGD__HEADER_BUTTON], [1], [Description])
+    ])
+
     # margin-container:
     AM_CONDITIONAL([LIBGD_MARGIN_CONTAINER],[_LIBGD_IF_OPTION_SET([margin-container],[true],[false])])
     _LIBGD_IF_OPTION_SET([margin-container],[
diff --git a/libgd/gd-header-button.c b/libgd/gd-header-button.c
new file mode 100644
index 0000000..8ed98df
--- /dev/null
+++ b/libgd/gd-header-button.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This program 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 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "gd-header-button.h"
+
+typedef GTypeInterface GdHeaderButtonIface;
+typedef GdHeaderButtonIface GdHeaderButtonInterface;
+#define GD_HEADER_BUTTON_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GD_TYPE_HEADER_BUTTON, 
GdHeaderButtonIface))
+
+G_DEFINE_INTERFACE (GdHeaderButton, gd_header_button, GTK_TYPE_BUTTON)
+
+#define P_(s) s
+enum {
+  PROP_0,
+  PROP_LABEL,
+  PROP_USE_MARKUP,
+  PROP_SYMBOLIC_ICON_NAME
+};
+
+static void
+gd_header_button_default_init (GdHeaderButtonIface *iface)
+{
+  GParamSpec *pspec;
+
+  /**
+   * GdHeaderButton:label:
+   *
+   * The label of the #GdHeaderButton object.
+   */
+  pspec = g_param_spec_string ("label",
+                               P_("Text label"),
+                               P_("Label displayed by the button"),
+                               NULL,
+                               G_PARAM_READWRITE |
+                               G_PARAM_STATIC_STRINGS);
+  g_object_interface_install_property (iface, pspec);
+
+  /**
+   * GdHeaderButton:use-markup:
+   *
+   * Whether the label of the #GdHeaderButton object should use markup.
+   */
+  pspec = g_param_spec_boolean ("use-markup",
+                                P_("Use markup"),
+                                P_("Whether the label should use markup"),
+                                FALSE,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_STRINGS);
+  g_object_interface_install_property (iface, pspec);
+
+  /**
+   * GdHeaderButton:symbolic-icon-name:
+   *
+   * The symbolic icon name of the #GdHeaderButton object.
+   */
+  pspec = g_param_spec_string ("symbolic-icon-name",
+                               P_("Symbolic icon name"),
+                               P_("The name of the symbolic icon displayed by the button"),
+                               NULL,
+                               G_PARAM_READWRITE |
+                               G_PARAM_STATIC_STRINGS);
+  g_object_interface_install_property (iface, pspec);
+}
+
+/**
+ * gd_header_button_get_label:
+ * @self:
+ *
+ * Returns: (transfer full):
+ */
+gchar *
+gd_header_button_get_label (GdHeaderButton *self)
+{
+  gchar *label;
+  g_object_get (self, "label", &label, NULL);
+
+  return label;
+}
+
+/**
+ * gd_header_button_set_label:
+ * @self:
+ * @label: (allow-none):
+ *
+ */
+void
+gd_header_button_set_label (GdHeaderButton *self,
+                            const gchar    *label)
+{
+  g_object_set (self, "label", label, NULL);
+}
+
+/**
+ * gd_header_button_get_symbolic_icon_name:
+ * @self:
+ *
+ * Returns: (transfer full):
+ */
+gchar *
+gd_header_button_get_symbolic_icon_name (GdHeaderButton *self)
+{
+  gchar *symbolic_icon_name;
+  g_object_get (self, "symbolic-icon-name", &symbolic_icon_name, NULL);
+
+  return symbolic_icon_name;
+}
+
+/**
+ * gd_header_button_set_symbolic_icon_name:
+ * @self:
+ * @symbolic_icon_name: (allow-none):
+ *
+ */
+void
+gd_header_button_set_symbolic_icon_name (GdHeaderButton *self,
+                                         const gchar    *symbolic_icon_name)
+{
+  if (symbolic_icon_name != NULL &&
+      !g_str_has_suffix (symbolic_icon_name, "-symbolic"))
+    {
+      g_warning ("gd_header_button_set_symbolic_icon_name was called with "
+                 "a non-symbolic name.");
+      return;
+    }
+
+  g_object_set (self, "symbolic-icon-name", symbolic_icon_name, NULL);
+}
+
+/**
+ * gd_header_button_get_use_markup:
+ * @self:
+ *
+ * Returns:
+ */
+gboolean
+gd_header_button_get_use_markup (GdHeaderButton *self)
+{
+  gboolean use_markup;
+
+  g_object_get (self, "use-markup", &use_markup, NULL);
+  return use_markup;
+}
+
+/**
+ * gd_header_button_set_use_markup:
+ * @self:
+ * @use_markup:
+ *
+ */
+void
+gd_header_button_set_use_markup (GdHeaderButton *self,
+                                 gboolean        use_markup)
+{
+  g_object_set (self, "use-markup", use_markup, NULL);
+}
+
+/* generic implementation for all private subclasses */
+typedef struct _GdHeaderButtonPrivate GdHeaderButtonPrivate;
+struct _GdHeaderButtonPrivate {
+  gchar *label;
+  gchar *symbolic_icon_name;
+
+  gboolean use_markup;
+};
+
+#define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, G_OBJECT_TYPE (inst), GdHeaderButtonPrivate)
+#define GET_PARENT_CLASS(inst) g_type_class_peek_parent (G_OBJECT_GET_CLASS (inst))
+
+static void
+rebuild_child (GdHeaderButton *self)
+{
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+  GtkStyleContext *context;
+  GtkWidget *button_child, *label;
+
+  button_child = gtk_bin_get_child (GTK_BIN (self));
+  if (button_child != NULL)
+    gtk_widget_destroy (button_child);
+
+  button_child = NULL;
+  context = gtk_widget_get_style_context (GTK_WIDGET (self));
+
+  if (priv->symbolic_icon_name != NULL)
+    {
+      button_child = gtk_image_new_from_icon_name (priv->symbolic_icon_name, GTK_ICON_SIZE_MENU);
+      if (priv->label != NULL)
+        gtk_widget_set_tooltip_text (GTK_WIDGET (self), priv->label);
+
+      gtk_style_context_remove_class (context, "text-button");
+      gtk_style_context_add_class (context, "image-button");
+    }
+  else if (priv->label != NULL)
+    {
+      label = gtk_label_new (priv->label);
+      gtk_label_set_use_markup (GTK_LABEL (label), priv->use_markup);
+
+      if (GTK_IS_MENU_BUTTON (self))
+        {
+          GtkWidget *arrow;
+
+          button_child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+          gtk_container_add (GTK_CONTAINER (button_child), label);
+
+          arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+          gtk_container_add (GTK_CONTAINER (button_child), arrow);
+        }
+      else
+        {
+          button_child = label;
+        }
+
+      gtk_style_context_remove_class (context, "image-button");
+      gtk_style_context_add_class (context, "text-button");
+    }
+
+  if (button_child)
+    {
+      gtk_widget_show_all (button_child);
+      gtk_container_add (GTK_CONTAINER (self), button_child);
+    }
+}
+
+static const gchar *
+button_get_label (GdHeaderButton *self)
+{
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+  return priv->label;
+}
+
+static void
+button_set_label (GdHeaderButton *self,
+                  const gchar    *label)
+{
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+
+  if (g_strcmp0 (priv->label, label) != 0)
+    {
+      g_free (priv->label);
+      priv->label = g_strdup (label);
+
+      rebuild_child (self);
+      g_object_notify (G_OBJECT (self), "label");
+    }
+}
+
+static void
+button_set_use_markup (GdHeaderButton *self,
+                       gboolean        use_markup)
+{
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+
+  if (priv->use_markup != use_markup)
+    {
+      priv->use_markup = use_markup;
+
+      rebuild_child (self);
+      g_object_notify (G_OBJECT (self), "use-markup");
+    }
+}
+
+static const gchar *
+button_get_symbolic_icon_name (GdHeaderButton *self)
+{
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+  return priv->symbolic_icon_name;
+}
+
+static void
+button_set_symbolic_icon_name (GdHeaderButton *self,
+                               const gchar    *symbolic_icon_name)
+{
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+
+  if (g_strcmp0 (priv->symbolic_icon_name, symbolic_icon_name) != 0)
+    {
+      g_free (priv->symbolic_icon_name);
+      priv->symbolic_icon_name = g_strdup (symbolic_icon_name);
+
+      rebuild_child (self);
+      g_object_notify (G_OBJECT (self), "symbolic-icon-name");
+    }
+}
+
+static void
+gd_header_button_generic_finalize (GObject *object)
+{
+  GdHeaderButton *self = GD_HEADER_BUTTON (object);
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+
+  g_free (priv->label);
+  g_free (priv->symbolic_icon_name);
+
+  G_OBJECT_CLASS (GET_PARENT_CLASS (object))->finalize (object);
+}
+
+static void
+gd_header_button_generic_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  GdHeaderButton *self = GD_HEADER_BUTTON (object);
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      button_set_label (self, g_value_get_string (value));
+      break;
+    case PROP_USE_MARKUP:
+      button_set_use_markup (self, g_value_get_boolean (value));
+      break;
+    case PROP_SYMBOLIC_ICON_NAME:
+      button_set_symbolic_icon_name (self, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gd_header_button_generic_get_property (GObject      *object,
+                                       guint         prop_id,
+                                       GValue       *value,
+                                       GParamSpec   *pspec)
+{
+  GdHeaderButton *self = GD_HEADER_BUTTON (object);
+  GdHeaderButtonPrivate *priv = GET_PRIVATE (self);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      g_value_set_string (value, priv->label);
+      break;
+    case PROP_USE_MARKUP:
+      g_value_set_boolean (value, priv->use_markup);
+      break;
+    case PROP_SYMBOLIC_ICON_NAME:
+      g_value_set_string (value, priv->symbolic_icon_name);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gd_header_button_generic_iface_init (GdHeaderButtonIface *iface)
+{
+}
+
+static void
+gd_header_button_generic_class_init (gpointer klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+  oclass->get_property = gd_header_button_generic_get_property;
+  oclass->set_property = gd_header_button_generic_set_property;
+  oclass->finalize = gd_header_button_generic_finalize;
+
+  g_object_class_override_property (oclass, PROP_LABEL, "label");
+  g_object_class_override_property (oclass, PROP_USE_MARKUP, "use-markup");
+  g_object_class_override_property (oclass, PROP_SYMBOLIC_ICON_NAME, "symbolic-icon-name");
+
+  g_type_class_add_private (klass, sizeof (GdHeaderButtonPrivate));
+}
+
+/* private subclasses */
+typedef GtkButton GdHeaderSimpleButton;
+typedef GtkButtonClass GdHeaderSimpleButtonClass;
+G_DEFINE_TYPE_WITH_CODE (GdHeaderSimpleButton, gd_header_simple_button, GTK_TYPE_BUTTON,
+                         G_IMPLEMENT_INTERFACE (GD_TYPE_HEADER_BUTTON, gd_header_button_generic_iface_init))
+
+static void
+gd_header_simple_button_class_init (GdHeaderSimpleButtonClass *klass)
+{
+  gd_header_button_generic_class_init (klass);
+}
+
+static void
+gd_header_simple_button_init (GdHeaderSimpleButton *self)
+{
+}
+
+typedef GtkToggleButton GdHeaderToggleButton;
+typedef GtkToggleButtonClass GdHeaderToggleButtonClass;
+G_DEFINE_TYPE_WITH_CODE (GdHeaderToggleButton, gd_header_toggle_button, GTK_TYPE_TOGGLE_BUTTON,
+                         G_IMPLEMENT_INTERFACE (GD_TYPE_HEADER_BUTTON, gd_header_button_generic_iface_init))
+
+static void
+gd_header_toggle_button_class_init (GdHeaderToggleButtonClass *klass)
+{
+  gd_header_button_generic_class_init (klass);
+}
+
+static void
+gd_header_toggle_button_init (GdHeaderToggleButton *self)
+{
+}
+
+typedef GtkMenuButton GdHeaderMenuButton;
+typedef GtkMenuButtonClass GdHeaderMenuButtonClass;
+G_DEFINE_TYPE_WITH_CODE (GdHeaderMenuButton, gd_header_menu_button, GTK_TYPE_MENU_BUTTON,
+                         G_IMPLEMENT_INTERFACE (GD_TYPE_HEADER_BUTTON, gd_header_button_generic_iface_init))
+
+static void
+gd_header_menu_button_class_init (GdHeaderMenuButtonClass *klass)
+{
+  gd_header_button_generic_class_init (klass);
+}
+
+static void
+gd_header_menu_button_init (GdHeaderMenuButton *self)
+{
+}
+
+/**
+ * gd_header_simple_button_new:
+ *
+ * Returns: (transfer none):
+ */
+GtkWidget *
+gd_header_simple_button_new (void)
+{
+  return g_object_new (GD_TYPE_HEADER_SIMPLE_BUTTON, NULL);
+}
+
+/**
+ * gd_header_toggle_button_new:
+ *
+ * Returns: (transfer none):
+ */
+GtkWidget *
+gd_header_toggle_button_new (void)
+{
+  return g_object_new (GD_TYPE_HEADER_TOGGLE_BUTTON, NULL);
+}
+
+/**
+ * gd_header_menu_button_new:
+ *
+ * Returns: (transfer none):
+ */
+GtkWidget *
+gd_header_menu_button_new (void)
+{
+  return g_object_new (GD_TYPE_HEADER_MENU_BUTTON, NULL);
+}
diff --git a/libgd/gd-header-button.h b/libgd/gd-header-button.h
new file mode 100644
index 0000000..cf7dea4
--- /dev/null
+++ b/libgd/gd-header-button.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This program 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 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __GD_HEADER_BUTTON_H__
+#define __GD_HEADER_BUTTON_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_HEADER_BUTTON    (gd_header_button_get_type ())
+#define GD_HEADER_BUTTON(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GD_TYPE_HEADER_BUTTON, GdHeaderButton))
+#define GD_IS_HEADER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GD_TYPE_HEADER_BUTTON))
+
+typedef struct _GdHeaderButton GdHeaderButton;
+
+GType   gd_header_button_get_type               (void) G_GNUC_CONST;
+
+void    gd_header_button_set_label              (GdHeaderButton *self,
+                                                 const gchar    *label);
+void    gd_header_button_set_symbolic_icon_name (GdHeaderButton *self,
+                                                 const gchar    *icon_name);
+gchar * gd_header_button_get_label              (GdHeaderButton *self);
+gchar * gd_header_button_get_symbolic_icon_name (GdHeaderButton *self);
+
+#define GD_TYPE_HEADER_SIMPLE_BUTTON (gd_header_simple_button_get_type ())
+GType       gd_header_simple_button_get_type (void) G_GNUC_CONST;
+GtkWidget * gd_header_simple_button_new      (void);
+
+#define GD_TYPE_HEADER_TOGGLE_BUTTON (gd_header_toggle_button_get_type ())
+GType       gd_header_toggle_button_get_type (void) G_GNUC_CONST;
+GtkWidget * gd_header_toggle_button_new      (void);
+
+#define GD_TYPE_HEADER_MENU_BUTTON   (gd_header_menu_button_get_type ())
+GType       gd_header_menu_button_get_type   (void) G_GNUC_CONST;
+GtkWidget * gd_header_menu_button_new        (void);
+
+G_END_DECLS
+
+#endif /* __GD_HEADER_BUTTON_H__ */
diff --git a/libgd/gd.h b/libgd/gd.h
index d1b7bd2..be015c0 100644
--- a/libgd/gd.h
+++ b/libgd/gd.h
@@ -56,6 +56,10 @@ G_BEGIN_DECLS
 # include <libgd/gd-header-bar.h>
 #endif
 
+#ifdef LIBGD__HEADER_BUTTON
+# include <libgd/gd-header-button.h>
+#endif
+
 #ifdef LIBGD_MARGIN_CONTAINER
 # include <libgd/gd-margin-container.h>
 #endif


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