extension-prefs: Give the UI a bit of GNOME 3 treatment
The extension-prefs UI has never been great, but as the GNOME 3 design patterns are evolving, it is starting to look seriously outdated. Modernize the UI a bit to have it fit in a bit better. https://bugzilla.gnome.org/show_bug.cgi?id=730829
This commit is contained in:
parent
dd85670f8b
commit
e1b30b2924
@ -23,6 +23,11 @@ const GnomeShellIface = '<node> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const customCss = '.prefs-button { \
|
||||
padding: 8px; \
|
||||
border-radius: 20px; \
|
||||
}';
|
||||
|
||||
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
|
||||
|
||||
function stripPrefix(string, prefix) {
|
||||
@ -46,15 +51,9 @@ const Application = new Lang.Class({
|
||||
|
||||
this._extensionPrefsModules = {};
|
||||
|
||||
this._extensionIters = {};
|
||||
this._startupUuid = null;
|
||||
},
|
||||
|
||||
_buildModel: function() {
|
||||
this._model = new Gtk.ListStore();
|
||||
this._model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]);
|
||||
},
|
||||
|
||||
_extensionAvailable: function(uuid) {
|
||||
let extension = ExtensionUtils.extensions[uuid];
|
||||
|
||||
@ -70,11 +69,6 @@ const Application = new Lang.Class({
|
||||
return true;
|
||||
},
|
||||
|
||||
_setExtensionInsensitive: function(layout, cell, model, iter, data) {
|
||||
let uuid = model.get_value(iter, 0);
|
||||
cell.set_sensitive(this._extensionAvailable(uuid));
|
||||
},
|
||||
|
||||
_getExtensionPrefsModule: function(extension) {
|
||||
let uuid = extension.metadata.uuid;
|
||||
|
||||
@ -104,21 +98,13 @@ const Application = new Lang.Class({
|
||||
widget = this._buildErrorUI(extension, e);
|
||||
}
|
||||
|
||||
// Destroy the current prefs widget, if it exists
|
||||
if (this._extensionPrefsBin.get_child())
|
||||
this._extensionPrefsBin.get_child().destroy();
|
||||
|
||||
this._extensionPrefsBin.add(widget);
|
||||
this._extensionSelector.set_active_iter(this._extensionIters[uuid]);
|
||||
},
|
||||
|
||||
_extensionSelected: function() {
|
||||
let [success, iter] = this._extensionSelector.get_active_iter();
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
let uuid = this._model.get_value(iter, 0);
|
||||
this._selectExtension(uuid);
|
||||
let dialog = new Gtk.Dialog({ use_header_bar: true,
|
||||
modal: true,
|
||||
title: extension.metadata.name,
|
||||
transient_for: this._window });
|
||||
dialog.set_default_size(600, 400);
|
||||
dialog.get_content_area().add(widget);
|
||||
dialog.show();
|
||||
},
|
||||
|
||||
_buildErrorUI: function(extension, exc) {
|
||||
@ -151,48 +137,26 @@ const Application = new Lang.Class({
|
||||
|
||||
_buildUI: function(app) {
|
||||
this._window = new Gtk.ApplicationWindow({ application: app,
|
||||
window_position: Gtk.WindowPosition.CENTER,
|
||||
title: _("GNOME Shell Extension Preferences") });
|
||||
window_position: Gtk.WindowPosition.CENTER });
|
||||
|
||||
this._window.set_size_request(600, 400);
|
||||
this._window.set_size_request(800, 500);
|
||||
|
||||
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
||||
this._window.add(vbox);
|
||||
this._titlebar = new Gtk.HeaderBar({ show_close_button: true,
|
||||
title: _("GNOME Shell Extensions") });
|
||||
this._window.set_titlebar(this._titlebar);
|
||||
|
||||
let toolbar = new Gtk.Toolbar();
|
||||
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
|
||||
vbox.add(toolbar);
|
||||
let toolitem;
|
||||
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
shadow_type: Gtk.ShadowType.IN,
|
||||
halign: Gtk.Align.CENTER,
|
||||
margin: 18 });
|
||||
this._window.add(scroll);
|
||||
|
||||
let label = new Gtk.Label({ label: '<b>' + _("Extension") + '</b>',
|
||||
use_markup: true });
|
||||
toolitem = new Gtk.ToolItem({ child: label });
|
||||
toolbar.add(toolitem);
|
||||
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE });
|
||||
this._extensionSelector.set_sort_func(Lang.bind(this, this._sortList));
|
||||
this._extensionSelector.set_header_func(Lang.bind(this, this._updateHeader));
|
||||
|
||||
this._extensionSelector = new Gtk.ComboBox({ model: this._model,
|
||||
margin_left: 8,
|
||||
hexpand: true });
|
||||
this._extensionSelector.get_style_context().add_class(Gtk.STYLE_CLASS_RAISED);
|
||||
scroll.add(this._extensionSelector);
|
||||
|
||||
let renderer = new Gtk.CellRendererText();
|
||||
this._extensionSelector.pack_start(renderer, true);
|
||||
this._extensionSelector.add_attribute(renderer, 'text', 1);
|
||||
this._extensionSelector.set_cell_data_func(renderer, Lang.bind(this, this._setExtensionInsensitive));
|
||||
this._extensionSelector.connect('changed', Lang.bind(this, this._extensionSelected));
|
||||
|
||||
toolitem = new Gtk.ToolItem({ child: this._extensionSelector });
|
||||
toolitem.set_expand(true);
|
||||
toolbar.add(toolitem);
|
||||
|
||||
this._extensionPrefsBin = new Gtk.Frame();
|
||||
vbox.add(this._extensionPrefsBin);
|
||||
|
||||
let label = new Gtk.Label({
|
||||
label: _("Select an extension to configure using the combobox above."),
|
||||
vexpand: true
|
||||
});
|
||||
|
||||
this._extensionPrefsBin.add(label);
|
||||
|
||||
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
|
||||
this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) {
|
||||
@ -203,6 +167,35 @@ const Application = new Lang.Class({
|
||||
this._window.show_all();
|
||||
},
|
||||
|
||||
_addCustomStyle: function() {
|
||||
let provider = new Gtk.CssProvider();
|
||||
|
||||
try {
|
||||
provider.load_from_data(customCss, -1);
|
||||
} catch(e) {
|
||||
log('Failed to add application style');
|
||||
return;
|
||||
}
|
||||
|
||||
let screen = this._window.window.get_screen();
|
||||
let priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION;
|
||||
Gtk.StyleContext.add_provider_for_screen(screen, provider, priority);
|
||||
},
|
||||
|
||||
_sortList: function(row1, row2) {
|
||||
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
|
||||
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
|
||||
return name1.localeCompare(name2);
|
||||
},
|
||||
|
||||
_updateHeader: function(row, before) {
|
||||
if (!before || row.get_header())
|
||||
return;
|
||||
|
||||
let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL });
|
||||
row.set_header(sep);
|
||||
},
|
||||
|
||||
_scanExtensions: function() {
|
||||
let finder = new ExtensionUtils.ExtensionFinder();
|
||||
finder.connect('extension-found', Lang.bind(this, this._extensionFound));
|
||||
@ -211,9 +204,16 @@ const Application = new Lang.Class({
|
||||
},
|
||||
|
||||
_extensionFound: function(finder, extension) {
|
||||
let iter = this._model.append();
|
||||
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
|
||||
this._extensionIters[extension.uuid] = iter;
|
||||
let row = new ExtensionRow(extension.uuid);
|
||||
|
||||
row.prefsButton.visible = this._extensionAvailable(row.uuid);
|
||||
row.prefsButton.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._selectExtension(row.uuid);
|
||||
}));
|
||||
|
||||
row.show_all();
|
||||
this._extensionSelector.add(row);
|
||||
},
|
||||
|
||||
_extensionsLoaded: function() {
|
||||
@ -227,8 +227,8 @@ const Application = new Lang.Class({
|
||||
},
|
||||
|
||||
_onStartup: function(app) {
|
||||
this._buildModel();
|
||||
this._buildUI(app);
|
||||
this._addCustomStyle();
|
||||
this._scanExtensions();
|
||||
},
|
||||
|
||||
@ -250,6 +250,53 @@ const Application = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const ExtensionRow = new Lang.Class({
|
||||
Name: 'ExtensionRow',
|
||||
Extends: Gtk.ListBoxRow,
|
||||
|
||||
_init: function(uuid) {
|
||||
this.parent();
|
||||
|
||||
this.uuid = uuid;
|
||||
|
||||
this._buildUI();
|
||||
},
|
||||
|
||||
_buildUI: function() {
|
||||
let extension = ExtensionUtils.extensions[this.uuid];
|
||||
|
||||
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
|
||||
hexpand: true, margin: 12, spacing: 6 });
|
||||
this.add(hbox);
|
||||
|
||||
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 6, hexpand: true });
|
||||
hbox.add(vbox);
|
||||
|
||||
let name = GLib.markup_escape_text(extension.metadata.name, -1);
|
||||
let label = new Gtk.Label({ label: '<b>' + name + '</b>',
|
||||
use_markup: true,
|
||||
halign: Gtk.Align.START });
|
||||
vbox.add(label);
|
||||
|
||||
let desc = extension.metadata.description.split('\n')[0];
|
||||
label = new Gtk.Label({ label: desc,
|
||||
ellipsize: Pango.EllipsizeMode.END,
|
||||
halign: Gtk.Align.START });
|
||||
vbox.add(label);
|
||||
|
||||
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
|
||||
no_show_all: true });
|
||||
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
|
||||
icon_size: Gtk.IconSize.BUTTON,
|
||||
visible: true }));
|
||||
button.get_style_context().add_class('prefs-button');
|
||||
hbox.add(button);
|
||||
|
||||
this.prefsButton = button;
|
||||
}
|
||||
});
|
||||
|
||||
function initEnvironment() {
|
||||
// Monkey-patch in a "global" object that fakes some Shell utilities
|
||||
// that ExtensionUtils depends on.
|
||||
|
Loading…
Reference in New Issue
Block a user