[gnome-shell] Avoid ellipsizing app names; Draw glow around running



commit 96cf9c739e3836e05977a24179cc2dd65f304765
Author: Colin Walters <walters verbum org>
Date:   Sat Jul 4 17:28:34 2009 -0400

    Avoid ellipsizing app names; Draw glow around running
    
    Corresponding with the design, if an application is in a running
    state (has > 0 windows open), draw a glow behind the name.
    
    To make the display look a bit nicer, set the width of each item
    to be equal to the longest word among all the items.

 js/ui/appDisplay.js |   79 +++++++++++++++++++++++++++++++++++++++++++--------
 src/shell-global.c  |   74 +++++++++++++++++++++++++++++++++++++++++++++++
 src/shell-global.h  |    8 +++++
 3 files changed, 149 insertions(+), 12 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 2eaf51b..a939a83 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -19,6 +19,10 @@ const Workspaces = imports.ui.workspaces;
 const ENTERED_MENU_COLOR = new Clutter.Color();
 ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
 
+const GLOW_COLOR = new Clutter.Color();
+GLOW_COLOR.from_pixel(0x4f6ba4ff);
+const GLOW_PADDING = 5;
+
 const APP_ICON_SIZE = 48;
 const APP_PADDING = 18;
 
@@ -464,7 +468,6 @@ WellDisplayItem.prototype = {
                                    border: 0,
                                    padding: 1,
                                    border_color: GenericDisplay.ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR,
-                                   width: APP_ICON_SIZE + APP_PADDING,
                                    reactive: true });
         this.actor.connect('enter-event', Lang.bind(this,
             function(o, event) {
@@ -494,25 +497,46 @@ WellDisplayItem.prototype = {
 
         this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
 
-        let nameBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
+        let nameBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
                                     x_align: Big.BoxAlignment.CENTER });
+        this._nameBox = nameBox;
+
+        this._wordWidth = Shell.Global.get().get_max_word_width(this.actor, appInfo.get_name(),
+                                                                "Sans 12px");
         this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
                                         font_name: "Sans 12px",
-                                        ellipsize: Pango.EllipsizeMode.END,
                                         line_alignment: Pango.Alignment.CENTER,
                                         line_wrap: true,
-                                        line_wrap_mode: Pango.WrapMode.WORD_CHAR,
+                                        line_wrap_mode: Pango.WrapMode.WORD,
                                         text: appInfo.get_name() });
-        nameBox.append(this._name, Big.BoxPackFlags.EXPAND);
+        nameBox.append(this._name, Big.BoxPackFlags.NONE);
         if (this._windows.length > 0) {
-            let runningBox = new Big.Box({ /* border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
-                                           border: 1,
-                                           padding: 1 */ });
-            runningBox.append(nameBox, Big.BoxPackFlags.EXPAND);
-            this.actor.append(runningBox, Big.BoxPackFlags.NONE);
-        } else {
-            this.actor.append(nameBox, Big.BoxPackFlags.NONE);
+            let glow = new Shell.DrawingArea({});
+            glow.connect('redraw', Lang.bind(this, function (e, tex) {
+                Shell.Global.clutter_cairo_texture_draw_glow(tex,
+                                                             GLOW_COLOR.red / 255,
+                                                             GLOW_COLOR.green / 255,
+                                                             GLOW_COLOR.blue / 255,
+                                                             GLOW_COLOR.alpha / 255);
+            }));
+            this._name.connect('notify::allocation', Lang.bind(this, function (n, alloc) {
+                let x = this._name.x;
+                let y = this._name.y;
+                let width = this._name.width;
+                let height = this._name.height;
+                // If we're smaller than the allocated box width, pad out the glow a bit
+                // to make it more visible
+                if ((width + GLOW_PADDING * 2) < this._nameBox.width) {
+                    width += GLOW_PADDING * 2;
+                    x -= GLOW_PADDING;
+                }
+                glow.set_size(width, height);
+                glow.set_position(x, y);
+            }));
+            nameBox.add_actor(glow);
+            glow.lower(this._name);
         }
+        this.actor.append(nameBox, Big.BoxPackFlags.NONE);
     },
 
     _handleActivate: function () {
@@ -560,6 +584,14 @@ WellDisplayItem.prototype = {
     // that represents the item as it is being dragged.
     getDragActorSource: function() {
         return this._icon;
+    },
+
+    getWordWidth: function() {
+        return this._wordWidth;
+    },
+
+    setWidth: function(width) {
+        this._nameBox.width = width + GLOW_PADDING * 2;
     }
 };
 
@@ -587,14 +619,32 @@ WellArea.prototype = {
             v.destroy();
         }));
 
+        this._maxWordWidth = 0;
+        let displays = []
         for (let i = 0; i < infos.length; i++) {
             let app = infos[i];
             let display = new WellDisplayItem(app, this.isFavorite);
+            displays.push(display);
+            let width = display.getWordWidth();
+            if (width > this._maxWordWidth)
+                this._maxWordWidth = width;
             display.connect('activated', Lang.bind(this, function (display) {
                 this.emit('activated', display);
             }));
             this.actor.add_actor(display.actor);
         }
+        this._displays = displays;
+    },
+
+    getWordWidth: function() {
+        return this._maxWordWidth;
+    },
+
+    setItemWidth: function(width) {
+        for (let i = 0; i < this._displays.length; i++) {
+            let display = this._displays[i];
+            display.setWidth(width);
+        }
     },
 
     // Draggable target interface
@@ -710,6 +760,11 @@ AppWell.prototype = {
         let running = this._lookupApps(runningIds);
         this._favoritesArea.redisplay(favorites);
         this._runningArea.redisplay(running);
+        let maxWidth = this._favoritesArea.getWordWidth();
+        if (this._runningArea.getWordWidth() > maxWidth)
+            maxWidth = this._runningArea.getWordWidth();
+        this._favoritesArea.setItemWidth(maxWidth);
+        this._runningArea.setItemWidth(maxWidth);
         // If it's empty, we hide it so the top border doesn't show up
         if (running.length == 0)
           this._runningBox.hide();
diff --git a/src/shell-global.c b/src/shell-global.c
index 8429cd1..0c70e30 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -1061,6 +1061,46 @@ shell_global_create_root_pixmap_actor (ShellGlobal *global)
   return clutter_clone_new (global->root_pixmap);
 }
 
+/**
+ * shell_global_get_max_word_width:
+ * @global:
+ * @ref: Actor to use for font information
+ * @text: Text to analyze
+ * @font: Given font size to use
+ *
+ * Compute the largest pixel size among the individual words in text, when
+ * rendered in the given font.
+ */
+guint
+shell_global_get_max_word_width (ShellGlobal *global, ClutterActor *ref, const char *text, const char *font)
+{
+  PangoLayout *layout;
+  PangoFontDescription *fontdesc;
+  char **components;
+  char **iter;
+  gint max;
+
+  layout = clutter_actor_create_pango_layout (ref, NULL);
+  fontdesc = pango_font_description_from_string (font);
+  pango_layout_set_font_description (layout, fontdesc);
+  pango_font_description_free (fontdesc);
+
+  max = 0;
+  components = g_strsplit (text, " ", 0);
+  for (iter = components; *iter; iter++)
+    {
+      char *component = *iter;
+      gint width, height;
+      pango_layout_set_text (layout, component, -1);
+      pango_layout_get_pixel_size (layout, &width, &height);
+      if (width > max)
+        max = width;
+    }
+  g_object_unref (layout);
+  g_strfreev (components);
+  return (guint)max;
+}
+
 void
 shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,
                                                int                  hour,
@@ -1107,3 +1147,37 @@ shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,
 
   cairo_destroy (cr);
 }
+
+
+void
+shell_global_clutter_cairo_texture_draw_glow (ClutterCairoTexture *texture,
+                                              double red,
+                                              double green,
+                                              double blue,
+                                              double alpha)
+{
+  cairo_t *cr;
+  guint width, height;
+  cairo_pattern_t *gradient;
+
+  clutter_cairo_texture_get_surface_size (texture, &width, &height);
+
+  clutter_cairo_texture_clear (texture);
+  cr = clutter_cairo_texture_create (texture);
+
+  cairo_save (cr);
+  cairo_translate (cr, width / 2.0, height / 2.0);
+  cairo_scale (cr, width / 2.0, height / 2.0);
+
+  gradient = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
+  cairo_pattern_add_color_stop_rgba (gradient, 0.0, red, green, blue, alpha);
+  cairo_pattern_add_color_stop_rgba (gradient, 0.7, red, green, blue, alpha * 0.7);
+  cairo_pattern_add_color_stop_rgba (gradient, 1.0, red, green, blue, alpha * 0.3);
+  cairo_set_source (cr, gradient);
+
+  cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2.0 * M_PI);
+  cairo_fill (cr);
+  cairo_restore (cr);
+  cairo_pattern_destroy (gradient);
+  cairo_destroy (cr);
+}
diff --git a/src/shell-global.h b/src/shell-global.h
index 813d42a..52cd9ef 100644
--- a/src/shell-global.h
+++ b/src/shell-global.h
@@ -81,10 +81,18 @@ void shell_global_format_time_relative_pretty (ShellGlobal *global, guint delta,
 
 ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);
 
+guint shell_global_get_max_word_width (ShellGlobal *global, ClutterActor *ref, const char *text, const char *font);
+
 void shell_global_clutter_cairo_texture_draw_clock (ClutterCairoTexture *texture,
 						    int                  hour,
 						    int                  minute);
 
+void shell_global_clutter_cairo_texture_draw_glow (ClutterCairoTexture *texture,
+                                                   double red,
+                                                   double blue,
+                                                   double green,
+                                                   double alpha);
+
 G_END_DECLS
 
 #endif /* __SHELL_GLOBAL_H__ */



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