Cinnamon app menu a mess.

Please post suggestions for improvement of Cinnamon here
https://github.com/linuxmint/Cinnamon

Cinnamon app menu a mess.

Postby violent23 on Mon Jan 28, 2013 5:48 pm

Why are the apps in Administration duplicated in Preferences? What makes it even worse is that the menu editor cannot edit these two categories.

It is very redundant to have the Administration tab in the app menu when all those apps are already listed under the Preferences tab.
violent23
Level 1
Level 1
 
Posts: 16
Joined: Sun Sep 05, 2010 10:23 pm

Linux Mint is funded by ads and donations.
 

Re: Cinnamon app menu a mess.

Postby Pablo Pablo on Tue Jan 29, 2013 6:21 am

*very* redundant? :D
Pablo Pablo
Level 1
Level 1
 
Posts: 5
Joined: Thu Nov 22, 2012 2:59 pm

Re: Cinnamon app menu a mess.

Postby roblm on Sun Feb 24, 2013 5:36 pm

This is also one of my main gripes with Cinnamon 1.6.7. The Preferences category is especially bad. Besides it's own separate apps and apps found in other categories, it individually lists all 15 of the apps found in Cinnamon Settings and the 14 apps found in System Settings and of course these are all repeated in the All Applications category. This would be alright if the Preferences and Administration categories could be edited. I like to tweak my menus to be as compact as possible. To my knowledge they could be edited in past versions using Alacarte. I even tried other menu editors like Mozo and Kmenuedit, knowing they probably wouldn't work. My solution was to eliminate the Preferences category. To do this go to "/etc/xdg/menus". Open as root the file "cinnamon-setting.menu". Delete the 10 lines starting with "<- Merge in these other files as submenus ->" up to "</Menu>". Then delete the resulting extra spaces between lines so that there is only one space. Be sure the line "<!- System Settings ->" lines up with the line "<DefaulMergeDirs/>" on the left side. Go down the list and under "<Layout>" delete the line "<Menuname>Preferences</Menuname>". Close the space that forms. Save the new settings and close the file. Do not delete this file hoping to eliminate both the Preferences and Administration categories or your menu will be unusable. Restart Cinnamon and the Preferences category should be gone. Also, all the apps listed under it will disappear from the All Applications category.
Now you will need to replace any removed apps that you may need to access. I added "Cinnamon Settings" and "Startup Applications" to the "System Tools" category. To do this I right clicked the menu button and selected "edit menu". I highlighted "System Tools" on the left and clicked "New Item" on the right. In the "Create Launcher" window I typed "Cinnamon Settings" under "name". For the "command" line, I temporarily left this window open and opened the file manager and went to "/usr/share/applications". I right clicked on "Cinnamon Settings" and selected "properties". I copied the words in the "command" line, which were "cinnamon-settings", and pasted them into the "command" line in the "Create Launcher" window. I then clicked on the icon and selected "icons" on the left and then on the right selected Mint-X>categories>24>gnome-system.png. Click "open" and OK. I repeated the process for the "Startup Applications" app except for the icon I went to icons/Mint-X/apps/24/gnome-session.png. For any other apps in the Administration category you want to remove, then here is a solution. Go to "/usr/share" and create a new folder named "applications-2". Open as root "/usr/share/applications" and move any apps you won't need to open over to the applications-2 folder. I moved "User Accounts" and "Windows Wireless Drivers" as I will not have any immediate need to use them. To make my menu even more compact, I replaced the default Cinnamon Menu with the "Simpler Menu" by downloading the Simpler Menu applet. It eliminates the Quit, Logout and Lock Screen buttons on the menu. I prefer one single button that contains all the options when clicked. I downloaded the "Quit" applet to replace these 3 buttons and it was installed on the panel directly under the menu. This freed up more space for adding other apps to the favorites section of the menu and lowers the height significantly for short mouse movements. I also removed the "Places" category that came with the Simpler Menu by editing the "applets.js" file that came with it. I am very happy with the new compact menu and each category has no more than 6 apps listed in them and there is no need for scrolling in them except for the All Applications category, which now only has 21 apps. I want to emphasize the point that if you decide to follow this procedure, then you do so at your own risk. First make a copy of the “cinnamon-settings.menu” file in case something goes wrong. I have VirtualBox installed on my computer and I then installed Linux Mint 14 Cinnamon in a virtual environment to test out the procedure before making any permanent changes. I have not experienced any problems yet but I made the changes only two days ago.

This is an update to this message. There is now a better solution to this problem. See my February 27th message below.
Last edited by roblm on Tue Mar 05, 2013 9:21 pm, edited 8 times in total.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby roblm on Sun Feb 24, 2013 6:25 pm

Screenshot 11.png
Preferences category removed.
Screenshot 12.png
Unused applications moved out of Administration category.
Screenshot 13.png
Quit applet.
Last edited by roblm on Tue Mar 05, 2013 9:21 pm, edited 4 times in total.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby violent23 on Sun Feb 24, 2013 11:06 pm

roblm wrote:This is also one of my main gripes with Cinnamon 1.6. The Preferences category is especially bad. Besides listing apps found in other categories, it individually lists all 15 of the apps found in Cinnamon Settings and the 14 apps found in System Settings and of course these are all repeated in the All Applications category. This would be alright if the Preferences and Administration categories could be edited. I like to tweak my menus to be as compact as possible. To my knowledge they could be edited in past versions using Alacarte. I even tried other menu editors like Mozo and Kmenuedit, knowing they probably wouldn't work. My solution was to eliminate the Preferences category. To do this go to "/etc/xdg/menus". Open as root the file "cinnamon-setting.menu". Delete the 10 lines starting with "<- Merge in these other files as submenus ->" up to "</Menu>". Then delete the resulting extra spaces between lines so that there is only one space. Be sure the line "<!- System Settings ->" lines up with the line "<DefaulMergeDirs/>" on the left side. Go down the list and under "<Layout>" delete the line "<Menuname>Preferences</Menuname>". Close the space that forms. Save the new settings and close the file. Do not delete this file hoping to eliminate both the Preferences and Administration categories or your menu will be unusable. Restart Cinnamon and the Preferences category should be gone. Also, all the apps listed under it will disappear from the All Applications category.
Now you will need to replace any removed apps that you may need to access. I added "Cinnamon Settings" and "Startup Applications" to the "System Tools" category. To do this I right clicked the menu button and selected "edit menu". I highlighted "System Tools" on the left and clicked "New Item" on the right. In the "Create Launcher" window I typed "Cinnamon Settings" under "name". For the "command" line, I temporarily left this window open and opened the file manager and went to "/usr/share/applications". I right clicked on "Cinnamon Settings" and selected "properties". I copied the words in the "command" line, which were "cinnamon-settings", and pasted them into the "command" line in the "Create Launcher" window. I then clicked on the icon and selected "icons" on the left and then on the right selected Mint-X>categories>24>gnome-system.png. Click "open" and OK. I repeated the process for the "Startup Applications" app except for the icon I went to icons/Mint-X/apps/24/gnome-session.png. For any other apps in the Administration category you want to remove, then here is a solution. Go to "/usr/share" and create a new folder named "applications-2". Open as root "/usr/share/applications" and move any apps you won't need to open over to the applications-2 folder. I moved "User Accounts" and "Windows Wireless Drivers" as I will not have any immediate need to use them. To make my menu even more compact, I replaced the default Cinnamon Menu with the "Simpler Menu" by downloading the Simpler Menu applet. It eliminates the Quit, Logout and Lock Screen buttons on the menu. I prefer one single button that contains all the options when clicked. I downloaded the "Quit" applet to replace these 3 buttons and it was installed on the panel directly under the menu. This freed up more space for adding other apps to the favorites section of the menu and lowers the height significantly for short mouse movements. I also removed the "Places" category that came with the Simpler Menu by editing the "applets.js" file that came with it. I am very happy with the new compact menu and each category has no more than 6 apps listed in them and there is no need for scrolling in them except for the All Applications category, which now only has 21 apps. I want to emphasize the point that if you decide to follow this procedure, then you do so at your own risk. First make a copy of the “cinnamon-settings.menu” file in case something goes wrong. I have VirtualBox installed on my computer and I then installed Linux Mint 14 Cinnamon in a virtual environment to test out the procedure before making any permanent changes. I have not experienced any problems yet but I made the changes only two days ago. Check out the attached picture of the new menu.


Wow, very useful tips, thanks.

I too use Simpler Menu and the Quit applet. If you wouldn't mind sharing a little bit more depth, what did you edit out of the applets.js for Simpler Menu. If it is too hard to explain could you upload the edited applets.js for me to replace mine as I too do not like the places category.
violent23
Level 1
Level 1
 
Posts: 16
Joined: Sun Sep 05, 2010 10:23 pm

Re: Cinnamon app menu a mess.

Postby roblm on Mon Feb 25, 2013 5:51 pm

To remove the Places category in the Simpler Menu delete 13 lines of code in the first quarter of the applet.js file, from the line
“function PlaceCategoryButton(app) {“
up to and including the line
“Signals.addSignalMethods(PlaceCategoryButton.prototype);”
and the brackets and spaces between these lines. There should then be a space between the line
“Signals.addSignalMethods(CategoryButton.prototype);”
and the line
“function FavoritesButton(appsMenuButton, app, nbFavorites) {“.

Then go down to the last quarter of the file and delete 14 more lines of code, from the line
“this.placesButton = new PlaceCategoryButton();”
up to and including the line
“this.categoriesBox.add_actor(this.placesButton.actor);”
and the brackets and spaces between these lines. There should then be a space between the line
“this._refreshApps();”
and the line
“this.selectedAppBox = new St.BoxLayout({ style_class: 'menu-selected-app-box', vertical: true });”.

Save the settings and close the file. Restart Cinnamon.


Modified "applets.js" file for Simpler Menu is below.
Code: Select all
const Applet = imports.ui.applet;
const Mainloop = imports.mainloop;
const GMenu = imports.gi.GMenu;
const Lang = imports.lang;
const Cinnamon = imports.gi.Cinnamon;
const St = imports.gi.St;
const Clutter = imports.gi.Clutter;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const AppFavorites = imports.ui.appFavorites;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Signals = imports.signals;
const GnomeSession = imports.misc.gnomeSession;
const ScreenSaver = imports.misc.screenSaver;
const FileUtils = imports.misc.fileUtils;
const Util = imports.misc.util;
const Tweener = imports.ui.tweener;
const DND = imports.ui.dnd;
const Meta = imports.gi.Meta;

const ICON_SIZE = 16;
const MAX_FAV_ICON_SIZE = 32;
const CATEGORY_ICON_SIZE = 22;
const APPLICATION_ICON_SIZE = 22;

const USER_DESKTOP_PATH = FileUtils.getUserDesktopDir();

let appsys = Cinnamon.AppSystem.get_default();

function ApplicationContextMenuItem(appButton, label, action) {
    this._init(appButton, label, action);
}

ApplicationContextMenuItem.prototype = {
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,

    _init: function (appButton, label, action) {
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this, {focusOnHover: false});

        this._appButton = appButton;
        this._action = action;
        this.label = new St.Label({ text: label });
        this.addActor(this.label);
    },

    activate: function (event) {
        switch (this._action){
            case "add_to_panel":
                let settings = new Gio.Settings({ schema: 'org.cinnamon' });
                let desktopFiles = settings.get_strv('panel-launchers');
                desktopFiles.push(this._appButton.app.get_id());
                settings.set_strv('panel-launchers', desktopFiles);
                break;
            case "add_to_desktop":
                let file = Gio.file_new_for_path(this._appButton.app.get_app_info().get_filename());
                let destFile = Gio.file_new_for_path(USER_DESKTOP_PATH+"/"+this._appButton.app.get_id());
                try{
                    file.copy(destFile, 0, null, function(){});
                    // Need to find a way to do that using the Gio library, but modifying the access::can-execute attribute on the file object seems unsupported
                    Util.spawnCommandLine("chmod +x \""+USER_DESKTOP_PATH+"/"+this._appButton.app.get_id()+"\"");
                }catch(e){
                    global.log(e);
                }
                break;
            case "add_to_favorites":
                AppFavorites.getAppFavorites().addFavorite(this._appButton.app.get_id());
                break;
            case "remove_from_favorites":
                AppFavorites.getAppFavorites().removeFavorite(this._appButton.app.get_id());
                break;
        }
        this._appButton.actor.grab_key_focus();
        this._appButton.toggleMenu();
        return false;
    }

};

function GenericApplicationButton(appsMenuButton, app) {
    this._init(appsMenuButton, app);
}

GenericApplicationButton.prototype = {
    __proto__: PopupMenu.PopupSubMenuMenuItem.prototype,
   
    _init: function(appsMenuButton, app, withMenu) {
        this.app = app;
        this.appsMenuButton = appsMenuButton;
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this, {hover: false});
       
        this.withMenu = withMenu;
       
        if (this.withMenu){
            this.menu = new PopupMenu.PopupSubMenu(this.actor);
            this.menu.actor.set_style_class_name('menu-context-menu');
            this.menu.connect('open-state-changed', Lang.bind(this, this._subMenuOpenStateChanged));
        }
    },
   
    _onButtonReleaseEvent: function (actor, event) {
        if (event.get_button()==1){
            this.activate(event);
        }
        if (event.get_button()==3){
            this.appsMenuButton.closeApplicationsContextMenus(this.app, true);
            this.toggleMenu();
        }
        return true;
    },
   
    activate: function(event) {
        this.app.open_new_window(-1);
        this.appsMenuButton.menu.close();
    },
   
    closeMenu: function() {
        if (this.withMenu) this.menu.close();
    },
   
    toggleMenu: function() {
        if (!this.withMenu) return;
       
        if (!this.menu.isOpen){
            let children = this.menu.box.get_children();
            for (var i in children){
                children[i].destroy();
            }
            let menuItem;
            menuItem = new ApplicationContextMenuItem(this, _("Add to panel"), "add_to_panel");
            this.menu.addMenuItem(menuItem);
            if (USER_DESKTOP_PATH){
                menuItem = new ApplicationContextMenuItem(this, _("Add to desktop"), "add_to_desktop");
                this.menu.addMenuItem(menuItem);
            }
            if (AppFavorites.getAppFavorites().isFavorite(this.app.get_id())){
                menuItem = new ApplicationContextMenuItem(this, _("Remove from favorites"), "remove_from_favorites");
                this.menu.addMenuItem(menuItem);
            }else{
                menuItem = new ApplicationContextMenuItem(this, _("Add to favorites"), "add_to_favorites");
                this.menu.addMenuItem(menuItem);
            }
        }
        this.menu.toggle();
    },
   
    _subMenuOpenStateChanged: function() {
        if (this.menu.isOpen) this.appsMenuButton._scrollToButton(this.menu);
    }
}

function ApplicationButton(appsMenuButton, app) {
    this._init(appsMenuButton, app);
}

ApplicationButton.prototype = {
    __proto__: GenericApplicationButton.prototype,
   
    _init: function(appsMenuButton, app) {
        GenericApplicationButton.prototype._init.call(this, appsMenuButton, app, true);

        this.actor.add_style_class_name('menu-application-button');
        this.icon = this.app.create_icon_texture(APPLICATION_ICON_SIZE);
        this.addActor(this.icon);
        this.label = new St.Label({ text: this.app.get_name(), style_class: 'menu-application-button-label' });
        this.addActor(this.label);
       
        this._draggable = DND.makeDraggable(this.actor);
        this.isDraggableApp = true;
    },
   
    get_app_id: function() {
        return this.app.get_id();
    },
   
    getDragActor: function() {
        let favorites = AppFavorites.getAppFavorites().getFavorites();
        let nbFavorites = favorites.length;
        let monitorHeight = Main.layoutManager.primaryMonitor.height;
        let real_size = (0.7*monitorHeight) / nbFavorites;
        let icon_size = 0.6*real_size;
        if (icon_size>MAX_FAV_ICON_SIZE) icon_size = MAX_FAV_ICON_SIZE;
        return this.app.create_icon_texture(icon_size);
    },

    // Returns the original actor that should align with the actor
    // we show as the item is being dragged.
    getDragActorSource: function() {
        return this.actor;
    }
};
Signals.addSignalMethods(ApplicationButton.prototype);

function PlaceButton(appsMenuButton, place, button_name) {
    this._init(appsMenuButton, place, button_name);
}

PlaceButton.prototype = {
    _init: function(appsMenuButton,place, button_name) {
this.place = place;
        this.button_name = button_name;
        this.actor = new St.Button({ reactive: true, label: this.button_name, style_class: 'menu-application-button', x_align: St.Align.START });
        this.actor._delegate = this;
        this.buttonbox = new St.BoxLayout();
        this.label = new St.Label({ text: this.button_name, style_class: 'menu-application-button-label' });
        this.icon = place.iconFactory(APPLICATION_ICON_SIZE);
        this.buttonbox.add_actor(this.icon);
        this.buttonbox.add_actor(this.label);
        this.actor.set_child(this.buttonbox);
        this.actor.connect('clicked', Lang.bind(this, function() {
this.place.launch();
            appsMenuButton.menu.close();
}));
    }
};
Signals.addSignalMethods(PlaceButton.prototype);

function CategoryButton(app) {
    this._init(app);
}

CategoryButton.prototype = {
    _init: function(category) {
        var label;
if (category){
           let icon = category.get_icon();
           if (icon && icon.get_names)
               this.icon_name = icon.get_names().toString();
           else
               this.icon_name = "";
           label = category.get_name();
        }else label = _("All Applications");
        this.actor = new St.Button({ reactive: true, label: label, style_class: 'menu-category-button', x_align: St.Align.START });
        this.actor._delegate = this;
        this.buttonbox = new St.BoxLayout();
        this.label = new St.Label({ text: label, style_class: 'menu-category-button-label' });
        if (category && this.icon_name){
           this.icon = new St.Icon({icon_name: this.icon_name, icon_size: CATEGORY_ICON_SIZE, icon_type: St.IconType.FULLCOLOR});
           this.buttonbox.add_actor(this.icon);
        }
        this.buttonbox.add_actor(this.label);
        this.actor.set_child(this.buttonbox);
        //this.actor.set_tooltip_text(category.get_name());
    }
};
Signals.addSignalMethods(CategoryButton.prototype);

function FavoritesButton(appsMenuButton, app, nbFavorites) {
    this._init(appsMenuButton, app, nbFavorites);
}

FavoritesButton.prototype = {
    __proto__: GenericApplicationButton.prototype,
   
    _init: function(appsMenuButton, app, nbFavorites) {
        GenericApplicationButton.prototype._init.call(this, appsMenuButton, app);       
        let monitorHeight = Main.layoutManager.primaryMonitor.height;
        let real_size = (0.7*monitorHeight) / nbFavorites;
        let icon_size = 0.6*real_size;
        if (icon_size>MAX_FAV_ICON_SIZE) icon_size = MAX_FAV_ICON_SIZE;
        this.actor.style = "padding-top: "+(icon_size/3)+"px;padding-bottom: "+(icon_size/3)+"px; margin:auto;"

        this.actor.add_style_class_name('menu-favorites-button');
        this.addActor(app.create_icon_texture(icon_size)); 
       
        this._draggable = DND.makeDraggable(this.actor);     
        this.isDraggableApp = true;
    },
   
    get_app_id: function() {
        return this.app.get_id();
    },
   
    getDragActor: function() {
        return new Clutter.Clone({ source: this.actor });
    },

    // Returns the original actor that should align with the actor
    // we show as the item is being dragged.
    getDragActorSource: function() {
        return this.actor;
    }
};

function SystemButton(appsMenuButton, icon, nbFavorites) {
    this._init(appsMenuButton, icon, nbFavorites);
}

SystemButton.prototype = {
    _init: function(appsMenuButton, icon, nbFavorites) {
        this.actor = new St.Button({ reactive: true, style_class: 'menu-favorites-button' });       
        let monitorHeight = Main.layoutManager.primaryMonitor.height;
        let real_size = (0.7*monitorHeight) / nbFavorites;
        let icon_size = 0.6*real_size;
        if (icon_size>MAX_FAV_ICON_SIZE) icon_size = MAX_FAV_ICON_SIZE;
        this.actor.style = "padding-top: "+(icon_size/3)+"px;padding-bottom: "+(icon_size/3)+"px; margin:auto;"
        let iconObj = new St.Icon({icon_name: icon, icon_size: icon_size, icon_type: St.IconType.FULLCOLOR});
        this.actor.set_child(iconObj);             
    }
};

function CategoriesApplicationsBox() {
    this._init();
}

CategoriesApplicationsBox.prototype = {
    _init: function() {
        this.actor = new St.BoxLayout();
        this.actor._delegate = this;
    },
   
    acceptDrop : function(source, actor, x, y, time) {
        if (source instanceof FavoritesButton){
            AppFavorites.getAppFavorites().removeFavorite(source.app.get_id());
            return true;
        }
        return false;
    }
}

function FavoritesBox() {
    this._init();
}

FavoritesBox.prototype = {
    _init: function() {
        this.actor = new St.BoxLayout({ vertical: true });
        this.actor._delegate = this;
       
        this._dragPlaceholder = null;
        this._dragPlaceholderPos = -1;
        this._animatingPlaceholdersCount = 0;
    },
   
    _clearDragPlaceholder: function() {
        if (this._dragPlaceholder) {
            this._dragPlaceholder.animateOutAndDestroy();
            this._dragPlaceholder = null;
            this._dragPlaceholderPos = -1;
        }
    },
   
    handleDragOver : function(source, actor, x, y, time) {
        let app = source.app;

        // Don't allow favoriting of transient apps
        if (app == null || app.is_window_backed() || (!(source instanceof FavoritesButton) && app.get_id() in AppFavorites.getAppFavorites().getFavoriteMap()))
            return DND.DragMotionResult.NO_DROP;

        let favorites = AppFavorites.getAppFavorites().getFavorites();
        let numFavorites = favorites.length;

        let favPos = favorites.indexOf(app);

        let children = this.actor.get_children();
        let numChildren = children.length;
        let boxHeight = this.actor.height;

        // Keep the placeholder out of the index calculation; assuming that
        // the remove target has the same size as "normal" items, we don't
        // need to do the same adjustment there.
        if (this._dragPlaceholder) {
            boxHeight -= this._dragPlaceholder.actor.height;
            numChildren--;
        }

        let pos = Math.round(y * numFavorites / boxHeight);

        if (pos != this._dragPlaceholderPos && pos <= numFavorites) {
            if (this._animatingPlaceholdersCount > 0) {
                let appChildren = children.filter(function(actor) {
                    return (actor._delegate instanceof FavoritesButton);
                });
                this._dragPlaceholderPos = children.indexOf(appChildren[pos]);
            } else {
                this._dragPlaceholderPos = pos;
            }

            // Don't allow positioning before or after self
            if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
                if (this._dragPlaceholder) {
                    this._dragPlaceholder.animateOutAndDestroy();
                    this._animatingPlaceholdersCount++;
                    this._dragPlaceholder.actor.connect('destroy',
                        Lang.bind(this, function() {
                            this._animatingPlaceholdersCount--;
                        }));
                }
                this._dragPlaceholder = null;

                return DND.DragMotionResult.CONTINUE;
            }

            // If the placeholder already exists, we just move
            // it, but if we are adding it, expand its size in
            // an animation
            let fadeIn;
            if (this._dragPlaceholder) {
                this._dragPlaceholder.actor.destroy();
                fadeIn = false;
            } else {
                fadeIn = true;
            }

            this._dragPlaceholder = new DND.GenericDragPlaceholderItem();
            this._dragPlaceholder.child.set_width (source.actor.height);
            this._dragPlaceholder.child.set_height (source.actor.height);
            this.actor.insert_actor(this._dragPlaceholder.actor,
                                   this._dragPlaceholderPos);
            if (fadeIn)
                this._dragPlaceholder.animateIn();
        }

        let srcIsFavorite = (favPos != -1);

        if (srcIsFavorite)
            return DND.DragMotionResult.MOVE_DROP;

        return DND.DragMotionResult.COPY_DROP;
    },
   
    // Draggable target interface
    acceptDrop : function(source, actor, x, y, time) {
        let app = source.app;

        // Don't allow favoriting of transient apps
        if (app == null || app.is_window_backed()) {
            return false;
        }

        let id = app.get_id();

        let favorites = AppFavorites.getAppFavorites().getFavoriteMap();

        let srcIsFavorite = (id in favorites);

        let favPos = 0;
        let children = this.actor.get_children();
        for (let i = 0; i < this._dragPlaceholderPos; i++) {
            if (this._dragPlaceholder &&
                children[i] == this._dragPlaceholder.actor)
                continue;
           
            if (!(children[i]._delegate instanceof FavoritesButton)) continue;

            let childId = children[i]._delegate.app.get_id();
            if (childId == id)
                continue;
            if (childId in favorites)
                favPos++;
        }

        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
            function () {
                let appFavorites = AppFavorites.getAppFavorites();
                if (srcIsFavorite)
                    appFavorites.moveFavoriteToPos(id, favPos);
                else
                    appFavorites.addFavoriteAtPos(id, favPos);
                return false;
            }));

        return true;
    }
}

function MyApplet(orientation) {
    this._init(orientation);
}

MyApplet.prototype = {
    __proto__: Applet.TextIconApplet.prototype,

    _init: function(orientation) {       
        Applet.TextIconApplet.prototype._init.call(this, orientation);
       
        try {                   
            this.set_applet_tooltip(_("Menu"));
                                   
            this.menuManager = new PopupMenu.PopupMenuManager(this);
            this.menu = new Applet.AppletPopupMenu(this, orientation);
            this.menuManager.addMenu(this.menu);   
                       
            this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
                       
            this.menu.actor.add_style_class_name('menu-background');
            this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));                               
                                   
            this._updateIcon();
           
            global.settings.connect("changed::menu-icon", Lang.bind(this, function() {
                this._updateIcon();
            }));
           
            this.set_applet_label(_("Menu"));                                           
            let menuLabel = global.settings.get_string("menu-text");
            if (menuLabel != "Menu") {
                this.set_applet_label(menuLabel);                 
            }
            global.settings.connect("changed::menu-text", Lang.bind(this, function() {
                    this.set_applet_label(global.settings.get_string("menu-text"));
                }));
            this._searchInactiveIcon = new St.Icon({ style_class: 'menu-search-entry-icon',
                                               icon_name: 'edit-find',
                                               icon_type: St.IconType.SYMBOLIC });
            this._searchActiveIcon = new St.Icon({ style_class: 'menu-search-entry-icon',
                                             icon_name: 'edit-clear',
                                             icon_type: St.IconType.SYMBOLIC });
            this._searchTimeoutId = 0;
            this._searchIconClickedId = 0;
            this._applicationsButtons = new Array();
            this._favoritesButtons = new Array();
            this._selectedItemIndex = null;
            this._previousSelectedItemIndex = null;
            this._activeContainer = null;
            this._applicationsBoxWidth = 0;

            this._display();
            appsys.connect('installed-changed', Lang.bind(this, this._refreshApps));
            AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._refreshFavs));

            this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateToggled)); 
           
           
            this.hover_delay = global.settings.get_int("menu-hover-delay") / 1000;
            global.settings.connect("changed::menu-hover-delay", Lang.bind(this, function() {
                    this.hover_delay = global.settings.get_int("menu-hover-delay") / 1000;
            }));
               
            global.display.connect('overlay-key', Lang.bind(this, function(){
                try{
                    this.menu.toggle();
                }
                catch(e) {
                    global.logError(e);
                }
            }));   
           
            this.edit_menu_item = new Applet.MenuItem(_("Edit menu"), Gtk.STOCK_EDIT, Lang.bind(this, this._launch_editor));
            this._applet_context_menu.addMenuItem(this.edit_menu_item);
                                                                           
        }
        catch (e) {
            global.logError(e);
        }
    },
   
    on_orientation_changed: function (orientation) {
        this.menu.destroy();
        this.menu = new Applet.AppletPopupMenu(this, orientation);
        this.menuManager.addMenu(this.menu);
       
        this.menu.actor.add_style_class_name('menu-background');
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateToggled));
       
        this._display();
    },
   
    _launch_editor: function() {
        Util.spawnCommandLine("cinnamon-menu-editor");
    },
   
    on_applet_clicked: function(event) {
        this.menu.toggle();     
    },       
           
    _onSourceKeyPress: function(actor, event) {
        let symbol = event.get_key_symbol();

        if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
            this.menu.toggle();
            return true;
        } else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) {
            this.menu.close();
            return true;
        } else if (symbol == Clutter.KEY_Down) {
            if (!this.menu.isOpen)
                this.menu.toggle();
            this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false);
            return true;
        } else
            return false;
    },

    _onOpenStateChanged: function(menu, open) {
        if (open) {
            this.actor.add_style_pseudo_class('active');           
      }
        else {
            this.actor.remove_style_pseudo_class('active');           
            if (this.searchActive) {
            this.resetSearch();
            this._select_category(null, this._allAppsCategoryButton);
         }
        }
    },

    destroy: function() {
        this.actor._delegate = null;
        this.menu.destroy();
        this.actor.destroy();
        this.emit('destroy');
    },
   
    _updateIcon: function(){
        let icon_file = global.settings.get_string("menu-icon");
        try{
           this.set_applet_icon_path(icon_file);               
        }catch(e){
           global.log("WARNING : Could not load icon file \""+icon_file+"\" for menu button");
        }
    },

    _onMenuKeyPress: function(actor, event) {

        let symbol = event.get_key_symbol();
       
        if (symbol==Clutter.KEY_Super_L && this.menu.isOpen) {
            this.menu.close();
            return true;
        }

        if (this._activeContainer === null && symbol == Clutter.KEY_Up) {
            this._activeContainer = this.applicationsBox;
            children = this._activeContainer.get_children();
            this._selectedItemIndex = children.length;
        } else if (this._activeContainer === null && symbol == Clutter.KEY_Down) {
            this._activeContainer = this.applicationsBox;
            children = this._activeContainer.get_children();
            this._selectedItemIndex = -1;
        }else if (this._activeContainer === null) {
            this._activeContainer = this.categoriesBox;
            this._selectedItemIndex = -1;
            this._previousSelectedItemIndex = -1;
        }
       
       
        let children = this._activeContainer.get_children();
       
        if (children.length==0){
            this._activeContainer = this.categoriesBox;
            this._selectedItemIndex = -1;
            this._previousSelectedItemIndex = -1;
            children = this._activeContainer.get_children();
        }

        let index = this._selectedItemIndex;

        if (symbol == Clutter.KEY_Up) {
            if (this._activeContainer==this.applicationsBox) index = this._selectedItemIndex - 1 < 0 ? 0 : this._selectedItemIndex - 2;
            else index = this._selectedItemIndex - 1 < 0 ? 0 : this._selectedItemIndex - 1;
        } else if (symbol == Clutter.KEY_Down) {
            if (this._activeContainer==this.applicationsBox && this._selectedItemIndex!=-1) index = this._selectedItemIndex + 2 >= children.length ? children.length - 2 : this._selectedItemIndex + 2;
            else index = this._selectedItemIndex + 1 == children.length ? children.length - 1 : this._selectedItemIndex + 1;
        } else if (symbol == Clutter.KEY_Right && this._activeContainer === this.categoriesBox) {
            this._activeContainer = this.applicationsBox;
            children = this._activeContainer.get_children();
            index = 0;
            this._previousSelectedItemIndex = this._selectedItemIndex;
            this._selectedItemIndex = -1;
        } else if (symbol == Clutter.KEY_Left && this._activeContainer === this.applicationsBox && !this.searchActive) {
            this._clearSelections(this.applicationsBox);
            this._activeContainer = this.categoriesBox;
            children = this._activeContainer.get_children();
            index = this._previousSelectedItemIndex;
            this._selectedItemIndex = -1;
        } else if (this._activeContainer === this.applicationsBox && (symbol == Clutter.KEY_Return || symbol == Clutter.KP_Enter)) {
            let item_actor = children[this._selectedItemIndex];
            item_actor._delegate.activate();
            return true;
        } else {
            return false;
        }

        if (index == this._selectedItemIndex) {
            return true;
        }
       
        if (this._activeContainer==this.applicationsBox){
            if (index>=children.length-1) index = children.length-2;
        }else{
            if (index>=children.length) index = children.length-1;
        }

        this._selectedItemIndex = index;
        let item_actor = children[this._selectedItemIndex];

        if (!item_actor || item_actor === this.searchEntry) {
            return false;
        }

        item_actor._delegate.emit('enter-event');
        return true;
    },

    _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);
    },

    _clearSelections: function(container) {
        container.get_children().forEach(function(actor) {
            actor.style_class = "menu-category-button";
        });
    },

    _onOpenStateToggled: function(menu, open) {
       if (open) {
           global.stage.set_key_focus(this.searchEntry);
           this._selectedItemIndex = null;
           this._activeContainer = null;
           let monitorHeight = Main.layoutManager.primaryMonitor.height;
           let applicationsBoxHeight = this.applicationsBox.get_allocation_box().y2-this.applicationsBox.get_allocation_box().y1;
           let scrollBoxHeight = (this.leftBox.get_allocation_box().y2-this.leftBox.get_allocation_box().y1)                                   
                                    -(this.searchBox.get_allocation_box().y2-this.searchBox.get_allocation_box().y1);           
           // if (scrollBoxHeight < (0.2*monitorHeight)  &&  (scrollBoxHeight < applicationsBoxHeight)) {
             //    scrollBoxHeight = Math.min(0.2*monitorHeight, applicationsBoxHeight);
            // }
            this.applicationsScrollBox.style = "height: "+scrollBoxHeight+"px;";
       } else {
           this.closeApplicationsContextMenus(null, false);
           //this.resetSearch();
           //this._clearSelections(this.categoriesBox);
           //this._clearSelections(this.applicationsBox);
       }
    },
   
    _refreshApps : function() {
        this._applicationsButtons = new Array();
        this._applicationsBoxWidth = 0;
       
        //Remove all categories
       this.categoriesBox.get_children().forEach(Lang.bind(this, function (child) {
            child.destroy();
        }));
       
        this._allAppsCategoryButton = new CategoryButton(null);
             this._allAppsCategoryButton.actor.connect('clicked', Lang.bind(this, function() {
            this._select_category(null, this._allAppsCategoryButton);
         }));
         this._addEnterEvent(this._allAppsCategoryButton, Lang.bind(this, function() {
             if (!this.searchActive) {
                 this._allAppsCategoryButton.isHovered = true;
                 Tweener.addTween(this, {
                        time: this.hover_delay,
                        onComplete: function () {
                            if (this._allAppsCategoryButton.isHovered) {
                                this._select_category(null, this._allAppsCategoryButton);
                            }
                        }
                 });
            }
         }));
         this._allAppsCategoryButton.actor.connect('leave-event', Lang.bind(this, function () {
            this._allAppsCategoryButton.isHovered = false;
         }));
         this.categoriesBox.add_actor(this._allAppsCategoryButton.actor);
       
        let trees = [appsys.get_tree(), appsys.get_settings_tree()];
       
        for (var i in trees) {
            let tree = trees[i];
            let root = tree.get_root_directory();
           
            let iter = root.iter();
            let nextType;
            while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
                if (nextType == GMenu.TreeItemType.DIRECTORY) {
                    let dir = iter.get_directory();
                    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 categoryButton = new CategoryButton(dir);
                       categoryButton.actor.connect('clicked', Lang.bind(this, function() {
                         this._select_category(dir, categoryButton);
                      }));
                      this._addEnterEvent(categoryButton, Lang.bind(this, function() {
                          if (!this.searchActive) {
                             categoryButton.isHovered = true;
                             Tweener.addTween(this, {
                                time: this.hover_delay,
                                onComplete: function () {
                                    if (categoryButton.isHovered) {
                                        this._select_category(dir, categoryButton);
                                    }
                                }
                             });
                          }
                      }));
                      categoryButton.actor.connect('leave-event', function () {
                            categoryButton.isHovered = false;
                      });
                      this.categoriesBox.add_actor(categoryButton.actor);
                    }
                }
            }
        }
       
        this._select_category(null, this._allAppsCategoryButton);   
        this._setCategoriesButtonActive(!this.searchActive);                 
    },
   
    _refreshFavs : function() {        
       //Remove all favorites
       this.leftBox.get_children().forEach(Lang.bind(this, function (child) {
            child.destroy();
        }));
       
        let favoritesBox = new FavoritesBox();
        this.leftBox.add_actor(favoritesBox.actor, { y_align: St.Align.END, y_fill: false });
       
        //Load favorites again
        this._favoritesButtons = new Array();
        let launchers = global.settings.get_strv('favorite-apps');
        let appSys = Cinnamon.AppSystem.get_default();
        let j = 0;
        for ( let i = 0; i < launchers.length; ++i ) {
            let app = appSys.lookup_app(launchers[i]);
            if (!app) app = appSys.lookup_settings_app(launchers[i]);
            if (app) {
                let button = new FavoritesButton(this, app, launchers.length +3); // + 3 because we're adding 3 system buttons at the bottom
                this._favoritesButtons[app] = button;
                favoritesBox.actor.add_actor(button.actor, { y_align: St.Align.END, y_fill: false });
                button.actor.connect('enter-event', Lang.bind(this, function() {
                   this.selectedAppTitle.set_text(button.app.get_name());
                   if (button.app.get_description()) this.selectedAppDescription.set_text(button.app.get_description());
                   else this.selectedAppDescription.set_text("");
                }));
                button.actor.connect('leave-event', Lang.bind(this, function() {
                   this.selectedAppTitle.set_text("");
                   this.selectedAppDescription.set_text("");
                }));
                ++j;
            }
        }

               
    },
   
    _loadCategory: function(dir, top_dir) {
        var iter = dir.iter();
        var nextType;
        if (!top_dir) top_dir = dir;
        while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
            if (nextType == GMenu.TreeItemType.ENTRY) {
                var entry = iter.get_entry();
                if (!entry.get_app_info().get_nodisplay()) {
               var app = appsys.lookup_app_by_tree_entry(entry);
                    if (!app) app = appsys.lookup_settings_app_by_tree_entry(entry);
                    if (!this.applicationsByCategory[top_dir.get_menu_id()]) this.applicationsByCategory[top_dir.get_menu_id()] = new Array();
               this.applicationsByCategory[top_dir.get_menu_id()].push(app);
            }
            } else if (nextType == GMenu.TreeItemType.DIRECTORY) {
                this._loadCategory(iter.get_directory(), top_dir);
            }
        }
    },
   
    _scrollToButton: function(button) {
        var current_scroll_value = this.applicationsScrollBox.get_vscroll_bar().get_adjustment().get_value();
        var box_height = this.applicationsScrollBox.get_allocation_box().y2-this.applicationsScrollBox.get_allocation_box().y1;
        var new_scroll_value = current_scroll_value;
        if (current_scroll_value > button.actor.get_allocation_box().y1-10) new_scroll_value = button.actor.get_allocation_box().y1-10;
        if (box_height+current_scroll_value < button.actor.get_allocation_box().y2+10) new_scroll_value = button.actor.get_allocation_box().y2-box_height+10;
        if (new_scroll_value!=current_scroll_value) this.applicationsScrollBox.get_vscroll_bar().get_adjustment().set_value(new_scroll_value);
    },
               
    _display : function() {
        this._activeContainer = null;
        let section = new PopupMenu.PopupMenuSection();
        this.menu.addMenuItem(section);
       
        let leftPane = new St.BoxLayout({ vertical: true });
                 
        this.leftBox = new St.BoxLayout({ style_class: 'menu-favorites-box', vertical: true });       
       
        this._session = new GnomeSession.SessionManager();
        this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();           
                                       
        leftPane.add_actor(this.leftBox, { y_align: St.Align.END, y_fill: false });       
       
        let rightPane = new St.BoxLayout({ vertical: true });
       
        this.searchBox = new St.BoxLayout({ style_class: 'menu-search-box' });
        rightPane.add_actor(this.searchBox);
       
        this.searchEntry = new St.Entry({ name: 'menu-search-entry',
                                     hint_text: _("Type to search..."),
                                     track_hover: true,
                                     can_focus: true });
        this.searchEntry.set_secondary_icon(this._searchInactiveIcon);
        this.searchBox.add_actor(this.searchEntry);
        this.searchActive = false;
        this.searchEntryText = this.searchEntry.clutter_text;
        this.searchEntryText.connect('text-changed', Lang.bind(this, this._onSearchTextChanged));
        this.searchEntryText.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
        this._previousSearchPattern = "";

        this.categoriesApplicationsBox = new CategoriesApplicationsBox();
        rightPane.add_actor(this.categoriesApplicationsBox.actor);
        this.categoriesBox = new St.BoxLayout({ style_class: 'menu-categories-box', vertical: true });
        this.applicationsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, y_align: St.Align.START, style_class: 'vfade menu-applications-scrollbox' });
       
        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.applicationsBox = new St.BoxLayout({ style_class: 'menu-applications-box', vertical:true });
        this.applicationsScrollBox.add_actor(this.applicationsBox);
        this.applicationsScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
        this.categoriesApplicationsBox.actor.add_actor(this.categoriesBox);
        this.categoriesApplicationsBox.actor.add_actor(this.applicationsScrollBox);
                     
        this._refreshFavs();
                                                         
        this.mainBox = new St.BoxLayout({ style_class: 'menu-applications-box', vertical:false });       
               
        this.mainBox.add_actor(leftPane, { span: 1 });
        this.mainBox.add_actor(rightPane, { span: 1 });
       
        section.actor.add_actor(this.mainBox);
       
      this.applicationsByCategory = {};
        this._refreshApps();
                       
        this.selectedAppBox = new St.BoxLayout({ style_class: 'menu-selected-app-box', vertical: true });
        this.selectedAppTitle = new St.Label({ style_class: 'menu-selected-app-title', text: "" });
        this.selectedAppBox.add_actor(this.selectedAppTitle);
        this.selectedAppDescription = new St.Label({ style_class: 'menu-selected-app-description', text: "" });
        this.selectedAppBox.add_actor(this.selectedAppDescription);
        section.actor.add_actor(this.selectedAppBox);
    },
   
    _clearApplicationsBox: function(selectedActor){
       let actors = this.applicationsBox.get_children();
      for (var i=0; i<actors.length; i++) {
         let actor = actors[i];
         this.applicationsBox.remove_actor(actor);
      }
             
       let actors = this.categoriesBox.get_children();

         for (var i=0; i<actors.length; i++){
             let actor = actors[i];
             if (this.searchActive) actor.style_class = "menu-category-button-greyed";
             else if (actor==selectedActor) actor.style_class = "menu-category-button-selected";
             else actor.style_class = "menu-category-button";
         }
    },
   
    _select_category : function(dir, categoryButton) {
          this.resetSearch();
          this._clearApplicationsBox(categoryButton.actor);
          if (dir) this._displayButtons(this._listApplications(dir.get_menu_id()));
          else this._displayButtons(this._listApplications(null));
           this.closeApplicationsContextMenus(null, false);
   },
   
    closeApplicationsContextMenus: function(excludeApp, animate) {
        for (var app in this._applicationsButtons){
            if (app!=excludeApp && this._applicationsButtons[app].menu.isOpen){
                if (animate)
                    this._applicationsButtons[app].toggleMenu();
                else
                    this._applicationsButtons[app].closeMenu();
            }
        }
    },
   
    _onApplicationButtonRealized: function(actor) {
        if (actor.get_width() > this._applicationsBoxWidth){
            this._applicationsBoxWidth = actor.get_width();
            this.applicationsBox.set_width(this._applicationsBoxWidth);
        }
    },
   
    _displayButtons: function(apps, places){
         if (apps){
            for (var i=0; i<apps.length; i++) {
               let app = apps[i];
               if (!this._applicationsButtons[app]){
                  let applicationButton = new ApplicationButton(this, app);
                  applicationButton.actor.connect('realize', Lang.bind(this, this._onApplicationButtonRealized));
                  applicationButton.actor.connect('leave-event', Lang.bind(this, function() {
                     this.selectedAppTitle.set_text("");
                     this.selectedAppDescription.set_text("");
                  }));
                  this._addEnterEvent(applicationButton, Lang.bind(this, function() {
                      this.selectedAppTitle.set_text(applicationButton.app.get_name());
                      if (applicationButton.app.get_description()) this.selectedAppDescription.set_text(applicationButton.app.get_description());
                      else this.selectedAppDescription.set_text("");
                      this._clearSelections(this.applicationsBox);
                      applicationButton.actor.style_class = "menu-category-button-selected";
                      this._scrollToButton(applicationButton);
                  }));
                  this._applicationsButtons[app] = applicationButton;
               }
               this.applicationsBox.add_actor(this._applicationsButtons[app].actor);
               this.applicationsBox.add_actor(this._applicationsButtons[app].menu.actor);
            }
         }

         if (places){
            for (var i=0; i<places.length; i++) {
               let place = places[i];
               let button = new PlaceButton(this, place, place.name);
               this._addEnterEvent(button, Lang.bind(this, function() {
                   this._clearSelections(this.applicationsBox);
                   button.actor.style_class = "menu-category-button-selected";
                   this._scrollToButton(button);
               }));
               this.applicationsBox.add_actor(button.actor);
            }
         }
    },
     
     _select_places : function(button) {
         this.resetSearch();
       this._clearApplicationsBox(button.actor);
               
         let bookmarks = this._listBookmarks();
         let devices = this._listDevices();
         this._displayButtons(null, bookmarks.concat(devices));
    },       
     
     _setCategoriesButtonActive: function(active) {         
         try{
             let categoriesButtons = this.categoriesBox.get_children();
             for (var i in categoriesButtons){
                 let button = categoriesButtons[i];
                 let icon = button._delegate.icon;
                 if (active){
                     button.remove_style_class_name("menu-category-button-greyed");
                     button.add_style_class_name("menu-category-button");
                 }else{
                     button.remove_style_class_name("menu-category-button");
                     button.add_style_class_name("menu-category-button-greyed");
                 }
             }
        }catch(e){
             global.log(e);
        }
     },
     
     resetSearch: function(){
        this.searchEntry.set_text("");
        this.searchActive = false;
        this._setCategoriesButtonActive(true);
        global.stage.set_key_focus(this.searchEntry);
     },
     
     _onSearchTextChanged: function (se, prop) {
        this._clearSelections(this.categoriesBox);
        this._clearSelections(this.applicationsBox);
        this.searchActive = this.searchEntry.get_text() != '';
        if (this.searchActive) {
            this.searchEntry.set_secondary_icon(this._searchActiveIcon);

            if (this._searchIconClickedId == 0) {
                this._searchIconClickedId = this.searchEntry.connect('secondary-icon-clicked',
                    Lang.bind(this, function() {
                        this.resetSearch();       
                        this._select_category(null, this._allAppsCategoryButton);                 
                    }));
            }
           
            this._setCategoriesButtonActive(false);
        } else {
            if (this._searchIconClickedId > 0)
                this.searchEntry.disconnect(this._searchIconClickedId);
            this._searchIconClickedId = 0;

            this.searchEntry.set_secondary_icon(this._searchInactiveIcon);
           
            this._setCategoriesButtonActive(true);
        }
        if (!this.searchActive) {
            if (this._searchTimeoutId > 0) {
                Mainloop.source_remove(this._searchTimeoutId);
                this._searchTimeoutId = 0;
            }
            return;
        }
        if (this._searchTimeoutId > 0)
            return;
        this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, this._doSearch));
    },
   
    _listBookmarks: function(pattern){
       let bookmarks = Main.placesManager.getBookmarks();
       var res = new Array();
       for (let id = 0; id < bookmarks.length; id++) {
          if (!pattern || bookmarks[id].name.toLowerCase().indexOf(pattern)!=-1) res.push(bookmarks[id]);
       }
       return res;
    },
   
    _listDevices: function(pattern){
       let devices = Main.placesManager.getMounts();
       var res = new Array();
       for (let id = 0; id < devices.length; id++) {
          if (!pattern || devices[id].name.toLowerCase().indexOf(pattern)!=-1) res.push(devices[id]);
       }
       return res;
    },
   
    _listApplications: function(category_menu_id, pattern){
       var applist;
       if (category_menu_id) applist = this.applicationsByCategory[category_menu_id];
       else{
          applist = new Array();
          for (directory in this.applicationsByCategory) applist = applist.concat(this.applicationsByCategory[directory]);
       }
       
       var res;
       if (pattern){
          res = new Array();
          for (var i in applist){
             let app = applist[i];
             if (app.get_name().toLowerCase().indexOf(pattern)!=-1 || (app.get_description() && app.get_description().toLowerCase().indexOf(pattern)!=-1) || (app.get_id() && app.get_id().slice(0, -8).toLowerCase().indexOf(pattern)!=-1)) res.push(app);
          }
       }else res = applist;
       
       res.sort(function(a,b){
          return a.get_name().toLowerCase() > b.get_name().toLowerCase();
       });
       
       return res;
    },
   
    _doSearch: function(){
       this._searchTimeoutId = 0;
       let pattern = this.searchEntryText.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '').toLowerCase();
       if (pattern==this._previousSearchPattern) return false;
       this._previousSearchPattern = pattern;
       
       this._activeContainer = null;
       this._selectedItemIndex = null;
       this._previousSelectedItemIndex = null;
       
       // _listApplications returns all the applications when the search
       // string is zero length. This will happend if you type a space
       // in the search entry.
       if (pattern.length == 0) {
           return false;
       }

       var appResults = this._listApplications(null, pattern);
       
       var placesResults = new Array();
       
       var bookmarks = this._listBookmarks(pattern);
       for (var i in bookmarks) placesResults.push(bookmarks[i]);
       
       var devices = this._listDevices(pattern);
       for (var i in devices) placesResults.push(devices[i]);
       
       this._clearApplicationsBox();
       this._displayButtons(appResults, placesResults);
       
       let applicationsBoxChilren = this.applicationsBox.get_children();
       if (applicationsBoxChilren.length>0){
           this._activeContainer = this.applicationsBox;
           this._selectedItemIndex = 0;
           let item_actor = applicationsBoxChilren[this._selectedItemIndex];
           if (item_actor && item_actor !== this.searchEntry) {
               item_actor._delegate.emit('enter-event');
           }
       }

       return false;
    }
   
   
};

function main(metadata, orientation) { 
    let myApplet = new MyApplet(orientation);
    return myApplet;     
}
Last edited by roblm on Tue Mar 05, 2013 9:38 pm, edited 6 times in total.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby roblm on Wed Feb 27, 2013 7:03 pm

This is an important update to the message I previously posted on February 24. I have been working on the problem of not being able to edit the Preferences and Administration categories in the Linux Mint 14.1 Cinnamon menu. I now have a better solution which will allow you to edit both of these categories. To enable this go to “/etc/xdg/menus”. Right click the file “cinnamon-settings.menu” and select “Open as Root”. Open the file and copy 21 lines of code starting with line
“<!-- Merge in these other files as submenus -->”
up to and including the line
“</Menu> <!-- End System Settings -->”.
Close the file. In the same folder open the file “ cinnamon-applications.menu”. Paste the previously copied lines into the space between any two sections of code in the bottom section of the file. I put mine between the “ <!-- System Tools-->” section and the “ <!-- Other -->” section. There should be a space above the first pasted line and a space below the last pasted line. Now two lines that were just pasted need to be changed. In the line
“<!-- Merge in these other files as submenus -->” remove the words and type “Settings” so that the new line will read “<!-- Settings -->”. The line “</Menu>” will be changed to “</Menu> <!-- End Settings -->”. Save the new settings and close the file. Reopen the file “cinnamon-settings.menu” and now delete the 21 lines that you previously were asked to copy. There will then be a space between “<DefaultMergeDirs/>” and “<Layout>”. Save the settings and close the file. Restart Cinnamon by pressing the keys Alt+F2 at the same time and in the command window type r. You should now be able to edit the Preferences and Administration categories in the menu.

