Skip to content

Commit

Permalink
Add functionality for fully and partial selection
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDoctorDE committed Sep 8, 2024
1 parent 3046ed9 commit 17e37d3
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 98 deletions.
4 changes: 2 additions & 2 deletions api/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,10 @@ packages:
dependency: transitive
description:
name: shelf_static
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.1.3"
shelf_web_socket:
dependency: transitive
description:
Expand Down
19 changes: 12 additions & 7 deletions app/lib/helpers/rect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,23 @@ extension RectHelper on Rect {
return Rect.fromLTRB(firstX, firstY, secondX, secondY);
}

bool containsLine(Offset first, Offset second) {
bool containsLine(Offset first, Offset second, {bool full = false}) {
final normalizedRect = normalized();
final topLeft = normalizedRect.topLeft;
final topRight = normalizedRect.topRight;
final bottomLeft = normalizedRect.bottomLeft;
final bottomRight = normalizedRect.bottomRight;
return lineIntersectsLine(topLeft, topRight, first, second) ||
lineIntersectsLine(topRight, bottomRight, first, second) ||
lineIntersectsLine(bottomRight, bottomLeft, first, second) ||
lineIntersectsLine(bottomLeft, topLeft, first, second) ||
normalizedRect.contains(first) ||
normalizedRect.contains(second);
final tlr = lineIntersectsLine(topLeft, topRight, first, second);

final tbr = lineIntersectsLine(topRight, bottomRight, first, second);
final blr = lineIntersectsLine(bottomRight, bottomLeft, first, second);
final tbl = lineIntersectsLine(bottomLeft, topLeft, first, second);
final containsFirst = normalizedRect.contains(first);
final containsSecond = normalizedRect.contains(second);
if (full) {
return tlr && tbr && blr && tbl && containsFirst && containsSecond;
}
return tlr || tbr || blr || tbl || containsFirst || containsSecond;
}
}

Expand Down
4 changes: 3 additions & 1 deletion app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -611,5 +611,7 @@
"installed": "Installed",
"install": "Install",
"deselect": "Deselect",
"changeLayer": "Change layer"
"changeLayer": "Change layer",
"fullSelection": "Full selection",
"fullSelectionDescription": "When enabled, elements must be fully contained within the selection box to be selected. If disabled, elements can be selected by touching the selection box, even if only partially."
}
20 changes: 15 additions & 5 deletions app/lib/renderers/elements/path.dart
Original file line number Diff line number Diff line change
Expand Up @@ -242,18 +242,28 @@ class PathHitCalculator extends HitCalculator {
}

