[gnome-shell/user-status-update: 3/12] status-menu: Implement new mockups



commit b79c5921ba7b9a26375dcc2c96d48963714e6a82
Author: Florian MÃllner <fmuellner gnome org>
Date:   Thu Jul 28 16:59:03 2011 +0200

    status-menu: Implement new mockups

 data/theme/gnome-shell.css |   15 ++
 js/ui/statusMenu.js        |  344 +++++++++++++++++++++++++++++++++++++-------
 2 files changed, 308 insertions(+), 51 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index ef8cb0d..65c2b0d 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -354,6 +354,21 @@ StTooltip StLabel {
     spacing: 4px;
 }
 
+.status-chooser .popup-menu-item {
+    padding: .4em 0.75em;
+}
+
+.status-chooser-user-icon {
+    border: 2px solid #8b8b8b;
+    border-radius: 5px;
+    width: 64px;
+    height: 64px;
+}
+
+.status-chooser-user-name {
+    font-weight: bold;
+}
+
 #legacyTray {
     spacing: 14px;
     padding-left: 14px;
diff --git a/js/ui/statusMenu.js b/js/ui/statusMenu.js
index c506be0..a250f33 100644
--- a/js/ui/statusMenu.js
+++ b/js/ui/statusMenu.js
@@ -22,11 +22,263 @@ const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
 const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
 const DISABLE_LOG_OUT_KEY = 'disable-log-out';
 
+const IMStatus = {
+    AVAILABLE: 0,
+    BUSY: 1,
+    HIDDEN: 2,
+    AWAY: 3,
+    IDLE: 4,
+    OFFLINE: 5,
+    LAST: 6
+};
+
 // Adapted from gdm/gui/user-switch-applet/applet.c
 //
 // Copyright (C) 2004-2005 James M. Cape <jcape ignore-your tv>.
 // Copyright (C) 2008,2009 Red Hat, Inc.
 
+
+function IMStatusItem(label, iconName) {
+    this._init(label, iconName);
+}
+
+IMStatusItem.prototype = {
+    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+
+    _init: function(label, iconName) {
+        PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
+
+        this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
+        this.addActor(this._icon);
+
+        if (iconName)
+            this._icon.icon_name = iconName;
+
+        this.label = new St.Label({ text: label });
+        this.addActor(this.label);
+    }
+};
+
+function IMStatusChooserItem() {
+    this._init();
+}
+
+IMStatusChooserItem.prototype = {
+    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+
+    _init: function() {
+        PopupMenu.PopupBaseMenuItem.prototype._init.call (this,
+                                                          { reactive: false,
+                                                            style_class: 'status-chooser' });
+
+        this._iconBin = new St.Bin({ style_class: 'status-chooser-user-icon' });
+        this.addActor(this._iconBin);
+
+        this._section = new PopupMenu.PopupMenuSection();
+        this.addActor(this._section.actor);
+
+        this._name = new PopupMenu.PopupMenuItem('',
+                                                 { reactive: false,
+                                                   style_class: 'status-chooser-user-name' });
+        this._section.addMenuItem(this._name);
+
+        this._combo = new PopupMenu.PopupComboBoxMenuItem();
+        this._section.addMenuItem(this._combo);
+
+        let item;
+
+        item = new IMStatusItem(_("Available"), 'user-available');
+        this._combo.addMenuItem(item, IMStatus.AVAILABLE);
+
+        item = new IMStatusItem(_("Busy"), 'user-busy');
+        this._combo.addMenuItem(item, IMStatus.BUSY);
+
+        item = new IMStatusItem(_("Hidden"), 'user-invisible');
+        this._combo.addMenuItem(item, IMStatus.HIDDEN);
+
+        item = new IMStatusItem(_("Away"), 'user-away');
+        this._combo.addMenuItem(item, IMStatus.AWAY);
+
+        item = new IMStatusItem(_("Idle"), 'user-idle');
+        this._combo.addMenuItem(item, IMStatus.IDLE);
+
+        item = new IMStatusItem(_("Unavailable"), 'user-offline');
+        this._combo.addMenuItem(item, IMStatus.OFFLINE);
+
+        this._combo.connect('active-item-changed',
+                            Lang.bind(this, this._changeIMStatus));
+
+        this._presence = new GnomeSession.Presence();
+        this._presence.getStatus(Lang.bind(this, this._sessionStatusChanged));
+        this._presence.connect('StatusChanged',
+                               Lang.bind(this, this._sessionStatusChanged));
+
+        this._accountMgr = Tp.AccountManager.dup()
+        let [presence, s, msg] = this._accountMgr.get_most_available_presence();
+
+        this._previousPresence = presence;
+        this._accountMgr.connect('most-available-presence-changed',
+                                 Lang.bind(this, this._IMStatusChanged));
+
+        this._gdm = Gdm.UserManager.ref_default();
+        this._gdm.queue_load();
+
+        this._user = this._gdm.get_user(GLib.get_user_name());
+
+        this._userLoadedId = this._user.connect('notify::is-loaded',
+                                                Lang.bind(this,
+                                                          this._updateUser));
+        this._userChangedId = this._user.connect('changed',
+                                                 Lang.bind(this,
+                                                           this._updateUser));
+    },
+
+    // Override getColumnWidths()/setColumnWidths() to make the item
+    // independent from the overall column layout of the menu
+    getColumnWidths: function() {
+        return [];
+    },
+
+    setColumnWidths: function(widths) {
+        this._columnWidths = PopupMenu.PopupBaseMenuItem.prototype.getColumnWidths.call(this);
+        let sectionWidths = this._section.getColumnWidths();
+        this._section.setColumnWidths(sectionWidths);
+    },
+
+    _updateUser: function() {
+        let iconFile = null;
+        if (this._user.is_loaded) {
+          this._name.label.set_text(this._user.get_real_name());
+          iconFile = this._user.get_icon_file();
+          if (!GLib.file_test(iconFile, GLib.FileTest.EXISTS))
+              iconFile = null;
+        } else {
+          this._name.label.set_text("");
+        }
+
+        if (iconFile)
+            this._setIconFromFile(iconFile);
+        else
+            this._setIconFromName('avatar-default');
+    },
+
+    _setIconFromFile: function(iconFile) {
+        this._iconBin.set_style('background-image: url("' + iconFile + '");');
+    },
+
+    _setIconFromName: function(iconName) {
+        this._iconBin.set_style(null);
+
+        if (iconName != null) {
+            let textureCache = St.TextureCache.get_default();
+            let icon = textureCache.load_icon_name(this._iconBin.get_theme_node(),
+                                                   iconName,
+                                                   St.IconType.SYMBOLIC,
+                                                   _DIALOG_ICON_SIZE);
+
+            this._iconBin.child = icon;
+            this._iconBin.show();
+        } else {
+            this._iconBin.child = null;
+            this._iconBin.hide();
+        }
+    },
+
+    _statusForPresence: function(presence) {
+        switch(presence) {
+            case Tp.ConnectionPresenceType.AVAILABLE:
+                return _("Available");
+            case Tp.ConnectionPresenceType.BUSY:
+                return _("Busy");
+            case Tp.ConnectionPresenceType.OFFLINE:
+                return _("Unavailable");
+            case Tp.ConnectionPresenceType.HIDDEN:
+                return _("Hidden");
+            case Tp.ConnectionPresenceType.AWAY:
+                return _("Away");
+            case Tp.ConnectionPresenceType.EXTENDED_AWAY:
+                return _("Idle");
+            default:
+                return _("Unknown");
+        }
+    },
+
+    _IMStatusChanged: function(accountMgr, presence, status, message) {
+        if (presence == Tp.ConnectionPresenceType.AVAILABLE)
+            this._presence.setStatus(GnomeSession.PresenceStatus.AVAILABLE);
+
+        if (!this._expectedPresence || presence != this._expectedPresence)
+            this._previousPresence = presence;
+        else
+            this._expectedPresence = undefined;
+
+        let activatedItem;
+
+        if (presence == Tp.ConnectionPresenceType.AVAILABLE)
+            activatedItem = IMStatus.AVAILABLE;
+        else if (presence == Tp.ConnectionPresenceType.BUSY)
+            activatedItem = IMStatus.BUSY;
+        else if (presence == Tp.ConnectionPresenceType.HIDDEN)
+            activatedItem = IMStatus.HIDDEN;
+        else if (presence == Tp.ConnectionPresenceType.AWAY)
+            activatedItem = IMStatus.AWAY;
+        else if (presence == Tp.ConnectionPresenceType.EXTENDED_AWAY)
+            activatedItem = IMStatus.IDLE;
+        else if (presence == Tp.ConnectionPresenceType.OFFLINE)
+            activatedItem = IMStatus.OFFLINE;
+
+        this._combo.setActiveItem(activatedItem);
+        for (let i = 0; i < IMStatus.LAST; i++) {
+            if (i == IMStatus.AVAILABLE || i == IMStatus.OFFLINE)
+                continue;   // always visible
+
+            this._combo.setItemVisible(i, i == activatedItem);
+        }
+    },
+
+    _changeIMStatus: function(menuItem, id) {
+        let [presence, s, msg] = this._accountMgr.get_most_available_presence();
+        let newPresence, status;
+
+        if (id == IMStatus.AVAILABLE) {
+            newPresence = Tp.ConnectionPresenceType.AVAILABLE;
+        } else if (id == IMStatus.OFFLINE) {
+            newPresence = Tp.ConnectionPresenceType.OFFLINE;
+        } else
+            return;
+
+        status = this._statusForPresence(newPresence);
+        msg = msg ? msg : "";
+        this._accountMgr.set_all_requested_presences(newPresence, status, msg);
+    },
+
+    _sessionStatusChanged: function(sessionPresence, sessionStatus) {
+        let [presence, s, msg] = this._accountMgr.get_most_available_presence();
+        let newPresence, status;
+
+        if (sessionStatus == GnomeSession.PresenceStatus.AVAILABLE) {
+            newPresence = this._previousPresence;
+        } else if (sessionStatus == GnomeSession.PresenceStatus.BUSY) {
+            // Only change presence if the current one is "more present" than
+            // busy
+            if (presence == Tp.ConnectionPresenceType.AVAILABLE) {
+                newPresence = Tp.ConnectionPresenceType.BUSY;
+            } else {
+                return;
+            }
+        } else {
+            return;
+        }
+
+        status = this._statusForPresence(newPresence);
+        msg = msg ? msg : "";
+
+        this._expectedPresence = newPresence;
+        this._accountMgr.set_all_requested_presences(newPresence, status, msg);
+    }
+};
+
+
 function StatusMenuButton() {
     this._init();
 }
@@ -46,7 +298,6 @@ StatusMenuButton.prototype = {
 
         this._user = this._gdm.get_user(GLib.get_user_name());
         this._presence = new GnomeSession.Presence();
-        this._presenceItems = {};
         this._session = new GnomeSession.SessionManager();
         this._haveShutdown = true;
 
@@ -60,13 +311,26 @@ StatusMenuButton.prototype = {
         box.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false });
 
         let textureCache = St.TextureCache.get_default();
-        this._availableIcon = new St.Icon({ icon_name: 'user-available', style_class: 'popup-menu-icon' });
-        this._busyIcon = new St.Icon({ icon_name: 'user-busy', style_class: 'popup-menu-icon' });
-        this._invisibleIcon = new St.Icon({ icon_name: 'user-invisible', style_class: 'popup-menu-icon' });
-        this._idleIcon = new St.Icon({ icon_name: 'user-idle', style_class: 'popup-menu-icon' });
-
-        this._presence.connect('StatusChanged', Lang.bind(this, this._updatePresenceIcon));
-        this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon));
+        this._offlineIcon = new St.Icon({ icon_name: 'user-offline',
+                                          style_class: 'popup-menu-icon' });
+        this._availableIcon = new St.Icon({ icon_name: 'user-available',
+                                            style_class: 'popup-menu-icon' });
+        this._busyIcon = new St.Icon({ icon_name: 'user-busy',
+                                       style_class: 'popup-menu-icon' });
+        this._invisibleIcon = new St.Icon({ icon_name: 'user-invisible',
+                                            style_class: 'popup-menu-icon' });
+        this._awayIcon = new St.Icon({ icon_name: 'user-away',
+                                       style_class: 'popup-menu-icon' });
+        this._idleIcon = new St.Icon({ icon_name: 'user-idle',
+                                       style_class: 'popup-menu-icon' });
+
+        this._presence.connect('StatusChanged',
+                               Lang.bind(this, this._updateSwitch));
+        this._presence.getStatus(Lang.bind(this, this._updateSwitch));
+
+        this._account_mgr.connect('most-available-presence-changed',
+                                  Lang.bind(this, this._updatePresenceIcon));
+        this._updatePresenceIcon();
 
         this._name = new St.Label();
         box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false });
