workspace: Move more things to LayoutStrategy subclass
Only keep computeLayout, computeWindowSlots, computeScaleAndSpace and the contructor in the superclass, the rest is actually layout specific and won't apply anymore when we introduce the new vertical layout strategy. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1617>
This commit is contained in:
parent
c635ff490a
commit
ac7dc62da6
@ -114,6 +114,38 @@ var LayoutStrategy = class {
|
|||||||
this._columnSpacing = params.columnSpacing;
|
this._columnSpacing = params.columnSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute strategy-specific window slots for each window in
|
||||||
|
// @windows, given the @layout. The strategy may also use @layout
|
||||||
|
// as strategy-specific storage.
|
||||||
|
//
|
||||||
|
// This must calculate:
|
||||||
|
// * maxColumns - The maximum number of columns used by the layout.
|
||||||
|
// * gridWidth - The total width used by the grid, unscaled, unspaced.
|
||||||
|
// * gridHeight - The totial height used by the grid, unscaled, unspaced.
|
||||||
|
// * rows - A list of rows, which should be instantiated by _newRow.
|
||||||
|
computeLayout(_windows, _layout) {
|
||||||
|
throw new GObject.NotImplementedError(`computeLayout in ${this.constructor.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given @layout, compute the overall scale and space of the layout.
|
||||||
|
//
|
||||||
|
// This method does not return anything, but instead installs
|
||||||
|
// the properties "scale" and "space" on @layout directly.
|
||||||
|
//
|
||||||
|
// Make sure to call this methods before calling computeWindowSlots(),
|
||||||
|
// as it depends on the scale property installed in @layout here.
|
||||||
|
computeScaleAndSpace(_layout) {
|
||||||
|
throw new GObject.NotImplementedError(`computeScaleAndSpace in ${this.constructor.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an array with final position and size information for each
|
||||||
|
// window of the layout, given a bounding area that it will be inside of.
|
||||||
|
computeWindowSlots(_layout, _area) {
|
||||||
|
throw new GObject.NotImplementedError(`computeWindowSlots in ${this.constructor.name}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var UnalignedLayoutStrategy = class extends LayoutStrategy {
|
||||||
_newRow() {
|
_newRow() {
|
||||||
// Row properties:
|
// Row properties:
|
||||||
//
|
//
|
||||||
@ -150,37 +182,91 @@ var LayoutStrategy = class {
|
|||||||
return _interpolate(1.5, 1, ratio);
|
return _interpolate(1.5, 1, ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the size of each row, by assigning to the properties
|
_computeRowSizes(layout) {
|
||||||
// row.width, row.height, row.fullWidth, row.fullHeight, and
|
let { rows, scale } = layout;
|
||||||
// (optionally) for each row in @layout.rows. This method is
|
for (let i = 0; i < rows.length; i++) {
|
||||||
// intended to be called by subclasses.
|
let row = rows[i];
|
||||||
_computeRowSizes(_layout) {
|
row.width = row.fullWidth * scale + (row.windows.length - 1) * this._columnSpacing;
|
||||||
throw new GObject.NotImplementedError(`_computeRowSizes in ${this.constructor.name}`);
|
row.height = row.fullHeight * scale;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute strategy-specific window slots for each window in
|
_keepSameRow(row, window, width, idealRowWidth) {
|
||||||
// @windows, given the @layout. The strategy may also use @layout
|
if (row.fullWidth + width <= idealRowWidth)
|
||||||
// as strategy-specific storage.
|
return true;
|
||||||
//
|
|
||||||
// This must calculate:
|
let oldRatio = row.fullWidth / idealRowWidth;
|
||||||
// * maxColumns - The maximum number of columns used by the layout.
|
let newRatio = (row.fullWidth + width) / idealRowWidth;
|
||||||
// * gridWidth - The total width used by the grid, unscaled, unspaced.
|
|
||||||
// * gridHeight - The totial height used by the grid, unscaled, unspaced.
|
if (Math.abs(1 - newRatio) < Math.abs(1 - oldRatio))
|
||||||
// * rows - A list of rows, which should be instantiated by _newRow.
|
return true;
|
||||||
computeLayout(_windows, _layout) {
|
|
||||||
throw new GObject.NotImplementedError(`computeLayout in ${this.constructor.name}`);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given @layout, compute the overall scale and space of the layout.
|
_sortRow(row) {
|
||||||
// The scale is the individual, non-fancy scale of each window, and
|
// Sort windows horizontally to minimize travel distance.
|
||||||
// the space is the percentage of the available area eventually
|
// This affects in what order the windows end up in a row.
|
||||||
// used by the layout.
|
row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
computeLayout(windows, layout) {
|
||||||
|
let numRows = layout.numRows;
|
||||||
|
|
||||||
|
let rows = [];
|
||||||
|
let totalWidth = 0;
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
let window = windows[i];
|
||||||
|
let s = this._computeWindowScale(window);
|
||||||
|
totalWidth += window.boundingBox.width * s;
|
||||||
|
}
|
||||||
|
|
||||||
|
let idealRowWidth = totalWidth / numRows;
|
||||||
|
|
||||||
|
// Sort windows vertically to minimize travel distance.
|
||||||
|
// This affects what rows the windows get placed in.
|
||||||
|
let sortedWindows = windows.slice();
|
||||||
|
sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y);
|
||||||
|
|
||||||
|
let windowIdx = 0;
|
||||||
|
for (let i = 0; i < numRows; i++) {
|
||||||
|
let row = this._newRow();
|
||||||
|
rows.push(row);
|
||||||
|
|
||||||
|
for (; windowIdx < sortedWindows.length; windowIdx++) {
|
||||||
|
let window = sortedWindows[windowIdx];
|
||||||
|
let s = this._computeWindowScale(window);
|
||||||
|
let width = window.boundingBox.width * s;
|
||||||
|
let height = window.boundingBox.height * s;
|
||||||
|
row.fullHeight = Math.max(row.fullHeight, height);
|
||||||
|
|
||||||
|
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
|
||||||
|
if (this._keepSameRow(row, window, width, idealRowWidth) || (i === numRows - 1)) {
|
||||||
|
row.windows.push(window);
|
||||||
|
row.fullWidth += width;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let gridHeight = 0;
|
||||||
|
let maxRow;
|
||||||
|
for (let i = 0; i < numRows; i++) {
|
||||||
|
let row = rows[i];
|
||||||
|
this._sortRow(row);
|
||||||
|
|
||||||
|
if (!maxRow || row.fullWidth > maxRow.fullWidth)
|
||||||
|
maxRow = row;
|
||||||
|
gridHeight += row.fullHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.rows = rows;
|
||||||
|
layout.maxColumns = maxRow.windows.length;
|
||||||
|
layout.gridWidth = maxRow.fullWidth;
|
||||||
|
layout.gridHeight = gridHeight;
|
||||||
|
}
|
||||||
|
|
||||||
// This method does not return anything, but instead installs
|
|
||||||
// the properties "scale" and "space" on @layout directly.
|
|
||||||
//
|
|
||||||
// Make sure to call this methods before calling computeWindowSlots(),
|
|
||||||
// as it depends on the scale property installed in @layout here.
|
|
||||||
computeScaleAndSpace(layout) {
|
computeScaleAndSpace(layout) {
|
||||||
let area = layout.area;
|
let area = layout.area;
|
||||||
|
|
||||||
@ -282,93 +368,6 @@ var LayoutStrategy = class {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var UnalignedLayoutStrategy = class extends LayoutStrategy {
|
|
||||||
_computeRowSizes(layout) {
|
|
||||||
let { rows, scale } = layout;
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
|
||||||
let row = rows[i];
|
|
||||||
row.width = row.fullWidth * scale + (row.windows.length - 1) * this._columnSpacing;
|
|
||||||
row.height = row.fullHeight * scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_keepSameRow(row, window, width, idealRowWidth) {
|
|
||||||
if (row.fullWidth + width <= idealRowWidth)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
let oldRatio = row.fullWidth / idealRowWidth;
|
|
||||||
let newRatio = (row.fullWidth + width) / idealRowWidth;
|
|
||||||
|
|
||||||
if (Math.abs(1 - newRatio) < Math.abs(1 - oldRatio))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_sortRow(row) {
|
|
||||||
// Sort windows horizontally to minimize travel distance.
|
|
||||||
// This affects in what order the windows end up in a row.
|
|
||||||
row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
computeLayout(windows, layout) {
|
|
||||||
let numRows = layout.numRows;
|
|
||||||
|
|
||||||
let rows = [];
|
|
||||||
let totalWidth = 0;
|
|
||||||
for (let i = 0; i < windows.length; i++) {
|
|
||||||
let window = windows[i];
|
|
||||||
let s = this._computeWindowScale(window);
|
|
||||||
totalWidth += window.boundingBox.width * s;
|
|
||||||
}
|
|
||||||
|
|
||||||
let idealRowWidth = totalWidth / numRows;
|
|
||||||
|
|
||||||
// Sort windows vertically to minimize travel distance.
|
|
||||||
// This affects what rows the windows get placed in.
|
|
||||||
let sortedWindows = windows.slice();
|
|
||||||
sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y);
|
|
||||||
|
|
||||||
let windowIdx = 0;
|
|
||||||
for (let i = 0; i < numRows; i++) {
|
|
||||||
let row = this._newRow();
|
|
||||||
rows.push(row);
|
|
||||||
|
|
||||||
for (; windowIdx < sortedWindows.length; windowIdx++) {
|
|
||||||
let window = sortedWindows[windowIdx];
|
|
||||||
let s = this._computeWindowScale(window);
|
|
||||||
let width = window.boundingBox.width * s;
|
|
||||||
let height = window.boundingBox.height * s;
|
|
||||||
row.fullHeight = Math.max(row.fullHeight, height);
|
|
||||||
|
|
||||||
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
|
|
||||||
if (this._keepSameRow(row, window, width, idealRowWidth) || (i == numRows - 1)) {
|
|
||||||
row.windows.push(window);
|
|
||||||
row.fullWidth += width;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let gridHeight = 0;
|
|
||||||
let maxRow;
|
|
||||||
for (let i = 0; i < numRows; i++) {
|
|
||||||
let row = rows[i];
|
|
||||||
this._sortRow(row);
|
|
||||||
|
|
||||||
if (!maxRow || row.fullWidth > maxRow.fullWidth)
|
|
||||||
maxRow = row;
|
|
||||||
gridHeight += row.fullHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.rows = rows;
|
|
||||||
layout.maxColumns = maxRow.windows.length;
|
|
||||||
layout.gridWidth = maxRow.fullWidth;
|
|
||||||
layout.gridHeight = gridHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function animateAllocation(actor, box) {
|
function animateAllocation(actor, box) {
|
||||||
if (actor.allocation.equal(box) ||
|
if (actor.allocation.equal(box) ||
|
||||||
actor.allocation.get_width() === 0 ||
|
actor.allocation.get_width() === 0 ||
|
||||||
|
Loading…
Reference in New Issue
Block a user