[gnome-shell/wip/fmuellner/notification-redux+sass: 34/122] messageTray: Update notification banner
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/fmuellner/notification-redux+sass: 34/122] messageTray: Update notification banner
- Date: Tue, 17 Feb 2015 15:06:50 +0000 (UTC)
commit 85976ec88a9f739b09194eb6cef127cec83ba405
Author: Florian Müllner <fmuellner gnome org>
Date: Wed Feb 11 20:20:03 2015 +0100
messageTray: Update notification banner
js/ui/messageTray.js | 275 +++++++-------------------------------------------
1 files changed, 35 insertions(+), 240 deletions(-)
---
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index f4da406..bc1b6fc 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -486,8 +486,6 @@ const Notification = new Lang.Class({
this.bannerBodyText = null;
this.bannerBodyMarkup = false;
this._bannerBodyAdded = false;
- this._titleFitsInBannerMode = true;
- this._spacing = 0;
this._scrollPolicy = Gtk.PolicyType.AUTOMATIC;
this._soundName = null;
this._soundFile = null;
@@ -499,40 +497,23 @@ const Notification = new Lang.Class({
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
- this._table = new St.Table({ style_class: 'notification',
- reactive: true });
- this._table.connect('style-changed', Lang.bind(this, this._styleChanged));
- this.actor.set_child(this._table);
-
- // The first line should have the title, followed by the
- // banner text, but ellipsized if they won't both fit. We can't
- // make St.Table or St.BoxLayout do this the way we want (don't
- // show banner at all if title needs to be ellipsized), so we
- // use Shell.GenericContainer.
- this._bannerBox = new Shell.GenericContainer();
- this._bannerBox.connect('get-preferred-width', Lang.bind(this, this._bannerBoxGetPreferredWidth));
- this._bannerBox.connect('get-preferred-height', Lang.bind(this, this._bannerBoxGetPreferredHeight));
- this._bannerBox.connect('allocate', Lang.bind(this, this._bannerBoxAllocate));
- this._table.add(this._bannerBox, { row: 0,
- col: 1,
- col_span: 2,
- x_expand: false,
- y_expand: false,
- y_fill: false });
-
- // This is an empty cell that overlaps with this._bannerBox cell to ensure
- // that this._bannerBox cell expands horizontally, while not forcing the
- // this._imageBin that is also in col: 2 to expand horizontally.
- this._table.add(new St.Bin(), { row: 0,
- col: 2,
- y_expand: false,
- y_fill: false });
-
- this._titleLabel = new St.Label();
- this._bannerBox.add_actor(this._titleLabel);
- this._bannerUrlHighlighter = new URLHighlighter();
- this._bannerLabel = this._bannerUrlHighlighter.actor;
- this._bannerBox.add_actor(this._bannerLabel);
+ let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
+ this._grid = new St.Widget({ style_class: 'notification', layout_manager: layout });
+ layout.hookup_style(this._grid);
+
+ this.actor.set_child(this._grid);
+
+ this._titleLabel = new St.Label({ x_expand: true });
+ layout.attach(this._titleLabel, 1, 0, 1, 1);
+ let closeIcon = new St.Icon({ icon_name: 'window-close-symbolic',
+ icon_size: 16 });
+ this._closeButton = new St.Button({ child: closeIcon });
+ layout.attach(this._closeButton, 3, 0, 1, 1);
+
+ this._closeButton.connect('clicked', Lang.bind(this,
+ function() {
+ this.destroy(NotificationDestroyedReason.DISMISSED);
+ }));
// If called with only one argument we assume the caller
// will call .update() later on. This is the case of
@@ -593,7 +574,7 @@ const Notification = new Lang.Class({
this._buttonBox = null;
}
if (!this._scrollArea && !this._actionArea)
- this._table.remove_style_class_name('multi-line-notification');
+ this._grid.remove_style_class_name('multi-line-notification');
if (params.gicon) {
this._icon = new St.Icon({ gicon: params.gicon,
@@ -602,19 +583,16 @@ const Notification = new Lang.Class({
this._icon = this.source.createIcon(this.ICON_SIZE);
}
+ let layout = this._grid.layout_manager;
if (this._icon) {
- this._table.add(this._icon, { row: 0,
- col: 0,
- x_expand: false,
- y_expand: false,
- y_fill: false,
- y_align: St.Align.START });
+ this._icon.set_y_align(Clutter.ActorAlign.START);
+ layout.attach(this._icon, 0, 0, 1, 1);
}
if (params.secondaryGIcon) {
this._secondaryIcon = new St.Icon({ gicon: params.secondaryGIcon,
style_class: 'secondary-icon' });
- this._bannerBox.add_actor(this._secondaryIcon);
+ layout.attach(this._secondaryGIcon, 2, 0, 1, 1);
}
this.title = title;
@@ -633,7 +611,7 @@ const Notification = new Lang.Class({
// arguably for action buttons as well. Labels other than the title
// will be allocated at the available width, so that their alignment
// is done correctly automatically.
- this._table.set_text_direction(titleDirection);
+ this._grid.set_text_direction(titleDirection);
// Unless the notification has custom content, we save this.bannerBodyText
// to add it to the content of the notification if the notification is
@@ -643,13 +621,8 @@ const Notification = new Lang.Class({
this.bannerBodyMarkup = params.bannerMarkup;
this._bannerBodyAdded = false;
- banner = banner ? banner.replace(/\n/g, ' ') : '';
-
- this._bannerUrlHighlighter.setMarkup(banner, params.bannerMarkup);
- this._bannerLabel.queue_relayout();
-
// Add the bannerBody now if we know for sure we'll need it
- if (this.bannerBodyText && this.bannerBodyText.indexOf('\n') > -1)
+ if (this.bannerBodyText)
this._addBannerBody();
if (this._soundName != params.soundName ||
@@ -666,23 +639,14 @@ const Notification = new Lang.Class({
this._icon.visible = visible;
},
- enableScrolling: function(enableScrolling) {
- this._scrollPolicy = enableScrolling ? Gtk.PolicyType.AUTOMATIC : Gtk.PolicyType.NEVER;
- if (this._scrollArea) {
- this._scrollArea.vscrollbar_policy = this._scrollPolicy;
- this._scrollArea.enable_mouse_scrolling = enableScrolling;
- }
- },
-
_createScrollArea: function() {
- this._table.add_style_class_name('multi-line-notification');
+ this._grid.add_style_class_name('multi-line-notification');
this._scrollArea = new St.ScrollView({ style_class: 'notification-scrollview',
vscrollbar_policy: this._scrollPolicy,
hscrollbar_policy: Gtk.PolicyType.NEVER,
visible: this.expanded });
- this._table.add(this._scrollArea, { row: 1,
- col: 2 });
- this._updateLastColumnSettings();
+ let layout = this._grid.layout_manager;
+ layout.attach(this._scrollArea, 1, 1, 3, 1);
this._contentArea = new St.BoxLayout({ style_class: 'notification-body',
vertical: true });
this._scrollArea.add_actor(this._contentArea);
@@ -740,11 +704,10 @@ const Notification = new Lang.Class({
// setActionArea:
// @actor: the actor
- // @props: (option) St.Table child properties
//
// Puts @actor into the action area of the notification, replacing
// the previous contents
- setActionArea: function(actor, props) {
+ setActionArea: function(actor) {
if (this._actionArea) {
this._actionArea.destroy();
this._actionArea = null;
@@ -756,35 +719,17 @@ const Notification = new Lang.Class({
this._actionArea = actor;
this._actionArea.visible = this.expanded;
- if (!props)
- props = {};
- props.row = 2;
- props.col = 2;
-
- this._table.add_style_class_name('multi-line-notification');
- this._table.add(this._actionArea, props);
- this._updateLastColumnSettings();
+ let layout = this._grid.layout_manager;
+ this._grid.add_style_class_name('multi-line-notification');
+ layout.attach_next_to(this._actionArea, null,
+ Clutter.GridPosition.BOTTOM, 4, 1);
this.updated();
},
- _updateLastColumnSettings: function() {
- if (this._scrollArea)
- this._table.child_set(this._scrollArea, { col: 1,
- col_span: 2 });
- if (this._actionArea)
- this._table.child_set(this._actionArea, { col: 1,
- col_span: 2 });
- },
-
addButton: function(button, callback) {
if (!this._buttonBox) {
- let box = new St.BoxLayout({ style_class: 'notification-actions' });
- this.setActionArea(box, { x_expand: false,
- y_expand: false,
- x_fill: false,
- y_fill: false,
- x_align: St.Align.END });
- this._buttonBox = box;
+ this._buttonBox = new St.BoxLayout({ style_class: 'notification-actions' });
+ this.setActionArea(this._buttonBox);
global.focus_manager.add_group(this._buttonBox);
}
@@ -837,130 +782,8 @@ const Notification = new Lang.Class({
this.forFeedback = forFeedback;
},
- _styleChanged: function() {
- this._spacing = this._table.get_theme_node().get_length('spacing-columns');
- },
-
- _bannerBoxGetPreferredWidth: function(actor, forHeight, alloc) {
- let [titleMin, titleNat] = this._titleLabel.get_preferred_width(forHeight);
- let [bannerMin, bannerNat] = this._bannerLabel.get_preferred_width(forHeight);
-
- if (this._secondaryIcon) {
- let [secondaryIconMin, secondaryIconNat] = this._secondaryIcon.get_preferred_width(forHeight);
-
- alloc.min_size = secondaryIconMin + this._spacing + titleMin;
- alloc.natural_size = secondaryIconNat + this._spacing + titleNat + this._spacing + bannerNat;
- } else {
- alloc.min_size = titleMin;
- alloc.natural_size = titleNat + this._spacing + bannerNat;
- }
- },
-
- _bannerBoxGetPreferredHeight: function(actor, forWidth, alloc) {
- [alloc.min_size, alloc.natural_size] =
- this._titleLabel.get_preferred_height(forWidth);
- },
-
- _bannerBoxAllocate: function(actor, box, flags) {
- let availWidth = box.x2 - box.x1;
-
- let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
- let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth);
- let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth);
-
- let rtl = (this._table.text_direction == Clutter.TextDirection.RTL);
- let x = rtl ? availWidth : 0;
-
- if (this._secondaryIcon) {
- let [iconMinW, iconNatW] = this._secondaryIcon.get_preferred_width(-1);
- let [iconMinH, iconNatH] = this._secondaryIcon.get_preferred_height(availWidth);
-
- let secondaryIconBox = new Clutter.ActorBox();
- let secondaryIconBoxW = Math.min(iconNatW, availWidth);
-
- // allocate secondary icon box
- if (rtl) {
- secondaryIconBox.x1 = x - secondaryIconBoxW;
- secondaryIconBox.x2 = x;
- x = x - (secondaryIconBoxW + this._spacing);
- } else {
- secondaryIconBox.x1 = x;
- secondaryIconBox.x2 = x + secondaryIconBoxW;
- x = x + secondaryIconBoxW + this._spacing;
- }
- secondaryIconBox.y1 = 0;
- // Using titleNatH ensures that the secondary icon is centered vertically
- secondaryIconBox.y2 = titleNatH;
-
- availWidth = availWidth - (secondaryIconBoxW + this._spacing);
- this._secondaryIcon.allocate(secondaryIconBox, flags);
- }
-
- let titleBox = new Clutter.ActorBox();
- let titleBoxW = Math.min(titleNatW, availWidth);
- if (rtl) {
- titleBox.x1 = availWidth - titleBoxW;
- titleBox.x2 = availWidth;
- } else {
- titleBox.x1 = x;
- titleBox.x2 = titleBox.x1 + titleBoxW;
- }
- titleBox.y1 = 0;
- titleBox.y2 = titleNatH;
- this._titleLabel.allocate(titleBox, flags);
- this._titleFitsInBannerMode = (titleNatW <= availWidth);
-
- let bannerFits = true;
- if (titleBoxW + this._spacing > availWidth) {
- this._bannerLabel.opacity = 0;
- bannerFits = false;
- } else {
- let bannerBox = new Clutter.ActorBox();
-
- if (rtl) {
- bannerBox.x1 = 0;
- bannerBox.x2 = titleBox.x1 - this._spacing;
-
- bannerFits = (bannerBox.x2 - bannerNatW >= 0);
- } else {
- bannerBox.x1 = titleBox.x2 + this._spacing;
- bannerBox.x2 = availWidth;
-
- bannerFits = (bannerBox.x1 + bannerNatW <= availWidth);
- }
- bannerBox.y1 = 0;
- bannerBox.y2 = titleNatH;
- this._bannerLabel.allocate(bannerBox, flags);
-
- // Make _bannerLabel visible if the entire notification
- // fits on one line, or if the notification is currently
- // unexpanded and only showing one line anyway.
- if (!this.expanded || (bannerFits && this._table.row_count == 1))
- this._bannerLabel.opacity = 255;
- }
-
- // If the banner doesn't fully fit in the banner box, we possibly need to add the
- // banner to the body. We can't do that from here though since that will force a
- // relayout, so we add it to the main loop.
- if (!bannerFits && this._canExpandContent())
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
- Lang.bind(this,
- function() {
- if (this._destroyed)
- return false;
-
- if (this._canExpandContent()) {
- this._addBannerBody();
- this._table.add_style_class_name('multi-line-notification');
- this.updated();
- }
- return false;
- }));
- },
-
_canExpandContent: function() {
- return (this.bannerBodyText && !this._bannerBodyAdded) ||
- (!this._titleFitsInBannerMode &&
!this._table.has_style_class_name('multi-line-notification'));
+ return this.bannerBodyText && !this._bannerBodyAdded;
},
playSound: function() {
@@ -1010,30 +833,6 @@ const Notification = new Lang.Class({
if (this._scrollArea)
this._scrollArea.show();
- // The banner is never shown when the title did not fit, so this
- // can be an if-else statement.
- if (!this._titleFitsInBannerMode) {
- // Remove ellipsization from the title label and make it wrap so that
- // we show the full title when the notification is expanded.
- this._titleLabel.clutter_text.line_wrap = true;
- this._titleLabel.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
- this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
- } else if (this._table.row_count > 1 && this._bannerLabel.opacity != 0) {
- // We always hide the banner if the notification has additional content.
- //
- // We don't need to wrap the banner that doesn't fit the way we wrap the
- // title that doesn't fit because we won't have a notification with
- // row_count=1 that has a banner that doesn't fully fit. We'll either add
- // that banner to the content of the notification in _bannerBoxAllocate()
- // or the notification will have custom content.
- if (animate)
- Tweener.addTween(this._bannerLabel,
- { opacity: 0,
- time: ANIMATION_TIME,
- transition: 'easeOutQuad' });
- else
- this._bannerLabel.opacity = 0;
- }
this.emit('expanded');
},
@@ -1052,10 +851,6 @@ const Notification = new Lang.Class({
this._titleLabel.clutter_text.line_wrap = false;
this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.END;
- // Restore banner opacity in case the notification is shown in the
- // banner mode again on update.
- this._bannerLabel.opacity = 255;
-
// Restore height requisition
this.actor.add_style_class_name('notification-unexpanded');
},
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]