You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

183 lines
5.1 KiB

import 'package:flutter/material.dart';
import 'package:logic_circuits_simulator/utils/iterable_extension.dart';
class TruthTableHeaderText extends StatelessWidget {
final String text;
final BoxBorder? border;
const TruthTableHeaderText(this.text, {super.key, this.border});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: border,
),
padding: const EdgeInsets.symmetric(
horizontal: 8,
),
child: Text(
text,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
);
}
}
class TruthTableTrue extends StatelessWidget {
final BoxBorder? border;
final void Function()? onTap;
const TruthTableTrue({super.key, this.border, this.onTap});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: border,
),
child: InkWell(
onTap: onTap,
child: Text(
'T',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: Colors.green,
fontSize: 20,
),
),
),
);
}
}
class TruthTableFalse extends StatelessWidget {
final BoxBorder? border;
final void Function()? onTap;
const TruthTableFalse({super.key, this.border, this.onTap});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: border,
),
child: InkWell(
onTap: onTap,
child: Text(
'F',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: Colors.red,
fontSize: 20,
),
),
),
);
}
}
class TruthTableEditor extends StatelessWidget {
static const marginBorder = BorderSide(
color: Colors.black,
width: 2,
);
static const innerBorder = BorderSide(
color: Colors.black45,
width: 1,
);
final List<String> inputs;
final List<String> outputs;
final List<String> truthTable;
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
Widget build(BuildContext context) {
return Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
border: TableBorder.symmetric(outside: const BorderSide(width: 2)),
children: List.generate(
truthTable.length + 1,
(index) {
if (index == 0) {
return TableRow(
children: inputs
.indexedMap<Widget>(
(index, e) => TruthTableHeaderText(
e,
border: Border(
bottom: marginBorder,
right: index == inputs.length - 1
? marginBorder
: innerBorder,
),
)
)
.followedBy(
outputs
.indexedMap(
(index, e) => TruthTableHeaderText(
e,
border: Border(
bottom: const BorderSide(width: 2),
right: index == outputs.length - 1
? BorderSide.none
: innerBorder,
),
)
)
)
.toList(),
);
}
final inputBinary = (index - 1).toRadixString(2).padLeft(inputs.length, '0');
final outputBinary = truthTable[index - 1];
Widget runeToWidget({required int rune, void Function()? onTap, BoxBorder? border}) {
return int.parse(String.fromCharCode(rune)) != 0
? TruthTableTrue(
border: border,
onTap: onTap,
)
: TruthTableFalse(
border: border,
onTap: onTap,
);
}
return TableRow(
children: inputBinary.runes.indexedMap(
(i, r) => runeToWidget(
rune: r,
border: i == inputBinary.runes.length - 1
? const Border(right: marginBorder)
: const Border(right: innerBorder),
)
)
.followedBy(outputBinary.runes.indexedMap(
(i, r) => runeToWidget(
rune: r,
border: i == outputBinary.runes.length - 1
? null
: const Border(right: innerBorder),
onTap: onUpdateTable == null ? null : () {
onUpdateTable!(index - 1, outputBinary.replaceRange(i, i+1, (outputBinary[i] == "1") ? "0" : "1"));
},
),
))
.toList(),
);
},
),
);
}
}