From 53b3d2a6c268f9d9549a0d60416d6a490d5e6157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 17 Feb 2015 01:13:48 +0100 Subject: [PATCH] messageTray: Add NotificationBanner actor We no longer have a single notification actor that is either displayed as banner or reparented to the summary depending on state - both the lock screen and the notification section of the message list create their own UI based on the information attached to the notification object. Adding to this that different representations of a notification may now exist simultaneously (as they are included in the message list immediately rather than after the banner has been displayed), it no longer makes sense to keep the banner actor in the notification itself. Add a new NotificationBanner class that provides a separate banner implementation based on the message list's NotificationMessage that will soon replace the existing notification banners. --- data/theme/gnome-shell-sass | 2 +- data/theme/gnome-shell.css | 33 +++++++++++++ js/ui/messageTray.js | 92 +++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/data/theme/gnome-shell-sass b/data/theme/gnome-shell-sass index 860102c31..de2baea3f 160000 --- a/data/theme/gnome-shell-sass +++ b/data/theme/gnome-shell-sass @@ -1 +1 @@ -Subproject commit 860102c31bda598df340f2d68ea5be18e52da176 +Subproject commit de2baea3f921a28160a9be154683776338c1b5c2 diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index f9e2086b7..63c79d940 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -1146,6 +1146,39 @@ StScrollBar { .url-highlighter { link-color: #215d9c; } +.notification-banner { + font-size: 11pt; + width: 34em; + margin: 5px; + border-radius: 6px; + color: #eeeeec; + background-color: #2e3436; + border: 1px solid #1c1f1f; } + .notification-banner:hover { + background-color: #2e3436; } + .notification-banner:focus { + background-color: #2e3436; } + .notification-banner .notification-icon { + padding: 5px; } + .notification-banner .notification-content { + padding: 5px; + spacing: 5px; } + .notification-banner .secondary-icon { + icon-size: 1.09em; } + .notification-banner .notification-actions { + background-color: #1c1f1f; + padding-top: 2px; + spacing: 1px; } + .notification-banner .notification-button { + padding: 4px 4px 5px; + background-color: #222728; } + .notification-banner .notification-button:first-child { + border-radius: 0 0 0 6px; } + .notification-banner .notification-button:last-child { + border-radius: 0 0 6px 0; } + .notification-banner .notification-button:hover, .notification-banner .notification-buttonfocus { + background-color: #292f30; } + .notification { font-size: 11pt; width: 34em; diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js index a9ee24f06..32f8578dd 100644 --- a/js/ui/messageTray.js +++ b/js/ui/messageTray.js @@ -13,6 +13,7 @@ const Shell = imports.gi.Shell; const Signals = imports.signals; const St = imports.gi.St; +const Calendar = imports.ui.calendar; const GnomeSession = imports.misc.gnomeSession; const Main = imports.ui.main; const Params = imports.misc.params; @@ -1105,6 +1106,97 @@ const Notification = new Lang.Class({ }); Signals.addSignalMethods(Notification.prototype); +const NotificationBanner = new Lang.Class({ + Name: 'NotificationBanner', + Extends: Calendar.NotificationMessage, + + _init: function(notification) { + this.parent(notification); + + this.actor.add_style_class_name('notification-banner'); + this.actor.connect('destroy', Lang.bind(this, this._onDestroyed)); + + this._buttonBox = null; + + this._addActions(); + this._addSecondaryIcon(); + + this._activatedId = this.notification.connect('activated', + Lang.bind(this, function() { + // We hide all types of notifications once the user clicks on + // them because the common outcome of clicking should be the + // relevant window being brought forward and the user's + // attention switching to the window. + this.emit('done-displaying'); + })); + }, + + _onDestroyed: function() { + this.notification.disconnect(this._activatedId); + }, + + _onUpdated: function(n, clear) { + this.parent(n, clear); + + if (clear) { + this.setSecondaryActor(null); + this.setActionArea(null); + this._buttonBox = null; + } + + this._addActions(); + this._addSecondaryIcon(); + }, + + _addActions: function() { + this.notification.actions.forEach(Lang.bind(this, + function(action) { + this.addAction(action.label, action.callback); + })); + }, + + _addSecondaryIcon: function() { + if (this.notification.secondaryGIcon) { + let icon = new St.Icon({ gicon: this.notification.secondaryGIcon }); + this.setSecondaryActor(icon); + } + }, + + addButton: function(button, callback) { + if (!this._buttonBox) { + this._buttonBox = new St.BoxLayout({ style_class: 'notification-actions', + x_expand: true }); + this.setActionArea(this._buttonBox); + global.focus_manager.add_group(this._buttonBox); + } + + this._buttonBox.add(button); + button.connect('clicked', Lang.bind(this, function() { + callback(); + + if (!this.notification.resident) { + // We don't hide a resident notification when the user invokes one of its actions, + // because it is common for such notifications to update themselves with new + // information based on the action. We'd like to display the updated information + // in place, rather than pop-up a new notification. + this.emit('done-displaying'); + this.notification.destroy(); + } + })); + + return button; + }, + + addAction: function(label, callback) { + let button = new St.Button({ style_class: 'notification-button', + label: label, + x_expand: true, + can_focus: true }); + + return this.addButton(button, callback); + } +}); + const SourceActor = new Lang.Class({ Name: 'SourceActor',