Skip to content

Commit 82179c6

Browse files
committed
refactor: new and simplified tile and layout description
1 parent 0e1a054 commit 82179c6

16 files changed

+156
-187
lines changed

src/components/layout/Layout.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
export const LAYOUT_HORIZONTAL_TYPE = 0;
2-
export const LAYOUT_VERTICAL_TYPE = 1;
1+
import { Tile } from "./Tile";
32

4-
export interface Layout {
5-
type: number // 0 means horizontal, 1 means vertical
6-
length: number
7-
items: Layout[]
3+
export class Layout {
4+
tiles: Tile[];
5+
6+
constructor(tiles: Tile[]) {
7+
this.tiles = tiles;
8+
}
89
}

src/components/layout/LayoutUtils.ts

+26-47
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {logger} from "@/utils/shell";
22
import GLib from "@gi-types/glib2";
3-
import { TileGroup } from "@/components/layout/tileGroup";
4-
import { LAYOUT_HORIZONTAL_TYPE, Layout } from "./Layout";
3+
import { Layout } from "./Layout";
4+
import { Tile } from "./Tile";
55

66
const debug = logger('LayoutsUtils');
77

@@ -14,28 +14,22 @@ export class LayoutsUtils {
1414
return GLib.build_filenamev([this.configPath, 'layouts.json']);
1515
}
1616

17-
public static LoadLayouts(): TileGroup[] {
17+
public static LoadLayouts(): Layout[] {
1818
const availableLayouts = [
19-
new TileGroup({}),
20-
new TileGroup({
21-
tiles: [
22-
new TileGroup({ perc: 0.22 }),
23-
new TileGroup({ perc: 0.56 }),
24-
new TileGroup({ perc: 0.22 }),
25-
],
26-
}),
27-
new TileGroup({
28-
tiles: [
29-
new TileGroup({ perc: 0.33 }),
30-
new TileGroup({ perc: 0.67 }),
31-
],
32-
}),
33-
new TileGroup({
34-
tiles: [
35-
new TileGroup({ perc: 0.67 }),
36-
new TileGroup({ perc: 0.33 }),
37-
],
38-
})
19+
new Layout([]),
20+
new Layout([
21+
new Tile({ x:0, y:0, height: 1, width: 0.22 }),
22+
new Tile({ x:0.22, y:0, height: 1, width: 0.56 }),
23+
new Tile({ x:0.78, y:0, height: 1, width: 0.22 }),
24+
]),
25+
new Layout([
26+
new Tile({ x:0, y:0, height: 1, width: 0.33 }),
27+
new Tile({ x:0.33, y:0, height: 1, width: 0.67 }),
28+
]),
29+
new Layout([
30+
new Tile({ x:0.33, y:0, height: 1, width: 0.67 }),
31+
new Tile({ x:0, y:0, height: 1, width: 0.33 }),
32+
]),
3933
];
4034
const filePath = this.layoutsPath;
4135
if (GLib.file_test(filePath, GLib.FileTest.EXISTS)) {
@@ -45,8 +39,7 @@ export class LayoutsUtils {
4539
const decoder = new TextDecoder('utf-8');
4640
let contentsString = decoder.decode(contents);
4741
const parsed = JSON.parse(contentsString);
48-
const layouts = parsed.definitions as Layout[];
49-
availableLayouts[0] = this._layoutToTileGroup(layouts[0]);
42+
return parsed.definitions as Layout[];
5043
}
5144
} catch (exception) {
5245
debug(`exception loading layouts: ${JSON.stringify(exception)}`);
@@ -56,27 +49,13 @@ export class LayoutsUtils {
5649
return availableLayouts;
5750
}
5851

59-
private static _layoutToTileGroup(layout: Layout) : TileGroup {
60-
return new TileGroup({
61-
perc: layout.length / 100,
62-
horizontal: layout.type === LAYOUT_HORIZONTAL_TYPE,
63-
tiles: layout.items ? layout.items.map(LayoutsUtils._layoutToTileGroup):[],
64-
});
65-
}
66-
67-
private static _getDefaultLayout(): TileGroup {
68-
return new TileGroup({
69-
tiles: [
70-
new TileGroup({ perc: 0.22, horizontal: false, tiles: [
71-
new TileGroup({ perc: 0.5 }),
72-
new TileGroup({ perc: 0.5 })
73-
] }),
74-
new TileGroup({ perc: 0.56 }),
75-
new TileGroup({ perc: 0.22, horizontal: false, tiles: [
76-
new TileGroup({ perc: 0.5 }),
77-
new TileGroup({ perc: 0.5 })
78-
] }),
79-
],
80-
});
52+
private static _getDefaultLayout(): Layout {
53+
return new Layout([
54+
new Tile({ x:0, y:0, height: 0.5, width: 0.22 }), // top-left
55+
new Tile({ x:0, y:0.5, height: 0.5, width: 0.22 }), // bottom-left
56+
new Tile({ x:0.22, y:0, height: 1, width: 0.56 }), // center
57+
new Tile({ x:0.78, y:0, height: 0.5, width: 0.22 }), // top-right
58+
new Tile({ x:0.78, y:0.5, height: 0.5, width: 0.22 }), // bottom-right
59+
]);
8160
}
8261
}

src/components/layout/LayoutWidget.ts

+14-45
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Widget } from "@gi-types/st1";
22
import { TilePreview } from "../tilepreview/tilePreview";
33
import { Actor, Margin } from '@gi-types/clutter10';
4-
import { TileGroup } from "./tileGroup";
54
import { Rectangle } from "@gi-types/meta10";
65
import { registerGObjectClass } from "@/utils/gjs";
76
import { buildTileMargin } from "@/utils/ui";
87
import { logger } from "@/utils/shell";
8+
import { Layout } from "./Layout";
9+
import { Tile } from "./Tile";
910

1011
const debug = logger(`LayoutWidget`);
1112

@@ -14,60 +15,35 @@ const debug = logger(`LayoutWidget`);
1415
export class LayoutWidget<TileType extends TilePreview> extends Widget {
1516
protected _previews: TileType[];
1617
protected _containerRect: Rectangle;
17-
protected _layout: TileGroup;
18+
protected _layout: Layout;
1819
protected _innerMargin: Margin;
1920
protected _outerMargin: Margin;
2021

21-
constructor(parent: Actor | null, layout: TileGroup, innerMargin: Margin, outerMargin: Margin, containerRect: Rectangle, style_class: string = "") {
22+
constructor(parent: Actor | null, layout: Layout, innerMargin: Margin, outerMargin: Margin, containerRect: Rectangle, style_class: string = "") {
2223
super({ style_class });
2324
if (parent) parent.add_child(this);
2425
this._previews = [];
2526
this._containerRect = new Rectangle();
26-
this._layout = new TileGroup({tiles: []});
27+
this._layout = new Layout([]);
2728
this._innerMargin = new Margin();
2829
this._outerMargin = new Margin();
2930
this.relayout({ containerRect, layout, innerMargin, outerMargin });
3031
}
3132

32-
protected build_layout(groupRect: Rectangle, group: TileGroup, previews: TileType[], innerMargin: Margin, outerMargin: Margin, containerRect: Rectangle): TileType[] {
33-
if (group.tiles.length == 0) {
34-
const tileMargin = buildTileMargin(groupRect, innerMargin, outerMargin, containerRect);
35-
const tile = this.buildTile(this, groupRect.copy(), tileMargin);
36-
previews.push(tile);
37-
return previews;
38-
}
39-
40-
const workingRect = groupRect.copy();
41-
42-
group.tiles.forEach((innerGroup, index) => {
43-
let innerGroupRect = new Rectangle({
44-
x: workingRect.x,
45-
y: workingRect.y,
46-
width: group.horizontal ? groupRect.width * innerGroup.perc:groupRect.width,
47-
height: group.horizontal ? groupRect.height:groupRect.height * innerGroup.perc,
48-
});
49-
// if there is remaining width or height, then we have lost some pixel because of
50-
// floating point precision. Ensure the remaining width or height is given to the last tile
51-
if (index === group.tiles.length - 1) {
52-
// ensure we don't go beyond the limits and ensure the remaining
53-
// width or height is given to the last tile
54-
innerGroupRect.width = groupRect.x + groupRect.width - innerGroupRect.x;
55-
innerGroupRect.height = groupRect.y + groupRect.height - innerGroupRect.y;
56-
}
57-
this.build_layout(innerGroupRect, innerGroup, previews, innerMargin, outerMargin, containerRect);
58-
workingRect.x += group.horizontal ? innerGroupRect.width:0;
59-
workingRect.y += group.horizontal ? 0:innerGroupRect.height;
60-
})
61-
62-
return previews;
33+
protected draw_layout(): void {
34+
this._previews = this._layout.tiles.map(tile => {
35+
const tileRect = tile.apply_props(this._containerRect);
36+
const tileMargin = buildTileMargin(tileRect, this._innerMargin, this._outerMargin, this._containerRect);
37+
return this.buildTile(this, tileRect, tileMargin, tile);
38+
});
6339
}
6440

65-
protected buildTile(parent: Actor, rect: Rectangle, margin: Margin): TileType {
41+
protected buildTile(parent: Actor, rect: Rectangle, margin: Margin, tile: Tile): TileType {
6642
throw("This class shouldn't be instantiated but be extended instead");
6743
}
6844

6945
public relayout(params?: Partial<{
70-
layout: TileGroup,
46+
layout: Layout,
7147
containerRect: Rectangle,
7248
innerMargin: Margin,
7349
outerMargin: Margin
@@ -100,14 +76,7 @@ export class LayoutWidget<TileType extends TilePreview> extends Widget {
10076
this._previews = [];
10177
if (this._containerRect.width === 0 || this._containerRect.height === 0) return;
10278

103-
this._previews = this.build_layout(
104-
this._containerRect,
105-
this._layout,
106-
[],
107-
this._innerMargin,
108-
this._outerMargin,
109-
this._containerRect
110-
);
79+
this.draw_layout();
11180
this._previews.forEach((lay) => lay.open());
11281
}
11382
}

src/components/layout/Tile.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Rectangle } from "@gi-types/meta10";
2+
import GObject from "@gi-types/gobject2";
3+
4+
export class Tile {
5+
static $gtype = GObject.TYPE_JSOBJECT;
6+
7+
x: number;
8+
y: number;
9+
width: number;
10+
height: number;
11+
12+
constructor({x, y, width, height}:{ x: number, y: number, width: number, height: number }) {
13+
this.x = x;
14+
this.y = y;
15+
this.width = width;
16+
this.height = height;
17+
}
18+
19+
public apply_props(container: Rectangle): Rectangle {
20+
return new Rectangle({
21+
x: (container.width * this.x) + container.x,
22+
y: (container.height * this.y) + container.y,
23+
width: container.width * this.width,
24+
height: container.height * this.height,
25+
})
26+
}
27+
}

src/components/layout/tileGroup.ts

-11
This file was deleted.

src/components/snapassist/snapAssist.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import { registerGObjectClass } from "@/utils/gjs";
22
import { Actor, AnimationMode, ActorAlign, Margin } from '@gi-types/clutter10';
33
import { Rectangle, Window } from "@gi-types/meta10";
44
import { BoxLayout, Side, ThemeContext, Widget } from "@gi-types/st1";
5-
import { TileGroup } from "../layout/tileGroup";
65
import { logger } from "@/utils/shell";
7-
import { MetaInfo, TYPE_DOUBLE } from "@gi-types/gobject2";
6+
import { MetaInfo } from "@gi-types/gobject2";
87
import { SnapAssistTile } from "./snapAssistTile";
98
import { SnapAssistLayout } from "./snapAssistLayout";
9+
import { Layout } from "../layout/Layout";
10+
import { Tile } from "../layout/Tile";
1011

1112
export const SNAP_ASSIST_SIGNAL = 'snap-assist';
1213
export const SNAP_ASSIST_ANIMATION_TIME = 180;
@@ -18,7 +19,7 @@ export class SnapAssist extends BoxLayout {
1819
static metaInfo: MetaInfo = {
1920
Signals: {
2021
"snap-assist": {
21-
param_types: [Rectangle.$gtype, TYPE_DOUBLE, TYPE_DOUBLE]
22+
param_types: [ Tile.$gtype ]
2223
},
2324
},
2425
GTypeName: "SnapAssist"
@@ -41,7 +42,7 @@ export class SnapAssist extends BoxLayout {
4142
private _workArea: Rectangle = new Rectangle();
4243
private _hoveredTile: SnapAssistTile | undefined;
4344

44-
constructor(parent: Actor, layouts: TileGroup[], margin: Margin, workArea: Rectangle, scaleFactor: number) {
45+
constructor(parent: Actor, layouts: Layout[], margin: Margin, workArea: Rectangle, scaleFactor: number) {
4546
super({
4647
name: 'snap_assist',
4748
x_align: ActorAlign.CENTER,
@@ -193,15 +194,14 @@ export class SnapAssist extends BoxLayout {
193194
this._hoveredTile.set_hover(false);
194195
}
195196
this._hoveredTile = undefined;
196-
if (wasEnlarged) this.emit(SNAP_ASSIST_SIGNAL, new Rectangle(), 0, 0);
197+
if (wasEnlarged) this.emit(SNAP_ASSIST_SIGNAL, new Tile({x:0, y:0, width: 0, height: 0}));
197198
return;
198199
}
199200

200201
const {changed, layout} = this.handleTileHovering(currPointerPos);
201202
if (changed) {
202-
const tileRect = this._hoveredTile ? this._hoveredTile.rect:new Rectangle();
203-
const layoutRect = this._hoveredTile ? new Rectangle({x: layout?.x, y: layout?.y, width: layout?.width, height: layout?.height}):new Rectangle();
204-
this.emit(SNAP_ASSIST_SIGNAL, tileRect, layoutRect.width, layoutRect.height);
203+
const tile = this._hoveredTile?.tile || new Tile({x:0,y:0,width:0,height:0});
204+
this.emit(SNAP_ASSIST_SIGNAL, tile);
205205
}
206206
}
207207

src/components/snapassist/snapAssistLayout.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { Actor, Margin, AnimationMode } from '@gi-types/clutter10';
33
import { getGlobalPosition } from "@/utils/ui";
44
import { Rectangle } from "@gi-types/meta10";
55
import { LayoutWidget } from "../layout/LayoutWidget";
6-
import { TileGroup } from "../layout/tileGroup";
76
import { SnapAssistTile } from "./snapAssistTile";
87
import { logger } from "@/utils/shell";
8+
import { Layout } from "../layout/Layout";
9+
import { Tile } from "../layout/Tile";
910

1011
const debug = logger("snapAssistLayout");
1112

@@ -14,16 +15,16 @@ export class SnapAssistLayout extends LayoutWidget<SnapAssistTile> {
1415
private static readonly _snapAssistHeight: number = 84;
1516
private static readonly _snapAssistWidth: number = 150; // 16:9 ratio. -> (16*this._snapAssistHeight) / 9 and then rounded to int
1617

17-
constructor(parent: Actor | null, layout: TileGroup, margin: Margin, scaleFactor: number) {
18+
constructor(parent: Actor | null, layout: Layout, gaps: Margin, scaleFactor: number) {
1819
const rect = new Rectangle({height: SnapAssistLayout._snapAssistHeight * scaleFactor, width: SnapAssistLayout._snapAssistWidth * scaleFactor, x: 0, y: 0});
19-
const margins = new Margin({top: margin.top * scaleFactor, bottom: margin.bottom * scaleFactor, left: margin.left * scaleFactor, right: margin.right * scaleFactor});
20-
const outerMargin = Math.min(margin.top, Math.min(margin.bottom, Math.min(margin.left, margin.right))) * scaleFactor;
21-
super(parent, layout, margins, new Margin({top: outerMargin, bottom: outerMargin, left: outerMargin, right: outerMargin }), rect, "snap-assist-layout");
20+
gaps = new Margin({top: gaps.top * scaleFactor, bottom: gaps.bottom * scaleFactor, left: gaps.left * scaleFactor, right: gaps.right * scaleFactor});
21+
const outerMargin = Math.min(gaps.top, Math.min(gaps.bottom, Math.min(gaps.left, gaps.right))) * scaleFactor;
22+
super(parent, layout, gaps, new Margin({top: outerMargin, bottom: outerMargin, left: outerMargin, right: outerMargin }), rect, "snap-assist-layout");
2223
this.ensure_style();
2324
}
2425

25-
buildTile(parent: Actor, rect: Rectangle, margin: Margin): SnapAssistTile {
26-
return new SnapAssistTile(parent, rect, margin);
26+
buildTile(parent: Actor, rect: Rectangle, gaps: Margin, tile: Tile): SnapAssistTile {
27+
return new SnapAssistTile({parent, rect, gaps, tile});
2728
}
2829

2930
public getTileBelow(cursorPos: {x: number, y: number}) : SnapAssistTile | undefined {
+4-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import { registerGObjectClass } from "@/utils/gjs";
2-
import { Rectangle } from "@gi-types/meta10";
3-
import { Actor, Margin } from '@gi-types/clutter10';
42
import { TilePreview } from "../tilepreview/tilePreview";
53

64
@registerGObjectClass
75
export class SnapAssistTile extends TilePreview {
8-
constructor(parent: Actor, rect?: Rectangle, margins?: Margin) {
9-
super(parent, rect, margins);
10-
}
11-
126
_init() {
137
super._init();
148
this.set_style_class_name('snap-assist-tile');
159
}
10+
11+
public get tile() {
12+
return this._tile;
13+
}
1614
}

src/components/tilepreview/selectionTilePreview.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ import { Rectangle } from "@gi-types/meta10";
33
import { Actor, Color, Margin } from '@gi-types/clutter10';
44
import { TilePreview } from "./tilePreview";
55
import { logger } from "@/utils/shell";
6+
import { Tile } from "../layout/Tile";
67

78
const debug = logger("SelectionTilePreview");
89

910
@registerGObjectClass
1011
export class SelectionTilePreview extends TilePreview {
1112
private _backgroundColor: Color | null = null;
1213

13-
constructor(parent: Actor, rect?: Rectangle, margins?: Margin) {
14-
super(parent, rect, margins);
14+
constructor(params: {
15+
parent?: Actor,
16+
rect?: Rectangle,
17+
gaps?: Margin,
18+
}) {
19+
super({tile: new Tile({x:0, y:0, width: 0, height: 0}), ...params});
1520
this._recolor();
1621
this.connect("style-changed", () => {
1722
const { red, green, blue } = this.get_theme_node().get_background_color();

0 commit comments

Comments
 (0)