diff --git a/.gitignore b/.gitignore index d86b573..022f031 100644 --- a/.gitignore +++ b/.gitignore @@ -123,3 +123,5 @@ app.*.symbols pubspec.lock **/*.evc **/pubspec_overrides.yaml + +flutter_eval.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 8767e43..d3ee20a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.4.6 +- Add Builder +- Add AlignmentGeometry, Alignment, and BoxConstraints +- Add alignment, margin, constraints, and transformAlignment on Container +- Add widthFactor and heightFactor on Center +- Add TextDirection, VerticalDirection, and TextBaseline +- Add textDirection and verticalDirection on Row +- Add verticalDirection and textBaseline on Column +- Documentation improvements + ## 0.4.5 - Support for Flutter 3.3 - Update example to the Flutter counter example diff --git a/README.md b/README.md index 2a868ad..2a81658 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,22 @@ Your project structure should look like this: └── main.dart ``` +You'll also have to change your entrypoint a bit. flutter_eval does not support +`runApp()` as it runs inside an existing Flutter app, which already calls runApp(). +Instead, you can change your main() function to look like this: + +```dart +Widget main() { + // do any setup, then + return MyApp(); +} +``` + +Alternatively, you can simply comment out runApp() and reference Widget +constructors directly from RuntimeWidget. This is recommended if your project +has multiple widgets which are displayed at different times or in different +parts of the app. + Finally, in the root of your project, run: ```bash dart_eval compile -o program.evc @@ -122,6 +138,37 @@ The resulting `program.evc` file will be in the root of your project and you can in flutter_eval, as an asset or from a URL. The package name will be automatically inferred from your pubspec.yaml file. +## Calling functions and passing arguments + +To instantiate a class with its default constructor, append a '.' to the class name. + +When calling a dart_eval function or constructor externally, you must specify *all* +arguments - even optional and named ones - in order, using null to indicate the absence +of an argument (whereas `$null()` indicates a null value). + +E.g. for the following class: + +```dart +class MyApp extends SomeWidget { + MyApp(this.name, {Key? key, Color? color}) : super(key: key, color: color); + + final String name; +} +``` + +You could instantiate it in `RuntimeWidget` with: + +```dart +return RuntimeWidget( + uri: Uri.parse('asset:assets/program.evc'), + library: 'package:example/main.dart', + function: 'MyApp.', + args: [$String('Jessica'), null, null] +); +``` + +You can also pass callbacks with `$Function`. + ## Supported widgets and classes Currently supported widgets and classes include: @@ -130,10 +177,12 @@ Currently supported widgets and classes include: - `WidgetsApp`, `Container`, `Column`, `Row`, `Center`; - `Padding`, `EdgeInsetsGeometry`, `EdgeInsets`; - `MainAxisAlignment`, `MainAxisSize`, `CrossAxisAlignment`; +- `AlignmentGeometry`, `Alignment`, `Constraints`, `BoxConstraints`; - `Color`, `ColorSwatch`, `Colors`, `FontWeight`, `FontStyle`; - `MaterialApp`, `MaterialColor`, `MaterialAccentColor`; - `Theme`, `ThemeData`, `TextTheme`; - `Text`, `TextStyle`, `TextEditingController`, `TextField`; +- `TextDirection`, `VerticalDirection`, `TextBaseline` - `Scaffold`, `ScaffoldMessenger`, `AppBar`, `SnackBar`, `FloatingActionButton`; - `TextButton`, `ElevatedButton`; - `Navigator`, `NavigatorState`; diff --git a/lib/flutter_eval.dart b/lib/flutter_eval.dart index a4fa7ac..a866081 100644 --- a/lib/flutter_eval.dart +++ b/lib/flutter_eval.dart @@ -21,12 +21,15 @@ import 'package:flutter_eval/src/material/text_theme.dart'; import 'package:flutter_eval/src/material/theme.dart'; import 'package:flutter_eval/src/material/theme_data.dart'; import 'package:flutter_eval/src/painting.dart'; +import 'package:flutter_eval/src/painting/alignment.dart'; import 'package:flutter_eval/src/painting/basic_types.dart'; import 'package:flutter_eval/src/painting/colors.dart'; import 'package:flutter_eval/src/painting/edge_insets.dart'; import 'package:flutter_eval/src/painting/text_style.dart'; import 'package:flutter_eval/src/rendering.dart'; +import 'package:flutter_eval/src/rendering/box.dart'; import 'package:flutter_eval/src/rendering/flex.dart'; +import 'package:flutter_eval/src/rendering/object.dart'; import 'package:flutter_eval/src/sky_engine/ui/painting.dart'; import 'package:flutter_eval/src/sky_engine/ui/text.dart'; import 'package:flutter_eval/src/sky_engine/ui/ui.dart'; @@ -78,7 +81,12 @@ void setupFlutterForCompile(Compiler compiler) { $TextButton.$declaration, $ThemeData.$declaration, $Theme.$declaration, - $ElevatedButton.$declaration + $ElevatedButton.$declaration, + $Builder.$declaration, + $AlignmentGeometry.$declaration, + $Alignment.$declaration, + $Constraints.$declaration, + $BoxConstraints.$declaration ]; compiler.defineBridgeClasses(classes); @@ -88,6 +96,9 @@ void setupFlutterForCompile(Compiler compiler) { compiler.defineBridgeEnum($MainAxisSize.$declaration); compiler.defineBridgeEnum($FontWeight.$declaration); compiler.defineBridgeEnum($FontStyle.$declaration); + compiler.defineBridgeEnum($TextDirection.$declaration); + compiler.defineBridgeEnum($VerticalDirection.$declaration); + compiler.defineBridgeEnum($TextBaseline.$declaration); compiler.addSource(DartSource('dart:ui', dartUiSource)); @@ -105,7 +116,7 @@ void setupFlutterForCompile(Compiler compiler) { compiler.addSource(DartSource('package:flutter/src/widgets/framework.dart', widgetsFrameworkSource)); compiler.addSource(DartSource('package:flutter/src/widgets/basic.dart', widgetsBasicSource)); - /*final outJson = json.encode({ + /* final outJson = json.encode({ 'classes': classes.map((c) => c.toJson()).toList(), 'enums': [ $MainAxisAlignment.$declaration.toJson(), @@ -128,7 +139,7 @@ void setupFlutterForCompile(Compiler compiler) { ] }); - File('flutter_eval.json').writeAsStringSync(outJson);*/ + File('flutter_eval.json').writeAsStringSync(outJson); */ } /// Setup Flutter classes for use in a dart_eval [Runtime]. After @@ -144,14 +155,35 @@ void setupFlutterForRuntime(Runtime runtime) { ..registerBridgeFunc('package:flutter/src/widgets/framework.dart', 'StatefulWidget.', $StatefulWidget$bridge.$new, isBridge: true) ..registerBridgeFunc('package:flutter/src/widgets/framework.dart', 'State.', $State$bridge.$new, isBridge: true) + ..registerBridgeFunc('package:flutter/src/painting/alignment.dart', 'Alignment.', $Alignment.$new) + ..registerBridgeFunc('package:flutter/src/painting/alignment.dart', 'Alignment.topLeft*g', $Alignment.$topLeft) + ..registerBridgeFunc('package:flutter/src/painting/alignment.dart', 'Alignment.topCenter*g', $Alignment.$topCenter) + ..registerBridgeFunc('package:flutter/src/painting/alignment.dart', 'Alignment.topRight*g', $Alignment.$topRight) + ..registerBridgeFunc( + 'package:flutter/src/painting/alignment.dart', 'Alignment.centerLeft*g', $Alignment.$centerLeft) + ..registerBridgeFunc('package:flutter/src/painting/alignment.dart', 'Alignment.center*g', $Alignment.$center) + ..registerBridgeFunc( + 'package:flutter/src/painting/alignment.dart', 'Alignment.centerRight*g', $Alignment.$centerRight) + ..registerBridgeFunc( + 'package:flutter/src/painting/alignment.dart', 'Alignment.bottomLeft*g', $Alignment.$bottomLeft) + ..registerBridgeFunc( + 'package:flutter/src/painting/alignment.dart', 'Alignment.bottomCenter*g', $Alignment.$bottomCenter) + ..registerBridgeFunc( + 'package:flutter/src/painting/alignment.dart', 'Alignment.bottomRight*g', $Alignment.$bottomRight) ..registerBridgeFunc('package:flutter/src/painting/edge_insets.dart', 'EdgeInsets.fromLTRB', $EdgeInsets.$fromLTRB) ..registerBridgeFunc('package:flutter/src/painting/edge_insets.dart', 'EdgeInsets.all', $EdgeInsets.$all) ..registerBridgeFunc('package:flutter/src/painting/text_style.dart', 'TextStyle.', $TextStyle.$new) + ..registerBridgeFunc('package:flutter/src/rendering/box.dart', 'BoxConstraints.', $BoxConstraints.$new) + ..registerBridgeFunc('package:flutter/src/rendering/box.dart', 'BoxConstraints.tightFor', $BoxConstraints.$tightFor) + ..registerBridgeFunc( + 'package:flutter/src/rendering/box.dart', 'BoxConstraints.tightForFinite', $BoxConstraints.$tightForFinite) + ..registerBridgeFunc('package:flutter/src/rendering/box.dart', 'BoxConstraints.expand', $BoxConstraints.$expand) ..registerBridgeFunc('package:flutter/src/widgets/app.dart', 'WidgetsApp.', $WidgetsApp.$new) ..registerBridgeFunc('package:flutter/src/widgets/basic.dart', 'Padding.', $Padding.$new) ..registerBridgeFunc('package:flutter/src/widgets/basic.dart', 'Column.', $Column.$new) ..registerBridgeFunc('package:flutter/src/widgets/basic.dart', 'Row.', $Row.$new) ..registerBridgeFunc('package:flutter/src/widgets/basic.dart', 'Center.', $Center.$new) + ..registerBridgeFunc('package:flutter/src/widgets/basic.dart', 'Builder.', $Builder.$new) ..registerBridgeFunc('package:flutter/src/widgets/text.dart', 'Text.', $Text.$new) ..registerBridgeFunc('package:flutter/src/widgets/container.dart', 'Container.', $Container.$new) ..registerBridgeFunc( diff --git a/lib/src/painting.dart b/lib/src/painting.dart index 19cc4cc..166ee18 100644 --- a/lib/src/painting.dart +++ b/lib/src/painting.dart @@ -1,6 +1,7 @@ const paintingSource = ''' library painting; +export 'package:flutter/src/painting/alignment.dart'; export 'package:flutter/src/painting/basic_types.dart'; export 'package:flutter/src/painting/edge_insets.dart'; export 'package:flutter/src/painting/text_style.dart'; diff --git a/lib/src/painting/alignment.dart b/lib/src/painting/alignment.dart new file mode 100644 index 0000000..407d34e --- /dev/null +++ b/lib/src/painting/alignment.dart @@ -0,0 +1,141 @@ +import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:dart_eval/stdlib/core.dart'; +import 'package:flutter/material.dart'; + +class $AlignmentGeometry implements $Instance { + static const $type = + BridgeTypeRef.spec(BridgeTypeSpec('package:flutter/src/painting/alignment.dart', 'AlignmentGeometry')); + + static const $declaration = BridgeClassDef(BridgeClassType($type, isAbstract: true), + constructors: {}, methods: {}, getters: {}, setters: {}, fields: {}, wrap: true); + + $AlignmentGeometry.wrap(this.$value); + + @override + final AlignmentGeometry $value; + + late final $Instance _superclass = $Object($value); + + @override + AlignmentGeometry get $reified => $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + return _superclass.$getProperty(runtime, identifier); + } + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + return _superclass.$setProperty(runtime, identifier, value); + } +} + +class $Alignment implements $Instance { + static const $type = BridgeTypeRef.spec(BridgeTypeSpec('package:flutter/src/painting/alignment.dart', 'Alignment')); + + static const _stValueType = + BridgeMethodDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($Alignment.$type)), isStatic: true); + static const $declaration = + BridgeClassDef(BridgeClassType($type, isAbstract: false, $extends: $AlignmentGeometry.$type), + constructors: { + '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ + BridgeParameter('x', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), false), + BridgeParameter('y', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), false), + ])) + }, + methods: {}, + getters: { + 'x': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)))), + 'y': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)))), + 'topLeft': _stValueType, + 'topCenter': _stValueType, + 'topRight': _stValueType, + 'centerLeft': _stValueType, + 'center': _stValueType, + 'centerRight': _stValueType, + 'bottomLeft': _stValueType, + 'bottomCenter': _stValueType, + 'bottomRight': _stValueType, + }, + setters: {}, + fields: {}, + wrap: true); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment( + args[0]!.$value, + args[1]!.$value, + )); + } + + static $Value? $topLeft(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.topLeft); + } + + static $Value? $topCenter(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.topCenter); + } + + static $Value? $topRight(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.topRight); + } + + static $Value? $centerLeft(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.centerLeft); + } + + static $Value? $center(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.center); + } + + static $Value? $centerRight(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.centerRight); + } + + static $Value? $bottomLeft(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.bottomLeft); + } + + static $Value? $bottomCenter(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.bottomCenter); + } + + static $Value? $bottomRight(Runtime runtime, $Value? target, List<$Value?> args) { + return $Alignment.wrap(Alignment.bottomRight); + } + + $Alignment.wrap(this.$value); + + @override + final Alignment $value; + + late final $Instance _superclass = $AlignmentGeometry.wrap($value); + + @override + get $reified => $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'x': + return $double($value.x); + case 'y': + return $double($value.y); + } + return _superclass.$getProperty(runtime, identifier); + } + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError(); + } +} diff --git a/lib/src/painting/basic_types.dart b/lib/src/painting/basic_types.dart index 9fba658..29ddb89 100644 --- a/lib/src/painting/basic_types.dart +++ b/lib/src/painting/basic_types.dart @@ -1,3 +1,7 @@ +import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:flutter/material.dart'; + const paintingBasicTypesSource = ''' export 'dart:ui' show BlendMode, @@ -43,3 +47,37 @@ export 'dart:ui' show export 'package:flutter/foundation.dart' show VoidCallback; '''; + +class $VerticalDirection implements $Instance { + static const $type = + BridgeTypeRef.spec(BridgeTypeSpec('package:flutter/src/painting/basic_types.dart', 'VerticalDirection')); + + static const $declaration = + BridgeEnumDef($type, methods: {}, getters: {}, setters: {}, values: ['rtl', 'ltr'], fields: {}); + + static final $values = { + 'up': $VerticalDirection.wrap(VerticalDirection.up), + 'down': $VerticalDirection.wrap(VerticalDirection.down), + }; + + $VerticalDirection.wrap(this.$value); + + @override + final VerticalDirection $value; + + @override + get $reified => $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + throw UnimplementedError(); + } + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError(); + } +} diff --git a/lib/src/rendering.dart b/lib/src/rendering.dart index ce79d1c..78fd141 100644 --- a/lib/src/rendering.dart +++ b/lib/src/rendering.dart @@ -1,3 +1,5 @@ const renderingSource = ''' +export 'package:flutter/src/rendering/box.dart'; export 'package:flutter/src/rendering/flex.dart'; +export 'package:flutter/src/rendering/object.dart'; '''; diff --git a/lib/src/rendering/box.dart b/lib/src/rendering/box.dart new file mode 100644 index 0000000..cfa0f84 --- /dev/null +++ b/lib/src/rendering/box.dart @@ -0,0 +1,113 @@ +import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:dart_eval/stdlib/core.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_eval/src/rendering/object.dart'; + +class $BoxConstraints implements $Instance { + static const $type = BridgeTypeRef.spec(BridgeTypeSpec('package:flutter/src/rendering/box.dart', 'BoxConstraints')); + + static const $declaration = BridgeClassDef(BridgeClassType($type, isAbstract: true), + constructors: { + '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ + BridgeParameter('minWidth', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + BridgeParameter('maxWidth', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + BridgeParameter('minHeight', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + BridgeParameter('maxHeight', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + ])), + 'tightFor': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ + BridgeParameter( + 'width', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType), nullable: true), true), + BridgeParameter( + 'height', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType), nullable: true), true), + ])), + 'tightForFinite': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ + BridgeParameter('width', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + BridgeParameter('height', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + ])), + 'expand': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ + BridgeParameter( + 'width', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType), nullable: true), true), + BridgeParameter( + 'height', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType), nullable: true), true), + ])), + }, + methods: {}, + getters: { + 'minWidth': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)))), + 'maxWidth': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)))), + 'minHeight': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)))), + 'maxHeight': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)))), + }, + setters: {}, + fields: {}, + wrap: true); + + late final $Instance _superclass = $Constraints.wrap($value); + + $BoxConstraints.wrap(this.$value); + + @override + final BoxConstraints $value; + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $BoxConstraints.wrap(BoxConstraints( + minWidth: args[0]?.$value ?? 0.0, + maxWidth: args[1]?.$value ?? double.infinity, + minHeight: args[2]?.$value ?? 0.0, + maxHeight: args[3]?.$value ?? double.infinity, + )); + } + + static $Value? $tightFor(Runtime runtime, $Value? target, List<$Value?> args) { + return $BoxConstraints.wrap(BoxConstraints.tightFor( + width: args[0]?.$value, + height: args[1]?.$value, + )); + } + + static $Value? $tightForFinite(Runtime runtime, $Value? target, List<$Value?> args) { + return $BoxConstraints.wrap(BoxConstraints.tightForFinite( + width: args[0]?.$value ?? 0.0, + height: args[1]?.$value ?? 0.0, + )); + } + + static $Value? $expand(Runtime runtime, $Value? target, List<$Value?> args) { + return $BoxConstraints.wrap(BoxConstraints.expand( + width: args[0]?.$value, + height: args[1]?.$value, + )); + } + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'minWidth': + return $double($value.minWidth); + case 'maxWidth': + return $double($value.maxWidth); + case 'minHeight': + return $double($value.minHeight); + case 'maxHeight': + return $double($value.maxHeight); + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + get $reified => $value; + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError('Property not found or cannot set $identifier on Constraints'); + } +} diff --git a/lib/src/rendering/object.dart b/lib/src/rendering/object.dart new file mode 100644 index 0000000..a800fb6 --- /dev/null +++ b/lib/src/rendering/object.dart @@ -0,0 +1,49 @@ +import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:dart_eval/stdlib/core.dart'; +import 'package:flutter/rendering.dart'; + +class $Constraints implements $Instance { + static const $type = BridgeTypeRef.spec(BridgeTypeSpec('package:flutter/src/rendering/object.dart', 'Constraints')); + + static const $declaration = BridgeClassDef(BridgeClassType($type, isAbstract: true), + constructors: {}, + methods: {}, + getters: { + 'isTight': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.boolType)))), + 'isNormalized': BridgeMethodDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.boolType)))), + }, + setters: {}, + fields: {}, + wrap: true); + + $Constraints.wrap(this.$value); + + @override + final Constraints $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'isTight': + return $bool($value.isTight); + case 'isNormalized': + return $bool($value.isNormalized); + default: + throw UnimplementedError('Property not found $identifier on Constraints'); + } + } + + @override + get $reified => $value; + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError('Property not found or cannot set $identifier on Constraints'); + } +} diff --git a/lib/src/sky_engine/ui/text.dart b/lib/src/sky_engine/ui/text.dart index c34a4d2..26ee4a7 100644 --- a/lib/src/sky_engine/ui/text.dart +++ b/lib/src/sky_engine/ui/text.dart @@ -75,3 +75,66 @@ class $FontWeight implements $Instance { throw UnimplementedError(); } } + +class $TextDirection implements $Instance { + static const $type = BridgeTypeRef.spec(BridgeTypeSpec('dart:ui', 'TextDirection')); + + static const $declaration = + BridgeEnumDef($type, methods: {}, getters: {}, setters: {}, values: ['rtl', 'ltr'], fields: {}); + + static final $values = {'rtl': $TextDirection.wrap(TextDirection.rtl), 'ltr': $TextDirection.wrap(TextDirection.ltr)}; + + $TextDirection.wrap(this.$value); + + @override + final TextDirection $value; + + @override + get $reified => $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + throw UnimplementedError(); + } + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError(); + } +} + +class $TextBaseline implements $Instance { + static const $type = BridgeTypeRef.spec(BridgeTypeSpec('dart:ui', 'TextBaseline')); + + static const $declaration = + BridgeEnumDef($type, methods: {}, getters: {}, setters: {}, values: ['alphabetic', 'ideographic'], fields: {}); + + static final $values = { + 'alphabetic': $TextBaseline.wrap(TextBaseline.alphabetic), + 'ideographic': $TextBaseline.wrap(TextBaseline.ideographic) + }; + + $TextBaseline.wrap(this.$value); + + @override + final TextBaseline $value; + + @override + get $reified => $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + throw UnimplementedError(); + } + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError(); + } +} diff --git a/lib/src/widgets/basic.dart b/lib/src/widgets/basic.dart index 1e9cfc7..93b748f 100644 --- a/lib/src/widgets/basic.dart +++ b/lib/src/widgets/basic.dart @@ -2,8 +2,10 @@ import 'package:dart_eval/dart_eval.dart'; import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_eval/src/foundation/key.dart'; +import 'package:flutter_eval/src/painting/basic_types.dart'; import 'package:flutter_eval/src/painting/edge_insets.dart'; import 'package:flutter_eval/src/rendering/flex.dart'; +import 'package:flutter_eval/src/sky_engine/ui/text.dart'; import 'package:flutter_eval/src/widgets/framework.dart'; const widgetsBasicSource = ''' @@ -74,9 +76,11 @@ class $Column implements $Instance { constructors: { '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ BridgeParameter('key', BridgeTypeAnnotation($Key.$type, nullable: true), true), - BridgeParameter('mainAxisSize', BridgeTypeAnnotation($MainAxisSize.$type), true), BridgeParameter('mainAxisAlignment', BridgeTypeAnnotation($MainAxisAlignment.$type), true), + BridgeParameter('mainAxisSize', BridgeTypeAnnotation($MainAxisSize.$type), true), BridgeParameter('crossAxisAlignment', BridgeTypeAnnotation($CrossAxisAlignment.$type), true), + BridgeParameter('verticalDirection', BridgeTypeAnnotation($VerticalDirection.$type), true), + BridgeParameter('textBaseline', BridgeTypeAnnotation($TextBaseline.$type), true), BridgeParameter( 'children', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.listType, [$Widget.$type])), true), ])) @@ -92,10 +96,12 @@ class $Column implements $Instance { static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { return $Column.wrap(Column( key: args[0]?.$value, - mainAxisSize: args[1]?.$value ?? MainAxisSize.max, - mainAxisAlignment: args[2]?.$value ?? MainAxisAlignment.start, + mainAxisAlignment: args[1]?.$value ?? MainAxisAlignment.start, + mainAxisSize: args[2]?.$value ?? MainAxisSize.max, crossAxisAlignment: args[3]?.$value ?? CrossAxisAlignment.center, - children: (args[4]?.$reified as List).cast(), + verticalDirection: args[4]?.$value ?? VerticalDirection.down, + textBaseline: args[5]?.$value, + children: (args[6]?.$reified as List).cast(), )); } @@ -126,9 +132,11 @@ class $Row implements $Instance { constructors: { '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ BridgeParameter('key', BridgeTypeAnnotation($Key.$type, nullable: true), true), - BridgeParameter('mainAxisSize', BridgeTypeAnnotation($MainAxisSize.$type), true), BridgeParameter('mainAxisAlignment', BridgeTypeAnnotation($MainAxisAlignment.$type), true), + BridgeParameter('mainAxisSize', BridgeTypeAnnotation($MainAxisSize.$type), true), BridgeParameter('crossAxisAlignment', BridgeTypeAnnotation($CrossAxisAlignment.$type), true), + BridgeParameter('textDirection', BridgeTypeAnnotation($TextDirection.$type), true), + BridgeParameter('verticalDirection', BridgeTypeAnnotation($VerticalDirection.$type), true), BridgeParameter( 'children', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.listType, [$Widget.$type])), true), ])) @@ -144,10 +152,12 @@ class $Row implements $Instance { static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { return $Row.wrap(Row( key: args[0]?.$value, - mainAxisSize: args[1]?.$value ?? MainAxisSize.max, - mainAxisAlignment: args[2]?.$value ?? MainAxisAlignment.start, + mainAxisAlignment: args[1]?.$value ?? MainAxisAlignment.start, + mainAxisSize: args[2]?.$value ?? MainAxisSize.max, crossAxisAlignment: args[3]?.$value ?? CrossAxisAlignment.center, - children: (args[4]?.$reified as List).cast(), + textDirection: args[4]?.$value, + verticalDirection: args[5]?.$value ?? VerticalDirection.down, + children: (args[6]?.$reified as List).cast(), )); } @@ -178,6 +188,8 @@ class $Center implements $Instance { constructors: { '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ BridgeParameter('key', BridgeTypeAnnotation($Key.$type, nullable: true), true), + BridgeParameter('widthFactor', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), + BridgeParameter('heightFactor', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType)), true), BridgeParameter('child', BridgeTypeAnnotation($Widget.$type), true), ])) }, @@ -192,7 +204,9 @@ class $Center implements $Instance { static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { return $Center.wrap(Center( key: args[0]?.$value, - child: args[1]?.$value, + widthFactor: args[1]?.$value, + heightFactor: args[2]?.$value, + child: args[3]?.$value, )); } @@ -215,3 +229,48 @@ class $Center implements $Instance { throw UnimplementedError(); } } + +class $Builder implements $Instance { + static const $type = BridgeTypeRef.spec(BridgeTypeSpec('package:flutter/src/widgets/basic.dart', 'Builder')); + + static const $declaration = BridgeClassDef(BridgeClassType($type, isAbstract: false, $extends: $Widget.$type), + constructors: { + '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ + BridgeParameter('key', BridgeTypeAnnotation($Key.$type, nullable: true), true), + BridgeParameter('builder', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.functionType)), true), + ])) + }, + methods: {}, + getters: {}, + setters: {}, + fields: {}, + wrap: true); + + const $Builder.wrap(this.$value); + + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $Builder.wrap(Builder( + key: args[0]?.$value, + builder: args[1]?.$value, + )); + } + + @override + final Builder $value; + + @override + Builder get $reified => $value; + + @override + $Value? $getProperty(Runtime runtime, String identifier) { + throw UnimplementedError(); + } + + @override + int get $runtimeType => throw UnimplementedError(); + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + throw UnimplementedError(); + } +} diff --git a/lib/src/widgets/container.dart b/lib/src/widgets/container.dart index 67e57fb..33b42ad 100644 --- a/lib/src/widgets/container.dart +++ b/lib/src/widgets/container.dart @@ -3,7 +3,9 @@ import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_eval/src/foundation/key.dart'; +import 'package:flutter_eval/src/painting/alignment.dart'; import 'package:flutter_eval/src/painting/edge_insets.dart'; +import 'package:flutter_eval/src/rendering/box.dart'; import 'package:flutter_eval/src/sky_engine/ui/painting.dart'; import 'framework.dart'; @@ -18,13 +20,17 @@ class $Container implements Container, $Instance { constructors: { '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), namedParams: [ BridgeParameter('key', BridgeTypeAnnotation($Key.$type, nullable: true), true), - BridgeParameter('color', BridgeTypeAnnotation($Color.$type, nullable: true), true), - BridgeParameter('child', BridgeTypeAnnotation($Widget.$type, nullable: true), true), + BridgeParameter('alignment', BridgeTypeAnnotation($AlignmentGeometry.$type, nullable: true), true), BridgeParameter('padding', BridgeTypeAnnotation($EdgeInsetsGeometry.$type, nullable: true), true), + BridgeParameter('color', BridgeTypeAnnotation($Color.$type, nullable: true), true), BridgeParameter( 'width', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType), nullable: true), true), BridgeParameter( 'height', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.doubleType), nullable: true), true), + BridgeParameter('constraints', BridgeTypeAnnotation($BoxConstraints.$type, nullable: true), true), + BridgeParameter('margin', BridgeTypeAnnotation($EdgeInsetsGeometry.$type, nullable: true), true), + BridgeParameter('transformAlignment', BridgeTypeAnnotation($AlignmentGeometry.$type, nullable: true), true), + BridgeParameter('child', BridgeTypeAnnotation($Widget.$type, nullable: true), true), ])) }, methods: {}, @@ -36,11 +42,15 @@ class $Container implements Container, $Instance { static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { return $Container.wrap(Container( key: args[0]?.$value, - color: args[1]?.$value, - child: args[2]?.$value, - padding: args[3]?.$value, + alignment: args[1]?.$value, + padding: args[2]?.$value, + color: args[3]?.$value, width: args[4]?.$value, height: args[5]?.$value, + constraints: args[6]?.$value, + margin: args[7]?.$value, + transformAlignment: args[8]?.$value, + child: args[9]?.$value, )); } diff --git a/lib/src/widgets/framework.dart b/lib/src/widgets/framework.dart index 12e2778..eaae2fd 100644 --- a/lib/src/widgets/framework.dart +++ b/lib/src/widgets/framework.dart @@ -407,6 +407,9 @@ class $State$bridge extends State with $Bridge $_invoke('build', [$BuildContext.wrap(context)]); + + @override + T get widget => $_get('widget'); } class $BuildContext implements BuildContext, $Instance { diff --git a/lib/src/widgets/text.dart b/lib/src/widgets/text.dart index 06d0dc1..27c5486 100644 --- a/lib/src/widgets/text.dart +++ b/lib/src/widgets/text.dart @@ -2,6 +2,7 @@ import 'package:dart_eval/dart_eval.dart'; import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_eval/src/foundation/key.dart'; import 'package:flutter_eval/src/painting/text_style.dart'; import 'package:flutter_eval/src/widgets/framework.dart'; @@ -13,6 +14,7 @@ class $Text implements Text, $Instance { '': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [ BridgeParameter('data', BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.stringType)), false), ], namedParams: [ + BridgeParameter('key', BridgeTypeAnnotation($Key.$type, nullable: true), true), BridgeParameter('style', BridgeTypeAnnotation($TextStyle.$type, nullable: true), true), ])) }, @@ -27,7 +29,8 @@ class $Text implements Text, $Instance { static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { return $Text.wrap(Text( args[0]!.$value, - style: args[1]?.$value, + key: args[1]?.$value, + style: args[2]?.$value, )); } diff --git a/pubspec.yaml b/pubspec.yaml index 110d8a3..7e008de 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_eval description: Flutter bridge library for dart_eval, enabling creation of fully dynamic Flutter apps and widgets that can be loaded from a file or the Internet at runtime. -version: 0.4.5 +version: 0.4.6 homepage: https://github.com/ethanblake4/flutter_eval environment: @@ -10,7 +10,7 @@ environment: dependencies: flutter: sdk: flutter - dart_eval: ^0.4.3 + dart_eval: ^0.4.6 path_provider: ^2.0.11 http: ^0.13.5 diff --git a/test/flutter_eval_test.dart b/test/flutter_eval_test.dart index 633aad8..8e09a7e 100644 --- a/test/flutter_eval_test.dart +++ b/test/flutter_eval_test.dart @@ -1,6 +1,7 @@ import 'package:dart_eval/dart_eval.dart'; import 'package:flutter/material.dart'; import 'package:flutter_eval/flutter_eval.dart'; +import 'package:flutter_eval/src/painting/alignment.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -111,4 +112,28 @@ void main() { await tester.pump(); expect(find.text('Hello123'), findsOneWidget); }); + + test('Alignment', () { + final compiler = Compiler(); + setupFlutterForCompile(compiler); + final program = compiler.compile({ + 'example': { + 'main.dart': ''' + import 'package:flutter/material.dart'; + + List main() { + return [Alignment.topLeft, Alignment.topCenter]; + } + ''' + } + }); + final runtime = Runtime(program.write().buffer.asByteData()); + setupFlutterForRuntime(runtime); + runtime.setup(); + final result = runtime.executeLib('package:example/main.dart', 'main'); + expect(result, isNotNull); + expect(result[0], isA<$Alignment>()); + expect((result[0] as $Alignment).$value.x, -1.0); + expect((result[0] as $Alignment).$value.y, -1.0); + }); }