首页 > 解决方案 > 如何在 Cinnamon Applet 中显示多个对象

问题描述

我正在尝试为我的面板编写一个 Cinnamon Applet。我已经想出了如何创建一个简单的图标,但我不知道如何才能让第二个图标出现。

这是我当前的简单代码:

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

我正在尝试创建一个工作区切换器,它在我的侧面板上有图标而不是文本标签,这部分是我无法绕开我的大脑的部分。

我知道主函数调用了一个最终显示在 Applet 上的对象。如何从 someIcon 类中生成另一个图标?

标签: javascriptlinuxappletgnomecinnamon

解决方案


一般的做法

该类IconApplet只能处理一个图标。我会使用该类的代码作为模板来编写一个MultiIconApplet能够处理多个的类。

您可以在中找到原始代码/usr/share/cinnamon/js/ui/applet.js并搜索class IconApplet. 复制出来修改一下。在构建一个图标容器的地方,您可以拥有一组它们:

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]);
    }

然后,实现每个IconApplet方法,但说明您要定位的图标的索引。例如:

    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();
    }

对每个方法重复,this._applet_icon与交换this._applet_icons[index]

有一种方法会覆盖父类方法,因此您需要在没有参数的情况下实现它并循环遍历图标:

    on_panel_height_changed_internal() {
        this.applet_icons.forEach((icon, index) => {
            if (icon) this._setStyle(index);
        )};
        this.on_panel_height_changed();
    }

最后,你需要实现一个对方向变化的反应,这只是父类中的一个抽象方法:

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

工作区切换器的专业解决方案

由于您要实现的是工作区切换器,因此您也可以从标准小程序开始/usr/share/cinnamon/applets/workspace-switcher@cinnamon.org并修改其代码。

您需要做的就是SimpleButton在该小程序中查找该类,并在其中添加一个St.Label来表示工作区,而不是添加一个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();
    }

推荐阅读