[gtk+] assistant: add ability to use header bar



commit ec10bbd6f59676a83f5bf6e0786ecf81925bbc39
Author: William Jon McCann <william jon mccann gmail com>
Date:   Tue Jan 28 21:27:26 2014 -0500

    assistant: add ability to use header bar
    
    https://bugzilla.gnome.org/show_bug.cgi?id=723212

 gtk/gtkassistant.c               |  202 +++++++++++++++++++++++++++++++++++++-
 gtk/resources/ui/gtkassistant.ui |    8 ++
 2 files changed, 209 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c
index 178efb6..62e530c 100644
--- a/gtk/gtkassistant.c
+++ b/gtk/gtkassistant.c
@@ -109,6 +109,9 @@ struct _GtkAssistantPrivate
   GtkWidget *sidebar_frame;
   GtkWidget *content;
   GtkWidget *action_area;
+  GtkWidget *headerbar;
+  gint use_header_bar;
+  gboolean constructed;
 
   GList     *pages;
   GSList    *visited_pages;
@@ -210,6 +213,11 @@ enum
   LAST_SIGNAL
 };
 
+enum {
+  PROP_0,
+  PROP_USE_HEADER_BAR
+};
+
 static guint signals [LAST_SIGNAL] = { 0 };
 
 
@@ -218,6 +226,156 @@ G_DEFINE_TYPE_WITH_CODE (GtkAssistant, gtk_assistant, GTK_TYPE_WINDOW,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                 gtk_assistant_buildable_interface_init))
 
+static void
+set_use_header_bar (GtkAssistant *assistant,
+                    gint          use_header_bar)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  if (use_header_bar == -1)
+    return;
+
+  priv->use_header_bar = use_header_bar;
+}
+
+static void
+gtk_assistant_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  GtkAssistant *assistant = GTK_ASSISTANT (object);
+
+  switch (prop_id)
+    {
+    case PROP_USE_HEADER_BAR:
+      set_use_header_bar (assistant, g_value_get_int (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_assistant_get_property (GObject      *object,
+                            guint         prop_id,
+                            GValue       *value,
+                            GParamSpec   *pspec)
+{
+  GtkAssistant *assistant = GTK_ASSISTANT (object);
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  switch (prop_id)
+    {
+    case PROP_USE_HEADER_BAR:
+      g_value_set_int (value, priv->use_header_bar);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+add_cb (GtkContainer *container,
+        GtkWidget    *widget,
+        GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  if (priv->use_header_bar)
+    g_warning ("Content added to the action area of a assistant using header bars");
+
+  gtk_widget_show (GTK_WIDGET (container));
+}
+
+static void
+apply_use_header_bar (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  gtk_widget_set_visible (priv->action_area, !priv->use_header_bar);
+  gtk_widget_set_visible (priv->headerbar, priv->use_header_bar);
+  if (!priv->use_header_bar)
+    gtk_window_set_titlebar (GTK_WINDOW (assistant), NULL);
+  if (priv->use_header_bar)
+    g_signal_connect (priv->action_area, "add", G_CALLBACK (add_cb), assistant);
+}
+
+static void
+add_to_header_bar (GtkAssistant *assistant,
+                   GtkWidget    *child)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
+
+  if (child == priv->back || child == priv->cancel)
+    gtk_header_bar_pack_start (GTK_HEADER_BAR (priv->headerbar), child);
+  else
+    gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->headerbar), child);
+}
+
+static void
+add_action_widgets (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  GList *children;
+  GList *l;
+
+  if (priv->use_header_bar)
+    {
+      children = gtk_container_get_children (GTK_CONTAINER (priv->action_area));
+      for (l = children; l != NULL; l = l->next)
+        {
+          GtkWidget *child = l->data;
+          gboolean has_default;
+
+          has_default = gtk_widget_has_default (child);
+
+          g_object_ref (child);
+          gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
+          add_to_header_bar (assistant, child);
+          g_object_unref (child);
+
+          if (has_default)
+            {
+              gtk_widget_grab_default (child);
+              gtk_style_context_add_class (gtk_widget_get_style_context (child), "suggested-action");
+            }
+        }
+      g_list_free (children);
+    }
+}
+
+static GObject *
+gtk_assistant_constructor (GType                  type,
+                           guint                  n_construct_properties,
+                           GObjectConstructParam *construct_params)
+{
+  GObject *object;
+  GtkAssistant *assistant;
+  GtkAssistantPrivate *priv;
+
+  object = G_OBJECT_CLASS (gtk_assistant_parent_class)->constructor (type,
+                                                                     n_construct_properties,
+                                                                     construct_params);
+
+  assistant = GTK_ASSISTANT (object);
+  priv = assistant->priv;
+
+  priv->constructed = TRUE;
+  if (priv->use_header_bar == -1)
+    priv->use_header_bar = FALSE;
+
+  add_action_widgets (assistant);
+  apply_use_header_bar (assistant);
+
+  return object;
+}
 
 static void
 gtk_assistant_class_init (GtkAssistantClass *class)
@@ -230,6 +388,10 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   widget_class    = (GtkWidgetClass *) class;
   container_class = (GtkContainerClass *) class;
 
+  gobject_class->constructor  = gtk_assistant_constructor;
+  gobject_class->set_property = gtk_assistant_set_property;
+  gobject_class->get_property = gtk_assistant_get_property;
+
   widget_class->destroy = gtk_assistant_destroy;
   widget_class->map = gtk_assistant_map;
   widget_class->unmap = gtk_assistant_unmap;
@@ -327,6 +489,25 @@ gtk_assistant_class_init (GtkAssistantClass *class)
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
 
+  /**
+   * GtkAssistant:use-header-bar:
+   *
+   * %TRUE if the assistant uses a #GtkHeaderBar for action buttons
+   * instead of the action-area.
+   *
+   * For technical reasons, this property is declared as an integer
+   * property, but you should only set it to %TRUE or %FALSE.
+   *
+   * Since: 3.12
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_USE_HEADER_BAR,
+                                   g_param_spec_int ("use-header-bar",
+                                                     P_("Use Header Bar"),
+                                                     P_("Use Header Bar for actions."),
+                                                     -1, 1, -1,
+                                                     GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
   gtk_widget_class_install_style_property (widget_class,
                                            g_param_spec_int ("header-padding",
                                                              P_("Header Padding"),
@@ -433,6 +614,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
                                               "/org/gtk/libgtk/ui/gtkassistant.ui");
 
   gtk_widget_class_bind_template_child_internal_private (widget_class, GtkAssistant, action_area);
+  gtk_widget_class_bind_template_child_internal_private (widget_class, GtkAssistant, headerbar);
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, content);
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, cancel);
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, forward);
@@ -1007,6 +1189,10 @@ gtk_assistant_init (GtkAssistant *assistant)
   priv->forward_function_data = assistant;
   priv->forward_data_destroy = NULL;
 
+  g_object_get (gtk_widget_get_settings (GTK_WIDGET (assistant)),
+                "gtk-dialogs-use-header", &priv->use_header_bar,
+                NULL);
+
   gtk_widget_init_template (GTK_WIDGET (assistant));
 
   if (alternative_button_order (assistant))
@@ -1691,6 +1877,17 @@ gtk_assistant_set_forward_page_func (GtkAssistant         *assistant,
     update_buttons_state (assistant);
 }
 
+static void
+add_to_action_area (GtkAssistant *assistant,
+                    GtkWidget    *child)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  gtk_widget_set_valign (child, GTK_ALIGN_BASELINE);
+
+  gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
+}
+
 /**
  * gtk_assistant_add_action_widget:
  * @assistant: a #GtkAssistant
@@ -1719,7 +1916,10 @@ gtk_assistant_add_action_widget (GtkAssistant *assistant,
         update_actions_size (assistant);
     }
 
-  gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
+  if (priv->constructed && priv->use_header_bar)
+    add_to_header_bar (assistant, child);
+  else
+    add_to_action_area (assistant, child);
 }
 
 /**
diff --git a/gtk/resources/ui/gtkassistant.ui b/gtk/resources/ui/gtkassistant.ui
index 050050c..983cd83 100644
--- a/gtk/resources/ui/gtkassistant.ui
+++ b/gtk/resources/ui/gtkassistant.ui
@@ -3,10 +3,18 @@
   <!-- interface-requires gtk+ 3.10 -->
   <template class="GtkAssistant" parent="GtkWindow">
     <property name="can_focus">False</property>
+    <child type="titlebar">
+      <object class="GtkHeaderBar" id="headerbar">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="show-close-button">False</property>
+      </object>
+    </child>
     <child>
       <object class="GtkBox" id="main_box">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="border_width">0</property>
         <property name="spacing">12</property>
         <child>
           <object class="GtkFrame" id="sidebar_frame">


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