I am trying to write a Cinnamon Applet for my panels. I have figured out how to create a simple icon but I cannot figure out how can I get a second one to appear.
Here is my current simple code:
const Applet = imports.ui.applet;
class wholeModule extends Applet.Applet {
constructor(orientation, panel_height, instance_id) {
let icon = new someIcon(orientation, panel_height, instance_id);
icon.updateIconName('google-chrome-symbolic');
let icon2 = new someIcon(orientation, panel_height, instance_id);
icon2.updateIconName('google-chrome');
return icon;
}
}
class someIcon extends Applet.IconApplet {
constructor(orientation, panel_height, instance_id) {
super(orientation, panel_height, instance_id);
this.set_applet_icon_name('user-desktop-symbolic');
this.set_applet_tooltip(_('test text'));
}
updateIconName(name) {
this.set_applet_icon_name(name);
}
setToolTip(text) {
this.set_applet_tooltip(_(text));
}
}
function main(metadata, orientation, panel_height, instance_id) {
return new wholeModule(orientation, panel_height, instance_id);
}
I am trying to create a workspace-switcher that has icons instead of text labels on my side panel and this part is what I cannot wrap my brain around.
I get that the main function calls for an object that ends up displayed on the Applet. How can I spawn another icon from someIcon class?
The class IconApplet
is only able to handle one icon. I would use the code of that class as a template to write a class MultiIconApplet
that is able to handle multiples.
You can find the original code in /usr/share/cinnamon/js/ui/applet.js
and search for class IconApplet
. Copy it out and modify. Where one icon container is built, you can have an array of them:
var MultiIconApplet = class MultiIconApplet extends Applet {
// provide the number of icons you need as an extra parameter
_init(orientation, panel_height, icon_count, instance_id) {
super._init(orientation, panel_height, instance_id);
this.orientation = orientation; //orientation makes a difference
this._applet_icon_boxes = []; //array of containers
this._applet_icons = []; //array of icons
for (var i = 0; i < icon_count; i++) {
var box = new St.Bin();
this._applet_icon_boxes.push(box);
box.set_fill(true,true);
box.set_alignment(St.Align.MIDDLE,St.Align.MIDDLE);
this.actor.add(box);
}
// this method constructs the actual icons
_ensureIcon(index) {
if (!this._applet_icons[index] ||
!(this._applet_icons[index] instanceof St.Icon))
this._applet_icons[index] = new St.Icon({
reactive: true, track_hover: true,
style_class: 'applet-icon'
});
this._applet_icon_boxes[index].set_child(this._applet_icons[index]);
}
Then, implement each of the IconApplet
methods, but state the index of the icon you want to target. For example:
set_applet_icon_name (index, icon_name) {
this._ensureIcon(index);
this._applet_icon[index].set_icon_name(icon_name);
this._applet_icon[index].set_icon_type(St.IconType.FULLCOLOR);
this._setStyle();
}
Repeat for each of the methods, exchanging this._applet_icon
with this._applet_icons[index]
.
There is one method that overwrites the parent class method, so you need to implement that without parameter and loop through the icons:
on_panel_height_changed_internal() {
this.applet_icons.forEach((icon, index) => {
if (icon) this._setStyle(index);
)};
this.on_panel_height_changed();
}
Finally, you need to implement a reaction to orientation change, which is only an abstract method in the parent class:
on_orientation_changed(neworientation) {
this.orientation = neworientation;
if (this.orientation == St.Side.TOP || this.orientation == St.Side.BOTTOM)
this.actor.set_vertical(false);
else
this.actor.set_vertical(true);
}
}
Since what you want to achieve is a workspace switcher, you can also start out with the standard applet at /usr/share/cinnamon/applets/workspace-switcher@cinnamon.org
and modify its code.
All you need to do is look for the class SimpleButton
in that applet, and where it adds a St.Label
to represent the workspace, instead add a St.Icon
:
class SimpleButton extends WorkspaceButton {
constructor(index, applet) {
super(index, applet);
this.actor = new St.Button({ name: 'workspaceButton',
style_class: 'workspace-button',
reactive: applet._draggable.inhibit });
if (applet.orientation == St.Side.TOP || applet.orientation == St.Side.BOTTOM) {
this.actor.set_height(applet._panelHeight);
} else {
this.actor.set_width(applet._panelHeight);
this.actor.add_style_class_name('vertical');
}
let icon = new St.Icon({
icon_name: ..., // choose one based on index
icon_size: applet.getPanelIconSize()
style_class: 'applet-icon'
});
this.actor.set_child(icon);
this.update();
}