From af06b78605b7bbcfce9f2c839909c90bbd91daa5 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Fri, 8 Feb 2013 18:59:15 -0500 Subject: [PATCH] searchDisplay: Cache result display actors When we create a result actor, cache it, so it can be used for subsearches of the same initial. For now, to keep memory usage and the stage graph relatively clean, don't persist the actors across searches, but maybe we should do this in the future. This also means that we don't query getResultMetas for items that we've seen in the same initial search. https://bugzilla.gnome.org/show_bug.cgi?id=704912 --- js/ui/appDisplay.js | 6 ++++- js/ui/iconGrid.js | 5 ++++ js/ui/search.js | 57 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index cc711bd40..7186d9f3d 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -92,7 +92,7 @@ const BaseAppView = new Lang.Class({ }, removeAll: function() { - this._grid.removeAll(); + this._grid.destroyAll(); this._items = {}; this._allItems = []; }, @@ -613,6 +613,10 @@ const FrequentView = new Lang.Class({ return this._usage.get_most_used("").length >= MIN_FREQUENT_APPS_COUNT; }, + removeAll: function() { + this._grid.destroyAll(); + }, + loadApps: function() { let mostUsed = this._usage.get_most_used (""); let hasUsefulData = this.hasUsefulData(); diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js index 8bcb56d2c..4801ac23b 100644 --- a/js/ui/iconGrid.js +++ b/js/ui/iconGrid.js @@ -413,6 +413,11 @@ const IconGrid = new Lang.Class({ }, removeAll: function() { + this._items = []; + this._grid.remove_all_children(); + }, + + destroyAll: function() { this._items = []; this._grid.destroy_all_children(); }, diff --git a/js/ui/search.js b/js/ui/search.js index 7cd219557..4fb03eecc 100644 --- a/js/ui/search.js +++ b/js/ui/search.js @@ -323,6 +323,8 @@ const SearchResultsBase = new Lang.Class({ let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' }); this.actor.add(separator.actor); + + this._resultDisplays = {}; }, destroy: function() { @@ -334,6 +336,7 @@ const SearchResultsBase = new Lang.Class({ }, clear: function() { + this._resultDisplays = {}; this._clearResultDisplay(); this.actor.hide(); }, @@ -349,6 +352,27 @@ const SearchResultsBase = new Lang.Class({ _setMoreIconVisible: function(visible) { }, + _ensureResultActors: function(results, callback) { + let metasNeeded = results.filter(Lang.bind(this, function(resultId) { + return this._resultDisplays[resultId] === undefined; + })); + + if (metasNeeded.length === 0) { + callback(); + } else { + this.provider.getResultMetas(metasNeeded, Lang.bind(this, function(metas) { + metasNeeded.forEach(Lang.bind(this, function(resultId, i) { + let meta = metas[i]; + let display = this._createResultDisplay(meta); + display.connect('activate', Lang.bind(this, this._activateResult)); + display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); + this._resultDisplays[resultId] = display; + })); + callback(); + })); + } + }, + updateSearch: function(providerResults, terms, callback) { this._terms = terms; @@ -361,15 +385,17 @@ const SearchResultsBase = new Lang.Class({ let results = this.provider.filterResults(providerResults, maxResults); let hasMoreResults = results.length < providerResults.length; - this.provider.getResultMetas(results, Lang.bind(this, function(metas) { - this.clear(); + this._ensureResultActors(results, Lang.bind(this, function() { + this._clearResultDisplay(); // To avoid CSS transitions causing flickering when // the first search result stays the same, we hide the // content while filling in the results. this.actor.hide(); this._clearResultDisplay(); - this._renderResults(metas); + results.forEach(Lang.bind(this, function(resultId) { + this._addItem(this._resultDisplays[resultId]); + })); this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch); this.actor.show(); callback(); @@ -414,17 +440,16 @@ const ListSearchResults = new Lang.Class({ return MAX_LIST_SEARCH_RESULTS_ROWS; }, - _renderResults: function(metas) { - for (let i = 0; i < metas.length; i++) { - let display = new ListSearchResult(this.provider, metas[i]); - display.connect('activate', Lang.bind(this, this._activateResult)); - display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); - this._content.add_actor(display.actor); - } + _clearResultDisplay: function () { + this._content.remove_all_children(); }, - _clearResultDisplay: function () { - this._content.destroy_all_children(); + _createResultDisplay: function(meta) { + return new ListSearchResult(this.provider, meta); + }, + + _addItem: function(display) { + this._content.add_actor(display.actor); }, getFirstResult: function() { @@ -468,6 +493,14 @@ const GridSearchResults = new Lang.Class({ this._grid.removeAll(); }, + _createResultDisplay: function(meta) { + return new GridSearchResult(this.provider, meta); + }, + + _addItem: function(display) { + this._grid.addItem(display.actor); + }, + getFirstResult: function() { if (this._grid.visibleItemsCount() > 0) return this._grid.getItemAtIndex(0)._delegate;