eb79f5b512
Since ES5, trailing commas in arrays and object literals are valid. We generally haven't used them so far, but they are actually a good idea, as they make additions and removals in diffs much cleaner. https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
211 lines
6.2 KiB
JavaScript
211 lines
6.2 KiB
JavaScript
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
|
/* exported init buildPrefsWidget */
|
|
|
|
const { Gio, GObject, Gtk } = imports.gi;
|
|
|
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
|
const _ = Gettext.gettext;
|
|
const N_ = e => e;
|
|
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
|
|
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
|
const WORKSPACE_KEY = 'workspace-names';
|
|
|
|
const WorkspaceNameModel = GObject.registerClass(
|
|
class WorkspaceNameModel extends Gtk.ListStore {
|
|
_init(params) {
|
|
super._init(params);
|
|
this.set_column_types([GObject.TYPE_STRING]);
|
|
|
|
this.Columns = {
|
|
LABEL: 0,
|
|
};
|
|
|
|
this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
|
this._reloadFromSettings();
|
|
|
|
// overriding class closure doesn't work, because GtkTreeModel
|
|
// plays tricks with marshallers and class closures
|
|
this.connect('row-changed', this._onRowChanged.bind(this));
|
|
this.connect('row-inserted', this._onRowInserted.bind(this));
|
|
this.connect('row-deleted', this._onRowDeleted.bind(this));
|
|
}
|
|
|
|
_reloadFromSettings() {
|
|
if (this._preventChanges)
|
|
return;
|
|
this._preventChanges = true;
|
|
|
|
let newNames = this._settings.get_strv(WORKSPACE_KEY);
|
|
|
|
let i = 0;
|
|
let [ok, iter] = this.get_iter_first();
|
|
while (ok && i < newNames.length) {
|
|
this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
|
|
ok = this.iter_next(iter);
|
|
i++;
|
|
}
|
|
|
|
while (ok)
|
|
ok = this.remove(iter);
|
|
|
|
for (; i < newNames.length; i++) {
|
|
iter = this.append();
|
|
this.set(iter, [this.Columns.LABEL], [newNames[i]]);
|
|
}
|
|
|
|
this._preventChanges = false;
|
|
}
|
|
|
|
_onRowChanged(self, path, iter) {
|
|
if (this._preventChanges)
|
|
return;
|
|
this._preventChanges = true;
|
|
|
|
let index = path.get_indices()[0];
|
|
let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
|
|
if (index >= names.length) {
|
|
// fill with blanks
|
|
for (let i = names.length; i <= index; i++)
|
|
names[i] = '';
|
|
}
|
|
|
|
names[index] = this.get_value(iter, this.Columns.LABEL);
|
|
|
|
this._settings.set_strv(WORKSPACE_KEY, names);
|
|
|
|
this._preventChanges = false;
|
|
}
|
|
|
|
_onRowInserted(self, path, iter) {
|
|
if (this._preventChanges)
|
|
return;
|
|
this._preventChanges = true;
|
|
|
|
let index = path.get_indices()[0];
|
|
let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
let label = this.get_value(iter, this.Columns.LABEL) || '';
|
|
names.splice(index, 0, label);
|
|
|
|
this._settings.set_strv(WORKSPACE_KEY, names);
|
|
|
|
this._preventChanges = false;
|
|
}
|
|
|
|
_onRowDeleted(self, path) {
|
|
if (this._preventChanges)
|
|
return;
|
|
this._preventChanges = true;
|
|
|
|
let index = path.get_indices()[0];
|
|
let names = this._settings.get_strv(WORKSPACE_KEY);
|
|
|
|
if (index >= names.length)
|
|
return;
|
|
|
|
names.splice(index, 1);
|
|
|
|
// compact the array
|
|
for (let i = names.length - 1; i >= 0 && !names[i]; i++)
|
|
names.pop();
|
|
|
|
this._settings.set_strv(WORKSPACE_KEY, names);
|
|
|
|
this._preventChanges = false;
|
|
}
|
|
});
|
|
|
|
const WorkspaceSettingsWidget = GObject.registerClass(
|
|
class WorkspaceSettingsWidget extends Gtk.Grid {
|
|
_init(params) {
|
|
super._init(params);
|
|
this.margin = 12;
|
|
this.orientation = Gtk.Orientation.VERTICAL;
|
|
|
|
this.add(new Gtk.Label({
|
|
label: '<b>%s</b>'.format(_('Workspace Names')),
|
|
use_markup: true,
|
|
margin_bottom: 6,
|
|
hexpand: true,
|
|
halign: Gtk.Align.START,
|
|
}));
|
|
|
|
let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN });
|
|
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
this.add(scrolled);
|
|
|
|
this._store = new WorkspaceNameModel();
|
|
this._treeView = new Gtk.TreeView({
|
|
model: this._store,
|
|
headers_visible: false,
|
|
reorderable: true,
|
|
hexpand: true,
|
|
vexpand: true,
|
|
});
|
|
|
|
let column = new Gtk.TreeViewColumn({ title: _('Name') });
|
|
let renderer = new Gtk.CellRendererText({ editable: true });
|
|
renderer.connect('edited', this._cellEdited.bind(this));
|
|
column.pack_start(renderer, true);
|
|
column.add_attribute(renderer, 'text', this._store.Columns.LABEL);
|
|
this._treeView.append_column(column);
|
|
|
|
scrolled.add(this._treeView);
|
|
|
|
let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR });
|
|
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
|
|
|
|
let newButton = new Gtk.ToolButton({ icon_name: 'list-add-symbolic' });
|
|
newButton.connect('clicked', this._newClicked.bind(this));
|
|
toolbar.add(newButton);
|
|
|
|
let delButton = new Gtk.ToolButton({ icon_name: 'list-remove-symbolic' });
|
|
delButton.connect('clicked', this._delClicked.bind(this));
|
|
toolbar.add(delButton);
|
|
|
|
let selection = this._treeView.get_selection();
|
|
selection.connect('changed', () => {
|
|
delButton.sensitive = selection.count_selected_rows() > 0;
|
|
});
|
|
delButton.sensitive = selection.count_selected_rows() > 0;
|
|
|
|
this.add(toolbar);
|
|
}
|
|
|
|
_cellEdited(renderer, path, newText) {
|
|
let [ok, iter] = this._store.get_iter_from_string(path);
|
|
|
|
if (ok)
|
|
this._store.set(iter, [this._store.Columns.LABEL], [newText]);
|
|
}
|
|
|
|
_newClicked() {
|
|
let iter = this._store.append();
|
|
let index = this._store.get_path(iter).get_indices()[0];
|
|
|
|
let label = _('Workspace %d').format(index + 1);
|
|
this._store.set(iter, [this._store.Columns.LABEL], [label]);
|
|
}
|
|
|
|
_delClicked() {
|
|
let [any, model_, iter] = this._treeView.get_selection().get_selected();
|
|
|
|
if (any)
|
|
this._store.remove(iter);
|
|
}
|
|
});
|
|
|
|
function init() {
|
|
ExtensionUtils.initTranslations();
|
|
}
|
|
|
|
function buildPrefsWidget() {
|
|
let widget = new WorkspaceSettingsWidget();
|
|
widget.show_all();
|
|
|
|
return widget;
|
|
}
|