[gnome-shell] Merge searchDisplay.js and search.js
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Merge searchDisplay.js and search.js
- Date: Tue, 29 Oct 2013 20:03:51 +0000 (UTC)
commit dd44219aa5b9da0411b539057eef44e273133649
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Tue Oct 29 15:49:05 2013 -0400
Merge searchDisplay.js and search.js
search.js used to do a lot more, but now that most of the
functionality has been moved to the remote search system,
it doesn't do a lot. Merge searchDisplay.js into it.
js/Makefile.am | 1 -
js/ui/search.js | 563 +++++++++++++++++++++++++++++++++++++++++++++++
js/ui/searchDisplay.js | 567 ------------------------------------------------
js/ui/viewSelector.js | 3 +-
po/POTFILES.in | 2 +-
5 files changed, 565 insertions(+), 571 deletions(-)
---
diff --git a/js/Makefile.am b/js/Makefile.am
index 4fdbae8..677af78 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -90,7 +90,6 @@ nobase_dist_js_DATA = \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \
- ui/searchDisplay.js \
ui/shellDBus.js \
ui/status/accessibility.js \
ui/status/brightness.js \
diff --git a/js/ui/search.js b/js/ui/search.js
index 3648fa1..1ee9471 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -1,10 +1,26 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
+const Gtk = imports.gi.Gtk;
+const Meta = imports.gi.Meta;
const Signals = imports.signals;
+const St = imports.gi.St;
+const Atk = imports.gi.Atk;
+
+const DND = imports.ui.dnd;
+const IconGrid = imports.ui.iconGrid;
+const Main = imports.ui.main;
+const Overview = imports.ui.overview;
+const Separator = imports.ui.separator;
+const Search = imports.ui.search;
+const Util = imports.misc.util;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
+const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
+const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
+
const SearchSystem = new Lang.Class({
Name: 'SearchSystem',
@@ -95,3 +111,550 @@ const SearchSystem = new Lang.Class({
}
});
Signals.addSignalMethods(SearchSystem.prototype);
+
+const MaxWidthBin = new Lang.Class({
+ Name: 'MaxWidthBin',
+ Extends: St.Bin,
+
+ vfunc_allocate: function(box, flags) {
+ let themeNode = this.get_theme_node();
+ let maxWidth = themeNode.get_max_width();
+ let availWidth = box.x2 - box.x1;
+ let adjustedBox = box;
+
+ if (availWidth > maxWidth) {
+ let excessWidth = availWidth - maxWidth;
+ adjustedBox.x1 += Math.floor(excessWidth / 2);
+ adjustedBox.x2 -= Math.floor(excessWidth / 2);
+ }
+
+ this.parent(adjustedBox, flags);
+ }
+});
+
+const SearchResult = new Lang.Class({
+ Name: 'SearchResult',
+
+ _init: function(provider, metaInfo, terms) {
+ this.provider = provider;
+ this.metaInfo = metaInfo;
+ this.terms = terms;
+
+ this.actor = new St.Button({ reactive: true,
+ can_focus: true,
+ track_hover: true,
+ x_align: St.Align.START,
+ y_fill: true });
+
+ this.actor._delegate = this;
+ this.actor.connect('clicked', Lang.bind(this, this.activate));
+ },
+
+ activate: function() {
+ this.provider.activateResult(this.metaInfo.id, this.terms);
+ Main.overview.toggle();
+ },
+
+ setSelected: function(selected) {
+ if (selected)
+ this.actor.add_style_pseudo_class('selected');
+ else
+ this.actor.remove_style_pseudo_class('selected');
+ }
+});
+
+const ListSearchResult = new Lang.Class({
+ Name: 'ListSearchResult',
+ Extends: SearchResult,
+
+ ICON_SIZE: 64,
+
+ _init: function(provider, metaInfo, terms) {
+ this.parent(provider, metaInfo, terms);
+
+ this.actor.style_class = 'list-search-result';
+ this.actor.x_fill = true;
+
+ let content = new St.BoxLayout({ style_class: 'list-search-result-content',
+ vertical: false });
+ this.actor.set_child(content);
+
+ // An icon for, or thumbnail of, content
+ let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
+ if (icon) {
+ content.add(icon);
+ }
+
+ let details = new St.BoxLayout({ vertical: true });
+ content.add(details, { x_fill: true,
+ y_fill: false,
+ x_align: St.Align.START,
+ y_align: St.Align.MIDDLE });
+
+ let title = new St.Label({ style_class: 'list-search-result-title',
+ text: this.metaInfo['name'] })
+ details.add(title, { x_fill: false,
+ y_fill: false,
+ x_align: St.Align.START,
+ y_align: St.Align.START });
+ this.actor.label_actor = title;
+
+ if (this.metaInfo['description']) {
+ let description = new St.Label({ style_class: 'list-search-result-description' });
+ description.clutter_text.set_markup(this.metaInfo['description']);
+ details.add(description, { x_fill: false,
+ y_fill: false,
+ x_align: St.Align.START,
+ y_align: St.Align.END });
+ }
+ }
+});
+
+const GridSearchResult = new Lang.Class({
+ Name: 'GridSearchResult',
+ Extends: SearchResult,
+
+ _init: function(provider, metaInfo, terms) {
+ this.parent(provider, metaInfo, terms);
+
+ this.actor.style_class = 'grid-search-result';
+
+ let content = provider.createResultObject(metaInfo, terms);
+ let dragSource = null;
+
+ if (content == null) {
+ let actor = new St.Bin();
+ let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
+ { createIcon: this.metaInfo['createIcon'] });
+ actor.set_child(icon.actor);
+ actor.label_actor = icon.label;
+ dragSource = icon.icon;
+ content = { actor: actor, icon: icon };
+ } else {
+ if (content._delegate && content._delegate.getDragActorSource)
+ dragSource = content._delegate.getDragActorSource();
+ }
+
+ this.actor.set_child(content.actor);
+ this.actor.label_actor = content.actor.label_actor;
+ this.icon = content.icon;
+
+ let draggable = DND.makeDraggable(this.actor);
+ draggable.connect('drag-begin',
+ Lang.bind(this, function() {
+ Main.overview.beginItemDrag(this);
+ }));
+ draggable.connect('drag-cancelled',
+ Lang.bind(this, function() {
+ Main.overview.cancelledItemDrag(this);
+ }));
+ draggable.connect('drag-end',
+ Lang.bind(this, function() {
+ Main.overview.endItemDrag(this);
+ }));
+
+ if (!dragSource)
+ // not exactly right, but alignment problems are hard to notice
+ dragSource = content;
+ this._dragActorSource = dragSource;
+ },
+
+ getDragActorSource: function() {
+ return this._dragActorSource;
+ },
+
+ getDragActor: function() {
+ return this.metaInfo['createIcon'](Main.overview.dashIconSize);
+ },
+
+ shellWorkspaceLaunch: function(params) {
+ if (this.provider.dragActivateResult)
+ this.provider.dragActivateResult(this.metaInfo.id, params);
+ else
+ this.provider.activateResult(this.metaInfo.id, this.terms);
+ }
+});
+
+const SearchResultsBase = new Lang.Class({
+ Name: 'SearchResultsBase',
+
+ _init: function(provider) {
+ this.provider = provider;
+
+ this._terms = [];
+
+ this.actor = new St.BoxLayout({ style_class: 'search-section',
+ vertical: true });
+
+ this._resultDisplayBin = new St.Bin({ x_fill: true,
+ y_fill: true });
+ this.actor.add(this._resultDisplayBin, { expand: true });
+
+ let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
+ this.actor.add(separator.actor);
+ },
+
+ destroy: function() {
+ this.actor.destroy();
+ this._terms = [];
+ },
+
+ _clearResultDisplay: function() {
+ },
+
+ clear: function() {
+ this._clearResultDisplay();
+ this.actor.hide();
+ },
+
+ _keyFocusIn: function(actor) {
+ this.emit('key-focus-in', actor);
+ },
+
+ _setMoreIconVisible: function(visible) {
+ },
+
+ updateSearch: function(providerResults, terms, callback) {
+ this._terms = terms;
+
+ if (providerResults.length == 0) {
+ this._clearResultDisplay();
+ this.actor.hide();
+ callback();
+ } else {
+ let maxResults = this._getMaxDisplayedResults();
+ let results = this.provider.filterResults(providerResults, maxResults);
+ let hasMoreResults = results.length < providerResults.length;
+
+ this.provider.getResultMetas(results, Lang.bind(this, function(metas) {
+ this.clear();
+
+ // 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);
+ this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
+ this.actor.show();
+ callback();
+ }));
+ }
+ }
+});
+
+const ListSearchResults = new Lang.Class({
+ Name: 'ListSearchResults',
+ Extends: SearchResultsBase,
+
+ _init: function(provider) {
+ this.parent(provider);
+
+ this._container = new St.BoxLayout({ style_class: 'search-section-content' });
+ this.providerIcon = new ProviderIcon(provider);
+ this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
+ this.providerIcon.connect('clicked', Lang.bind(this,
+ function() {
+ provider.launchSearch(this._terms);
+ Main.overview.toggle();
+ }));
+
+ this._container.add(this.providerIcon, { x_fill: false,
+ y_fill: false,
+ x_align: St.Align.START,
+ y_align: St.Align.START });
+
+ this._content = new St.BoxLayout({ style_class: 'list-search-results',
+ vertical: true });
+ this._container.add(this._content, { expand: true });
+
+ this._resultDisplayBin.set_child(this._container);
+ },
+
+ _setMoreIconVisible: function(visible) {
+ this.providerIcon.moreIcon.visible = true;
+ },
+
+ _getMaxDisplayedResults: function() {
+ 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], this._terms);
+ display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
+ this._content.add_actor(display.actor);
+ }
+ },
+
+ _clearResultDisplay: function () {
+ this._content.destroy_all_children();
+ },
+
+ getFirstResult: function() {
+ if (this._content.get_n_children() > 0)
+ return this._content.get_child_at_index(0)._delegate;
+ else
+ return null;
+ }
+});
+Signals.addSignalMethods(ListSearchResults.prototype);
+
+const GridSearchResults = new Lang.Class({
+ Name: 'GridSearchResults',
+ Extends: SearchResultsBase,
+
+ _init: function(provider) {
+ this.parent(provider);
+
+ this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
+ xAlign: St.Align.START });
+ this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
+ this._bin.set_child(this._grid.actor);
+
+ this._resultDisplayBin.set_child(this._bin);
+ },
+
+ _getMaxDisplayedResults: function() {
+ return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
+ },
+
+ _renderResults: function(metas) {
+ for (let i = 0; i < metas.length; i++) {
+ let display = new GridSearchResult(this.provider, metas[i], this._terms);
+ display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
+ this._grid.addItem(display);
+ }
+ },
+
+ _clearResultDisplay: function () {
+ this._grid.removeAll();
+ },
+
+ getFirstResult: function() {
+ if (this._grid.visibleItemsCount() > 0)
+ return this._grid.getItemAtIndex(0)._delegate;
+ else
+ return null;
+ }
+});
+Signals.addSignalMethods(GridSearchResults.prototype);
+
+const SearchResults = new Lang.Class({
+ Name: 'SearchResults',
+
+ _init: function(searchSystem) {
+ this._searchSystem = searchSystem;
+ this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
+
+ this.actor = new St.BoxLayout({ name: 'searchResults',
+ vertical: true });
+
+ this._content = new St.BoxLayout({ name: 'searchResultsContent',
+ vertical: true });
+ this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
+ x_fill: true,
+ y_fill: true,
+ child: this._content });
+
+ let scrollChild = new St.BoxLayout();
+ scrollChild.add(this._contentBin, { expand: true });
+
+ this._scrollView = new St.ScrollView({ x_fill: true,
+ y_fill: false,
+ overlay_scrollbars: true,
+ style_class: 'search-display vfade' });
+ this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+ this._scrollView.add_actor(scrollChild);
+ let action = new Clutter.PanAction({ interpolate: true });
+ action.connect('pan', Lang.bind(this, this._onPan));
+ this._scrollView.add_action(action);
+
+ this.actor.add(this._scrollView, { x_fill: true,
+ y_fill: true,
+ expand: true,
+ x_align: St.Align.START,
+ y_align: St.Align.START });
+
+ this._statusText = new St.Label({ style_class: 'search-statustext' });
+ this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
+ y_align: St.Align.MIDDLE });
+ this._content.add(this._statusBin, { expand: true });
+ this._statusBin.add_actor(this._statusText);
+ this._providers = this._searchSystem.getProviders();
+ this._providerDisplays = {};
+ for (let i = 0; i < this._providers.length; i++) {
+ this.createProviderDisplay(this._providers[i]);
+ }
+
+ this._highlightDefault = false;
+ this._defaultResult = null;
+ },
+
+ _onPan: function(action) {
+ let [dist, dx, dy] = action.get_motion_delta(0);
+ let adjustment = this._scrollView.vscroll.adjustment;
+ adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
+ return false;
+ },
+
+ _keyFocusIn: function(provider, actor) {
+ Util.ensureActorVisibleInScrollView(this._scrollView, actor);
+ },
+
+ createProviderDisplay: function(provider) {
+ let providerDisplay = null;
+
+ if (provider.appInfo) {
+ providerDisplay = new ListSearchResults(provider);
+ } else {
+ providerDisplay = new GridSearchResults(provider);
+ }
+
+ providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
+ this._providerDisplays[provider.id] = providerDisplay;
+ this._content.add(providerDisplay.actor);
+ },
+
+ destroyProviderDisplay: function(provider) {
+ this._providerDisplays[provider.id].destroy();
+ delete this._providerDisplays[provider.id];
+ },
+
+ _clearDisplay: function() {
+ for (let i = 0; i < this._providers.length; i++) {
+ let provider = this._providers[i];
+ let providerDisplay = this._providerDisplays[provider.id];
+ providerDisplay.clear();
+ }
+ },
+
+ reset: function() {
+ this._searchSystem.reset();
+ this._statusBin.hide();
+ this._clearDisplay();
+ this._defaultResult = null;
+ },
+
+ startingSearch: function() {
+ this.reset();
+ this._statusText.set_text(_("Searching…"));
+ this._statusBin.show();
+ },
+
+ _maybeSetInitialSelection: function() {
+ let newDefaultResult = null;
+
+ for (let i = 0; i < this._providers.length; i++) {
+ let provider = this._providers[i];
+ let display = this._providerDisplays[provider.id];
+
+ if (!display.actor.visible)
+ continue;
+
+ let firstResult = display.getFirstResult();
+ if (firstResult) {
+ newDefaultResult = firstResult;
+ break; // select this one!
+ }
+ }
+
+ if (newDefaultResult != this._defaultResult) {
+ if (this._defaultResult)
+ this._defaultResult.setSelected(false);
+ if (newDefaultResult)
+ newDefaultResult.setSelected(this._highlightDefault);
+
+ this._defaultResult = newDefaultResult;
+ }
+ },
+
+ _updateStatusText: function () {
+ let haveResults = false;
+
+ for (let i = 0; i < this._providers.length; i++) {
+ let provider = this._providers[i];
+ let display = this._providerDisplays[provider.id];
+ if (display.getFirstResult()) {
+ haveResults = true;
+ break;
+ }
+ }
+
+ if (!haveResults) {
+ this._statusText.set_text(_("No results."));
+ this._statusBin.show();
+ } else {
+ this._statusBin.hide();
+ }
+ },
+
+ _updateResults: function(searchSystem, results) {
+ let terms = searchSystem.getTerms();
+ let [provider, providerResults] = results;
+ let display = this._providerDisplays[provider.id];
+
+ display.updateSearch(providerResults, terms, Lang.bind(this, function() {
+ this._maybeSetInitialSelection();
+ this._updateStatusText();
+ }));
+ },
+
+ activateDefault: function() {
+ if (this._defaultResult)
+ this._defaultResult.activate();
+ },
+
+ highlightDefault: function(highlight) {
+ this._highlightDefault = highlight;
+ if (this._defaultResult)
+ this._defaultResult.setSelected(highlight);
+ },
+
+ navigateFocus: function(direction) {
+ let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
+ if (direction == Gtk.DirectionType.TAB_BACKWARD ||
+ direction == (rtl ? Gtk.DirectionType.RIGHT
+ : Gtk.DirectionType.LEFT) ||
+ direction == Gtk.DirectionType.UP) {
+ this.actor.navigate_focus(null, direction, false);
+ return;
+ }
+
+ let from = this._defaultResult ? this._defaultResult.actor : null;
+ this.actor.navigate_focus(from, direction, false);
+ }
+});
+
+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,
+ accessible_name: provider.appInfo.get_name(),
+ 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/viewSelector.js b/js/ui/viewSelector.js
index 9e86288..3c9cf21 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -16,7 +16,6 @@ const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const RemoteSearch = imports.ui.remoteSearch;
const Search = imports.ui.search;
-const SearchDisplay = imports.ui.searchDisplay;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const WorkspacesView = imports.ui.workspacesView;
@@ -102,7 +101,7 @@ const ViewSelector = new Lang.Class({
this._appsPage = this._addPage(this.appDisplay.actor,
_("Applications"), 'view-grid-symbolic');
- this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
+ this._searchResults = new Search.SearchResults(this._searchSystem);
this._searchPage = this._addPage(this._searchResults.actor,
_("Search"), 'edit-find-symbolic',
{ a11yFocus: this._entry });
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6ec28e7..3113662 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -38,7 +38,7 @@ js/ui/panel.js
js/ui/popupMenu.js
js/ui/runDialog.js
js/ui/screenShield.js
-js/ui/searchDisplay.js
+js/ui/search.js
js/ui/shellEntry.js
js/ui/shellMountOperation.js
js/ui/status/accessibility.js
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]