appDisplay: Make refiltering folders more efficient

Rather than queueing a full redisplay, simply filter the apps inside
folders by toggling the icon's visibility.

https://bugzilla.gnome.org/show_bug.cgi?id=723179
This commit is contained in:
Jasper St. Pierre 2014-01-28 11:36:57 -05:00
parent 3779ac2c8a
commit 10147ee331
2 changed files with 91 additions and 31 deletions

View File

@ -115,6 +115,10 @@ const BaseAppView = new Lang.Class({
this._loadApps(); this._loadApps();
}, },
getAllItems: function() {
return this._allItems;
},
addItem: function(icon) { addItem: function(icon) {
let id = icon.id; let id = icon.id;
if (this._items[id] !== undefined) if (this._items[id] !== undefined)
@ -124,10 +128,12 @@ const BaseAppView = new Lang.Class({
this._items[id] = icon; this._items[id] = icon;
}, },
loadGrid: function() { _compareItems: function(a, b) {
this._allItems.sort(Lang.bind(this, function(a, b) {
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
})); },
loadGrid: function() {
this._allItems.sort(this._compareItems);
this._allItems.forEach(Lang.bind(this, function(item) { this._allItems.forEach(Lang.bind(this, function(item) {
this._grid.addItem(item); this._grid.addItem(item);
})); }));
@ -363,6 +369,32 @@ const AllView = new Lang.Class({
this.parent(); this.parent();
}, },
_itemNameChanged: function(item) {
// If an item's name changed, we can pluck it out of where it's
// supposed to be and reinsert it where it's sorted.
let oldIdx = this._allItems.indexOf(item);
this._allItems.splice(oldIdx, 1);
let newIdx = Util.insertSorted(this._allItems, item, this._compareItems);
this._grid.removeItem(item);
this._grid.addItem(item, newIdx);
},
_refilterApps: function() {
this._allItems.forEach(function(icon) {
if (icon instanceof AppIcon)
icon.actor.visible = true;
});
this.folderIcons.forEach(Lang.bind(this, function(folder) {
let folderApps = folder.getAppIds();
folderApps.forEach(Lang.bind(this, function(appId) {
let appIcon = this._items[appId];
appIcon.actor.visible = false;
}));
}));
},
_loadApps: function() { _loadApps: function() {
let apps = Gio.AppInfo.get_all().filter(function(appInfo) { let apps = Gio.AppInfo.get_all().filter(function(appInfo) {
return appInfo.should_show(); return appInfo.should_show();
@ -374,20 +406,10 @@ const AllView = new Lang.Class({
let folders = this._folderSettings.get_strv('folder-children'); let folders = this._folderSettings.get_strv('folder-children');
folders.forEach(Lang.bind(this, function(id) { folders.forEach(Lang.bind(this, function(id) {
let folder = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders.folder', let path = this._folderSettings.path + 'folders/' + id + '/';
path: this._folderSettings.path + 'folders/' + id + '/' }); let icon = new FolderIcon(id, path, this);
folder.connect('changed', Lang.bind(this, function() { icon.connect('name-changed', Lang.bind(this, this._itemNameChanged));
Main.queueDeferredWork(this._redisplayWorkId); icon.connect('apps-changed', Lang.bind(this, this._refilterApps));
}));
let folderName = _getFolderName(folder);
let folderApps = folder.get_strv('apps');
folderApps.forEach(function(appId) {
let idx = apps.indexOf(appId);
if (idx >= 0)
apps.splice(idx, 1);
});
let icon = new FolderIcon(id, folderName, folderApps, this);
this.addItem(icon); this.addItem(icon);
this.folderIcons.push(icon); this.folderIcons.push(icon);
})); }));
@ -399,6 +421,7 @@ const AllView = new Lang.Class({
})); }));
this.loadGrid(); this.loadGrid();
this._refilterApps();
}, },
getCurrentPageY: function() { getCurrentPageY: function() {
@ -986,11 +1009,12 @@ const FolderView = new Lang.Class({
const FolderIcon = new Lang.Class({ const FolderIcon = new Lang.Class({
Name: 'FolderIcon', Name: 'FolderIcon',
_init: function(id, name, apps, parentView) { _init: function(id, path, parentView) {
this.id = id; this.id = id;
this.name = name;
this._parentView = parentView; this._parentView = parentView;
this._folder = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders.folder',
path: path });
this.actor = new St.Button({ style_class: 'app-well-app app-folder', this.actor = new St.Button({ style_class: 'app-well-app app-folder',
button_mask: St.ButtonMask.ONE, button_mask: St.ButtonMask.ONE,
toggle_mode: true, toggle_mode: true,
@ -1001,22 +1025,11 @@ const FolderIcon = new Lang.Class({
// whether we need to update arrow side, position etc. // whether we need to update arrow side, position etc.
this._popupInvalidated = false; this._popupInvalidated = false;
this.icon = new IconGrid.BaseIcon(this.name, this.icon = new IconGrid.BaseIcon('', { createIcon: Lang.bind(this, this._createIcon), setSizeManually: true });
{ createIcon: Lang.bind(this, this._createIcon), setSizeManually: true });
this.actor.set_child(this.icon.actor); this.actor.set_child(this.icon.actor);
this.actor.label_actor = this.icon.label; this.actor.label_actor = this.icon.label;
this.view = new FolderView(); this.view = new FolderView();
let appSys = Shell.AppSystem.get_default();
apps.forEach(Lang.bind(this, function(appId) {
let app = appSys.lookup_app(appId);
if (!app)
return;
let icon = new AppIcon(app);
this.view.addItem(icon);
}));
this.view.loadGrid();
this.actor.connect('clicked', Lang.bind(this, this.actor.connect('clicked', Lang.bind(this,
function() { function() {
@ -1029,6 +1042,48 @@ const FolderIcon = new Lang.Class({
if (!this.actor.mapped && this._popup) if (!this.actor.mapped && this._popup)
this._popup.popdown(); this._popup.popdown();
})); }));
this._folder.connect('changed', Lang.bind(this, this._redisplay));
this._redisplay();
},
getAppIds: function() {
return this.view.getAllItems().map(function(item) {
return item.id;
});
},
_updateName: function() {
let name = _getFolderName(this._folder);
if (this.name == name)
return;
this.name = name;
this.icon.label.text = this.name;
this.emit('name-changed');
},
_redisplay: function() {
this._updateName();
this.view.removeAll();
let appSys = Shell.AppSystem.get_default();
let folderApps = this._folder.get_strv('apps');
folderApps.forEach(Lang.bind(this, function(appId) {
let app = appSys.lookup_app(appId);
if (!app)
return;
if (!app.get_app_info().should_show())
return;
let icon = new AppIcon(app);
this.view.addItem(icon);
}));
this.view.loadGrid();
this.emit('apps-changed');
}, },
_createIcon: function(iconSize) { _createIcon: function(iconSize) {
@ -1107,6 +1162,7 @@ const FolderIcon = new Lang.Class({
this._popupInvalidated = true; this._popupInvalidated = true;
}, },
}); });
Signals.addSignalMethods(FolderIcon.prototype);
const AppFolderPopup = new Lang.Class({ const AppFolderPopup = new Lang.Class({
Name: 'AppFolderPopup', Name: 'AppFolderPopup',

View File

@ -433,6 +433,10 @@ const IconGrid = new Lang.Class({
this._grid.add_actor(item.actor); this._grid.add_actor(item.actor);
}, },
removeItem: function(item) {
this._grid.remove_child(item.actor);
},
getItemAtIndex: function(index) { getItemAtIndex: function(index) {
return this._grid.get_child_at_index(index); return this._grid.get_child_at_index(index);
}, },