diff --git a/extension.js b/extension.js index ec2464c..0100b09 100644 --- a/extension.js +++ b/extension.js @@ -17,7 +17,9 @@ */ /* Based on https://stackoverflow.com/questions/33001192/how-to-send-a-string-to-a-gnome-shell-extension */ - +// https://github.com/bananenfisch/RecentItems/blob/master/extension.js +// https://github.com/julio641742/gnome-shell-extension-reference/blob/master/tutorials/POPUPMENU-EXTENSION.md +// https://gjs-docs.gnome.org/st10~1.0_api/st.widget const St = imports.gi.St; const Gio = imports.gi.Gio; const Lang = imports.lang; @@ -25,13 +27,111 @@ const GLib = imports.gi.GLib const Main = imports.ui.main; const Mainloop = imports.mainloop; const clutter = imports.gi.Clutter; +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; +const GObject = imports.gi.GObject; +const Gtk = imports.gi.Gtk; +const Pixbuf = imports.gi.GdkPixbuf; +const Cogl = imports.gi.Cogl; -class MonitorWidget { - constructor(name, group, text, style, icon, iconStyle, onClick, box, lastWidget) { - this.name = name; +var MyPopupMenuItem = GObject.registerClass({ + GTypeName: "MyPopupMenuItem" +}, +class MyPopupMenuItem extends PopupMenu.PopupBaseMenuItem { + _init(gicon, text, params) { + super._init(params); + + this.box = new St.BoxLayout({ style_class: 'popup-combobox-item' }); + this.box.set_vertical(true); + this._img = new clutter.Image(); + let initial_pixbuf = Pixbuf.Pixbuf.new_from_file('/tmp/cat2.jpg'); + this._img.set_data(initial_pixbuf.get_pixels(), + initial_pixbuf.get_has_alpha() ? Cogl.PixelFormat.RGBA_8888 + : Cogl.PixelFormat.RGB_888, + initial_pixbuf.get_width(), + initial_pixbuf.get_height(), + initial_pixbuf.get_rowstride()); + this._icon = new clutter.Actor(); + this._icon.set_content(this._img); + this._icon.set_size(150,//initial_pixbuf.get_width(), + 300);//initial_pixbuf.get_height()); + this.box.add(this._icon); + + // if (gicon) + // this.icon = new St.Icon({ gicon: gicon, style_class: 'popup-menu-icon' }); + // else + // this.icon = new St.Icon({ icon_name: 'edit-clear-symbolic', icon_size: 22 }); + + // this.box.add(this._icon); + this.label = new St.Label({ text: " " + text }); + this.box.add(this.label); + this.add_child(this.box); + } +}); + + +var RecentItems = GObject.registerClass({ + GTypeName: "RecentItems" +}, +class RecentItems extends PanelMenu.Button { + _init() { + super._init(0.0); + this.connect('enter-event', this._onEnter.bind(this)); + this.connect('leave-event', this._onLeave.bind(this)); + this._iconActor = new St.Icon({ icon_name: 'document-open-recent-symbolic', style_class: 'system-status-icon' }); + this.actor.add_actor(this._iconActor); + this.actor.add_style_class_name('panel-status-button'); + Main.panel.addToStatusArea('recent-items', this); + + let menuItem = new MyPopupMenuItem('', 'hello', {}); + this.menu.addMenuItem(menuItem); + } + + _onEnter() { + this.menu.open(true); + } + + _onLeave() { + this.menu.close(); + } +}); + +var MonitorWidget = GObject.registerClass({ + GTypeName: "MonitorWidget" +}, +class MonitorWidget extends PanelMenu.Button { + + _init(item, group, lastWidget) { + super._init(0.0); + + this.name = item['name']; this.group = group; - this._createIcon(icon, iconStyle); - this._createText(text, style); + + if (item.hasOwnProperty('icon')) + { + this.icon = this._createIcon(icon, iconStyle); + this.add_child(this.icon); + } + else + this.icon = null; + + if (item.hasOwnProperty('text')) + { + this.widget = this._createText(text, style); + this.add_child(this.widget); + } + else + this.widget = null; + + if (item.hasOwnProperty('popup')) + this._createPopup(item['popup']); + + if (item.hasOwnProperty('on-click')) + onClick = item['on-click']; + let box = 'center'; + if (item.hasOwnProperty('box')) + box = item['box']; + this.onClick = onClick; switch(box) { @@ -52,51 +152,44 @@ class MonitorWidget { log(`${box} box is undefined, falling back to center one`); this.box = Main.panel._centerBox; } + + let menuItem = new MyPopupMenuItem('', 'hello', {}); + this.menu.addMenuItem(menuItem); + + this.connect('enter-event', this._onEnter.bind(this)); + this.connect('leave-event', this._onLeave.bind(this)); - this._addToBox(lastWidget); + Main.panel.addToStatusArea(group, this, (lastWidget>0)?lastWidget:-1, box); + } + + _onEnter() { + this.menu.open(true); + } + + _onLeave() { + this.menu.close(); } _createText(text, style) { this.style = style; if (text === '') { - this.widget = null; + return null; } else { - this.widget = new St.Button({ label: text }); - this.widget.set_style(this.style); - } + widget = new St.Button({ label: text }); + widget.set_style(this.style); + return widget; + } } _createIcon(icon, style) { this.iconStyle = style; if (icon === '') { - this.icon = null; + return null; } else { let gicon = Gio.icon_new_for_string(icon); - this.icon = new St.Icon({ gicon }); - this.icon.set_style(this.iconStyle); - } - } - - _addToBox(lastWidget) { - // lastWidget => NULL, insert at the end - if (this.box !== Main.panel._rigthBox || lastWidget) { - if (this.icon) { - this.box.insert_child_above(this.icon, lastWidget); - lastWidget = this.icon; - } - if (this.widget) - this.box.insert_child_above(this.widget, lastWidget); - } else { - if (this.icon) { - this.box.insert_child_at_index(this.icon, 0); - lastWidget = this.icon; - } - if (this.widget) { - if (lastWidget) - this.box.insert_child_above(this.widget, lastWidget); - else - this.box.insert_child_at_index(this.icon, 0); - } + gicon = new St.Icon({ gicon }); + gicon.set_style(this.iconStyle); + return gicon; } } @@ -141,7 +234,7 @@ class MonitorWidget { if (prevIcon && icon !== '') this.box.remove_child(prevIcon); } -} +}); // From https://github.com/ubuntu/gnome-shell-extension-appindicator/blob/master/interfaces.js // loads a xml file into an in-memory string @@ -190,16 +283,16 @@ class GenericMonitorDBUS { let item = parameters['items'][itemIndex]; if (!item.hasOwnProperty('name')) throw new Error('No name defined for item'); - if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon')) - throw new Error('No text not icon defined for item'); - if (item.hasOwnProperty('on-click')) { - if (item['on-click'] !== 'signal' && item['on-click'] !== 'delete') - throw new Error('Invalid on-click value'); - } - if (item.hasOwnProperty('box')) { - if (item['box'] !== 'left' && item['box'] !== 'center' && item['box'] !== 'right') - throw new Error('Invalid box value'); - } + // if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon')) + // throw new Error('No text not icon defined for item'); + // if (item.hasOwnProperty('on-click')) { + // if (item['on-click'] !== 'signal' && item['on-click'] !== 'delete') + // throw new Error('Invalid on-click value'); + // } + // if (item.hasOwnProperty('box')) { + // if (item['box'] !== 'left' && item['box'] !== 'center' && item['box'] !== 'right') + // throw new Error('Invalid box value'); + // } } } @@ -319,9 +412,8 @@ class GenericMonitorDBUS { // New widget if (monitorWidget === null) { - if (group.length) - lastWidget = group[group.length - 1].widget; - monitorWidget = new MonitorWidget(item['name'], groupName, text, style, icon, iconStyle, onClick, box, lastWidget); + lastWidget = group.length - 1; + monitorWidget = new MonitorWidget(item, groupName, lastWidget); group.push(monitorWidget); // Connect signals if (onClick !== '') {