77556d181e
Since this link in the keyboard menu points to Region and Language Settings in System Settings, we should be consistent and use that term instead of "Localization Settings" Also, this removes ellipsis from "Show Keyboard Layout" since it doesn't require further input. https://bugzilla.gnome.org/show_bug.cgi?id=652984
204 lines
7.2 KiB
JavaScript
204 lines
7.2 KiB
JavaScript
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
const GdkPixbuf = imports.gi.GdkPixbuf;
|
|
const Gkbd = imports.gi.Gkbd;
|
|
const Gio = imports.gi.Gio;
|
|
const GLib = imports.gi.GLib;
|
|
const Lang = imports.lang;
|
|
const Shell = imports.gi.Shell;
|
|
const St = imports.gi.St;
|
|
|
|
const Main = imports.ui.main;
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
const PanelMenu = imports.ui.panelMenu;
|
|
const Util = imports.misc.util;
|
|
|
|
function LayoutMenuItem() {
|
|
this._init.apply(this, arguments);
|
|
}
|
|
|
|
LayoutMenuItem.prototype = {
|
|
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
|
|
|
|
_init: function(config, id, indicator, long_name) {
|
|
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
|
|
|
|
this._config = config;
|
|
this._id = id;
|
|
this.label = new St.Label({ text: long_name });
|
|
this.indicator = indicator;
|
|
this.addActor(this.label);
|
|
this.addActor(this.indicator);
|
|
},
|
|
|
|
activate: function(event) {
|
|
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
|
|
this._config.lock_group(this._id);
|
|
}
|
|
};
|
|
|
|
function XKBIndicator() {
|
|
this._init.call(this);
|
|
}
|
|
|
|
XKBIndicator.prototype = {
|
|
__proto__: PanelMenu.Button.prototype,
|
|
|
|
_init: function() {
|
|
PanelMenu.Button.prototype._init.call(this, St.Align.START);
|
|
|
|
this._container = new Shell.GenericContainer();
|
|
this._container.connect('get-preferred-width', Lang.bind(this, this._get_preferred_width));
|
|
this._container.connect('get-preferred-height', Lang.bind(this, this._get_preferred_height));
|
|
this._container.connect('allocate', Lang.bind(this, this._allocate));
|
|
this.actor.set_child(this._container);
|
|
|
|
this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
|
|
this._container.add_actor(this._iconActor);
|
|
this._labelActors = [ ];
|
|
this._layoutItems = [ ];
|
|
|
|
this._showFlags = false;
|
|
this._config = Gkbd.Configuration.get();
|
|
this._config.connect('changed', Lang.bind(this, this._sync_config));
|
|
this._config.connect('group-changed', Lang.bind(this, this._sync_group));
|
|
this._config.start_listen();
|
|
|
|
this._sync_config();
|
|
|
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, function() {
|
|
Main.overview.hide();
|
|
Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
|
|
}));
|
|
this.menu.addAction(_("Region and Language Settings"), function() {
|
|
Main.overview.hide();
|
|
let app = Shell.AppSystem.get_default().get_app('gnome-region-panel.desktop');
|
|
app.activate(-1);
|
|
});
|
|
},
|
|
|
|
_sync_config: function() {
|
|
this._showFlags = this._config.if_flags_shown();
|
|
if (this._showFlags) {
|
|
this._container.set_skip_paint(this._iconActor, false);
|
|
} else {
|
|
this._container.set_skip_paint(this._iconActor, true);
|
|
}
|
|
|
|
let groups = this._config.get_group_names();
|
|
if (groups.length > 1) {
|
|
this.actor.show();
|
|
} else {
|
|
this.menu.close();
|
|
this.actor.hide();
|
|
}
|
|
|
|
for (let i = 0; i < this._layoutItems.length; i++)
|
|
this._layoutItems[i].destroy();
|
|
|
|
for (let i = 0; i < this._labelActors.length; i++)
|
|
this._labelActors[i].destroy();
|
|
|
|
let short_names = this._config.get_short_group_names();
|
|
|
|
this._selectedLayout = null;
|
|
this._layoutItems = [ ];
|
|
this._selectedLabel = null;
|
|
this._labelActors = [ ];
|
|
for (let i = 0; i < groups.length; i++) {
|
|
let icon_name = this._config.get_group_name(i);
|
|
let actor;
|
|
if (this._showFlags)
|
|
actor = new St.Icon({ icon_name: icon_name, icon_type: St.IconType.SYMBOLIC, style_class: 'popup-menu-icon' });
|
|
else
|
|
actor = new St.Label({ text: short_names[i] });
|
|
let item = new LayoutMenuItem(this._config, i, actor, groups[i]);
|
|
item._short_group_name = short_names[i];
|
|
item._icon_name = icon_name;
|
|
this._layoutItems.push(item);
|
|
this.menu.addMenuItem(item, i);
|
|
|
|
let shortLabel = new St.Label({ text: short_names[i] });
|
|
this._labelActors.push(shortLabel);
|
|
this._container.add_actor(shortLabel);
|
|
this._container.set_skip_paint(shortLabel, true);
|
|
}
|
|
|
|
this._sync_group();
|
|
},
|
|
|
|
_sync_group: function() {
|
|
let selected = this._config.get_current_group();
|
|
|
|
if (this._selectedLayout) {
|
|
this._selectedLayout.setShowDot(false);
|
|
this._selectedLayout = null;
|
|
}
|
|
|
|
if (this._selectedLabel) {
|
|
this._container.set_skip_paint(this._selectedLabel, true);
|
|
this._selectedLabel = null;
|
|
}
|
|
|
|
let item = this._layoutItems[selected];
|
|
item.setShowDot(true);
|
|
|
|
this._iconActor.icon_name = item._icon_name;
|
|
this._selectedLabel = this._labelActors[selected];
|
|
this._container.set_skip_paint(this._selectedLabel, this._showFlags);
|
|
|
|
this._selectedLayout = item;
|
|
},
|
|
|
|
_get_preferred_width: function(container, for_height, alloc) {
|
|
/* Here, and in _get_preferred_height, we need to query for the
|
|
height of all children, but we ignore the results for those
|
|
we don't actually display. */
|
|
let max_min_width = 0, max_natural_width = 0;
|
|
if (this._showFlags)
|
|
[max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
|
|
|
|
for (let i = 0; i < this._labelActors.length; i++) {
|
|
let [min_width, natural_width] = this._labelActors[i].get_preferred_width(for_height);
|
|
if (!this._showFlags) {
|
|
max_min_width = Math.max(max_min_width, min_width);
|
|
max_natural_width = Math.max(max_natural_width, natural_width);
|
|
}
|
|
}
|
|
|
|
alloc.min_size = max_min_width;
|
|
alloc.natural_size = max_natural_width;
|
|
},
|
|
|
|
_get_preferred_height: function(container, for_width, alloc) {
|
|
let max_min_height = 0, max_natural_height = 0;
|
|
if (this._showFlags)
|
|
[max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
|
|
|
|
for (let i = 0; i < this._labelActors.length; i++) {
|
|
let [min_height, natural_height] = this._labelActors[i].get_preferred_height(for_width);
|
|
if (!this._showFlags) {
|
|
max_min_height = Math.max(max_min_height, min_height);
|
|
max_natural_height = Math.max(max_natural_height, natural_height);
|
|
}
|
|
}
|
|
|
|
alloc.min_size = max_min_height;
|
|
alloc.natural_size = max_natural_height;
|
|
},
|
|
|
|
_allocate: function(container, box, flags) {
|
|
// translate box to (0, 0)
|
|
box.x2 -= box.x1;
|
|
box.x1 = 0;
|
|
box.y2 -= box.y1;
|
|
box.y1 = 0;
|
|
|
|
this._iconActor.allocate_align_fill(box, 0.5, 0, false, false, flags);
|
|
for (let i = 0; i < this._labelActors.length; i++)
|
|
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
|
|
}
|
|
};
|