Unverified Commit 0ad0a56e authored by Nazareno Cavazzon's avatar Nazareno Cavazzon Committed by GitHub

panningDirection parameter added to InteractiveViewer (#109014)

parent 8074811c
......@@ -34,7 +34,7 @@ class MyStatelessWidget extends StatelessWidget {
const int columnCount = 6;
return InteractiveViewer(
alignPanAxis: true,
panAxis: PanAxis.aligned,
constrained: false,
scaleEnabled: false,
child: Table(
......
......@@ -67,7 +67,12 @@ class InteractiveViewer extends StatefulWidget {
InteractiveViewer({
super.key,
this.clipBehavior = Clip.hardEdge,
@Deprecated(
'Use panAxis instead. '
'This feature was deprecated after v3.3.0-0.5.pre.',
)
this.alignPanAxis = false,
this.panAxis = PanAxis.free,
this.boundaryMargin = EdgeInsets.zero,
this.constrained = true,
// These default scale values were eyeballed as reasonable limits for common
......@@ -83,6 +88,7 @@ class InteractiveViewer extends StatefulWidget {
this.transformationController,
required Widget this.child,
}) : assert(alignPanAxis != null),
assert(panAxis != null),
assert(child != null),
assert(constrained != null),
assert(minScale != null),
......@@ -114,7 +120,12 @@ class InteractiveViewer extends StatefulWidget {
InteractiveViewer.builder({
super.key,
this.clipBehavior = Clip.hardEdge,
@Deprecated(
'Use panAxis instead. '
'This feature was deprecated after v3.3.0-0.5.pre.',
)
this.alignPanAxis = false,
this.panAxis = PanAxis.free,
this.boundaryMargin = EdgeInsets.zero,
// These default scale values were eyeballed as reasonable limits for common
// use cases.
......@@ -128,7 +139,7 @@ class InteractiveViewer extends StatefulWidget {
this.scaleFactor = 200.0,
this.transformationController,
required InteractiveViewerWidgetBuilder this.builder,
}) : assert(alignPanAxis != null),
}) : assert(panAxis != null),
assert(builder != null),
assert(minScale != null),
assert(minScale > 0),
......@@ -158,6 +169,8 @@ class InteractiveViewer extends StatefulWidget {
/// Defaults to [Clip.hardEdge].
final Clip clipBehavior;
/// This property is deprecated, please use [panAxis] instead.
///
/// If true, panning is only allowed in the direction of the horizontal axis
/// or the vertical axis.
///
......@@ -169,8 +182,25 @@ class InteractiveViewer extends StatefulWidget {
/// See also:
/// * [constrained], which has an example of creating a table that uses
/// alignPanAxis.
@Deprecated(
'Use panAxis instead. '
'This feature was deprecated after v3.3.0-0.5.pre.',
)
final bool alignPanAxis;
/// When set to [PanAxis.aligned], panning is only allowed in the horizontal
/// axis or the vertical axis, diagonal panning is not allowed.
///
/// When set to [PanAxis.vertical] or [PanAxis.horizontal] panning is only
/// allowed in the specified axis. For example, if set to [PanAxis.vertical],
/// panning will only be allowed in the vertical axis. And if set to [PanAxis.horizontal],
/// panning will only be allowed in the horizontal axis.
///
/// When set to [PanAxis.free] panning is allowed in all directions.
///
/// Defaults to [PanAxis.free].
final PanAxis panAxis;
/// A margin for the visible boundaries of the child.
///
/// Any transformation that results in the viewport being able to view outside
......@@ -507,7 +537,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
final GlobalKey _parentKey = GlobalKey();
Animation<Offset>? _animation;
late AnimationController _controller;
Axis? _panAxis; // Used with alignPanAxis.
Axis? _currentAxis; // Used with panAxis.
Offset? _referenceFocalPoint; // Point where the current gesture began.
double? _scaleStart; // Scale value at start of scaling gesture.
double? _rotationStart = 0.0; // Rotation at start of rotation gesture.
......@@ -566,9 +596,26 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
return matrix.clone();
}
final Offset alignedTranslation = widget.alignPanAxis && _panAxis != null
? _alignAxis(translation, _panAxis!)
: translation;
late final Offset alignedTranslation;
if (_currentAxis != null) {
switch(widget.panAxis){
case PanAxis.horizontal:
alignedTranslation = _alignAxis(translation, Axis.horizontal);
break;
case PanAxis.vertical:
alignedTranslation = _alignAxis(translation, Axis.vertical);
break;
case PanAxis.aligned:
alignedTranslation = _alignAxis(translation, _currentAxis!);
break;
case PanAxis.free:
alignedTranslation = translation;
break;
}
} else {
alignedTranslation = translation;
}
final Matrix4 nextMatrix = matrix.clone()..translate(
alignedTranslation.dx,
......@@ -734,7 +781,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
}
_gestureType = null;
_panAxis = null;
_currentAxis = null;
_scaleStart = _transformationController!.value.getMaxScaleOnAxis();
_referenceFocalPoint = _transformationController!.toScene(
details.localFocalPoint,
......@@ -825,7 +872,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
widget.onInteractionUpdate?.call(details);
return;
}
_panAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
_currentAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
// Translate so that the same point in the scene is underneath the
// focal point before and after the movement.
final Offset translationChange = focalPointScene - _referenceFocalPoint!;
......@@ -853,13 +900,13 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
_controller.reset();
if (!_gestureIsSupported(_gestureType)) {
_panAxis = null;
_currentAxis = null;
return;
}
// If the scale ended with enough velocity, animate inertial movement.
if (_gestureType != _GestureType.pan || details.velocity.pixelsPerSecond.distance < kMinFlingVelocity) {
_panAxis = null;
_currentAxis = null;
return;
}
......@@ -947,7 +994,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
// Handle inertia drag animation.
void _onAnimate() {
if (!_controller.isAnimating) {
_panAxis = null;
_currentAxis = null;
_animation?.removeListener(_onAnimate);
_animation = null;
_controller.reset();
......@@ -1296,3 +1343,20 @@ Axis? _getPanAxis(Offset point1, Offset point2) {
final double y = point2.dy - point1.dy;
return x.abs() > y.abs() ? Axis.horizontal : Axis.vertical;
}
/// This enum is used to specify the behavior of the [InteractiveViewer] when
/// the user drags the viewport.
enum PanAxis{
/// The user can only pan the viewport along the horizontal axis.
horizontal,
/// The user can only pan the viewport along the vertical axis.
vertical,
/// The user can pan the viewport along the horizontal and vertical axes
/// but not diagonally.
aligned,
/// The user can pan the viewport freely in any direction.
free,
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment