[gnome-shell] dash: Move labels beside the app icon upon hovering



commit 2b9561fcbb549bea3c36e24b621ecdd710d1803d
Author: Seif Lotfy <seif lotfy collabora co uk>
Date:   Fri Dec 16 23:46:07 2011 +0100

    dash: Move labels beside the app icon upon hovering
    
    Instead of using an St.Tooltip to show the app's name under the icon,
    manually position a new St.Label ourselves. Make sure to keep the label
    hidden when right-clicking so it doesn't get in the way of the popup menu.
    Only one tooltip/label will be displayed at a time.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=666166

 data/theme/gnome-shell.css |   11 ++++++
 js/ui/appDisplay.js        |    4 ++-
 js/ui/dash.js              |   86 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 98 insertions(+), 3 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 5b8d3cd..4294e5e 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -645,6 +645,17 @@ StTooltip StLabel {
     font-size: 11pt;
 }
 
+.dash-label {
+    border-radius: 7px;
+    padding: 4px 12px;
+    background-color: rgba(0,0,0,0.5);
+    color: #ffffff;
+    font-size: 0.9em;
+    font-weight: bold;;
+    text-align: center;
+    -x-offset: 8px;
+}
+
 /* Apps */
 
 .icon-grid {
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 6931780..5d845e6 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -470,6 +470,7 @@ const AppWellIcon = new Lang.Class({
                                                 Lang.bind(this,
                                                           this._onStateChanged));
         this._onStateChanged();
+        this.isMenuUp = false;
     },
 
     _onDestroy: function() {
@@ -551,8 +552,8 @@ const AppWellIcon = new Lang.Class({
             this._menuManager.addMenu(this._menu);
         }
 
+        this.isMenuUp = true;
         this.actor.set_hover(true);
-        this.actor.show_tooltip();
         this._menu.popup();
 
         return false;
@@ -568,6 +569,7 @@ const AppWellIcon = new Lang.Class({
 
     _onMenuPoppedDown: function() {
         this.actor.sync_hover();
+        this.isMenuUp = false;
     },
 
     _onActivate: function (event) {
diff --git a/js/ui/dash.js b/js/ui/dash.js
index 97fa33a..e2ff6ee 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -6,6 +6,7 @@ const Lang = imports.lang;
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
+const Mainloop = imports.mainloop;
 
 const AppDisplay = imports.ui.appDisplay;
 const AppFavorites = imports.ui.appFavorites;
@@ -16,6 +17,9 @@ const Tweener = imports.ui.tweener;
 const Workspace = imports.ui.workspace;
 
 const DASH_ANIMATION_TIME = 0.2;
+const DASH_ITEM_LABEL_SHOW_TIME = 0.15;
+const DASH_ITEM_LABEL_HIDE_TIME = 0.1;
+const DASH_ITEM_HOVER_TIMEOUT = 300;
 
 // A container like StBin, but taking the child's scale into account
 // when requesting a size
@@ -32,6 +36,8 @@ const DashItemContainer = new Lang.Class({
                            Lang.bind(this, this._allocate));
         this.actor._delegate = this;
 
+        this._label = null;
+
         this.child = null;
         this._childScale = 1;
         this._childOpacity = 255;
@@ -84,6 +90,60 @@ const DashItemContainer = new Lang.Class({
         alloc.natural_size = natWidth * this.child.scale_y;
     },
 
+    showLabel: function() {
+        if (this._label == null)
+            return;
+
+        this._label.opacity = 0;
+        this._label.show();
+
+        let [stageX, stageY] = this.actor.get_transformed_position();
+
+        let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
+
+        let labelHeight = this._label.get_height();
+        let yOffset = Math.floor((itemHeight - labelHeight) / 2)
+
+        let y = stageY + yOffset;
+
+        let node = this._label.get_theme_node();
+        let xOffset = node.get_length('-x-offset');
+
+        let x;
+        if (St.Widget.get_default_direction () == St.TextDirection.RTL)
+            x = stageX - this._label.get_width() - xOffset;
+        else
+            x = stageX + this.actor.get_width() + xOffset;
+
+        this._label.set_position(x, y);
+        Tweener.addTween(this._label,
+                         { opacity: 255,
+                           time: DASH_ITEM_LABEL_SHOW_TIME,
+                           transition: 'easeOutQuad',
+                         });
+    },
+
+    setLabelText: function(text) {
+        if (this._label == null)
+            this._label = new St.Label({ style_class: 'dash-label'});
+
+        this._label.set_text(text);
+        Main.layoutManager.addChrome(this._label);
+        this._label.hide();
+    },
+
+    hideLabel: function () {
+        this._label.opacity = 255;
+        Tweener.addTween(this._label,
+                         { opacity: 0,
+                           time: DASH_ITEM_LABEL_HIDE_TIME,
+                           transition: 'easeOutQuad',
+                           onComplete: Lang.bind(this, function() {
+                               this._label.hide();
+                           })
+                         });
+    },
+
     setChild: function(actor) {
         if (this.child == actor)
             return;
@@ -238,6 +298,7 @@ const Dash = new Lang.Class({
         this._dragPlaceholderPos = -1;
         this._animatingPlaceholdersCount = 0;
         this._favRemoveTarget = null;
+        this._labelTimeoutId = 0;
 
         this._box = new St.BoxLayout({ name: 'dash',
                                        vertical: true,
@@ -371,16 +432,37 @@ const Dash = new Lang.Class({
                                    Lang.bind(this, function() {
                                        display.actor.opacity = 255;
                                    }));
-        display.actor.set_tooltip_text(app.get_name());
 
         let item = new DashItemContainer();
         item.setChild(display.actor);
 
-        display.icon.setIconSize(this.iconSize);
+        item.setLabelText(app.get_name());
 
+        display.icon.setIconSize(this.iconSize);
+        display.actor.connect('notify::hover',
+                               Lang.bind(this, function() {
+                                   this._onHover(item, display)
+                               }));
         return item;
     },
 
+    _onHover: function (item, display) {
+        if (display.actor.get_hover() && !display.isMenuUp) {
+            if (this._labelTimeoutId == 0) {
+                this._labelTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
+                    Lang.bind(this, function() {
+                        item.showLabel();
+                        return false;
+                    }));
+            }
+        } else {
+            if (this._labelTimeoutId > 0)
+                Mainloop.source_remove(this._labelTimeoutId);
+            this._labelTimeoutId = 0;
+            item.hideLabel();
+        }
+    },
+
     _adjustIconSize: function() {
         // For the icon size, we only consider children which are "proper"
         // icons (i.e. ignoring drag placeholders) and which are not



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