If anyone followed the instructions on my February 24th posting, then you will not have the original “cinnamon-settings.menu” file because some of the lines were deleted. Hopefully you made a copy of the file before making the alteration. I have posted an original file below. Also, you can move the contents in the folder “/user/share/applications-2” back to /user/share/applications” and then delete the applications-2 folder. I have also posted the modified "cinnamon-applications.menu" and "cinnamon-settings.menu" files below.


Original "cinnamon-settings.menu" file is below:

Code: Select all
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
 "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">

<Menu>

  <Name>Desktop</Name>
  <Directory>cinnamon-menu-system.directory</Directory>

  <!-- Read standard .directory and .desktop file locations -->
  <DefaultAppDirs/>
  <DefaultDirectoryDirs/>

  <!-- Read in overrides and child menus from applications-merged/ -->
  <DefaultMergeDirs/>
 
  <!-- Merge in these other files as submenus -->
  <Menu>
    <Name>Preferences</Name>
    <Directory>cinnamon-settings.directory</Directory>
    <Include>
      <And>
        <Category>Settings</Category>
      </And>
    </Include>
  </Menu>

  <!-- System Settings -->
  <Menu>
    <Name>Administration</Name>
    <Directory>cinnamon-settings-system.directory</Directory>
    <Include>
      <And>
        <Category>Settings</Category>
        <Category>System</Category>
      </And>
    </Include>
  </Menu>     <!-- End System Settings -->

  <Layout>
    <Menuname>Preferences</Menuname>
    <Menuname>Administration</Menuname>
    <Merge type="menus"/>
    <Merge type="files"/>
  </Layout>

</Menu> <!-- End Settings -->




Modified "cinnamon-settings.menu" file is below:

Code: Select all
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
 "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">

<Menu>

  <Name>Desktop</Name>
  <Directory>cinnamon-menu-system.directory</Directory>

  <!-- Read standard .directory and .desktop file locations -->
  <DefaultAppDirs/>
  <DefaultDirectoryDirs/>

  <!-- Read in overrides and child menus from applications-merged/ -->
  <DefaultMergeDirs/>

  <Layout>
    <Menuname>Preferences</Menuname>
    <Menuname>Administration</Menuname>
    <Merge type="menus"/>
    <Merge type="files"/>
  </Layout>

</Menu> <!-- End Settings -->




Modified "cinnamon-applications.menu" file is below:

Code: Select all
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
 "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">

<Menu>

  <Name>Applications</Name>
  <Directory>cinnamon-menu-applications.directory</Directory>

  <!-- Scan legacy dirs first, as later items take priority -->
  <KDELegacyDirs/>
  <LegacyDir>/etc/X11/applnk</LegacyDir>
  <LegacyDir>/usr/share/cinnamon/apps</LegacyDir>

  <!-- Read standard .directory and .desktop file locations -->
  <DefaultAppDirs/>
  <DefaultDirectoryDirs/>

  <!-- Read in overrides and child menus from applications-merged/ -->
  <DefaultMergeDirs/>

  <!-- Accessories submenu -->
  <Menu>
    <Name>Accessories</Name>
    <Directory>cinnamon-utility.directory</Directory>
    <Include>
      <And>
        <Category>Utility</Category>
   <!-- Accessibility spec must have either the Utility or Settings
        category, and we display an accessibility submenu already for
        the ones that do not have Settings, so don't display accessibility
        applications here -->
        <Not><Category>Accessibility</Category></Not>
        <Not><Category>System</Category></Not>
      </And>
    </Include>
  </Menu> <!-- End Accessories -->

  <!-- Accessibility submenu -->
  <Menu>
    <Name>Universal Access</Name>
    <Directory>cinnamon-utility-accessibility.directory</Directory>
    <Include>
      <And>
        <Category>Accessibility</Category>
        <Not><Category>Settings</Category></Not>
      </And>
    </Include>
  </Menu> <!-- End Accessibility -->

  <!-- Development Tools -->
  <Menu>
    <Name>Development</Name>
    <Directory>cinnamon-development.directory</Directory>
    <Include>
      <And>
        <Category>Development</Category>
      </And>
      <Filename>emacs.desktop</Filename>
    </Include>
  </Menu> <!-- End Development Tools -->

  <!-- Education -->
  <Menu>
    <Name>Education</Name>
    <Directory>cinnamon-education.directory</Directory>
    <Include>
      <And>
        <Category>Education</Category>
      </And>
    </Include>
  </Menu> <!-- End Education -->

  <!-- Games -->
  <Menu>
    <Name>Games</Name>
    <Directory>cinnamon-game.directory</Directory>
    <Include>
      <And>
        <Category>Game</Category>
      </And>
    </Include>
  </Menu> <!-- End Games -->

  <!-- Graphics -->
  <Menu>
    <Name>Graphics</Name>
    <Directory>cinnamon-graphics.directory</Directory>
    <Include>
      <And>
        <Category>Graphics</Category>
      </And>
    </Include>
  </Menu> <!-- End Graphics -->

  <!-- Internet -->
  <Menu>
    <Name>Internet</Name>
    <Directory>cinnamon-network.directory</Directory>
    <Include>
      <And>
        <Category>Network</Category>
      </And>
    </Include>
  </Menu>   <!-- End Internet -->

  <!-- Multimedia -->
  <Menu>
    <Name>Multimedia</Name>
    <Directory>cinnamon-audio-video.directory</Directory>
    <Include>
      <And>
        <Category>AudioVideo</Category>
      </And>
    </Include>
  </Menu>   <!-- End Multimedia -->

  <!-- Office -->
  <Menu>
    <Name>Office</Name>
    <Directory>cinnamon-office.directory</Directory>
    <Include>
      <And>
        <Category>Office</Category>
      </And>
    </Include>
  </Menu> <!-- End Office -->

  <!-- System Tools-->
  <Menu>
    <Name>System</Name>
    <Directory>cinnamon-system-tools.directory</Directory>
    <Include>
      <And>
        <Category>System</Category>
        <Not><Category>Settings</Category></Not>
      </And>
    </Include>
  </Menu>   <!-- End System Tools -->

  <!-- Settings -->
  <Menu>
    <Name>Preferences</Name>
    <Directory>cinnamon-settings.directory</Directory>
    <Include>
      <And>
        <Category>Settings</Category>
      </And>
    </Include>
  </Menu> <!-- End Settings -->

  <!-- System Settings -->
  <Menu>
    <Name>Administration</Name>
    <Directory>cinnamon-settings-system.directory</Directory>
    <Include>
      <And>
        <Category>Settings</Category>
        <Category>System</Category>
      </And>
    </Include>
  </Menu>     <!-- End System Settings -->
 
  <!-- Other -->
  <Menu>
    <Name>Other</Name>
    <Directory>cinnamon-other.directory</Directory>
    <OnlyUnallocated/>
    <Include>
      <And>
        <Not><Category>Core</Category></Not>
        <Not><Category>Settings</Category></Not>
        <Not><Category>Screensaver</Category></Not>
      </And>
    </Include>
  </Menu> <!-- End Other -->
 
   <!-- Wine -->
  <Menu>
    <Name>Wine</Name>
    <Directory>wine-wine.directory</Directory>
    <Include>
      <And>
        <Category>Wine</Category>
      </And>
    </Include>
  </Menu> <!-- End Wine -->

