Browse Source
For now just the code, without UI that shows the simulation. However, the code works. Also added ground work for visual designer.master
Kenneth Bruen
2 years ago
26 changed files with 1770 additions and 452 deletions
@ -0,0 +1,75 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
|
||||||
|
class UnsatisfiedDependenciesDialog extends StatelessWidget { |
||||||
|
final List<String> dependencies; |
||||||
|
|
||||||
|
const UnsatisfiedDependenciesDialog({required this.dependencies, super.key}); |
||||||
|
|
||||||
|
List<String> get projectIds { |
||||||
|
return dependencies |
||||||
|
.map((dep) => dep.split('/')[0]) |
||||||
|
.toSet() |
||||||
|
.toList(); |
||||||
|
} |
||||||
|
|
||||||
|
List<String> componentIds(String projectId) { |
||||||
|
return dependencies |
||||||
|
.map((dep) => dep.split('/')) |
||||||
|
.where((dep) => dep[0] == projectId) |
||||||
|
.map((dep) => dep[1]) |
||||||
|
.toSet() |
||||||
|
.toList(); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return AlertDialog( |
||||||
|
title: const Text('Unsatisfied Dependencies'), |
||||||
|
content: IntrinsicWidth( |
||||||
|
child: SingleChildScrollView( |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
const Padding( |
||||||
|
padding: EdgeInsets.all(8.0), |
||||||
|
child: Text('The component you are trying to design has the following dependencies that are not available.'), |
||||||
|
), |
||||||
|
const Padding( |
||||||
|
padding: EdgeInsets.all(8.0), |
||||||
|
child: Text('Consider importing the required projects or checking that they are up to date with the required components.'), |
||||||
|
), |
||||||
|
...projectIds.map( |
||||||
|
(pId) => Padding( |
||||||
|
padding: const EdgeInsets.all(8.0), |
||||||
|
child: Column( |
||||||
|
mainAxisSize: MainAxisSize.min, |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Padding( |
||||||
|
padding: const EdgeInsets.all(2.0), |
||||||
|
child: Text('Project $pId:'), |
||||||
|
), |
||||||
|
...componentIds(pId).map( |
||||||
|
(cId) => Padding( |
||||||
|
padding: const EdgeInsets.fromLTRB(16.0 + 2.0, 2.0, 2.0, 2.0), |
||||||
|
child: Text('- Component $cId'), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
actions: [ |
||||||
|
TextButton( |
||||||
|
onPressed: () => Navigator.of(context).pop(), |
||||||
|
child: const Text('OK'), |
||||||
|
), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
export 'package:logic_circuits_simulator/models/projects.dart'; |
||||||
|
export 'package:logic_circuits_simulator/models/project.dart'; |
||||||
|
export 'package:logic_circuits_simulator/models/component.dart'; |
||||||
|
export 'package:logic_circuits_simulator/models/wiring.dart'; |
@ -0,0 +1,26 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
|
||||||
|
part 'component.freezed.dart'; |
||||||
|
part 'component.g.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class ComponentEntry with _$ComponentEntry { |
||||||
|
const factory ComponentEntry({ |
||||||
|
required String componentId, |
||||||
|
required String componentName, |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
String? componentDescription, |
||||||
|
required List<String> inputs, |
||||||
|
required List<String> outputs, |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? truthTable, |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? logicExpression, |
||||||
|
@JsonKey(defaultValue: false) |
||||||
|
required bool visualDesigned, |
||||||
|
@JsonKey(defaultValue: []) |
||||||
|
required List<String> dependencies, |
||||||
|
}) = _ComponentEntry; |
||||||
|
|
||||||
|
factory ComponentEntry.fromJson(Map<String, Object?> json) => _$ComponentEntryFromJson(json); |
||||||
|
} |
@ -0,0 +1,380 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target |
||||||
|
|
||||||
|
part of 'component.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
ComponentEntry _$ComponentEntryFromJson(Map<String, dynamic> json) { |
||||||
|
return _ComponentEntry.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$ComponentEntry { |
||||||
|
String get componentId => throw _privateConstructorUsedError; |
||||||
|
String get componentName => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
String? get componentDescription => throw _privateConstructorUsedError; |
||||||
|
List<String> get inputs => throw _privateConstructorUsedError; |
||||||
|
List<String> get outputs => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? get truthTable => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? get logicExpression => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(defaultValue: false) |
||||||
|
bool get visualDesigned => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(defaultValue: []) |
||||||
|
List<String> get dependencies => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$ComponentEntryCopyWith<ComponentEntry> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $ComponentEntryCopyWith<$Res> { |
||||||
|
factory $ComponentEntryCopyWith( |
||||||
|
ComponentEntry value, $Res Function(ComponentEntry) then) = |
||||||
|
_$ComponentEntryCopyWithImpl<$Res>; |
||||||
|
$Res call( |
||||||
|
{String componentId, |
||||||
|
String componentName, |
||||||
|
@JsonKey(includeIfNull: false) String? componentDescription, |
||||||
|
List<String> inputs, |
||||||
|
List<String> outputs, |
||||||
|
@JsonKey(includeIfNull: false) List<String>? truthTable, |
||||||
|
@JsonKey(includeIfNull: false) List<String>? logicExpression, |
||||||
|
@JsonKey(defaultValue: false) bool visualDesigned, |
||||||
|
@JsonKey(defaultValue: []) List<String> dependencies}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$ComponentEntryCopyWithImpl<$Res> |
||||||
|
implements $ComponentEntryCopyWith<$Res> { |
||||||
|
_$ComponentEntryCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
final ComponentEntry _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function(ComponentEntry) _then; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? componentId = freezed, |
||||||
|
Object? componentName = freezed, |
||||||
|
Object? componentDescription = freezed, |
||||||
|
Object? inputs = freezed, |
||||||
|
Object? outputs = freezed, |
||||||
|
Object? truthTable = freezed, |
||||||
|
Object? logicExpression = freezed, |
||||||
|
Object? visualDesigned = freezed, |
||||||
|
Object? dependencies = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
componentId: componentId == freezed |
||||||
|
? _value.componentId |
||||||
|
: componentId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
componentName: componentName == freezed |
||||||
|
? _value.componentName |
||||||
|
: componentName // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
componentDescription: componentDescription == freezed |
||||||
|
? _value.componentDescription |
||||||
|
: componentDescription // ignore: cast_nullable_to_non_nullable |
||||||
|
as String?, |
||||||
|
inputs: inputs == freezed |
||||||
|
? _value.inputs |
||||||
|
: inputs // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>, |
||||||
|
outputs: outputs == freezed |
||||||
|
? _value.outputs |
||||||
|
: outputs // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>, |
||||||
|
truthTable: truthTable == freezed |
||||||
|
? _value.truthTable |
||||||
|
: truthTable // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
logicExpression: logicExpression == freezed |
||||||
|
? _value.logicExpression |
||||||
|
: logicExpression // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
visualDesigned: visualDesigned == freezed |
||||||
|
? _value.visualDesigned |
||||||
|
: visualDesigned // ignore: cast_nullable_to_non_nullable |
||||||
|
as bool, |
||||||
|
dependencies: dependencies == freezed |
||||||
|
? _value.dependencies |
||||||
|
: dependencies // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_ComponentEntryCopyWith<$Res> |
||||||
|
implements $ComponentEntryCopyWith<$Res> { |
||||||
|
factory _$$_ComponentEntryCopyWith( |
||||||
|
_$_ComponentEntry value, $Res Function(_$_ComponentEntry) then) = |
||||||
|
__$$_ComponentEntryCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
$Res call( |
||||||
|
{String componentId, |
||||||
|
String componentName, |
||||||
|
@JsonKey(includeIfNull: false) String? componentDescription, |
||||||
|
List<String> inputs, |
||||||
|
List<String> outputs, |
||||||
|
@JsonKey(includeIfNull: false) List<String>? truthTable, |
||||||
|
@JsonKey(includeIfNull: false) List<String>? logicExpression, |
||||||
|
@JsonKey(defaultValue: false) bool visualDesigned, |
||||||
|
@JsonKey(defaultValue: []) List<String> dependencies}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_ComponentEntryCopyWithImpl<$Res> |
||||||
|
extends _$ComponentEntryCopyWithImpl<$Res> |
||||||
|
implements _$$_ComponentEntryCopyWith<$Res> { |
||||||
|
__$$_ComponentEntryCopyWithImpl( |
||||||
|
_$_ComponentEntry _value, $Res Function(_$_ComponentEntry) _then) |
||||||
|
: super(_value, (v) => _then(v as _$_ComponentEntry)); |
||||||
|
|
||||||
|
@override |
||||||
|
_$_ComponentEntry get _value => super._value as _$_ComponentEntry; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? componentId = freezed, |
||||||
|
Object? componentName = freezed, |
||||||
|
Object? componentDescription = freezed, |
||||||
|
Object? inputs = freezed, |
||||||
|
Object? outputs = freezed, |
||||||
|
Object? truthTable = freezed, |
||||||
|
Object? logicExpression = freezed, |
||||||
|
Object? visualDesigned = freezed, |
||||||
|
Object? dependencies = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_ComponentEntry( |
||||||
|
componentId: componentId == freezed |
||||||
|
? _value.componentId |
||||||
|
: componentId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
componentName: componentName == freezed |
||||||
|
? _value.componentName |
||||||
|
: componentName // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
componentDescription: componentDescription == freezed |
||||||
|
? _value.componentDescription |
||||||
|
: componentDescription // ignore: cast_nullable_to_non_nullable |
||||||
|
as String?, |
||||||
|
inputs: inputs == freezed |
||||||
|
? _value._inputs |
||||||
|
: inputs // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>, |
||||||
|
outputs: outputs == freezed |
||||||
|
? _value._outputs |
||||||
|
: outputs // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>, |
||||||
|
truthTable: truthTable == freezed |
||||||
|
? _value._truthTable |
||||||
|
: truthTable // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
logicExpression: logicExpression == freezed |
||||||
|
? _value._logicExpression |
||||||
|
: logicExpression // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>?, |
||||||
|
visualDesigned: visualDesigned == freezed |
||||||
|
? _value.visualDesigned |
||||||
|
: visualDesigned // ignore: cast_nullable_to_non_nullable |
||||||
|
as bool, |
||||||
|
dependencies: dependencies == freezed |
||||||
|
? _value._dependencies |
||||||
|
: dependencies // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<String>, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_ComponentEntry implements _ComponentEntry { |
||||||
|
const _$_ComponentEntry( |
||||||
|
{required this.componentId, |
||||||
|
required this.componentName, |
||||||
|
@JsonKey(includeIfNull: false) this.componentDescription, |
||||||
|
required final List<String> inputs, |
||||||
|
required final List<String> outputs, |
||||||
|
@JsonKey(includeIfNull: false) final List<String>? truthTable, |
||||||
|
@JsonKey(includeIfNull: false) final List<String>? logicExpression, |
||||||
|
@JsonKey(defaultValue: false) required this.visualDesigned, |
||||||
|
@JsonKey(defaultValue: []) required final List<String> dependencies}) |
||||||
|
: _inputs = inputs, |
||||||
|
_outputs = outputs, |
||||||
|
_truthTable = truthTable, |
||||||
|
_logicExpression = logicExpression, |
||||||
|
_dependencies = dependencies; |
||||||
|
|
||||||
|
factory _$_ComponentEntry.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_ComponentEntryFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String componentId; |
||||||
|
@override |
||||||
|
final String componentName; |
||||||
|
@override |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
final String? componentDescription; |
||||||
|
final List<String> _inputs; |
||||||
|
@override |
||||||
|
List<String> get inputs { |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(_inputs); |
||||||
|
} |
||||||
|
|
||||||
|
final List<String> _outputs; |
||||||
|
@override |
||||||
|
List<String> get outputs { |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(_outputs); |
||||||
|
} |
||||||
|
|
||||||
|
final List<String>? _truthTable; |
||||||
|
@override |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? get truthTable { |
||||||
|
final value = _truthTable; |
||||||
|
if (value == null) return null; |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(value); |
||||||
|
} |
||||||
|
|
||||||
|
final List<String>? _logicExpression; |
||||||
|
@override |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? get logicExpression { |
||||||
|
final value = _logicExpression; |
||||||
|
if (value == null) return null; |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(value); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
@JsonKey(defaultValue: false) |
||||||
|
final bool visualDesigned; |
||||||
|
final List<String> _dependencies; |
||||||
|
@override |
||||||
|
@JsonKey(defaultValue: []) |
||||||
|
List<String> get dependencies { |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(_dependencies); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'ComponentEntry(componentId: $componentId, componentName: $componentName, componentDescription: $componentDescription, inputs: $inputs, outputs: $outputs, truthTable: $truthTable, logicExpression: $logicExpression, visualDesigned: $visualDesigned, dependencies: $dependencies)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_ComponentEntry && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other.componentId, componentId) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other.componentName, componentName) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other.componentDescription, componentDescription) && |
||||||
|
const DeepCollectionEquality().equals(other._inputs, _inputs) && |
||||||
|
const DeepCollectionEquality().equals(other._outputs, _outputs) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other._truthTable, _truthTable) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other._logicExpression, _logicExpression) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other.visualDesigned, visualDesigned) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other._dependencies, _dependencies)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash( |
||||||
|
runtimeType, |
||||||
|
const DeepCollectionEquality().hash(componentId), |
||||||
|
const DeepCollectionEquality().hash(componentName), |
||||||
|
const DeepCollectionEquality().hash(componentDescription), |
||||||
|
const DeepCollectionEquality().hash(_inputs), |
||||||
|
const DeepCollectionEquality().hash(_outputs), |
||||||
|
const DeepCollectionEquality().hash(_truthTable), |
||||||
|
const DeepCollectionEquality().hash(_logicExpression), |
||||||
|
const DeepCollectionEquality().hash(visualDesigned), |
||||||
|
const DeepCollectionEquality().hash(_dependencies)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
_$$_ComponentEntryCopyWith<_$_ComponentEntry> get copyWith => |
||||||
|
__$$_ComponentEntryCopyWithImpl<_$_ComponentEntry>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_ComponentEntryToJson(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _ComponentEntry implements ComponentEntry { |
||||||
|
const factory _ComponentEntry( |
||||||
|
{required final String componentId, |
||||||
|
required final String componentName, |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
final String? componentDescription, |
||||||
|
required final List<String> inputs, |
||||||
|
required final List<String> outputs, |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
final List<String>? truthTable, |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
final List<String>? logicExpression, |
||||||
|
@JsonKey(defaultValue: false) |
||||||
|
required final bool visualDesigned, |
||||||
|
@JsonKey(defaultValue: []) |
||||||
|
required final List<String> dependencies}) = _$_ComponentEntry; |
||||||
|
|
||||||
|
factory _ComponentEntry.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_ComponentEntry.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get componentId => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
String get componentName => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
String? get componentDescription => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
List<String> get inputs => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
List<String> get outputs => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? get truthTable => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(includeIfNull: false) |
||||||
|
List<String>? get logicExpression => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(defaultValue: false) |
||||||
|
bool get visualDesigned => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(defaultValue: []) |
||||||
|
List<String> get dependencies => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_ComponentEntryCopyWith<_$_ComponentEntry> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'component.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_ComponentEntry _$$_ComponentEntryFromJson(Map<String, dynamic> json) => |
||||||
|
_$_ComponentEntry( |
||||||
|
componentId: json['componentId'] as String, |
||||||
|
componentName: json['componentName'] as String, |
||||||
|
componentDescription: json['componentDescription'] as String?, |
||||||
|
inputs: |
||||||
|
(json['inputs'] as List<dynamic>).map((e) => e as String).toList(), |
||||||
|
outputs: |
||||||
|
(json['outputs'] as List<dynamic>).map((e) => e as String).toList(), |
||||||
|
truthTable: (json['truthTable'] as List<dynamic>?) |
||||||
|
?.map((e) => e as String) |
||||||
|
.toList(), |
||||||
|
logicExpression: (json['logicExpression'] as List<dynamic>?) |
||||||
|
?.map((e) => e as String) |
||||||
|
.toList(), |
||||||
|
visualDesigned: json['visualDesigned'] as bool? ?? false, |
||||||
|
dependencies: (json['dependencies'] as List<dynamic>?) |
||||||
|
?.map((e) => e as String) |
||||||
|
.toList() ?? |
||||||
|
[], |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_ComponentEntryToJson(_$_ComponentEntry instance) { |
||||||
|
final val = <String, dynamic>{ |
||||||
|
'componentId': instance.componentId, |
||||||
|
'componentName': instance.componentName, |
||||||
|
}; |
||||||
|
|
||||||
|
void writeNotNull(String key, dynamic value) { |
||||||
|
if (value != null) { |
||||||
|
val[key] = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
writeNotNull('componentDescription', instance.componentDescription); |
||||||
|
val['inputs'] = instance.inputs; |
||||||
|
val['outputs'] = instance.outputs; |
||||||
|
writeNotNull('truthTable', instance.truthTable); |
||||||
|
writeNotNull('logicExpression', instance.logicExpression); |
||||||
|
val['visualDesigned'] = instance.visualDesigned; |
||||||
|
val['dependencies'] = instance.dependencies; |
||||||
|
return val; |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
|
||||||
|
part 'wiring.freezed.dart'; |
||||||
|
part 'wiring.g.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class Wiring with _$Wiring { |
||||||
|
const factory Wiring({ |
||||||
|
required List<WiringInstance> instances, |
||||||
|
required List<WiringWire> wires, |
||||||
|
}) = _Wiring; |
||||||
|
|
||||||
|
factory Wiring.fromJson(Map<String, dynamic> json) => _$WiringFromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
@freezed |
||||||
|
class WiringInstance with _$WiringInstance { |
||||||
|
const factory WiringInstance({ |
||||||
|
required String instanceId, |
||||||
|
required String componentId, |
||||||
|
}) = _WiringInstance; |
||||||
|
|
||||||
|
factory WiringInstance.fromJson(Map<String, dynamic> json) => _$WiringInstanceFromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
@freezed |
||||||
|
class WiringWire with _$WiringWire { |
||||||
|
const factory WiringWire({ |
||||||
|
required String wireId, |
||||||
|
required String output, |
||||||
|
required String input, |
||||||
|
}) = _WiringWire; |
||||||
|
|
||||||
|
factory WiringWire.fromJson(Map<String, dynamic> json) => _$WiringWireFromJson(json); |
||||||
|
} |
@ -0,0 +1,497 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target |
||||||
|
|
||||||
|
part of 'wiring.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
Wiring _$WiringFromJson(Map<String, dynamic> json) { |
||||||
|
return _Wiring.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$Wiring { |
||||||
|
List<WiringInstance> get instances => throw _privateConstructorUsedError; |
||||||
|
List<WiringWire> get wires => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$WiringCopyWith<Wiring> get copyWith => throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $WiringCopyWith<$Res> { |
||||||
|
factory $WiringCopyWith(Wiring value, $Res Function(Wiring) then) = |
||||||
|
_$WiringCopyWithImpl<$Res>; |
||||||
|
$Res call({List<WiringInstance> instances, List<WiringWire> wires}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$WiringCopyWithImpl<$Res> implements $WiringCopyWith<$Res> { |
||||||
|
_$WiringCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
final Wiring _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function(Wiring) _then; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? instances = freezed, |
||||||
|
Object? wires = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
instances: instances == freezed |
||||||
|
? _value.instances |
||||||
|
: instances // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<WiringInstance>, |
||||||
|
wires: wires == freezed |
||||||
|
? _value.wires |
||||||
|
: wires // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<WiringWire>, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_WiringCopyWith<$Res> implements $WiringCopyWith<$Res> { |
||||||
|
factory _$$_WiringCopyWith(_$_Wiring value, $Res Function(_$_Wiring) then) = |
||||||
|
__$$_WiringCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
$Res call({List<WiringInstance> instances, List<WiringWire> wires}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_WiringCopyWithImpl<$Res> extends _$WiringCopyWithImpl<$Res> |
||||||
|
implements _$$_WiringCopyWith<$Res> { |
||||||
|
__$$_WiringCopyWithImpl(_$_Wiring _value, $Res Function(_$_Wiring) _then) |
||||||
|
: super(_value, (v) => _then(v as _$_Wiring)); |
||||||
|
|
||||||
|
@override |
||||||
|
_$_Wiring get _value => super._value as _$_Wiring; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? instances = freezed, |
||||||
|
Object? wires = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_Wiring( |
||||||
|
instances: instances == freezed |
||||||
|
? _value._instances |
||||||
|
: instances // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<WiringInstance>, |
||||||
|
wires: wires == freezed |
||||||
|
? _value._wires |
||||||
|
: wires // ignore: cast_nullable_to_non_nullable |
||||||
|
as List<WiringWire>, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_Wiring implements _Wiring { |
||||||
|
const _$_Wiring( |
||||||
|
{required final List<WiringInstance> instances, |
||||||
|
required final List<WiringWire> wires}) |
||||||
|
: _instances = instances, |
||||||
|
_wires = wires; |
||||||
|
|
||||||
|
factory _$_Wiring.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_WiringFromJson(json); |
||||||
|
|
||||||
|
final List<WiringInstance> _instances; |
||||||
|
@override |
||||||
|
List<WiringInstance> get instances { |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(_instances); |
||||||
|
} |
||||||
|
|
||||||
|
final List<WiringWire> _wires; |
||||||
|
@override |
||||||
|
List<WiringWire> get wires { |
||||||
|
// ignore: implicit_dynamic_type |
||||||
|
return EqualUnmodifiableListView(_wires); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'Wiring(instances: $instances, wires: $wires)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_Wiring && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other._instances, _instances) && |
||||||
|
const DeepCollectionEquality().equals(other._wires, _wires)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash( |
||||||
|
runtimeType, |
||||||
|
const DeepCollectionEquality().hash(_instances), |
||||||
|
const DeepCollectionEquality().hash(_wires)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
_$$_WiringCopyWith<_$_Wiring> get copyWith => |
||||||
|
__$$_WiringCopyWithImpl<_$_Wiring>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_WiringToJson(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _Wiring implements Wiring { |
||||||
|
const factory _Wiring( |
||||||
|
{required final List<WiringInstance> instances, |
||||||
|
required final List<WiringWire> wires}) = _$_Wiring; |
||||||
|
|
||||||
|
factory _Wiring.fromJson(Map<String, dynamic> json) = _$_Wiring.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
List<WiringInstance> get instances => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
List<WiringWire> get wires => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_WiringCopyWith<_$_Wiring> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
WiringInstance _$WiringInstanceFromJson(Map<String, dynamic> json) { |
||||||
|
return _WiringInstance.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$WiringInstance { |
||||||
|
String get instanceId => throw _privateConstructorUsedError; |
||||||
|
String get componentId => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$WiringInstanceCopyWith<WiringInstance> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $WiringInstanceCopyWith<$Res> { |
||||||
|
factory $WiringInstanceCopyWith( |
||||||
|
WiringInstance value, $Res Function(WiringInstance) then) = |
||||||
|
_$WiringInstanceCopyWithImpl<$Res>; |
||||||
|
$Res call({String instanceId, String componentId}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$WiringInstanceCopyWithImpl<$Res> |
||||||
|
implements $WiringInstanceCopyWith<$Res> { |
||||||
|
_$WiringInstanceCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
final WiringInstance _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function(WiringInstance) _then; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? instanceId = freezed, |
||||||
|
Object? componentId = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
instanceId: instanceId == freezed |
||||||
|
? _value.instanceId |
||||||
|
: instanceId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
componentId: componentId == freezed |
||||||
|
? _value.componentId |
||||||
|
: componentId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_WiringInstanceCopyWith<$Res> |
||||||
|
implements $WiringInstanceCopyWith<$Res> { |
||||||
|
factory _$$_WiringInstanceCopyWith( |
||||||
|
_$_WiringInstance value, $Res Function(_$_WiringInstance) then) = |
||||||
|
__$$_WiringInstanceCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
$Res call({String instanceId, String componentId}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_WiringInstanceCopyWithImpl<$Res> |
||||||
|
extends _$WiringInstanceCopyWithImpl<$Res> |
||||||
|
implements _$$_WiringInstanceCopyWith<$Res> { |
||||||
|
__$$_WiringInstanceCopyWithImpl( |
||||||
|
_$_WiringInstance _value, $Res Function(_$_WiringInstance) _then) |
||||||
|
: super(_value, (v) => _then(v as _$_WiringInstance)); |
||||||
|
|
||||||
|
@override |
||||||
|
_$_WiringInstance get _value => super._value as _$_WiringInstance; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? instanceId = freezed, |
||||||
|
Object? componentId = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_WiringInstance( |
||||||
|
instanceId: instanceId == freezed |
||||||
|
? _value.instanceId |
||||||
|
: instanceId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
componentId: componentId == freezed |
||||||
|
? _value.componentId |
||||||
|
: componentId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_WiringInstance implements _WiringInstance { |
||||||
|
const _$_WiringInstance( |
||||||
|
{required this.instanceId, required this.componentId}); |
||||||
|
|
||||||
|
factory _$_WiringInstance.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_WiringInstanceFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String instanceId; |
||||||
|
@override |
||||||
|
final String componentId; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'WiringInstance(instanceId: $instanceId, componentId: $componentId)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_WiringInstance && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other.instanceId, instanceId) && |
||||||
|
const DeepCollectionEquality() |
||||||
|
.equals(other.componentId, componentId)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash( |
||||||
|
runtimeType, |
||||||
|
const DeepCollectionEquality().hash(instanceId), |
||||||
|
const DeepCollectionEquality().hash(componentId)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
_$$_WiringInstanceCopyWith<_$_WiringInstance> get copyWith => |
||||||
|
__$$_WiringInstanceCopyWithImpl<_$_WiringInstance>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_WiringInstanceToJson(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _WiringInstance implements WiringInstance { |
||||||
|
const factory _WiringInstance( |
||||||
|
{required final String instanceId, |
||||||
|
required final String componentId}) = _$_WiringInstance; |
||||||
|
|
||||||
|
factory _WiringInstance.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_WiringInstance.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get instanceId => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
String get componentId => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_WiringInstanceCopyWith<_$_WiringInstance> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
WiringWire _$WiringWireFromJson(Map<String, dynamic> json) { |
||||||
|
return _WiringWire.fromJson(json); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$WiringWire { |
||||||
|
String get wireId => throw _privateConstructorUsedError; |
||||||
|
String get output => throw _privateConstructorUsedError; |
||||||
|
String get input => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||||
|
@JsonKey(ignore: true) |
||||||
|
$WiringWireCopyWith<WiringWire> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $WiringWireCopyWith<$Res> { |
||||||
|
factory $WiringWireCopyWith( |
||||||
|
WiringWire value, $Res Function(WiringWire) then) = |
||||||
|
_$WiringWireCopyWithImpl<$Res>; |
||||||
|
$Res call({String wireId, String output, String input}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$WiringWireCopyWithImpl<$Res> implements $WiringWireCopyWith<$Res> { |
||||||
|
_$WiringWireCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
final WiringWire _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function(WiringWire) _then; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? wireId = freezed, |
||||||
|
Object? output = freezed, |
||||||
|
Object? input = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
wireId: wireId == freezed |
||||||
|
? _value.wireId |
||||||
|
: wireId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
output: output == freezed |
||||||
|
? _value.output |
||||||
|
: output // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
input: input == freezed |
||||||
|
? _value.input |
||||||
|
: input // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_WiringWireCopyWith<$Res> |
||||||
|
implements $WiringWireCopyWith<$Res> { |
||||||
|
factory _$$_WiringWireCopyWith( |
||||||
|
_$_WiringWire value, $Res Function(_$_WiringWire) then) = |
||||||
|
__$$_WiringWireCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
$Res call({String wireId, String output, String input}); |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_WiringWireCopyWithImpl<$Res> extends _$WiringWireCopyWithImpl<$Res> |
||||||
|
implements _$$_WiringWireCopyWith<$Res> { |
||||||
|
__$$_WiringWireCopyWithImpl( |
||||||
|
_$_WiringWire _value, $Res Function(_$_WiringWire) _then) |
||||||
|
: super(_value, (v) => _then(v as _$_WiringWire)); |
||||||
|
|
||||||
|
@override |
||||||
|
_$_WiringWire get _value => super._value as _$_WiringWire; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? wireId = freezed, |
||||||
|
Object? output = freezed, |
||||||
|
Object? input = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_WiringWire( |
||||||
|
wireId: wireId == freezed |
||||||
|
? _value.wireId |
||||||
|
: wireId // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
output: output == freezed |
||||||
|
? _value.output |
||||||
|
: output // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
input: input == freezed |
||||||
|
? _value.input |
||||||
|
: input // ignore: cast_nullable_to_non_nullable |
||||||
|
as String, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
@JsonSerializable() |
||||||
|
class _$_WiringWire implements _WiringWire { |
||||||
|
const _$_WiringWire( |
||||||
|
{required this.wireId, required this.output, required this.input}); |
||||||
|
|
||||||
|
factory _$_WiringWire.fromJson(Map<String, dynamic> json) => |
||||||
|
_$$_WiringWireFromJson(json); |
||||||
|
|
||||||
|
@override |
||||||
|
final String wireId; |
||||||
|
@override |
||||||
|
final String output; |
||||||
|
@override |
||||||
|
final String input; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'WiringWire(wireId: $wireId, output: $output, input: $input)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_WiringWire && |
||||||
|
const DeepCollectionEquality().equals(other.wireId, wireId) && |
||||||
|
const DeepCollectionEquality().equals(other.output, output) && |
||||||
|
const DeepCollectionEquality().equals(other.input, input)); |
||||||
|
} |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
int get hashCode => Object.hash( |
||||||
|
runtimeType, |
||||||
|
const DeepCollectionEquality().hash(wireId), |
||||||
|
const DeepCollectionEquality().hash(output), |
||||||
|
const DeepCollectionEquality().hash(input)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
_$$_WiringWireCopyWith<_$_WiringWire> get copyWith => |
||||||
|
__$$_WiringWireCopyWithImpl<_$_WiringWire>(this, _$identity); |
||||||
|
|
||||||
|
@override |
||||||
|
Map<String, dynamic> toJson() { |
||||||
|
return _$$_WiringWireToJson(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _WiringWire implements WiringWire { |
||||||
|
const factory _WiringWire( |
||||||
|
{required final String wireId, |
||||||
|
required final String output, |
||||||
|
required final String input}) = _$_WiringWire; |
||||||
|
|
||||||
|
factory _WiringWire.fromJson(Map<String, dynamic> json) = |
||||||
|
_$_WiringWire.fromJson; |
||||||
|
|
||||||
|
@override |
||||||
|
String get wireId => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
String get output => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
String get input => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_WiringWireCopyWith<_$_WiringWire> get copyWith => |
||||||
|
throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
|
||||||
|
part of 'wiring.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// JsonSerializableGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
_$_Wiring _$$_WiringFromJson(Map<String, dynamic> json) => _$_Wiring( |
||||||
|
instances: (json['instances'] as List<dynamic>) |
||||||
|
.map((e) => WiringInstance.fromJson(e as Map<String, dynamic>)) |
||||||
|
.toList(), |
||||||
|
wires: (json['wires'] as List<dynamic>) |
||||||
|
.map((e) => WiringWire.fromJson(e as Map<String, dynamic>)) |
||||||
|
.toList(), |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_WiringToJson(_$_Wiring instance) => <String, dynamic>{ |
||||||
|
'instances': instance.instances, |
||||||
|
'wires': instance.wires, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_WiringInstance _$$_WiringInstanceFromJson(Map<String, dynamic> json) => |
||||||
|
_$_WiringInstance( |
||||||
|
instanceId: json['instanceId'] as String, |
||||||
|
componentId: json['componentId'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_WiringInstanceToJson(_$_WiringInstance instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'instanceId': instance.instanceId, |
||||||
|
'componentId': instance.componentId, |
||||||
|
}; |
||||||
|
|
||||||
|
_$_WiringWire _$$_WiringWireFromJson(Map<String, dynamic> json) => |
||||||
|
_$_WiringWire( |
||||||
|
wireId: json['wireId'] as String, |
||||||
|
output: json['output'] as String, |
||||||
|
input: json['input'] as String, |
||||||
|
); |
||||||
|
|
||||||
|
Map<String, dynamic> _$$_WiringWireToJson(_$_WiringWire instance) => |
||||||
|
<String, dynamic>{ |
||||||
|
'wireId': instance.wireId, |
||||||
|
'output': instance.output, |
||||||
|
'input': instance.input, |
||||||
|
}; |
@ -0,0 +1,69 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart'; |
||||||
|
import 'package:logic_circuits_simulator/models.dart'; |
||||||
|
import 'package:logic_circuits_simulator/pages_arguments/design_component.dart'; |
||||||
|
import 'package:logic_circuits_simulator/state/component.dart'; |
||||||
|
import 'package:logic_circuits_simulator/utils/provider_hook.dart'; |
||||||
|
import 'package:logic_circuits_simulator/utils/stack_canvas_controller_hook.dart'; |
||||||
|
import 'package:stack_canvas/stack_canvas.dart'; |
||||||
|
|
||||||
|
class DesignComponentPage extends HookWidget { |
||||||
|
final ComponentEntry component; |
||||||
|
|
||||||
|
const DesignComponentPage({required this.component, super.key}); |
||||||
|
DesignComponentPage.fromArguments(DesignComponentPageArguments args, {super.key}) |
||||||
|
: component = args.component; |
||||||
|
|
||||||
|
static const String routeName = '/project/component/design'; |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
final componentState = useProvider<ComponentState>(); |
||||||
|
final canvasController = useStackCanvasController(); |
||||||
|
final widgets = useState(<CanvasObject<Widget>>[]); |
||||||
|
useEffect(() { |
||||||
|
canvasController.addCanvasObjects(widgets.value); |
||||||
|
|
||||||
|
return () { |
||||||
|
// Cleanup |
||||||
|
canvasController.clearCanvas(); |
||||||
|
}; |
||||||
|
}, [widgets]); |
||||||
|
|
||||||
|
return Scaffold( |
||||||
|
appBar: AppBar( |
||||||
|
centerTitle: true, |
||||||
|
title: Text('Design - ${component.componentName}'), |
||||||
|
), |
||||||
|
body: OrientationBuilder( |
||||||
|
builder: (context, orientation) { |
||||||
|
if (orientation == Orientation.portrait) { |
||||||
|
return Column( |
||||||
|
mainAxisSize: MainAxisSize.max, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: StackCanvas( |
||||||
|
canvasController: canvasController, |
||||||
|
backgroundColor: Theme.of(context).colorScheme.background, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
else { |
||||||
|
return Row( |
||||||
|
mainAxisSize: MainAxisSize.max, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: StackCanvas( |
||||||
|
canvasController: canvasController, |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||||
|
import 'package:logic_circuits_simulator/models.dart'; |
||||||
|
|
||||||
|
part 'design_component.freezed.dart'; |
||||||
|
|
||||||
|
@freezed |
||||||
|
class DesignComponentPageArguments with _$DesignComponentPageArguments { |
||||||
|
const factory DesignComponentPageArguments({ |
||||||
|
required ComponentEntry component, |
||||||
|
}) = _DesignComponentPageArguments; |
||||||
|
} |
@ -0,0 +1,150 @@ |
|||||||
|
// coverage:ignore-file |
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||||
|
// ignore_for_file: type=lint |
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target |
||||||
|
|
||||||
|
part of 'design_component.dart'; |
||||||
|
|
||||||
|
// ************************************************************************** |
||||||
|
// FreezedGenerator |
||||||
|
// ************************************************************************** |
||||||
|
|
||||||
|
T _$identity<T>(T value) => value; |
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError( |
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
mixin _$DesignComponentPageArguments { |
||||||
|
ComponentEntry get component => throw _privateConstructorUsedError; |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
$DesignComponentPageArgumentsCopyWith<DesignComponentPageArguments> |
||||||
|
get copyWith => throw _privateConstructorUsedError; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class $DesignComponentPageArgumentsCopyWith<$Res> { |
||||||
|
factory $DesignComponentPageArgumentsCopyWith( |
||||||
|
DesignComponentPageArguments value, |
||||||
|
$Res Function(DesignComponentPageArguments) then) = |
||||||
|
_$DesignComponentPageArgumentsCopyWithImpl<$Res>; |
||||||
|
$Res call({ComponentEntry component}); |
||||||
|
|
||||||
|
$ComponentEntryCopyWith<$Res> get component; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class _$DesignComponentPageArgumentsCopyWithImpl<$Res> |
||||||
|
implements $DesignComponentPageArgumentsCopyWith<$Res> { |
||||||
|
_$DesignComponentPageArgumentsCopyWithImpl(this._value, this._then); |
||||||
|
|
||||||
|
final DesignComponentPageArguments _value; |
||||||
|
// ignore: unused_field |
||||||
|
final $Res Function(DesignComponentPageArguments) _then; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? component = freezed, |
||||||
|
}) { |
||||||
|
return _then(_value.copyWith( |
||||||
|
component: component == freezed |
||||||
|
? _value.component |
||||||
|
: component // ignore: cast_nullable_to_non_nullable |
||||||
|
as ComponentEntry, |
||||||
|
)); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
$ComponentEntryCopyWith<$Res> get component { |
||||||
|
return $ComponentEntryCopyWith<$Res>(_value.component, (value) { |
||||||
|
return _then(_value.copyWith(component: value)); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
abstract class _$$_DesignComponentPageArgumentsCopyWith<$Res> |
||||||
|
implements $DesignComponentPageArgumentsCopyWith<$Res> { |
||||||
|
factory _$$_DesignComponentPageArgumentsCopyWith( |
||||||
|
_$_DesignComponentPageArguments value, |
||||||
|
$Res Function(_$_DesignComponentPageArguments) then) = |
||||||
|
__$$_DesignComponentPageArgumentsCopyWithImpl<$Res>; |
||||||
|
@override |
||||||
|
$Res call({ComponentEntry component}); |
||||||
|
|
||||||
|
@override |
||||||
|
$ComponentEntryCopyWith<$Res> get component; |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
class __$$_DesignComponentPageArgumentsCopyWithImpl<$Res> |
||||||
|
extends _$DesignComponentPageArgumentsCopyWithImpl<$Res> |
||||||
|
implements _$$_DesignComponentPageArgumentsCopyWith<$Res> { |
||||||
|
__$$_DesignComponentPageArgumentsCopyWithImpl( |
||||||
|
_$_DesignComponentPageArguments _value, |
||||||
|
$Res Function(_$_DesignComponentPageArguments) _then) |
||||||
|
: super(_value, (v) => _then(v as _$_DesignComponentPageArguments)); |
||||||
|
|
||||||
|
@override |
||||||
|
_$_DesignComponentPageArguments get _value => |
||||||
|
super._value as _$_DesignComponentPageArguments; |
||||||
|
|
||||||
|
@override |
||||||
|
$Res call({ |
||||||
|
Object? component = freezed, |
||||||
|
}) { |
||||||
|
return _then(_$_DesignComponentPageArguments( |
||||||
|
component: component == freezed |
||||||
|
? _value.component |
||||||
|
: component // ignore: cast_nullable_to_non_nullable |
||||||
|
as ComponentEntry, |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// @nodoc |
||||||
|
|
||||||
|
class _$_DesignComponentPageArguments implements _DesignComponentPageArguments { |
||||||
|
const _$_DesignComponentPageArguments({required this.component}); |
||||||
|
|
||||||
|
@override |
||||||
|
final ComponentEntry component; |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'DesignComponentPageArguments(component: $component)'; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
bool operator ==(dynamic other) { |
||||||
|
return identical(this, other) || |
||||||
|
(other.runtimeType == runtimeType && |
||||||
|
other is _$_DesignComponentPageArguments && |
||||||
|
const DeepCollectionEquality().equals(other.component, component)); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
int get hashCode => |
||||||
|
Object.hash(runtimeType, const DeepCollectionEquality().hash(component)); |
||||||
|
|
||||||
|
@JsonKey(ignore: true) |
||||||
|
@override |
||||||
|
_$$_DesignComponentPageArgumentsCopyWith<_$_DesignComponentPageArguments> |
||||||
|
get copyWith => __$$_DesignComponentPageArgumentsCopyWithImpl< |
||||||
|
_$_DesignComponentPageArguments>(this, _$identity); |
||||||
|
} |
||||||
|
|
||||||
|
abstract class _DesignComponentPageArguments |
||||||
|
implements DesignComponentPageArguments { |
||||||
|
const factory _DesignComponentPageArguments( |
||||||
|
{required final ComponentEntry component}) = |
||||||
|
_$_DesignComponentPageArguments; |
||||||
|
|
||||||
|
@override |
||||||
|
ComponentEntry get component => throw _privateConstructorUsedError; |
||||||
|
@override |
||||||
|
@JsonKey(ignore: true) |
||||||
|
_$$_DesignComponentPageArgumentsCopyWith<_$_DesignComponentPageArguments> |
||||||
|
get copyWith => throw _privateConstructorUsedError; |
||||||
|
} |
@ -0,0 +1,135 @@ |
|||||||
|
import 'dart:convert'; |
||||||
|
import 'dart:io'; |
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart'; |
||||||
|
import 'package:logic_circuits_simulator/models.dart'; |
||||||
|
import 'package:logic_circuits_simulator/utils/simulation.dart'; |
||||||
|
import 'package:path/path.dart' as path; |
||||||
|
import 'package:path_provider/path_provider.dart'; |
||||||
|
import 'package:tuple/tuple.dart'; |
||||||
|
|
||||||
|
class ComponentState extends ChangeNotifier { |
||||||
|
ProjectEntry? _currentProject; |
||||||
|
ComponentEntry? _currentComponent; |
||||||
|
Wiring _wiring = const Wiring(instances: [], wires: []); |
||||||
|
SimulatedComponent? _simulatedComponent; |
||||||
|
|
||||||
|
final Map<String, Tuple2<ProjectEntry, ComponentEntry>> _dependenciesMap = {}; |
||||||
|
|
||||||
|
ProjectEntry? get currentProject => _currentProject; |
||||||
|
ComponentEntry? get currentComponent => _currentComponent; |
||||||
|
Wiring get wiring => _wiring; |
||||||
|
|
||||||
|
Future<Directory> _getComponentDir() async { |
||||||
|
if (_currentProject == null) { |
||||||
|
throw Exception('Cannot get component directory without knowing project'); |
||||||
|
} |
||||||
|
if (_currentComponent == null) { |
||||||
|
throw Exception('Cannot get component directory of null'); |
||||||
|
} |
||||||
|
final appDir = await getApplicationDocumentsDirectory(); |
||||||
|
final result = Directory(path.join(appDir.path, 'LogicCircuitsSimulator', 'projects', _currentProject!.projectId, 'components', _currentComponent!.componentId)); |
||||||
|
if (!await result.exists()) { |
||||||
|
await result.create(recursive: true); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
Future<File> _getWiringFile() async { |
||||||
|
final result = File(path.join((await _getComponentDir()).path, 'wiring.json')); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
Future<void> _loadComponentFiles() async { |
||||||
|
final wiringFile = await _getWiringFile(); |
||||||
|
if (!await wiringFile.exists()) { |
||||||
|
_wiring = const Wiring(instances: [], wires: []); |
||||||
|
await wiringFile.writeAsString(jsonEncode(_wiring)); |
||||||
|
} |
||||||
|
else { |
||||||
|
_wiring = Wiring.fromJson(jsonDecode(await wiringFile.readAsString())); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Future<void> setCurrentComponent({ |
||||||
|
required ProjectEntry project, |
||||||
|
required ComponentEntry component, |
||||||
|
required Future<Tuple2<ProjectEntry, ComponentEntry>?> Function(String projectId, String componentId) onDependencyNeeded, |
||||||
|
}) async { |
||||||
|
_dependenciesMap.clear(); |
||||||
|
_simulatedComponent = null; |
||||||
|
|
||||||
|
_currentProject = project; |
||||||
|
_currentComponent = component; |
||||||
|
|
||||||
|
// Load dependencies |
||||||
|
final unsatisfiedDependencies = <String>[]; |
||||||
|
for (final depId in component.dependencies) { |
||||||
|
final splitted = depId.split('/'); |
||||||
|
final maybeDep = await onDependencyNeeded(splitted[0], splitted[1]); |
||||||
|
if (maybeDep == null) { |
||||||
|
unsatisfiedDependencies.add(depId); |
||||||
|
} |
||||||
|
else { |
||||||
|
_dependenciesMap[depId] = maybeDep; |
||||||
|
} |
||||||
|
} |
||||||
|
if (unsatisfiedDependencies.isNotEmpty) { |
||||||
|
throw DependenciesNotSatisfiedException(dependencies: unsatisfiedDependencies); |
||||||
|
} |
||||||
|
|
||||||
|
return _loadComponentFiles().then((_) => notifyListeners()); |
||||||
|
} |
||||||
|
|
||||||
|
void noComponent() { |
||||||
|
_dependenciesMap.clear(); |
||||||
|
_currentProject = null; |
||||||
|
_currentComponent = null; |
||||||
|
_wiring = const Wiring(instances: [], wires: []); |
||||||
|
_simulatedComponent = null; |
||||||
|
|
||||||
|
notifyListeners(); |
||||||
|
} |
||||||
|
|
||||||
|
Future<Map<String, bool>> simulate(Map<String, bool> inputs) async { |
||||||
|
Future<SimulatedComponent> onRequiredDependency(String depId) async { |
||||||
|
final t = _dependenciesMap[depId]!; |
||||||
|
final proj = t.item1; |
||||||
|
final comp = t.item2; |
||||||
|
final state = comp.visualDesigned ? ComponentState() : null; |
||||||
|
if (state != null) { |
||||||
|
await state.setCurrentComponent( |
||||||
|
project: proj, |
||||||
|
component: comp, |
||||||
|
onDependencyNeeded: (projId, compId) async => _dependenciesMap['$projId/$compId'], |
||||||
|
); |
||||||
|
} |
||||||
|
return SimulatedComponent( |
||||||
|
project: proj, |
||||||
|
component: comp, |
||||||
|
onRequiredDependency: onRequiredDependency, |
||||||
|
state: state, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
_simulatedComponent ??= SimulatedComponent( |
||||||
|
project: _currentProject!, |
||||||
|
component: _currentComponent!, |
||||||
|
onRequiredDependency: onRequiredDependency, |
||||||
|
state: this, |
||||||
|
); |
||||||
|
|
||||||
|
return _simulatedComponent!.simulate(inputs); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class DependenciesNotSatisfiedException with Exception { |
||||||
|
final List<String> dependencies; |
||||||
|
|
||||||
|
const DependenciesNotSatisfiedException({required this.dependencies}); |
||||||
|
|
||||||
|
@override |
||||||
|
String toString() { |
||||||
|
return 'DependenciesNotSatisfiedException(${dependencies.join(", ")})'; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,127 @@ |
|||||||
|
import 'package:logic_circuits_simulator/models.dart'; |
||||||
|
import 'package:logic_circuits_simulator/state/component.dart'; |
||||||
|
import 'package:logic_circuits_simulator/utils/iterable_extension.dart'; |
||||||
|
import 'package:logic_circuits_simulator/utils/logic_expressions.dart'; |
||||||
|
|
||||||
|
class SimulatedComponent { |
||||||
|
final ProjectEntry project; |
||||||
|
final ComponentEntry component; |
||||||
|
final ComponentState? state; |
||||||
|
final Future<SimulatedComponent> Function(String depId) onRequiredDependency; |
||||||
|
final _instances = <String, SimulatedComponent>{}; |
||||||
|
|
||||||
|
SimulatedComponent({ |
||||||
|
required this.project, |
||||||
|
required this.component, |
||||||
|
required this.onRequiredDependency, |
||||||
|
this.state |
||||||
|
}); |
||||||
|
|
||||||
|
Future<SimulatedComponent> _getInstance(String instanceId, String? depId) async { |
||||||
|
if (!_instances.containsKey(instanceId)) { |
||||||
|
if (depId != null) { |
||||||
|
_instances[instanceId] = await onRequiredDependency(depId); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw Exception('Attempted to get instance of unknown component'); |
||||||
|
} |
||||||
|
} |
||||||
|
return _instances[instanceId]!; |
||||||
|
} |
||||||
|
|
||||||
|
Future<Map<String, bool>> simulate(Map<String, bool> inputs) async { |
||||||
|
final input = int.parse(component.inputs.map((input) => inputs[input]! ? '1' : '0').join(), radix: 2); |
||||||
|
if (component.truthTable != null) { |
||||||
|
final output = component.truthTable![input]; |
||||||
|
return { |
||||||
|
for (final it in component.outputs.indexedMap((index, outName) => [outName, output[index]])) |
||||||
|
it[0] : it[1] == '1' |
||||||
|
}; |
||||||
|
} |
||||||
|
else if (component.logicExpression != null) { |
||||||
|
// Somehow? |
||||||
|
// A truth table should be automatically generated for every logic expression component. |
||||||
|
// Might as well handle cases where that isn't done anyway. |
||||||
|
final results = component.outputs.zipWith( |
||||||
|
[component.logicExpression!], |
||||||
|
(zips) { |
||||||
|
final output = zips[0]; |
||||||
|
final le = LogicExpression.parse(zips[1]); |
||||||
|
return [output, le.evaluate(inputs)]; |
||||||
|
}, |
||||||
|
); |
||||||
|
return { |
||||||
|
for (final it in results) |
||||||
|
it[0] as String : it[1] as bool |
||||||
|
}; |
||||||
|
} |
||||||
|
else if (state == null) { |
||||||
|
throw Exception('Cannot simulate designed component without its state'); |
||||||
|
} |
||||||
|
else { |
||||||
|
// Create instances |
||||||
|
final wiring = state!.wiring; |
||||||
|
for (final instance in wiring.instances) { |
||||||
|
_getInstance(instance.instanceId, instance.componentId); |
||||||
|
} |
||||||
|
|
||||||
|
// Simulate |
||||||
|
final requiredSinks = <String>[ |
||||||
|
...component.outputs.map((output) => 'self/$output'), |
||||||
|
]; |
||||||
|
final knownSources = { |
||||||
|
for (final entry in inputs.entries) |
||||||
|
'self/${entry.key}': entry.value |
||||||
|
}; |
||||||
|
final knownSinks = <String, bool>{}; |
||||||
|
|
||||||
|
while (requiredSinks.isNotEmpty) { |
||||||
|
final sink = requiredSinks.removeAt(0); |
||||||
|
// C-SOURCE - WIRE-OUT -> WIRE-IN - C-SINK |
||||||
|
if (knownSinks.containsKey(sink)) { |
||||||
|
// Requirement satisfied |
||||||
|
continue; |
||||||
|
} |
||||||
|
else { |
||||||
|
// Find wire that provides sink |
||||||
|
final wire = wiring.wires.where((wire) => wire.input == sink).first; |
||||||
|
if (knownSources.containsKey(wire.output)) { |
||||||
|
// If we know the output provided through the wire, |
||||||
|
// we know the input provided to the sink |
||||||
|
knownSinks[sink] = knownSources[wire.output]!; |
||||||
|
} |
||||||
|
else { |
||||||
|
// The instance providing the source for the wire has not been simulated. |
||||||
|
// See if all its sinks are known: |
||||||
|
final instanceId = wire.output.split('/')[0]; |
||||||
|
final instance = await _getInstance(instanceId, null); |
||||||
|
final depSinks = instance.component.inputs.map((input) => '$instanceId/$input').toList(); |
||||||
|
if (depSinks.map((depSink) => !knownSinks.containsKey(depSink)).where((cond) => cond).isEmpty) { |
||||||
|
// If so, then simulate |
||||||
|
final results = await instance.simulate({ |
||||||
|
for (final depSink in depSinks) |
||||||
|
depSink.split('/')[1] : knownSinks[depSink]! |
||||||
|
}); |
||||||
|
knownSources.addAll({ |
||||||
|
for (final result in results.entries) |
||||||
|
'$instanceId/${result.key}' : result.value |
||||||
|
}); |
||||||
|
// And resolve needed sink |
||||||
|
knownSinks[sink] = knownSources[wire.output]!; |
||||||
|
} |
||||||
|
else { |
||||||
|
// Otherwise, require the sinks and reschedule the current one |
||||||
|
requiredSinks.addAll(depSinks.where((depSink) => !knownSinks.containsKey(depSink))); |
||||||
|
requiredSinks.add(sink); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
for (final output in component.outputs) |
||||||
|
output : knownSinks['self/$output']! |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
import 'package:flutter/widgets.dart'; |
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart'; |
||||||
|
import 'package:stack_canvas/stack_canvas.dart'; |
||||||
|
|
||||||
|
StackCanvasController useStackCanvasController({ |
||||||
|
double zoomChangeUnit = 0.10, |
||||||
|
double moveChangeUnit = 30.00, |
||||||
|
Reference offsetReference = Reference.TopLeft, |
||||||
|
Reference zoomReference = Reference.TopLeft, |
||||||
|
}) { |
||||||
|
return use(_StackCanvasControllerHookCreator( |
||||||
|
moveChangeUnit: moveChangeUnit, |
||||||
|
offsetReference: offsetReference, |
||||||
|
zoomChangeUnit: zoomChangeUnit, |
||||||
|
zoomReference: zoomReference, |
||||||
|
)); |
||||||
|
} |
||||||
|
|
||||||
|
class _StackCanvasControllerHookCreator extends Hook<StackCanvasController> { |
||||||
|
final double zoomChangeUnit; |
||||||
|
final double moveChangeUnit; |
||||||
|
final Reference offsetReference; |
||||||
|
final Reference zoomReference; |
||||||
|
|
||||||
|
const _StackCanvasControllerHookCreator({ |
||||||
|
this.zoomChangeUnit = 0.10, |
||||||
|
this.moveChangeUnit = 30.00, |
||||||
|
this.offsetReference = Reference.TopLeft, |
||||||
|
this.zoomReference = Reference.TopLeft, |
||||||
|
}); |
||||||
|
|
||||||
|
@override |
||||||
|
HookState<StackCanvasController, Hook<StackCanvasController>> createState() { |
||||||
|
return _StackCanvasControllerHookCreatorState(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class _StackCanvasControllerHookCreatorState extends HookState<StackCanvasController, _StackCanvasControllerHookCreator> { |
||||||
|
late StackCanvasController _controller; |
||||||
|
|
||||||
|
@override |
||||||
|
void initHook() { |
||||||
|
super.initHook(); |
||||||
|
_controller = StackCanvasController( |
||||||
|
moveChangeUnit: hook.moveChangeUnit, |
||||||
|
offsetReference: hook.offsetReference, |
||||||
|
zoomChangeUnit: hook.zoomChangeUnit, |
||||||
|
zoomReference: hook.zoomReference, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
StackCanvasController build(BuildContext context) { |
||||||
|
return _controller; |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
void dispose() { |
||||||
|
super.dispose(); |
||||||
|
_controller.dispose(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue