mirror of
https://github.com/dancojocaru2000/logic-circuits-simulator.git
synced 2025-02-21 16:49:36 +02:00
Added adding subcomponents
This commit is contained in:
parent
e2731623f1
commit
9e5cf4f92f
5 changed files with 107 additions and 11 deletions
|
@ -140,7 +140,7 @@ class VisualComponent extends HookWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
static double getHeightOfIO(BuildContext context, List<String> options, int index, [TextStyle? textStyle]) {
|
static double getHeightOfIO(BuildContext context, List<String> options, int index, [TextStyle? textStyle]) {
|
||||||
assert(index < options.length);
|
assert(index <= options.length);
|
||||||
getHeightOfText(String text) {
|
getHeightOfText(String text) {
|
||||||
final textPainter = TextPainter(
|
final textPainter = TextPainter(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
|
@ -163,7 +163,9 @@ class VisualComponent extends HookWidget {
|
||||||
for (var i = 0; i < index; i++) {
|
for (var i = 0; i < index; i++) {
|
||||||
result += 5.0 + getHeightOfText(options[i]) + 5.0;
|
result += 5.0 + getHeightOfText(options[i]) + 5.0;
|
||||||
}
|
}
|
||||||
result += 5.0 + getHeightOfText(options[index]);
|
if (index < options.length) {
|
||||||
|
result += 5.0 + getHeightOfText(options[index]);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ import 'package:logic_circuits_simulator/utils/future_call_debounce.dart';
|
||||||
import 'package:logic_circuits_simulator/utils/iterable_extension.dart';
|
import 'package:logic_circuits_simulator/utils/iterable_extension.dart';
|
||||||
import 'package:logic_circuits_simulator/utils/provider_hook.dart';
|
import 'package:logic_circuits_simulator/utils/provider_hook.dart';
|
||||||
import 'package:logic_circuits_simulator/utils/stack_canvas_controller_hook.dart';
|
import 'package:logic_circuits_simulator/utils/stack_canvas_controller_hook.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:stack_canvas/stack_canvas.dart';
|
import 'package:stack_canvas/stack_canvas.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
Key canvasKey = GlobalKey();
|
Key canvasKey = GlobalKey();
|
||||||
|
@ -56,6 +58,9 @@ class DesignComponentPage extends HookWidget {
|
||||||
final cs = componentState;
|
final cs = componentState;
|
||||||
// First remove all connected wires
|
// First remove all connected wires
|
||||||
if (w is DesignComponent) {
|
if (w is DesignComponent) {
|
||||||
|
// Get project state to be able to remove dependency
|
||||||
|
final projectState = Provider.of<ProjectState>(context, listen: false);
|
||||||
|
|
||||||
final wires = cs.wiringDraft.wires
|
final wires = cs.wiringDraft.wires
|
||||||
.where(
|
.where(
|
||||||
(wire) => wire.input.startsWith('${w.instanceId}/') || wire.output.startsWith('${w.instanceId}/')
|
(wire) => wire.input.startsWith('${w.instanceId}/') || wire.output.startsWith('${w.instanceId}/')
|
||||||
|
@ -63,6 +68,9 @@ class DesignComponentPage extends HookWidget {
|
||||||
.map((wire) => wire.wireId)
|
.map((wire) => wire.wireId)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
// Get component id before removing
|
||||||
|
final componentId = cs.wiringDraft.instances.where((inst) => inst.instanceId == w.instanceId).first.componentId;
|
||||||
|
|
||||||
await cs.updateDesign(cs.designDraft.copyWith(
|
await cs.updateDesign(cs.designDraft.copyWith(
|
||||||
wires: cs.designDraft.wires
|
wires: cs.designDraft.wires
|
||||||
.where((wire) => !wires.contains(wire.wireId))
|
.where((wire) => !wires.contains(wire.wireId))
|
||||||
|
@ -83,6 +91,12 @@ class DesignComponentPage extends HookWidget {
|
||||||
.where((comp) => comp.instanceId != w.instanceId)
|
.where((comp) => comp.instanceId != w.instanceId)
|
||||||
.toList(),
|
.toList(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Remove dependency if it's the last of its kind
|
||||||
|
if (!cs.wiringDraft.instances.map((inst) => inst.componentId).contains(componentId)) {
|
||||||
|
componentState.removeDependency(componentId, modifyCurrentComponent: true);
|
||||||
|
await projectState.editComponent(componentState.currentComponent!);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (w is DesignInput) {
|
else if (w is DesignInput) {
|
||||||
final wires = cs.wiringDraft.wires
|
final wires = cs.wiringDraft.wires
|
||||||
|
@ -534,7 +548,7 @@ class DesignComponentPage extends HookWidget {
|
||||||
hw(update.delta.dx, update.delta.dy);
|
hw(update.delta.dx, update.delta.dy);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onTapUp: (update) {
|
onTapUp: (update) async {
|
||||||
final canvasCenterLocation = canvasController.canvasSize / 2;
|
final canvasCenterLocation = canvasController.canvasSize / 2;
|
||||||
final canvasCenterLocationOffset = Offset(canvasCenterLocation.width, canvasCenterLocation.height);
|
final canvasCenterLocationOffset = Offset(canvasCenterLocation.width, canvasCenterLocation.height);
|
||||||
final canvasLocation = update.localPosition - canvasCenterLocationOffset + canvasController.offset;
|
final canvasLocation = update.localPosition - canvasCenterLocationOffset + canvasController.offset;
|
||||||
|
@ -603,7 +617,62 @@ class DesignComponentPage extends HookWidget {
|
||||||
designSelection.value = null;
|
designSelection.value = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
final currentProjectState = Provider.of<ProjectState>(context, listen: false);
|
||||||
|
|
||||||
// Add subcomponent
|
// Add subcomponent
|
||||||
|
final splitted = ds.split('/');
|
||||||
|
var projectId = splitted[0];
|
||||||
|
final componentId = splitted[1];
|
||||||
|
|
||||||
|
if (Provider.of<ProjectState>(context, listen: false).currentProject!.projectId == projectId) {
|
||||||
|
projectId = 'self';
|
||||||
|
}
|
||||||
|
|
||||||
|
final depId = '$projectId/$componentId';
|
||||||
|
final project = projectId == 'self'
|
||||||
|
? Provider.of<ProjectState>(context, listen: false).currentProject!
|
||||||
|
: Provider.of<ProjectsState>(context, listen: false).index.projects.where((p) => p.projectId == projectId).first;
|
||||||
|
final projectState = ProjectState();
|
||||||
|
await projectState.setCurrentProject(project);
|
||||||
|
final component = projectState.index.components.where((c) => c.componentId == componentId).first;
|
||||||
|
|
||||||
|
// Add dependency
|
||||||
|
if (!componentState.hasDependency(depId)) {
|
||||||
|
componentState.addDependency(
|
||||||
|
depId,
|
||||||
|
Tuple2(
|
||||||
|
project,
|
||||||
|
component,
|
||||||
|
),
|
||||||
|
modifyCurrentComponent: true,
|
||||||
|
);
|
||||||
|
await currentProjectState.editComponent(componentState.currentComponent!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create component instance
|
||||||
|
final instanceId = const Uuid().v4();
|
||||||
|
await componentState.updateWiring(componentState.wiringDraft.copyWith(
|
||||||
|
instances: componentState.wiringDraft.instances + [
|
||||||
|
WiringInstance(
|
||||||
|
componentId: depId,
|
||||||
|
instanceId: instanceId,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
await componentState.updateDesign(componentState.designDraft.copyWith(
|
||||||
|
components: componentState.designDraft.components + [
|
||||||
|
DesignComponent(
|
||||||
|
instanceId: instanceId,
|
||||||
|
x: canvasLocation.dx,
|
||||||
|
y: canvasLocation.dy,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
|
||||||
|
// Recreate simulation with new subcomponent
|
||||||
|
await componentState.recreatePartialSimulation();
|
||||||
|
|
||||||
|
designSelection.value = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
|
|
|
@ -115,7 +115,7 @@ class ComponentState extends ChangeNotifier {
|
||||||
unsatisfiedDependencies.add(depId);
|
unsatisfiedDependencies.add(depId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_dependenciesMap[depId] = maybeDep;
|
addDependency(depId, maybeDep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unsatisfiedDependencies.isNotEmpty) {
|
if (unsatisfiedDependencies.isNotEmpty) {
|
||||||
|
@ -124,10 +124,34 @@ class ComponentState extends ChangeNotifier {
|
||||||
|
|
||||||
await _loadComponentFiles();
|
await _loadComponentFiles();
|
||||||
|
|
||||||
if (component.visualDesigned) {
|
await recreatePartialSimulation();
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDependency(String depId, Tuple2<ProjectEntry, ComponentEntry> dependency, {bool modifyCurrentComponent = false}) {
|
||||||
|
_dependenciesMap[depId] = dependency;
|
||||||
|
if (modifyCurrentComponent && _currentComponent?.dependencies.contains(depId) == false) {
|
||||||
|
_currentComponent = _currentComponent?.copyWith(
|
||||||
|
dependencies: (_currentComponent?.dependencies ?? []) + [depId],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeDependency(String depId, {bool modifyCurrentComponent = false}) {
|
||||||
|
_dependenciesMap.remove(depId);
|
||||||
|
if (modifyCurrentComponent && _currentComponent?.dependencies.contains(depId) == true) {
|
||||||
|
_currentComponent = _currentComponent?.copyWith(
|
||||||
|
dependencies: _currentComponent?.dependencies.where((dep) => dep != depId).toList() ?? [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> recreatePartialSimulation() async {
|
||||||
|
if (_currentComponent!.visualDesigned) {
|
||||||
_partialVisualSimulation = await PartialVisualSimulation.init(
|
_partialVisualSimulation = await PartialVisualSimulation.init(
|
||||||
project: project,
|
project: _currentProject!,
|
||||||
component: component,
|
component: _currentComponent!,
|
||||||
state: this,
|
state: this,
|
||||||
onRequiredDependency: _onRequiredDependency,
|
onRequiredDependency: _onRequiredDependency,
|
||||||
);
|
);
|
||||||
|
@ -136,6 +160,8 @@ class ComponentState extends ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasDependency(String depId) => _dependenciesMap.containsKey(depId);
|
||||||
|
|
||||||
void noComponent() {
|
void noComponent() {
|
||||||
_dependenciesMap.clear();
|
_dependenciesMap.clear();
|
||||||
_currentProject = null;
|
_currentProject = null;
|
||||||
|
|
|
@ -90,8 +90,8 @@ class ProjectState extends ChangeNotifier {
|
||||||
await _updateIndex(
|
await _updateIndex(
|
||||||
index.copyWith(
|
index.copyWith(
|
||||||
components: index.components
|
components: index.components
|
||||||
.where((c) => c.componentId != component.componentId)
|
.map((c) => c.componentId == component.componentId ? component : c)
|
||||||
.toList() + [component],
|
.toList(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,7 @@ class ProjectsState extends ChangeNotifier {
|
||||||
await _updateIndex(
|
await _updateIndex(
|
||||||
index.copyWith(
|
index.copyWith(
|
||||||
projects: index.projects
|
projects: index.projects
|
||||||
.where((p) => p.projectId != project.projectId)
|
.map((p) => p.projectId == project.projectId ? project : p)
|
||||||
.followedBy([project])
|
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Reference in a new issue