[polari/user-list-update: 3/6] userList: Allow filtering for long lists



commit 20ed978ac1476ab2b2ff63e57a5d4f17ab8784c9
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Oct 2 10:47:49 2013 +0200

    userList: Allow filtering for long lists
    
    The number of users connected to a room may be very large, in which
    case scanning the list for a particular nick is tedious; reveal a
    search entry in this case to allow filtering the list.

 data/resources/application.css |    4 ++
 src/userList.js                |   72 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 4 deletions(-)
---
diff --git a/data/resources/application.css b/data/resources/application.css
index f0e7150..2f25b16 100644
--- a/data/resources/application.css
+++ b/data/resources/application.css
@@ -20,6 +20,10 @@
     border-width: 0 0 0 1px;
 }
 
+.polari-user-list-search-area {
+    border-width: 0 0 1px 0;
+}
+
 .polari-selection-toolbar,
 .polari-input-area {
     background-color: @polari_dark_bg_color;
diff --git a/src/userList.js b/src/userList.js
index 6b8d21e..37fa477 100644
--- a/src/userList.js
+++ b/src/userList.js
@@ -13,6 +13,7 @@ const UserListSidebar = new Lang.Class({
         this._createWidget();
 
         this._rooms = {};
+        this._room = null;
 
         this._roomManager = new ChatroomManager.getDefault();
         this._roomManager.connect('room-added',
@@ -24,8 +25,34 @@ const UserListSidebar = new Lang.Class({
     },
 
     _createWidget: function() {
-        this.widget = new Gtk.Stack({ hexpand: true, visible: true });
-        this.widget.transition_type = Gtk.StackTransitionType.CROSSFADE;
+        this.widget = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
+
+        this._revealer = new Gtk.Revealer();
+        this.widget.add(this._revealer);
+
+        let frame = new Gtk.Frame();
+        frame.get_style_context().add_class('polari-user-list-search-area');
+        this._revealer.add(frame);
+
+        this._entry = new Gtk.SearchEntry({ margin: 4 });
+        this._entry.connect('search-changed',
+                            Lang.bind(this, this._updateFilter));
+        this._entry.connect_after('key-press-event', Lang.bind(this,
+            function(w, event) {
+                let [, keyval] = event.get_keyval();
+                if (keyval == Gdk.KEY_Escape) {
+                    this._entry.text = '';
+                    return true;
+                }
+                return false;
+            }));
+        frame.add(this._entry);
+
+        this._stack = new Gtk.Stack({ hexpand: true, vexpand: true });
+        this._stack.transition_type = Gtk.StackTransitionType.CROSSFADE;
+        this.widget.add(this._stack);
+
+        this.widget.show_all();
     },
 
     _roomAdded: function(roomManager, room) {
@@ -35,7 +62,10 @@ const UserListSidebar = new Lang.Class({
         let userList = new UserList(room);
         this._rooms[room.id] = userList;
 
-        this.widget.add_named(userList.widget, room.id);
+        this._stack.add_named(userList.widget, room.id);
+
+        userList.widget.vadjustment.connect('changed',
+                                            Lang.bind(this, this._updateEntryVisibility));
     },
 
     _roomRemoved: function(roomManager, room) {
@@ -46,11 +76,33 @@ const UserListSidebar = new Lang.Class({
     },
 
     _activeRoomChanged: function(manager, room) {
+        this._entry.text = '';
+        this._updateFilter();
+
+        this._room = room;
+
         if (!room || !this._rooms[room.id])
             return;
-        this.widget.set_visible_child_name(room.id);
+
+        this._stack.set_visible_child_name(room.id);
+        this._updateEntryVisibility();
+    },
+
+    _updateEntryVisibility: function() {
+        if (!this._room || !this._rooms[this._room.id])
+            return;
+        let userList = this._rooms[this._room.id];
+        let [, natHeight] = userList.widget.get_child().get_preferred_height();
+        let height = this.widget.get_allocated_height();
+        this._revealer.reveal_child = this._entry.text != '' ||
+                                      natHeight > height;
     },
 
+    _updateFilter: function() {
+        if (!this._room || !this._rooms[this._room.id])
+            return;
+        this._rooms[this._room.id].setFilter(this._entry.text);
+    }
 });
 
 const UserList = new Lang.Class({
@@ -65,6 +117,7 @@ const UserList = new Lang.Class({
 
         this._list.set_selection_mode(Gtk.SelectionMode.NONE);
         this._list.set_header_func(Lang.bind(this, this._updateHeader));
+        this._list.set_filter_func(Lang.bind(this, this._filterRows));
         this._list.set_sort_func(Lang.bind(this, this._sort));
 
         this._room = room;
@@ -89,6 +142,11 @@ const UserList = new Lang.Class({
         this.widget.show_all();
     },
 
+    setFilter: function(filter) {
+        this._filter = filter;
+        this._list.invalidate_filter();
+    },
+
     _onMemberRenamed: function(room, oldMember, newMember) {
         this._removeMember(oldMember);
         this._addMember(newMember);
@@ -129,6 +187,12 @@ const UserList = new Lang.Class({
         return (row1._member.alias < row2._member.alias) ? -1 : 1;
     },
 
+    _filterRows: function(row) {
+        if (!this._filter)
+            return true;
+        return row._member.alias.indexOf(this._filter) != -1;
+    },
+
     _updateHeader: function(row, before) {
         let numMembers = this._list.get_children().length;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]