mirror of
				https://github.com/dancojocaru2000/logic-circuits-simulator.git
				synced 2025-10-31 06:56:31 +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]) { | ||||
|     assert(index < options.length); | ||||
|     assert(index <= options.length); | ||||
|     getHeightOfText(String text) { | ||||
|       final textPainter = TextPainter( | ||||
|         text: TextSpan( | ||||
|  | @ -163,7 +163,9 @@ class VisualComponent extends HookWidget { | |||
|     for (var i = 0; i < index; i++) { | ||||
|       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; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -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/provider_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:tuple/tuple.dart'; | ||||
| import 'package:uuid/uuid.dart'; | ||||
| 
 | ||||
| Key canvasKey = GlobalKey(); | ||||
|  | @ -56,6 +58,9 @@ class DesignComponentPage extends HookWidget { | |||
|         final cs = componentState; | ||||
|         // First remove all connected wires | ||||
|         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 | ||||
|             .where( | ||||
|               (wire) => wire.input.startsWith('${w.instanceId}/') || wire.output.startsWith('${w.instanceId}/') | ||||
|  | @ -63,6 +68,9 @@ class DesignComponentPage extends HookWidget { | |||
|             .map((wire) => wire.wireId) | ||||
|             .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( | ||||
|             wires: cs.designDraft.wires | ||||
|               .where((wire) => !wires.contains(wire.wireId)) | ||||
|  | @ -83,6 +91,12 @@ class DesignComponentPage extends HookWidget { | |||
|               .where((comp) => comp.instanceId != w.instanceId) | ||||
|               .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) { | ||||
|           final wires = cs.wiringDraft.wires | ||||
|  | @ -534,7 +548,7 @@ class DesignComponentPage extends HookWidget { | |||
|                 hw(update.delta.dx, update.delta.dy); | ||||
|               } | ||||
|             }, | ||||
|             onTapUp: (update) { | ||||
|             onTapUp: (update) async { | ||||
|               final canvasCenterLocation = canvasController.canvasSize / 2; | ||||
|               final canvasCenterLocationOffset = Offset(canvasCenterLocation.width, canvasCenterLocation.height); | ||||
|               final canvasLocation = update.localPosition - canvasCenterLocationOffset + canvasController.offset; | ||||
|  | @ -603,7 +617,62 @@ class DesignComponentPage extends HookWidget { | |||
|                 designSelection.value = null; | ||||
|               } | ||||
|               else { | ||||
|                 final currentProjectState = Provider.of<ProjectState>(context, listen: false); | ||||
| 
 | ||||
|                 // 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( | ||||
|  |  | |||
|  | @ -115,7 +115,7 @@ class ComponentState extends ChangeNotifier { | |||
|         unsatisfiedDependencies.add(depId); | ||||
|       } | ||||
|       else { | ||||
|         _dependenciesMap[depId] = maybeDep; | ||||
|         addDependency(depId, maybeDep); | ||||
|       } | ||||
|     } | ||||
|     if (unsatisfiedDependencies.isNotEmpty) { | ||||
|  | @ -124,10 +124,34 @@ class ComponentState extends ChangeNotifier { | |||
| 
 | ||||
|     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( | ||||
|         project: project, | ||||
|         component: component, | ||||
|         project: _currentProject!, | ||||
|         component: _currentComponent!, | ||||
|         state: this, | ||||
|         onRequiredDependency: _onRequiredDependency, | ||||
|       ); | ||||
|  | @ -136,6 +160,8 @@ class ComponentState extends ChangeNotifier { | |||
|     notifyListeners(); | ||||
|   } | ||||
| 
 | ||||
|   bool hasDependency(String depId) => _dependenciesMap.containsKey(depId); | ||||
| 
 | ||||
|   void noComponent() { | ||||
|     _dependenciesMap.clear(); | ||||
|     _currentProject = null; | ||||
|  |  | |||
|  | @ -90,8 +90,8 @@ class ProjectState extends ChangeNotifier { | |||
|     await _updateIndex( | ||||
|       index.copyWith( | ||||
|         components: index.components | ||||
|           .where((c) => c.componentId != component.componentId) | ||||
|           .toList() + [component], | ||||
|           .map((c) => c.componentId == component.componentId ? component : c) | ||||
|           .toList(), | ||||
|       ) | ||||
|     ); | ||||
|   } | ||||
|  |  | |||
|  | @ -73,8 +73,7 @@ class ProjectsState extends ChangeNotifier { | |||
|     await _updateIndex( | ||||
|       index.copyWith( | ||||
|         projects: index.projects | ||||
|           .where((p) => p.projectId != project.projectId) | ||||
|           .followedBy([project]) | ||||
|           .map((p) => p.projectId == project.projectId ? project : p) | ||||
|           .toList() | ||||
|       ) | ||||
|     ); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue