help with a cinnamon applet (custom menu) development

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

help with a cinnamon applet (custom menu) development

Postby karlitos on Mon Mar 19, 2012 4:49 pm

Hi

I made a simple applet, which calls a gtk menu some days ago. I admit, that it is not the best solution for my idea, but it works somehow. Now I am trying to achieve same results by using pure javascript. But I allready went into some problems and in addition I have do not yet have idea how to solve some of the issues. So if anybody could help me a little, that will be very nice.

1. The entries in the menu are displayed nice. But nothing happens after I click them. I compared my code with some other applets, but I do not understand what is going wrong by me.

2. How can I create sub-menus ?

3. I store now the menu-entries directly in my code, which is quite sub-optimal. I could use some flat text-file, XML ... but what other solution would be good/state-of-the-art ?

Here is the code :
Code: Select all
const St = imports.gi.St;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Applet = imports.ui.applet;

const Gettext = imports.gettext;
const _ = Gettext.gettext;

let ICON_SIZE = 22;

// array which defines the menu entries
let itemList = new Array(); // regular array

itemList[0] = ["reload","Refresh the package index","gksu apt-get update"]; // literal array
itemList[1] = ["text-editor","Edit: /etc/default/grub","gksu gedit /etc/default/grub"]; // literal array
itemList[2] = ["separator"];
itemList[3] = ["text-editor","Edit: /etc/fstab","gksu gedit /etc/fstab"]; // literal array
itemList[4] = ["text-editor","Editor: ","gedit"]; // literal array


function MyPopupMenuItem()
{
   this._init.apply(this, arguments);
}

MyPopupMenuItem.prototype =
{
      __proto__: PopupMenu.PopupBaseMenuItem.prototype,
      _init: function(icon, text, params)
      {
         PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
         this.icon = icon;
         this.addActor(this.icon);
         this.label = new St.Label({ text: text });
         this.addActor(this.label);
      }
};

function MyMenu(launcher, orientation) {
   this._init(launcher, orientation);
}

MyMenu.prototype = {
      __proto__: PopupMenu.PopupMenu.prototype,

      _init: function(launcher, orientation) {
         this._launcher = launcher;       

         PopupMenu.PopupMenu.prototype._init.call(this, launcher.actor, 0.0, orientation, 0);
         Main.uiGroup.add_actor(this.actor);
         this.actor.hide();           
      }
};

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

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

      _init: function(orientation) {
         Applet.IconApplet.prototype._init.call(this, orientation);

         try {
                                this.set_applet_icon_symbolic_name("go-up");
                                this.set_applet_icon_name("gnome-gmenu");
                                this.set_applet_tooltip(_("launch a custom gtk menu"));

            this.menuManager = new PopupMenu.PopupMenuManager(this);
            this.menu = new MyMenu(this, orientation);
            this.menuManager.addMenu(this.menu);

            this._display();
         }
         catch (e) {
            global.logError(e);
         };
      },

      on_applet_clicked: function(event) {
         this.menu.toggle();       
      },

      _display: function() {

         let listCounter =0 ;
         for(listCounter; listCounter<itemList.length; listCounter++){

            if (itemList[listCounter][0].toLowerCase() != "separator"){
         
            // Display items from the itemList list
               let icon = new St.Icon({icon_name: itemList[listCounter][0], icon_size: ICON_SIZE, icon_type: St.IconType.FULLCOLOR});
               this.listItem = new MyPopupMenuItem(icon, _(itemList[listCounter][1]));
         
               this.menu.addMenuItem(this.listItem);
               this.listItem.connect('activate', function(actor, event) {
                      Main.Util.spawnCommandLine(itemList[listCounter][2]);
               });
            }//if
            else{
               // Separator
               this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
            }// else
         }// for
      }
};

function main(metadata, orientation) { 
   let myApplet = new MyApplet(orientation);
   return myApplet;     
};


Thanks in advance for any help - K
karlitos
Level 1
Level 1
 
Posts: 11
Joined: Wed May 20, 2009 5:55 am

Linux Mint is funded by ads and donations.
 

Re: help with a cinnamon applet (custom menu) development

Postby karlitos on Tue Mar 20, 2012 6:32 am

So I found a solution/workaround for my problem. I first copy the command from the array into a variable and then use this variable in the Main.Util.spawnCommandLine() function. Do not know wha I just can not use the command in the arry directly(
Code: Select all
Main.Util.spawnCommandLine(itemList[listCounter][2]);


Still looking for the way how to create sub-menus and storing the data for the menu entries outside of the javascript.
karlitos
Level 1
Level 1
 
Posts: 11
Joined: Wed May 20, 2009 5:55 am

Re: help with a cinnamon applet (custom menu) development

Postby mbokil on Sun Apr 29, 2012 6:56 pm

Still looking for the way how to create sub-menus and storing the data for the menu entries outside of the javascript.


You can access file data outside an applet in a separate file. I don't think there is an established API yet that reads/writes properties. Look at the example code below for the mylauncher app I wrote. You can read in a text file of properties and assign key/value pairs in javascript. I have been thinking about writing a Properties class if it doesn't exist for persisting applet data.

Install mylauncher applet and see how I put it all together: http://cinnamon-spices.linuxmint.com/applets/view/60

Code: Select all
// Mark Bokil 4/29/12
// Mylauncher Cinnamon Applet

const Lang = imports.lang;
const St = imports.gi.St;
const Cinnamon = imports.gi.Cinnamon;
const Applet = imports.ui.applet;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
const Gtk = imports.gi.Gtk;
const GLib = imports.gi.GLib;
const AppletMeta = imports.ui.appletManager.applets["mylauncher@markbokil.com"];
const AppletDir = imports.ui.appletManager.appletMeta["mylauncher@markbokil.com"].path;

const PropertiesFile = GLib.build_filenamev([global.userdatadir, 'applets/mylauncher@markbokil.com/mylauncher.properties']);


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

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

    _init: function(orientation) {       
        Applet.IconApplet.prototype._init.call(this, orientation);
       
        try {   
            this.set_applet_icon_symbolic_name("start-here-symbolic");
            this.set_applet_tooltip(_("My Launcher"));
           
            this.menuManager = new PopupMenu.PopupMenuManager(this);
            this._orientation = orientation;
            this.menu = new Applet.AppletPopupMenu(this, this._orientation);
            this.menuManager.addMenu(this.menu);       
                                                               
            this._contentSection = new PopupMenu.PopupMenuSection();
            this.menu.addMenuItem(this._contentSection);                   
 
            propLines = this.getProperties(); 

            for (let i = 0; i < propLines.length; i++) {
                let line = propLines[i];
                if (line.substring(0,1) == '#')
                    continue;
                if (line.trim(' ') == '')
                    continue;         
                let prop = line.split('=');

                // build menu items
                propName = prop[0].trim(' ');
                this.menu.addAction(_(propName), function(event) {
                    propVal =  prop[1].trim(' ');
                    //global.log(propName + ', ' + propVal); //debug
                    Util.spawnCommandLine(propVal);
                });
            }

            // dev debugging

            this.menu.addAction(_("Xkill"), function(event) {
                Util.spawnCommandLine(AppletDir + "/xkill.py");
            });
            this.menu.addAction(_("Looking Glass"), function(event) {
                Main.createLookingGlass().open();
            });
            this.menu.addAction(_("Restart Cinnamon"), function(event) {
                global.reexec_self();
            });

            // end debugging

            // context menu
            this.edit_menu_item = new Applet.MenuItem(_("Edit launcher apps list"), Gtk.STOCK_EDIT,
                Lang.bind(this, this.editProperties));
            this._applet_context_menu.addMenuItem(this.edit_menu_item);

        }
        catch (e) {
            global.logError(e);
        }
    },

   
    on_applet_clicked: function(event) {
        this.menu.toggle();       
    },

    on_orientation_changed: function (orientation) {
        this._orientation = orientation;
        this._initContextMenu();
    },

    getProperties: function () {
        let prop = Cinnamon.get_file_contents_utf8_sync(PropertiesFile);
        let lines = prop.split('\n');

        return lines;
    },

    editProperties: function () {
        Main.Util.spawnCommandLine("gedit " + PropertiesFile);
    },
       
   
};

function main(metadata, orientation) { 
    let myApplet = new MyApplet(orientation);
    return myApplet;     
}
mbokil
Level 1
Level 1
 
Posts: 12
Joined: Sun Apr 29, 2012 6:44 pm


Return to Cinnamon

Who is online

Users browsing this forum: Espair and 13 guests