</Menu> <!-- End Applications -->
Attachments
Menu Screenshot 4.png
Last edited by roblm on Thu Feb 28, 2013 9:11 pm, edited 7 times in total.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby roblm on Wed Feb 27, 2013 7:27 pm

Screenshot menu-editor.png
Preferences and Administration categories are now displayed in the Menu Editor window.
Screenshot 10.png
Now the categories in the menu can be lined up in the correct alphabetical order.
Screenshot 9.png
If you make a new category, it can now be moved to the bottom of the list for quick access. The default menu had Preferences and Administration in a fixed position at the bottom. Some people may prefer to have their favorites list displayed with icons and text instead of just plain icons, to more easily recognize them.
Last edited by roblm on Wed Mar 06, 2013 8:56 am, edited 9 times in total.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby violent23 on Wed Feb 27, 2013 8:43 pm

roblm wrote:Now the categories in the menu can be lined up in the correct alphabetical order.


Can't wait to try this. One question, are all the categories now editable in the Cinnamon edit menu app?
violent23
Level 1
Level 1
 
Posts: 16
Joined: Sun Sep 05, 2010 10:23 pm

Re: Cinnamon app menu a mess.

Postby roblm on Wed Feb 27, 2013 9:37 pm

All the categories can be edited now by either right clicking on menu or clicking on the Cinnamon Menu Editor app.

One problem I just noticed is that when I pasted the contents of the 3 files into the text window, the original formatting was correct, but after clicking on the submit button then some of the formatting was changed. Every line now is lined up with the left margin. When I click on the edit button all of the original formatting shows up correctly in the text window. I just took a screenshot of the original cinnamon-settings.menu file contents and uploaded the picture below.
To test these files with the changed format, I ran Linux Mint in a virtual environment with the VirtualBox program. I did not notice any change in the operation of the menu.
Attachments
cinnamon-settings.menu.png
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby violent23 on Thu Feb 28, 2013 10:38 am

roblm wrote:All the categories can be edited now by either right clicking on menu or clicking on the Cinnamon Menu Editor app.

One problem I just noticed is that when I pasted the contents of the 3 files into the text window, the original formatting was correct, but after clicking on the submit button then some of the formatting was changed. Every line now is lined up with the left margin. When I click on the edit button all of the original formatting shows up correctly in the text window. I just took a screenshot of the original cinnamon-settings.menu file contents and uploaded the picture below.
To test these files with the changed format, I ran Linux Mint in a virtual environment with the VirtualBox program. I did not notice any change in the operation of the menu.


You could always edit the post and put the code text in a code box. It's the fifth option from the left.

Code: Select all
like this
violent23
Level 1
Level 1
 
Posts: 16
Joined: Sun Sep 05, 2010 10:23 pm

Re: Cinnamon app menu a mess.

Postby roblm on Thu Feb 28, 2013 9:22 pm

I used your suggestion about using the code option and made the changes to the 3 files listed in the February 27th post. The formatting appears correct now.
I had planned to send the 3 files as attachments, which also worked. This topic is actually the first time I have responded in the linux forum so I was not familiar with the options above the text window.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby violent23 on Thu Feb 28, 2013 9:36 pm

Great work roblm. Glad to have a way to fix this broken menu and it's editing app.
violent23
Level 1
Level 1
 
Posts: 16
Joined: Sun Sep 05, 2010 10:23 pm

Re: Cinnamon app menu a mess.

Postby roblm on Thu Feb 28, 2013 11:04 pm

Here is another menu option for those who prefer text only.
Menu Screenshot 8.png

Here is an extreme menu option for those who prefer to type all of their commands.
cinnamon menu extreme.png


Check my post in this topic for more ways to customize the Cinnamon menu:
viewtopic.php?f=199&t=129524
Last edited by roblm on Fri Mar 21, 2014 5:33 pm, edited 2 times in total.
User avatar
roblm
Level 4
Level 4
 
Posts: 433
Joined: Sun Feb 24, 2013 2:41 pm

Re: Cinnamon app menu a mess.

Postby Chris_Z on Tue Mar 05, 2013 10:33 am

"Why are the apps in Administration duplicated in Preferences?"

It's a bug:

https://github.com/linuxmint/Cinnamon/issues/1217
Chris_Z
Level 1
Level 1
 
Posts: 14
Joined: Sun Dec 16, 2012 4:18 pm
Location: Stockholm, Sweden

Linux Mint is funded by ads and donations.
 

Return to Cinnamon

Who is online

Users browsing this forum: No registered users and 8 guests