[gtk+] Add a needs-attention child property to GtkStack



commit e59c28743ac2a399ecd22360aaf7cbc9c2c72812
Author: Paolo Borelli <pborelli gnome org>
Date:   Fri Aug 30 22:32:42 2013 +0200

    Add a needs-attention child property to GtkStack
    
    The child property is watched by the StackSwicther which in turns sets a
    needs-attention css class on the corresponding button, so that the theme
    can for instance show a throbbing animation if one of the hidden pages
    needs the user attention.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=707153

 gtk/gtkstack.c         |   31 ++++++++++++++++++++++++++++++-
 gtk/gtkstackswitcher.c |   41 +++++++++++++++++++++++++++++++++++++++++
 gtk/gtkstylecontext.h  |   11 +++++++++++
 tests/teststack.c      |    1 +
 4 files changed, 83 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index 01e943e..cee970a 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -82,7 +82,8 @@ enum
   CHILD_PROP_NAME,
   CHILD_PROP_TITLE,
   CHILD_PROP_ICON_NAME,
-  CHILD_PROP_POSITION
+  CHILD_PROP_POSITION,
+  CHILD_PROP_NEEDS_ATTENTION
 };
 
 typedef struct _GtkStackChildInfo GtkStackChildInfo;
@@ -92,6 +93,7 @@ struct _GtkStackChildInfo {
   gchar *name;
   gchar *title;
   gchar *icon_name;
+  gboolean needs_attention;
 };
 
 typedef struct {
@@ -416,6 +418,23 @@ gtk_stack_class_init (GtkStackClass *klass)
                       P_("The index of the child in the parent"),
                       -1, G_MAXINT, 0,
                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkStack:needs-attention:
+   *
+   * Sets a flag specifying whether the child requires the user attention.
+   * This is used by the #GtkStackSwitcher to change the appearance of the
+   * corresponding button when a page needs attention and it is not the
+   * current one.
+   *
+   * Since: 3.12
+   */
+  gtk_container_class_install_child_property (container_class, CHILD_PROP_NEEDS_ATTENTION,
+    g_param_spec_boolean ("needs-attention",
+                         P_("Needs Attention"),
+                         P_("Whether this page needs attention"),
+                         FALSE,
+                         GTK_PARAM_READWRITE));
 }
 
 /**
@@ -548,6 +567,10 @@ gtk_stack_get_child_property (GtkContainer *container,
       g_value_set_int (value, i);
       break;
 
+    case CHILD_PROP_NEEDS_ATTENTION:
+      g_value_set_boolean (value, info->needs_attention);
+      break;
+
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
       break;
@@ -615,6 +638,11 @@ gtk_stack_set_child_property (GtkContainer *container,
       reorder_child (stack, child, g_value_get_int (value));
       break;
 
+    case CHILD_PROP_NEEDS_ATTENTION:
+      info->needs_attention = g_value_get_boolean (value);
+      gtk_container_child_notify (container, child, "needs-attention");
+      break;
+
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
       break;
@@ -1001,6 +1029,7 @@ gtk_stack_add (GtkContainer *container,
   child_info->name = NULL;
   child_info->title = NULL;
   child_info->icon_name = NULL;
+  child_info->needs_attention = FALSE;
 
   priv->children = g_list_append (priv->children, child_info);
 
diff --git a/gtk/gtkstackswitcher.c b/gtk/gtkstackswitcher.c
index b8e008e..0aa6204 100644
--- a/gtk/gtkstackswitcher.c
+++ b/gtk/gtkstackswitcher.c
@@ -68,6 +68,7 @@ gtk_stack_switcher_init (GtkStackSwitcher *switcher)
   priv->buttons = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   context = gtk_widget_get_style_context (GTK_WIDGET (switcher));
+  gtk_style_context_add_class (context, "stack-switcher");
   gtk_style_context_add_class (context, GTK_STYLE_CLASS_LINKED);
 
   gtk_orientable_set_orientation (GTK_ORIENTABLE (switcher), GTK_ORIENTATION_HORIZONTAL);
@@ -139,6 +140,25 @@ rebuild_child (GtkWidget   *self,
 }
 
 static void
+update_needs_attention (GtkWidget *widget, GtkWidget *button, gpointer *data)
+{
+  GtkContainer *container;
+  gboolean needs_attention;
+  GtkStyleContext *context;
+
+  container = GTK_CONTAINER (data);
+  gtk_container_child_get (container, widget,
+                           "needs-attention", &needs_attention,
+                           NULL);
+
+  context = gtk_widget_get_style_context (button);
+  if (needs_attention && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+    gtk_style_context_add_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
+  else
+    gtk_style_context_remove_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
+}
+
+static void
 update_button (GtkStackSwitcher *self,
                GtkWidget        *widget,
                GtkWidget        *button)
@@ -165,6 +185,8 @@ update_button (GtkStackSwitcher *self,
 
   g_free (title);
   g_free (icon_name);
+
+  update_needs_attention (widget, button, priv->stack);
 }
 
 static void
@@ -202,6 +224,20 @@ on_position_updated (GtkWidget        *widget,
 }
 
 static void
+on_needs_attention_updated (GtkWidget        *widget,
+                            GParamSpec       *pspec,
+                            GtkStackSwitcher *self)
+{
+  GtkWidget *button;
+  GtkStackSwitcherPrivate *priv;
+
+  priv = gtk_stack_switcher_get_instance_private (self);
+
+  button = g_hash_table_lookup (priv->buttons, widget);
+  update_button (self, widget, button);
+}
+
+static void
 add_child (GtkStackSwitcher *self,
            GtkWidget        *widget)
 {
@@ -230,6 +266,7 @@ add_child (GtkStackSwitcher *self,
   g_signal_connect (widget, "child-notify::title", G_CALLBACK (on_title_icon_updated), self);
   g_signal_connect (widget, "child-notify::icon-name", G_CALLBACK (on_title_icon_updated), self);
   g_signal_connect (widget, "child-notify::position", G_CALLBACK (on_position_updated), self);
+  g_signal_connect (widget, "child-notify::needs-attention", G_CALLBACK (on_needs_attention_updated), self);
 
   g_hash_table_insert (priv->buttons, widget, button);
 }
@@ -269,6 +306,10 @@ on_child_changed (GtkWidget        *widget,
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
       priv->in_child_changed = FALSE;
     }
+
+  g_hash_table_foreach (priv->buttons,
+                        (GHFunc)update_needs_attention,
+                        priv->stack);
 }
 
 static void
diff --git a/gtk/gtkstylecontext.h b/gtk/gtkstylecontext.h
index 29f3ebf..ed5f40d 100644
--- a/gtk/gtkstylecontext.h
+++ b/gtk/gtkstylecontext.h
@@ -754,6 +754,17 @@ struct _GtkStyleContextClass
  */
 #define GTK_STYLE_CLASS_TITLEBAR "titlebar"
 
+/**
+ * GTK_STYLE_CLASS_NEEDS_ATTENTION:
+ *
+ * A CSS class used when an element needs the user attention,
+ * for instance a button in a stack switcher corresponding to
+ * a hidden page that changed state.
+*
+ * Since: 3.12
+ */
+#define GTK_STYLE_CLASS_NEEDS_ATTENTION "needs-attention"
+
 /* Predefined set of widget regions */
 
 /**
diff --git a/tests/teststack.c b/tests/teststack.c
index 3853af2..e684d23 100644
--- a/tests/teststack.c
+++ b/tests/teststack.c
@@ -144,6 +144,7 @@ main (gint argc,
   gtk_container_child_set (GTK_CONTAINER (stack), w2,
                           "name", "2",
                           "title", "2",
+                           "needs-attention", TRUE,
                           NULL);
 
 


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