[polari] userList: Use template for details
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [polari] userList: Use template for details
- Date: Mon, 23 Feb 2015 16:38:08 +0000 (UTC)
commit 8eecccb5cd1cbe9c01f09d62a1f576a6a13a545b
Author: Florian Müllner <fmuellner gnome org>
Date: Sun Feb 22 04:18:59 2015 +0100
userList: Use template for details
This is another good candidate for template use, so port this as well.
data/org.gnome.Polari.data.gresource.xml | 1 +
data/resources/user-list-details.ui | 89 +++++++++++
po/POTFILES.in | 1 +
src/userList.js | 251 +++++++++++++++++-------------
4 files changed, 230 insertions(+), 112 deletions(-)
---
diff --git a/data/org.gnome.Polari.data.gresource.xml b/data/org.gnome.Polari.data.gresource.xml
index 2d00f0d..91c4de2 100644
--- a/data/org.gnome.Polari.data.gresource.xml
+++ b/data/org.gnome.Polari.data.gresource.xml
@@ -7,6 +7,7 @@
<file alias="join-room-dialog.ui" preprocess="xml-stripblanks">resources/join-room-dialog.ui</file>
<file alias="main-window.ui" preprocess="xml-stripblanks">resources/main-window.ui</file>
<file alias="message-user-dialog.ui" preprocess="xml-stripblanks">resources/message-user-dialog.ui</file>
+ <file alias="user-list-details.ui" preprocess="xml-stripblanks">resources/user-list-details.ui</file>
<file alias="application.css">resources/application.css</file>
</gresource>
</gresources>
diff --git a/data/resources/user-list-details.ui b/data/resources/user-list-details.ui
new file mode 100644
index 0000000..7214d7d
--- /dev/null
+++ b/data/resources/user-list-details.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="Gjs_UserListDetails" parent="GtkFrame">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin">6</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkBox" id="spinnerBox">
+ <property name="spacing">6</property>
+ <property name="margin">12</property>
+ <property name="hexpand">True</property>
+ <property name="halign">center</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label" translatable="yes">Loading details</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="detailsGrid">
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <property name="hexpand">True</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="fullnameLabel">
+ <property name="ellipsize">end</property>
+ <property name="halign">start</property>
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="width">2</property>
+ <property name="top-attach">0</property>
+ <property name="left-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lastHeader">
+ <property name="label" translatable="yes">Last Activity:</property>
+ <property name="valign">start</property>
+ <property name="use_markup">True</property>
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="top-attach">1</property>
+ <property name="left-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lastLabel">
+ <property name="valign">end</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="hexpand">True</property>
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="top-attach">1</property>
+ <property name="left-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="messageButton">
+ <property name="label" translatable="yes">Message</property>
+ <property name="margin_top">12</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 29ff637..23c6b95 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,6 +7,7 @@ data/org.gnome.Polari.gschema.xml
[type: gettext/glade]data/resources/main-window.ui
[type: gettext/glade]data/resources/menus.ui
[type: gettext/glade]data/resources/message-user-dialog.ui
+[type: gettext/glade]data/resources/user-list-details.ui
src/application.js
src/appNotifications.js
src/chatView.js
diff --git a/src/userList.js b/src/userList.js
index f46593b..d81c3ad 100644
--- a/src/userList.js
+++ b/src/userList.js
@@ -1,6 +1,7 @@
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Tp = imports.gi.TelepathyGLib;
@@ -9,6 +10,8 @@ const ChatroomManager = imports.chatroomManager;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
+const READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
const MAX_USERS_SHOWN = 8;
const UserListPopover = new Lang.Class({
@@ -106,94 +109,74 @@ const UserListPopover = new Lang.Class({
}
});
-const UserListRow = new Lang.Class({
- Name: 'UserListRow',
-
- _init: function(user) {
- this._createWidget(user);
-
- this.widget.user = user;
-
- this.widget.connect('unmap', Lang.bind(this, function() {
- this._revealer.reveal_child = false;
- }));
- this.widget.connect('state-flags-changed',
- Lang.bind(this, this._updateArrowVisibility));
-
- this._revealer.connect('notify::reveal-child',
- Lang.bind(this, this._onExpandedChanged));
+const UserListDetails = new Lang.Class({
+ Name: 'UserListDetails',
+ Extends: Gtk.Frame,
+ Template: 'resource:///org/gnome/Polari/user-list-details.ui',
+ InternalChildren: ['spinnerBox',
+ 'spinner',
+ 'detailsGrid',
+ 'fullnameLabel',
+ 'lastHeader',
+ 'lastLabel',
+ 'messageButton'],
+ Properties: { 'expanded': GObject.ParamSpec.boolean('expanded',
+ 'expanded',
+ 'expanded',
+ READWRITE,
+ false)},
+
+ _init: function(params) {
+ this._user = params.user;
+ delete params.user;
+
+ this._expanded = false;
+
+ this.parent(params);
+
+ this._messageButton.connect('clicked',
+ Lang.bind(this, this._onButtonClicked));
+ this._user.connection.connect('notify::self-contact',
+ Lang.bind(this, this._updateButtonVisibility));
+ this._updateButtonVisibility();
+ this._detailsGrid.hide();
},
- get expand() {
- return this._revealer.reveal_child;
+ get expanded() {
+ return this._expanded;
},
- set expand(expand) {
- this._ensureDetails();
- this._revealer.reveal_child = expand;
- },
+ set expanded(v) {
+ if (v == this._expanded)
+ return;
- _createWidget: function(user) {
- this.widget = new Gtk.ListBoxRow();
+ this._expanded = v;
- let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
- this.widget.add(vbox);
+ if (this._expanded)
+ this._expand();
+ else
+ this._unexpand();
- let hbox = new Gtk.Box({ margin: 4, spacing: 4 });
- this._arrow = new Gtk.Arrow({ arrow_type: Gtk.ArrowType.RIGHT,
- no_show_all: true });
- hbox.add(new Gtk.Image({ icon_name: 'avatar-default-symbolic' }));
- hbox.add(new Gtk.Label({ label: user.alias,
- halign: Gtk.Align.START,
- hexpand: true,
- ellipsize: Pango.EllipsizeMode.END }));
- hbox.add(this._arrow);
- vbox.add(hbox);
+ this.notify('expanded');
+ },
- this._revealer = new Gtk.Revealer({ reveal_child: false });
- vbox.add(this._revealer);
+ _expand: function() {
+ let prevDetails = this._fullnameLabel.label != '';
+ this._detailsGrid.visible = prevDetails;
+ this._spinnerBox.visible = !prevDetails;
+ this._spinner.start();
- this.widget.show_all();
+ this._cancellable = new Gio.Cancellable();
+ this._user.request_contact_info_async(this._cancellable,
+ Lang.bind(this, this._onContactInfoReady));
},
- _ensureDetails: function() {
- if (this._revealer.get_child())
- return;
-
- let frame = new Gtk.Frame({ hexpand: true });
-
- let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
- spacing: 6, margin: 6 });
- frame.add(box);
-
- this._spinnerBox = new Gtk.Box({ spacing: 6, margin: 12,
- hexpand: true,
- halign: Gtk.Align.CENTER });
- this._spinner = new Gtk.Spinner();
- this._spinnerBox.add(this._spinner);
- this._spinnerBox.add(new Gtk.Label({ label: _("Loading details") }));
- box.add(this._spinnerBox);
-
- this._detailsGrid = new Gtk.Grid({ row_spacing: 6, column_spacing: 6,
- hexpand: true });
- box.add(this._detailsGrid);
-
- let user = this.widget.user;
- if (user != user.connection.self_contact) {
- let button = new Gtk.Button({ label: _("Message"),
- margin_top: 12,
- hexpand: true,
- halign: Gtk.Align.END });
- button.connect('clicked', Lang.bind(this, this._onButtonClicked));
- user.connection.connect('notify::self-contact', function() {
- if (user == user.connection.self_contact)
- button.destroy();
- });
- box.add(button);
- }
+ _unexpand: function() {
+ this._spinner.stop();
- this._revealer.add(frame);
- frame.show_all();
+ if (this._cancellable)
+ this._cancellable.cancel();
+ this._cancellable = null;
},
_formatLast: function(seconds) {
@@ -228,7 +211,7 @@ const UserListRow = new Lang.Class({
_onContactInfoReady: function(c, res) {
let fn, last;
- let info = this.widget.user.get_contact_info();
+ let info = this._user.get_contact_info();
for (let i = 0; i < info.length; i++) {
if (info[i].field_name == 'fn')
fn = info[i].field_value[0];
@@ -237,47 +220,105 @@ const UserListRow = new Lang.Class({
}
if (!fn)
- fn = this.widget.user.alias;
-
- this._detailsGrid.foreach(function(w) { w.destroy(); });
+ fn = this._user.alias;
- let row = 0;
- let w = new Gtk.Label({ label: fn, ellipsize: Pango.EllipsizeMode.END,
- halign: Gtk.Align.START });
- this._detailsGrid.attach(w, 0, row++, 2, 1);
+ this._fullnameLabel.label = fn;
if (last) {
+ this._lastHeader.label = '<small>' + _("Last Activity:") + '</small>';
+ this._lastHeader.show();
- w = new Gtk.Label({ label: '<small>' + _("Last Activity:") + '</small>',
- use_markup: true,
- valign: Gtk.Align.START });
- this._detailsGrid.attach(w, 0, row, 1, 1);
-
- w = new Gtk.Label({ label: '<small>' + this._formatLast(last) + '</small>',
- use_markup: true,
- wrap: true,
- hexpand: true });
- this._detailsGrid.attach(w, 1, row++, 1, 1);
+ this._lastLabel.label = '<small>' + this._formatLast(last) + '</small>';
+ this._lastLabel.show();
+ } else {
+ this._lastHeader.hide();
+ this._lastLabel.hide();
}
- this._detailsGrid.show_all();
-
this._spinner.stop();
this._spinnerBox.hide();
+ this._detailsGrid.show();
},
_onButtonClicked: function() {
- let account = this.widget.user.connection.get_account();
+ let account = this._user.connection.get_account();
let app = Gio.Application.get_default();
let action = app.lookup_action('message-user');
let time = Gtk.get_current_event().get_time();
action.activate(GLib.Variant.new('(ssu)',
[ account.get_object_path(),
- this.widget.user.alias,
+ this._user.alias,
time ]));
},
+ _updateButtonVisibility: function() {
+ let visible = this._user != this._user.connection.self_contact;
+ this._messageButton.visible = visible;
+ }
+});
+
+const UserListRow = new Lang.Class({
+ Name: 'UserListRow',
+
+ _init: function(user) {
+ this._createWidget(user);
+
+ this.widget.user = user;
+
+ this.widget.connect('unmap', Lang.bind(this, function() {
+ this._revealer.reveal_child = false;
+ }));
+ this.widget.connect('state-flags-changed',
+ Lang.bind(this, this._updateArrowVisibility));
+
+ this._revealer.connect('notify::reveal-child',
+ Lang.bind(this, this._onExpandedChanged));
+ },
+
+ get expand() {
+ return this._revealer.reveal_child;
+ },
+
+ set expand(expand) {
+ if (expand)
+ this._ensureDetails();
+ this._revealer.reveal_child = expand;
+ },
+
+ _createWidget: function(user) {
+ this.widget = new Gtk.ListBoxRow();
+
+ let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
+ this.widget.add(vbox);
+
+ let hbox = new Gtk.Box({ margin: 4, spacing: 4 });
+ this._arrow = new Gtk.Arrow({ arrow_type: Gtk.ArrowType.RIGHT,
+ no_show_all: true });
+ hbox.add(new Gtk.Image({ icon_name: 'avatar-default-symbolic' }));
+ hbox.add(new Gtk.Label({ label: user.alias,
+ halign: Gtk.Align.START,
+ hexpand: true,
+ ellipsize: Pango.EllipsizeMode.END }));
+ hbox.add(this._arrow);
+ vbox.add(hbox);
+
+ this._revealer = new Gtk.Revealer({ reveal_child: false });
+ vbox.add(this._revealer);
+
+ this.widget.show_all();
+ },
+
+ _ensureDetails: function() {
+ if (this._revealer.get_child())
+ return;
+
+ let details = new UserListDetails({ user: this.widget.user })
+ this._revealer.bind_property('reveal-child', details, 'expanded', 0);
+
+ this._revealer.add(details);
+ },
+
_updateArrowVisibility: function() {
let flags = this.widget.get_state_flags();
this._arrow.visible = this.expand ||
@@ -289,24 +330,10 @@ const UserListRow = new Lang.Class({
if (this._revealer.reveal_child) {
this.widget.get_style_context().add_class('expanded');
this._arrow.arrow_type = Gtk.ArrowType.DOWN;
-
- let prevDetails = this._detailsGrid.get_children().length > 0;
- this._spinnerBox.visible = !prevDetails;
- this._spinner.start();
-
- this._cancellable = new Gio.Cancellable();
- this.widget.user.request_contact_info_async(this._cancellable,
- Lang.bind(this, this._onContactInfoReady));
} else {
this.widget.get_style_context().remove_class('expanded');
this._arrow.arrow_type = Gtk.ArrowType.RIGHT;
this._updateArrowVisibility();
-
- this._spinner.stop();
-
- if (this._cancellable)
- this._cancellable.cancel();
- this._cancellable = null;
}
}
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]