mirror of
https://github.com/dancojocaru2000/logic-circuits-simulator.git
synced 2025-02-21 16:49:36 +02:00
Added adding component IO
This commit is contained in:
parent
fc361b04d3
commit
e2731623f1
1 changed files with 162 additions and 19 deletions
|
@ -534,8 +534,16 @@ class DesignComponentPage extends HookWidget {
|
|||
hw(update.delta.dx, update.delta.dy);
|
||||
}
|
||||
},
|
||||
onTap: () {
|
||||
if (designSelection.value == 'wiring') {
|
||||
onTapUp: (update) {
|
||||
final canvasCenterLocation = canvasController.canvasSize / 2;
|
||||
final canvasCenterLocationOffset = Offset(canvasCenterLocation.width, canvasCenterLocation.height);
|
||||
final canvasLocation = update.localPosition - canvasCenterLocationOffset + canvasController.offset;
|
||||
final ds = designSelection.value;
|
||||
|
||||
if (ds == null) {
|
||||
return;
|
||||
}
|
||||
if (ds == 'wiring') {
|
||||
// Handle wire creation
|
||||
if (hoveredIO.value == null) {
|
||||
// If clicking on something not hovered, ignore
|
||||
|
@ -568,6 +576,35 @@ class DesignComponentPage extends HookWidget {
|
|||
hoveredIO.value = null;
|
||||
}
|
||||
}
|
||||
else if (ds.startsWith('input:')) {
|
||||
final inputName = ds.substring(6);
|
||||
componentState.updateDesign(componentState.designDraft.copyWith(
|
||||
inputs: componentState.designDraft.inputs + [
|
||||
DesignInput(
|
||||
name: inputName,
|
||||
x: canvasLocation.dx - IOComponent.getNeededWidth(context, inputName) / 2,
|
||||
y: canvasLocation.dy,
|
||||
),
|
||||
],
|
||||
));
|
||||
designSelection.value = null;
|
||||
}
|
||||
else if (ds.startsWith('output:')) {
|
||||
final outputName = ds.substring(7);
|
||||
componentState.updateDesign(componentState.designDraft.copyWith(
|
||||
outputs: componentState.designDraft.outputs + [
|
||||
DesignOutput(
|
||||
name: outputName,
|
||||
x: canvasLocation.dx - IOComponent.getNeededWidth(context, outputName) / 2,
|
||||
y: canvasLocation.dy,
|
||||
),
|
||||
],
|
||||
));
|
||||
designSelection.value = null;
|
||||
}
|
||||
else {
|
||||
// Add subcomponent
|
||||
}
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
|
@ -619,13 +656,14 @@ class DesignComponentPage extends HookWidget {
|
|||
|
||||
final componentPicker = ComponentPicker(
|
||||
key: pickerKey,
|
||||
onSeletionUpdate: (selection) {
|
||||
onSelectionUpdate: (selection) {
|
||||
designSelection.value = selection;
|
||||
if (selection != 'wiring') {
|
||||
wireToDelete.value = null;
|
||||
sourceToConnect.value = null;
|
||||
}
|
||||
},
|
||||
selection: designSelection.value,
|
||||
);
|
||||
|
||||
if (orientation == Orientation.portrait) {
|
||||
|
@ -726,33 +764,29 @@ class DebuggingButtons extends StatelessWidget {
|
|||
}
|
||||
|
||||
class ComponentPicker extends HookWidget {
|
||||
const ComponentPicker({required this.onSeletionUpdate, super.key});
|
||||
const ComponentPicker({required this.onSelectionUpdate, required this.selection, super.key});
|
||||
|
||||
final void Function(String? selection) onSeletionUpdate;
|
||||
final String? selection;
|
||||
final void Function(String? selection) onSelectionUpdate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final projectsState = useProvider<ProjectsState>();
|
||||
final tickerProvider = useSingleTickerProvider();
|
||||
final selection = useState<String?>(null);
|
||||
final tabBarControllerState = useState<TabController?>(null );
|
||||
final tabBarControllerState = useState<TabController?>(null);
|
||||
useEffect(() {
|
||||
selection.addListener(() {
|
||||
onSeletionUpdate(selection.value);
|
||||
});
|
||||
|
||||
tabBarControllerState.value = TabController(
|
||||
length: 1 + projectsState.projects.length,
|
||||
length: 3 + projectsState.projects.length,
|
||||
vsync: tickerProvider,
|
||||
initialIndex: 1,
|
||||
);
|
||||
|
||||
tabBarControllerState.value!.addListener(() {
|
||||
if (tabBarControllerState.value!.index == 0) {
|
||||
selection.value = 'wiring';
|
||||
onSelectionUpdate('wiring');
|
||||
}
|
||||
else {
|
||||
selection.value = null;
|
||||
onSelectionUpdate(null);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -776,6 +810,12 @@ class ComponentPicker extends HookWidget {
|
|||
const Tab(
|
||||
text: 'Wiring',
|
||||
),
|
||||
const Tab(
|
||||
text: 'Inputs',
|
||||
),
|
||||
const Tab(
|
||||
text: 'Outputs',
|
||||
),
|
||||
for (final project in projectsState.projects)
|
||||
Tab(
|
||||
text: project.projectName,
|
||||
|
@ -806,6 +846,18 @@ class ComponentPicker extends HookWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
IOComponentPickerOptions(
|
||||
orientation: orientation,
|
||||
outputs: false,
|
||||
selection: selection,
|
||||
onSelected: onSelectionUpdate,
|
||||
),
|
||||
IOComponentPickerOptions(
|
||||
orientation: orientation,
|
||||
outputs: true,
|
||||
selection: selection,
|
||||
onSelected: onSelectionUpdate,
|
||||
),
|
||||
for (final project in projectsState.projects)
|
||||
HookBuilder(
|
||||
builder: (context) {
|
||||
|
@ -844,21 +896,21 @@ class ComponentPicker extends HookWidget {
|
|||
for (final component in components)
|
||||
IntrinsicWidth(
|
||||
child: Card(
|
||||
color: selection.value == '${project.projectId}/${component.componentId}' ? Theme.of(context).colorScheme.primaryContainer : null,
|
||||
color: selection == '${project.projectId}/${component.componentId}' ? Theme.of(context).colorScheme.primaryContainer : null,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if (selection.value != '${project.projectId}/${component.componentId}') {
|
||||
selection.value = '${project.projectId}/${component.componentId}';
|
||||
if (selection != '${project.projectId}/${component.componentId}') {
|
||||
onSelectionUpdate('${project.projectId}/${component.componentId}');
|
||||
}
|
||||
else {
|
||||
selection.value = null;
|
||||
onSelectionUpdate(null);
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
component.componentName,
|
||||
style: selection.value == '${project.projectId}/${component.componentId}'
|
||||
style: selection == '${project.projectId}/${component.componentId}'
|
||||
? TextStyle(
|
||||
inherit: true,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
|
@ -888,3 +940,94 @@ class ComponentPicker extends HookWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class IOComponentPickerOptions extends HookWidget {
|
||||
final Orientation orientation;
|
||||
final bool outputs;
|
||||
final String? selection;
|
||||
final void Function(String? selection) onSelected;
|
||||
|
||||
const IOComponentPickerOptions({required this.orientation, required this.outputs, required this.selection, required this.onSelected, super.key,});
|
||||
|
||||
String getSelectionName(String option) => '${!outputs ? "input" : "output"}:$option';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final componentState = useProvider<ComponentState>();
|
||||
|
||||
final scrollController = useScrollController();
|
||||
|
||||
final options = !outputs ? componentState.currentComponent!.inputs : componentState.currentComponent!.outputs;
|
||||
|
||||
return Builder(
|
||||
builder: (context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text('To add an ${!outputs ? "input" : "output"}, select it below and then click on the canvas to place it. You can only add one of each. Red ${!outputs ? "inputs" : "outputs"} have already been placed.'),
|
||||
),
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
controller: scrollController,
|
||||
scrollbarOrientation: orientation == Orientation.portrait ? ScrollbarOrientation.bottom : ScrollbarOrientation.right,
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
scrollDirection: orientation == Orientation.portrait ? Axis.horizontal : Axis.vertical,
|
||||
child: Wrap(
|
||||
direction: orientation == Orientation.portrait ? Axis.vertical : Axis.horizontal,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
for (final option in options)
|
||||
IntrinsicWidth(
|
||||
child: Card(
|
||||
color: (
|
||||
!outputs
|
||||
? componentState.designDraft.inputs.map((input) => input.name).contains(option)
|
||||
: componentState.designDraft.outputs.map((output) => output.name).contains(option)
|
||||
)
|
||||
? const Color.fromARGB(100, 255, 0, 0)
|
||||
: selection == getSelectionName(option)
|
||||
? Theme.of(context).colorScheme.primaryContainer
|
||||
: null,
|
||||
child: InkWell(
|
||||
onTap: (
|
||||
!outputs
|
||||
? componentState.designDraft.inputs.map((input) => input.name).contains(option)
|
||||
: componentState.designDraft.outputs.map((output) => output.name).contains(option)
|
||||
) ? null : () {
|
||||
if (selection == getSelectionName(option)) {
|
||||
onSelected(null);
|
||||
}
|
||||
else {
|
||||
onSelected(getSelectionName(option));
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
option,
|
||||
style: selection == getSelectionName(option)
|
||||
? TextStyle(
|
||||
inherit: true,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue