Unverified Commit e8c94210 authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

migrate part of painting to nullsafety (#62951)

parent 2c1b95b9
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
...@@ -33,7 +32,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -33,7 +32,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
final double scale; final double scale;
@override @override
final Map<String, String> headers; final Map<String, String>? headers;
@override @override
Future<NetworkImage> obtainKey(image_provider.ImageConfiguration configuration) { Future<NetworkImage> obtainKey(image_provider.ImageConfiguration configuration) {
...@@ -71,7 +70,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -71,7 +70,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
HttpClient client = _sharedHttpClient; HttpClient client = _sharedHttpClient;
assert(() { assert(() {
if (debugNetworkImageHttpClientProvider != null) if (debugNetworkImageHttpClientProvider != null)
client = debugNetworkImageHttpClientProvider(); client = debugNetworkImageHttpClientProvider!();
return true; return true;
}()); }());
return client; return client;
...@@ -102,7 +101,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -102,7 +101,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
final Uint8List bytes = await consolidateHttpClientResponseBytes( final Uint8List bytes = await consolidateHttpClientResponseBytes(
response, response,
onBytesReceived: (int cumulative, int total) { onBytesReceived: (int cumulative, int? total) {
chunkEvents.add(ImageChunkEvent( chunkEvents.add(ImageChunkEvent(
cumulativeBytesLoaded: cumulative, cumulativeBytesLoaded: cumulative,
expectedTotalBytes: total, expectedTotalBytes: total,
...@@ -118,7 +117,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm ...@@ -118,7 +117,7 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
// have had a chance to track the key in the cache at all. // have had a chance to track the key in the cache at all.
// Schedule a microtask to give the cache a chance to add the key. // Schedule a microtask to give the cache a chance to add the key.
scheduleMicrotask(() { scheduleMicrotask(() {
PaintingBinding.instance.imageCache.evict(key); PaintingBinding.instance!.imageCache!.evict(key);
}); });
rethrow; rethrow;
} finally { } finally {
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'dart:ui' as ui; import 'dart:ui' as ui;
...@@ -33,7 +32,7 @@ class NetworkImage ...@@ -33,7 +32,7 @@ class NetworkImage
final double scale; final double scale;
@override @override
final Map<String, String> headers; final Map<String, String>? headers;
@override @override
Future<NetworkImage> obtainKey( Future<NetworkImage> obtainKey(
...@@ -58,9 +57,9 @@ class NetworkImage ...@@ -58,9 +57,9 @@ class NetworkImage
informationCollector: _imageStreamInformationCollector(key)); informationCollector: _imageStreamInformationCollector(key));
} }
InformationCollector _imageStreamInformationCollector( InformationCollector? _imageStreamInformationCollector(
image_provider.NetworkImage key) { image_provider.NetworkImage key) {
InformationCollector collector; InformationCollector? collector;
assert(() { assert(() {
collector = () { collector = () {
return <DiagnosticsNode>[ return <DiagnosticsNode>[
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math; import 'dart:math' as math;
...@@ -57,24 +56,24 @@ class BeveledRectangleBorder extends OutlinedBorder { ...@@ -57,24 +56,24 @@ class BeveledRectangleBorder extends OutlinedBorder {
} }
@override @override
ShapeBorder lerpFrom(ShapeBorder a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
assert(t != null); assert(t != null);
if (a is BeveledRectangleBorder) { if (a is BeveledRectangleBorder) {
return BeveledRectangleBorder( return BeveledRectangleBorder(
side: BorderSide.lerp(a.side, side, t), side: BorderSide.lerp(a.side, side, t),
borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t), borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t)!,
); );
} }
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
ShapeBorder lerpTo(ShapeBorder b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
assert(t != null); assert(t != null);
if (b is BeveledRectangleBorder) { if (b is BeveledRectangleBorder) {
return BeveledRectangleBorder( return BeveledRectangleBorder(
side: BorderSide.lerp(side, b.side, t), side: BorderSide.lerp(side, b.side, t),
borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t), borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t)!,
); );
} }
return super.lerpTo(b, t); return super.lerpTo(b, t);
...@@ -83,7 +82,7 @@ class BeveledRectangleBorder extends OutlinedBorder { ...@@ -83,7 +82,7 @@ class BeveledRectangleBorder extends OutlinedBorder {
/// Returns a copy of this RoundedRectangleBorder with the given fields /// Returns a copy of this RoundedRectangleBorder with the given fields
/// replaced with the new values. /// replaced with the new values.
@override @override
BeveledRectangleBorder copyWith({ BorderSide side, BorderRadius borderRadius }) { BeveledRectangleBorder copyWith({ BorderSide? side, BorderRadius? borderRadius }) {
return BeveledRectangleBorder( return BeveledRectangleBorder(
side: side ?? this.side, side: side ?? this.side,
borderRadius: borderRadius ?? this.borderRadius, borderRadius: borderRadius ?? this.borderRadius,
...@@ -120,17 +119,17 @@ class BeveledRectangleBorder extends OutlinedBorder { ...@@ -120,17 +119,17 @@ class BeveledRectangleBorder extends OutlinedBorder {
} }
@override @override
Path getInnerPath(Rect rect, { TextDirection textDirection }) { Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
return _getPath(borderRadius.resolve(textDirection).toRRect(rect).deflate(side.width)); return _getPath(borderRadius.resolve(textDirection).toRRect(rect).deflate(side.width));
} }
@override @override
Path getOuterPath(Rect rect, { TextDirection textDirection }) { Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return _getPath(borderRadius.resolve(textDirection).toRRect(rect)); return _getPath(borderRadius.resolve(textDirection).toRRect(rect));
} }
@override @override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) { void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
if (rect.isEmpty) if (rect.isEmpty)
return; return;
switch (side.style) { switch (side.style) {
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -130,7 +129,7 @@ abstract class BorderRadiusGeometry { ...@@ -130,7 +129,7 @@ abstract class BorderRadiusGeometry {
/// into a concrete [BorderRadius] using [resolve]. /// into a concrete [BorderRadius] using [resolve].
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadiusGeometry lerp(BorderRadiusGeometry a, BorderRadiusGeometry b, double t) { static BorderRadiusGeometry? lerp(BorderRadiusGeometry? a, BorderRadiusGeometry? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
...@@ -148,11 +147,11 @@ abstract class BorderRadiusGeometry { ...@@ -148,11 +147,11 @@ abstract class BorderRadiusGeometry {
/// * [BorderRadius], for which this is a no-op (returns itself). /// * [BorderRadius], for which this is a no-op (returns itself).
/// * [BorderRadiusDirectional], which flips the horizontal direction /// * [BorderRadiusDirectional], which flips the horizontal direction
/// based on the `direction` argument. /// based on the `direction` argument.
BorderRadius resolve(TextDirection direction); BorderRadius resolve(TextDirection? direction);
@override @override
String toString() { String toString() {
String visual, logical; String? visual, logical;
if (_topLeft == _topRight && if (_topLeft == _topRight &&
_topRight == _bottomLeft && _topRight == _bottomLeft &&
_bottomLeft == _bottomRight) { _bottomLeft == _bottomRight) {
...@@ -474,24 +473,24 @@ class BorderRadius extends BorderRadiusGeometry { ...@@ -474,24 +473,24 @@ class BorderRadius extends BorderRadiusGeometry {
/// If either is null, this function interpolates from [BorderRadius.zero]. /// If either is null, this function interpolates from [BorderRadius.zero].
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadius lerp(BorderRadius a, BorderRadius b, double t) { static BorderRadius? lerp(BorderRadius? a, BorderRadius? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b * t; return b! * t;
if (b == null) if (b == null)
return a * (1.0 - t); return a * (1.0 - t);
return BorderRadius.only( return BorderRadius.only(
topLeft: Radius.lerp(a.topLeft, b.topLeft, t), topLeft: Radius.lerp(a.topLeft, b.topLeft, t)!,
topRight: Radius.lerp(a.topRight, b.topRight, t), topRight: Radius.lerp(a.topRight, b.topRight, t)!,
bottomLeft: Radius.lerp(a.bottomLeft, b.bottomLeft, t), bottomLeft: Radius.lerp(a.bottomLeft, b.bottomLeft, t)!,
bottomRight: Radius.lerp(a.bottomRight, b.bottomRight, t), bottomRight: Radius.lerp(a.bottomRight, b.bottomRight, t)!,
); );
} }
@override @override
BorderRadius resolve(TextDirection direction) => this; BorderRadius resolve(TextDirection? direction) => this;
} }
/// An immutable set of radii for each corner of a rectangle, but with the /// An immutable set of radii for each corner of a rectangle, but with the
...@@ -691,26 +690,26 @@ class BorderRadiusDirectional extends BorderRadiusGeometry { ...@@ -691,26 +690,26 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
/// If either is null, this function interpolates from [BorderRadiusDirectional.zero]. /// If either is null, this function interpolates from [BorderRadiusDirectional.zero].
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderRadiusDirectional lerp(BorderRadiusDirectional a, BorderRadiusDirectional b, double t) { static BorderRadiusDirectional? lerp(BorderRadiusDirectional? a, BorderRadiusDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b * t; return b! * t;
if (b == null) if (b == null)
return a * (1.0 - t); return a * (1.0 - t);
return BorderRadiusDirectional.only( return BorderRadiusDirectional.only(
topStart: Radius.lerp(a.topStart, b.topStart, t), topStart: Radius.lerp(a.topStart, b.topStart, t)!,
topEnd: Radius.lerp(a.topEnd, b.topEnd, t), topEnd: Radius.lerp(a.topEnd, b.topEnd, t)!,
bottomStart: Radius.lerp(a.bottomStart, b.bottomStart, t), bottomStart: Radius.lerp(a.bottomStart, b.bottomStart, t)!,
bottomEnd: Radius.lerp(a.bottomEnd, b.bottomEnd, t), bottomEnd: Radius.lerp(a.bottomEnd, b.bottomEnd, t)!,
); );
} }
@override @override
BorderRadius resolve(TextDirection direction) { BorderRadius resolve(TextDirection? direction) {
assert(direction != null); assert(direction != null);
switch (direction) { switch (direction!) {
case TextDirection.rtl: case TextDirection.rtl:
return BorderRadius.only( return BorderRadius.only(
topLeft: topEnd, topLeft: topEnd,
...@@ -726,7 +725,6 @@ class BorderRadiusDirectional extends BorderRadiusGeometry { ...@@ -726,7 +725,6 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
bottomRight: bottomEnd, bottomRight: bottomEnd,
); );
} }
return null;
} }
} }
...@@ -838,9 +836,9 @@ class _MixedBorderRadius extends BorderRadiusGeometry { ...@@ -838,9 +836,9 @@ class _MixedBorderRadius extends BorderRadiusGeometry {
} }
@override @override
BorderRadius resolve(TextDirection direction) { BorderRadius resolve(TextDirection? direction) {
assert(direction != null); assert(direction != null);
switch (direction) { switch (direction!) {
case TextDirection.rtl: case TextDirection.rtl:
return BorderRadius.only( return BorderRadius.only(
topLeft: _topLeft + _topEnd, topLeft: _topLeft + _topEnd,
...@@ -856,6 +854,5 @@ class _MixedBorderRadius extends BorderRadiusGeometry { ...@@ -856,6 +854,5 @@ class _MixedBorderRadius extends BorderRadiusGeometry {
bottomRight: _bottomRight + _bottomEnd, bottomRight: _bottomRight + _bottomEnd,
); );
} }
return null;
} }
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' as ui show lerpDouble; import 'dart:ui' as ui show lerpDouble;
...@@ -130,9 +129,9 @@ class BorderSide { ...@@ -130,9 +129,9 @@ class BorderSide {
/// Creates a copy of this border but with the given fields replaced with the new values. /// Creates a copy of this border but with the given fields replaced with the new values.
BorderSide copyWith({ BorderSide copyWith({
Color color, Color? color,
double width, double? width,
BorderStyle style, BorderStyle? style,
}) { }) {
assert(width == null || width >= 0.0); assert(width == null || width >= 0.0);
return BorderSide( return BorderSide(
...@@ -186,7 +185,6 @@ class BorderSide { ...@@ -186,7 +185,6 @@ class BorderSide {
..strokeWidth = 0.0 ..strokeWidth = 0.0
..style = PaintingStyle.stroke; ..style = PaintingStyle.stroke;
} }
return null;
} }
/// Whether the two given [BorderSide]s can be merged using [new /// Whether the two given [BorderSide]s can be merged using [new
...@@ -219,12 +217,12 @@ class BorderSide { ...@@ -219,12 +217,12 @@ class BorderSide {
return a; return a;
if (t == 1.0) if (t == 1.0)
return b; return b;
final double width = ui.lerpDouble(a.width, b.width, t); final double width = ui.lerpDouble(a.width, b.width, t)!;
if (width < 0.0) if (width < 0.0)
return BorderSide.none; return BorderSide.none;
if (a.style == b.style) { if (a.style == b.style) {
return BorderSide( return BorderSide(
color: Color.lerp(a.color, b.color, t), color: Color.lerp(a.color, b.color, t)!,
width: width, width: width,
style: a.style, // == b.style style: a.style, // == b.style
); );
...@@ -247,7 +245,7 @@ class BorderSide { ...@@ -247,7 +245,7 @@ class BorderSide {
break; break;
} }
return BorderSide( return BorderSide(
color: Color.lerp(colorA, colorB, t), color: Color.lerp(colorA, colorB, t)!,
width: width, width: width,
style: BorderStyle.solid, style: BorderStyle.solid,
); );
...@@ -319,7 +317,7 @@ abstract class ShapeBorder { ...@@ -319,7 +317,7 @@ abstract class ShapeBorder {
/// The `reversed` argument is true if this object was the right operand of /// The `reversed` argument is true if this object was the right operand of
/// the `+` operator, and false if it was the left operand. /// the `+` operator, and false if it was the left operand.
@protected @protected
ShapeBorder add(ShapeBorder other, { bool reversed = false }) => null; ShapeBorder? add(ShapeBorder other, { bool reversed = false }) => null;
/// Creates a new border consisting of the two borders on either side of the /// Creates a new border consisting of the two borders on either side of the
/// operator. /// operator.
...@@ -382,7 +380,7 @@ abstract class ShapeBorder { ...@@ -382,7 +380,7 @@ abstract class ShapeBorder {
/// ///
/// Instead of calling this directly, use [ShapeBorder.lerp]. /// Instead of calling this directly, use [ShapeBorder.lerp].
@protected @protected
ShapeBorder lerpFrom(ShapeBorder a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a == null) if (a == null)
return scale(t); return scale(t);
return null; return null;
...@@ -414,7 +412,7 @@ abstract class ShapeBorder { ...@@ -414,7 +412,7 @@ abstract class ShapeBorder {
/// ///
/// Instead of calling this directly, use [ShapeBorder.lerp]. /// Instead of calling this directly, use [ShapeBorder.lerp].
@protected @protected
ShapeBorder lerpTo(ShapeBorder b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b == null) if (b == null)
return scale(1.0 - t); return scale(1.0 - t);
return null; return null;
...@@ -428,9 +426,9 @@ abstract class ShapeBorder { ...@@ -428,9 +426,9 @@ abstract class ShapeBorder {
/// and `b` after `t=0.5`. /// and `b` after `t=0.5`.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static ShapeBorder lerp(ShapeBorder a, ShapeBorder b, double t) { static ShapeBorder? lerp(ShapeBorder? a, ShapeBorder? b, double t) {
assert(t != null); assert(t != null);
ShapeBorder result; ShapeBorder? result;
if (b != null) if (b != null)
result = b.lerpFrom(a, t); result = b.lerpFrom(a, t);
if (result == null && a != null) if (result == null && a != null)
...@@ -457,7 +455,7 @@ abstract class ShapeBorder { ...@@ -457,7 +455,7 @@ abstract class ShapeBorder {
/// ///
/// * [getInnerPath], which creates the path for the inner edge. /// * [getInnerPath], which creates the path for the inner edge.
/// * [Path.contains], which can tell if an [Offset] is within a [Path]. /// * [Path.contains], which can tell if an [Offset] is within a [Path].
Path getOuterPath(Rect rect, { TextDirection textDirection }); Path getOuterPath(Rect rect, { TextDirection? textDirection });
/// Create a [Path] that describes the inner edge of the border. /// Create a [Path] that describes the inner edge of the border.
/// ///
...@@ -478,7 +476,7 @@ abstract class ShapeBorder { ...@@ -478,7 +476,7 @@ abstract class ShapeBorder {
/// ///
/// * [getOuterPath], which creates the path for the outer edge. /// * [getOuterPath], which creates the path for the outer edge.
/// * [Path.contains], which can tell if an [Offset] is within a [Path]. /// * [Path.contains], which can tell if an [Offset] is within a [Path].
Path getInnerPath(Rect rect, { TextDirection textDirection }); Path getInnerPath(Rect rect, { TextDirection? textDirection });
/// Paints the border within the given [Rect] on the given [Canvas]. /// Paints the border within the given [Rect] on the given [Canvas].
/// ///
...@@ -486,7 +484,7 @@ abstract class ShapeBorder { ...@@ -486,7 +484,7 @@ abstract class ShapeBorder {
/// has a text direction dependency (for example if it is expressed in terms /// has a text direction dependency (for example if it is expressed in terms
/// of "start" and "end" instead of "left" and "right"). It may be null if /// of "start" and "end" instead of "left" and "right"). It may be null if
/// the border will not need the text direction to paint itself. /// the border will not need the text direction to paint itself.
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }); void paint(Canvas canvas, Rect rect, { TextDirection? textDirection });
@override @override
String toString() { String toString() {
...@@ -548,7 +546,7 @@ class _CompoundBorder extends ShapeBorder { ...@@ -548,7 +546,7 @@ class _CompoundBorder extends ShapeBorder {
// border, and "merged" is the result of attempting to merge it with the // border, and "merged" is the result of attempting to merge it with the
// new border. If it's null, it couldn't be merged. // new border. If it's null, it couldn't be merged.
final ShapeBorder ours = reversed ? borders.last : borders.first; final ShapeBorder ours = reversed ? borders.last : borders.first;
final ShapeBorder merged = ours.add(other, reversed: reversed) final ShapeBorder? merged = ours.add(other, reversed: reversed)
?? other.add(ours, reversed: !reversed); ?? other.add(ours, reversed: !reversed);
if (merged != null) { if (merged != null) {
final List<ShapeBorder> result = <ShapeBorder>[...borders]; final List<ShapeBorder> result = <ShapeBorder>[...borders];
...@@ -574,27 +572,27 @@ class _CompoundBorder extends ShapeBorder { ...@@ -574,27 +572,27 @@ class _CompoundBorder extends ShapeBorder {
} }
@override @override
ShapeBorder lerpFrom(ShapeBorder a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
return _CompoundBorder.lerp(a, this, t); return _CompoundBorder.lerp(a, this, t);
} }
@override @override
ShapeBorder lerpTo(ShapeBorder b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
return _CompoundBorder.lerp(this, b, t); return _CompoundBorder.lerp(this, b, t);
} }
static _CompoundBorder lerp(ShapeBorder a, ShapeBorder b, double t) { static _CompoundBorder lerp(ShapeBorder? a, ShapeBorder? b, double t) {
assert(t != null); assert(t != null);
assert(a is _CompoundBorder || b is _CompoundBorder); // Not really necessary, but all call sites currently intend this. assert(a is _CompoundBorder || b is _CompoundBorder); // Not really necessary, but all call sites currently intend this.
final List<ShapeBorder> aList = a is _CompoundBorder ? a.borders : <ShapeBorder>[a]; final List<ShapeBorder?> aList = a is _CompoundBorder ? a.borders : <ShapeBorder?>[a];
final List<ShapeBorder> bList = b is _CompoundBorder ? b.borders : <ShapeBorder>[b]; final List<ShapeBorder?> bList = b is _CompoundBorder ? b.borders : <ShapeBorder?>[b];
final List<ShapeBorder> results = <ShapeBorder>[]; final List<ShapeBorder> results = <ShapeBorder>[];
final int length = math.max(aList.length, bList.length); final int length = math.max(aList.length, bList.length);
for (int index = 0; index < length; index += 1) { for (int index = 0; index < length; index += 1) {
final ShapeBorder localA = index < aList.length ? aList[index] : null; final ShapeBorder? localA = index < aList.length ? aList[index] : null;
final ShapeBorder localB = index < bList.length ? bList[index] : null; final ShapeBorder? localB = index < bList.length ? bList[index] : null;
if (localA != null && localB != null) { if (localA != null && localB != null) {
final ShapeBorder localResult = localA.lerpTo(localB, t) ?? localB.lerpFrom(localA, t); final ShapeBorder? localResult = localA.lerpTo(localB, t) ?? localB.lerpFrom(localA, t);
if (localResult != null) { if (localResult != null) {
results.add(localResult); results.add(localResult);
continue; continue;
...@@ -613,19 +611,19 @@ class _CompoundBorder extends ShapeBorder { ...@@ -613,19 +611,19 @@ class _CompoundBorder extends ShapeBorder {
} }
@override @override
Path getInnerPath(Rect rect, { TextDirection textDirection }) { Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
for (int index = 0; index < borders.length - 1; index += 1) for (int index = 0; index < borders.length - 1; index += 1)
rect = borders[index].dimensions.resolve(textDirection).deflateRect(rect); rect = borders[index].dimensions.resolve(textDirection).deflateRect(rect);
return borders.last.getInnerPath(rect, textDirection: textDirection); return borders.last.getInnerPath(rect, textDirection: textDirection);
} }
@override @override
Path getOuterPath(Rect rect, { TextDirection textDirection }) { Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
return borders.first.getOuterPath(rect, textDirection: textDirection); return borders.first.getOuterPath(rect, textDirection: textDirection);
} }
@override @override
void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) { void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
for (final ShapeBorder border in borders) { for (final ShapeBorder border in borders) {
border.paint(canvas, rect, textDirection: textDirection); border.paint(canvas, rect, textDirection: textDirection);
rect = border.dimensions.resolve(textDirection).deflateRect(rect); rect = border.dimensions.resolve(textDirection).deflateRect(rect);
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -85,7 +84,7 @@ abstract class BoxBorder extends ShapeBorder { ...@@ -85,7 +84,7 @@ abstract class BoxBorder extends ShapeBorder {
// We override this to tighten the return value, so that callers can assume // We override this to tighten the return value, so that callers can assume
// that we'll return a [BoxBorder]. // that we'll return a [BoxBorder].
@override @override
BoxBorder add(ShapeBorder other, { bool reversed = false }) => null; BoxBorder? add(ShapeBorder other, { bool reversed = false }) => null;
/// Linearly interpolate between two borders. /// Linearly interpolate between two borders.
/// ///
...@@ -104,12 +103,12 @@ abstract class BoxBorder extends ShapeBorder { ...@@ -104,12 +103,12 @@ abstract class BoxBorder extends ShapeBorder {
/// instead [add] the two sets of sides and interpolate them simultaneously. /// instead [add] the two sets of sides and interpolate them simultaneously.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxBorder lerp(BoxBorder a, BoxBorder b, double t) { static BoxBorder? lerp(BoxBorder? a, BoxBorder? b, double t) {
assert(t != null); assert(t != null);
if ((a is Border || a == null) && (b is Border || b == null)) if ((a is Border?) && (b is Border?))
return Border.lerp(a as Border, b as Border, t); return Border.lerp(a, b, t);
if ((a is BorderDirectional || a == null) && (b is BorderDirectional || b == null)) if ((a is BorderDirectional?) && (b is BorderDirectional?))
return BorderDirectional.lerp(a as BorderDirectional, b as BorderDirectional, t); return BorderDirectional.lerp(a, b, t);
if (b is Border && a is BorderDirectional) { if (b is Border && a is BorderDirectional) {
final BoxBorder c = b; final BoxBorder c = b;
b = a; b = a;
...@@ -167,14 +166,14 @@ abstract class BoxBorder extends ShapeBorder { ...@@ -167,14 +166,14 @@ abstract class BoxBorder extends ShapeBorder {
} }
@override @override
Path getInnerPath(Rect rect, { @required TextDirection textDirection }) { Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
assert(textDirection != null, 'The textDirection argument to $runtimeType.getInnerPath must not be null.'); assert(textDirection != null, 'The textDirection argument to $runtimeType.getInnerPath must not be null.');
return Path() return Path()
..addRect(dimensions.resolve(textDirection).deflateRect(rect)); ..addRect(dimensions.resolve(textDirection).deflateRect(rect));
} }
@override @override
Path getOuterPath(Rect rect, { @required TextDirection textDirection }) { Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
assert(textDirection != null, 'The textDirection argument to $runtimeType.getOuterPath must not be null.'); assert(textDirection != null, 'The textDirection argument to $runtimeType.getOuterPath must not be null.');
return Path() return Path()
..addRect(rect); ..addRect(rect);
...@@ -203,9 +202,9 @@ abstract class BoxBorder extends ShapeBorder { ...@@ -203,9 +202,9 @@ abstract class BoxBorder extends ShapeBorder {
void paint( void paint(
Canvas canvas, Canvas canvas,
Rect rect, { Rect rect, {
TextDirection textDirection, TextDirection? textDirection,
BoxShape shape = BoxShape.rectangle, BoxShape shape = BoxShape.rectangle,
BorderRadius borderRadius, BorderRadius? borderRadius,
}); });
static void _paintUniformBorderWithRadius(Canvas canvas, Rect rect, BorderSide side, BorderRadius borderRadius) { static void _paintUniformBorderWithRadius(Canvas canvas, Rect rect, BorderSide side, BorderRadius borderRadius) {
...@@ -414,7 +413,7 @@ class Border extends BoxBorder { ...@@ -414,7 +413,7 @@ class Border extends BoxBorder {
} }
@override @override
Border add(ShapeBorder other, { bool reversed = false }) { Border? add(ShapeBorder other, { bool reversed = false }) {
if (other is Border && if (other is Border &&
BorderSide.canMerge(top, other.top) && BorderSide.canMerge(top, other.top) &&
BorderSide.canMerge(right, other.right) && BorderSide.canMerge(right, other.right) &&
...@@ -436,14 +435,14 @@ class Border extends BoxBorder { ...@@ -436,14 +435,14 @@ class Border extends BoxBorder {
} }
@override @override
ShapeBorder lerpFrom(ShapeBorder a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a is Border) if (a is Border)
return Border.lerp(a, this, t); return Border.lerp(a, this, t);
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
ShapeBorder lerpTo(ShapeBorder b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is Border) if (b is Border)
return Border.lerp(this, b, t); return Border.lerp(this, b, t);
return super.lerpTo(b, t); return super.lerpTo(b, t);
...@@ -455,12 +454,12 @@ class Border extends BoxBorder { ...@@ -455,12 +454,12 @@ class Border extends BoxBorder {
/// borders. /// borders.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static Border lerp(Border a, Border b, double t) { static Border? lerp(Border? a, Border? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b.scale(t); return b!.scale(t);
if (b == null) if (b == null)
return a.scale(1.0 - t); return a.scale(1.0 - t);
return Border( return Border(
...@@ -494,9 +493,9 @@ class Border extends BoxBorder { ...@@ -494,9 +493,9 @@ class Border extends BoxBorder {
void paint( void paint(
Canvas canvas, Canvas canvas,
Rect rect, { Rect rect, {
TextDirection textDirection, TextDirection? textDirection,
BoxShape shape = BoxShape.rectangle, BoxShape shape = BoxShape.rectangle,
BorderRadius borderRadius, BorderRadius? borderRadius,
}) { }) {
if (isUniform) { if (isUniform) {
switch (top.style) { switch (top.style) {
...@@ -694,7 +693,7 @@ class BorderDirectional extends BoxBorder { ...@@ -694,7 +693,7 @@ class BorderDirectional extends BoxBorder {
} }
@override @override
BoxBorder add(ShapeBorder other, { bool reversed = false }) { BoxBorder? add(ShapeBorder other, { bool reversed = false }) {
if (other is BorderDirectional) { if (other is BorderDirectional) {
final BorderDirectional typedOther = other; final BorderDirectional typedOther = other;
if (BorderSide.canMerge(top, typedOther.top) && if (BorderSide.canMerge(top, typedOther.top) &&
...@@ -747,14 +746,14 @@ class BorderDirectional extends BoxBorder { ...@@ -747,14 +746,14 @@ class BorderDirectional extends BoxBorder {
} }
@override @override
ShapeBorder lerpFrom(ShapeBorder a, double t) { ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
if (a is BorderDirectional) if (a is BorderDirectional)
return BorderDirectional.lerp(a, this, t); return BorderDirectional.lerp(a, this, t);
return super.lerpFrom(a, t); return super.lerpFrom(a, t);
} }
@override @override
ShapeBorder lerpTo(ShapeBorder b, double t) { ShapeBorder? lerpTo(ShapeBorder? b, double t) {
if (b is BorderDirectional) if (b is BorderDirectional)
return BorderDirectional.lerp(this, b, t); return BorderDirectional.lerp(this, b, t);
return super.lerpTo(b, t); return super.lerpTo(b, t);
...@@ -766,12 +765,12 @@ class BorderDirectional extends BoxBorder { ...@@ -766,12 +765,12 @@ class BorderDirectional extends BoxBorder {
/// borders. /// borders.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BorderDirectional lerp(BorderDirectional a, BorderDirectional b, double t) { static BorderDirectional? lerp(BorderDirectional? a, BorderDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b.scale(t); return b!.scale(t);
if (b == null) if (b == null)
return a.scale(1.0 - t); return a.scale(1.0 - t);
return BorderDirectional( return BorderDirectional(
...@@ -808,9 +807,9 @@ class BorderDirectional extends BoxBorder { ...@@ -808,9 +807,9 @@ class BorderDirectional extends BoxBorder {
void paint( void paint(
Canvas canvas, Canvas canvas,
Rect rect, { Rect rect, {
TextDirection textDirection, TextDirection? textDirection,
BoxShape shape = BoxShape.rectangle, BoxShape shape = BoxShape.rectangle,
BorderRadius borderRadius, BorderRadius? borderRadius,
}) { }) {
if (isUniform) { if (isUniform) {
switch (top.style) { switch (top.style) {
...@@ -839,7 +838,7 @@ class BorderDirectional extends BoxBorder { ...@@ -839,7 +838,7 @@ class BorderDirectional extends BoxBorder {
BorderSide left, right; BorderSide left, right;
assert(textDirection != null, 'Non-uniform BorderDirectional objects require a TextDirection when painting.'); assert(textDirection != null, 'Non-uniform BorderDirectional objects require a TextDirection when painting.');
switch (textDirection) { switch (textDirection!) {
case TextDirection.rtl: case TextDirection.rtl:
left = end; left = end;
right = start; right = start;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math; import 'dart:math' as math;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' as ui show Shadow, lerpDouble; import 'dart:ui' as ui show Shadow, lerpDouble;
...@@ -79,19 +78,19 @@ class BoxShadow extends ui.Shadow { ...@@ -79,19 +78,19 @@ class BoxShadow extends ui.Shadow {
/// offset and a zero blurRadius. /// offset and a zero blurRadius.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static BoxShadow lerp(BoxShadow a, BoxShadow b, double t) { static BoxShadow? lerp(BoxShadow? a, BoxShadow? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b.scale(t); return b!.scale(t);
if (b == null) if (b == null)
return a.scale(1.0 - t); return a.scale(1.0 - t);
return BoxShadow( return BoxShadow(
color: Color.lerp(a.color, b.color, t), color: Color.lerp(a.color, b.color, t)!,
offset: Offset.lerp(a.offset, b.offset, t), offset: Offset.lerp(a.offset, b.offset, t)!,
blurRadius: ui.lerpDouble(a.blurRadius, b.blurRadius, t), blurRadius: ui.lerpDouble(a.blurRadius, b.blurRadius, t)!,
spreadRadius: ui.lerpDouble(a.spreadRadius, b.spreadRadius, t), spreadRadius: ui.lerpDouble(a.spreadRadius, b.spreadRadius, t)!,
); );
} }
...@@ -100,7 +99,7 @@ class BoxShadow extends ui.Shadow { ...@@ -100,7 +99,7 @@ class BoxShadow extends ui.Shadow {
/// If the lists differ in length, excess items are lerped with null. /// If the lists differ in length, excess items are lerped with null.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static List<BoxShadow> lerpList(List<BoxShadow> a, List<BoxShadow> b, double t) { static List<BoxShadow>? lerpList(List<BoxShadow>? a, List<BoxShadow>? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
...@@ -108,7 +107,7 @@ class BoxShadow extends ui.Shadow { ...@@ -108,7 +107,7 @@ class BoxShadow extends ui.Shadow {
b ??= <BoxShadow>[]; b ??= <BoxShadow>[];
final int commonLength = math.min(a.length, b.length); final int commonLength = math.min(a.length, b.length);
return <BoxShadow>[ return <BoxShadow>[
for (int i = 0; i < commonLength; i += 1) BoxShadow.lerp(a[i], b[i], t), for (int i = 0; i < commonLength; i += 1) BoxShadow.lerp(a[i], b[i], t)!,
for (int i = commonLength; i < a.length; i += 1) a[i].scale(1.0 - t), for (int i = commonLength; i < a.length; i += 1) a[i].scale(1.0 - t),
for (int i = commonLength; i < b.length; i += 1) b[i].scale(t), for (int i = commonLength; i < b.length; i += 1) b[i].scale(t),
]; ];
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show lerpDouble, WindowPadding; import 'dart:ui' as ui show lerpDouble, WindowPadding;
...@@ -73,7 +72,6 @@ abstract class EdgeInsetsGeometry { ...@@ -73,7 +72,6 @@ abstract class EdgeInsetsGeometry {
case Axis.vertical: case Axis.vertical:
return vertical; return vertical;
} }
return null;
} }
/// The size that this [EdgeInsets] would occupy with an empty interior. /// The size that this [EdgeInsets] would occupy with an empty interior.
...@@ -218,12 +216,12 @@ abstract class EdgeInsetsGeometry { ...@@ -218,12 +216,12 @@ abstract class EdgeInsetsGeometry {
/// into a concrete [EdgeInsets] using [resolve]. /// into a concrete [EdgeInsets] using [resolve].
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsetsGeometry lerp(EdgeInsetsGeometry a, EdgeInsetsGeometry b, double t) { static EdgeInsetsGeometry? lerp(EdgeInsetsGeometry? a, EdgeInsetsGeometry? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b * t; return b! * t;
if (b == null) if (b == null)
return a * (1.0 - t); return a * (1.0 - t);
if (a is EdgeInsets && b is EdgeInsets) if (a is EdgeInsets && b is EdgeInsets)
...@@ -231,12 +229,12 @@ abstract class EdgeInsetsGeometry { ...@@ -231,12 +229,12 @@ abstract class EdgeInsetsGeometry {
if (a is EdgeInsetsDirectional && b is EdgeInsetsDirectional) if (a is EdgeInsetsDirectional && b is EdgeInsetsDirectional)
return EdgeInsetsDirectional.lerp(a, b, t); return EdgeInsetsDirectional.lerp(a, b, t);
return _MixedEdgeInsets.fromLRSETB( return _MixedEdgeInsets.fromLRSETB(
ui.lerpDouble(a._left, b._left, t), ui.lerpDouble(a._left, b._left, t)!,
ui.lerpDouble(a._right, b._right, t), ui.lerpDouble(a._right, b._right, t)!,
ui.lerpDouble(a._start, b._start, t), ui.lerpDouble(a._start, b._start, t)!,
ui.lerpDouble(a._end, b._end, t), ui.lerpDouble(a._end, b._end, t)!,
ui.lerpDouble(a._top, b._top, t), ui.lerpDouble(a._top, b._top, t)!,
ui.lerpDouble(a._bottom, b._bottom, t), ui.lerpDouble(a._bottom, b._bottom, t)!,
); );
} }
...@@ -249,7 +247,7 @@ abstract class EdgeInsetsGeometry { ...@@ -249,7 +247,7 @@ abstract class EdgeInsetsGeometry {
/// * [EdgeInsets], for which this is a no-op (returns itself). /// * [EdgeInsets], for which this is a no-op (returns itself).
/// * [EdgeInsetsDirectional], which flips the horizontal direction /// * [EdgeInsetsDirectional], which flips the horizontal direction
/// based on the `direction` argument. /// based on the `direction` argument.
EdgeInsets resolve(TextDirection direction); EdgeInsets resolve(TextDirection? direction);
@override @override
String toString() { String toString() {
...@@ -597,32 +595,32 @@ class EdgeInsets extends EdgeInsetsGeometry { ...@@ -597,32 +595,32 @@ class EdgeInsets extends EdgeInsetsGeometry {
/// If either is null, this function interpolates from [EdgeInsets.zero]. /// If either is null, this function interpolates from [EdgeInsets.zero].
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsets lerp(EdgeInsets a, EdgeInsets b, double t) { static EdgeInsets? lerp(EdgeInsets? a, EdgeInsets? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b * t; return b! * t;
if (b == null) if (b == null)
return a * (1.0 - t); return a * (1.0 - t);
return EdgeInsets.fromLTRB( return EdgeInsets.fromLTRB(
ui.lerpDouble(a.left, b.left, t), ui.lerpDouble(a.left, b.left, t)!,
ui.lerpDouble(a.top, b.top, t), ui.lerpDouble(a.top, b.top, t)!,
ui.lerpDouble(a.right, b.right, t), ui.lerpDouble(a.right, b.right, t)!,
ui.lerpDouble(a.bottom, b.bottom, t), ui.lerpDouble(a.bottom, b.bottom, t)!,
); );
} }
@override @override
EdgeInsets resolve(TextDirection direction) => this; EdgeInsets resolve(TextDirection? direction) => this;
/// Creates a copy of this EdgeInsets but with the given fields replaced /// Creates a copy of this EdgeInsets but with the given fields replaced
/// with the new values. /// with the new values.
EdgeInsets copyWith({ EdgeInsets copyWith({
double left, double? left,
double top, double? top,
double right, double? right,
double bottom, double? bottom,
}) { }) {
return EdgeInsets.only( return EdgeInsets.only(
left: left ?? this.left, left: left ?? this.left,
...@@ -822,32 +820,31 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry { ...@@ -822,32 +820,31 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry {
/// [EdgeInsetsGeometry.lerp] static method. /// [EdgeInsetsGeometry.lerp] static method.
/// ///
/// {@macro dart.ui.shadow.lerp} /// {@macro dart.ui.shadow.lerp}
static EdgeInsetsDirectional lerp(EdgeInsetsDirectional a, EdgeInsetsDirectional b, double t) { static EdgeInsetsDirectional? lerp(EdgeInsetsDirectional? a, EdgeInsetsDirectional? b, double t) {
assert(t != null); assert(t != null);
if (a == null && b == null) if (a == null && b == null)
return null; return null;
if (a == null) if (a == null)
return b * t; return b! * t;
if (b == null) if (b == null)
return a * (1.0 - t); return a * (1.0 - t);
return EdgeInsetsDirectional.fromSTEB( return EdgeInsetsDirectional.fromSTEB(
ui.lerpDouble(a.start, b.start, t), ui.lerpDouble(a.start, b.start, t)!,
ui.lerpDouble(a.top, b.top, t), ui.lerpDouble(a.top, b.top, t)!,
ui.lerpDouble(a.end, b.end, t), ui.lerpDouble(a.end, b.end, t)!,
ui.lerpDouble(a.bottom, b.bottom, t), ui.lerpDouble(a.bottom, b.bottom, t)!,
); );
} }
@override @override
EdgeInsets resolve(TextDirection direction) { EdgeInsets resolve(TextDirection? direction) {
assert(direction != null); assert(direction != null);
switch (direction) { switch (direction!) {
case TextDirection.rtl: case TextDirection.rtl:
return EdgeInsets.fromLTRB(end, top, start, bottom); return EdgeInsets.fromLTRB(end, top, start, bottom);
case TextDirection.ltr: case TextDirection.ltr:
return EdgeInsets.fromLTRB(start, top, end, bottom); return EdgeInsets.fromLTRB(start, top, end, bottom);
} }
return null;
} }
} }
...@@ -943,14 +940,13 @@ class _MixedEdgeInsets extends EdgeInsetsGeometry { ...@@ -943,14 +940,13 @@ class _MixedEdgeInsets extends EdgeInsetsGeometry {
} }
@override @override
EdgeInsets resolve(TextDirection direction) { EdgeInsets resolve(TextDirection? direction) {
assert(direction != null); assert(direction != null);
switch (direction) { switch (direction!) {
case TextDirection.rtl: case TextDirection.rtl:
return EdgeInsets.fromLTRB(_end + _left, _top, _start + _right, _bottom); return EdgeInsets.fromLTRB(_end + _left, _top, _start + _right, _bottom);
case TextDirection.ltr: case TextDirection.ltr:
return EdgeInsets.fromLTRB(_start + _left, _top, _end + _right, _bottom); return EdgeInsets.fromLTRB(_start + _left, _top, _end + _right, _bottom);
} }
return null;
} }
} }
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