From 1ce88bff21ab2576a3231fc9f6e6855dd61e5ac7 Mon Sep 17 00:00:00 2001 From: Dmytro Kravchyna Date: Fri, 26 Mar 2021 18:43:04 +0200 Subject: [PATCH 1/2] null-safe --- .gitignore | 1 + pubspec.lock | 188 --------------------------------------------------- pubspec.yaml | 4 +- 3 files changed, 3 insertions(+), 190 deletions(-) delete mode 100644 pubspec.lock diff --git a/.gitignore b/.gitignore index 549d79a..157c58b 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,4 @@ build/ !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +/.vs diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index ea53bf7..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,188 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.2" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.5" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.14.11" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.4" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.6" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.8" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.4" - pedantic: - dependency: "direct dev" - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.5" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.3" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.5" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.11" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.6" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.8" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.5.0" -sdks: - dart: ">=2.4.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 68db99d..0c5e7c9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,14 +4,14 @@ version: 1.1.1+1 homepage: https://github.com/artrmz/flutter_control_pad environment: - sdk: ">=2.2.2 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: sdk: flutter dev_dependencies: - pedantic: ^1.0.0 + pedantic: ^1.11.0 flutter_test: sdk: flutter From 0cdfe96dc240a053f769b48d7a40b087b55c8faf Mon Sep 17 00:00:00 2001 From: Dmytro Kravchyna Date: Fri, 26 Mar 2021 18:43:13 +0200 Subject: [PATCH 2/2] null-safe --- lib/models/pad_button_item.dart | 10 +-- lib/views/circle_view.dart | 42 ++++----- lib/views/joystick_view.dart | 122 ++++++++++++------------- lib/views/pad_button_view.dart | 38 ++++---- pubspec.lock | 153 ++++++++++++++++++++++++++++++++ 5 files changed, 258 insertions(+), 107 deletions(-) create mode 100644 pubspec.lock diff --git a/lib/models/pad_button_item.dart b/lib/models/pad_button_item.dart index eac22d4..7fcdb1b 100644 --- a/lib/models/pad_button_item.dart +++ b/lib/models/pad_button_item.dart @@ -11,15 +11,15 @@ class PadButtonItem { /// [buttonText] optional parameter, the text to be displayed inside the /// button. Omitted if [buttonImage] is set. Default value is empty string. - final String buttonText; + final String? buttonText; /// [buttonImage] optional parameter, image which will be displayed inside /// the button. - final Image buttonImage; + final Image? buttonImage; /// [buttonIcon] optional parameter, image which will be displayed inside /// the button. - final Icon buttonIcon; + final Icon? buttonIcon; /// [backgroundColor] color of button in default state. final Color backgroundColor; @@ -34,12 +34,12 @@ class PadButtonItem { final List supportedGestures; const PadButtonItem({ - @required this.index, + required this.index, this.buttonText, this.buttonImage, this.buttonIcon, this.backgroundColor = Colors.white54, this.pressedColor = Colors.lightBlueAccent, this.supportedGestures = const [Gestures.TAP], - }) : assert(index != null); + }); } diff --git a/lib/views/circle_view.dart b/lib/views/circle_view.dart index b201b4a..80443fa 100644 --- a/lib/views/circle_view.dart +++ b/lib/views/circle_view.dart @@ -2,28 +2,25 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; class CircleView extends StatelessWidget { - final double size; + final double? size; - final Color color; + final Color? color; - final List boxShadow; + final List? boxShadow; - final Border border; + final Border? border; - final double opacity; + final Image? buttonImage; - final Image buttonImage; + final Icon? buttonIcon; - final Icon buttonIcon; - - final String buttonText; + final String? buttonText; CircleView({ this.size, this.color = Colors.transparent, this.boxShadow, this.border, - this.opacity, this.buttonImage, this.buttonIcon, this.buttonText, @@ -34,19 +31,19 @@ class CircleView extends StatelessWidget { return Container( width: size, height: size, - child: Center( - child: buttonIcon != null - ? buttonIcon - : (buttonImage != null) - ? buttonImage - : (buttonText != null) ? Text(buttonText) : null, - ), decoration: BoxDecoration( color: color, shape: BoxShape.circle, border: border, boxShadow: boxShadow, ), + child: Center( + child: buttonIcon != null + ? buttonIcon! + : (buttonImage != null) + ? buttonImage! + : (buttonText != null) ? Text(buttonText!) : null, + ), ); } @@ -87,11 +84,10 @@ class CircleView extends StatelessWidget { factory CircleView.padBackgroundCircle( double size, Color backgroundColour, borderColor, Color shadowColor, - {double opacity}) => + {double? opacity}) => CircleView( size: size, color: backgroundColour, - opacity: opacity, border: Border.all( color: borderColor, width: 4.0, @@ -108,10 +104,10 @@ class CircleView extends StatelessWidget { factory CircleView.padButtonCircle( double size, - Color color, - Image image, - Icon icon, - String text, + Color? color, + Image? image, + Icon? icon, + String? text, ) => CircleView( size: size, diff --git a/lib/views/joystick_view.dart b/lib/views/joystick_view.dart index bbc32b0..85ca085 100644 --- a/lib/views/joystick_view.dart +++ b/lib/views/joystick_view.dart @@ -13,7 +13,7 @@ class JoystickView extends StatelessWidget { /// /// Defaults to half of the width in the portrait /// or half of the height in the landscape mode - final double size; + final double? size; /// Color of the icons /// @@ -35,12 +35,12 @@ class JoystickView extends StatelessWidget { /// The opacity applies to the whole joystick including icons /// /// Defaults to [null] which means there will be no [Opacity] widget used - final double opacity; + final double? opacity; /// Callback to be called when user pans the joystick /// /// Defaults to [null] - final JoystickDirectionCallback onDirectionChanged; + final JoystickDirectionCallback? onDirectionChanged; /// Indicates how often the [onDirectionChanged] should be called. /// @@ -50,36 +50,34 @@ class JoystickView extends StatelessWidget { /// /// The exception is the [onDirectionChanged] callback being called /// on the [onPanStart] and [onPanEnd] callbacks. It will be called immediately. - final Duration interval; + final Duration? interval; /// Shows top/right/bottom/left arrows on top of Joystick /// /// Defaults to [true] final bool showArrows; - JoystickView( - {this.size, - this.iconsColor = Colors.white54, - this.backgroundColor = Colors.blueGrey, - this.innerCircleColor = Colors.blueGrey, - this.opacity, - this.onDirectionChanged, - this.interval, - this.showArrows = true}); + JoystickView({ + this.size, + this.iconsColor = Colors.white54, + this.backgroundColor = Colors.blueGrey, + this.innerCircleColor = Colors.blueGrey, + this.opacity, + this.onDirectionChanged, + this.interval, + this.showArrows = true}); @override Widget build(BuildContext context) { - double actualSize = size != null - ? size - : _math.min(MediaQuery.of(context).size.width, - MediaQuery.of(context).size.height) * - 0.5; - double innerCircleSize = actualSize / 2; - Offset lastPosition = Offset(innerCircleSize, innerCircleSize); - Offset joystickInnerPosition = _calculatePositionOfInnerCircle( - lastPosition, innerCircleSize, actualSize, Offset(0, 0)); - - DateTime _callbackTimestamp; + final actualSize = size != null + ? size! + : _math.min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) * 0.5; + final innerCircleSize = actualSize / 2; + var lastPosition = Offset(innerCircleSize, innerCircleSize); + var joystickInnerPosition = _calculatePositionOfInnerCircle( + lastPosition, innerCircleSize, actualSize, Offset(0, 0)); + + DateTime? _callbackTimestamp; return Center( child: StatefulBuilder( @@ -91,12 +89,12 @@ class JoystickView extends StatelessWidget { backgroundColor, ), Positioned( + top: joystickInnerPosition.dy, + left: joystickInnerPosition.dx, child: CircleView.joystickInnerCircle( actualSize / 2, innerCircleColor, ), - top: joystickInnerPosition.dy, - left: joystickInnerPosition.dx, ), if (showArrows) ...createArrows(), ], @@ -111,7 +109,7 @@ class JoystickView extends StatelessWidget { onPanEnd: (details) { _callbackTimestamp = null; if (onDirectionChanged != null) { - onDirectionChanged(0, 0); + onDirectionChanged!(0, 0); } joystickInnerPosition = _calculatePositionOfInnerCircle( Offset(innerCircleSize, innerCircleSize), @@ -133,7 +131,7 @@ class JoystickView extends StatelessWidget { setState(() => lastPosition = details.localPosition); }, child: (opacity != null) - ? Opacity(opacity: opacity, child: joystick) + ? Opacity(opacity: opacity!, child: joystick) : joystick, ); }, @@ -144,67 +142,71 @@ class JoystickView extends StatelessWidget { List createArrows() { return [ Positioned( + top: 7.0, + left: 0.0, + right: 0.0, child: Icon( Icons.arrow_upward, color: iconsColor, + size: 15, ), - top: 16.0, - left: 0.0, - right: 0.0, ), Positioned( + top: 0.0, + bottom: 0.0, + left: 7.0, child: Icon( Icons.arrow_back, color: iconsColor, + size: 15, ), - top: 0.0, - bottom: 0.0, - left: 16.0, ), Positioned( + top: 0.0, + bottom: 0.0, + right: 7.0, child: Icon( Icons.arrow_forward, color: iconsColor, + size: 15, ), - top: 0.0, - bottom: 0.0, - right: 16.0, ), Positioned( + bottom: 7.0, + left: 0.0, + right: 0.0, child: Icon( Icons.arrow_downward, color: iconsColor, + size: 15, ), - bottom: 16.0, - left: 0.0, - right: 0.0, ), ]; } - DateTime _processGesture(double size, double ignoreSize, Offset offset, - DateTime callbackTimestamp) { - double middle = size / 2.0; + DateTime? _processGesture(double size, double ignoreSize, Offset offset, + DateTime? callbackTimestamp) { + final middle = size / 2.0; - double angle = _math.atan2(offset.dy - middle, offset.dx - middle); - double degrees = angle * 180 / _math.pi + 90; + final angle = _math.atan2(offset.dy - middle, offset.dx - middle); + var degrees = angle * 180 / _math.pi + 90; if (offset.dx < middle && offset.dy < middle) { degrees = 360 + degrees; } - double dx = _math.max(0, _math.min(offset.dx, size)); - double dy = _math.max(0, _math.min(offset.dy, size)); + final dx = _math.max(0, _math.min(offset.dx, size)); + final dy = _math.max(0, _math.min(offset.dy, size)); - double distance = + final distance = _math.sqrt(_math.pow(middle - dx, 2) + _math.pow(middle - dy, 2)); - double normalizedDistance = _math.min(distance / (size / 2), 1.0); + final normalizedDistance = _math.min(distance / (size / 2), 1.0); - DateTime _callbackTimestamp = callbackTimestamp; + var _callbackTimestamp = callbackTimestamp; if (onDirectionChanged != null && _canCallOnDirectionChanged(callbackTimestamp)) { _callbackTimestamp = DateTime.now(); - onDirectionChanged(degrees, normalizedDistance); + onDirectionChanged!(degrees, normalizedDistance); } return _callbackTimestamp; @@ -214,11 +216,11 @@ class JoystickView extends StatelessWidget { /// /// Returns true if enough time has passed since last time it was called /// or when there is no [interval] set. - bool _canCallOnDirectionChanged(DateTime callbackTimestamp) { + bool _canCallOnDirectionChanged(DateTime? callbackTimestamp) { if (interval != null && callbackTimestamp != null) { - int intervalMilliseconds = interval.inMilliseconds; - int timestampMilliseconds = callbackTimestamp.millisecondsSinceEpoch; - int currentTimeMilliseconds = DateTime.now().millisecondsSinceEpoch; + final intervalMilliseconds = interval!.inMilliseconds; + final timestampMilliseconds = callbackTimestamp.millisecondsSinceEpoch; + final currentTimeMilliseconds = DateTime.now().millisecondsSinceEpoch; if (currentTimeMilliseconds - timestampMilliseconds <= intervalMilliseconds) { @@ -231,16 +233,16 @@ class JoystickView extends StatelessWidget { Offset _calculatePositionOfInnerCircle( Offset lastPosition, double innerCircleSize, double size, Offset offset) { - double middle = size / 2.0; + final middle = size / 2.0; - double angle = _math.atan2(offset.dy - middle, offset.dx - middle); - double degrees = angle * 180 / _math.pi; + final angle = _math.atan2(offset.dy - middle, offset.dx - middle); + var degrees = angle * 180 / _math.pi; if (offset.dx < middle && offset.dy < middle) { degrees = 360 + degrees; } - bool isStartPosition = lastPosition.dx == innerCircleSize && + final isStartPosition = lastPosition.dx == innerCircleSize && lastPosition.dy == innerCircleSize; - double lastAngleRadians = + final lastAngleRadians = (isStartPosition) ? 0 : (degrees) * (_math.pi / 180.0); var rBig = size / 2; diff --git a/lib/views/pad_button_view.dart b/lib/views/pad_button_view.dart index 906d057..42dffc5 100644 --- a/lib/views/pad_button_view.dart +++ b/lib/views/pad_button_view.dart @@ -16,14 +16,14 @@ class PadButtonsView extends StatelessWidget { /// recalculated for pad buttons size. /// /// Default value is calculated according to screen size. - final double size; + final double? size; /// List of pad buttons, default contains 4 buttons final List buttons; /// [padButtonPressedCallback] contains information which button(index) was /// used by user and what gesture was done on it. - final PadButtonPressedCallback padButtonPressedCallback; + final PadButtonPressedCallback? padButtonPressedCallback; /// [buttonsStateMap] contains current colors of each button. final Map buttonsStateMap = HashMap(); @@ -37,34 +37,34 @@ class PadButtonsView extends StatelessWidget { PadButtonsView({ this.size, this.buttons = const [ - PadButtonItem(index: 0, buttonText: "A"), - PadButtonItem(index: 1, buttonText: "B", pressedColor: Colors.red), - PadButtonItem(index: 2, buttonText: "C", pressedColor: Colors.green), - PadButtonItem(index: 3, buttonText: "D", pressedColor: Colors.yellow), + PadButtonItem(index: 0, buttonText: 'A'), + PadButtonItem(index: 1, buttonText: 'B', pressedColor: Colors.red), + PadButtonItem(index: 2, buttonText: 'C', pressedColor: Colors.green), + PadButtonItem(index: 3, buttonText: 'D', pressedColor: Colors.yellow), ], this.padButtonPressedCallback, this.buttonsPadding = 0, this.backgroundPadButtonsColor = Colors.transparent, - }) : assert(buttons != null && buttons.isNotEmpty) { + }) : assert(buttons.isNotEmpty) { buttons.forEach( (button) => buttonsStateMap[button.index] = button.backgroundColor); } @override Widget build(BuildContext context) { - double actualSize = size != null - ? size + final actualSize = size != null + ? size! : _math.min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) * 0.5; - double innerCircleSize = actualSize / 3; + final innerCircleSize = actualSize / 3; return Center( child: Stack(children: createButtons(innerCircleSize, actualSize))); } List createButtons(double innerCircleSize, double actualSize) { - List list = List(); + final list = []; list.add(CircleView.padBackgroundCircle( actualSize, backgroundPadButtonsColor, @@ -90,6 +90,8 @@ class PadButtonsView extends StatelessWidget { Positioned createPositionedButtons(PadButtonItem paddButton, double actualSize, int index, double innerCircleSize) { return Positioned( + top: _calculatePositionYOfButton(index, innerCircleSize, actualSize), + left: _calculatePositionXOfButton(index, innerCircleSize, actualSize), child: StatefulBuilder(builder: (context, setState) { return GestureDetector( onTap: () { @@ -140,23 +142,21 @@ class PadButtonsView extends StatelessWidget { ), ); }), - top: _calculatePositionYOfButton(index, innerCircleSize, actualSize), - left: _calculatePositionXOfButton(index, innerCircleSize, actualSize), ); } void _processGesture(PadButtonItem button, Gestures gesture) { if (padButtonPressedCallback != null && button.supportedGestures.contains(gesture)) { - padButtonPressedCallback(button.index, gesture); - print("$gesture paddbutton id = ${[button.index]}"); + padButtonPressedCallback!(button.index, gesture); + print('$gesture paddbutton id = ${[button.index]}'); } } double _calculatePositionXOfButton( int index, double innerCircleSize, double actualSize) { - double degrees = 360 / buttons.length * index; - double lastAngleRadians = (degrees) * (_math.pi / 180.0); + final degrees = 360 / buttons.length * index; + final lastAngleRadians = (degrees) * (_math.pi / 180.0); var rBig = actualSize / 2; var rSmall = (innerCircleSize + 2 * buttonsPadding) / 2; @@ -166,8 +166,8 @@ class PadButtonsView extends StatelessWidget { double _calculatePositionYOfButton( int index, double innerCircleSize, double actualSize) { - double degrees = 360 / buttons.length * index; - double lastAngleRadians = (degrees) * (_math.pi / 180.0); + final degrees = 360 / buttons.length * index; + final lastAngleRadians = (degrees) * (_math.pi / 180.0); var rBig = actualSize / 2; var rSmall = (innerCircleSize + 2 * buttonsPadding) / 2; diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..fd7fbbb --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,153 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + pedantic: + dependency: "direct dev" + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.19" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" +sdks: + dart: ">=2.12.0 <3.0.0"