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:
parent
c985fdccba
commit
8507d3c4e4
@ -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>
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user