[gnome-shell/app-picker-refresh: 16/16] appDisplay: Add additional view showing frequently used apps



commit 17815dca6ee9c1810688a629dec77f8c83bd0faf
Author: Florian Müllner <fmuellner gnome org>
Date:   Mon Feb 18 20:18:08 2013 +0100

    appDisplay: Add additional view showing frequently used apps

 data/theme/gnome-shell.css |   39 ++++++++++++--
 js/ui/appDisplay.js        |  128 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 149 insertions(+), 18 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 2184390..6b1bf92 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -848,13 +848,44 @@ StScrollBar StButton#vhandle:active {
 }
 
 .app-display {
-    padding: 0px 16px 32px 32px;
+    padding: 8px;
     spacing: 20px;
 }
 
-.app-display:rtl {
-    padding-left: 16px;
-    padding-right: 32px;
+.app-view-controls {
+    border-radius: 8px;
+    border: 1px solid rgba(245,245,245,0.6);
+    width: 250px;
+}
+
+.app-view-controls-bin {
+    padding-right: 10px;
+}
+
+.app-view-control {
+    padding: 4px 16px;
+    background-gradient-start: rgba(254,254,254,0.1);
+    background-gradient-end: rgba(5,5,6,0.1);
+    background-gradient-direction: vertical;
+}
+
+.app-view-control:first-child {
+    border-radius: 8px 0px 0px 8px;
+}
+
+.app-view-control:last-child {
+    border-radius: 0px 8px 8px 0px;
+}
+
+.app-view-control:checked {
+    background-gradient-start: rgba(0,0,0,0.8);
+    background-gradient-end: rgba(5,5,6,0.1);
+    background-gradient-direction: vertical;
+}
+
+StScrollView.frequent-apps StScrollBar {
+    min-width: 0px;
+    width: 0px;
 }
 
 .app-folder-icon {
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 1920929..102a138 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -20,6 +20,7 @@ const DND = imports.ui.dnd;
 const IconGrid = imports.ui.iconGrid;
 const Main = imports.ui.main;
 const Overview = imports.ui.overview;
+const OverviewControls = imports.ui.overviewControls;
 const PopupMenu = imports.ui.popupMenu;
 const Tweener = imports.ui.tweener;
 const Workspace = imports.ui.workspace;
@@ -223,6 +224,49 @@ const AlphabeticalView = new Lang.Class({
 });
 
 
+const FrequentView = new Lang.Class({
+    Name: 'FrequentView',
+
+    _init: function() {
+        this._grid = new IconGrid.IconGrid({ xAlign: St.Align.MIDDLE,
+                                             columnLimit: 6 });
+        let box = new St.BoxLayout({ vertical: true });
+        box.add(this._grid.actor);
+
+        // HACK: IconGrid currently lacks API to only display items that match
+        // the allocation, so rather than clipping away eventual overflow, we
+        // use an unscrollable ScrollView with hidden scrollbars to nicely
+        // fade out cut off items
+        this.actor = new St.ScrollView({ x_fill: true,
+                                         y_fill: false,
+                                         y_align: St.Align.START,
+                                         x_expand: true,
+                                         reactive: false,
+                                         style_class: 'frequent-apps vfade' });
+        this.actor.add_actor(box);
+        this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+
+        this._usage = Shell.AppUsage.get_default();
+    },
+
+    removeAll: function() {
+        this._grid.removeAll();
+    },
+
+    loadApps: function() {
+        let mostUsed = this._usage.get_most_used ("");
+        for (let i = 0; i < mostUsed.length; i++) {
+            let appIcon = new AppIcon(mostUsed[i]);
+            this._grid.addItem(appIcon.actor, -1);
+        }
+    }
+});
+
+const Views = {
+    FREQUENT: 0,
+    ALL: 1
+};
+
 /* This class represents a display containing a collection of application items.
  * The applications are sorted based on their name.
  */
@@ -235,30 +279,87 @@ const AppDisplay = new Lang.Class({
             Main.queueDeferredWork(this._workId);
         }));
 
-        let box = new St.BoxLayout();
-        this.actor = new St.Bin({ child: box,
-                                  style_class: 'app-display',
-                                  x_fill: true, y_fill: true });
-
-        this._view = new AlphabeticalView({ scrollable: true });
-        box.add(this._view.actor, { expand: true });
+        this._views = [];
+
+        let view, button;
+        view = new FrequentView();
+        button = new St.Button({ label: _("Frequent"),
+                                 style_class: 'app-view-control',
+                                 x_expand: true });
+        this._views[Views.FREQUENT] = { 'view': view, 'control': button };
+
+        view = new AlphabeticalView({ scrollable: true });
+        button = new St.Button({ label: _("All"),
+                                 style_class: 'app-view-control',
+                                 x_expand: true });
+        this._views[Views.ALL] = { 'view': view, 'control': button };
+
+        this.actor = new St.BoxLayout({ style_class: 'app-display',
+                                        vertical: true,
+                                        x_expand: true, y_expand: true });
+
+        this._viewStack = new St.Widget({ layout_manager: new Clutter.BinLayout(),
+                                          x_expand: true, y_expand: true });
+        let bin = new St.Bin({ child: this._viewStack,
+                               clip_to_allocation: true,
+                               x_fill: true, y_fill: true });
+        this.actor.add(bin, { expand: true });
+
+        let layout = new Clutter.BoxLayout({ homogeneous: true });
+        this._controls = new St.Widget({ style_class: 'app-view-controls',
+                                         layout_manager: layout });
+        this.actor.add(new St.Bin({ child: this._controls }));
+
+
+        for (let i = 0; i < this._views.length; i++) {
+            this._viewStack.add_actor(this._views[i].view.actor);
+            this._controls.add_actor(this._views[i].control);
+
+            let viewIndex = i;
+            this._views[i].control.connect('clicked', Lang.bind(this,
+                function(actor) {
+                    this._showView(viewIndex);
+                }));
+        }
+        this._showView(Views.FREQUENT);
 
         // We need a dummy actor to catch the keyboard focus if the
         // user Ctrl-Alt-Tabs here before the deferred work creates
         // our real contents
         this._focusDummy = new St.Bin({ can_focus: true });
-        box.add(this._focusDummy);
+        this._viewStack.add_actor(this._focusDummy);
 
         this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
     },
 
