package holeg.ui.controller; import holeg.model.*; import holeg.ui.model.GuiSettings; import holeg.model.Model; import holeg.utility.math.vector.Vec2f; import holeg.utility.math.vector.Vec2i; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; /** * Controller for the Canvas. * * @author Gruppe14 */ public class CanvasController { private final Control control; /** * Constructor. * * @param control the Controller * */ public CanvasController(Control control) { this.control = control; } /** * Add an CpsObject to the model and notify the ObjectListener for update. * * @param object CpsObject to be added. */ public void addObject(GroupNode groupNode, AbstractCanvasObject object) { groupNode.add(object); } /** * Deletes an CpsObject on the Canvas and its connections. * * @param obj AbstractCpsObject */ public void deleteObject(AbstractCanvasObject obj) { if(obj instanceof GroupNode groupNode) { deleteAllObjectsInGroupNode(groupNode); control.OnRemoveGroupNode.broadcast(groupNode); }else{ removeAllConnectionsFromObject(obj); } obj.getGroupNode().ifPresent(groupNode -> groupNode.remove(obj)); } public void deleteObjects(Collection objects) { objects.forEach(this::deleteObject); } /** * Replaces {@code toBeReplaced} by {@code by} on the canvas * * @param toBeReplaced the object that will be replaced * @param by the object that will replace it */ public void replaceObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) { //Replace edges for (Edge edge : control.getModel().getEdgesOnCanvas()) { if (edge.getA() == toBeReplaced && edge.getB() != by) { if(control.doesEdgeExist(new Edge(by, edge.getB(), 0))){ continue; } edge.setA(by); } else if (edge.getB() == toBeReplaced && edge.getA() != by) { if(control.doesEdgeExist(new Edge(edge.getA(), by, 0))){ continue; } edge.setB(by); } } // set Position of by to exactly toBeReplaced by.setPosition(toBeReplaced.getPosition()); deleteObject(toBeReplaced); } /** * Add an edge to the Canvas. * * @param edge the edge */ public void addEdgeOnCanvas(Edge edge) { control.getModel().getEdgesOnCanvas().add(edge); } /** * Removes an Edge from the Canvas. * * @param edge the edge to remove */ public void removeEdgesOnCanvas(Edge edge) { control.getModel().getEdgesOnCanvas().remove(edge); } /** * Some cleaning Algorithm which traverses the UpperNode through BFS Can be * extended with other cleaning stuff No need for coloring since there tree * is only directed in one direction */ public void deleteAllObjectsInGroupNode(GroupNode node) { Set objectsInGroupNode = node.getAllObjectsRecursive().collect(Collectors.toSet()); control.getModel().getEdgesOnCanvas().removeIf(edge -> objectsInGroupNode.contains(edge.getA()) || objectsInGroupNode.contains(edge.getB())); } public void removeAllConnectionsFromObject(AbstractCanvasObject obj) { control.getModel().getEdgesOnCanvas().removeIf(edge -> edge.getA() == obj || edge.getB() == obj); } public void group(Set objects) { if(objects.isEmpty()){ return; } final GroupNode groupNode = new GroupNode("GroupNode"); groupNode.setPosition(GroupNode.calculateMiddlePosition(objects)); objects.stream().findFirst().flatMap(AbstractCanvasObject::getGroupNode) .ifPresent(parentGroupNode -> parentGroupNode.add(groupNode)); objects.forEach(object -> object.getGroupNode().ifPresent(old -> old.remove(object))); groupNode.addAll(objects); } public void ungroup(Set objects) { for(AbstractCanvasObject obj : objects){ if(obj instanceof GroupNode groupNode){ Vec2i middle = GroupNode.calculateMiddlePosition(groupNode.getObjectsInThisLayer().collect(Collectors.toList())); groupNode.getObjectsInThisLayer().forEach(child -> {child.setPosition(groupNode.getPosition().subtract(middle).add(child.getPosition())); child.getPosition().clampX(0, GuiSettings.canvasSize.getX()); child.getPosition().clampY(0, GuiSettings.canvasSize.getY());}); groupNode.ungroup(); control.OnRemoveGroupNode.broadcast(groupNode); } } } }