search-display: Move SearchResults to a separate file
With the new layout, search results will be displayed in an independent view like window previews, applications and possible future additions; it does not make much sense keeping it with the switching logic, so move the code to its own file. Also remove the dash-prefix from the relevant style classes. https://bugzilla.gnome.org/show_bug.cgi?id=634948
This commit is contained in:
parent
26225f0bfb
commit
e6bb06a7cc
@ -431,25 +431,25 @@ StTooltip StLabel {
|
|||||||
padding: 8px 0px;
|
padding: 8px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-search-statustext,
|
.search-statustext,
|
||||||
.dash-search-section-header {
|
.search-section-header {
|
||||||
padding: 4px 0px;
|
padding: 4px 0px;
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-search-section-results {
|
.search-section-results {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-search-section-list-results {
|
.search-section-list-results {
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-search-result-content {
|
.search-result-content {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dash-search-result-content:selected {
|
.search-result-content:selected {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border: 1px solid #5c5c5c;
|
border: 1px solid #5c5c5c;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
@ -40,6 +40,7 @@ nobase_dist_js_DATA = \
|
|||||||
ui/runDialog.js \
|
ui/runDialog.js \
|
||||||
ui/scripting.js \
|
ui/scripting.js \
|
||||||
ui/search.js \
|
ui/search.js \
|
||||||
|
ui/searchDisplay.js \
|
||||||
ui/shellDBus.js \
|
ui/shellDBus.js \
|
||||||
ui/statusIconDispatcher.js \
|
ui/statusIconDispatcher.js \
|
||||||
ui/statusMenu.js \
|
ui/statusMenu.js \
|
||||||
|
316
js/ui/dash.js
316
js/ui/dash.js
@ -17,12 +17,10 @@ const PlaceDisplay = imports.ui.placeDisplay;
|
|||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Search = imports.ui.search;
|
const Search = imports.ui.search;
|
||||||
|
const SearchDisplay = imports.ui.searchDisplay;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
|
|
||||||
// 25 search results (per result type) should be enough for everyone
|
|
||||||
const MAX_RENDERED_SEARCH_RESULTS = 25;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the index in an array of a given length that is obtained
|
* Returns the index in an array of a given length that is obtained
|
||||||
* if the provided index is incremented by an increment and the array
|
* if the provided index is incremented by an increment and the array
|
||||||
@ -283,295 +281,6 @@ SearchEntry.prototype = {
|
|||||||
};
|
};
|
||||||
Signals.addSignalMethods(SearchEntry.prototype);
|
Signals.addSignalMethods(SearchEntry.prototype);
|
||||||
|
|
||||||
function SearchResult(provider, metaInfo, terms) {
|
|
||||||
this._init(provider, metaInfo, terms);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchResult.prototype = {
|
|
||||||
_init: function(provider, metaInfo, terms) {
|
|
||||||
this.provider = provider;
|
|
||||||
this.metaInfo = metaInfo;
|
|
||||||
this.actor = new St.Clickable({ style_class: 'dash-search-result',
|
|
||||||
reactive: true,
|
|
||||||
x_align: St.Align.START,
|
|
||||||
x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
this.actor._delegate = this;
|
|
||||||
|
|
||||||
let content = provider.createResultActor(metaInfo, terms);
|
|
||||||
if (content == null) {
|
|
||||||
content = new St.BoxLayout({ style_class: 'dash-search-result-content' });
|
|
||||||
let title = new St.Label({ text: this.metaInfo['name'] });
|
|
||||||
let icon = this.metaInfo['icon'];
|
|
||||||
content.add(icon, { y_fill: false });
|
|
||||||
content.add(title, { expand: true, y_fill: false });
|
|
||||||
}
|
|
||||||
this._content = content;
|
|
||||||
this.actor.set_child(content);
|
|
||||||
|
|
||||||
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
|
|
||||||
|
|
||||||
let draggable = DND.makeDraggable(this.actor);
|
|
||||||
draggable.connect('drag-begin',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
Main.overview.beginItemDrag(this);
|
|
||||||
}));
|
|
||||||
draggable.connect('drag-end',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
Main.overview.endItemDrag(this);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
setSelected: function(selected) {
|
|
||||||
if (selected)
|
|
||||||
this._content.add_style_pseudo_class('selected');
|
|
||||||
else
|
|
||||||
this._content.remove_style_pseudo_class('selected');
|
|
||||||
},
|
|
||||||
|
|
||||||
activate: function() {
|
|
||||||
this.provider.activateResult(this.metaInfo.id);
|
|
||||||
Main.overview.toggle();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onResultClicked: function(actor, event) {
|
|
||||||
this.activate();
|
|
||||||
},
|
|
||||||
|
|
||||||
getDragActorSource: function() {
|
|
||||||
return this.metaInfo['icon'];
|
|
||||||
},
|
|
||||||
|
|
||||||
getDragActor: function(stageX, stageY) {
|
|
||||||
return new Clutter.Clone({ source: this.metaInfo['icon'] });
|
|
||||||
},
|
|
||||||
|
|
||||||
shellWorkspaceLaunch: function() {
|
|
||||||
if (this.provider.dragActivateResult)
|
|
||||||
this.provider.dragActivateResult(this.metaInfo.id);
|
|
||||||
else
|
|
||||||
this.provider.activateResult(this.metaInfo.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function OverflowSearchResults(provider) {
|
|
||||||
this._init(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
OverflowSearchResults.prototype = {
|
|
||||||
__proto__: Search.SearchResultDisplay.prototype,
|
|
||||||
|
|
||||||
_init: function(provider) {
|
|
||||||
Search.SearchResultDisplay.prototype._init.call(this, provider);
|
|
||||||
this.actor = new St.OverflowBox({ style_class: 'dash-search-section-list-results' });
|
|
||||||
},
|
|
||||||
|
|
||||||
getVisibleResultCount: function() {
|
|
||||||
return this.actor.get_n_visible();
|
|
||||||
},
|
|
||||||
|
|
||||||
renderResults: function(results, terms) {
|
|
||||||
for (let i = 0; i < results.length && i < MAX_RENDERED_SEARCH_RESULTS; i++) {
|
|
||||||
let result = results[i];
|
|
||||||
let meta = this.provider.getResultMeta(result);
|
|
||||||
let display = new SearchResult(this.provider, meta, terms);
|
|
||||||
this.actor.add_actor(display.actor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
selectIndex: function(index) {
|
|
||||||
let nVisible = this.actor.get_n_visible();
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
if (this.selectionIndex >= 0) {
|
|
||||||
let prevActor = children[this.selectionIndex];
|
|
||||||
prevActor._delegate.setSelected(false);
|
|
||||||
}
|
|
||||||
this.selectionIndex = -1;
|
|
||||||
if (index >= nVisible)
|
|
||||||
return false;
|
|
||||||
else if (index < 0)
|
|
||||||
return false;
|
|
||||||
let targetActor = children[index];
|
|
||||||
targetActor._delegate.setSelected(true);
|
|
||||||
this.selectionIndex = index;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
activateSelected: function() {
|
|
||||||
let children = this.actor.get_children();
|
|
||||||
let targetActor = children[this.selectionIndex];
|
|
||||||
targetActor._delegate.activate();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function SearchResults(searchSystem) {
|
|
||||||
this._init(searchSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchResults.prototype = {
|
|
||||||
_init: function(searchSystem) {
|
|
||||||
this._searchSystem = searchSystem;
|
|
||||||
|
|
||||||
this.actor = new St.BoxLayout({ name: 'dashSearchResults',
|
|
||||||
vertical: true });
|
|
||||||
this._statusText = new St.Label({ style_class: 'dash-search-statustext' });
|
|
||||||
this.actor.add(this._statusText);
|
|
||||||
this._selectedProvider = -1;
|
|
||||||
this._providers = this._searchSystem.getProviders();
|
|
||||||
this._providerMeta = [];
|
|
||||||
for (let i = 0; i < this._providers.length; i++)
|
|
||||||
this.createProviderMeta(this._providers[i]);
|
|
||||||
},
|
|
||||||
|
|
||||||
createProviderMeta: function(provider) {
|
|
||||||
let providerBox = new St.BoxLayout({ style_class: 'dash-search-section',
|
|
||||||
vertical: true });
|
|
||||||
let titleButton = new St.Button({ style_class: 'dash-search-section-header',
|
|
||||||
reactive: true,
|
|
||||||
x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
titleButton.connect('clicked', Lang.bind(this, function () { this._onHeaderClicked(provider); }));
|
|
||||||
providerBox.add(titleButton);
|
|
||||||
let titleBox = new St.BoxLayout();
|
|
||||||
titleButton.set_child(titleBox);
|
|
||||||
let title = new St.Label({ text: provider.title });
|
|
||||||
let count = new St.Label();
|
|
||||||
titleBox.add(title, { expand: true });
|
|
||||||
titleBox.add(count);
|
|
||||||
|
|
||||||
let resultDisplayBin = new St.Bin({ style_class: 'dash-search-section-results',
|
|
||||||
x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
providerBox.add(resultDisplayBin, { expand: true });
|
|
||||||
let resultDisplay = provider.createResultContainerActor();
|
|
||||||
if (resultDisplay == null) {
|
|
||||||
resultDisplay = new OverflowSearchResults(provider);
|
|
||||||
}
|
|
||||||
resultDisplayBin.set_child(resultDisplay.actor);
|
|
||||||
|
|
||||||
this._providerMeta.push({ actor: providerBox,
|
|
||||||
resultDisplay: resultDisplay,
|
|
||||||
count: count });
|
|
||||||
this.actor.add(providerBox);
|
|
||||||
},
|
|
||||||
|
|
||||||
_clearDisplay: function() {
|
|
||||||
this._selectedProvider = -1;
|
|
||||||
this._visibleResultsCount = 0;
|
|
||||||
for (let i = 0; i < this._providerMeta.length; i++) {
|
|
||||||
let meta = this._providerMeta[i];
|
|
||||||
meta.resultDisplay.clear();
|
|
||||||
meta.actor.hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reset: function() {
|
|
||||||
this._searchSystem.reset();
|
|
||||||
this._statusText.hide();
|
|
||||||
this._clearDisplay();
|
|
||||||
},
|
|
||||||
|
|
||||||
startingSearch: function() {
|
|
||||||
this.reset();
|
|
||||||
this._statusText.set_text(_("Searching..."));
|
|
||||||
this._statusText.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
_metaForProvider: function(provider) {
|
|
||||||
return this._providerMeta[this._providers.indexOf(provider)];
|
|
||||||
},
|
|
||||||
|
|
||||||
updateSearch: function (searchString) {
|
|
||||||
let results = this._searchSystem.updateSearch(searchString);
|
|
||||||
|
|
||||||
this._clearDisplay();
|
|
||||||
|
|
||||||
if (results.length == 0) {
|
|
||||||
this._statusText.set_text(_("No matching results."));
|
|
||||||
this._statusText.show();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
this._statusText.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
let terms = this._searchSystem.getTerms();
|
|
||||||
|
|
||||||
for (let i = 0; i < results.length; i++) {
|
|
||||||
let [provider, providerResults] = results[i];
|
|
||||||
let meta = this._metaForProvider(provider);
|
|
||||||
meta.actor.show();
|
|
||||||
meta.resultDisplay.renderResults(providerResults, terms);
|
|
||||||
meta.count.set_text('' + providerResults.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectDown(false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onHeaderClicked: function(provider) {
|
|
||||||
provider.expandSearch(this._searchSystem.getTerms());
|
|
||||||
},
|
|
||||||
|
|
||||||
_modifyActorSelection: function(resultDisplay, up) {
|
|
||||||
let success;
|
|
||||||
let index = resultDisplay.getSelectionIndex();
|
|
||||||
if (up && index == -1)
|
|
||||||
index = resultDisplay.getVisibleResultCount() - 1;
|
|
||||||
else if (up)
|
|
||||||
index = index - 1;
|
|
||||||
else
|
|
||||||
index = index + 1;
|
|
||||||
return resultDisplay.selectIndex(index);
|
|
||||||
},
|
|
||||||
|
|
||||||
selectUp: function(recursing) {
|
|
||||||
for (let i = this._selectedProvider; i >= 0; i--) {
|
|
||||||
let meta = this._providerMeta[i];
|
|
||||||
if (!meta.actor.visible)
|
|
||||||
continue;
|
|
||||||
let success = this._modifyActorSelection(meta.resultDisplay, true);
|
|
||||||
if (success) {
|
|
||||||
this._selectedProvider = i;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this._providerMeta.length > 0 && !recursing) {
|
|
||||||
this._selectedProvider = this._providerMeta.length - 1;
|
|
||||||
this.selectUp(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
selectDown: function(recursing) {
|
|
||||||
let current = this._selectedProvider;
|
|
||||||
if (current == -1)
|
|
||||||
current = 0;
|
|
||||||
for (let i = current; i < this._providerMeta.length; i++) {
|
|
||||||
let meta = this._providerMeta[i];
|
|
||||||
if (!meta.actor.visible)
|
|
||||||
continue;
|
|
||||||
let success = this._modifyActorSelection(meta.resultDisplay, false);
|
|
||||||
if (success) {
|
|
||||||
this._selectedProvider = i;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this._providerMeta.length > 0 && !recursing) {
|
|
||||||
this._selectedProvider = 0;
|
|
||||||
this.selectDown(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
activateSelected: function() {
|
|
||||||
let current = this._selectedProvider;
|
|
||||||
if (current < 0)
|
|
||||||
return;
|
|
||||||
let meta = this._providerMeta[current];
|
|
||||||
let resultDisplay = meta.resultDisplay;
|
|
||||||
resultDisplay.activateSelected();
|
|
||||||
Main.overview.hide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function MoreLink() {
|
function MoreLink() {
|
||||||
this._init();
|
this._init();
|
||||||
@ -654,27 +363,6 @@ SectionHeader.prototype = {
|
|||||||
|
|
||||||
Signals.addSignalMethods(SectionHeader.prototype);
|
Signals.addSignalMethods(SectionHeader.prototype);
|
||||||
|
|
||||||
function SearchSectionHeader(title, onClick) {
|
|
||||||
this._init(title, onClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchSectionHeader.prototype = {
|
|
||||||
_init : function(title, onClick) {
|
|
||||||
this.actor = new St.Button({ style_class: 'dash-search-section-header',
|
|
||||||
x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
let box = new St.BoxLayout();
|
|
||||||
this.actor.set_child(box);
|
|
||||||
let titleText = new St.Label({ style_class: 'dash-search-section-title',
|
|
||||||
text: title });
|
|
||||||
this.countText = new St.Label({ style_class: 'dash-search-section-count' });
|
|
||||||
|
|
||||||
box.add(titleText);
|
|
||||||
box.add(this.countText, { expand: true, x_fill: false, x_align: St.Align.END });
|
|
||||||
|
|
||||||
this.actor.connect('clicked', onClick);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Section(titleString, suppressBrowse) {
|
function Section(titleString, suppressBrowse) {
|
||||||
this._init(titleString, suppressBrowse);
|
this._init(titleString, suppressBrowse);
|
||||||
@ -736,7 +424,7 @@ OldDash.prototype = {
|
|||||||
this._searchSystem.registerProvider(new PlaceDisplay.PlaceSearchProvider());
|
this._searchSystem.registerProvider(new PlaceDisplay.PlaceSearchProvider());
|
||||||
this._searchSystem.registerProvider(new DocDisplay.DocSearchProvider());
|
this._searchSystem.registerProvider(new DocDisplay.DocSearchProvider());
|
||||||
|
|
||||||
this.searchResults = new SearchResults(this._searchSystem);
|
this.searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||||
this.actor.add(this.searchResults.actor);
|
this.actor.add(this.searchResults.actor);
|
||||||
this.searchResults.actor.hide();
|
this.searchResults.actor.hide();
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ SearchProvider.prototype = {
|
|||||||
* implementation will show the icon next to the name.
|
* implementation will show the icon next to the name.
|
||||||
*
|
*
|
||||||
* The actor should be an instance of St.Widget, with the style class
|
* The actor should be an instance of St.Widget, with the style class
|
||||||
* 'dash-search-result-content'.
|
* 'search-result-content'.
|
||||||
*/
|
*/
|
||||||
createResultActor: function(resultMeta, terms) {
|
createResultActor: function(resultMeta, terms) {
|
||||||
return null;
|
return null;
|
||||||
|
304
js/ui/searchDisplay.js
Normal file
304
js/ui/searchDisplay.js
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Search = imports.ui.search;
|
||||||
|
|
||||||
|
|
||||||
|
// 25 search results (per result type) should be enough for everyone
|
||||||
|
const MAX_RENDERED_SEARCH_RESULTS = 25;
|
||||||
|
|
||||||
|
function SearchResult(provider, metaInfo, terms) {
|
||||||
|
this._init(provider, metaInfo, terms);
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResult.prototype = {
|
||||||
|
_init: function(provider, metaInfo, terms) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.metaInfo = metaInfo;
|
||||||
|
this.actor = new St.Clickable({ style_class: 'search-result',
|
||||||
|
reactive: true,
|
||||||
|
x_align: St.Align.START,
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
|
||||||
|
let content = provider.createResultActor(metaInfo, terms);
|
||||||
|
if (content == null) {
|
||||||
|
content = new St.BoxLayout({ style_class: 'search-result-content' });
|
||||||
|
let title = new St.Label({ text: this.metaInfo['name'] });
|
||||||
|
let icon = this.metaInfo['icon'];
|
||||||
|
content.add(icon, { y_fill: false });
|
||||||
|
content.add(title, { expand: true, y_fill: false });
|
||||||
|
}
|
||||||
|
this._content = content;
|
||||||
|
this.actor.set_child(content);
|
||||||
|
|
||||||
|
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
|
||||||
|
|
||||||
|
let draggable = DND.makeDraggable(this.actor);
|
||||||
|
draggable.connect('drag-begin',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
Main.overview.beginItemDrag(this);
|
||||||
|
}));
|
||||||
|
draggable.connect('drag-end',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
Main.overview.endItemDrag(this);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
setSelected: function(selected) {
|
||||||
|
if (selected)
|
||||||
|
this._content.add_style_pseudo_class('selected');
|
||||||
|
else
|
||||||
|
this._content.remove_style_pseudo_class('selected');
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function() {
|
||||||
|
this.provider.activateResult(this.metaInfo.id);
|
||||||
|
Main.overview.toggle();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onResultClicked: function(actor, event) {
|
||||||
|
this.activate();
|
||||||
|
},
|
||||||
|
|
||||||
|
getDragActorSource: function() {
|
||||||
|
return this.metaInfo['icon'];
|
||||||
|
},
|
||||||
|
|
||||||
|
getDragActor: function(stageX, stageY) {
|
||||||
|
return new Clutter.Clone({ source: this.metaInfo['icon'] });
|
||||||
|
},
|
||||||
|
|
||||||
|
shellWorkspaceLaunch: function() {
|
||||||
|
if (this.provider.dragActivateResult)
|
||||||
|
this.provider.dragActivateResult(this.metaInfo.id);
|
||||||
|
else
|
||||||
|
this.provider.activateResult(this.metaInfo.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function OverflowSearchResults(provider) {
|
||||||
|
this._init(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
OverflowSearchResults.prototype = {
|
||||||
|
__proto__: Search.SearchResultDisplay.prototype,
|
||||||
|
|
||||||
|
_init: function(provider) {
|
||||||
|
Search.SearchResultDisplay.prototype._init.call(this, provider);
|
||||||
|
this.actor = new St.OverflowBox({ style_class: 'search-section-list-results' });
|
||||||
|
},
|
||||||
|
|
||||||
|
getVisibleResultCount: function() {
|
||||||
|
return this.actor.get_n_visible();
|
||||||
|
},
|
||||||
|
|
||||||
|
renderResults: function(results, terms) {
|
||||||
|
for (let i = 0; i < results.length && i < MAX_RENDERED_SEARCH_RESULTS; i++) {
|
||||||
|
let result = results[i];
|
||||||
|
let meta = this.provider.getResultMeta(result);
|
||||||
|
let display = new SearchResult(this.provider, meta, terms);
|
||||||
|
this.actor.add_actor(display.actor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectIndex: function(index) {
|
||||||
|
let nVisible = this.actor.get_n_visible();
|
||||||
|
let children = this.actor.get_children();
|
||||||
|
if (this.selectionIndex >= 0) {
|
||||||
|
let prevActor = children[this.selectionIndex];
|
||||||
|
prevActor._delegate.setSelected(false);
|
||||||
|
}
|
||||||
|
this.selectionIndex = -1;
|
||||||
|
if (index >= nVisible)
|
||||||
|
return false;
|
||||||
|
else if (index < 0)
|
||||||
|
return false;
|
||||||
|
let targetActor = children[index];
|
||||||
|
targetActor._delegate.setSelected(true);
|
||||||
|
this.selectionIndex = index;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
activateSelected: function() {
|
||||||
|
let children = this.actor.get_children();
|
||||||
|
let targetActor = children[this.selectionIndex];
|
||||||
|
targetActor._delegate.activate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function SearchResults(searchSystem) {
|
||||||
|
this._init(searchSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResults.prototype = {
|
||||||
|
_init: function(searchSystem) {
|
||||||
|
this._searchSystem = searchSystem;
|
||||||
|
|
||||||
|
this.actor = new St.BoxLayout({ name: 'searchResults',
|
||||||
|
vertical: true });
|
||||||
|
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||||
|
this.actor.add(this._statusText);
|
||||||
|
this._selectedProvider = -1;
|
||||||
|
this._providers = this._searchSystem.getProviders();
|
||||||
|
this._providerMeta = [];
|
||||||
|
for (let i = 0; i < this._providers.length; i++)
|
||||||
|
this.createProviderMeta(this._providers[i]);
|
||||||
|
},
|
||||||
|
|
||||||
|
createProviderMeta: function(provider) {
|
||||||
|
let providerBox = new St.BoxLayout({ style_class: 'search-section',
|
||||||
|
vertical: true });
|
||||||
|
let titleButton = new St.Button({ style_class: 'search-section-header',
|
||||||
|
reactive: true,
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
titleButton.connect('clicked', Lang.bind(this, function () { this._onHeaderClicked(provider); }));
|
||||||
|
providerBox.add(titleButton);
|
||||||
|
let titleBox = new St.BoxLayout();
|
||||||
|
titleButton.set_child(titleBox);
|
||||||
|
let title = new St.Label({ text: provider.title });
|
||||||
|
let count = new St.Label();
|
||||||
|
titleBox.add(title, { expand: true });
|
||||||
|
titleBox.add(count);
|
||||||
|
|
||||||
|
let resultDisplayBin = new St.Bin({ style_class: 'search-section-results',
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
providerBox.add(resultDisplayBin, { expand: true });
|
||||||
|
let resultDisplay = provider.createResultContainerActor();
|
||||||
|
if (resultDisplay == null) {
|
||||||
|
resultDisplay = new OverflowSearchResults(provider);
|
||||||
|
}
|
||||||
|
resultDisplayBin.set_child(resultDisplay.actor);
|
||||||
|
|
||||||
|
this._providerMeta.push({ actor: providerBox,
|
||||||
|
resultDisplay: resultDisplay,
|
||||||
|
count: count });
|
||||||
|
this.actor.add(providerBox);
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearDisplay: function() {
|
||||||
|
this._selectedProvider = -1;
|
||||||
|
this._visibleResultsCount = 0;
|
||||||
|
for (let i = 0; i < this._providerMeta.length; i++) {
|
||||||
|
let meta = this._providerMeta[i];
|
||||||
|
meta.resultDisplay.clear();
|
||||||
|
meta.actor.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function() {
|
||||||
|
this._searchSystem.reset();
|
||||||
|
this._statusText.hide();
|
||||||
|
this._clearDisplay();
|
||||||
|
},
|
||||||
|
|
||||||
|
startingSearch: function() {
|
||||||
|
this.reset();
|
||||||
|
this._statusText.set_text(_("Searching..."));
|
||||||
|
this._statusText.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
_metaForProvider: function(provider) {
|
||||||
|
return this._providerMeta[this._providers.indexOf(provider)];
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSearch: function (searchString) {
|
||||||
|
let results = this._searchSystem.updateSearch(searchString);
|
||||||
|
|
||||||
|
this._clearDisplay();
|
||||||
|
|
||||||
|
if (results.length == 0) {
|
||||||
|
this._statusText.set_text(_("No matching results."));
|
||||||
|
this._statusText.show();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this._statusText.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
let terms = this._searchSystem.getTerms();
|
||||||
|
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
let [provider, providerResults] = results[i];
|
||||||
|
let meta = this._metaForProvider(provider);
|
||||||
|
meta.actor.show();
|
||||||
|
meta.resultDisplay.renderResults(providerResults, terms);
|
||||||
|
meta.count.set_text('' + providerResults.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectDown(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onHeaderClicked: function(provider) {
|
||||||
|
provider.expandSearch(this._searchSystem.getTerms());
|
||||||
|
},
|
||||||
|
|
||||||
|
_modifyActorSelection: function(resultDisplay, up) {
|
||||||
|
let success;
|
||||||
|
let index = resultDisplay.getSelectionIndex();
|
||||||
|
if (up && index == -1)
|
||||||
|
index = resultDisplay.getVisibleResultCount() - 1;
|
||||||
|
else if (up)
|
||||||
|
index = index - 1;
|
||||||
|
else
|
||||||
|
index = index + 1;
|
||||||
|
return resultDisplay.selectIndex(index);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectUp: function(recursing) {
|
||||||
|
for (let i = this._selectedProvider; i >= 0; i--) {
|
||||||
|
let meta = this._providerMeta[i];
|
||||||
|
if (!meta.actor.visible)
|
||||||
|
continue;
|
||||||
|
let success = this._modifyActorSelection(meta.resultDisplay, true);
|
||||||
|
if (success) {
|
||||||
|
this._selectedProvider = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._providerMeta.length > 0 && !recursing) {
|
||||||
|
this._selectedProvider = this._providerMeta.length - 1;
|
||||||
|
this.selectUp(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectDown: function(recursing) {
|
||||||
|
let current = this._selectedProvider;
|
||||||
|
if (current == -1)
|
||||||
|
current = 0;
|
||||||
|
for (let i = current; i < this._providerMeta.length; i++) {
|
||||||
|
let meta = this._providerMeta[i];
|
||||||
|
if (!meta.actor.visible)
|
||||||
|
continue;
|
||||||
|
let success = this._modifyActorSelection(meta.resultDisplay, false);
|
||||||
|
if (success) {
|
||||||
|
this._selectedProvider = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._providerMeta.length > 0 && !recursing) {
|
||||||
|
this._selectedProvider = 0;
|
||||||
|
this.selectDown(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
activateSelected: function() {
|
||||||
|
let current = this._selectedProvider;
|
||||||
|
if (current < 0)
|
||||||
|
return;
|
||||||
|
let meta = this._providerMeta[current];
|
||||||
|
let resultDisplay = meta.resultDisplay;
|
||||||
|
resultDisplay.activateSelected();
|
||||||
|
Main.overview.hide();
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user