@@ -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] .
4039typedef 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.
4547typedef 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] .
5859typedef 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] .
6671typedef 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] .
7377typedef 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] .
8184typedef 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