diff --git a/data/Makefile.am b/data/Makefile.am index c998dce16..f3e90b0ec 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -34,6 +34,7 @@ dist_theme_DATA = \ theme/gnome-shell.css \ theme/logged-in-indicator.svg \ theme/message-tray-background.png \ + theme/more-results.svg \ theme/noise-texture.png \ theme/panel-button-border.svg \ theme/panel-button-highlight-narrow.svg \ diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index a4b984275..fd3121ef9 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -871,8 +871,15 @@ StScrollBar StButton#vhandle:active { padding: 4px 8px; } +.search-provider-icon-more { + width: 16px; + height: 16px; + background-image: url("more-results.svg"); +} + .app-well-app > .overview-icon, .show-apps > .overview-icon, +.search-provider-icon, .search-result-content > .overview-icon { border-radius: 4px; padding: 3px; @@ -889,6 +896,7 @@ StScrollBar StButton#vhandle:active { .app-well-app:hover > .overview-icon, .show-apps:hover > .overview-icon, +.search-provider-icon:hover, .search-result-content:hover > .overview-icon { background-color: rgba(255,255,255,0.1); text-shadow: black 0px 2px 2px; @@ -926,8 +934,10 @@ StScrollBar StButton#vhandle:active { .app-well-app:focus > .overview-icon, .search-result-content:focus > .overview-icon, .show-apps:focus > .overview-icon, +.search-provider-icon:focus, .app-well-app:selected > .overview-icon, -.search-result-content:selected > .overview-icon { +.search-result-content:selected > .overview-icon, +.search-provider-icon:selected { background-color: rgba(255,255,255,0.33); } diff --git a/data/theme/more-results.svg b/data/theme/more-results.svg new file mode 100644 index 000000000..264e14d9d --- /dev/null +++ b/data/theme/more-results.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index 944b2463c..754864d39 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -315,8 +315,9 @@ const AppSearchProvider = new Lang.Class({ Extends: Search.SearchProvider, _init: function() { - this.parent(_("APPLICATIONS")); + this.parent(); this._appSys = Shell.AppSystem.get_default(); + this.id = 'applications'; }, getResultMetas: function(apps, callback) { @@ -372,10 +373,8 @@ const SettingsSearchProvider = new Lang.Class({ Extends: Search.SearchProvider, _init: function() { - this.parent(_("SETTINGS")); - + this.parent(Gio.DesktopAppInfo.new('gnome-control-center.desktop')); this._appSys = Shell.AppSystem.get_default(); - this.appInfo = Gio.DesktopAppInfo.new('gnome-control-center.desktop'); }, getResultMetas: function(prefs, callback) { diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js index 0059ca0d8..f10205a2f 100644 --- a/js/ui/remoteSearch.js +++ b/js/ui/remoteSearch.js @@ -176,7 +176,7 @@ const RemoteSearchProvider = new Lang.Class({ this.proxy = new proxyType(Gio.DBus.session, dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed)); - this.parent(appInfo.get_name().toUpperCase(), appInfo, true); + this.parent(appInfo, true); this._cancellable = new Gio.Cancellable(); }, diff --git a/js/ui/search.js b/js/ui/search.js index e21c2a741..6bbbdab41 100644 --- a/js/ui/search.js +++ b/js/ui/search.js @@ -76,12 +76,14 @@ const SearchResultDisplay = new Lang.Class({ const SearchProvider = new Lang.Class({ Name: 'SearchProvider', - _init: function(title, appInfo, isRemoteProvider) { - this.title = title; + _init: function(appInfo, isRemoteProvider) { this.appInfo = appInfo; this.searchSystem = null; this.isRemoteProvider = !!isRemoteProvider; this.canLaunchSearch = false; + + if (this.appInfo) + this.id = this.appInfo.get_id(); }, /** @@ -273,7 +275,7 @@ const SearchSystem = new Lang.Class({ results.push([provider, []]); provider.getSubsearchResultSet(previousResults, terms); } catch (error) { - log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message); + log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message); } } } else { @@ -283,7 +285,7 @@ const SearchSystem = new Lang.Class({ results.push([provider, []]); provider.getInitialResultSet(terms); } catch (error) { - log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message); + log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message); } } } diff --git a/js/ui/searchDisplay.js b/js/ui/searchDisplay.js index 869586b9f..67a674d3f 100644 --- a/js/ui/searchDisplay.js +++ b/js/ui/searchDisplay.js @@ -144,6 +144,10 @@ const GridSearchResults = new Lang.Class({ return this._grid.visibleItemsCount(); }, + hasMoreResults: function() { + return this._notDisplayedResult.length > 0; + }, + setResults: function(results, terms) { // copy the lists this._notDisplayedResult = results.slice(0); @@ -222,11 +226,22 @@ const SearchResults = new Lang.Class({ }, createProviderMeta: function(provider) { - let providerBox = new St.BoxLayout({ style_class: 'search-section', - vertical: true }); - let title = new St.Label({ style_class: 'search-section-header', - text: provider.title }); - providerBox.add(title, { x_fill: false, x_align: St.Align.START }); + let providerBox = new St.BoxLayout({ style_class: 'search-section' }); + let providerIcon = null; + + if (provider.appInfo) { + providerIcon = new ProviderIcon(provider); + providerIcon.connect('clicked', Lang.bind(this, + function() { + provider.launchSearch(this._searchSystem.getTerms()); + Main.overview.toggle(); + })); + + providerBox.add(providerIcon, { 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', x_fill: true, @@ -237,6 +252,7 @@ const SearchResults = new Lang.Class({ this._providerMeta.push({ provider: provider, actor: providerBox, + icon: providerIcon, resultDisplay: resultDisplay }); this._content.add(providerBox); }, @@ -343,6 +359,11 @@ const SearchResults = new Lang.Class({ meta.resultDisplay.setResults(providerResults, terms); let results = meta.resultDisplay.getResultsForDisplay(); + if (meta.icon) + meta.icon.moreIcon.visible = + meta.resultDisplay.hasMoreResults() && + provider.canLaunchSearch; + provider.getResultMetas(results, Lang.bind(this, function(metas) { this._clearDisplayForProvider(provider); meta.actor.show(); @@ -395,3 +416,35 @@ const SearchResults = new Lang.Class({ } } }); + +const ProviderIcon = new Lang.Class({ + Name: 'ProviderIcon', + Extends: St.Button, + + PROVIDER_ICON_SIZE: 48, + + _init: function(provider) { + this.provider = provider; + this.parent({ style_class: 'search-provider-icon', + reactive: true, + can_focus: true, + track_hover: true }); + + this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() }); + this.set_child(this._content); + + let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL); + + this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more', + visible: false, + x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END, + y_align: Clutter.ActorAlign.END, + x_expand: true, + y_expand: true }); + + let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE, + gicon: provider.appInfo.get_icon() }); + this._content.add_actor(icon); + this._content.add_actor(this.moreIcon); + } +}); diff --git a/js/ui/wanda.js b/js/ui/wanda.js index 305bf9baa..846098b04 100644 --- a/js/ui/wanda.js +++ b/js/ui/wanda.js @@ -136,7 +136,8 @@ const WandaSearchProvider = new Lang.Class({ Extends: Search.SearchProvider, _init: function() { - this.parent(_("Your favorite Easter Egg")); + this.parent(); + this.id = 'wanda'; }, getResultMetas: function(fish, callback) {