diff --git a/package.json b/package.json index ea4b4cc..9cac547 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "modernwindowmanager", - "version": "5.0.0", + "version": "6.0.0", "author": "Domenico Ferraro ", "private": true, "license": "GPL v2.0", diff --git a/resources/metadata.json b/resources/metadata.json index fca0453..16d3ba5 100644 --- a/resources/metadata.json +++ b/resources/metadata.json @@ -11,7 +11,7 @@ "45", "46" ], - "version": 5, + "version": 6, "url": "https://github.com/domferr/modernwindowmanager", "settings-schema": "org.gnome.shell.extensions.modernwindowmanager" } \ No newline at end of file diff --git a/src/components/editor/editorDialog.ts b/src/components/editor/editorDialog.ts index 3c7dc6a..f0d95b5 100644 --- a/src/components/editor/editorDialog.ts +++ b/src/components/editor/editorDialog.ts @@ -19,7 +19,6 @@ export default class EditorDialog extends ModalDialog.ModalDialog { private readonly _layoutHeight: number = 72; private readonly _layoutWidth: number = 128; // 16:9 ratio. -> (16*layoutHeight) / 9 and then rounded to int private readonly _gapsSize: number = 3; - private readonly _signals: SignalHandling; private _layoutsBoxLayout: St.BoxLayout; @@ -31,7 +30,7 @@ export default class EditorDialog extends ModalDialog.ModalDialog { legend: boolean }) { super({ - destroyOnClose: false, + destroyOnClose: true, styleClass: 'editor-dialog', }); @@ -59,9 +58,9 @@ export default class EditorDialog extends ModalDialog.ModalDialog { if (!params.legend) { this._drawLayouts({ layouts: GlobalState.get().layouts, ...params }); - this._signals.connect(GlobalState.get(), "layouts-changed", () => { + /*this._signals.connect(GlobalState.get(), GlobalState.SIGNAL_LAYOUTS_CHANGED, () => { this._drawLayouts({ layouts: GlobalState.get().layouts, ...params }); - }); + });*/ } this.addButton({ @@ -74,8 +73,6 @@ export default class EditorDialog extends ModalDialog.ModalDialog { }); if (params.legend) this._makeLegendDialog(); - - this.connect("destroy", () => this._signals.disconnect()); } private _makeLegendDialog() { @@ -152,8 +149,8 @@ export default class EditorDialog extends ModalDialog.ModalDialog { legend.add_child(suggestion1); legend.add_child(suggestion2); legend.add_child(suggestion3); - this._signals.disconnect(); - this.contentLayout.remove_all_children(); + + this.contentLayout.destroy_all_children(); this.contentLayout.add_child(new St.Label({ text: "How to use the editor", xAlign: Clutter.ActorAlign.CENTER, @@ -180,7 +177,7 @@ export default class EditorDialog extends ModalDialog.ModalDialog { onNewLayout: () => void }) { const gaps = Settings.get_inner_gaps(1).top > 0 ? this._gapsSize:0 - this._layoutsBoxLayout.remove_all_children(); + this._layoutsBoxLayout.destroy_all_children(); params.layouts.forEach((lay, btnInd) => { const box = new St.BoxLayout({ @@ -195,6 +192,7 @@ export default class EditorDialog extends ModalDialog.ModalDialog { deleteBtn.child = new St.Icon({ iconName: "edit-delete-symbolic", iconSize: 16 }); deleteBtn.connect('clicked', (self) => { params.onDeleteLayout(btnInd, lay); + this._drawLayouts({ ...params, layouts: GlobalState.get().layouts }); }); box.add_child(deleteBtn); } diff --git a/src/components/editor/layoutEditor.ts b/src/components/editor/layoutEditor.ts index 82708c3..d1b3f67 100644 --- a/src/components/editor/layoutEditor.ts +++ b/src/components/editor/layoutEditor.ts @@ -64,7 +64,6 @@ export default class LayoutEditor extends St.Widget { } public set layout(newLayout: Layout) { - debug("set layout"); // cleanup this._sliders.forEach(slider => slider.destroy()); this._sliders = []; diff --git a/src/components/layout/LayoutWidget.ts b/src/components/layout/LayoutWidget.ts index 76655bd..b10f77c 100644 --- a/src/components/layout/LayoutWidget.ts +++ b/src/components/layout/LayoutWidget.ts @@ -73,7 +73,7 @@ export default class LayoutWidget extends St.Widge containerRect: Mtk.Rectangle, innerGaps: Clutter.Margin, outerGaps: Clutter.Margin - }>) { + }>): boolean { var trigger_relayout = this._previews.length === 0; if (params?.innerGaps) { this._innerGaps = params.innerGaps.copy(); @@ -94,15 +94,21 @@ export default class LayoutWidget extends St.Widge if (!trigger_relayout) { debug("relayout not needed"); - return; + return false; } - this._previews?.forEach((preview) => preview.destroy()); - this.remove_all_children(); + this._previews?.forEach((preview) => { + if (preview.get_parent() === this) { + this.remove_child(preview); + } + preview.destroy(); + }); this._previews = []; - if (this._containerRect.width === 0 || this._containerRect.height === 0) return; + if (this._containerRect.width === 0 || this._containerRect.height === 0) return true; this.draw_layout(); this._previews.forEach((lay) => lay.open()); + + return true; } } \ No newline at end of file diff --git a/src/components/snapassist/snapAssistLayout.ts b/src/components/snapassist/snapAssistLayout.ts index 516c669..dfcf4ba 100644 --- a/src/components/snapassist/snapAssistLayout.ts +++ b/src/components/snapassist/snapAssistLayout.ts @@ -31,7 +31,7 @@ export default class SnapAssistLayout extends LayoutWidget { super.relayout({ containerRect: buildRectangle({x: 0, y: 0, width, height}) - }) + }); } buildTile(parent: Clutter.Actor, rect: Mtk.Rectangle, gaps: Clutter.Margin, tile: Tile): SnapAssistTile { diff --git a/src/components/snapassist/snapAssistTile.ts b/src/components/snapassist/snapAssistTile.ts index 578b331..213b9bf 100644 --- a/src/components/snapassist/snapAssistTile.ts +++ b/src/components/snapassist/snapAssistTile.ts @@ -12,6 +12,7 @@ const debug = logger("SnapAssistTile"); @registerGObjectClass export default class SnapAssistTile extends TilePreview { protected _tile: Tile; + private _styleChangedSignalID: number | undefined; constructor(params: { parent?: Clutter.Actor, @@ -42,14 +43,13 @@ export default class SnapAssistTile extends TilePreview { ); this._applyStyle(); - const styleChangedSignalID = St.ThemeContext.get_for_stage(global.get_stage()).connect( - "changed", + this._styleChangedSignalID = St.ThemeContext.get_for_stage(global.get_stage()).connect( + "changed", () => { this._applyStyle(); } ); - - this.connect("destroy", () => St.ThemeContext.get_for_stage(global.get_stage()).disconnect(styleChangedSignalID)); + this.connect("destroy", () => this.onDestroy()); } _init() { @@ -74,4 +74,11 @@ export default class SnapAssistTile extends TilePreview { this.add_style_class_name("dark"); } } + + onDestroy(): void { + if (this._styleChangedSignalID) { + St.ThemeContext.get_for_stage(global.get_stage()).disconnect(this._styleChangedSignalID); + this._styleChangedSignalID = undefined; + } + } } \ No newline at end of file diff --git a/src/components/tilepreview/selectionTilePreview.ts b/src/components/tilepreview/selectionTilePreview.ts index a0b0e02..ea38589 100644 --- a/src/components/tilepreview/selectionTilePreview.ts +++ b/src/components/tilepreview/selectionTilePreview.ts @@ -1,5 +1,4 @@ import { registerGObjectClass } from "@/utils/gjs"; -import Mtk from 'gi://Mtk'; import Clutter from 'gi://Clutter'; import St from 'gi://St'; import TilePreview from "./tilePreview"; @@ -40,8 +39,8 @@ export default class SelectionTilePreview extends TilePreview { close() { if (!this._showing) return; - this._rect.width = 0; - this._rect.height = 0; + this._rect.width = this.gaps.left + this.gaps.right; + this._rect.height = this.gaps.top + this.gaps.bottom; super.close(); } } \ No newline at end of file diff --git a/src/components/tilepreview/tilePreview.ts b/src/components/tilepreview/tilePreview.ts index c4b5d0b..af7780a 100644 --- a/src/components/tilepreview/tilePreview.ts +++ b/src/components/tilepreview/tilePreview.ts @@ -10,14 +10,14 @@ export const WINDOW_ANIMATION_TIME = 100; const debug = logger('tilePreview'); -export module TilePreview { - export interface ConstructorProperties +//export module TilePreview { + export interface TilePreviewConstructorProperties extends St.Widget.ConstructorProperties { parent: Clutter.Actor; rect: Mtk.Rectangle; gaps: Clutter.Margin; } -} +//} @registerGObjectClass export default class TilePreview extends St.Widget { @@ -26,7 +26,7 @@ export default class TilePreview extends St.Widget { private _gaps: Clutter.Margin; - constructor(params: Partial) { + constructor(params: Partial) { super(params); if (params.parent) params.parent.add_child(this); @@ -44,6 +44,10 @@ export default class TilePreview extends St.Widget { this._gaps.left = gaps.left * scalingFactor; } + public get gaps(): Clutter.Margin { + return this._gaps; + } + _init() { super._init(); this.set_style_class_name('tile-preview custom-tile-preview'); diff --git a/src/components/tilingsystem/tilingLayout.ts b/src/components/tilingsystem/tilingLayout.ts index b4fb78d..2119be1 100644 --- a/src/components/tilingsystem/tilingLayout.ts +++ b/src/components/tilingsystem/tilingLayout.ts @@ -3,25 +3,51 @@ import { logger } from "@/utils/shell"; import { registerGObjectClass } from "@/utils/gjs"; import Mtk from 'gi://Mtk'; import Clutter from 'gi://Clutter'; -import BlurTilePreview from '../tilepreview/blurTilePreview'; -import TilePreview, { WINDOW_ANIMATION_TIME } from '../tilepreview/tilePreview'; +import TilePreview, { WINDOW_ANIMATION_TIME, TilePreviewConstructorProperties } from '../tilepreview/tilePreview'; import LayoutWidget from '../layout/LayoutWidget'; import Layout from '../layout/Layout'; import Tile from '../layout/Tile'; +import { buildRectangle, buildTileGaps } from '@utils/ui'; const debug = logger('tilingLayout'); +@registerGObjectClass +class DynamicTilePreview extends TilePreview { + private _originalRect: Mtk.Rectangle; + private _canRestore: boolean; + + constructor(params: Partial, canRestore?: boolean) { + super(params); + this._canRestore = canRestore || false; + this._originalRect = this.rect.copy(); + } + + public get originalRect(): Mtk.Rectangle { + return this._originalRect; + } + + public get canRestore(): boolean { + return this._canRestore; + } + + public restore(ease: boolean = false): boolean { + if (!this._canRestore) return false; + + this._rect = this._originalRect.copy(); + if (this.showing) this.open(ease); + + return true; + } +} + /** * A TilingLayout is a group of multiple tile previews. By aggregating all of them, * it is possible to easily show and hide each tile at the same time and to get the * hovered tile. */ @registerGObjectClass -export default class TilingLayout extends LayoutWidget { - private readonly _blur = false; - +export default class TilingLayout extends LayoutWidget { private _showing: boolean; - private _hoveredTiles: TilePreview[]; constructor(layout: Layout, innerGaps: Clutter.Margin, outerGaps: Clutter.Margin, workarea: Mtk.Rectangle, scalingFactor?: number) { super({ @@ -33,7 +59,6 @@ export default class TilingLayout extends LayoutWidget { scalingFactor }); this._showing = false; - this._hoveredTiles = []; super.relayout(); } @@ -42,8 +67,8 @@ export default class TilingLayout extends LayoutWidget { this.hide(); } - protected buildTile(parent: Clutter.Actor, rect: Mtk.Rectangle, gaps: Clutter.Margin, tile: Tile): TilePreview { - return this._blur ? new BlurTilePreview({ parent, rect, gaps }):new TilePreview({ parent, rect, gaps }); + protected buildTile(parent: Clutter.Actor, rect: Mtk.Rectangle, gaps: Clutter.Margin, tile?: Tile): DynamicTilePreview { + return new DynamicTilePreview({ parent, rect, gaps }, true); } public get showing(): boolean { @@ -103,31 +128,159 @@ export default class TilingLayout extends LayoutWidget { }); } - public getTileBelow(currPointerPos: { x: number; y: number }) : Mtk.Rectangle | undefined { - for (let i = 0; i < this._previews.length; i++) { - let preview = this._previews[i]; - const isHovering = currPointerPos.x >= preview.x && currPointerPos.x <= preview.x + preview.width - && currPointerPos.y >= preview.y && currPointerPos.y <= preview.y + preview.height; - if (isHovering) return preview.rect; + private _isHovered(currPointerPos: { x: number; y: number }, preview: Mtk.Rectangle): boolean { + return currPointerPos.x >= preview.x && currPointerPos.x <= preview.x + preview.width + && currPointerPos.y >= preview.y && currPointerPos.y <= preview.y + preview.height; + } + + public getTileBelow(currPointerPos: { x: number; y: number }, reset: boolean) : Mtk.Rectangle | undefined { + let found = this._previews.find(preview => this._isHovered(currPointerPos, preview.rect)); + if (!found || (!found.canRestore && reset)) { + found = this._previews.find(preview => preview.canRestore && this._isHovered(currPointerPos, preview.originalRect)); } - return undefined; + if (!found) return undefined; + + if (reset && found.originalRect) return found.originalRect; + return found.rect; } public unhoverAllTiles() { - this._hoveredTiles.forEach(prev => prev.open()); - this._hoveredTiles = []; + const newPreviewsArray: DynamicTilePreview[] = []; + this._previews.forEach(preview => { + if (preview.restore(true)) { + newPreviewsArray.push(preview); + preview.open(); + } else { + this.remove_child(preview); + preview.destroy(); + } + }); + this._previews = newPreviewsArray; } - public hoverTilesInRect(rect: Mtk.Rectangle) { - this._hoveredTiles = []; + public hoverTilesInRect(rect: Mtk.Rectangle, reset: boolean) { + const newPreviewsArray: DynamicTilePreview[] = []; + this._previews.forEach(preview => { - const [isInside, _] = rect.intersect(preview.rect); - if (isInside) { - preview.close(); - this._hoveredTiles.push(preview); + const [hasIntersection, rectangles] = this._subtractRectangles(preview.rect, rect); + if (hasIntersection) { + if (rectangles.length > 0) { + let maxIndex = 0; + for (let i = 0; i < rectangles.length; i++) { + if (rectangles[i].area() > rectangles[maxIndex].area()) maxIndex = i; + } + for (let i = 0; i < rectangles.length; i++) { + if (i === maxIndex) continue; + + const rect = rectangles[i]; + const gaps = buildTileGaps(rect, this._innerGaps, this._outerGaps, this._containerRect); + const innerPreview = new DynamicTilePreview({ parent: this, rect, gaps }, false); + innerPreview.open(); + this.set_child_above_sibling(innerPreview, preview); + newPreviewsArray.push(innerPreview); + } + preview.open(false, rectangles[maxIndex].union(preview.rect.intersect(rect)[1])); + preview.open(true, rectangles[maxIndex]); + newPreviewsArray.push(preview); + } else { + preview.close(); + newPreviewsArray.push(preview); + } } else { - preview.open(); + if (reset /*&& !preview.originalRect.intersect(rect)[0]*/) { + if (preview.restore(true)) { + preview.open(true); + newPreviewsArray.push(preview); + } else { + this.remove_child(preview); + preview.destroy(); + } + } else { + preview.open(true); + newPreviewsArray.push(preview); + } } }); + + this._previews = newPreviewsArray; + } + + /* + Given the source rectangle (made by A, B, C, D and Hole), subtract the hole and obtain A, B, C and D. + Edge cases: + - The hole may not be inside the source rect (i.e there is no interstaction). + It returns false and an array with the source rectangle only + - The hole intersects the source rectangle, it returns true and an array with A, B, C and D rectangles. + Some of A, B, C and D may not be returned if they don't exist + - The hole is equal to the source rectangle, it returns true and an empty array since A, B, C and D + rectangles do not exist + + Example: + ------------------------- + | A | + |-----------------------| + | B | hole | C | + |-----------------------| + | D | + ------------------------- + */ + private _subtractRectangles(sourceRect: Mtk.Rectangle, holeRect: Mtk.Rectangle): [boolean, Mtk.Rectangle[]] { + const [hasIntersection, intersection] = sourceRect.intersect(holeRect); + + if (!hasIntersection) { + return [false, [sourceRect]]; + } + + if (intersection.area() >= sourceRect.area()*0.98) { + return [true, []]; + } + + const results: Mtk.Rectangle[] = []; + + //A + const heightA = intersection.y - sourceRect.y; + if (heightA > 0) { + results.push(buildRectangle({ + x: sourceRect.x, + y: sourceRect.y, + width: sourceRect.width, + height: heightA + })); + } + + //B + const widthB = intersection.x - sourceRect.x; + if (widthB > 0 && intersection.height > 0) { + results.push(buildRectangle({ + x: sourceRect.x, + y: intersection.y, + width: widthB, + height: intersection.height + })); + } + + //C + const widthC = sourceRect.x + sourceRect.width - intersection.x - intersection.width; + if (widthC > 0 && intersection.height > 0) { + results.push(buildRectangle({ + x: intersection.x + intersection.width, + y: intersection.y, + width: widthC, + height: intersection.height + })); + } + + //D + const heightD = sourceRect.y + sourceRect.height - intersection.y - intersection.height; + if (heightD > 0) { + results.push(buildRectangle({ + x: sourceRect.x, + y: intersection.y + intersection.height, + width: sourceRect.width, + height: heightD + })); + } + + return [true, results]; } } \ No newline at end of file diff --git a/src/components/tilingsystem/tilingManager.ts b/src/components/tilingsystem/tilingManager.ts index 8f9034d..5a11411 100644 --- a/src/components/tilingsystem/tilingManager.ts +++ b/src/components/tilingsystem/tilingManager.ts @@ -39,7 +39,7 @@ export class TilingManager { private _movingWindowTimerId: number | null = null; private readonly _signals: SignalHandling; - private readonly _debug: (msg: string) => void; + private readonly _debug: (...content: any[]) => void; /** * Constructs a new TilingManager instance. @@ -242,14 +242,14 @@ export class TilingManager { return GLib.SOURCE_CONTINUE; } - let selectionRect = this._tilingLayout.getTileBelow(currPointerPos); + let selectionRect = this._tilingLayout.getTileBelow(currPointerPos, changedSpanMultipleTiles && !allowSpanMultipleTiles); if (!selectionRect) return GLib.SOURCE_CONTINUE; - + selectionRect = selectionRect.copy(); if (allowSpanMultipleTiles) { selectionRect = selectionRect.union(this._selectedTilesPreview.rect); } - this._tilingLayout.hoverTilesInRect(selectionRect); + this._tilingLayout.hoverTilesInRect(selectionRect, !allowSpanMultipleTiles); this._selectedTilesPreview.gaps = buildTileGaps( selectionRect, @@ -291,7 +291,7 @@ export class TilingManager { if (!this._isPointerInsideThisMonitor()) return; // abort if there is an invalid selection - if (this._selectedTilesPreview.innerWidth === 0 || this._selectedTilesPreview.innerHeight === 0) { + if (selectionRect.width <= 0 || selectionRect.height <= 0) { return; } diff --git a/src/indicator/defaultMenu.ts b/src/indicator/defaultMenu.ts index 9707a71..1d0a3b4 100644 --- a/src/indicator/defaultMenu.ts +++ b/src/indicator/defaultMenu.ts @@ -10,6 +10,9 @@ import GlobalState from '@/globalState'; import CurrentMenu from './currentMenu'; import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; import LayoutButton from './layoutButton'; +import { logger } from '@utils/shell'; + +const debug = logger("DefaultMenu"); export default class DefaultMenu implements CurrentMenu { private readonly _signals: SignalHandling; @@ -60,6 +63,7 @@ export default class DefaultMenu implements CurrentMenu { }); this._signals.connect(Main.layoutManager, 'monitors-changed', () => { + debug("monitors-changed") this._updateScaling(); }); } @@ -118,7 +122,9 @@ export default class DefaultMenu implements CurrentMenu { public destroy() { this._signals.disconnect(); - (this._indicator.menu as PopupMenu.PopupMenu).removeAll(); + this._layoutsButtons.forEach(btn => btn.destroy()); this._layoutsButtons = []; + this._layoutsBoxLayout.destroy(); + (this._indicator.menu as PopupMenu.PopupMenu).removeAll(); } } \ No newline at end of file diff --git a/src/indicator/indicator.ts b/src/indicator/indicator.ts index 387d4dd..72bc68f 100644 --- a/src/indicator/indicator.ts +++ b/src/indicator/indicator.ts @@ -4,7 +4,7 @@ import Shell from 'gi://Shell'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; import { logger } from '@/utils/shell'; -import { addToStatusArea, enableScalingFactorSupport, getMonitors, getScalingFactor } from '@/utils/ui'; +import { enableScalingFactorSupport, getMonitors, getScalingFactor } from '@/utils/ui'; import Settings from '@/settings'; import Layout from '@/components/layout/Layout'; import Tile from '@/components/layout/Tile'; @@ -15,7 +15,7 @@ import EditingMenu from './editingMenu'; import EditorDialog from '../components/editor/editorDialog'; import CurrentMenu from './currentMenu'; import { registerGObjectClass } from '@utils/gjs'; -import { PopupMenu } from 'resource:///org/gnome/shell/ui/popupMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const debug = logger('indicator'); @@ -35,7 +35,7 @@ export default class Indicator extends PanelMenu.Button { constructor(path: string, uuid: string) { super(0.5, 'Modern Window Manager Indicator', false); - addToStatusArea(this, uuid); + Main.panel.addToStatusArea(uuid, this, 1, 'right'); // Bind the "show-indicator" setting to the "visible" property. Settings.bind(Settings.SETTING_SHOW_INDICATOR, this, 'visible'); @@ -59,8 +59,7 @@ export default class Indicator extends PanelMenu.Button { if (value) { const monitor = Main.layoutManager.findMonitorForActor(this); const scalingFactor = getScalingFactor(monitor?.index || Main.layoutManager.primaryIndex); - //@ts-ignore - enableScalingFactorSupport(this.menu.box, scalingFactor); + enableScalingFactorSupport((this.menu as PopupMenu.PopupMenu).box, scalingFactor); } if (this._currentMenu && this._state === IndicatorState.DEFAULT) { @@ -70,7 +69,7 @@ export default class Indicator extends PanelMenu.Button { } public enable() { - (this.menu as PopupMenu).removeAll(); + (this.menu as PopupMenu.PopupMenu).removeAll(); this._currentMenu = new DefaultMenu(this); // todo diff --git a/src/indicator/utils.ts b/src/indicator/utils.ts index 2c4f4d6..50ca36c 100644 --- a/src/indicator/utils.ts +++ b/src/indicator/utils.ts @@ -3,7 +3,7 @@ import Clutter from 'gi://Clutter'; export const createButton = (icon_name: string, text: string) : St.Button => { const btn = new St.Button({ - styleClass: "button", + styleClass: "message-list-clear-button button", canFocus: true, xExpand: true, child: new St.BoxLayout({ @@ -16,7 +16,7 @@ export const createButton = (icon_name: string, text: string) : St.Button => { style: "spacing: 8px", }) }); - btn.child.add_child(new St.Icon({ iconName: icon_name, iconSize: 16 })); + btn.child.add_child(new St.Icon({ iconName: icon_name, iconSize: 16, yAlign: Clutter.ActorAlign.CENTER })); btn.child.add_child(new St.Label({ marginBottom: 4, marginTop: 4, text: text, yAlign: Clutter.ActorAlign.CENTER })); return btn; } \ No newline at end of file diff --git a/src/utils/ui.ts b/src/utils/ui.ts index bb49f80..4453954 100644 --- a/src/utils/ui.ts +++ b/src/utils/ui.ts @@ -7,10 +7,6 @@ import { Monitor } from 'resource:///org/gnome/shell/ui/layout.js'; export const getMonitors = (): Monitor[] => Main.layoutManager.monitors; -export const addToStatusArea = (button: any, uuid: string) => { - Main.panel.addToStatusArea(uuid, button, 1, 'right'); -}; - export const isPointInsideRect = (point: {x: number, y:number }, rect: Mtk.Rectangle) => { return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height; @@ -32,16 +28,16 @@ export const positionRelativeTo = (actor: Clutter.Actor, anchestor: Clutter.Acto } } -export const buildTileGaps = (tilePos: Mtk.Rectangle, innerMargin: Clutter.Margin, outerMargin: Clutter.Margin, containerRect: Mtk.Rectangle, scalingFactor: number = 1): Clutter.Margin => { - const isLeft = tilePos.x === containerRect.x; - const isTop = tilePos.y === containerRect.y; - const isRight = tilePos.x + tilePos.width === containerRect.x + containerRect.width; - const isBottom = tilePos.y + tilePos.height === containerRect.y + containerRect.height; +export const buildTileGaps = (tilePos: Mtk.Rectangle, innerGaps: Clutter.Margin, outerGaps: Clutter.Margin, container: Mtk.Rectangle, scalingFactor: number = 1): Clutter.Margin => { + const isLeft = tilePos.x === container.x; + const isTop = tilePos.y === container.y; + const isRight = tilePos.x + tilePos.width === container.x + container.width; + const isBottom = tilePos.y + tilePos.height === container.y + container.height; const margin = new Clutter.Margin(); - margin.top = (isTop ? outerMargin.top:innerMargin.top/2) * scalingFactor; - margin.bottom = (isBottom ? outerMargin.bottom:innerMargin.bottom/2) * scalingFactor; - margin.left = (isLeft ? outerMargin.left:innerMargin.left/2) * scalingFactor; - margin.right = (isRight ? outerMargin.right:innerMargin.right/2) * scalingFactor; + margin.top = (isTop ? outerGaps.top:innerGaps.top/2) * scalingFactor; + margin.bottom = (isBottom ? outerGaps.bottom:innerGaps.bottom/2) * scalingFactor; + margin.left = (isLeft ? outerGaps.left:innerGaps.left/2) * scalingFactor; + margin.right = (isRight ? outerGaps.right:innerGaps.right/2) * scalingFactor; return margin; }