[gnome-shell/wip/session-menu: 1/2] loginDialog: Move the session list to a PopupMenu



commit df6f6b7368d916cbd05f6854815e77806ccbe1cf
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Jun 23 23:14:10 2013 -0400

    loginDialog: Move the session list to a PopupMenu
    
    There are some issues with the existing session menu. First, it looks
    kinda bad. It seems like it's hanging around there, but it doesn't really know
    what to do with itself.
    
    Second, when it expands down it requires that the buttons below move
    down with it. This kind of movement is awkward and looks a bit weird.
    
    Third, it's current position makes the "dialog" tall and unwieldy when
    you add things like messages for finger print readers or authentication errors.
    
    This commit moves the session list to a menu behind a button to address
    the above problems.
    
    Some updates to patch by Ray Strode.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=702818

 data/theme/gnome-shell.css |   38 ++-------
 js/gdm/loginDialog.js      |  213 +++++++++++++-------------------------------
 2 files changed, 70 insertions(+), 181 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 4c76ff2..765894a 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -2350,43 +2350,17 @@ StScrollBar StButton#vhandle:active {
     width: 15em;
 }
 
-.login-dialog-session-list,
-.login-dialog-session-list-item {
-    color: #babdb6;
-}
-
-.login-dialog-session-list-button:focus,
-.login-dialog-session-list-button:active,
-.login-dialog-session-list-button:hover,
-.login-dialog-session-list-item:focus,
-.login-dialog-session-list-item:hover {
-    color: white;
+.login-dialog-session-list-button StIcon {
+    icon-size: 1.25em;
 }
 
 .login-dialog-session-list-button {
-    padding: 4px;
+    color: #8b8b8b;
 }
 
-.login-dialog-session-list-scroll-view {
-    padding: 6px;
-}
-
-.login-dialog-session-list-item {
-    padding-bottom: 6px;
-}
-
-.login-dialog-session-list-triangle {
-    padding-right: 6px;
-}
-
-.login-dialog-session-list-item-box {
-    padding-left: 6px;
-    spacing: 6px;
-}
-
-.login-dialog-session-list-item-dot {
-    width: 10px;
-    height: 10px;
+.login-dialog-session-list-button:hover,
+.login-dialog-session-list-button:active {
+    color: white;
 }
 
 .login-dialog-logo-bin {
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index af5103a..0ac774b 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -34,10 +34,12 @@ const St = imports.gi.St;
 
 const Animation = imports.ui.animation;
 const Batch = imports.gdm.batch;
+const BoxPointer = imports.ui.boxpointer;
 const CtrlAltTab = imports.ui.ctrlAltTab;
 const GdmUtil = imports.gdm.util;
 const Layout = imports.ui.layout;
 const Main = imports.ui.main;
+const PopupMenu = imports.ui.popupMenu;
 const Realmd = imports.gdm.realmd;
 const Tweener = imports.ui.tweener;
 const UserWidget = imports.ui.userWidget;
@@ -288,184 +290,102 @@ const UserList = new Lang.Class({
 });
 Signals.addSignalMethods(UserList.prototype);
 
-const SessionListItem = new Lang.Class({
-    Name: 'SessionListItem',
-
-    _init: function(id, name) {
-        this.id = id;
-
-        this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
-                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
-                                     can_focus: true,
-                                     reactive: true,
-                                     x_fill: true,
-                                     x_align: St.Align.START });
-
-        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' });
-
-        this.actor.add_actor(this._box);
-        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
-
-        this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' });
-        this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
-        this._box.add_actor(this._dot);
-        this.setShowDot(false);
-
-        let label = new St.Label({ style_class: 'login-dialog-session-list-item-label',
-                                   text: name });
-        this.actor.label_actor = label;
-
-        this._box.add_actor(label);
-    },
-
-    setShowDot: function(show) {
-        if (show)
-            this._dot.opacity = 255;
-        else
-            this._dot.opacity = 0;
-    },
-
-    _onRepaintDot: function(area) {
-        let cr = area.get_context();
-        let [width, height] = area.get_surface_size();
-        let color = area.get_theme_node().get_foreground_color();
-
-        cr.setSourceRGBA (color.red / 255,
-                          color.green / 255,
-                          color.blue / 255,
-                          color.alpha / 255);
-        cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
-        cr.fill();
-        cr.$dispose();
-    },
-
-    _onClicked: function() {
-        this.emit('activate');
-    }
-});
-Signals.addSignalMethods(SessionListItem.prototype);
-
 const SessionList = new Lang.Class({
     Name: 'SessionList',
 
     _init: function() {
-        this.actor = new St.Bin();
-
-        this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list',
-                                       vertical: true});
-        this.actor.child = this._box;
-
+        let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
         this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
-                                       button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
+                                       reactive: true,
+                                       track_hover: true,
                                        can_focus: true,
-                                       x_fill: true,
-                                       y_fill: true });
-        let box = new St.BoxLayout();
-        this._button.add_actor(box);
-
-        this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle',
-                                        text: '\u25B8' });
-        box.add_actor(this._triangle);
-
-        let label = new St.Label({ style_class: 'login-dialog-session-list-label',
-                                   text: _("Session…") });
-        box.add_actor(label);
-
-        this._button.connect('clicked',
-                             Lang.bind(this, this._onClicked));
-        this._box.add_actor(this._button);
-        this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'});
-        this._scrollView.set_policy(Gtk.PolicyType.NEVER,
-                                    Gtk.PolicyType.AUTOMATIC);
-        this._box.add_actor(this._scrollView);
-        this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list',
-                                            vertical: true });
-        this._scrollView.add_actor(this._itemList);
-        this._scrollView.hide();
-        this.isOpen = false;
-        this._populate();
-    },
+                                       accessible_name: _("Choose Session"),
+                                       accessible_role: Atk.Role.MENU,
+                                       child: gearIcon });
 
-    open: function() {
-        if (this.isOpen)
-            return;
+        this.actor = new St.Bin({ child: this._button });
 
-        this._button.add_style_pseudo_class('open');
-        this._scrollView.show();
-        this._triangle.set_text('\u25BE');
+        this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
+        Main.uiGroup.add_actor(this._menu.actor);
+        this._menu.actor.hide();
 
-        this.isOpen = true;
-    },
+        this._menu.connect('open-state-changed',
+                           Lang.bind(this, function(menu, isOpen) {
+                                if (isOpen)
+                                    this._button.add_style_pseudo_class('active');
+                                else
+                                    this._button.remove_style_pseudo_class('active');
+                           }));
 
-    close: function() {
-        if (!this.isOpen)
-            return;
+        let subtitle = new PopupMenu.PopupMenuItem(_("Session"), { style_class: 'popup-subtitle-menu-item',
+                                                                   reactive: false });
+        this._menu.addMenuItem(subtitle);
 
-        this._button.remove_style_pseudo_class('open');
-        this._scrollView.hide();
-        this._triangle.set_text('\u25B8');
+        this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
+        this._manager.addMenu(this._menu);
 
-        this.isOpen = false;
-    },
+        this._button.connect('clicked', Lang.bind(this, function() {
+            this._menu.toggle();
+        }));
 
-    _onClicked: function() {
-        if (!this.isOpen)
-            this.open();
-        else
-            this.close();
+        this._items = {};
+        this._activeSessionId = null;
+        this._populate();
     },
 
     updateSensitivity: function(sensitive) {
         this._button.reactive = sensitive;
         this._button.can_focus = sensitive;
+        this._menu.close(BoxPointer.PopupAnimation.NONE);
+    },
 
-        for (let id in this._items)
-            this._items[id].actor.reactive = sensitive;
+    _updateOrnament: function() {
+        let itemIds = Object.keys(this._items);
+        for (let i = 0; i < itemIds.length; i++) {
+            if (itemIds[i] == this._activeSessionId)
+                this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.DOT);
+            else
+                this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE);
+        }
     },
 
     setActiveSession: function(sessionId) {
          if (sessionId == this._activeSessionId)
              return;
 
-         if (this._activeSessionId)
-             this._items[this._activeSessionId].setShowDot(false);
-
-         this._items[sessionId].setShowDot(true);
          this._activeSessionId = sessionId;
+         this._updateOrnament();
 
          this.emit('session-activated', this._activeSessionId);
     },
 
-    _populate: function() {
-        this._itemList.destroy_all_children();
-        this._activeSessionId = null;
-        this._items = {};
+    close: function() {
+        this._menu.close();
+    },
 
+    _populate: function() {
         let ids = Gdm.get_session_ids();
         ids.sort();
 
         if (ids.length <= 1) {
-            this._box.hide();
             this._button.hide();
-        } else {
-            this._button.show();
-            this._box.show();
+            return;
         }
 
         for (let i = 0; i < ids.length; i++) {
             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
 
-            let item = new SessionListItem(ids[i], sessionName);
-            this._itemList.add_actor(item.actor);
-            this._items[ids[i]] = item;
+            let id = ids[i];
+            let item = new PopupMenu.PopupMenuItem(sessionName);
+            this._menu.addMenuItem(item);
+            this._items[id] = item;
 
             if (!this._activeSessionId)
-                this.setActiveSession(ids[i]);
+                this.setActiveSession(id);
 
-            item.connect('activate',
-                         Lang.bind(this, function() {
-                             this.setActiveSession(item.id);
-                         }));
+            item.connect('activate', Lang.bind(this, function() {
+                this.setActiveSession(id);
+            }));
         }
     }
 });
@@ -585,17 +505,6 @@ const LoginDialog = new Lang.Class({
         this._promptLoginHint.hide();
         this._promptBox.add(this._promptLoginHint);
 
-        this._sessionList = new SessionList();
-        this._sessionList.connect('session-activated',
-                                  Lang.bind(this, function(list, sessionId) {
-                                                this._greeter.call_select_session_sync (sessionId, null);
-                                            }));
-
-        this._promptBox.add(this._sessionList.actor,
-                            { expand: true,
-                              x_fill: false,
-                              y_fill: true,
-                              x_align: St.Align.START });
         this._buttonBox = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
                                              vertical: false });
         this._promptBox.add(this._buttonBox,
@@ -655,6 +564,11 @@ const LoginDialog = new Lang.Class({
                                    this._onUserListActivated(item);
                                }));
 
+        this._sessionList = new SessionList();
+        this._sessionList.connect('session-activated',
+                                  Lang.bind(this, function(list, sessionId) {
+                                                this._greeter.call_select_session_sync (sessionId, null);
+                                            }));
    },
 
     _updateDisableUserList: function() {
@@ -814,7 +728,7 @@ const LoginDialog = new Lang.Class({
 
     _prepareDialog: function(forSecret, hold) {
         this._buttonBox.visible = true;
-        this._buttonBox.destroy_all_children();
+        this._buttonBox.remove_all_children();
 
         if (!this._disableUserList || this._verifyingUser) {
             this._cancelButton = new St.Button({ style_class: 'modal-dialog-button',
@@ -843,6 +757,9 @@ const LoginDialog = new Lang.Class({
                             { expand: false,
                               x_align: St.Align.END });
 
+        this._buttonBox.add(this._sessionList.actor,
+                            { expand: false,
+                              x_align: St.Align.END });
         this._signInButton = new St.Button({ style_class: 'modal-dialog-button',
                                              button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
                                              reactive: true,
@@ -889,8 +806,6 @@ const LoginDialog = new Lang.Class({
     },
 
     _hidePrompt: function() {
-        this._buttonBox.destroy_all_children();
-
         if (this._promptEntryTextChangedId > 0) {
             this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId);
             this._promptEntryTextChangedId = 0;
@@ -913,7 +828,7 @@ const LoginDialog = new Lang.Class({
         this._sessionList.close();
         this._promptLoginHint.hide();
 
-        this._buttonBox.destroy_all_children();
+        this._buttonBox.remove_all_children();
         this._signInButton = null;
         this._cancelButton = null;
     },


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