searchDisplay, and others: Switch from provider title to provider icon

Display a '+' icon on the provider icon if there are more results that are
hidden. If the provider icon is clicked, ask the provider to launch itself and
perform a search with the current terms.

https://bugzilla.gnome.org/show_bug.cgi?id=681797
This commit is contained in:
Tanner Doshier 2012-08-09 16:52:36 -05:00 committed by Jasper St. Pierre
parent c985fdccba
commit 8507d3c4e4
4 changed files with 133 additions and 6 deletions

View File

@ -143,5 +143,25 @@
</doc:doc> </doc:doc>
</arg> </arg>
</method> </method>
<method name="LaunchSearch">
<doc:doc>
<doc:description>
<doc:para>
Called when the user clicks on the provider icon. The provider
application should open and run the active search term itself.
</doc:para>
</doc:description>
</doc:doc>
<arg type="as" direction="in">
<doc:doc>
<doc:summary>
<doc:para>
The current search term(s).
</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method>
</interface> </interface>
</node> </node>

View File

@ -27,6 +27,9 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
<method name="ActivateResult"> <method name="ActivateResult">
<arg type="s" direction="in" /> <arg type="s" direction="in" />
</method> </method>
<method name="LaunchSearch">
<arg type="as" direction="in" />
</method>
</interface>; </interface>;
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface); var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
@ -112,6 +115,7 @@ const RemoteSearchProvider = new Lang.Class({
this.parent(title.toUpperCase()); this.parent(title.toUpperCase());
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
this.icon = icon;
}, },
createIcon: function(size, meta) { createIcon: function(size, meta) {
@ -196,6 +200,10 @@ const RemoteSearchProvider = new Lang.Class({
activateResult: function(id) { activateResult: function(id) {
this._proxy.ActivateResultRemote(id); this._proxy.ActivateResultRemote(id);
},
launchSearch: function(terms) {
this._proxy.LaunchSearchRemote(terms);
} }
}); });

View File

@ -163,6 +163,16 @@ const SearchProvider = new Lang.Class({
*/ */
activateResult: function(id) { activateResult: function(id) {
throw new Error('Not implemented'); throw new Error('Not implemented');
},
/**
* launchSearch:
* @terms: Current search terms
*
* Called when the user clicks the provider icon.
*/
launchSearch: function(terms) {
throw new Error('Not implemented');
} }
}); });
Signals.addSignalMethods(SearchProvider.prototype); Signals.addSignalMethods(SearchProvider.prototype);
@ -261,5 +271,11 @@ const SearchSystem = new Lang.Class({
} }
} }
}, },
launchSearch: function(provider) {
let terms = this.getTerms();
provider.launchSearch(terms);
Main.overview.toggle();
}
}); });
Signals.addSignalMethods(SearchSystem.prototype); Signals.addSignalMethods(SearchSystem.prototype);

View File