+    _showView: function(activeIndex) {
+        for (let i = 0; i < this._views.length; i++) {
+            let actor = this._views[i].view.actor;
+            let params = { time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
+                           opacity: (i == activeIndex) ? 255 : 0 };
+            if (i == activeIndex)
+                actor.visible = true;
+            else
+                params.onComplete = function() { actor.hide(); };
+            Tweener.addTween(actor, params);
+
+            if (i == activeIndex)
+                this._views[i].control.add_style_pseudo_class('checked');
+            else
+                this._views[i].control.remove_style_pseudo_class('checked');
+        }
+    },
+
     _removeAll: function() {
-        this._view.removeAll();
+        for (let i = 0; i < this._views.length; i++)
+            this._views[i].view.removeAll();
     },
 
     _redisplay: function() {
         this._removeAll();
 
+        this._views[Views.FREQUENT].view.loadApps();
+
         var tree = this._appSystem.get_tree();
         var root = tree.get_root_directory();
 
@@ -270,11 +371,10 @@ const AppDisplay = new Lang.Class({
                 if (dir.get_is_nodisplay())
                     continue;
 
-                if (FOLDER_CATEGORIES.indexOf(dir.get_menu_id()) != -1) {
-                    this._view.addFolder(dir);
-                } else
-
-                _loadCategory(dir, this._view);
+                if (FOLDER_CATEGORIES.indexOf(dir.get_menu_id()) != -1)
+                    this._views[Views.ALL].view.addFolder(dir);
+                else
+                    _loadCategory(dir, this._views[Views.ALL].view);
             }
         }
 


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