@override
bool hit(Rect rect) {
bool hit(Rect rect, {bool full = false}) {
if (!elementRect.overlaps(rect)) {
return false;
}
if (points.length == 1) {
return rect.contains(points.first.toOffset());
}
return _getInterpolatedPoints(points)
.any((point) => rect.contains(point.toOffset()));
final interpolated = _getInterpolatedPoints(points);
if (full) {
return interpolated.every((point) => rect.contains(point.toOffset()));
}
return interpolated.any((point) => rect.contains(point.toOffset()));
}

@override
bool hitPolygon(List<ui.Offset> polygon) => _getInterpolatedPoints(points)
.any((point) => isPointInPolygon(polygon, point.toOffset()));
bool hitPolygon(List<ui.Offset> polygon, {bool full = false}) {
final interpolated = _getInterpolatedPoints(points);
if (full) {
return interpolated
.every((point) => isPointInPolygon(polygon, point.toOffset()));
}
return interpolated
.any((point) => isPointInPolygon(polygon, point.toOffset()));
}
}
55 changes: 37 additions & 18 deletions app/lib/renderers/elements/shape.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class ShapeHitCalculator extends HitCalculator {
ShapeHitCalculator(this.element, this.rect, this.rotation);

@override
bool hit(Rect rect) {
bool hit(Rect rect, {bool full = false}) {
if (!this.rect.inflate(element.property.strokeWidth).overlaps(rect)) {
return false;
}
Expand All @@ -215,6 +215,9 @@ class ShapeHitCalculator extends HitCalculator {
tl,
bl,
);
if (full) {
return lrt && tbr && lrb && tbl;
}
return lrt || tbr || lrb || tbl;
}

Expand All @@ -238,7 +241,7 @@ class ShapeHitCalculator extends HitCalculator {
}

@override
bool hitPolygon(List<ui.Offset> polygon) {
bool hitPolygon(List<ui.Offset> polygon, {bool full = false}) {
final center = rect.center;
// use isPointInPolygon
switch (element.property.shape) {
Expand All @@ -247,33 +250,49 @@ class ShapeHitCalculator extends HitCalculator {
final right = Offset(rect.right, center.dy).rotate(center, rotation);
final bottom = Offset(center.dx, rect.bottom).rotate(center, rotation);
final left = Offset(rect.left, center.dy).rotate(center, rotation);
return isPointInPolygon(polygon, top) ||
isPointInPolygon(polygon, right) ||
isPointInPolygon(polygon, bottom) ||
isPointInPolygon(polygon, left) ||
isPointInPolygon(polygon, center);
final isTop = isPointInPolygon(polygon, top);
final isRight = isPointInPolygon(polygon, right);
final isBottom = isPointInPolygon(polygon, bottom);
final isLeft = isPointInPolygon(polygon, left);
final isCenter = isPointInPolygon(polygon, center);
if (full) {
return isTop && isRight && isBottom && isLeft && isCenter;
}
return isTop || isRight || isBottom || isLeft || isCenter;
case LineShape _:
return isPointInPolygon(polygon,
element.firstPosition.toOffset().rotate(center, rotation)) ||
isPointInPolygon(polygon,
element.secondPosition.toOffset().rotate(center, rotation));
final isFirst = isPointInPolygon(
polygon, element.firstPosition.toOffset().rotate(center, rotation));
final isSecond = isPointInPolygon(polygon,
element.secondPosition.toOffset().rotate(center, rotation));
if (full) {
return isFirst && isSecond;
}
return isFirst || isSecond;
case RectangleShape _:
final topLeft = rect.topLeft.rotate(center, rotation);
final topRight = rect.topRight.rotate(center, rotation);
final bottomLeft = rect.bottomLeft.rotate(center, rotation);
final bottomRight = rect.bottomRight.rotate(center, rotation);
return isPointInPolygon(polygon, topLeft) ||
isPointInPolygon(polygon, topRight) ||
isPointInPolygon(polygon, bottomLeft) ||
isPointInPolygon(polygon, bottomRight) ||
isPointInPolygon(polygon, center);
final isTopLeft = isPointInPolygon(polygon, topLeft);
final isTopRight = isPointInPolygon(polygon, topRight);
final isBottomLeft = isPointInPolygon(polygon, bottomLeft);
final isBottomRight = isPointInPolygon(polygon, bottomRight);
if (full) {
return isTopLeft && isTopRight && isBottomLeft && isBottomRight;
}
return isTopLeft || isTopRight || isBottomLeft || isBottomRight;
case TriangleShape _:
final firstPosition =
element.firstPosition.toOffset().rotate(center, rotation);
final secondPosition =
element.secondPosition.toOffset().rotate(center, rotation);
return isPointInPolygon(polygon, firstPosition) ||
isPointInPolygon(polygon, secondPosition);
final isFirst = isPointInPolygon(polygon, firstPosition);
final isSecond = isPointInPolygon(polygon, secondPosition);
final isCenter = isPointInPolygon(polygon, center);
if (full) {
return isFirst && isSecond && isCenter;
}
return isFirst || isSecond || isCenter;
}
}
}
38 changes: 30 additions & 8 deletions app/lib/renderers/renderer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,45 @@ class DefaultHitCalculator extends HitCalculator {
DefaultHitCalculator(this.rect, this.rotation);

@override
bool hit(Rect rect) => this.rect?.overlaps(rect) ?? false;
bool hit(Rect rect, {bool full = false}) {
final element = this.rect;
if (element == null) return false;
if (full) {
return element.top >= rect.top &&
element.left >= rect.left &&
element.right <= rect.right &&
element.bottom <= rect.bottom;
}
return element.overlaps(rect);
}

@override
bool hitPolygon(List<ui.Offset> polygon) {
bool hitPolygon(List<ui.Offset> polygon, {bool full = false}) {
if (rect == null) return false;
final center = rect!.center;
return isPointInPolygon(polygon, center) ||
isPointInPolygon(polygon, rect!.topLeft.rotate(center, rotation)) ||
isPointInPolygon(polygon, rect!.topRight.rotate(center, rotation)) ||
isPointInPolygon(polygon, rect!.bottomLeft.rotate(center, rotation)) ||
final isCenter = isPointInPolygon(polygon, center);
final isTopLeft =
isPointInPolygon(polygon, rect!.topLeft.rotate(center, rotation));
final isTopRight =
isPointInPolygon(polygon, rect!.topRight.rotate(center, rotation));
final isBottomLeft =
isPointInPolygon(polygon, rect!.bottomLeft.rotate(center, rotation));
final isBottomRight =
isPointInPolygon(polygon, rect!.bottomRight.rotate(center, rotation));
if (full) {
return isCenter &&
isTopLeft &&
isTopRight &&
isBottomLeft &&
isBottomRight;
}
return isCenter || isTopLeft || isTopRight || isBottomLeft || isBottomRight;
}
}

abstract class HitCalculator {
bool hit(Rect rect);
bool hitPolygon(List<Offset> polygon);
bool hit(Rect rect, {bool full = false});
bool hitPolygon(List<Offset> polygon, {bool full = false});

bool isPointInPolygon(List<Offset> polygon, Offset testPoint) {
bool result = false;
Expand Down
8 changes: 4 additions & 4 deletions app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -482,19 +482,19 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "0dea6f8f827ca8ae34a2260824599537f78c1cb3"
resolved-ref: "0dea6f8f827ca8ae34a2260824599537f78c1cb3"
ref: bb3b74ea95dcb133a19bf9a00942355030961b6e
resolved-ref: bb3b74ea95dcb133a19bf9a00942355030961b6e
url: "https://github.com/rydmike/flex_color_scheme"
source: git
version: "8.0.0-dev.1"
flex_seed_scheme:
dependency: transitive
description:
name: flex_seed_scheme
sha256: "86470c8dc470f55dd3e28a6d30e3253a1c176df32903263d7daeabfc0c77dbd4"
sha256: "7d97ba5c20f0e5cb1e3e2c17c865e1f797d129de31fc1f75d2dcce9470d6373c"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
version: "3.3.0"
flutter:
dependency: "direct main"
description: flutter
Expand Down
2 changes: 1 addition & 1 deletion app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ dependencies:
flex_color_scheme:
git:
url: https://github.com/rydmike/flex_color_scheme
ref: 0dea6f8f827ca8ae34a2260824599537f78c1cb3
ref: bb3b74ea95dcb133a19bf9a00942355030961b6e
json_annotation: ^4.9.0
path: ^1.8.3
printing: ^5.13.1
Expand Down
Loading

0 comments on commit 17e37d3

Please sign in to comment.