@ -7,6 +7,7 @@ const Meta = imports.gi.Meta;
const St = imports.gi.St; const St = imports.gi.St;
const Atk = imports.gi.Atk; const Atk = imports.gi.Atk;
const AppDisplay = imports.ui.appDisplay;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -111,8 +112,8 @@ const GridSearchResults = new Lang.Class({
this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS, this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START }); xAlign: St.Align.START });
this.actor = new St.Bin({ x_align: St.Align.START }); this.actor = new St.Bin({ x_align: St.Align.START });
this.actor.set_child(this._grid.actor); this.actor.set_child(this._grid.actor);
this._width = 0; this._width = 0;
this.actor.connect('notify::width', Lang.bind(this, function() { this.actor.connect('notify::width', Lang.bind(this, function() {
this._width = this.actor.width; this._width = this.actor.width;
@ -130,6 +131,7 @@ const GridSearchResults = new Lang.Class({
}, },
getResultsForDisplay: function() { getResultsForDisplay: function() {
this._grid.actor.ensure_style();
let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount(); let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount();
let canDisplay = this._grid.childrenInRow(this._width) * this._grid.getRowLimit() let canDisplay = this._grid.childrenInRow(this._width) * this._grid.getRowLimit()
- alreadyVisible; - alreadyVisible;
@ -143,6 +145,10 @@ const GridSearchResults = new Lang.Class({
return this._grid.visibleItemsCount(); return this._grid.visibleItemsCount();
}, },
hasMoreResults: function() {
return this._notDisplayedResult.length > 0;
},
setResults: function(results, terms) { setResults: function(results, terms) {
// copy the lists // copy the lists
this._notDisplayedResult = results.slice(0); this._notDisplayedResult = results.slice(0);
@ -220,21 +226,32 @@ const SearchResults = new Lang.Class({
}, },
createProviderMeta: function(provider) { createProviderMeta: function(provider) {
let providerBox = new St.BoxLayout({ style_class: 'search-section', let providerBox = new St.BoxLayout({ style_class: 'search-section' });
vertical: true }); let isAppsProvider = (provider instanceof AppDisplay.AppSearchProvider);
let title = new St.Label({ style_class: 'search-section-header',
text: provider.title }); let providerIcon;
providerBox.add(title, { x_fill: false, x_align: St.Align.START }); if (!isAppsProvider) {
providerIcon = new ProviderIcon(provider);
providerIcon.connect('launch-search', Lang.bind(this, function(providerIcon) {
this._searchSystem.launchSearch(providerIcon.provider);
}));
providerBox.add(providerIcon.actor, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
}
let resultDisplayBin = new St.Bin({ style_class: 'search-section-results', let resultDisplayBin = new St.Bin({ style_class: 'search-section-results',
x_fill: true, x_fill: true,
y_fill: true }); y_fill: true });
providerBox.add(resultDisplayBin, { expand: true }); providerBox.add(resultDisplayBin, { expand: true });
let resultDisplay = new GridSearchResults(provider); let resultDisplay = new GridSearchResults(provider);
resultDisplayBin.set_child(resultDisplay.actor); resultDisplayBin.set_child(resultDisplay.actor);
this._providerMeta.push({ provider: provider, this._providerMeta.push({ provider: provider,
actor: providerBox, actor: providerBox,
icon: providerIcon,
resultDisplay: resultDisplay }); resultDisplay: resultDisplay });
this._content.add(providerBox); this._content.add(providerBox);
}, },
@ -341,6 +358,9 @@ const SearchResults = new Lang.Class({
meta.resultDisplay.setResults(providerResults, terms); meta.resultDisplay.setResults(providerResults, terms);
let results = meta.resultDisplay.getResultsForDisplay(); let results = meta.resultDisplay.getResultsForDisplay();
if (meta.icon)
meta.icon.moreIcon.visible = meta.resultDisplay.hasMoreResults();
provider.getResultMetas(results, Lang.bind(this, function(metas) { provider.getResultMetas(results, Lang.bind(this, function(metas) {
this._clearDisplayForProvider(provider); this._clearDisplayForProvider(provider);
meta.actor.show(); meta.actor.show();
@ -393,3 +413,66 @@ const SearchResults = new Lang.Class({
} }
} }
}); });
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
PROVIDER_ICON_SIZE: 48,
MORE_ICON_SIZE: 16,
_init: function(provider) {
this.provider = provider;
this.actor = new St.Button({ style_class: 'search-section-icon-bin',
reactive: true,
can_focus: true,
track_hover: true });
this.actor.connect('clicked', Lang.bind(this, this._onIconClicked));
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.actor.set_child(this._content);
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Icon({ style_class: 'search-section-icon-more',
icon_size: this.MORE_ICON_SIZE,
icon_name: 'list-add-symbolic',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
// HACK: without these, ClutterBinLayout
// ignores alignment properties on the actor
x_expand: true,
y_expand: true });
this._iconBin = new St.Bin({ style_class: 'search-section-icon',
width: this.PROVIDER_ICON_SIZE,
height: this.PROVIDER_ICON_SIZE });
this._content.add_actor(this._iconBin);
this._content.add_actor(this.moreIcon);
this._createProviderIcon();
},
_createProviderIcon: function() {
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE });
if (this.provider.icon)
icon.gicon = this.provider.icon;
else
icon.icon_name = 'application-x-executable';
this._iconBin.set_child(icon);
},
activate: function() {
this.emit('launch-search');
},
_onIconClicked: function(actor) {
this.activate();
}
});
Signals.addSignalMethods(ProviderIcon.prototype);