[clutter/text-selection-color: 2/5] clutter-text: Add a selected-text-color



commit a3c109c8b31f2f74a0abbe75f6e91d525f9bd773
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Wed Mar 2 12:02:56 2011 -0500

    clutter-text: Add a selected-text-color
    
    http://bugzilla.clutter-project.org/show_bug.cgi?id=2595

 clutter/clutter-text.c |  185 ++++++++++++++++++++++++++++++++++++++++++------
 clutter/clutter-text.h |    5 ++
 2 files changed, 167 insertions(+), 23 deletions(-)
---
diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c
index f65e2f5..ce2139e 100644
--- a/clutter/clutter-text.c
+++ b/clutter/clutter-text.c
@@ -82,6 +82,7 @@ typedef struct _LayoutCache     LayoutCache;
 static const ClutterColor default_cursor_color    = {   0,   0,   0, 255 };
 static const ClutterColor default_selection_color = {   0,   0,   0, 255 };
 static const ClutterColor default_text_color      = {   0,   0,   0, 255 };
+static const ClutterColor default_selected_text_color = {   0,   0,   0, 255 };
 
 G_DEFINE_TYPE (ClutterText, clutter_text, CLUTTER_TYPE_ACTOR);
 
@@ -147,6 +148,7 @@ struct _ClutterTextPrivate
   guint preedit_set         : 1;
   guint is_default_font     : 1;
   guint has_focus           : 1;
+  guint selected_text_color_set : 1;
 
   /* current cursor position */
   gint position;
@@ -181,6 +183,8 @@ struct _ClutterTextPrivate
 
   ClutterColor selection_color;
 
+  ClutterColor selected_text_color;
+
   gint max_length;
 
   gunichar password_char;
@@ -221,6 +225,8 @@ enum
   PROP_PASSWORD_CHAR,
   PROP_MAX_LENGTH,
   PROP_SINGLE_LINE_MODE,
+  PROP_SELECTED_TEXT_COLOR,
+  PROP_SELECTED_TEXT_COLOR_SET,
 
   PROP_LAST
 };
@@ -1189,6 +1195,10 @@ clutter_text_set_property (GObject      *gobject,
       clutter_text_set_single_line_mode (self, g_value_get_boolean (value));
       break;
 
+    case PROP_SELECTED_TEXT_COLOR:
+      clutter_text_set_selected_text_color (self, clutter_value_get_color (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
     }
@@ -1304,6 +1314,14 @@ clutter_text_get_property (GObject    *gobject,
       g_value_set_boxed (value, priv->attrs);
       break;
 
+    case PROP_SELECTED_TEXT_COLOR:
+      clutter_value_set_color (value, &priv->selected_text_color);
+      break;
+
+    case PROP_SELECTED_TEXT_COLOR_SET:
+      g_value_set_boolean (value, priv->selected_text_color_set);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
     }
@@ -1358,15 +1376,16 @@ clutter_text_finalize (GObject *gobject)
   G_OBJECT_CLASS (clutter_text_parent_class)->finalize (gobject);
 }
 
+/* Draws the selected text, its background, and the cursor */
 static void
-cursor_paint (ClutterText *self)
+selection_paint (ClutterText *self)
 {
   ClutterTextPrivate *priv = self->priv;
   ClutterActor *actor = CLUTTER_ACTOR (self);
+  guint8 paint_opacity = clutter_actor_get_paint_opacity (actor);
 
   if (priv->editable && priv->cursor_visible)
     {
-      guint8 paint_opacity = clutter_actor_get_paint_opacity (actor);
       const ClutterColor *color;
       gint position;
 
@@ -1377,6 +1396,7 @@ cursor_paint (ClutterText *self)
 
       if (position == priv->selection_bound)
         {
+          /* No selection, just draw the cursor */
           if (priv->cursor_color_set)
             color = &priv->cursor_color;
           else
@@ -1396,6 +1416,9 @@ cursor_paint (ClutterText *self)
         }
       else
         {
+          /* Paint selection background first */
+          CoglPath *selection_path = cogl_path_new ();
+          CoglColor cogl_color = { 0, };
           PangoLayout *layout = clutter_text_get_layout (self);
           gchar *utf8 = clutter_text_get_display_text (self);
           gint lines;
@@ -1403,20 +1426,6 @@ cursor_paint (ClutterText *self)
           gint end_index;
           gint line_no;
 
-          if (priv->selection_color_set)
-            color = &priv->selection_color;
-          else if (priv->cursor_color_set)
-            color = &priv->cursor_color;
-          else
-            color = &priv->text_color;
-
-          cogl_set_source_color4ub (color->red,
-                                    color->green,
-                                    color->blue,
-                                    paint_opacity
-                                    * color->alpha
-                                    / 255);
-
           if (position == 0)
             start_index = 0;
           else
@@ -1475,15 +1484,54 @@ cursor_paint (ClutterText *self)
                   range_width = (ranges[i * 2 + 1] - ranges[i * 2])
                               / PANGO_SCALE;
 
-                  cogl_rectangle (range_x,
-                                  y,
-                                  range_x + range_width,
-                                  y + height);
+                  cogl_path_rectangle (selection_path,
+                                       range_x,
+                                       y,
+                                       range_x + range_width,
+                                       y + height);
                 }
 
               g_free (ranges);
             }
 
+          /* Paint selection background */
+          if (priv->selection_color_set)
+            color = &priv->selection_color;
+          else if (priv->cursor_color_set)
+            color = &priv->cursor_color;
+          else
+            color = &priv->text_color;
+
+          cogl_set_source_color4ub (color->red,
+                                    color->green,
+                                    color->blue,
+                                    paint_opacity * color->alpha / 255);
+
+          cogl_path_fill (selection_path);
+
+          /* Paint selected text */
+          cogl_clip_push_from_path (selection_path);
+          cogl_object_unref (selection_path);
+
+          if (priv->selected_text_color_set)
+            color = &priv->selected_text_color;
+          else if (priv->selection_color_set)
+            color = &priv->selection_color;
+          else if (priv->cursor_color_set)
+            color = &priv->cursor_color;
+          else
+            color = &priv->text_color;
+
+          cogl_color_init_from_4ub (&cogl_color,
+                                    color->red,
+                                    color->green,
+                                    color->blue,
+                                    paint_opacity * color->alpha / 255);
+
+          cogl_pango_render_layout (layout, priv->text_x, 0, &cogl_color, 0);
+
+          cogl_clip_pop ();
+
           g_free (utf8);
         }
     }
@@ -1904,9 +1952,6 @@ clutter_text_paint (ClutterActor *self)
 
   priv->text_x = text_x;
 
-  if (priv->has_focus)
-    cursor_paint (text);
-
   real_opacity = clutter_actor_get_paint_opacity (self)
                * priv->text_color.alpha
                / 255;
@@ -1920,6 +1965,9 @@ clutter_text_paint (ClutterActor *self)
                             real_opacity);
   cogl_pango_render_layout (layout, text_x, 0, &color, 0);
 
+  if (priv->has_focus)
+    selection_paint (text);
+
   if (clip_set)
     cogl_clip_pop ();
 
@@ -2957,6 +3005,36 @@ clutter_text_class_init (ClutterTextClass *klass)
   g_object_class_install_property (gobject_class, PROP_SINGLE_LINE_MODE, pspec);
 
   /**
+   * ClutterText:selected-text-color:
+   *
+   * The color of selected text.
+   *
+   * Since: 1.8
+   */
+  pspec = clutter_param_spec_color ("selected-text-color",
+                                    P_("Selected Text Color"),
+                                    P_("Selected Text Color"),
+                                    &default_selected_text_color,
+                                    CLUTTER_PARAM_READWRITE);
+  obj_props[PROP_SELECTED_TEXT_COLOR] = pspec;
+  g_object_class_install_property (gobject_class, PROP_SELECTED_TEXT_COLOR, pspec);
+
+  /**
+   * ClutterText:selected-text-color-set:
+   *
+   * Will be set to %TRUE if #ClutterText:selected-text-color has been set.
+   *
+   * Since: 1.8
+   */
+  pspec = g_param_spec_boolean ("selected-text-color-set",
+                                P_("Selected Text Color Set"),
+                                P_("Whether the selected text color has been set"),
+                                FALSE,
+                                CLUTTER_PARAM_READABLE);
+  obj_props[PROP_SELECTED_TEXT_COLOR_SET] = pspec;
+  g_object_class_install_property (gobject_class, PROP_SELECTED_TEXT_COLOR_SET, pspec);
+
+  /**
    * ClutterText::text-changed:
    * @self: the #ClutterText that emitted the signal
    *
@@ -3185,6 +3263,7 @@ clutter_text_init (ClutterText *self)
   priv->text_color = default_text_color;
   priv->cursor_color = default_cursor_color;
   priv->selection_color = default_selection_color;
+  priv->selected_text_color = default_selected_text_color;
 
   /* get the default font name from the context; we don't use
    * set_font_description() here because we are initializing
@@ -3207,6 +3286,7 @@ clutter_text_init (ClutterText *self)
 
   priv->selection_color_set = FALSE;
   priv->cursor_color_set = FALSE;
+  priv->selected_text_color_set = FALSE;
   priv->preedit_set = FALSE;
 
   priv->password_char = 0;
@@ -3803,6 +3883,65 @@ clutter_text_get_selection_color (ClutterText  *self,
 }
 
 /**
+ * clutter_text_set_selected_text_color:
+ * @self: a #ClutterText
+ * @color: the selected text color, or %NULL to unset it
+ *
+ * Sets the selected text color of a #ClutterText actor.
+ *
+ * If @color is %NULL, the selected text color will be the same as the
+ * selection color, which then falls back to cursor, and then text color.
+ *
+ * Since: 1.8
+ */
+void
+clutter_text_set_selected_text_color (ClutterText        *self,
+                                      const ClutterColor *color)
+{
+  ClutterTextPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_TEXT (self));
+
+  priv = self->priv;
+
+  if (color)
+    {
+      priv->selected_text_color = *color;
+      priv->selected_text_color_set = TRUE;
+    }
+  else
+    priv->selected_text_color_set = FALSE;
+
+  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SELECTED_TEXT_COLOR]);
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SELECTED_TEXT_COLOR_SET]);
+}
+
+/**
+ * clutter_text_get_selected_text_color:
+ * @self: a #ClutterText
+ * @color: (out caller-allocates): return location for a #ClutterColor
+ *
+ * Retrieves the color of selected text of a #ClutterText actor.
+ *
+ * Since: 1.8
+ */
+void
+clutter_text_get_selected_text_color (ClutterText  *self,
+                                      ClutterColor *color)
+{
+  ClutterTextPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_TEXT (self));
+  g_return_if_fail (color != NULL);
+
+  priv = self->priv;
+
+  *color = priv->selected_text_color;
+}
+
+/**
  * clutter_text_set_font_description:
  * @self: a #ClutterText
  * @font_desc: a #PangoFontDescription
diff --git a/clutter/clutter-text.h b/clutter/clutter-text.h
index 9edbbca..315bd46 100644
--- a/clutter/clutter-text.h
+++ b/clutter/clutter-text.h
@@ -200,6 +200,11 @@ void                  clutter_text_set_single_line_mode (ClutterText          *s
                                                          gboolean              single_line);
 gboolean              clutter_text_get_single_line_mode (ClutterText          *self);
 
+void                  clutter_text_set_selected_text_color  (ClutterText          *self,
+                                                             const ClutterColor   *color);
+void                  clutter_text_get_selected_text_color  (ClutterText          *self,
+                                                             ClutterColor         *color);
+
 gboolean              clutter_text_activate             (ClutterText          *self);
 gboolean              clutter_text_position_to_coords   (ClutterText          *self,
                                                          gint                  position,



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