[gnome-shell] Add "InfoBar" and undo capability to overview



commit 0b2eeccd4b1e9003110f52cf7a871aed978a82af
Author: Maxim Ermilov <zaspire rambler ru>
Date:   Tue Feb 9 01:50:50 2010 +0300

    Add "InfoBar" and undo capability to overview
    
    It allow to show some information to user and Undo his actions.
    https://bugzilla.gnome.org/show_bug.cgi?id=608933

 data/theme/gnome-shell.css |   21 ++++++++
 js/ui/appFavorites.js      |   40 +++++++++++++--
 js/ui/overview.js          |  118 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 174 insertions(+), 5 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 65f0f38..4cd6209 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -133,6 +133,27 @@ StTooltip {
 
 /* Overlay */
 
+.info-bar {
+    border-radius: 3px;
+    border: 1px solid #5c5c5c;
+    background: #1e1e1e;
+    color: #cccccc;
+    font-size: 14px;
+    height: 26px;
+}
+
+.info-bar-panel {
+    padding: 11px;
+}
+
+.info-bar-link-button {
+    text-decoration: underline;
+}
+
+.info-bar-link-button:hover {
+    color: #ffffff;
+}
+
 .workspaces {
     color: white;
 }
diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js
index 3f32c0b..74a6596 100644
--- a/js/ui/appFavorites.js
+++ b/js/ui/appFavorites.js
@@ -3,7 +3,10 @@
 const Shell = imports.gi.Shell;
 const Lang = imports.lang;
 const Signals = imports.signals;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
 
+const Main = imports.ui.main;
 
 function AppFavorites() {
     this._init();
@@ -61,23 +64,50 @@ AppFavorites.prototype = {
         return appId in this._favorites;
     },
 
-    addFavorite: function(appId) {
+    _addFavorite: function(appId) {
         if (appId in this._favorites)
-            return;
+            return false;
+
         let app = Shell.AppSystem.get_default().get_app(appId);
+
         if (!app)
-            return;
+            return false;
+
         let ids = this._getIds();
         ids.push(appId);
         this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
         this._favorites[appId] = app;
+        return true;
     },
 
-    removeFavorite: function(appId) {
-        if (!appId in this._favorites)
+    addFavorite: function(appId) {
+        if (!this._addFavorite(appId))
             return;
+
+        let app = Shell.AppSystem.get_default().get_app(appId);
+
+        Main.overview.infoBar.setMessage(_('%s has been added to your favorites.').format(app.get_name()), Lang.bind(this, function () {
+            this._removeFavorite(appId);
+        }));
+    },
+
+    _removeFavorite: function(appId) {
+        if (!appId in this._favorites)
+            return false;
+
         let ids = this._getIds().filter(function (id) { return id != appId; });
         this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
+        return true;
+    },
+
+    removeFavorite: function(appId) {
+        if (!this._removeFavorite(appId))
+            return;
+
+        Main.overview.infoBar.setMessage(_('%s has been removed from your favorites.').format(this._favorites[appId].get_name()),
+                                         Lang.bind(this, function () {
+            this._addFavorite(appId);
+        }));
     }
 };
 Signals.addSignalMethods(AppFavorites.prototype);
diff --git a/js/ui/overview.js b/js/ui/overview.js
index d085928..008bebd 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -9,6 +9,8 @@ const Shell = imports.gi.Shell;
 const Signals = imports.signals;
 const Lang = imports.lang;
 const St = imports.gi.St;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
 
 const AppDisplay = imports.ui.appDisplay;
 const DocDisplay = imports.ui.docDisplay;
@@ -74,10 +76,119 @@ const SHADOW_WIDTH = 6;
 
 const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
 
+const INFO_BAR_HIDE_TIMEOUT = 30;
+
 let wideScreen = false;
 let displayGridColumnWidth = null;
 let displayGridRowHeight = null;
 
+function InfoBar() {
+    this._init();
+}
+
+InfoBar.prototype = {
+    _init: function() {
+        this.actor = new St.Bin({ style_class: 'info-bar-panel',
+                                  x_fill: true,
+                                  y_fill: false });
+        this._label = new St.Label();
+        this._undo = new St.Button({ label: _('Undo'),
+                                     style_class: 'info-bar-link-button' });
+
+        let bin = new St.Bin({ style_class: 'info-bar',
+                               x_fill: false,
+                               y_fill: false,
+                               x_align: St.Align.MIDDLE,
+                               y_align: St.Align.MIDDLE });
+        this.actor.set_child(bin);
+
+        let box = new St.BoxLayout();
+        bin.set_child(box);
+        this._timeoutId = 0;
+
+        box.add(this._label, {'y-fill' : false, 'y-align' : St.Align.MIDDLE});
+        box.add(this._undo);
+
+        this.actor.set_opacity(0);
+
+        this._undoCallback = null;
+        this._undo.connect('clicked', Lang.bind(this, this._onUndoClicked));
+
+        this._overviewWasHidden = false;
+        this._hidingOverviewId = 0;
+    },
+
+    _onUndoClicked: function() {
+        Mainloop.source_remove(this._timeoutId);
+        this._timeoutId = 0;
+
+        if (this._undoCallback)
+            this._undoCallback();
+        this.actor.set_opacity(0);
+        this._undoCallback = null;
+    },
+
+    _hideDone: function() {
+        this._undoCallback = null;
+    },
+
+    _hide: function() {
+        this._overviewWasHidden = false;
+        Tweener.addTween(this.actor,
+                         { opacity: 0,
+                           transition: 'easeOutQuad',
+                           time: ANIMATION_TIME,
+                           onComplete: this._hideDone,
+                           onCompleteScope: this
+                         });
+    },
+
+    _onTimeout: function() {
+        this._timeoutId = 0;
+        if (this._overviewWasHidden)
+            this._hide();
+        return false;
+    },
+
+    _onOverviewHiding: function() {
+        if (this._timeoutId == 0)
+            this._hide();
+        else
+            this._overviewWasHidden = true;
+    },
+
+    setMessage: function(text, undoCallback) {
+        if (this._timeoutId)
+            Mainloop.source_remove(this._timeoutId);
+
+        if (this._hidingOverviewId == 0) {
+            // Set here, because when constructor is called, overview is null.
+            if (!Main.overview)
+                return;
+            // We don't actually use the ID, it's just a way of tracking whether we've hooked up the signal
+            this._hidingOverviewId = Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding));
+        }
+        this._timeout = false;
+        this._overviewWasHidden = false;
+
+        this._label.text = text + '  ';
+
+        Tweener.addTween(this.actor,
+                         { opacity: 255,
+                           transition: 'easeOutQuad',
+                           time: ANIMATION_TIME
+                         });
+
+        this._timeoutId = Mainloop.timeout_add_seconds(INFO_BAR_HIDE_TIMEOUT, Lang.bind(this, this._onTimeout));
+
+        this._undoCallback = undoCallback;
+        if (undoCallback)
+            this._undo.show();
+        else
+            this._undo.hide();
+    }
+};
+
 function Overview() {
     this._init();
 }
@@ -87,6 +198,9 @@ Overview.prototype = {
         this._group = new Clutter.Group();
         this._group._delegate = this;
 
+        this.infoBar = new InfoBar();
+        this._group.add_actor(this.infoBar.actor);
+
         this._workspacesViewSwitch = new WorkspacesView.WorkspacesViewSwitch();
         this._workspacesViewSwitch.connect('view-changed', Lang.bind(this, this._onViewChanged));
 
@@ -229,6 +343,10 @@ Overview.prototype = {
         this._dash.sectionArea.height = this._workspacesHeight;
         this._dash.searchResults.actor.height = this._workspacesHeight;
 
+        this.infoBar.actor.set_position(displayGridColumnWidth, Panel.PANEL_HEIGHT);
+        this.infoBar.actor.set_size(primary.width - displayGridColumnWidth, this._workspacesY - Panel.PANEL_HEIGHT);
+        this.infoBar.actor.raise_top();
+
         // place the 'Add Workspace' button in the bottom row of the grid
         this._workspacesBarX = this._workspacesX;
         this._workspacesBarWidth = primary.width - this._workspacesBarX - WORKSPACE_GRID_PADDING;



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