[gnome-shell/wip/fmuellner/notification-redux+sass: 188/207] calendar: Support action area and expanded bodies
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/fmuellner/notification-redux+sass: 188/207] calendar: Support action area and expanded bodies
- Date: Tue, 17 Feb 2015 17:09:49 +0000 (UTC)
commit 34db86ce37b67aa94770b772dddb0f5d4ee0f013
Author: Florian Müllner <fmuellner gnome org>
Date: Tue Feb 17 01:12:44 2015 +0100
calendar: Support action area and expanded bodies
js/ui/calendar.js | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 195 insertions(+), 2 deletions(-)
---
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index 0c30610..c3f7cbb 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -4,6 +4,7 @@ const Atk = imports.gi.Atk;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const St = imports.gi.St;
@@ -1017,16 +1018,126 @@ const URLHighlighter = new Lang.Class({
}
});
+const LabelExpanderLayout = new Lang.Class({
+ Name: 'LabelExpanderLayout',
+ Extends: Clutter.LayoutManager,
+ Properties: { 'expansion': GObject.ParamSpec.double('expansion',
+ 'Expansion',
+ 'Expansion of the layout, between 0 (collapsed) ' +
+ 'and 1 (fully expanded',
+ GObject.ParamFlags.READABLE |
GObject.ParamFlags.WRITABLE,
+ 0, 1, 0)},
+
+ _init: function(params) {
+ this._expansion = 0;
+ this.expandLines = 6;
+
+ this.parent(params);
+ },
+
+ get expansion() {
+ return this._expansion;
+ },
+
+ set expansion(v) {
+ if (v == this._expansion)
+ return;
+ this._expansion = v;
+ this.notify('expansion');
+
+ let visibleIndex = this._expansion > 0 ? 1 : 0;
+ for (let i = 0; this._container && i < this._container.get_n_children(); i++)
+ this._container.get_child_at_index(i).visible = (i == visibleIndex);
+
+ this.layout_changed();
+ },
+
+ vfunc_set_container: function(container) {
+ this._container = container;
+ },
+
+ vfunc_get_preferred_width: function(container, forHeight) {
+ let [min, nat] = [0, 0];
+
+ for (let i = 0; i < container.get_n_children(); i++) {
+ if (i > 1)
+ break; // we support one unexpanded + one expanded child
+
+ let child = container.get_child_at_index(i);
+ let [childMin, childNat] = child.get_preferred_width(forHeight);
+ [min, nat] = [Math.max(min, childMin), Math.max(nat, childNat)];
+ }
+
+ return [min, nat];
+ },
+
+ vfunc_get_preferred_height: function(container, forWidth) {
+ let [min, nat] = [0, 0];
+
+ let children = container.get_children();
+ if (children[0])
+ [min, nat] = children[0].get_preferred_height(forWidth);
+
+ if (children[1]) {
+ let [min2, nat2] = children[1].get_preferred_height(forWidth);
+ let [expMin, expNat] = [Math.min(min2, min * this.expandLines),
+ Math.min(nat2, nat * this.expandLines)];
+ [min, nat] = [min + this._expansion * (expMin - min),
+ nat + this._expansion * (expNat - nat)];
+ }
+
+ return [min, nat];
+ },
+
+ vfunc_allocate: function(container, box, flags) {
+ for (let i = 0; i < container.get_n_children(); i++) {
+ let child = container.get_child_at_index(i);
+
+ if (!child.visible)
+ continue;
+
+ let xAlign = 0;
+ let xFill = false;
+ if (child.needs_expand(Clutter.Orientation.HORIZONTAL)) {
+ switch(child.get_x_align()) {
+ case Clutter.ActorAlign.FILL:
+ xFill = true;
+ break;
+ case Clutter.ActorAlign.START:
+ break;
+ case Clutter.ActorAlign.CENTER:
+ xAlign = 0.5;
+ break;
+ case Clutter.ActorAlign.END:
+ xAlign = 1;
+ break;
+ }
+ }
+ child.allocate_align_fill(box, xAlign, 0, xFill, false, flags);
+ }
+
+ }
+});
+
const Message = new Lang.Class({
Name: 'Message',
_init: function(title, body) {
+ this.expanded = false;
+
this.actor = new St.Button({ style_class: 'message',
accessible_role: Atk.Role.NOTIFICATION,
x_expand: true, x_fill: true });
+ let vbox = new St.BoxLayout({ vertical: true });
+ this.actor.set_child(vbox);
+
let hbox = new St.BoxLayout();
- this.actor.set_child(hbox);
+ vbox.add_actor(hbox);
+
+ this._actionBin = new St.Widget({ layout_manager: new ScaleLayout(),
+ visible: false });
+ vbox.add_actor(this._actionBin);
this._iconBin = new St.Bin({ style_class: 'message-icon-bin',
y_expand: true,
@@ -1041,6 +1152,7 @@ const Message = new Lang.Class({
let titleBox = new St.BoxLayout();
contentBox.add_actor(titleBox);
+ let title = title ? _fixMarkup(title.replace(/\n/g, ' '), false) : '';
this.titleLabel = new St.Label({ style_class: 'message-title',
text: title, x_expand: true,
x_align: Clutter.ActorAlign.START });
@@ -1054,9 +1166,14 @@ const Message = new Lang.Class({
this._closeButton = new St.Button({ child: closeIcon, visible: false });
titleBox.add_actor(this._closeButton);
+ this._bodyStack = new St.Widget({ x_expand: true,
+ x_align: Clutter.ActorAlign.START });
+ this._bodyStack.layout_manager = new LabelExpanderLayout();
+ contentBox.add_actor(this._bodyStack);
+
this.bodyLabel = new URLHighlighter(body || '', false, this._useBodyMarkup);
this.bodyLabel.actor.add_style_class_name('message-body');
- contentBox.add_actor(this.bodyLabel.actor);
+ this._bodyStack.add_actor(this.bodyLabel.actor);
this._closeButton.connect('clicked', Lang.bind(this,
function() {
@@ -1084,6 +1201,82 @@ const Message = new Lang.Class({
this.bodyLabel.setMarkup(this.bodyLabel.actor.text, enable);
},
+ setActionArea: function(actor) {
+ if (actor == null) {
+ if (this._actionBin.get_n_children() > 1)
+ this._actionBin.get_child_at_index(1).destroy();
+ return;
+ }
+
+ if (this._actionBin.get_n_children() > 0)
+ throw new Error('Message already has an action area');
+
+ this._actionBin.add_actor(actor);
+ this._actionBin.visible = this.expanded;
+ },
+
+ setExpandedBody: function(actor) {
+ if (actor == null) {
+ if (this._bodyStack.get_n_children() > 1)
+ this._bodyStack.get_child_at_index(1).destroy();
+ return;
+ }
+
+ if (this._bodyStack.get_n_children() > 1)
+ throw new Error('Message already has an expanded body actor');
+
+ this._bodyStack.insert_child_at_index(actor, 1);
+ },
+
+ expand: function(animate) {
+ this.expanded = true;
+
+ this._actionBin.visible = (this._actionBin.get_n_children() > 0);
+
+ if (this._bodyStack.get_n_children() < 2) {
+ let expandedLabel = new URLHighlighter(this.bodyLabel.actor.text,
+ true, this._useBodyMarkup);
+ this.setExpandedBody(expandedLabel.actor);
+ }
+
+ if (animate) {
+ Tweener.addTween(this._bodyStack.layout_manager,
+ { expansion: 1,
+ time: MessageTray.ANIMATION_TIME,
+ transition: 'easeOutQuad' });
+ this._actionBin.scale_y = 0;
+ Tweener.addTween(this._actionBin,
+ { scale_y: 1,
+ time: MessageTray.ANIMATION_TIME,
+ transition: 'easeOutQuad' });
+ } else {
+ this._bodyStack.layout_manager.expansion = 1;
+ this._actionBin.scale_y = 1;
+ }
+ },
+
+ unexpand: function(animate) {
+ if (animate) {
+ Tweener.addTween(this._bodyStack.layout_manager,
+ { expansion: 0,
+ time: MessageTray.ANIMATION_TIME,
+ transition: 'easeOutQuad' });
+ Tweener.addTween(this._actionBin,
+ { scale_y: 0,
+ time: MessageTray.ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ onCompleteScope: this,
+ onComplete: function() {
+ this._actionBin.hide();
+ this.expanded = false;
+ }});
+ } else {
+ this._bodyStack.layout_manager.expansion = 0;
+ this._actionBin.scale_y = 0;
+ this.expanded = false;
+ }
+ },
+
canClear: function() {
return true;
},
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]