[gnome-shell-extensions/wip/apps-menu] apps-menu: Replace it with a new version based on AxeMenu



commit 8e008b08b86aa588354c4558edbc8f9e868b1ac4
Author: Debarshi Ray <debarshir gnome org>
Date:   Fri Jan 4 18:31:57 2013 +0100

    apps-menu: Replace it with a new version based on AxeMenu
    
    This is a severely toned down version of the original AxeMenu:
     - the column on the left has been removed, because it duplicates
       functionality provided by the places-menu and the user menu
     - the application search functionality has been removed because it
       is already provided by vanilla gnome-shell
     - the "All" category ended up being too crowded and has been replaced
       by "Favorites", so there is no separate page for it any more
    
    https://bugzilla.gnome.org/show_bug.cgi?id=692527

 extensions/apps-menu/Makefile.am                   |    1 +
 extensions/apps-menu/extension.js                  |  558 ++++++++++++++++++--
 extensions/apps-menu/metadata.json.in              |    1 +
 ...gnome.shell.extensions.apps-menu.gschema.xml.in |    8 +
 extensions/apps-menu/stylesheet.css                |    9 +-
 po/POTFILES.in                                     |    1 +
 6 files changed, 532 insertions(+), 46 deletions(-)
---
diff --git a/extensions/apps-menu/Makefile.am b/extensions/apps-menu/Makefile.am
index 86431d7..94ebc22 100644
--- a/extensions/apps-menu/Makefile.am
+++ b/extensions/apps-menu/Makefile.am
@@ -1,3 +1,4 @@
 EXTENSION_ID = apps-menu
 
 include ../../extension.mk
+include ../../settings.mk
diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js
index faf099f..6b112f6 100644
--- a/extensions/apps-menu/extension.js
+++ b/extensions/apps-menu/extension.js
@@ -1,111 +1,579 @@
 /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
+const Atk = imports.gi.Atk;
 const GMenu = imports.gi.GMenu;
 const Lang = imports.lang;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
-
+const Clutter = imports.gi.Clutter;
 const Main = imports.ui.main;
+const Meta = imports.gi.Meta;
 const PanelMenu = imports.ui.panelMenu;
 const PopupMenu = imports.ui.popupMenu;
+const Gtk = imports.gi.Gtk;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Signals = imports.signals;
+const Layout = imports.ui.layout;
+const Pango = imports.gi.Pango;
+
+const Gettext = imports.gettext.domain('gnome-shell-extensions');
+const _ = Gettext.gettext;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const Me = ExtensionUtils.getCurrentExtension();
+const Convenience = Me.imports.convenience;
+
+const appSys = Shell.AppSystem.get_default();
 
-const ICON_SIZE = 28;
+const APPLICATION_ICON_SIZE = 32;
 
-const AppMenuItem = new Lang.Class({
-    Name: 'AppsMenu.AppMenuItem',
+function fixMarkup(text, allowMarkup) {
+    if (allowMarkup) {
+        let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&amp;');
+        _text = _text.replace(/<(?!\/?[biu]>)/g, '&lt;');
+        try {
+            Pango.parse_markup(_text, -1, '');
+            return _text;
+        } catch (e) {}
+    }
+    return GLib.markup_escape_text(text, -1);
+}
+
+const ActivitiesMenuItem = new Lang.Class({
+    Name: 'ActivitiesMenuItem',
     Extends: PopupMenu.PopupBaseMenuItem,
 
-    _init: function (app, params) {
-        this.parent(params);
+    _init: function() {
+	this.parent();
+        this.addActor(new St.Label({ text: _("Activities Overview") }));
+    },
 
-        this._app = app;
-        this.label = new St.Label({ text: app.get_name() });
-        this.addActor(this.label);
-        this._icon = app.create_icon_texture(ICON_SIZE);
-        this.addActor(this._icon, { expand: false });
+    activate: function(event) {
+        appsMenuButton.toggleMenu();
+        Main.overview.toggle();
+	this.parent(event);
     },
+});
+
+const ApplicationMenuItem = new Lang.Class({
+    Name: 'ApplicationMenuItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
 
-    activate: function (event) {
-        this._app.activate_full(-1, event.get_time());
+    _init: function(menu, app) {
+	this.parent();
+	this._app = app;
+        this._menu = menu;
+
+        let icon = this._app.create_icon_texture(APPLICATION_ICON_SIZE);
+	this.addActor(icon);
+
+        let appName = fixMarkup(this._app.get_name());
+        this.addActor(new St.Label({ text: appName }));
+    },
 
-        this.parent(event);
+    activate: function(event) {
+	this._app.open_new_window(event.get_time());
+        this._menu._select_category(null, null);
+        this._menu.toggleMenu();
+	this.parent(event);
+    },
+
+    setActive: function(active, params) {
+        if (active)
+            this._menu._scrollToButton(this);
+        this.parent(active, params);
     }
+});
+
+const CategoryMenuItem = new Lang.Class({
+    Name: 'CategoryMenuItem',
+    Extends: PopupMenu.PopupBaseMenuItem,
+
+    _init: function(menu, category) {
+	this.parent();
+	this._category = category;
+        this._menu = menu;
+
+        let name;
+        if (this._category)
+            name = this._category.get_name();
+        else
+            name = _("Favorites");
 
+        this.addActor(new St.Label({ text: name }));
+    },
+
+    activate: function(event) {
+        this._menu._select_category(this._category, this);
+        this._menu._scrollToCatButton(this);
+	this.parent(event);
+    },
+
+    setActive: function(active, params) {
+        if (active) {
+            this._menu._select_category(this._category, this);
+            this._menu._scrollToCatButton(this);
+        }
+        this.parent(active, params);
+    }
+});
+
+const HotCorner = new Lang.Class({
+    Name: 'HotCorner',
+    Extends: Layout.HotCorner,
+
+    _init : function(menu) {
+        this._menu = menu;
+        this.parent();
+    },
+
+    _onCornerEntered : function() {
+        if (!this._entered) {
+            this._entered = true;
+            if (!Main.overview.animationInProgress) {
+                this._activationTime = Date.now() / 1000;
+                this.rippleAnimation();
+                Main.overview.toggle();
+            }
+        }
+        return false;
+    }
+});
+
+const ApplicationsMenu = new Lang.Class({
+    Name: 'ApplicationsMenu',
+    Extends: PopupMenu.PopupMenu,
+
+    _init: function(sourceActor, arrowAlignment, arrowSide, hotCorner) {
+        this.parent(sourceActor, arrowAlignment, arrowSide);
+        this._hotCorner = hotCorner;
+    },
+
+    open: function(animate) {
+        this._hotCorner.actor.hide();
+        this.parent(animate);
+    },
+
+    close: function(animate) {
+        this._hotCorner.actor.show();
+        this.parent(animate);
+    }
 });
 
 const ApplicationsButton = new Lang.Class({
-    Name: 'AppsMenu.ApplicationsButton',
-    Extends: PanelMenu.SystemStatusButton,
+    Name: 'ApplicationsButton',
+    Extends: PanelMenu.Button,
 
     _init: function() {
-        this.parent('start-here-symbolic');
+        this.parent(1.0, null, false);
+        this._hotCorner = new HotCorner(this);
+        this.setMenu(new ApplicationsMenu(this.actor, 1.0, St.Side.TOP, this._hotCorner));
+        Main.panel.menuManager.addMenu(this.menu);
+
+        // At this moment applications menu is not keyboard navigable at
+        // all (so not accessible), so it doesn't make sense to set as
+        // role ATK_ROLE_MENU like other elements of the panel.
+        this.actor.accessible_role = Atk.Role.LABEL;
+
+        let container = new Shell.GenericContainer();
+        container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
+        container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
+        container.connect('allocate', Lang.bind(this, this._containerAllocate));
+        this.actor.add_actor(container);
+        this.actor.name = 'panelApplications';
+
+        this._label = new St.Label({ text: _("Applications") });
+        container.add_actor(this._label);
+
+        this.actor.label_actor = this._label;
+
+        container.add_actor(this._hotCorner.actor);
+        Main.messageTray._grabHelper.addActor(this._hotCorner.actor);
 
-        this._appSys = Shell.AppSystem.get_default();
-        this._installedChangedId = this._appSys.connect('installed-changed', Lang.bind(this, this._refresh));
+        _capturedEventId = this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
 
+        Main.overview.connect('showing', Lang.bind(this, function() {
+            this.actor.add_accessible_state (Atk.StateType.CHECKED);
+        }));
+        Main.overview.connect('hiding', Lang.bind(this, function() {
+            this.actor.remove_accessible_state (Atk.StateType.CHECKED);
+        }));
+
+        this._selectedItemIndex = null;
+        this._previousSelectedItemIndex = null;
+        this._activeContainer = null;
+        this.reloadFlag = true;
+        this._createLayout();
         this._display();
+        _installedChangedId = appSys.connect('installed-changed', Lang.bind(this, this.reDisplay));
+        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateToggled));
+
+        Main.wm.addKeybinding('menu-toggle',
+                              Convenience.getSettings(),
+                              Meta.KeyBindingFlags.NONE,
+                              Main.KeybindingMode.NORMAL | Main.KeybindingMode.OVERVIEW,
+                              function() {
+                                  appsMenuButton.toggleMenu();
+                              });
+
+        // Since the hot corner uses stage coordinates, Clutter won't
+        // queue relayouts for us when the panel moves. Queue a relayout
+        // when that happens.
+        _panelBoxChangedId = Main.layoutManager.connect('panel-box-changed', Lang.bind(this, function() {
+            container.queue_relayout();
+        }));
     },
 
-    destroy: function() {
-        this._appSys.disconnect(this._installedChangedId);
+    _containerGetPreferredWidth: function(actor, forHeight, alloc) {
+        [alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight);
+    },
 
-        this.parent();
+    _containerGetPreferredHeight: function(actor, forWidth, alloc) {
+        [alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth);
     },
 
-    _refresh: function() {
-        this._clearAll();
-        this._display();
+    _containerAllocate: function(actor, box, flags) {
+        this._label.allocate(box, flags);
+
+        // The hot corner needs to be outside any padding/alignment
+        // that has been imposed on us
+        let primary = Main.layoutManager.primaryMonitor;
+        let hotBox = new Clutter.ActorBox();
+        let ok, x, y;
+        if (actor.get_text_direction() == Clutter.TextDirection.LTR) {
+            [ok, x, y] = actor.transform_stage_point(primary.x, primary.y);
+        } else {
+            [ok, x, y] = actor.transform_stage_point(primary.x + primary.width, primary.y);
+            // hotCorner.actor has northeast gravity, so we don't need
+            // to adjust x for its width
+        }
+
+        hotBox.x1 = Math.round(x);
+        hotBox.x2 = hotBox.x1 + this._hotCorner.actor.width;
+        hotBox.y1 = Math.round(y);
+        hotBox.y2 = hotBox.y1 + this._hotCorner.actor.height;
+        this._hotCorner.actor.allocate(hotBox, flags);
+    },
+
+    _createVertSeparator: function() {
+        let separator = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
+                                             pseudo_class: 'highlighted' });
+        separator.connect('repaint', Lang.bind(this, this._onVertSepRepaint));
+        return separator;
+    },
+
+    _onCapturedEvent: function(actor, event) {
+        if (event.type() == Clutter.EventType.BUTTON_PRESS) {
+            if (!this._hotCorner.shouldToggleOverviewOnClick())
+                return true;
+        }
+        return false;
+    },
+
+    _onButtonPress: function(actor, event) {
+        this.toggleMenu();
+    },
+
+    _onVertSepRepaint: function(area) {
+        let cr = area.get_context();
+        let themeNode = area.get_theme_node();
+        let [width, height] = area.get_surface_size();
+        let stippleColor = themeNode.get_color('-stipple-color');
+        let stippleWidth = themeNode.get_length('-stipple-width');
+        let x = Math.floor(width/2) + 0.5;
+        cr.moveTo(x, 0);
+        cr.lineTo(x, height);
+        Clutter.cairo_set_source_color(cr, stippleColor);
+        cr.setDash([1, 3], 1); // Hard-code for now
+        cr.setLineWidth(stippleWidth);
+        cr.stroke();
+    },
+
+    _addEnterEvent: function(button, callback) {
+        let _callback = Lang.bind(this, function() {
+            let parent = button.actor.get_parent();
+            if (this._activeContainer === this.categoriesBox && parent !== this._activeContainer) {
+                this._previousSelectedItemIndex = this._selectedItemIndex;
+            }
+            this._activeContainer = parent;
+            let children = this._activeContainer.get_children();
+            for (let i=0, l=children.length; i<l; i++) {
+                if (button.actor === children[i]) {
+                    this._selectedItemIndex = i;
+                }
+            };
+            callback();
+        });
+        button.connect('enter-event', _callback);
+        button.actor.connect('enter-event', _callback);
+    },
+
+    _onOpenStateToggled: function(menu, open) {
+       if (open) {
+           this._selectedItemIndex = null;
+
+           this.mainBox.show();
+           this._activeContainer = null;
+       }
+       PanelMenu.Button.prototype._onOpenStateChanged.call(this, menu, open);
+    },
+
+    reDisplay : function(e,object,p0,p1) {
+        if (this.reloadFlag && (p1 == 3 || p1 === undefined)) {
+            this._cleanControls();
+            this._display();
+        }
+        this.reloadFlag = true;
     },
 
-    _clearAll: function() {
-        this.menu.removeAll();
+    _cleanControls: function() {
+        this.categoriesBox.destroy_all_children();
+        this.applicationsBox.destroy_all_children();
     },
 
-    // Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
-    // (taken from js/ui/appDisplay.js in core shell)
-    _loadCategory: function(dir, menu) {
-        var iter = dir.iter();
-        var nextType;
+    _loadCategory: function(dir) {
+        let iter = dir.iter();
+        let nextType;
         while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
             if (nextType == GMenu.TreeItemType.ENTRY) {
-                var entry = iter.get_entry();
-                var app = this._appSys.lookup_app_by_tree_entry(entry);
-                if (!entry.get_app_info().get_nodisplay())
-                    menu.addMenuItem(new AppMenuItem(app));
+                let entry = iter.get_entry();
+                if (!entry.get_app_info().get_nodisplay()) {
+                    let app = appSys.lookup_app_by_tree_entry(entry);
+                    if (!this.applicationsByCategory[dir.get_menu_id()])
+                        this.applicationsByCategory[dir.get_menu_id()] = new Array();
+                    this.applicationsByCategory[dir.get_menu_id()].push(app);
+                }
             } else if (nextType == GMenu.TreeItemType.DIRECTORY) {
-                this._loadCategory(iter.get_directory(), menu);
+                let subdir = iter.get_directory();
+                if (subdir.get_is_nodisplay()) continue;
+                this.applicationsByCategory[subdir.get_menu_id()] = new Array();
+                this._loadCategory(subdir);
+                if (this.applicationsByCategory[subdir.get_menu_id()].length > 0) {
+                   let categoryMenuItem = new CategoryMenuItem(this, subdir);
+                   this.categoriesBox.add_actor(categoryMenuItem.actor);
+                }
             }
         }
     },
 
+    _scrollToButton: function(button) {
+        let appsScrollBoxAdj = this.applicationsScrollBox.get_vscroll_bar().get_adjustment();
+        let appsScrollBoxAlloc = this.applicationsScrollBox.get_allocation_box();
+        let currentScrollValue = appsScrollBoxAdj.get_value();
+        let boxHeight = appsScrollBoxAlloc.y2 - appsScrollBoxAlloc.y1;
+        let buttonAlloc = button.actor.get_allocation_box();
+        let newScrollValue = currentScrollValue;
+        if (currentScrollValue > buttonAlloc.y1 - 10)
+            newScrollValue = buttonAlloc.y1 - 10;
+        if (boxHeight + currentScrollValue < buttonAlloc.y2 + 10)
+            newScrollValue = buttonAlloc.y2 - boxHeight + 10;
+        if (newScrollValue != currentScrollValue)
+            appsScrollBoxAdj.set_value(newScrollValue);
+    },
+
+    _scrollToCatButton: function(button) {
+        let catsScrollBoxAdj = this.categoriesScrollBox.get_vscroll_bar().get_adjustment();
+        let catsScrollBoxAlloc = this.categoriesScrollBox.get_allocation_box();
+        let currentScrollValue = catsScrollBoxAdj.get_value();
+        let boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1;
+        let buttonAlloc = button.actor.get_allocation_box();
+        let newScrollValue = currentScrollValue;
+        if (currentScrollValue > buttonAlloc.y1 - 10)
+            newScrollValue = buttonAlloc.y1 - 10;
+        if (boxHeight + currentScrollValue < buttonAlloc.y2 + 10)
+            newScrollValue = buttonAlloc.y2 - boxHeight + 10;
+        if (newScrollValue != currentScrollValue)
+            catsScrollBoxAdj.set_value(newScrollValue);
+    },
+
+    _createLayout: function() {
+        let section = new PopupMenu.PopupMenuSection();
+        this.menu.addMenuItem(section);
+        this.mainBox = new St.BoxLayout({ style_class: 'main-box', vertical: false });
+        this.leftBox = new St.BoxLayout({ vertical: true });
+        this.applicationsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
+                                                         y_align: St.Align.START,
+                                                         style_class: 'vfade' });
+        this.applicationsScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+        let vscroll = this.applicationsScrollBox.get_vscroll_bar();
+        vscroll.connect('scroll-start', Lang.bind(this, function() {
+            this.menu.passEvents = true;
+        }));
+        vscroll.connect('scroll-stop', Lang.bind(this, function() {
+            this.menu.passEvents = false;
+        }));
+        this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false,
+                                                       y_align: St.Align.START,
+                                                       style_class: 'vfade' });
+        this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+        vscroll = this.categoriesScrollBox.get_vscroll_bar();
+        vscroll.connect('scroll-start', Lang.bind(this, function() {
+                              this.menu.passEvents = true;
+                          }));
+        vscroll.connect('scroll-stop', Lang.bind(this, function() {
+            this.menu.passEvents = false;
+        }));
+        this.leftBox.add(this.categoriesScrollBox, { expand: true,
+                                                     x_fill: true, y_fill: true,
+                                                     y_align: St.Align.START });
+
+        let activities = new ActivitiesMenuItem();
+        this.leftBox.add(activities.actor, { expand: false,
+                                             x_fill: true, y_fill: false,
+                                             y_align: St.Align.START });
+
+        this.applicationsBox = new St.BoxLayout({ style_class: 'applications-box', vertical:true });
+        this.applicationsScrollBox.add_actor(this.applicationsBox);
+        this.categoriesBox = new St.BoxLayout({ vertical: true });
+        this.categoriesScrollBox.add_actor(this.categoriesBox, { expand: true, x_fill: false });
+
+        this.mainBox.add(this.leftBox);
+        this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true});
+        this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true });
+        section.actor.add_actor(this.mainBox);
+    },
+
     _display : function() {
-        let tree = this._appSys.get_tree();
-        let root = tree.get_root_directory();
+        this._activeContainer = null;
+        this._applicationsButtons = new Array();
+        this.mainBox.style=('width: 640px;');
+        this.mainBox.hide();
 
+        //Load categories
+        this.applicationsByCategory = {};
+        let tree = appSys.get_tree();
+        let root = tree.get_root_directory();
+        let categoryMenuItem = new CategoryMenuItem(this, null);
+        this.categoriesBox.add_actor(categoryMenuItem.actor);
         let iter = root.iter();
         let nextType;
         while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
             if (nextType == GMenu.TreeItemType.DIRECTORY) {
                 let dir = iter.get_directory();
-                let item = new PopupMenu.PopupSubMenuMenuItem(dir.get_name());
-                this._loadCategory(dir, item.menu);
-                this.menu.addMenuItem(item);
+                if (dir.get_is_nodisplay()) continue;
+                this.applicationsByCategory[dir.get_menu_id()] = new Array();
+                this._loadCategory(dir);
+                if (this.applicationsByCategory[dir.get_menu_id()].length>0) {
+                   let categoryMenuItem = new CategoryMenuItem(this, dir);
+                   this.categoriesBox.add_actor(categoryMenuItem.actor);
+                }
+            }
+        }
+
+        //Load applications
+        this._displayButtons(this._listApplications(null));
+
+        let catHeight = this.categoriesBox.height + 45;
+        let smartHeight = catHeight + 20 + 'px;';
+        this.mainBox.style+=('height: ' + smartHeight);
+    },
+
+    _clearApplicationsBox: function(selectedActor) {
+        let actors = this.applicationsBox.get_children();
+        for (let i=0; i<actors.length; i++) {
+            let actor = actors[i];
+            this.applicationsBox.remove_actor(actor);
+        }
+    },
+
+    _select_category : function(dir, categoryMenuItem) {
+        if (categoryMenuItem)
+            this._clearApplicationsBox(categoryMenuItem.actor);
+        else
+            this._clearApplicationsBox(null);
+
+        if (dir)
+            this._displayButtons(this._listApplications(dir.get_menu_id()));
+        else
+            this._displayButtons(this._listApplications(null));
+    },
+
+    _displayButtons: function(apps) {
+         if (apps) {
+            for (let i=0; i<apps.length; i++) {
+               let app = apps[i];
+               if (!this._applicationsButtons[app]) {
+                  let applicationMenuItem = new ApplicationMenuItem(this, app);
+                  this._applicationsButtons[app] = applicationMenuItem;
+               }
+               if (!this._applicationsButtons[app].actor.get_parent())
+                  this.applicationsBox.add_actor(this._applicationsButtons[app].actor);
+            }
+         }
+    },
+
+    _listApplications: function(category_menu_id) {
+        let applist;
+
+        if (category_menu_id) {
+            applist = this.applicationsByCategory[category_menu_id];
+        } else {
+            applist = new Array();
+            let favorites = global.settings.get_strv('favorite-apps');
+            for (let i = 0; i < favorites.length; i++) {
+                let app = appSys.lookup_app(favorites[i]);
+                if (app)
+                    applist.push(app);
             }
         }
+
+        applist.sort(function(a,b) {
+            return a.get_name().toLowerCase() > b.get_name().toLowerCase();
+        });
+        return applist;
+    },
+
+    toggleMenu: function() {
+        if (!this.menu.isOpen) {
+            if (Main.overview.visible)
+                Main.overview.hide();
+        } else {
+            this.reloadFlag = false;
+            this._select_category(null, null);
+        }
+        this.menu.toggle();
+    },
+
+    destroy: function() {
+        this.actor._delegate = null;
+        this.menu.actor.get_children().forEach(function(c) { c.destroy() });
+        this.menu.destroy();
+        Main.wm.removeKeybinding('menu-toggle');
+        this.actor.destroy();
     }
 });
 
 let appsMenuButton;
+let activitiesButton;
+let activitiesButtonLabel;
+let _capturedEventId;
+let _installedChangedId;
+let _panelBoxChangedId;
+let extensionMeta;
 
 function enable() {
+    activitiesButton = Main.panel.statusArea['activities'];
+    activitiesButtonLabel = activitiesButton._label.get_text();
+    activitiesButton.hotCorner.actor.hide();
+    activitiesButton.container.hide();
     appsMenuButton = new ApplicationsButton();
-    Main.panel.addToStatusArea('apps-menu', appsMenuButton, 1, 'left');
+    Main.panel._leftBox.insert_child_at_index(appsMenuButton.container, 0);
+    Main.panel._axeMenu = appsMenuButton;
 }
 
 function disable() {
+    Main.panel._leftBox.remove_actor(appsMenuButton.container);
+    Main.panel.menuManager.removeMenu(appsMenuButton.menu);
+    appSys.disconnect(_installedChangedId);
+    appsMenuButton.actor.disconnect(_capturedEventId);
+    Main.layoutManager.disconnect(_panelBoxChangedId);
     appsMenuButton.destroy();
+    activitiesButton.container.show();
+    activitiesButton.hotCorner.actor.show();
+    Main.panel._leftBox.insert_child_at_index(activitiesButton.container, 0);
 }
 
-function init() {
-    /* do nothing */
+function init(metadata) {
+    Convenience.initTranslations();
 }
diff --git a/extensions/apps-menu/metadata.json.in b/extensions/apps-menu/metadata.json.in
index 8d5380c..46c5759 100644
--- a/extensions/apps-menu/metadata.json.in
+++ b/extensions/apps-menu/metadata.json.in
@@ -5,6 +5,7 @@
 "gettext-domain": "@gettext_domain@",
 "name": "Applications Menu",
 "description": "Add a gnome 2.x style menu for applications",
+"original-authors": [ "e2002 bk ru", "debarshir gnome org" ],
 "shell-version": [ "@shell_current@" ],
 "url": "@url@"
 }
diff --git a/extensions/apps-menu/org.gnome.shell.extensions.apps-menu.gschema.xml.in b/extensions/apps-menu/org.gnome.shell.extensions.apps-menu.gschema.xml.in
new file mode 100644
index 0000000..56f3013
--- /dev/null
+++ b/extensions/apps-menu/org.gnome.shell.extensions.apps-menu.gschema.xml.in
@@ -0,0 +1,8 @@
+<schemalist gettext-domain="gnome-shell-extensions">
+  <schema id="org.gnome.shell.extensions.apps-menu" path="/org/gnome/shell/extensions/apps-menu/">
+    <key name="menu-toggle" type="as">
+      <default>["&lt;Super&gt;r"]</default>
+      <_summary>Toggle AxeMenu.</_summary>
+    </key>
+  </schema>
+</schemalist>
diff --git a/extensions/apps-menu/stylesheet.css b/extensions/apps-menu/stylesheet.css
index db99e0c..cb3c60b 100644
--- a/extensions/apps-menu/stylesheet.css
+++ b/extensions/apps-menu/stylesheet.css
@@ -1 +1,8 @@
-/* none used*/
+.main-box {
+    padding-top: 10px;
+    padding-right: 10px;
+    padding-bottom: 10px;
+}
+.applications-box {
+    padding-right: 5px;
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6c752d6..fd6e7ae 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,6 +5,7 @@ extensions/alternate-tab/prefs.js
 extensions/alternative-status-menu/extension.js
 extensions/alternative-status-menu/org.gnome.shell.extensions.alternative-status-menu.gschema.xml.in
 extensions/apps-menu/extension.js
+extensions/apps-menu/org.gnome.shell.extensions.apps-menu.gschema.xml.in
 extensions/auto-move-windows/extension.js
 extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml.in
 extensions/auto-move-windows/prefs.js



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