package ui.controller; import java.awt.Point; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import classes.Edge; import classes.Node; import classes.GroupNode; import classes.AbstractCanvasObject; import classes.HolonObject; import classes.HolonSwitch; import classes.Position; import interfaces.ObjectListener; import ui.model.Model; /** * Controller for the Canvas. * * @author Gruppe14 */ public class CanvasController { private Model model; private MultiPurposeController mpC; /** * Constructor. * * @param model * the Model * @param mp * the MultipurposeController */ public CanvasController(Model model, MultiPurposeController mp) { this.model = model; this.mpC = mp; } /** * Add an CpsObject to the model and notify the ObjectListener for update. * * @param object * CpsObject to be added. * @param replace when true objects could be replaced */ public void addObject(AbstractCanvasObject object, boolean replace) { model.getCvsObjIdx().put(object.getId(), model.getObjectsOnCanvas().size()); model.getObjectsOnCanvas().add(object); /** * check if we should drag & drop replace */ if(!(object instanceof Node) && replace){ /** x of the dragged Object */ int x = object.getPosition().x; /** y of the dragged Object */ int y = object.getPosition().y; /** distance treshold for replacement */ int treshhold = model.getScale()/2; /** number of Objects that might be replaced (should be 1) */ int replaceCounter = 0; /** last object that could be replaced */ AbstractCanvasObject toBeReplaced = null; /** for each cps on Canvas */ for (AbstractCanvasObject cps : model.getObjectsOnCanvas()){ /** same object -> ignore */ if(cps == object)continue; /** x of object that might get replaced */ int c_x = cps.getPosition().x; /** y of object that might get replaced */ int c_y = cps.getPosition().y; /** if near enough */ if(Math.abs(x-c_x)()); addObject(object, true); } /** * adds the ObjectListener. * * @param objLis * ObjectListener */ public void addObjectListener(ObjectListener objLis) { model.getObjectListeners().add(objLis); } /** * notifies all listeners about changes in the Canvas. */ public void notifyObjListeners() { for (ObjectListener l : model.getObjectListeners()) { l.onChange(model.getObjectsOnCanvas()); } } /** * Deletes an CpsObject on the Canvas and its connections. * * @param obj * AbstractCpsObject */ public void deleteObjectOnCanvas(AbstractCanvasObject obj) { if (obj instanceof GroupNode) { this.bfsNodeCleaner((GroupNode) obj); } removeAllConnectionsFromObject(obj); mpC.decIdx(obj.getId(), model.getCvsObjIdx()); model.getCvsObjIdx().remove(obj.getId()); model.getObjectsOnCanvas().remove(obj); notifyObjListeners(); } /** * 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 replaceObjectOnCanvas(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) { //Replace edges ListIterator iter = model.getEdgesOnCanvas().listIterator(); while(iter.hasNext() ) { Edge edge = iter.next(); if(edge.getA() == toBeReplaced && edge.getB() != by) { edge.setA(by); } else if( edge.getB() == toBeReplaced && edge.getA() != by) { edge.setB(by); } } /** delete 'toBeReplaced' new empty connections, to prevent Nullpointer*/ toBeReplaced.setConnections(new ArrayList(1)); /** * set Position of by to exactly toBeReplaced */ by.setPosition(toBeReplaced.getPosition()); deleteObjectOnCanvas(toBeReplaced); } /** * Add an edge to the Canvas. * * @param edge * the edge */ public void addEdgeOnCanvas(Edge edge) { model.getEdgesOnCanvas().add(edge); } /** * Removes an Edge from the Canvas. * * @param edge * the edge to remove */ public void removeEdgesOnCanvas(Edge edge) { edge.getA().getConnections().remove(edge); edge.getB().getConnections().remove(edge); model.getEdgesOnCanvas().remove(edge); } /** * Paste all Selected Objects. * * @param p * the mouse Position */ public void pasteObjects(Point p) { model.getSelectedCpsObjects().clear(); AbstractCanvasObject tCps = null; int x = Integer.MAX_VALUE, y = Integer.MAX_VALUE; // Location whre to copy the Elements for (AbstractCanvasObject cps : model.getClipboradObjects()) { if (cps.getPosition().x < x) { x = cps.getPosition().x; } if (cps.getPosition().y < y) { y = cps.getPosition().y; } } ArrayList tempList = new ArrayList<>(); System.out.println("okay copy"); // Objects for (AbstractCanvasObject cps : model.getClipboradObjects()) { if (cps instanceof HolonObject) { System.out.println("copy"); tCps = new HolonObject((HolonObject) cps); } else if (cps instanceof HolonSwitch) { tCps = new HolonSwitch((HolonSwitch) cps); } else { tCps = new Node("Node"); } tCps.setPosition(new Position(p.x + (cps.getPosition().x - x), p.y + (cps.getPosition().y - y))); tCps.setSav(cps.getSav()); tempList.add(tCps); addObject(tCps, false); } // Edges boolean newEdge = true; for (AbstractCanvasObject cps : model.getClipboradObjects()) { for (Edge e : cps.getConnectedTo()) { // A and B of e in the copied Elements? if (model.getClipboradObjects().indexOf(e.getA()) != -1 && model.getClipboradObjects().indexOf(e.getB()) != -1) { AbstractCanvasObject a = tempList.get(model.getClipboradObjects().indexOf(e.getA())); AbstractCanvasObject b = tempList.get(model.getClipboradObjects().indexOf(e.getB())); // was this Edge created or not? for (Edge et : tempList.get(model.getClipboradObjects().indexOf(cps)).getConnectedTo()) { for (Edge etA : et.getA().getConnectedTo()) { if (et.getA() == a && et.getB() == b) { newEdge = false; } } for (Edge etB : et.getB().getConnectedTo()) { if (et.getA() == a && et.getB() == b) { newEdge = false; } } } if (newEdge) { Edge tempE = new Edge(tempList.get(model.getClipboradObjects().indexOf(e.getA())), // A tempList.get(model.getClipboradObjects().indexOf(e.getB())), /* B */ e.getCapacity()); addEdgeOnCanvas(tempE); } newEdge = true; } } } } /** * Cut all Selected Objects. */ @SuppressWarnings("unchecked") public void cutObjects() { model.setClipboradObjects((ArrayList) model.getSelectedCpsObjects().clone()); for (AbstractCanvasObject cps : model.getClipboradObjects()) { deleteObjectOnCanvas(cps); } model.getSelectedCpsObjects().clear(); } /** * 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 * * @param node */ public void bfsNodeCleaner(GroupNode node) { List objectsInGroupNode = node.getNodesAndGroupnodeNodes(); ListIterator iter = model.getEdgesOnCanvas().listIterator(); while(iter.hasNext() ) { Edge edge = iter.next(); if(objectsInGroupNode.contains(edge.getA()) || objectsInGroupNode.contains(edge.getB())) { iter.remove(); } } } public void removeAllConnectionsFromObject(AbstractCanvasObject obj) { ListIterator iter = model.getEdgesOnCanvas().listIterator(); while(iter.hasNext() ) { Edge edge = iter.next(); if(edge.getA() == obj || edge.getB() == obj) { iter.remove(); } } } /** * Deletes all Connections to Objects inside the to deleting UpperNode * * @param obj */ private void deleteConnections(AbstractCanvasObject obj) { ArrayDeque queue = new ArrayDeque<>(); Edge e = null; for (Edge edge : obj.getConnections()) { queue.add(edge); } while (!queue.isEmpty()) { e = queue.pop(); e.getA().getConnections().remove(e); e.getB().getConnections().remove(e); } } /** * Set the Background Image; * * @param imagePath * Image Path * @param mode * Image Mode * @param width * Image custom width * @param height * Image custom height */ public void setBackgroundImage(String imagePath, int mode, int width, int height) { model.setCanvasImagePath(imagePath); model.setCanvasImageMode(mode); model.setCanvasImageWidth(width); model.setCanvasImageHeight(height); } }