@@ -197,32 +461,36 @@ StatusMenuButton.prototype = {
         }
     },
 
-    _updatePresenceIcon: function(presence, status) {
-        if (status == GnomeSession.PresenceStatus.AVAILABLE)
+    _updateSwitch: function(presence, status) {
+        let active = status == GnomeSession.PresenceStatus.BUSY;
+        this._dontDisturbSwitch.setToggleState(active);
+    },
+
+    _updatePresenceIcon: function(accountMgr, presence, status, message) {
+        if (presence == Tp.ConnectionPresenceType.OFFLINE)
+            this._iconBox.child = this._offlineIcon;
+        else if (presence == Tp.ConnectionPresenceType.AVAILABLE)
             this._iconBox.child = this._availableIcon;
-        else if (status == GnomeSession.PresenceStatus.BUSY)
+        else if (presence == Tp.ConnectionPresenceType.BUSY)
             this._iconBox.child = this._busyIcon;
-        else if (status == GnomeSession.PresenceStatus.INVISIBLE)
+        else if (presence == Tp.ConnectionPresenceType.HIDDEN)
             this._iconBox.child = this._invisibleIcon;
-        else
+        else if (presence == Tp.ConnectionPresenceType.AWAY)
+            this._iconBox.child = this._awayIcon;
+        else if (presence == Tp.ConnectionPresenceType.EXTENDED_AWAY)
             this._iconBox.child = this._idleIcon;
-
-        for (let itemStatus in this._presenceItems)
-            this._presenceItems[itemStatus].setShowDot(itemStatus == status);
     },
 
     _createSubMenu: function() {
         let item;
 
-        item = new PopupMenu.PopupImageMenuItem(_("Available"), 'user-available');
-        item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.AVAILABLE));
+        item = new IMStatusChooserItem();
         this.menu.addMenuItem(item);
-        this._presenceItems[GnomeSession.PresenceStatus.AVAILABLE] = item;
 
-        item = new PopupMenu.PopupImageMenuItem(_("Busy"), 'user-busy');
-        item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.BUSY));
+        item = new PopupMenu.PopupSwitchMenuItem(_("Do Not Disturb"));
+        item.connect('activate', Lang.bind(this, this._updatePresenceStatus));
         this.menu.addMenuItem(item);
-        this._presenceItems[GnomeSession.PresenceStatus.BUSY] = item;
+        this._dontDisturbSwitch = item;
 
         item = new PopupMenu.PopupSeparatorMenuItem();
         this.menu.addMenuItem(item);
@@ -266,10 +534,10 @@ StatusMenuButton.prototype = {
         this._updateSuspendOrPowerOff();
     },
 
-    _setPresenceStatus: function(item, event, status) {
+    _updatePresenceStatus: function(item, event) {
+        let status = item.state ? GnomeSession.PresenceStatus.BUSY
+                                : GnomeSession.PresenceStatus.AVAILABLE;
         this._presence.setStatus(status);
-
-        this._setIMStatus(status);
     },
 
     _onMyAccountActivate: function() {
@@ -315,31 +583,5 @@ StatusMenuButton.prototype = {
         } else {
             this._session.ShutdownRemote();
         }
-    },
-
-    _setIMStatus: function(session_status) {
-        let [presence_type, presence_status, msg] = this._account_mgr.get_most_available_presence();
-        let type, status;
-
-        // We change the IM presence only if there are connected accounts
-        if (presence_type == Tp.ConnectionPresenceType.UNSET ||
-            presence_type == Tp.ConnectionPresenceType.OFFLINE ||
-            presence_type == Tp.ConnectionPresenceType.UNKNOWN ||
-            presence_type == Tp.ConnectionPresenceType.ERROR)
-          return;
-
-        if (session_status == GnomeSession.PresenceStatus.AVAILABLE) {
-            type = Tp.ConnectionPresenceType.AVAILABLE;
-            status = "available";
-        }
-        else if (session_status == GnomeSession.PresenceStatus.BUSY) {
-            type = Tp.ConnectionPresenceType.BUSY;
-            status = "busy";
-        }
-        else {
-          return;
-        }
-
-        this._account_mgr.set_all_requested_presences(type, status, msg);
     }
 };



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