Restore FractionalOffset operators (#12368)
These now act the way they used to act if both operands are FractionalOffsets. Once you mix in some other AlignmentGeometry objects, everything gets converted to the AlignmentGeometry coordinate system.
This commit is contained in:
parent
7bfa3c5676
commit
31b6ac049c
@ -540,7 +540,7 @@ class AlignmentDirectional extends AlignmentGeometry {
|
||||
if (start == 1.0 && y == 1.0)
|
||||
return 'AlignmentDirectional.bottomEnd';
|
||||
return 'AlignmentDirectional(${start.toStringAsFixed(1)}, '
|
||||
'${y.toStringAsFixed(1)})';
|
||||
'${y.toStringAsFixed(1)})';
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -21,6 +21,31 @@ import 'basic_types.dart';
|
||||
/// The [FractionalOffset] class specifies offsets in terms of a distance from
|
||||
/// the top left, regardless of the [TextDirection].
|
||||
///
|
||||
/// ## Design discussion
|
||||
///
|
||||
/// [FractionalOffset] and [Alignment] are two different representations of the
|
||||
/// same information: the location within a rectangle relative to the size of
|
||||
/// the rectangle. The difference between the two classes is in the coordinate
|
||||
/// system they use to represent the location.
|
||||
///
|
||||
/// [FractionalOffset] uses a coordinate system with an origin in the top-left
|
||||
/// corner of the rectangle whereas [Alignment] uses a coordinate system with an
|
||||
/// origin in the center of the rectangle.
|
||||
///
|
||||
/// Historically, [FractionalOffset] predates [Alignment]. When we attempted to
|
||||
/// make a version of [FractionalOffset] that adapted to the [TextDirection], we
|
||||
/// ran into difficulty because placing the origin in the top-left corner
|
||||
/// introduced a left-to-right bias that was hard to remove.
|
||||
///
|
||||
/// By placing the origin in the center, [Alignment] and [AlignmentDirectional]
|
||||
/// are able to use the same origin, which means we can use a linear function to
|
||||
/// resolve an [AlignmentDirectional] into an [Alignment] in both
|
||||
/// [TextDirection.rtl] and [TextDirection.ltr].
|
||||
///
|
||||
/// [Alignment] is better for most purposes than [FractionalOffset] and should
|
||||
/// be used instead of [FractionalOffset]. We continue to implement
|
||||
/// [FractionalOffset] to support code that predates [Alignment].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Alignment], which uses a coordinate system based on the center of the
|
||||
@ -108,6 +133,47 @@ class FractionalOffset extends Alignment {
|
||||
/// The bottom right corner.
|
||||
static const FractionalOffset bottomRight = const FractionalOffset(1.0, 1.0);
|
||||
|
||||
@override
|
||||
Alignment operator -(Alignment other) {
|
||||
if (other is! FractionalOffset)
|
||||
return super - other;
|
||||
final FractionalOffset typedOther = other;
|
||||
return new FractionalOffset(dx - typedOther.dx, dy - typedOther.dy);
|
||||
}
|
||||
|
||||
@override
|
||||
Alignment operator +(Alignment other) {
|
||||
if (other is! FractionalOffset)
|
||||
return super + other;
|
||||
final FractionalOffset typedOther = other;
|
||||
return new FractionalOffset(dx + typedOther.dx, dy + typedOther.dy);
|
||||
}
|
||||
|
||||
@override
|
||||
FractionalOffset operator -() {
|
||||
return new FractionalOffset(-dx, -dy);
|
||||
}
|
||||
|
||||
@override
|
||||
FractionalOffset operator *(double other) {
|
||||
return new FractionalOffset(dx * other, dy * other);
|
||||
}
|
||||
|
||||
@override
|
||||
FractionalOffset operator /(double other) {
|
||||
return new FractionalOffset(dx / other, dy / other);
|
||||
}
|
||||
|
||||
@override
|
||||
FractionalOffset operator ~/(double other) {
|
||||
return new FractionalOffset((dx ~/ other).toDouble(), (dy ~/ other).toDouble());
|
||||
}
|
||||
|
||||
@override
|
||||
FractionalOffset operator %(double other) {
|
||||
return new FractionalOffset(dx % other, dy % other);
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two [FractionalOffset]s.
|
||||
///
|
||||
/// If either is null, this function interpolates from [FractionalOffset.center].
|
||||
@ -120,4 +186,10 @@ class FractionalOffset extends Alignment {
|
||||
return new FractionalOffset(ui.lerpDouble(a.dx, 0.5, t), ui.lerpDouble(a.dy, 0.5, t));
|
||||
return new FractionalOffset(ui.lerpDouble(a.dx, b.dx, t), ui.lerpDouble(a.dy, b.dy, t));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FractionalOffset(${dx.toStringAsFixed(1)}, '
|
||||
'${dy.toStringAsFixed(1)})';
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,20 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('FractionalOffset control test', () {
|
||||
const FractionalOffset offset = const FractionalOffset(0.5, 0.25);
|
||||
const FractionalOffset a = const FractionalOffset(0.5, 0.25);
|
||||
const FractionalOffset b = const FractionalOffset(1.25, 0.75);
|
||||
|
||||
expect(offset, hasOneLineDescription);
|
||||
expect(offset.hashCode, equals(const FractionalOffset(0.5, 0.25).hashCode));
|
||||
expect(a, hasOneLineDescription);
|
||||
expect(a.hashCode, equals(const FractionalOffset(0.5, 0.25).hashCode));
|
||||
expect(a.toString(), equals('FractionalOffset(0.5, 0.3)'));
|
||||
|
||||
expect(offset / 2.0, const Alignment(0.0, -0.25));
|
||||
expect(offset ~/ 2.0, Alignment.center);
|
||||
expect(offset % 5.0, const Alignment(0.0, 4.5));
|
||||
expect(-a, const FractionalOffset(-0.5, -0.25));
|
||||
expect(a - b, const FractionalOffset(-0.75, -0.5));
|
||||
expect(a + b, const FractionalOffset(1.75, 1.0));
|
||||
expect(a * 2.0, const FractionalOffset(1.0, 0.5));
|
||||
expect(a / 2.0, const FractionalOffset(0.25, 0.125));
|
||||
expect(a ~/ 2.0, const FractionalOffset(0.0, 0.0));
|
||||
expect(a % 5.0, const FractionalOffset(0.5, 0.25));
|
||||
});
|
||||
|
||||
test('FractionalOffset.lerp()', () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user