Compare commits

..

No commits in common. "a2b6fa0725167f1bb903fd5ce9397f1a8b7a6089" and "0ab607ae3ddfdc1c65f2fe3bf2255957ebf531e1" have entirely different histories.

8 changed files with 30 additions and 206 deletions

View file

@ -1,62 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class NewAskForNameDialog extends HookWidget {
final String title;
final String? labelText;
const NewAskForNameDialog({required this.title, this.labelText, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final tec = useTextEditingController();
final onPressed = useMemoized(() => () {
Navigator.of(context).pop(tec.text);
}, [tec.text]);
return Dialog(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Align(
alignment: Alignment.centerRight,
child: IconButton(
icon: const Icon(Icons.close),
tooltip: 'Close',
onPressed: () {
Navigator.of(context).pop();
},
),
),
Text(
title,
style: Theme.of(context).textTheme.headline6,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
constraints: const BoxConstraints(minWidth: 300),
child: TextField(
controller: tec,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: labelText,
suffixIcon: IconButton(
icon: const Icon(Icons.done),
onPressed: onPressed,
),
),
onSubmitted: (_) => onPressed(),
),
),
),
],
),
),
),
);
}
}

View file

@ -20,9 +20,8 @@ class NewProjectDialog extends HookWidget {
}; };
}, [newDialogNameController.text]); }, [newDialogNameController.text]);
return Dialog( return Center(
child: Padding( child: Card(
padding: const EdgeInsets.all(8.0),
child: IntrinsicWidth( child: IntrinsicWidth(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,

View file

@ -34,12 +34,7 @@ class MyApp extends StatelessWidget {
title: 'Logic Circuits Simulator', title: 'Logic Circuits Simulator',
theme: ThemeData( theme: ThemeData(
useMaterial3: true, useMaterial3: true,
primarySwatch: Colors.orange, primarySwatch: Colors.amber,
),
darkTheme: ThemeData(
useMaterial3: true,
primarySwatch: Colors.orange,
brightness: Brightness.dark,
), ),
routes: { routes: {
ProjectsPage.routeName:(context) { ProjectsPage.routeName:(context) {

View file

@ -23,8 +23,6 @@ class ComponentEntry with _$ComponentEntry {
required List<String> outputs, required List<String> outputs,
@JsonKey(includeIfNull: false) @JsonKey(includeIfNull: false)
List<String>? truthTable, List<String>? truthTable,
@JsonKey(includeIfNull: false)
String? logicExpression,
}) = _ComponentEntry; }) = _ComponentEntry;
factory ComponentEntry.fromJson(Map<String, Object?> json) => _$ComponentEntryFromJson(json); factory ComponentEntry.fromJson(Map<String, Object?> json) => _$ComponentEntryFromJson(json);

View file

@ -166,8 +166,6 @@ mixin _$ComponentEntry {
List<String> get outputs => throw _privateConstructorUsedError; List<String> get outputs => throw _privateConstructorUsedError;
@JsonKey(includeIfNull: false) @JsonKey(includeIfNull: false)
List<String>? get truthTable => throw _privateConstructorUsedError; List<String>? get truthTable => throw _privateConstructorUsedError;
@JsonKey(includeIfNull: false)
String? get logicExpression => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
@ -186,8 +184,7 @@ abstract class $ComponentEntryCopyWith<$Res> {
@JsonKey(includeIfNull: false) String? componentDescription, @JsonKey(includeIfNull: false) String? componentDescription,
List<String> inputs, List<String> inputs,
List<String> outputs, List<String> outputs,
@JsonKey(includeIfNull: false) List<String>? truthTable, @JsonKey(includeIfNull: false) List<String>? truthTable});
@JsonKey(includeIfNull: false) String? logicExpression});
} }
/// @nodoc /// @nodoc
@ -207,7 +204,6 @@ class _$ComponentEntryCopyWithImpl<$Res>
Object? inputs = freezed, Object? inputs = freezed,
Object? outputs = freezed, Object? outputs = freezed,
Object? truthTable = freezed, Object? truthTable = freezed,
Object? logicExpression = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
componentId: componentId == freezed componentId: componentId == freezed
@ -234,10 +230,6 @@ class _$ComponentEntryCopyWithImpl<$Res>
? _value.truthTable ? _value.truthTable
: truthTable // ignore: cast_nullable_to_non_nullable : truthTable // ignore: cast_nullable_to_non_nullable
as List<String>?, as List<String>?,
logicExpression: logicExpression == freezed
? _value.logicExpression
: logicExpression // ignore: cast_nullable_to_non_nullable
as String?,
)); ));
} }
} }
@ -255,8 +247,7 @@ abstract class _$$_ComponentEntryCopyWith<$Res>
@JsonKey(includeIfNull: false) String? componentDescription, @JsonKey(includeIfNull: false) String? componentDescription,
List<String> inputs, List<String> inputs,
List<String> outputs, List<String> outputs,
@JsonKey(includeIfNull: false) List<String>? truthTable, @JsonKey(includeIfNull: false) List<String>? truthTable});
@JsonKey(includeIfNull: false) String? logicExpression});
} }
/// @nodoc /// @nodoc
@ -278,7 +269,6 @@ class __$$_ComponentEntryCopyWithImpl<$Res>
Object? inputs = freezed, Object? inputs = freezed,
Object? outputs = freezed, Object? outputs = freezed,
Object? truthTable = freezed, Object? truthTable = freezed,
Object? logicExpression = freezed,
}) { }) {
return _then(_$_ComponentEntry( return _then(_$_ComponentEntry(
componentId: componentId == freezed componentId: componentId == freezed
@ -305,10 +295,6 @@ class __$$_ComponentEntryCopyWithImpl<$Res>
? _value._truthTable ? _value._truthTable
: truthTable // ignore: cast_nullable_to_non_nullable : truthTable // ignore: cast_nullable_to_non_nullable
as List<String>?, as List<String>?,
logicExpression: logicExpression == freezed
? _value.logicExpression
: logicExpression // ignore: cast_nullable_to_non_nullable
as String?,
)); ));
} }
} }
@ -322,8 +308,7 @@ class _$_ComponentEntry implements _ComponentEntry {
@JsonKey(includeIfNull: false) this.componentDescription, @JsonKey(includeIfNull: false) this.componentDescription,
required final List<String> inputs, required final List<String> inputs,
required final List<String> outputs, required final List<String> outputs,
@JsonKey(includeIfNull: false) final List<String>? truthTable, @JsonKey(includeIfNull: false) final List<String>? truthTable})
@JsonKey(includeIfNull: false) this.logicExpression})
: _inputs = inputs, : _inputs = inputs,
_outputs = outputs, _outputs = outputs,
_truthTable = truthTable; _truthTable = truthTable;
@ -362,13 +347,9 @@ class _$_ComponentEntry implements _ComponentEntry {
return EqualUnmodifiableListView(value); return EqualUnmodifiableListView(value);
} }
@override
@JsonKey(includeIfNull: false)
final String? logicExpression;
@override @override
String toString() { String toString() {
return 'ComponentEntry(componentId: $componentId, componentName: $componentName, componentDescription: $componentDescription, inputs: $inputs, outputs: $outputs, truthTable: $truthTable, logicExpression: $logicExpression)'; return 'ComponentEntry(componentId: $componentId, componentName: $componentName, componentDescription: $componentDescription, inputs: $inputs, outputs: $outputs, truthTable: $truthTable)';
} }
@override @override
@ -385,9 +366,7 @@ class _$_ComponentEntry implements _ComponentEntry {
const DeepCollectionEquality().equals(other._inputs, _inputs) && const DeepCollectionEquality().equals(other._inputs, _inputs) &&
const DeepCollectionEquality().equals(other._outputs, _outputs) && const DeepCollectionEquality().equals(other._outputs, _outputs) &&
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other._truthTable, _truthTable) && .equals(other._truthTable, _truthTable));
const DeepCollectionEquality()
.equals(other.logicExpression, logicExpression));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@ -399,8 +378,7 @@ class _$_ComponentEntry implements _ComponentEntry {
const DeepCollectionEquality().hash(componentDescription), const DeepCollectionEquality().hash(componentDescription),
const DeepCollectionEquality().hash(_inputs), const DeepCollectionEquality().hash(_inputs),
const DeepCollectionEquality().hash(_outputs), const DeepCollectionEquality().hash(_outputs),
const DeepCollectionEquality().hash(_truthTable), const DeepCollectionEquality().hash(_truthTable));
const DeepCollectionEquality().hash(logicExpression));
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@ -420,8 +398,7 @@ abstract class _ComponentEntry implements ComponentEntry {
@JsonKey(includeIfNull: false) final String? componentDescription, @JsonKey(includeIfNull: false) final String? componentDescription,
required final List<String> inputs, required final List<String> inputs,
required final List<String> outputs, required final List<String> outputs,
@JsonKey(includeIfNull: false) final List<String>? truthTable, @JsonKey(includeIfNull: false) final List<String>? truthTable}) =
@JsonKey(includeIfNull: false) final String? logicExpression}) =
_$_ComponentEntry; _$_ComponentEntry;
factory _ComponentEntry.fromJson(Map<String, dynamic> json) = factory _ComponentEntry.fromJson(Map<String, dynamic> json) =
@ -442,9 +419,6 @@ abstract class _ComponentEntry implements ComponentEntry {
@JsonKey(includeIfNull: false) @JsonKey(includeIfNull: false)
List<String>? get truthTable => throw _privateConstructorUsedError; List<String>? get truthTable => throw _privateConstructorUsedError;
@override @override
@JsonKey(includeIfNull: false)
String? get logicExpression => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$_ComponentEntryCopyWith<_$_ComponentEntry> get copyWith => _$$_ComponentEntryCopyWith<_$_ComponentEntry> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;

View file

@ -30,7 +30,6 @@ _$_ComponentEntry _$$_ComponentEntryFromJson(Map<String, dynamic> json) =>
truthTable: (json['truthTable'] as List<dynamic>?) truthTable: (json['truthTable'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList(), .toList(),
logicExpression: json['logicExpression'] as String?,
); );
Map<String, dynamic> _$$_ComponentEntryToJson(_$_ComponentEntry instance) { Map<String, dynamic> _$$_ComponentEntryToJson(_$_ComponentEntry instance) {
@ -49,6 +48,5 @@ Map<String, dynamic> _$$_ComponentEntryToJson(_$_ComponentEntry instance) {
val['inputs'] = instance.inputs; val['inputs'] = instance.inputs;
val['outputs'] = instance.outputs; val['outputs'] = instance.outputs;
writeNotNull('truthTable', instance.truthTable); writeNotNull('truthTable', instance.truthTable);
writeNotNull('logicExpression', instance.logicExpression);
return val; return val;
} }

View file

@ -1,9 +1,6 @@
import 'dart:math';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:logic_circuits_simulator/dialogs/new_ask_for_name.dart';
import 'package:logic_circuits_simulator/models/project.dart'; import 'package:logic_circuits_simulator/models/project.dart';
import 'package:logic_circuits_simulator/state/project.dart'; import 'package:logic_circuits_simulator/state/project.dart';
import 'package:logic_circuits_simulator/utils/iterable_extension.dart'; import 'package:logic_circuits_simulator/utils/iterable_extension.dart';
@ -21,12 +18,11 @@ class EditComponentPage extends HookWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final anySave = useState(false); final anySave = useState(false);
final projectState = useProvider<ProjectState>(); final projectState = useProvider<ProjectState>();
ComponentEntry ce() => projectState.index.components.where((c) => c.componentId == component.componentId).first; final ce = projectState.index.components.where((c) => c.componentId == component.componentId).first;
final truthTable = useState(ce().truthTable?.toList()); final truthTable = useState(ce.truthTable?.toList());
final logicExpression = useState(ce().logicExpression); final inputs = useState(ce.inputs.toList());
final inputs = useState(ce().inputs.toList()); final outputs = useState(ce.outputs.toList());
final outputs = useState(ce().outputs.toList()); final componentNameEditingController = useTextEditingController(text: ce.componentName);
final componentNameEditingController = useTextEditingController(text: ce().componentName);
useValueListenable(componentNameEditingController); useValueListenable(componentNameEditingController);
final dirty = useMemoized( final dirty = useMemoized(
() { () {
@ -42,37 +38,29 @@ class EditComponentPage extends HookWidget {
// Don't allow saving empty outputs // Don't allow saving empty outputs
return false; return false;
} }
if (truthTable.value == null && logicExpression.value == null) { if (componentNameEditingController.text != ce.componentName) {
// Don't allow saving components without functionality
return false;
}
if (componentNameEditingController.text != ce().componentName) {
return true; return true;
} }
if (!const ListEquality().equals(inputs.value, ce().inputs)) { if (!const ListEquality().equals(inputs.value, ce.inputs)) {
return true; return true;
} }
if (!const ListEquality().equals(outputs.value, ce().outputs)) { if (!const ListEquality().equals(outputs.value, ce.outputs)) {
return true; return true;
} }
if (!const ListEquality().equals(truthTable.value, ce().truthTable)) { if (!const ListEquality().equals(truthTable.value, ce.truthTable)) {
return true;
}
if (logicExpression.value != ce().logicExpression) {
return true; return true;
} }
return false; return false;
}, },
[ [
componentNameEditingController.text, componentNameEditingController.text,
ce().componentName, ce.componentName,
inputs.value, inputs.value,
ce().inputs, ce.inputs,
outputs.value, outputs.value,
ce().outputs, ce.outputs,
truthTable.value, truthTable.value,
ce().truthTable, ce.truthTable,
], ],
); );
@ -148,20 +136,8 @@ class EditComponentPage extends HookWidget {
IconButton( IconButton(
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
tooltip: 'Add new input', tooltip: 'Add new input',
onPressed: () async { onPressed: () {
final inputName = await showDialog<String>(
context: context,
builder: (context) {
return const NewAskForNameDialog(
title: 'New Input',
labelText: 'Input name',
);
},
);
if (inputName != null) {
truthTable.value = truthTable.value?.expand((element) => [element, element]).toList();
inputs.value = inputs.value.toList()..add(inputName);
}
}, },
), ),
], ],
@ -240,20 +216,8 @@ class EditComponentPage extends HookWidget {
IconButton( IconButton(
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
tooltip: 'Add new output', tooltip: 'Add new output',
onPressed: () async { onPressed: () {
final outputName = await showDialog<String>(
context: context,
builder: (context) {
return const NewAskForNameDialog(
title: 'New Output',
labelText: 'Output name',
);
},
);
if (outputName != null) {
truthTable.value = truthTable.value?.map((e) => '${e}0').toList();
outputs.value = outputs.value.toList()..add(outputName);
}
}, },
), ),
], ],
@ -307,48 +271,6 @@ class EditComponentPage extends HookWidget {
childCount: outputs.value.length, childCount: outputs.value.length,
), ),
), ),
if (truthTable.value == null && logicExpression.value == null) ...[
SliverToBoxAdapter(
child: Column(
children: [
const Divider(),
Text(
'Choose component kind',
style: Theme.of(context).textTheme.headline4,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () {
logicExpression.value = '';
},
child: const Text('Logic Expression'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: () {
final row = "0" * outputs.value.length;
truthTable.value = List.generate(pow(2, inputs.value.length) as int, (_) => row);
},
child: const Text('Truth Table'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: OutlinedButton(
onPressed: null,
child: const Text('Visual Designer'),
),
),
],
),
),
],
if (logicExpression.value != null) ...[
],
if (truthTable.value != null) ...[ if (truthTable.value != null) ...[
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
@ -378,9 +300,9 @@ class EditComponentPage extends HookWidget {
floatingActionButton: !dirty ? null : FloatingActionButton( floatingActionButton: !dirty ? null : FloatingActionButton(
onPressed: () async { onPressed: () async {
if (componentNameEditingController.text.isNotEmpty) { if (componentNameEditingController.text.isNotEmpty) {
await projectState.editComponent(ce().copyWith(componentName: componentNameEditingController.text)); await projectState.editComponent(component.copyWith(componentName: componentNameEditingController.text));
} }
await projectState.editComponent(ce().copyWith( await projectState.editComponent(ce.copyWith(
inputs: inputs.value, inputs: inputs.value,
outputs: outputs.value, outputs: outputs.value,
truthTable: truthTable.value, truthTable: truthTable.value,

View file

@ -28,7 +28,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.9.0" version: "2.8.2"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description: