cleanup: Use inheritance for Actor classes instead of composition

Remove the `this.actor = ...` and `this.actor._delegate = this` patterns in most
of classes, by inheriting all the actor container classes.

Uses interfaces when needed for making sure that multiple classes will implement
some required methods or to avoid redefining the same code multiple times.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
This commit is contained in:
Marco Trevisan (Treviño)
2019-07-16 11:24:13 +02:00
committed by Florian Müllner
parent f67b409fc1
commit c4c5c4fd5c
58 changed files with 2000 additions and 1757 deletions

View File

@ -2,7 +2,6 @@
/* exported SearchResultsView */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
const IconGrid = imports.ui.iconGrid;
@ -33,20 +32,22 @@ class MaxWidthBox extends St.BoxLayout {
}
});
var SearchResult = class {
constructor(provider, metaInfo, resultsView) {
var SearchResult = GObject.registerClass(
class SearchResult extends St.Button {
_init(provider, metaInfo, resultsView) {
this.provider = provider;
this.metaInfo = metaInfo;
this._resultsView = resultsView;
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true });
super._init({
reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true
});
this.actor._delegate = this;
this.actor.connect('clicked', this.activate.bind(this));
this.connect('clicked', this.activate.bind(this));
}
activate() {
@ -57,20 +58,19 @@ var SearchResult = class {
St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
Main.overview.toggle();
}
};
Signals.addSignalMethods(SearchResult.prototype);
});
var ListSearchResult = class extends SearchResult {
var ListSearchResult = GObject.registerClass(
class ListSearchResult extends SearchResult {
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
constructor(provider, metaInfo, resultsView) {
super(provider, metaInfo, resultsView);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
this.style_class = 'list-search-result';
this.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
this.set_child(content);
this._termsChangedId = 0;
@ -93,7 +93,7 @@ var ListSearchResult = class extends SearchResult {
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this.actor.label_actor = title;
this.label_actor = title;
if (this.metaInfo['description']) {
this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' });
@ -109,7 +109,7 @@ var ListSearchResult = class extends SearchResult {
this._highlightTerms();
}
this.actor.connect('destroy', this._onDestroy.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
get ICON_SIZE() {
@ -126,49 +126,53 @@ var ListSearchResult = class extends SearchResult {
this._resultsView.disconnect(this._termsChangedId);
this._termsChangedId = 0;
}
};
});
var GridSearchResult = class extends SearchResult {
constructor(provider, metaInfo, resultsView) {
super(provider, metaInfo, resultsView);
var GridSearchResult = GObject.registerClass(
class GridSearchResult extends SearchResult {
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
this.actor.style_class = 'grid-search-result';
this.style_class = 'grid-search-result';
this.icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
let content = new St.Bin({ child: this.icon });
this.actor.set_child(content);
this.actor.label_actor = this.icon.label;
this.set_child(content);
this.label_actor = this.icon.label;
}
};
});
var SearchResultsBase = GObject.registerClass({
GTypeFlags: GObject.TypeFlags.ABSTRACT,
Properties: {
'focus-child': GObject.ParamSpec.object(
'focus-child', 'focus-child', 'focus-child',
GObject.ParamFlags.READABLE,
Clutter.Actor.$gtype),
}
}, class SearchResultsBase extends St.BoxLayout {
_init(provider, resultsView) {
super._init({ style_class: 'search-section', vertical: true });
var SearchResultsBase = class {
constructor(provider, resultsView) {
this.provider = provider;
this._resultsView = resultsView;
this._terms = [];
this._focusChild = null;
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 });
this.add(this._resultDisplayBin, { expand: true });
let separator = new St.Widget({ style_class: 'search-section-separator' });
this.actor.add(separator);
this.add(separator);
this._resultDisplays = {};
this._cancellable = new Gio.Cancellable();
this.actor.connect('destroy', this._onDestroy.bind(this));
}
destroy() {
this.actor.destroy();
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
@ -185,10 +189,10 @@ var SearchResultsBase = class {
clear() {
this._cancellable.cancel();
for (let resultId in this._resultDisplays)
this._resultDisplays[resultId].actor.destroy();
this._resultDisplays[resultId].destroy();
this._resultDisplays = {};
this._clearResultDisplay();
this.actor.hide();
this.hide();
}
get focusChild() {
@ -199,7 +203,7 @@ var SearchResultsBase = class {
if (this._focusChild == actor)
return;
this._focusChild = actor;
this.emit('focus-child-changed');
this.notify('focus-child');
}
_setMoreCount(_count) {
@ -238,7 +242,7 @@ var SearchResultsBase = class {
metasNeeded.forEach((resultId, i) => {
let meta = metas[i];
let display = this._createResultDisplay(meta);
display.actor.connect('key-focus-in', this._keyFocusIn.bind(this));
display.connect('key-focus-in', this._keyFocusIn.bind(this));
this._resultDisplays[resultId] = display;
});
callback(true);
@ -250,7 +254,7 @@ var SearchResultsBase = class {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
this.hide();
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
@ -269,22 +273,23 @@ var SearchResultsBase = class {
// 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.hide();
this._clearResultDisplay();
results.forEach(resultId => {
this._addItem(this._resultDisplays[resultId]);
});
this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0);
this.actor.show();
this.show();
callback();
});
}
}
};
});
var ListSearchResults = class extends SearchResultsBase {
constructor(provider, resultsView) {
super(provider, resultsView);
var ListSearchResults = GObject.registerClass(
class ListSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerInfo = new ProviderInfo(provider);
@ -325,21 +330,21 @@ var ListSearchResults = class extends SearchResultsBase {
}
_addItem(display) {
this._content.add_actor(display.actor);
this._content.add_actor(display);
}
getFirstResult() {
if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0)._delegate;
return this._content.get_child_at_index(0);
else
return null;
}
};
Signals.addSignalMethods(ListSearchResults.prototype);
});
var GridSearchResults = class extends SearchResultsBase {
constructor(provider, resultsView) {
super(provider, resultsView);
var GridSearchResults = GObject.registerClass(
class GridSearchResults extends SearchResultsBase {
_init(provider, resultsView) {
super._init(provider, resultsView);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
@ -361,7 +366,7 @@ var GridSearchResults = class extends SearchResultsBase {
updateSearch(...args) {
if (this._notifyAllocationId)
this.actor.disconnect(this._notifyAllocationId);
this.disconnect(this._notifyAllocationId);
if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater;
@ -369,7 +374,7 @@ var GridSearchResults = class extends SearchResultsBase {
// Make sure the maximum number of results calculated by
// _getMaxDisplayedResults() is updated after width changes.
this._notifyAllocationId = this.actor.connect('notify::allocation', () => {
this._notifyAllocationId = this.connect('notify::allocation', () => {
if (this._updateSearchLater)
return;
this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
@ -383,7 +388,7 @@ var GridSearchResults = class extends SearchResultsBase {
}
_getMaxDisplayedResults() {
let width = this.actor.allocation.x2 - this.actor.allocation.x1;
let width = this.allocation.get_width();
if (width == 0)
return -1;
@ -406,17 +411,17 @@ var GridSearchResults = class extends SearchResultsBase {
getFirstResult() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0)._delegate;
return this._grid.getItemAtIndex(0);
else
return null;
}
};
Signals.addSignalMethods(GridSearchResults.prototype);
});
var SearchResultsView = class {
constructor() {
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
var SearchResultsView = GObject.registerClass({
Signals: { 'terms-changed': {} }
}, class SearchResultsView extends St.BoxLayout {
_init() {
super._init({ name: 'searchResults', vertical: true });
this._content = new MaxWidthBox({ name: 'searchResultsContent',
vertical: true });
@ -432,16 +437,18 @@ var SearchResultsView = class {
action.connect('pan', this._onPan.bind(this));
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.add(this._scrollView, {
x_fill: true,
y_fill: true,
expand: true,
x_align: St.Align.START,
y_align: St.Align.STAR
});
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.actor.add(this._statusBin, { expand: true });
this.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._highlightDefault = false;
@ -599,7 +606,7 @@ var SearchResultsView = class {
_onPan(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;
adjustment.value -= (dy / this.height) * adjustment.page_size;
return false;
}
@ -617,9 +624,9 @@ var SearchResultsView = class {
else
providerDisplay = new GridSearchResults(provider, this);
providerDisplay.connect('focus-child-changed', this._focusChildChanged.bind(this));
providerDisplay.actor.hide();
this._content.add(providerDisplay.actor);
providerDisplay.connect('notify::focus-child', this._focusChildChanged.bind(this));
providerDisplay.hide();
this._content.add(providerDisplay);
provider.display = providerDisplay;
}
@ -637,7 +644,7 @@ var SearchResultsView = class {
let provider = providers[i];
let display = provider.display;
if (!display.actor.visible)
if (!display.visible)
continue;
let firstResult = display.getFirstResult();
@ -712,22 +719,22 @@ var SearchResultsView = class {
this._doSearch();
if (this._defaultResult)
this._defaultResult.actor.popup_menu();
this._defaultResult.popup_menu();
}
navigateFocus(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
let rtl = this.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == St.DirectionType.TAB_BACKWARD ||
direction == (rtl
? St.DirectionType.RIGHT
: St.DirectionType.LEFT) ||
direction == St.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false);
this.navigate_focus(null, direction, false);
return;
}
let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false);
let from = this._defaultResult ? this._defaultResult : null;
this.navigate_focus(from, direction, false);
}
_setSelected(result, selected) {
@ -735,10 +742,10 @@ var SearchResultsView = class {
return;
if (selected) {
result.actor.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result.actor);
result.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result);
} else {
result.actor.remove_style_pseudo_class('selected');
result.remove_style_pseudo_class('selected');
}
}
@ -751,8 +758,7 @@ var SearchResultsView = class {
return description.replace(this._highlightRegex, '<b>$1</b>');
}
};
Signals.addSignalMethods(SearchResultsView.prototype);
});
var ProviderInfo = GObject.registerClass(
class ProviderInfo extends St.Button {