2013-05-09 17:35:57 -04:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
|
2013-05-09 16:24:40 -04:00
|
|
|
const Atk = imports.gi.Atk;
|
2013-05-09 17:35:57 -04:00
|
|
|
const GLib = imports.gi.GLib;
|
2013-05-09 12:28:44 -04:00
|
|
|
const GObject = imports.gi.GObject;
|
2013-05-09 17:35:57 -04:00
|
|
|
const Gio = imports.gi.Gio;
|
|
|
|
const Shell = imports.gi.Shell;
|
2013-05-09 12:28:44 -04:00
|
|
|
const ShellMenu = imports.gi.ShellMenu;
|
2013-05-09 17:35:57 -04:00
|
|
|
const St = imports.gi.St;
|
|
|
|
|
|
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
|
|
|
2013-04-24 16:21:57 -04:00
|
|
|
function stripMnemonics(label) {
|
|
|
|
if (!label)
|
|
|
|
return '';
|
|
|
|
|
|
|
|
// remove all underscores that are not followed by another underscore
|
|
|
|
return label.replace(/_([^_])/, '$1');
|
|
|
|
}
|
|
|
|
|
2013-05-09 17:32:52 -04:00
|
|
|
function _insertItem(menu, trackerItem, position) {
|
2013-05-10 11:17:16 -04:00
|
|
|
let mapper;
|
2013-05-09 17:32:52 -04:00
|
|
|
|
2013-05-10 11:17:16 -04:00
|
|
|
if (trackerItem.get_is_separator())
|
|
|
|
mapper = new RemoteMenuSeparatorItemMapper(trackerItem);
|
|
|
|
else if (trackerItem.get_has_submenu())
|
|
|
|
mapper = new RemoteMenuSubmenuItemMapper(trackerItem);
|
|
|
|
else
|
|
|
|
mapper = new RemoteMenuItemMapper(trackerItem);
|
|
|
|
|
|
|
|
let item = mapper.menuItem;
|
2013-05-09 17:32:52 -04:00
|
|
|
menu.addMenuItem(item, position);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _removeItem(menu, position) {
|
|
|
|
let items = menu._getMenuItems();
|
|
|
|
items[position].destroy();
|
|
|
|
}
|
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var RemoteMenuSeparatorItemMapper = class {
|
|
|
|
constructor(trackerItem) {
|
2013-04-24 16:21:57 -04:00
|
|
|
this._trackerItem = trackerItem;
|
|
|
|
this.menuItem = new PopupMenu.PopupSeparatorMenuItem();
|
2017-12-01 19:27:35 -05:00
|
|
|
this._trackerItem.connect('notify::label', this._updateLabel.bind(this));
|
2013-04-24 16:21:57 -04:00
|
|
|
this._updateLabel();
|
|
|
|
|
2017-10-30 20:38:18 -04:00
|
|
|
this.menuItem.connect('destroy', () => {
|
2013-04-24 16:21:57 -04:00
|
|
|
trackerItem.run_dispose();
|
|
|
|
});
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-04-24 16:21:57 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateLabel() {
|
2013-05-10 13:39:21 -04:00
|
|
|
this.menuItem.label.text = stripMnemonics(this._trackerItem.label);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
|
|
|
};
|
2013-05-10 14:32:58 -04:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var RequestSubMenu = class extends PopupMenu.PopupSubMenuMenuItem {
|
|
|
|
constructor() {
|
|
|
|
super('');
|
2013-05-10 14:32:58 -04:00
|
|
|
this._requestOpen = false;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-10 14:32:58 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_setOpenState(open) {
|
2013-05-10 14:32:58 -04:00
|
|
|
this.emit('request-open', open);
|
|
|
|
this._requestOpen = open;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-10 14:32:58 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_getOpenState() {
|
2013-05-10 14:32:58 -04:00
|
|
|
return this._requestOpen;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
|
|
|
};
|
2013-05-10 13:39:21 -04:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var RemoteMenuSubmenuItemMapper = class {
|
|
|
|
constructor(trackerItem) {
|
2013-05-10 13:39:21 -04:00
|
|
|
this._trackerItem = trackerItem;
|
2013-05-10 14:32:58 -04:00
|
|
|
this.menuItem = new RequestSubMenu();
|
2017-12-01 19:27:35 -05:00
|
|
|
this._trackerItem.connect('notify::label', this._updateLabel.bind(this));
|
2013-05-10 13:39:21 -04:00
|
|
|
this._updateLabel();
|
|
|
|
|
|
|
|
this._tracker = Shell.MenuTracker.new_for_item_submenu(this._trackerItem,
|
|
|
|
_insertItem.bind(null, this.menuItem.menu),
|
|
|
|
_removeItem.bind(null, this.menuItem.menu));
|
|
|
|
|
2017-10-30 20:38:18 -04:00
|
|
|
this.menuItem.connect('request-open', (menu, open) => {
|
2013-05-10 14:32:58 -04:00
|
|
|
this._trackerItem.request_submenu_shown(open);
|
2017-10-30 20:38:18 -04:00
|
|
|
});
|
2013-05-10 14:32:58 -04:00
|
|
|
|
2017-10-30 20:38:18 -04:00
|
|
|
this._trackerItem.connect('notify::submenu-shown', () => {
|
2013-05-10 14:32:58 -04:00
|
|
|
this.menuItem.setSubmenuShown(this._trackerItem.get_submenu_shown());
|
2017-10-30 20:38:18 -04:00
|
|
|
});
|
2013-05-10 14:32:58 -04:00
|
|
|
|
2017-10-30 20:38:18 -04:00
|
|
|
this.menuItem.connect('destroy', () => {
|
2013-05-10 13:39:21 -04:00
|
|
|
trackerItem.run_dispose();
|
|
|
|
});
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-10 13:39:21 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
destroy() {
|
2013-05-10 13:39:21 -04:00
|
|
|
this._tracker.destroy();
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-10 13:39:21 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateLabel() {
|
2013-04-24 16:21:57 -04:00
|
|
|
this.menuItem.label.text = stripMnemonics(this._trackerItem.label);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
|
|
|
};
|
2013-04-24 16:21:57 -04:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var RemoteMenuItemMapper = class {
|
|
|
|
constructor(trackerItem) {
|
2013-05-09 12:28:44 -04:00
|
|
|
this._trackerItem = trackerItem;
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2013-05-09 12:28:44 -04:00
|
|
|
this.menuItem = new PopupMenu.PopupBaseMenuItem();
|
2016-01-22 09:11:05 -05:00
|
|
|
this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
|
|
|
|
this.menuItem.actor.add_child(this._icon);
|
|
|
|
|
2013-05-09 12:28:44 -04:00
|
|
|
this._label = new St.Label();
|
2013-07-15 20:00:41 -04:00
|
|
|
this.menuItem.actor.add_child(this._label);
|
2013-05-09 12:28:44 -04:00
|
|
|
this.menuItem.actor.label_actor = this._label;
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2017-10-30 20:38:18 -04:00
|
|
|
this.menuItem.connect('activate', () => {
|
2013-05-09 12:28:44 -04:00
|
|
|
this._trackerItem.activated();
|
2017-10-30 20:38:18 -04:00
|
|
|
});
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2013-05-09 12:28:44 -04:00
|
|
|
this._trackerItem.bind_property('visible', this.menuItem.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2016-01-22 09:11:05 -05:00
|
|
|
this._trackerItem.connect('notify::icon', this._updateIcon.bind(this));
|
2017-12-01 19:27:35 -05:00
|
|
|
this._trackerItem.connect('notify::label', this._updateLabel.bind(this));
|
|
|
|
this._trackerItem.connect('notify::sensitive', this._updateSensitivity.bind(this));
|
|
|
|
this._trackerItem.connect('notify::role', this._updateRole.bind(this));
|
|
|
|
this._trackerItem.connect('notify::toggled', this._updateDecoration.bind(this));
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2016-01-22 09:11:05 -05:00
|
|
|
this._updateIcon();
|
2013-05-09 12:28:44 -04:00
|
|
|
this._updateLabel();
|
|
|
|
this._updateSensitivity();
|
2013-05-09 16:24:40 -04:00
|
|
|
this._updateRole();
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2017-10-30 20:38:18 -04:00
|
|
|
this.menuItem.connect('destroy', () => {
|
2013-05-09 12:28:44 -04:00
|
|
|
trackerItem.run_dispose();
|
2013-05-09 17:35:57 -04:00
|
|
|
});
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2016-01-22 09:11:05 -05:00
|
|
|
_updateIcon() {
|
|
|
|
this._icon.gicon = this._trackerItem.icon;
|
|
|
|
this._icon.visible = (this._icon.gicon != null);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2016-01-22 09:11:05 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateLabel() {
|
2013-04-24 16:21:57 -04:00
|
|
|
this._label.text = stripMnemonics(this._trackerItem.label);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateSensitivity() {
|
2013-05-09 12:28:44 -04:00
|
|
|
this.menuItem.setSensitive(this._trackerItem.sensitive);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateDecoration() {
|
2013-05-09 12:28:44 -04:00
|
|
|
let ornamentForRole = {};
|
|
|
|
ornamentForRole[ShellMenu.MenuTrackerItemRole.RADIO] = PopupMenu.Ornament.DOT;
|
|
|
|
ornamentForRole[ShellMenu.MenuTrackerItemRole.CHECK] = PopupMenu.Ornament.CHECK;
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2013-05-09 12:28:44 -04:00
|
|
|
let ornament = PopupMenu.Ornament.NONE;
|
|
|
|
if (this._trackerItem.toggled)
|
|
|
|
ornament = ornamentForRole[this._trackerItem.role];
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2013-05-09 12:28:44 -04:00
|
|
|
this.menuItem.setOrnament(ornament);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-09 16:24:40 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_updateRole() {
|
2013-05-09 16:24:40 -04:00
|
|
|
let a11yRoles = {};
|
|
|
|
a11yRoles[ShellMenu.MenuTrackerItemRole.NORMAL] = Atk.Role.MENU_ITEM;
|
|
|
|
a11yRoles[ShellMenu.MenuTrackerItemRole.RADIO] = Atk.Role.RADIO_MENU_ITEM;
|
|
|
|
a11yRoles[ShellMenu.MenuTrackerItemRole.CHECK] = Atk.Role.CHECK_MENU_ITEM;
|
|
|
|
|
|
|
|
let a11yRole = a11yRoles[this._trackerItem.role];
|
|
|
|
this.menuItem.actor.accessible_role = a11yRole;
|
|
|
|
|
|
|
|
this._updateDecoration();
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
|
|
|
};
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var RemoteMenu = class extends PopupMenu.PopupMenu {
|
|
|
|
constructor(sourceActor, model, actionGroup) {
|
|
|
|
super(sourceActor, 0.0, St.Side.TOP);
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2013-05-09 12:28:44 -04:00
|
|
|
this._model = model;
|
|
|
|
this._actionGroup = actionGroup;
|
|
|
|
this._tracker = Shell.MenuTracker.new(this._actionGroup,
|
|
|
|
this._model,
|
|
|
|
null, /* action namespace */
|
2013-05-09 17:32:52 -04:00
|
|
|
_insertItem.bind(null, this),
|
|
|
|
_removeItem.bind(null, this));
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-05-09 17:35:57 -04:00
|
|
|
|
2017-06-12 22:17:39 -04:00
|
|
|
get actionGroup() {
|
|
|
|
return this._actionGroup;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2017-06-12 22:17:39 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
destroy() {
|
2013-05-09 12:28:44 -04:00
|
|
|
this._tracker.destroy();
|
2017-10-30 21:19:44 -04:00
|
|
|
super.destroy();
|
|
|
|
}
|
|
|
|
};
|