[gnome-shell/gbsneto/remove-generic-container: 10/28] iconGrid: Stop using Shell.GenericContainer
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/gbsneto/remove-generic-container: 10/28] iconGrid: Stop using Shell.GenericContainer
- Date: Fri, 5 Oct 2018 22:28:12 +0000 (UTC)
commit 5f805d10153be170c479026c35b0cf4df5582ee0
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Mon Jul 2 11:03:07 2018 -0300
iconGrid: Stop using Shell.GenericContainer
Removing Shell.GenericContainer from the IconGrid class was
challenging because it needs the "skip paint" API from it.
This API was added, too, as a workaround to the inability
to override vfuncs from GJS.
The overrides are largely copy-pasted and translated versions
of the Shell.GenericContainer code.
The IconGrid:key-focus-in signal was renamed to :child-focused
to avoid clashing with ClutterActor:key-focus-in.
In GridSearchResults, the internal IconGrid had it's y_expand
set to false, so it doesn't push other search elements (the
list results mainly) to the bottom of the screen.
Because skip paint wasn't and still isn't a GObject property,
rename it to _skipPaint to reflect that.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/153
js/ui/appDisplay.js | 28 ++++-----
js/ui/iconGrid.js | 168 +++++++++++++++++++++++++++++++++++++---------------
js/ui/search.js | 3 +-
3 files changed, 137 insertions(+), 62 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 9d648c92e..6f67127c4 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -130,7 +130,7 @@ var BaseAppView = new Lang.Class({
this._childFocused(actor);
});
// Standard hack for ClutterBinLayout
- this._grid.actor.x_expand = true;
+ this._grid.x_expand = true;
this._items = {};
this._allItems = [];
@@ -203,7 +203,7 @@ var BaseAppView = new Lang.Class({
},
_doSpringAnimation(animationDirection) {
- this._grid.actor.opacity = 255;
+ this._grid.opacity = 255;
this._grid.animateSpring(animationDirection,
Main.overview.getShowAppsButton());
},
@@ -217,8 +217,8 @@ var BaseAppView = new Lang.Class({
}
if (animationDirection == IconGrid.AnimationDirection.IN) {
- let id = this._grid.actor.connect('paint', () => {
- this._grid.actor.disconnect(id);
+ let id = this._grid.connect('paint', () => {
+ this._grid.disconnect(id);
this._doSpringAnimation(animationDirection);
});
} else {
@@ -228,7 +228,7 @@ var BaseAppView = new Lang.Class({
animateSwitch(animationDirection) {
Tweener.removeTweens(this.actor);
- Tweener.removeTweens(this._grid.actor);
+ Tweener.removeTweens(this._grid);
let params = { time: VIEWS_SWITCH_TIME,
transition: 'easeOutQuad' };
@@ -242,7 +242,7 @@ var BaseAppView = new Lang.Class({
params.onComplete = () => { this.actor.hide(); };
}
- Tweener.addTween(this._grid.actor, params);
+ Tweener.addTween(this._grid, params);
}
});
Signals.addSignalMethods(BaseAppView.prototype);
@@ -396,7 +396,7 @@ var AllView = new Lang.Class({
let box = new St.BoxLayout({ vertical: true });
this._grid.currentPage = 0;
- this._stack.add_actor(this._grid.actor);
+ this._stack.add_actor(this._grid);
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
this._stack.add_actor(this._eventBlocker);
@@ -745,7 +745,7 @@ var AllView = new Lang.Class({
box.y2 = height;
box = this.actor.get_theme_node().get_content_box(box);
box = this._scrollView.get_theme_node().get_content_box(box);
- box = this._grid.actor.get_theme_node().get_content_box(box);
+ box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let oldNPages = this._grid.nPages();
@@ -794,9 +794,9 @@ var FrequentView = new Lang.Class({
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
- this._grid.actor.y_expand = true;
+ this._grid.y_expand = true;
- this.actor.add_actor(this._grid.actor);
+ this.actor.add_actor(this._grid);
this.actor.add_actor(this._noFrequentAppsLabel);
this._noFrequentAppsLabel.hide();
@@ -843,7 +843,7 @@ var FrequentView = new Lang.Class({
box.x2 = width;
box.y2 = height;
box = this.actor.get_theme_node().get_content_box(box);
- box = this._grid.actor.get_theme_node().get_content_box(box);
+ box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this._grid.adaptToSize(availWidth, availHeight);
@@ -1141,12 +1141,12 @@ var FolderView = new Lang.Class({
this.parent(null, null);
// If it not expand, the parent doesn't take into account its preferred_width when allocating
// the second time it allocates, so we apply the "Standard hack for ClutterBinLayout"
- this._grid.actor.x_expand = true;
+ this._grid.x_expand = true;
this.actor = new St.ScrollView({ overlay_scrollbars: true });
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
let scrollableContainer = new St.BoxLayout({ vertical: true, reactive: true });
- scrollableContainer.add_actor(this._grid.actor);
+ scrollableContainer.add_actor(this._grid);
this.actor.add_actor(scrollableContainer);
let action = new Clutter.PanAction({ interpolate: true });
@@ -1369,7 +1369,7 @@ var FolderIcon = new Lang.Class({
_updatePopupSize() {
// StWidget delays style calculation until needed, make sure we use the correct values
- this.view._grid.actor.ensure_style();
+ this.view._grid.ensure_style();
let offsetForEachSide = Math.ceil((this._popup.getOffset(St.Side.TOP) +
this._popup.getOffset(St.Side.BOTTOM) -
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index a0d008386..cbfeb05f4 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -189,8 +189,16 @@ function zoomOutActor(actor) {
var IconGrid = new Lang.Class({
Name: 'IconGrid',
+ Extends: St.Widget,
+ Signals: {'animation-done': {},
+ 'child-focused': { param_types: [Clutter.Actor.$gtype]} },
_init(params) {
+ this.parent({ style_class: 'icon-grid',
+ y_align: Clutter.ActorAlign.START });
+
+ this.actor = this;
+
params = Params.parse(params, { rowLimit: null,
columnLimit: null,
minRows: 1,
@@ -211,30 +219,23 @@ var IconGrid = new Lang.Class({
this.rightPadding = 0;
this.leftPadding = 0;
- this.actor = new St.BoxLayout({ style_class: 'icon-grid',
- vertical: true });
this._items = [];
this._clonesAnimating = [];
// Pulled from CSS, but hardcode some defaults here
this._spacing = 0;
this._hItemSize = this._vItemSize = ICON_SIZE;
this._fixedHItemSize = this._fixedVItemSize = undefined;
- this._grid = new Shell.GenericContainer();
- this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
- this.actor.connect('style-changed', this._onStyleChanged.bind(this));
+ this.connect('style-changed', this._onStyleChanged.bind(this));
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
- this.actor.connect('notify::mapped', () => {
- if (!this.actor.mapped)
+ this.connect('notify::mapped', () => {
+ if (!this.mapped)
this._cancelAnimation();
});
- this._grid.connect('get-preferred-width', this._getPreferredWidth.bind(this));
- this._grid.connect('get-preferred-height', this._getPreferredHeight.bind(this));
- this._grid.connect('allocate', this._allocate.bind(this));
- this._grid.connect('actor-added', this._childAdded.bind(this));
- this._grid.connect('actor-removed', this._childRemoved.bind(this));
+ this.connect('actor-added', this._childAdded.bind(this));
+ this.connect('actor-removed', this._childRemoved.bind(this));
},
_keyFocusIn(actor) {
@@ -249,13 +250,13 @@ var IconGrid = new Lang.Class({
child.disconnect(child._iconGridKeyFocusInId);
},
- _getPreferredWidth(grid, forHeight, alloc) {
+ vfunc_get_preferred_width(forHeight) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
- return;
+ return [0, 0];
- let nChildren = this._grid.get_n_children();
+ let nChildren = this.get_n_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
: nChildren;
@@ -263,22 +264,28 @@ var IconGrid = new Lang.Class({
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
// need higher level design
- alloc.min_size = this._getHItemSize() + this.leftPadding + this.rightPadding;
- alloc.natural_size = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding +
this.rightPadding;
+ let minSize = this._getHItemSize() + this.leftPadding + this.rightPadding;
+ let natSize = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
+
+ return this.get_theme_node().adjust_preferred_width(minSize, natSize);
},
_getVisibleChildren() {
- return this._grid.get_children().filter(actor => actor.visible);
+ return this.get_children().filter(actor => actor.visible);
},
- _getPreferredHeight(grid, forWidth, alloc) {
+ vfunc_get_preferred_height(forWidth) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
- return;
+ return [0, 0];
+ let themeNode = this.get_theme_node();
let children = this._getVisibleChildren();
let nColumns;
+
+ forWidth = themeNode.adjust_for_width(forWidth);
+
if (forWidth < 0)
nColumns = children.length;
else
@@ -293,16 +300,21 @@ var IconGrid = new Lang.Class({
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
- alloc.min_size = height;
- alloc.natural_size = height;
+
+ return themeNode.adjust_preferred_height(height, height);
},
- _allocate(grid, box, flags) {
+ vfunc_allocate(box, flags) {
+ this.set_allocation(box, flags);
+
+ let themeNode = this.get_theme_node();
+ box = themeNode.get_content_box(box);
+
if (this._fillParent) {
// Reset the passed in box to fill the parent
- let parentBox = this.actor.get_parent().allocation;
- let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
- box = this._grid.get_theme_node().get_content_box(gridBox);
+ let parentBox = this.get_parent().allocation;
+ let gridBox = themeNode.get_content_box(parentBox);
+ box = themeNode.get_content_box(gridBox);
}
let children = this._getVisibleChildren();
@@ -332,10 +344,10 @@ var IconGrid = new Lang.Class({
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
- this._grid.set_skip_paint(children[i], true);
+ children[i]._skipPaint = true;
} else {
children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
+ children[i]._skipPaint = false;
}
columnIndex++;
@@ -353,6 +365,66 @@ var IconGrid = new Lang.Class({
}
},
+ vfunc_paint() {
+ this.paint_background();
+
+ this.get_children().forEach(c => {
+ if (!c._skipPaint)
+ c.paint();
+ });
+ },
+
+ vfunc_pick(color) {
+ this.parent(color);
+
+ this.get_children().forEach(c => {
+ if (!c._skipPaint)
+ c.paint();
+ });
+ },
+
+ vfunc_get_paint_volume(paintVolume) {
+ // Setting the paint volume does not make sense when we don't have
+ // any allocation
+ if (!this.has_allocation())
+ return false;
+
+ let themeNode = this.get_theme_node();
+ let allocationBox = this.get_allocation_box();
+ let paintBox = themeNode.get_paint_box(allocationBox);
+
+ let origin = new Clutter.Vertex();
+ origin.x = paintBox.x1 - allocationBox.x1;
+ origin.y = paintBox.y1 - allocationBox.y1;
+ origin.z = 0.0;
+
+ paintVolume.set_origin(origin);
+ paintVolume.set_width(paintBox.x2 - paintBox.x1);
+ paintVolume.set_height(paintBox.y2 - paintBox.y1);
+
+ if (this.get_clip_to_allocation())
+ return true;
+
+ for (let child = this.get_first_child();
+ child != null;
+ child = child.get_next_sibling()) {
+
+ if (!child.visible)
+ continue;
+
+ if (child._skipPaint)
+ continue;
+
+ let childVolume = child.get_transformed_paint_volume(this);
+ if (!childVolume)
+ return false
+
+ paintVolume.union(childVolume);
+ }
+
+ return true;
+ },
+
/**
* Intended to be override by subclasses if they need a different
* set of items to be animated.
@@ -589,11 +661,11 @@ var IconGrid = new Lang.Class({
},
_onStyleChanged() {
- let themeNode = this.actor.get_theme_node();
+ let themeNode = this.get_theme_node();
this._spacing = themeNode.get_length('spacing');
this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
- this._grid.queue_relayout();
+ this.queue_relayout();
},
nRows(forWidth) {
@@ -625,12 +697,12 @@ var IconGrid = new Lang.Class({
removeAll() {
this._items = [];
- this._grid.remove_all_children();
+ this.remove_all_children();
},
destroyAll() {
this._items = [];
- this._grid.destroy_all_children();
+ this.destroy_all_children();
},
addItem(item, index) {
@@ -639,21 +711,21 @@ var IconGrid = new Lang.Class({
this._items.push(item);
if (index !== undefined)
- this._grid.insert_child_at_index(item.actor, index);
+ this.insert_child_at_index(item.actor, index);
else
- this._grid.add_actor(item.actor);
+ this.add_actor(item.actor);
},
removeItem(item) {
- this._grid.remove_child(item.actor);
+ this.remove_child(item.actor);
},
getItemAtIndex(index) {
- return this._grid.get_child_at_index(index);
+ return this.get_child_at_index(index);
},
visibleItemsCount() {
- return this._grid.get_n_children() - this._grid.get_n_skip_paint();
+ return this.get_children().filter(c => !c._skipPaint).length;
},
setSpacing(spacing) {
@@ -739,11 +811,12 @@ var IconGrid = new Lang.Class({
}
}
});
-Signals.addSignalMethods(IconGrid.prototype);
var PaginatedIconGrid = new Lang.Class({
Name: 'PaginatedIconGrid',
Extends: IconGrid,
+ Signals: {'space-opened': {},
+ 'space-closed': {} },
_init(params) {
this.parent(params);
@@ -754,20 +827,22 @@ var PaginatedIconGrid = new Lang.Class({
this._childrenPerPage = 0;
},
- _getPreferredHeight(grid, forWidth, alloc) {
- alloc.min_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) *
this._nPages + this._spaceBetweenPages * this._nPages;
- alloc.natural_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding)
* this._nPages + this._spaceBetweenPages * this._nPages;
+ vfunc_get_preferred_height(forWidth) {
+ let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) *
this._nPages + this._spaceBetweenPages * this._nPages;
+ return [height, height];
},
- _allocate(grid, box, flags) {
+ vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
+ this.set_allocation(box, flags);
+
if (this._fillParent) {
// Reset the passed in box to fill the parent
- let parentBox = this.actor.get_parent().allocation;
- let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
- box = this._grid.get_theme_node().get_content_box(gridBox);
+ let parentBox = this.get_parent().allocation;
+ let gridBox = this.get_theme_node().get_content_box(parentBox);
+ box = this.get_theme_node().get_content_box(gridBox);
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
@@ -795,7 +870,7 @@ var PaginatedIconGrid = new Lang.Class({
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
+ children[i]._skipPaint = false;
columnIndex++;
if (columnIndex == nColumns) {
@@ -966,4 +1041,3 @@ var PaginatedIconGrid = new Lang.Class({
}
}
});
-Signals.addSignalMethods(PaginatedIconGrid.prototype);
diff --git a/js/ui/search.js b/js/ui/search.js
index 97e18c058..4adf50217 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -363,8 +363,9 @@ var GridSearchResults = new Lang.Class({
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._bin.set_child(this._grid);
this._resultDisplayBin.set_child(this._bin);
},
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]