Files
dartamp/test/dock_controller_test.dart
T
hans 212f8e16d2 feat: Implement window dragging and docking functionality
- Added WindowDragController to manage custom dragging of sub-windows.
- Integrated dragging logic into EqWindow and PlWindow, allowing for smooth window movement.
- Introduced docking logic to snap windows together and maintain their positions relative to each other.
- Implemented persistence of window positions using SharedPreferences.
- Enhanced AppDelegate to support screen bounds and mouse location retrieval for accurate window positioning.
- Updated pubspec.yaml to include screen_retriever dependency.
- Added comprehensive tests for dock controller and dock logic to ensure correct behavior during window interactions.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
2026-08-10 15:53:29 +02:00

113 lines
4.7 KiB
Dart

import "dart:ui";
import "package:dartamp/src/docking/dock_controller.dart";
import "package:dartamp/src/docking/dock_logic.dart";
import "package:flutter_test/flutter_test.dart";
const screen = Rect.fromLTWH(0, 0, 1440, 900);
void main() {
late List<(DockWindow, Rect)> moved;
late Map<DockWindow, Rect>? persisted;
late DockController dock;
setUp(() {
moved = [];
persisted = null;
dock = DockController(
moveWindow: (window, rect) => moved.add((window, rect)),
persistRects: (rects) => persisted = rects,
)..screenRect = screen;
});
test("setRect and removeWindow maintain the rect map", () {
dock.setRect(DockWindow.eq, const Rect.fromLTWH(275, 0, 275, 116));
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(275, 0));
expect(dock.rects.length, 1);
dock.removeWindow(DockWindow.eq);
expect(dock.rectOf(DockWindow.eq), isNull);
});
test("a main-window drag moves the attached group by the same delta", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(500, 300, 275, 116));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(775, 300, 275, 116));
dock.beginMainDrag(const Offset(600, 340));
dock.mainDragTo(const Offset(700, 420));
dock.endMainDrag();
final mainRect = dock.rectOf(DockWindow.main)!;
final eqRect = dock.rectOf(DockWindow.eq)!;
expect(mainRect.topLeft, const Offset(600, 380));
expect(eqRect.topLeft, const Offset(875, 380));
expect(moved, contains((DockWindow.main, mainRect)));
expect(moved, contains((DockWindow.eq, eqRect)));
expect(persisted, isNotNull);
});
test("movement tracks the cumulative pointer delta", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(500, 300, 275, 116));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(775, 300, 275, 116));
dock.beginMainDrag(const Offset(600, 340));
dock.mainDragTo(const Offset(700, 420));
dock.mainDragTo(const Offset(800, 500));
expect(dock.rectOf(DockWindow.main)!.topLeft, const Offset(700, 460));
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(975, 460));
});
test("dragging to a screen corner snaps the whole group", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(10, 10, 275, 116));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(285, 10, 275, 116));
dock.beginMainDrag(const Offset(100, 100));
dock.mainDragTo(const Offset(95, 95));
expect(dock.rectOf(DockWindow.main)!.topLeft, Offset.zero);
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(275, 0));
});
test("an unattached window stays put while the group moves", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(500, 300, 275, 116));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(800, 500, 275, 116));
dock.beginMainDrag(const Offset(600, 340));
dock.mainDragTo(const Offset(650, 400));
expect(dock.rectOf(DockWindow.main)!.topLeft, const Offset(550, 360));
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(800, 500));
});
test("a sub-window resizing re-pins windows docked to its new edge", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(0, 0, 275, 116));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(275, 0, 275, 116));
dock.setRect(DockWindow.pl, const Rect.fromLTWH(0, 116, 280, 290));
dock.repinResized(DockWindow.main, const Rect.fromLTWH(0, 0, 330, 139.2));
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(330, 0));
expect(dock.rectOf(DockWindow.pl)!.topLeft, const Offset(0, 139.2));
});
test("subBounds re-pins the chain docked below the resized window", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(0, 0, 275, 116));
dock.setRect(DockWindow.pl, const Rect.fromLTWH(0, 116, 280, 290));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(0, 406, 275, 116));
dock.subBounds(DockWindow.pl, const Rect.fromLTWH(0, 116, 280, 14));
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(0, 130));
});
test("repinResized keeps everything pinned when the edge does not move", () {
dock.setRect(DockWindow.main, const Rect.fromLTWH(0, 0, 275, 116));
dock.setRect(DockWindow.eq, const Rect.fromLTWH(275, 0, 275, 116));
dock.repinResized(DockWindow.main, const Rect.fromLTWH(0, 0, 275, 14));
expect(dock.rectOf(DockWindow.eq)!.topLeft, const Offset(275, 0));
});
test("scaledSize accounts for shade state and UI scale", () {
expect(
DockController.scaledSize(DockWindow.main, false, 1.0),
const Size(275, 116),
);
expect(
DockController.scaledSize(DockWindow.eq, true, 1.0),
const Size(275, 14),
);
expect(
DockController.scaledSize(DockWindow.pl, false, 1.2),
const Size(336, 348),
);
});
}