[gnome-shell] extension-prefs: Give the UI a bit of GNOME 3 treatment



commit e1b30b292417b2a126d9742fe70e567f5e3e02e8
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri May 23 04:49:37 2014 +0200

    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

 js/extensionPrefs/main.js |  179 ++++++++++++++++++++++++++++-----------------
 1 files changed, 113 insertions(+), 66 deletions(-)
---
diff --git a/js/extensionPrefs/main.js b/js/extensionPrefs/main.js
index a3f516e..1dd09b1 100644
--- a/js/extensionPrefs/main.js
+++ b/js/extensionPrefs/main.js
@@ -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.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]