messageList: Use St.Bin as message container and use clutter to manage the list
When messages are added to the message list, we create a container for those, however since now the messages are actor themselves we can just create a list item actor that holds the message actor and refer to the message parent in order to get their container. This allows to remove the obj container map we used, using the native clutter parent-child hierarchy and handle signal connections cleanly. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
This commit is contained in:
parent
4dea1f801a
commit
9bb12f6f87
@ -999,9 +999,10 @@ class NotificationSection extends MessageList.MessageListSection {
|
|||||||
if (!this.mapped)
|
if (!this.mapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (let message of this._messages.keys())
|
this._messages.forEach(message => {
|
||||||
if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
|
if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
|
||||||
message.notification.acknowledged = true;
|
message.notification.acknowledged = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_shouldShow() {
|
_shouldShow() {
|
||||||
|
@ -564,7 +564,6 @@ var MessageListSection = GObject.registerClass({
|
|||||||
Main.sessionMode.disconnect(id);
|
Main.sessionMode.disconnect(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._messages = new Map();
|
|
||||||
this._date = new Date();
|
this._date = new Date();
|
||||||
this._empty = true;
|
this._empty = true;
|
||||||
this._canClear = false;
|
this._canClear = false;
|
||||||
@ -579,6 +578,10 @@ var MessageListSection = GObject.registerClass({
|
|||||||
return this._canClear;
|
return this._canClear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _messages() {
|
||||||
|
return this._list.get_children().map(i => i.child);
|
||||||
|
}
|
||||||
|
|
||||||
_onKeyFocusIn(messageActor) {
|
_onKeyFocusIn(messageActor) {
|
||||||
this.emit('message-focused', messageActor);
|
this.emit('message-focused', messageActor);
|
||||||
}
|
}
|
||||||
@ -599,58 +602,62 @@ var MessageListSection = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
addMessageAtIndex(message, index, animate) {
|
addMessageAtIndex(message, index, animate) {
|
||||||
let obj = {
|
if (this._messages.includes(message))
|
||||||
container: null,
|
throw new Error('Message was already added previously');
|
||||||
destroyId: 0,
|
|
||||||
keyFocusId: 0,
|
let listItem = new St.Bin({
|
||||||
closeId: 0
|
child: message,
|
||||||
};
|
x_fill: true,
|
||||||
let pivot = new Graphene.Point({ x: .5, y: .5 });
|
y_fill: true,
|
||||||
let scale = animate ? 0 : 1;
|
layout_manager: new ScaleLayout(),
|
||||||
obj.container = new St.Widget({ layout_manager: new ScaleLayout(),
|
pivot_point: new Graphene.Point({ x: .5, y: .5 }),
|
||||||
pivot_point: pivot,
|
|
||||||
scale_x: scale, scale_y: scale });
|
|
||||||
obj.keyFocusId = message.connect('key-focus-in',
|
|
||||||
this._onKeyFocusIn.bind(this));
|
|
||||||
obj.destroyId = message.connect('destroy', () => {
|
|
||||||
this.removeMessage(message, false);
|
|
||||||
});
|
});
|
||||||
obj.closeId = message.connect('close', () => {
|
listItem._connectionsIds = [];
|
||||||
|
|
||||||
|
listItem._connectionsIds.push(message.connect('key-focus-in',
|
||||||
|
this._onKeyFocusIn.bind(this)));
|
||||||
|
listItem._connectionsIds.push(message.connect('close', () => {
|
||||||
this.removeMessage(message, true);
|
this.removeMessage(message, true);
|
||||||
});
|
}));
|
||||||
|
listItem._connectionsIds.push(message.connect('destroy', () => {
|
||||||
|
listItem._connectionsIds.forEach(id => message.disconnect(id));
|
||||||
|
listItem.destroy();
|
||||||
|
}));
|
||||||
|
|
||||||
this._messages.set(message, obj);
|
this._list.insert_child_at_index(listItem, index);
|
||||||
obj.container.add_actor(message);
|
|
||||||
|
|
||||||
this._list.insert_child_at_index(obj.container, index);
|
if (animate) {
|
||||||
|
listItem.set({ scale_x: 0, scale_y: 0 });
|
||||||
if (animate)
|
listItem.ease({
|
||||||
obj.container.ease({
|
|
||||||
scale_x: 1,
|
scale_x: 1,
|
||||||
scale_y: 1,
|
scale_y: 1,
|
||||||
duration: MESSAGE_ANIMATION_TIME,
|
duration: MESSAGE_ANIMATION_TIME,
|
||||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
moveMessage(message, index, animate) {
|
moveMessage(message, index, animate) {
|
||||||
let obj = this._messages.get(message);
|
if (!this._messages.includes(message))
|
||||||
|
throw new Error(`Impossible to move the untracked message ${message}`);
|
||||||
|
|
||||||
|
let listItem = message.get_parent();
|
||||||
|
|
||||||
if (!animate) {
|
if (!animate) {
|
||||||
this._list.set_child_at_index(obj.container, index);
|
this._list.set_child_at_index(listItem, index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let onComplete = () => {
|
let onComplete = () => {
|
||||||
this._list.set_child_at_index(obj.container, index);
|
this._list.set_child_at_index(listItem, index);
|
||||||
obj.container.ease({
|
listItem.ease({
|
||||||
scale_x: 1,
|
scale_x: 1,
|
||||||
scale_y: 1,
|
scale_y: 1,
|
||||||
duration: MESSAGE_ANIMATION_TIME,
|
duration: MESSAGE_ANIMATION_TIME,
|
||||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
obj.container.ease({
|
listItem.ease({
|
||||||
scale_x: 0,
|
scale_x: 0,
|
||||||
scale_y: 0,
|
scale_y: 0,
|
||||||
duration: MESSAGE_ANIMATION_TIME,
|
duration: MESSAGE_ANIMATION_TIME,
|
||||||
@ -660,33 +667,31 @@ var MessageListSection = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeMessage(message, animate) {
|
removeMessage(message, animate) {
|
||||||
let obj = this._messages.get(message);
|
if (!this._messages.includes(message))
|
||||||
|
throw new Error(`Impossible to remove the untracked message ${message}`);
|
||||||
|
|
||||||
message.disconnect(obj.destroyId);
|
let listItem = message.get_parent();
|
||||||
message.disconnect(obj.keyFocusId);
|
listItem._connectionsIds.forEach(id => message.disconnect(id));
|
||||||
message.disconnect(obj.closeId);
|
|
||||||
|
|
||||||
this._messages.delete(message);
|
|
||||||
|
|
||||||
if (animate) {
|
if (animate) {
|
||||||
obj.container.ease({
|
listItem.ease({
|
||||||
scale_x: 0,
|
scale_x: 0,
|
||||||
scale_y: 0,
|
scale_y: 0,
|
||||||
duration: MESSAGE_ANIMATION_TIME,
|
duration: MESSAGE_ANIMATION_TIME,
|
||||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
obj.container.destroy();
|
listItem.destroy();
|
||||||
global.sync_pointer();
|
global.sync_pointer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
obj.container.destroy();
|
listItem.destroy();
|
||||||
global.sync_pointer();
|
global.sync_pointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
let messages = [...this._messages.keys()].filter(msg => msg.canClose());
|
let messages = this._messages.filter(msg => msg.canClose());
|
||||||
|
|
||||||
// If there are few messages, letting them all zoom out looks OK
|
// If there are few messages, letting them all zoom out looks OK
|
||||||
if (messages.length < 2) {
|
if (messages.length < 2) {
|
||||||
@ -699,9 +704,8 @@ var MessageListSection = GObject.registerClass({
|
|||||||
let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5);
|
let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5);
|
||||||
for (let i = 0; i < messages.length; i++) {
|
for (let i = 0; i < messages.length; i++) {
|
||||||
let message = messages[i];
|
let message = messages[i];
|
||||||
let obj = this._messages.get(message);
|
message.get_parent().ease({
|
||||||
obj.container.ease({
|
translation_x: this._list.width,
|
||||||
anchor_x: this._list.width,
|
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
duration: MESSAGE_ANIMATION_TIME,
|
duration: MESSAGE_ANIMATION_TIME,
|
||||||
delay: i * delay,
|
delay: i * delay,
|
||||||
@ -717,14 +721,15 @@ var MessageListSection = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sync() {
|
_sync() {
|
||||||
let empty = this._list.get_n_children() == 0;
|
let messages = this._messages;
|
||||||
|
let empty = messages.length == 0;
|
||||||
|
|
||||||
if (this._empty != empty) {
|
if (this._empty != empty) {
|
||||||
this._empty = empty;
|
this._empty = empty;
|
||||||
this.notify('empty');
|
this.notify('empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
let canClear = [...this._messages.keys()].some(m => m.canClose());
|
let canClear = messages.some(m => m.canClose());
|
||||||
if (this._canClear != canClear) {
|
if (this._canClear != canClear) {
|
||||||
this._canClear = canClear;
|
this._canClear = canClear;
|
||||||
this.notify('can-clear');
|
this.notify('can-clear');
|
||||||
|
Loading…
Reference in New Issue
Block a user