[gnome-shell] Add StIconColors object, compute in StThemeNode



commit 04da2a61dbee891b1db63e4f71e3da2af9b37a48
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sun Oct 31 22:06:48 2010 -0400

    Add StIconColors object, compute in StThemeNode
    
    A new StIconColors object is used to efficiently track the colors
    we need to colorize a symbolic icon.
    st_theme_node_compute_icon_colors() is added to compute the
    StIconColors for a theme node. (Refcounting of StIconColors means
    that we'll typically share the colors object of the parent node.)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=633865

 src/Makefile-st.am             |    2 +
 src/st/st-icon-colors.c        |  108 +++++++++++++++++++++++++++++++++++
 src/st/st-icon-colors.h        |   41 +++++++++++++
 src/st/st-theme-node-private.h |    1 +
 src/st/st-theme-node.c         |  122 ++++++++++++++++++++++++++++++++++++++++
 src/st/st-theme-node.h         |    3 +
 6 files changed, 277 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile-st.am b/src/Makefile-st.am
index b0272ae..40d27c5 100644
--- a/src/Makefile-st.am
+++ b/src/Makefile-st.am
@@ -80,6 +80,7 @@ st_source_h =					\
 	st/st-focus-manager.h			\
 	st/st-group.h				\
 	st/st-icon.h				\
+	st/st-icon-colors.h			\
 	st/st-im-text.h				\
 	st/st-label.h				\
 	st/st-overflow-box.h			\
@@ -130,6 +131,7 @@ st_source_c =					\
 	st/st-focus-manager.c			\
 	st/st-group.c				\
 	st/st-icon.c				\
+	st/st-icon-colors.c			\
 	st/st-im-text.c				\
 	st/st-label.c				\
 	st/st-overflow-box.c			\
diff --git a/src/st/st-icon-colors.c b/src/st/st-icon-colors.c
new file mode 100644
index 0000000..0655246
--- /dev/null
+++ b/src/st/st-icon-colors.c
@@ -0,0 +1,108 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * st-icon-colors.c: Colors for colorizing a symbolic icon
+ *
+ * Copyright 2010 Red Hat, Inc.
+ * Copyright 2010 Florian Müllner
+ *
+ * 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.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "st-icon-colors.h"
+
+/**
+ * st_icon_colors_new:
+ *
+ * Creates a new #StIconColors. All colors are initialized to transparent black.
+ *
+ * Return value: a newly created #StIconColors. Free with st_icon_colors_unref()
+ */
+StIconColors *
+st_icon_colors_new (void)
+{
+  StIconColors *colors;
+
+  colors = g_slice_new0 (StIconColors);
+  colors->ref_count = 1;
+
+  return colors;
+}
+
+/**
+ * st_icon_colors_ref:
+ * @colors: a #StIconColors
+ *
+ * Atomically increments the reference count of @colors by one.
+ *
+ * Returns: the passed in #StIconColors.
+ */
+StIconColors *
+st_icon_colors_ref (StIconColors *colors)
+{
+  g_return_val_if_fail (colors != NULL, NULL);
+  g_return_val_if_fail (colors->ref_count > 0, colors);
+
+  g_atomic_int_add ((volatile int *)&colors->ref_count, 1);
+  return colors;
+}
+
+/**
+ * st_icon_colors_unref:
+ * @colors: a #StIconColors
+ *
+ * Atomically decrements the reference count of @colors by one.
+ * If the reference count drops to 0, all memory allocated by the
+ * #StIconColors is released.
+ */
+void
+st_icon_colors_unref (StIconColors *colors)
+{
+  g_return_if_fail (colors != NULL);
+  g_return_if_fail (colors->ref_count > 0);
+
+  if (g_atomic_int_exchange_and_add ((volatile int *)&colors->ref_count, -1) - 1 == 0)
+    g_slice_free (StIconColors, colors);
+}
+
+/**
+ * st_icon_colors_copy:
+ * @colors: a #StIconColors
+ *
+ * Creates a new StIconColors structure that is a copy of the passed
+ * in @colors. You would use this function instead of st_icon_colors_ref()
+ * if you were planning to change colors in the result.
+ *
+ * Returns: a newly created #StIconColors.
+ */
+StIconColors *
+st_icon_colors_copy (StIconColors *colors)
+{
+  StIconColors *copy;
+
+  g_return_val_if_fail (colors != NULL, NULL);
+
+  copy = st_icon_colors_new ();
+
+  copy->foreground = colors->foreground;
+  copy->warning = colors->warning;
+  copy->error = colors->error;
+  copy->success = colors->success;
+
+  return copy;
+}
+
+G_DEFINE_BOXED_TYPE (StIconColors,
+                     st_icon_colors,
+                     st_icon_colors_ref,
+                     st_icon_colors_unref)
diff --git a/src/st/st-icon-colors.h b/src/st/st-icon-colors.h
new file mode 100644
index 0000000..b582308
--- /dev/null
+++ b/src/st/st-icon-colors.h
@@ -0,0 +1,41 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+#ifndef __ST_ICON_COLORS__
+#define __ST_ICON_COLORS__
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define ST_TYPE_ICON_COLORS (st_icon_colors_get_type ())
+
+typedef struct _StIconColors StIconColors;
+
+/**
+ * StIconColors:
+ * @foreground: foreground color
+ * @warning: color indicating a warning state
+ * @error: color indicating an error state
+ * @success: color indicating a successful operation
+ *
+ * The #StIconColors structure encapsulates colors for colorizing a symbolic
+ * icon.
+ */
+struct _StIconColors {
+  volatile guint ref_count;
+
+  ClutterColor foreground;
+  ClutterColor warning;
+  ClutterColor error;
+  ClutterColor success;
+};
+
+GType     st_icon_colors_get_type (void) G_GNUC_CONST;
+
+StIconColors *st_icon_colors_new   (void);
+StIconColors *st_icon_colors_ref   (StIconColors *colors);
+void          st_icon_colors_unref (StIconColors *colors);
+StIconColors *st_icon_colors_copy  (StIconColors *colors);
+
+G_END_DECLS
+
+#endif /* __ST_ICON_COLORS__ */
diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h
index 1ced764..7673755 100644
--- a/src/st/st-theme-node-private.h
+++ b/src/st/st-theme-node-private.h
@@ -67,6 +67,7 @@ struct _StThemeNode {
   StBorderImage *border_image;
   StShadow *shadow;
   StShadow *text_shadow;
+  StIconColors *icon_colors;
 
   GType element_type;
   char *element_id;
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index d325be0..a9d1c2f 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -36,6 +36,9 @@ static void st_theme_node_finalize           (GObject                 *object);
 
 static const ClutterColor BLACK_COLOR = { 0, 0, 0, 0xff };
 static const ClutterColor TRANSPARENT_COLOR = { 0, 0, 0, 0 };
+static const ClutterColor DEFAULT_SUCCESS_COLOR = { 0x4e, 0x9a, 0x06, 0xff };
+static const ClutterColor DEFAULT_WARNING_COLOR = { 0xf5, 0x79, 0x3e, 0xff };
+static const ClutterColor DEFAULT_ERROR_COLOR = { 0xcc, 0x00, 0x00, 0xff };
 
 extern gfloat st_slow_down_factor;
 
@@ -2748,6 +2751,125 @@ st_theme_node_get_text_shadow (StThemeNode *node)
   return result;
 }
 
+/**
+ * st_theme_node_get_icon_colors:
+ * @node: a #StThemeNode
+ *
+ * Gets the colors that should be used for colorizing symbolic icons according
+ * the style of this node.
+ *
+ * Return value: (transfer none): the icon colors to use for this theme node
+ */
+StIconColors *
+st_theme_node_get_icon_colors (StThemeNode *node)
+{
+  /* Foreground here will always be the same as st_theme_node_get_foreground_color(),
+   * but there's a loss of symmetry and little efficiency win if we try to exploit
+   * that. */
+
+  enum {
+    FOREGROUND = 1 << 0,
+    WARNING = 1 << 1,
+    ERROR = 1 << 2,
+    SUCCESS = 1 << 3
+  };
+
+  gboolean shared_with_parent;
+  int i;
+  ClutterColor color = { 0, };
+
+  guint still_need = FOREGROUND | WARNING | ERROR | SUCCESS;
+
+  g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
+
+  if (node->icon_colors)
+    return node->icon_colors;
+
+  if (node->parent_node)
+    {
+      node->icon_colors = st_theme_node_get_icon_colors (node->parent_node);
+      shared_with_parent = TRUE;
+    }
+  else
+    {
+      node->icon_colors = st_icon_colors_new ();
+      node->icon_colors->foreground = BLACK_COLOR;
+      node->icon_colors->warning = DEFAULT_WARNING_COLOR;
+      node->icon_colors->error = DEFAULT_ERROR_COLOR;
+      node->icon_colors->success = DEFAULT_SUCCESS_COLOR;
+      shared_with_parent = FALSE;
+    }
+
+  ensure_properties (node);
+
+  for (i = node->n_properties - 1; i >= 0 && still_need != 0; i--)
+    {
+      CRDeclaration *decl = node->properties[i];
+      GetFromTermResult result = VALUE_NOT_FOUND;
+      guint found = 0;
+
+      if ((still_need & FOREGROUND) != 0 &&
+          strcmp (decl->property->stryng->str, "color") == 0)
+        {
+          found = FOREGROUND;
+          result = get_color_from_term (node, decl->value, &color);
+        }
+      else if ((still_need & WARNING) != 0 &&
+               strcmp (decl->property->stryng->str, "warning-color") == 0)
+        {
+          found = WARNING;
+          result = get_color_from_term (node, decl->value, &color);
+        }
+      else if ((still_need & ERROR) != 0 &&
+               strcmp (decl->property->stryng->str, "error-color") == 0)
+        {
+          found = ERROR;
+          result = get_color_from_term (node, decl->value, &color);
+        }
+      else if ((still_need & SUCCESS) != 0 &&
+               strcmp (decl->property->stryng->str, "success-color") == 0)
+        {
+          found = SUCCESS;
+          result = get_color_from_term (node, decl->value, &color);
+        }
+
+      if (result == VALUE_INHERIT)
+        {
+          still_need &= ~found;
+        }
+      else if (result == VALUE_FOUND)
+        {
+          still_need &= ~found;
+          if (shared_with_parent)
+            {
+              node->icon_colors = st_icon_colors_copy (node->icon_colors);
+              shared_with_parent = FALSE;
+            }
+
+          switch (found)
+            {
+            case FOREGROUND:
+              node->icon_colors->foreground = color;
+              break;
+            case WARNING:
+              node->icon_colors->warning = color;
+              break;
+            case ERROR:
+              node->icon_colors->error = color;
+              break;
+            case SUCCESS:
+              node->icon_colors->success = color;
+              break;
+            }
+        }
+    }
+
+  if (shared_with_parent)
+    st_icon_colors_ref (node->icon_colors);
+
+  return node->icon_colors;
+}
+
 static float
 get_width_inc (StThemeNode *node)
 {
diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h
index aeb80d9..13e0bf6 100644
--- a/src/st/st-theme-node.h
+++ b/src/st/st-theme-node.h
@@ -25,6 +25,7 @@
 
 #include <clutter/clutter.h>
 #include "st-border-image.h"
+#include "st-icon-colors.h"
 #include "st-shadow.h"
 
 G_BEGIN_DECLS
@@ -197,6 +198,8 @@ StBorderImage *st_theme_node_get_border_image (StThemeNode *node);
 StShadow      *st_theme_node_get_shadow       (StThemeNode *node);
 StShadow      *st_theme_node_get_text_shadow  (StThemeNode *node);
 
+StIconColors  *st_theme_node_get_icon_colors  (StThemeNode *node);
+
 /* Helpers for get_preferred_width()/get_preferred_height() ClutterActor vfuncs */
 void st_theme_node_adjust_for_height       (StThemeNode  *node,
                                             float        *for_height);



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