Skip to content

Commit f99d12c

Browse files
SaadArdatiBirjuVachhani
authored andcommitted
🔧 (WIP) Continue GestureDetector refactor & add enabledHandles and visibleHandles set for granular handle control.
1 parent 085b6a0 commit f99d12c

File tree

3 files changed

+217
-206
lines changed

3 files changed

+217
-206
lines changed

packages/flutter_box_transform/lib/src/transformable_box.dart

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ typedef RectDragUpdateEvent = void Function(
3636
);
3737

3838
/// A callback that is called when the box ends a drag operation.
39-
/// [event] is either [PointerUpEvent] or [PointerCancelEvent].
4039
typedef RectDragEndEvent = void Function(
4140
DragEndDetails event,
4241
);
4342

43+
/// A callback that is called when the box cancels a drag operation.
44+
typedef RectDragCancelEvent = void Function();
45+
4446
/// A callback that is called when the box begins a resize operation.
4547
typedef RectResizeStart = void Function(
4648
HandlePosition handle,
@@ -54,30 +56,31 @@ typedef RectResizeUpdateEvent = void Function(
5456
);
5557

5658
/// A callback that is called when the box ends a resize operation.
57-
/// [event] is either [PointerUpEvent] or [PointerCancelEvent].
5859
typedef RectResizeEnd = void Function(
5960
HandlePosition handle,
6061
DragEndDetails event,
6162
);
6263

64+
/// A callback that is called when the box cancels a resize operation.
65+
typedef RectResizeCancel = void Function(
66+
HandlePosition handle,
67+
);
68+
6369
/// A callback that is called when the box reaches a terminal edge when
6470
/// resizing.
65-
/// [event] is either [PointerUpEvent] or [PointerCancelEvent].
6671
typedef TerminalEdgeEvent = void Function(
6772
bool reached,
6873
);
6974

7075
/// A callback that is called when the box reaches a minimum or maximum size
7176
/// when resizing a specific axis.
72-
/// [event] is either [PointerUpEvent] or [PointerCancelEvent].
7377
typedef TerminalAxisEvent = void Function(
7478
bool reachedMin,
7579
bool reachedMax,
7680
);
7781

7882
/// A callback that is called when the box reaches a minimum or maximum size
7983
/// when resizing.
80-
/// [event] is either [PointerUpEvent] or [PointerCancelEvent].
8184
typedef TerminalEvent = void Function(
8285
bool reachedMinWidth,
8386
bool reachedMaxWidth,
@@ -142,6 +145,14 @@ class TransformableBox extends StatefulWidget {
142145
/// The default value is 24 pixels in diameter.
143146
final double handleTapSize;
144147

148+
/// A set containing which handles to enable.
149+
final Set<HandlePosition> enabledHandles;
150+
151+
/// A set containing which handles to show. This is different from
152+
/// [enabledHandles] in that it will show the handle, but it will not be
153+
/// enabled for interaction.
154+
final Set<HandlePosition> visibleHandles;
155+
145156
/// The initial box that will be used to position set the initial size of
146157
/// the [TransformableBox] widget.
147158
///
@@ -182,16 +193,18 @@ class TransformableBox extends StatefulWidget {
182193
final BoxConstraints constraints;
183194

184195
/// Whether the box is resizable or not. Setting this to false will disable
185-
/// all resizing operations.
196+
/// all resizing operations. This is a convenience parameter that will ignore
197+
/// the [enabledHandles] parameter and set all handles to disabled.
186198
final bool resizable;
187199

188-
/// Whether the box should hide the corner/side resize controls when [resizable] is
189-
/// false.
200+
/// Whether the box should hide the corner/side resize controls when
201+
/// [resizable] is false. This is a convenience parameter that will ignore
202+
/// the [visibleHandles] parameter and set all handles to hidden.
190203
final bool hideHandlesWhenNotResizable;
191204

192205
/// Whether the box is movable or not. Setting this to false will disable
193206
/// all moving operations.
194-
final bool movable;
207+
final bool draggable;
195208

196209
/// Whether to allow flipping of the box while resizing. If this is set to
197210
/// true, the box will flip when the user drags the handles to opposite
@@ -228,9 +241,13 @@ class TransformableBox extends StatefulWidget {
228241
final RectDragUpdateEvent? onDragUpdate;
229242

230243
/// A callback that is called every time the [TransformableBox] is completes
231-
/// its drag operation via pointer up or cancel events.
244+
/// its drag operation via the pan end event.
232245
final RectDragEndEvent? onDragEnd;
233246

247+
/// A callback that is called every time the [TransformableBox] cancels
248+
/// its drag operation via the pan cancel event.
249+
final RectDragCancelEvent? onDragCancel;
250+
234251
/// A callback function that triggers when the box is about to start resizing.
235252
final RectResizeStart? onResizeStart;
236253

@@ -245,6 +262,9 @@ class TransformableBox extends StatefulWidget {
245262
/// A callback function that triggers when the box is about to end resizing.
246263
final RectResizeEnd? onResizeEnd;
247264

265+
/// A callback function that triggers when the box cancels resizing.
266+
final RectResizeCancel? onResizeCancel;
267+
248268
/// A callback function that triggers when the box reaches its minimum width
249269
/// when resizing.
250270
final TerminalEdgeEvent? onMinWidthReached;
@@ -296,6 +316,8 @@ class TransformableBox extends StatefulWidget {
296316
this.allowContentFlipping = true,
297317
this.hideHandlesWhenNotResizable = true,
298318
this.handleAlignment = HandleAlignment.center,
319+
this.enabledHandles = const {...HandlePosition.values},
320+
this.visibleHandles = const {...HandlePosition.values},
299321

300322
// Raw values.
301323
Rect? rect,
@@ -306,7 +328,7 @@ class TransformableBox extends StatefulWidget {
306328

307329
// Additional controls.
308330
this.resizable = true,
309-
this.movable = true,
331+
this.draggable = true,
310332
this.allowFlippingWhileResizing = true,
311333

312334
// Either resize or drag triggers.
@@ -316,11 +338,13 @@ class TransformableBox extends StatefulWidget {
316338
this.onResizeStart,
317339
this.onResizeUpdate,
318340
this.onResizeEnd,
341+
this.onResizeCancel,
319342

320343
// Drag Events.
321344
this.onDragStart,
322345
this.onDragUpdate,
323346
this.onDragEnd,
347+
this.onDragCancel,
324348

325349
// Terminal update events.
326350
this.onMinWidthReached,
@@ -369,8 +393,6 @@ class _TransformableBoxState extends State<TransformableBox> {
369393
constraints: widget.constraints,
370394
resizeModeResolver: widget.resizeModeResolver,
371395
allowFlippingWhileResizing: widget.allowFlippingWhileResizing,
372-
resizable: widget.resizable,
373-
movable: widget.movable,
374396
);
375397
}
376398
}
@@ -395,8 +417,6 @@ class _TransformableBoxState extends State<TransformableBox> {
395417
constraints: widget.constraints,
396418
resizeModeResolver: widget.resizeModeResolver,
397419
allowFlippingWhileResizing: widget.allowFlippingWhileResizing,
398-
resizable: widget.resizable,
399-
movable: widget.movable,
400420
);
401421
}
402422

@@ -432,14 +452,6 @@ class _TransformableBoxState extends State<TransformableBox> {
432452
shouldRecalculateSize = true;
433453
}
434454

435-
if (oldWidget.resizable != widget.resizable) {
436-
controller.setResizable(widget.resizable, notify: false);
437-
}
438-
439-
if (oldWidget.movable != widget.movable) {
440-
controller.setMovable(widget.movable, notify: false);
441-
}
442-
443455
if (oldWidget.allowFlippingWhileResizing !=
444456
widget.allowFlippingWhileResizing) {
445457
controller.setAllowFlippingWhileResizing(
@@ -519,6 +531,18 @@ class _TransformableBoxState extends State<TransformableBox> {
519531
widget.onTerminalSizeReached?.call(false, false, false, false);
520532
}
521533

534+
void onHandlePanCancel(HandlePosition handle) {
535+
controller.onResizeEnd();
536+
widget.onResizeCancel?.call(handle);
537+
widget.onMinWidthReached?.call(false);
538+
widget.onMaxWidthReached?.call(false);
539+
widget.onMinHeightReached?.call(false);
540+
widget.onMaxHeightReached?.call(false);
541+
widget.onTerminalWidthReached?.call(false, false);
542+
widget.onTerminalHeightReached?.call(false, false);
543+
widget.onTerminalSizeReached?.call(false, false, false, false);
544+
}
545+
522546
/// Called when the box drag event starts.
523547
void onDragPanStart(DragStartDetails event) {
524548
controller.onDragStart(event.localPosition);
@@ -541,6 +565,11 @@ class _TransformableBoxState extends State<TransformableBox> {
541565
widget.onDragEnd?.call(event);
542566
}
543567

568+
void onDragPanCancel() {
569+
controller.onDragEnd();
570+
widget.onDragCancel?.call();
571+
}
572+
544573
@override
545574
Widget build(BuildContext context) {
546575
final Flip flip = controller.flip;
@@ -552,13 +581,13 @@ class _TransformableBoxState extends State<TransformableBox> {
552581
child: widget.contentBuilder(context, rect, flip),
553582
);
554583

555-
if (controller.movable) {
584+
if (widget.draggable) {
556585
content = GestureDetector(
557586
behavior: HitTestBehavior.opaque,
558587
onPanStart: onDragPanStart,
559588
onPanUpdate: onDragPanUpdate,
560589
onPanEnd: onDragPanEnd,
561-
// onPanCancel: onDragPointerEnd,
590+
onPanCancel: onDragPanCancel,
562591
child: content,
563592
);
564593
}
@@ -576,32 +605,32 @@ class _TransformableBoxState extends State<TransformableBox> {
576605
height: rect.height,
577606
child: content,
578607
),
579-
if (controller.resizable || !widget.hideHandlesWhenNotResizable)
580-
for (final handle in HandlePosition.corners)
608+
if (widget.resizable || !widget.hideHandlesWhenNotResizable)
609+
for (final handle
610+
in widget.visibleHandles.where((handle) => handle.isDiagonal))
581611
_CornerHandleWidget(
582612
key: ValueKey(handle),
583613
handlePosition: handle,
584614
handleTapSize: widget.handleTapSize,
585-
resizable: controller.resizable,
615+
enabled: widget.enabledHandles.contains(handle),
586616
onPanStart: (event) => onHandlePanStart(event, handle),
587-
onPanUpdate: (event) =>
588-
onHandlePanUpdate(event, handle),
617+
onPanUpdate: (event) => onHandlePanUpdate(event, handle),
589618
onPanEnd: (event) => onHandlePanEnd(event, handle),
590-
// onPanCancel: (event) => onHandlePanCancel(event, handle),
619+
onPanCancel: () => onHandlePanCancel(handle),
591620
builder: widget.cornerHandleBuilder,
592621
),
593-
if (controller.resizable || !widget.hideHandlesWhenNotResizable)
594-
for (final handle in HandlePosition.sides)
622+
if (widget.resizable || !widget.hideHandlesWhenNotResizable)
623+
for (final handle
624+
in widget.visibleHandles.where((handle) => handle.isSide))
595625
_SideHandleWidget(
596626
key: ValueKey(handle),
597627
handlePosition: handle,
598628
handleTapSize: widget.handleTapSize,
599-
resizable: controller.resizable,
629+
enabled: widget.enabledHandles.contains(handle),
600630
onPanStart: (event) => onHandlePanStart(event, handle),
601-
onPanUpdate: (event) =>
602-
onHandlePanUpdate(event, handle),
631+
onPanUpdate: (event) => onHandlePanUpdate(event, handle),
603632
onPanEnd: (event) => onHandlePanEnd(event, handle),
604-
// onPanCancel: (event) => onHandlePanCancel(event, handle),
633+
onPanCancel: () => onHandlePanCancel(handle),
605634
builder: widget.sideHandleBuilder,
606635
),
607636
],
@@ -635,7 +664,7 @@ class _CornerHandleWidget extends StatelessWidget {
635664
final GestureDragCancelCallback? onPanCancel;
636665

637666
/// Whether the handle is resizable.
638-
final bool resizable;
667+
final bool enabled;
639668

640669
/// Creates a new handle widget.
641670
_CornerHandleWidget({
@@ -647,13 +676,13 @@ class _CornerHandleWidget extends StatelessWidget {
647676
this.onPanUpdate,
648677
this.onPanEnd,
649678
this.onPanCancel,
650-
required this.resizable,
679+
required this.enabled,
651680
}) : assert(handlePosition.isDiagonal, 'A corner handle must be diagonal.');
652681

653682
@override
654683
Widget build(BuildContext context) {
655684
Widget child = builder(context, handlePosition);
656-
if (resizable) {
685+
if (enabled) {
657686
child = GestureDetector(
658687
behavior: HitTestBehavior.opaque,
659688
onPanStart: onPanStart,
@@ -718,7 +747,7 @@ class _SideHandleWidget extends StatelessWidget {
718747
final GestureDragCancelCallback? onPanCancel;
719748

720749
/// Whether the handle is resizable.
721-
final bool resizable;
750+
final bool enabled;
722751

723752
/// Creates a new handle widget.
724753
_SideHandleWidget({
@@ -730,13 +759,13 @@ class _SideHandleWidget extends StatelessWidget {
730759
this.onPanUpdate,
731760
this.onPanEnd,
732761
this.onPanCancel,
733-
required this.resizable,
762+
required this.enabled,
734763
}) : assert(handlePosition.isSide, 'A cardinal handle must be cardinal.');
735764

736765
@override
737766
Widget build(BuildContext context) {
738767
Widget child = builder(context, handlePosition);
739-
if (resizable) {
768+
if (enabled) {
740769
child = GestureDetector(
741770
behavior: HitTestBehavior.opaque,
742771
onPanStart: onPanStart,

0 commit comments

Comments
 (0)