Browse Source

Added truth table editing

master
Kenneth Bruen 2 years ago
parent
commit
ce97a691a0
Signed by: kbruen
GPG Key ID: C1980A470C3EE5B1
  1. 134
      lib/pages/edit_component.dart
  2. 4
      pubspec.lock
  3. 1
      pubspec.yaml

134
lib/pages/edit_component.dart

@ -1,3 +1,4 @@
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/models/project.dart'; import 'package:logic_circuits_simulator/models/project.dart';
@ -18,18 +19,50 @@ class EditComponentPage extends HookWidget {
final anySave = useState(false); final anySave = useState(false);
final projectState = useProvider<ProjectState>(); final projectState = useProvider<ProjectState>();
final 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 inputs = useState(ce.inputs.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(
if (componentNameEditingController.text.isEmpty) { () {
// Don't allow saving empty name if (componentNameEditingController.text.isEmpty) {
// Don't allow saving empty name
return false;
}
if (inputs.value.isEmpty) {
// Don't allow saving empty inputs
return false;
}
if (outputs.value.isEmpty) {
// Don't allow saving empty outputs
return false;
}
if (componentNameEditingController.text != ce.componentName) {
return true;
}
if (!const ListEquality().equals(inputs.value, ce.inputs)) {
return true;
}
if (!const ListEquality().equals(outputs.value, ce.outputs)) {
return true;
}
if (!const ListEquality().equals(truthTable.value, ce.truthTable)) {
return true;
}
return false; return false;
} },
if (componentNameEditingController.text != ce.componentName) { [
return true; componentNameEditingController.text,
} ce.componentName,
return false; inputs.value,
}, [componentNameEditingController.text, ce.componentName]); ce.inputs,
outputs.value,
ce.outputs,
truthTable.value,
ce.truthTable,
],
);
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
@ -122,7 +155,7 @@ class EditComponentPage extends HookWidget {
childCount: ce.outputs.length, childCount: ce.outputs.length,
), ),
), ),
if (ce.truthTable != null) ...[ if (truthTable.value != null) ...[
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
@ -136,9 +169,12 @@ class EditComponentPage extends HookWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: TruthTableEditor( child: TruthTableEditor(
truthTable: ce.truthTable!, truthTable: truthTable.value!,
inputs: ce.inputs, inputs: inputs.value,
outputs: ce.outputs, outputs: outputs.value,
onUpdateTable: (idx, newValue) {
truthTable.value = truthTable.value?.toList()?..replaceRange(idx, idx+1, [newValue]);
},
), ),
), ),
) )
@ -150,6 +186,11 @@ class EditComponentPage extends HookWidget {
if (componentNameEditingController.text.isNotEmpty) { if (componentNameEditingController.text.isNotEmpty) {
await projectState.editComponent(component.copyWith(componentName: componentNameEditingController.text)); await projectState.editComponent(component.copyWith(componentName: componentNameEditingController.text));
} }
await projectState.editComponent(ce.copyWith(
inputs: inputs.value,
outputs: outputs.value,
truthTable: truthTable.value,
));
anySave.value = true; anySave.value = true;
// TODO: Implement saving // TODO: Implement saving
}, },
@ -187,8 +228,9 @@ class TruthTableHeaderText extends StatelessWidget {
class TruthTableTrue extends StatelessWidget { class TruthTableTrue extends StatelessWidget {
final BoxBorder? border; final BoxBorder? border;
final void Function()? onTap;
const TruthTableTrue({super.key, this.border}); const TruthTableTrue({super.key, this.border, this.onTap});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -196,12 +238,15 @@ class TruthTableTrue extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
border: border, border: border,
), ),
child: Text( child: InkWell(
'T', onTap: onTap,
textAlign: TextAlign.center, child: Text(
style: Theme.of(context).textTheme.bodyLarge!.copyWith( 'T',
color: Colors.green, textAlign: TextAlign.center,
fontSize: 20, style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: Colors.green,
fontSize: 20,
),
), ),
), ),
); );
@ -210,8 +255,9 @@ class TruthTableTrue extends StatelessWidget {
class TruthTableFalse extends StatelessWidget { class TruthTableFalse extends StatelessWidget {
final BoxBorder? border; final BoxBorder? border;
final void Function()? onTap;
const TruthTableFalse({super.key, this.border}); const TruthTableFalse({super.key, this.border, this.onTap});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -219,12 +265,15 @@ class TruthTableFalse extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
border: border, border: border,
), ),
child: Text( child: InkWell(
'F', onTap: onTap,
textAlign: TextAlign.center, child: Text(
style: Theme.of(context).textTheme.bodyLarge!.copyWith( 'F',
color: Colors.red, textAlign: TextAlign.center,
fontSize: 20, style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: Colors.red,
fontSize: 20,
),
), ),
), ),
); );
@ -236,7 +285,9 @@ class TruthTableEditor extends StatelessWidget {
final List<String> outputs; final List<String> outputs;
final List<String> truthTable; final List<String> truthTable;
const TruthTableEditor({Key? key, required this.inputs, required this.outputs, required this.truthTable}) : super(key: key); final void Function(int, String) onUpdateTable;
const TruthTableEditor({Key? key, required this.inputs, required this.outputs, required this.truthTable, required this.onUpdateTable}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -268,18 +319,33 @@ class TruthTableEditor extends StatelessWidget {
final inputBinary = (index - 1).toRadixString(2).padLeft(inputs.length, '0'); final inputBinary = (index - 1).toRadixString(2).padLeft(inputs.length, '0');
final outputBinary = truthTable[index - 1]; final outputBinary = truthTable[index - 1];
Widget runeToWidget(int rune, {BoxBorder? border}) { Widget runeToWidget({required int rune, void Function()? onTap, BoxBorder? border}) {
return int.parse(String.fromCharCode(rune)) != 0 ? TruthTableTrue(border: border) : TruthTableFalse(border: border); return int.parse(String.fromCharCode(rune)) != 0
? TruthTableTrue(
border: border,
onTap: onTap,
)
: TruthTableFalse(
border: border,
onTap: onTap,
);
} }
return TableRow( return TableRow(
children: inputBinary.runes.indexedMap( children: inputBinary.runes.indexedMap(
(index, r) => runeToWidget( (i, r) => runeToWidget(
r, rune: r,
border: index == inputBinary.runes.length - 1 ? const Border(right: BorderSide(width: 2)) : null, border: i == inputBinary.runes.length - 1 ? const Border(right: BorderSide(width: 2)) : null,
) )
) )
.followedBy(outputBinary.runes.map((r) => runeToWidget(r))) .followedBy(outputBinary.runes.indexedMap(
(i, r) => runeToWidget(
rune: r,
onTap: () {
onUpdateTable(index - 1, outputBinary.replaceRange(i, i+1, (outputBinary[i] == "1") ? "0" : "1"));
},
),
))
.toList(), .toList(),
); );
}, },

4
pubspec.lock

@ -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:
@ -128,7 +128,7 @@ packages:
source: hosted source: hosted
version: "4.1.0" version: "4.1.0"
collection: collection:
dependency: transitive dependency: "direct main"
description: description:
name: collection name: collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"

1
pubspec.yaml

@ -34,6 +34,7 @@ dependencies:
intl: ^0.17.0 intl: ^0.17.0
flutter_hooks: ^0.18.3 flutter_hooks: ^0.18.3
uuid: ^3.0.6 uuid: ^3.0.6
collection: ^1.16.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save