package holeg.ui.view.canvas; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Line2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.Optional; import java.util.logging.Logger; import java.util.stream.Collectors; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import com.google.gson.JsonParseException; import holeg.model.AbstractCanvasObject; import holeg.model.Edge; import holeg.model.GroupNode; import holeg.model.HolonObject; import holeg.model.HolonObject.HolonObjectState; import holeg.model.HolonSwitch.SwitchMode; import holeg.model.HolonSwitch; import holeg.model.Node; import holeg.preferences.ColorPreference; import holeg.preferences.ImagePreference; import holeg.ui.controller.Control; import holeg.ui.model.GuiSettings; import holeg.ui.view.inspector.UnitGraph; import holeg.utility.image.Import; import holeg.utility.math.vector.Vec2i; /** * This Class is the Canvas. All Objects will be visualized here * * @author Gruppe14 */ public class Canvas extends AbstractCanvas implements MouseListener, MouseMotionListener { private static final Logger log = Logger.getLogger(Canvas.class.getName()); private static final long serialVersionUID = 1L; public boolean disabled = false; GroupNode groupNode = null; private static Color[] colors = { ColorPreference.HolonObject.Producer, ColorPreference.HolonObject.NotSupplied, ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.Supplied, ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.NoEnergy }; /** * Constructor. * * @param mod the Model * @param control the Controller * @param unitGraph */ public Canvas(Control control, UnitGraph unitGraph, GroupNode groupNode) { toolTip = false; this.control = control; this.model = control.getModel(); this.groupNode = groupNode; showConnectionInformation = true; popmenu.add(itemCut); popmenu.add(itemCopy); popmenu.add(itemPaste); popmenu.add(itemDelete); popmenu.add(itemAlign); popmenu.addSeparator(); popmenu.add(itemGroup); popmenu.add(itemUngroup); popmenu.add(itemCreateTemplate); itemDelete.setEnabled(false); itemCut.setEnabled(false); itemCopy.setEnabled(false); itemPaste.setEnabled(true); itemAlign.setEnabled(false); itemGroup.setEnabled(false); itemUngroup.setEnabled(false); itemCut.setText("Cut"); itemGroup.addActionListener(actionEvent -> { // calculate uppernode pos (taken from the controller) unPos = new Vec2i(0, 0); animCps = new ArrayList<>(); for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) { animCps.add(cps); // add to animation Cps ArrayList unPos = unPos.add(cps.getPosition()); } unPos = unPos.divide(animCps.size()); // save old Position savePos = new ArrayList<>(); for (int i = 0; i < animCps.size(); i++) { savePos.add(new Vec2i(animCps.get(i).getPosition())); } animT = new javax.swing.Timer(animDelay, actionEvent1 -> { if (animDuration - animDelay > 0 && animCps.size() > 1) { for (AbstractCanvasObject animCpObject : animCps) { Vec2i pos = animCpObject.getPosition(); Vec2i difference = pos.subtract(unPos); Vec2i result = pos.subtract(difference.divide(animSteps)); pos.set(result); } repaint(); animDuration -= animDelay; animSteps--; } else { animDuration = ANIMTIME; animSteps = animDuration / animDelay; animT.stop(); for (int i = 0; i < animCps.size(); i++) { animCps.get(i).getPosition().set(savePos.get(i)); } control.addGroupNode("GroupNode", groupNode, animCps); control.calculateStateAndVisualForCurrentTimeStep(); control.clearSelection(); repaint(); } }); animT.start(); }); itemUngroup.addActionListener(actionEvent -> { // save old Position int upperNodeId = tempCps.getId(); closeUpperNodeTab(upperNodeId); savePos = new ArrayList<>(); animCps = ((GroupNode) tempCps).getAllObjectsRecursive().toList(); control.undoGroupNode((GroupNode) tempCps, groupNode); for (int i = 0; i < animCps.size(); i++) { savePos.add(new Vec2i(animCps.get(i).getPosition())); } for (AbstractCanvasObject cps : animCps) { int x = tempCps.getPosition().getX(); int y = tempCps.getPosition().getY(); cps.setPosition(new Vec2i(x, y)); } animT = new javax.swing.Timer(animDelay, actionEvent1 -> { control.clearSelection(); if (animDuration - animDelay >= 0) { for (int i = 0; i < animCps.size(); i++) { Vec2i pos = animCps.get(i).getPosition(); Vec2i difference = pos.subtract(savePos.get(i)); Vec2i result = pos.subtract(difference.divide(animSteps)); pos.set(result); } repaint(); animDuration -= animDelay; animSteps--; } else { animDuration = ANIMTIME; animSteps = animDuration / animDelay; animT.stop(); for (int i = 0; i < animCps.size(); i++) { animCps.get(i).getPosition().set(savePos.get(i)); } control.calculateStateAndVisualForCurrentTimeStep(); repaint(); } }); animT.start(); }); // adds the selected object(s) to the statistic panel itemDelete.addActionListener(actionEvent -> { // Remove the selected Object objects // Edge Deleting if (tempCps == null && edgeHighlight != null) { control.removeEdgesOnCanvas(edgeHighlight); // Look for a CPSNode with no Connections and delete them if (edgeHighlight.getA() instanceof Node) { control.delCanvasObject(edgeHighlight.getA(), false); } if (edgeHighlight.getB() instanceof Node) { // Look on the other end of the cable control.delCanvasObject(edgeHighlight.getB(), false); } edgeHighlight = null; } for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) { control.delCanvasObject(cps, false); toolTip = false; } control.tryAutoSave(); control.clearSelection(); tempCps = null; repaint(); }); itemCut.addActionListener(actionEvent -> { control.cut(null); itemPaste.setEnabled(true); repaint(); }); itemCopy.addActionListener(actionEvent -> { if (tempCps instanceof GroupNode) control.getObjectsInDepth(); control.copy(null); itemPaste.setEnabled(true); repaint(); }); itemAlign.addActionListener(actionEvent -> { for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) align(cps, GuiSettings.getPictureScaleDiv2()); repaint(); }); itemPaste.addActionListener(actionEvent -> { try { control.paste(null, mousePosition); } catch (JsonParseException | UnsupportedFlavorException | IOException e1) { JLabel message = new JLabel("The Clipboard information cannot be pastet into Application."); JOptionPane.showMessageDialog(null, message, "", JOptionPane.ERROR_MESSAGE); } repaint(); }); /* * create Template */ itemCreateTemplate.addActionListener(actionEvent -> { control.createTemplate((HolonObject) tempCps, (JFrame) SwingUtilities.getRoot(this)); }); this.addMouseListener(this); this.addMouseMotionListener(this); } /** * Paints all Components on the Canvas. * * @param g Graphics */ // protected void paintCanvasObject(Graphics2D g, DecoratedHolonObject decoratedHolonObject) { // Vec2i pos = decoratedHolonObject.getModel().getPosition(); // Color statecolor = ColorPreference.HolonObject.getStateColor(decoratedHolonObject.getState()); // g.setColor(statecolor); // g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(), // GuiSettings.getPictureScale(), GuiSettings.getPictureScale()); // drawCanvasObject(g, decoratedHolonObject.getModel().getImage(), pos); // } // // protected void drawCanvasObjectString(Graphics2D g, Vec2i posOfCanvasObject, float energy) { // g.setColor(Color.BLACK); // g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (GuiSettings.getPictureScale() / 4f))); // g.drawString((energy > 0) ? "+" + Float.toString(energy) : Float.toString(energy), // posOfCanvasObject.getX() - GuiSettings.getPictureScaleDiv2(), // posOfCanvasObject.getY() - GuiSettings.getPictureScaleDiv2() - 1); // } // // protected void paintConsumer(Graphics2D g, Consumer con) { // paintCanvasObject(g, con); // drawCanvasObjectString(g, con.getModel().getPosition(), -con.getEnergyNeededFromNetwork()); // if (GuiSettings.showSupplyBars) { // paintSupplyBar(g, con.getSupplyBarPercentage(), ColorPreference.HolonObject.getStateColor(con.getState()), // con.getModel().getPosition()); // } // } // // protected void paintSupplier(Graphics2D g, Supplier sup) { // paintCanvasObject(g, sup); // drawCanvasObjectString(g, sup.getModel().getPosition(), sup.getEnergyToSupplyNetwork()); // } // // protected void drawCanvasObject(Graphics2D g, String Image, Vec2i pos) { // g.drawImage(Import.loadImage(Image, GuiSettings.getPictureScale(), GuiSettings.getPictureScale()), // pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScale(), // GuiSettings.getPictureScale(), null); // } // // protected void paintCable(Graphics2D g, Edge cable, boolean isSelected) { // Vec2i start = cable.getA().getPosition(); // Vec2i end = cable.getB().getPosition(); // float currentEnergy = cable.getActualFlow(); // float capacity = cable.maxCapacity; // boolean unlimited = cable.isUnlimitedCapacity(); // switch (cable.getState()) { // case Burned: // g.setColor(ColorPreference.Edge.Burned); // g.setStroke(new BasicStroke(2)); // break; // case Working: // g.setColor(ColorPreference.Edge.Working); // g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1)); // break; // } // if (isSelected) { // g.setColor(Color.lightGray); // } // g.drawLine(start.getX(), start.getY(), end.getX(), end.getY()); // if (showConnectionInformation) { // Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2); // g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10))); // g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY()); // } // } // // protected void paintSwitch(Graphics2D g, DecoratedSwitch dSwitch) { // drawCanvasObject(g, dSwitch.getState() == SwitchState.Open ? HolonSwitch.getSwitchOpenImage() // : HolonSwitch.getSwitchClosedImage(), dSwitch.getModel().getPosition()); // } // // protected void paintExitCable(Graphics2D g, ExitCable eCable) { // Vec2i start = eCable.getStart().getPosition(); // Vec2i end = eCable.getFinish().getPosition(); // float currentEnergy; // float capacity = eCable.getEdge().maxCapacity; // boolean unlimited = eCable.getEdge().isUnlimitedCapacity(); // if(eCable.getEdge().getState() == null) { // System.err.print(eCable.getEdge()); // } // switch (eCable.getEdge().getState()) { // case Burned: // currentEnergy = 0.0f; // g.setColor(Color.RED); // g.setStroke(new BasicStroke(2)); // break; // case Working: // default: // currentEnergy = eCable.getEdge().getActualFlow(); // g.setColor(new Color(13, 175, 28)); // g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1)); // break; // } // g.drawLine(start.getX(), start.getY(), end.getX(), end.getY()); // Vec2i middle = new Vec2i((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2); // g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10))); // g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY()); // } // // protected void paintGroupNode(Graphics2D g, DecoratedGroupNode dGroupNode) { // Vec2i pos = dGroupNode.getModel().getPosition(); // g.setColor(Color.lightGray); // g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(), // GuiSettings.getPictureScale(), GuiSettings.getPictureScale()); // drawCanvasObject(g, ImagePreference.Canvas.GroupNode, pos); // paintGroupNodeBar(g, dGroupNode, pos); // } // // private void paintGroupNodeBar(Graphics2D g, DecoratedGroupNode dGroupNode, Vec2i pos) { // // +1, -2, -1 little Adjustment for pixel perfect alignment // int barWidth = (int) (GuiSettings.getPictureScale()); // int barHeight = (int) (GuiSettings.getPictureScale() / 5); // g.setColor(Color.WHITE); // g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth, // barHeight); // float[] percentages = getGroupNodeBarPercentages(dGroupNode); // // for (int i = 5; i >= 0; i--) { // g.setColor(colors[i]); // g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, // (int) (barWidth * percentages[i] - 1), barHeight); // } //// g.setColor(color); //// g.fillRect(pos.getX() - GuiSettings.GetPictureScaleDiv2(), pos.getY() + GuiSettings.GetPictureScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight); // g.setColor(Color.BLACK); // g.setStroke(new BasicStroke(1)); // g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1, // barHeight); // } // // /** // * HardCoded Stuff dont try at Home ;) // * // * @param dGroupNode // * @return // */ // public float[] getGroupNodeBarPercentages(DecoratedGroupNode dGroupNode) { // int[] amountOfObjects = new int[6]; // amountOfObjects[0] = dGroupNode.getAmountOfSupplier(); // amountOfObjects[1] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED); // amountOfObjects[2] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED); // amountOfObjects[3] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED); // amountOfObjects[4] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED); // amountOfObjects[5] = dGroupNode.getAmountOfPassiv(); // int countHolonObjects = amountOfObjects[0] + amountOfObjects[1] + amountOfObjects[2] + amountOfObjects[3] // + amountOfObjects[4] + amountOfObjects[5]; // float[] percentages = new float[6]; // int count = 0; // for (int i = 0; i < 6; i++) { // count += amountOfObjects[i]; // percentages[i] = (float) count / (float) countHolonObjects; // } // return percentages; // } private void paintSupplyBar(Graphics2D g, float percentage, Color color, Vec2i pos) { // +1, -2, -1 little Adjustment for pixel perfect alignment int barWidth = (int) (GuiSettings.getPictureScale()); int barHeight = (int) (GuiSettings.getPictureScale() / 5); g.setColor(Color.WHITE); g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth, barHeight); g.setColor(color); g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight); g.setColor(Color.BLACK); g.setStroke(new BasicStroke(1)); g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1, barHeight); g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (barHeight * 1.5) - 2)); String percentageString = (Math.round((percentage * 100))) + "%"; int stringWidth = (int) g.getFontMetrics().getStringBounds(percentageString, g).getWidth(); if (percentage > 1.0f) g.setColor(Color.WHITE); // Just to see better on purple g.drawString(percentageString, pos.getX() + 1 - stringWidth / 2, pos.getY() + GuiSettings.getPictureScaleDiv2() - 1 + barHeight); } // old code void drawMarker(Graphics2D g) { Color transparentGrey = ColorPreference.Panel.ObjectSelection; if (sx > x && sy > y) { g.drawRect(x, y, sx - x, sy - y); g.setColor(transparentGrey); g.fillRect(x, y, sx - x, sy - y); } else if (sx < x && sy < y) { g.drawRect(sx, sy, x - sx, y - sy); g.setColor(transparentGrey); g.fillRect(sx, sy, x - sx, y - sy); } else if (sx >= x) { g.drawRect(x, sy, sx - x, y - sy); g.setColor(transparentGrey); g.fillRect(x, sy, sx - x, y - sy); } else if (sy >= y) { g.drawRect(sx, y, x - sx, sy - y); g.setColor(transparentGrey); g.fillRect(sx, y, x - sx, sy - y); } } public void paintComponent(Graphics g) { super.paintComponent(g); // Graphics2D g2d = (Graphics2D) g; // g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); // // -->Old code TODO(Tom2021-12-1): remove // if (drawEdge) { // g2d.setColor(Color.BLACK); // g2d.setStroke(new BasicStroke(1)); // g2d.drawLine(tempCps.getPosition().getX(), tempCps.getPosition().getY(), x, y); // } // // <-- // // timstep: // g.setFont(new Font("TimesNewRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10))); // g2d.setColor(Color.BLACK); // // Optional optVisualState = control.getSimManager().getActualVisualRepresentationalState(); // // VisualState Representation: // if (optVisualState.isEmpty()) { // return; // } // VisualRepresentationalState visualState = optVisualState.get(); // // for (ExitCable cable : visualState.getExitCableList()) { // paintExitCable(g2d, cable); // } // for (Edge cable : visualState.getCableList()) { // paintCable(g2d, cable, GuiSettings.getSelectedEdges().contains(cable)); // } // for (DecoratedGroupNode dGroupNode : visualState.getGroupNodeList()) { // paintGroupNode(g2d, dGroupNode); // } // log.info(visualState.getConsumerList().stream().map(Object::toString).collect(Collectors.joining(", "))); // for (Consumer con : visualState.getConsumerList()) { // paintConsumer(g2d, con); // } // log.info(visualState.getSupplierList().stream().map(Object::toString).collect(Collectors.joining(", "))); // for (Supplier sup : visualState.getSupplierList()) { // paintSupplier(g2d, sup); // } // for (Passiv pas : visualState.getPassivList()) { // paintCanvasObject(g2d, pas); // } // for (DecoratedSwitch dSwitch : visualState.getSwitchList()) { // paintSwitch(g2d, dSwitch); // } // for (Node node : visualState.getNodeList()) { // drawCanvasObject(g2d, ImagePreference.Canvas.Node.Unselected, node.getPosition()); // } // // // -->oldCode // if (doMark) { // g2d.setColor(Color.BLACK); // g2d.setStroke(new BasicStroke(0)); // drawMarker(g2d); // } // // Test Selection // // Objects: // g2d.setColor(Color.BLUE); // g2d.setStroke(new BasicStroke(1)); // Color transparentGrey = ColorPreference.Panel.ObjectSelection; // for (AbstractCanvasObject aCps : GuiSettings.getSelectedObjects()) { // if (aCps instanceof Node) { // Vec2i pos = aCps.getPosition(); // g2d.setColor(transparentGrey); // g2d.fillOval(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2()), // pos.getY() - (int) (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale()); // g2d.setColor(Color.LIGHT_GRAY); // g2d.setStroke(new BasicStroke(2)); // g2d.drawOval(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2()), // pos.getY() - (int) (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale()); // } else { // Vec2i pos = aCps.getPosition(); // g2d.setColor(transparentGrey); // g2d.fillRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), // pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f), // (int) (GuiSettings.getPictureScale() * 1.5f)); // g2d.setColor(Color.LIGHT_GRAY); // g2d.setStroke(new BasicStroke(2)); // g2d.drawRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), // pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f), // (int) (GuiSettings.getPictureScale() * 1.5f)); // } // // } // // maybeReplace: // if (mayBeReplaced != null) { // g2d.setColor(Color.RED); // Vec2i pos = mayBeReplaced.getPosition(); // g2d.drawImage(Import.loadImage(ImagePreference.Canvas.ReplaceSymbol), pos.getX() + GuiSettings.getPictureScaleDiv2(), // pos.getY() - GuiSettings.getPictureScale(), GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScaleDiv2(), null); // } // // <-- OldCode } @Override public void mouseClicked(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { this.grabFocus(); if (!disabled) { tempCps = null; edgeHighlight = null; GuiSettings.getSelectedEdges().clear(); // Object Selection for (AbstractCanvasObject cps : groupNode.getObjectsInThisLayer().toList()) { cx = cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2(); cy = cps.getPosition().getY() - GuiSettings.getPictureScaleDiv2(); if (x - GuiSettings.getPictureScale() <= cx && y - GuiSettings.getPictureScale() <= cy && x >= cx && y >= cy) { tempCps = cps; dragging = true; if (e.isControlDown() && tempCps != null) { System.out.println("Add Remove Selection CANVAS"); if (GuiSettings.getSelectedObjects().contains(tempCps)) { control.removeObjectFromSelection(tempCps); } else { control.addSelectedObject(tempCps); } } if (e.isShiftDown()) { drawEdge = true; dragging = false; } } } // Edge Selection if (tempCps == null) { edgeHighlight = mousePositionOnEdge(x, y); GuiSettings.getSelectedEdges().add(edgeHighlight); if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) { control.clearSelection(); } } if (edgeHighlight == null && tempCps == null) { sx = e.getX(); sy = e.getY(); doMark = true; } repaint(); } } @Override public void mouseReleased(MouseEvent e) { if (!disabled) { x = e.getX(); y = e.getY(); dragging = false; if (drawEdge) { drawEdge = false; drawDeleteEdge(); } if (dragged) { control.tryAutoSave(); /** * check if a unique tempCps could replace an Object on the canvas */ if (GuiSettings.getSelectedObjects().size() == 1 && checkForReplacement(groupNode.getObjectsInThisLayer(), tempCps, tempCps.getPosition().getX(), tempCps.getPosition().getY())) { /** * if UpperNode would be replaced, close its tabs */ if (mayBeReplaced instanceof GroupNode) closeUpperNodeTab(mayBeReplaced.getId()); /** * replace on canvas (will save) */ control.replaceCanvasObject(mayBeReplaced, tempCps); mayBeReplaced = null; } } if (!e.isControlDown() && !dragged && tempCps != null && MouseEvent.BUTTON3 != e.getButton()) { control.clearSelection(); control.addSelectedObject(tempCps); if (tempCps instanceof GroupNode) control.getObjectsInDepth(); } dragged = false; // Rightclick List setRightClickMenu(e); markObjects(); boolean doubleclick = doubleClick(); if (doubleclick && tempCps instanceof HolonSwitch sw && MouseEvent.BUTTON3 != e.getButton() && tempCps != null) { sw.setMode(SwitchMode.Manual); sw.flipManualState(); } if (doubleclick && tempCps != null && tempCps instanceof GroupNode groupnode) { control.getGui().openNewUpperNodeTab(groupnode); } control.calculateStateAndVisualForTimeStep(model.getCurrentIteration()); repaint(); } } @Override public void mouseDragged(MouseEvent e) { if (!disabled) { // If Edge is drawn x = e.getX(); y = e.getY(); if (!GuiSettings.getSelectedObjects().contains(tempCps) && !doMark) { control.clearSelection(); if (tempCps != null) { control.addSelectedObject(tempCps); } } if (dragging) { try { dragged = true; float xDist, yDist; // Distance x = e.getX(); y = e.getY(); // Make sure its in bounds int scaleDiv2 = GuiSettings.getPictureScaleDiv2(); if (e.getX() < scaleDiv2) x = scaleDiv2; else if (e.getX() > this.getWidth() - scaleDiv2) x = this.getWidth() - scaleDiv2; if (e.getY() < scaleDiv2) y = scaleDiv2; else if (e.getY() > this.getHeight() - scaleDiv2) y = this.getHeight() - scaleDiv2; // Distance xDist = x - tempCps.getPosition().getX(); yDist = y - tempCps.getPosition().getY(); tempCps.setPosition(x, y); // Drag Position // ToolTipText Position and name toolTip = true; toolTipText = tempCps.getName() + ", " + tempCps.getId(); toolTipPos.setX(tempCps.getPosition().getX() - scaleDiv2); toolTipPos.setY(tempCps.getPosition().getY() + scaleDiv2); // All Selected Objects for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) { if (cps != tempCps) { x = (int) (cps.getPosition().getX() + xDist); y = (int) (cps.getPosition().getY() + yDist); // Make sure its in bounds if (x <= scaleDiv2) x = scaleDiv2; else if (x > this.getWidth() - scaleDiv2) x = this.getWidth() - scaleDiv2; if (y <= scaleDiv2) y = scaleDiv2; else if (y > this.getHeight() - scaleDiv2) y = this.getHeight() - scaleDiv2; cps.setPosition(x, y); } } /** * check if something might be replaced */ if (GuiSettings.getSelectedObjects().size() == 1) checkForReplacement(groupNode.getObjectsInThisLayer(), tempCps, x, y); repaint(); } catch (Exception eex) { } } // Mark Objects if (doMark) { tempSelected.clear(); for (AbstractCanvasObject cps : groupNode.getObjectsInThisLayer().toList()) { int x1 = sx, x2 = x, y1 = sy, y2 = y; if (sx >= x) { x1 = x; x2 = sx; } if (sy >= y) { y1 = y; y2 = sy; } if (x1 <= cps.getPosition().getX() + GuiSettings.getPictureScaleDiv2() && y1 <= cps.getPosition().getY() + GuiSettings.getPictureScaleDiv2() && x2 >= cps.getPosition().getX() && y2 >= cps.getPosition().getY()) { tempSelected.add(cps); } } } repaint(); } } @Override public void mouseMoved(MouseEvent e) { if (!disabled) { x = e.getX(); y = e.getY(); // Everything for the tooltip :) boolean on = false; for (AbstractCanvasObject cps : groupNode.getObjectsInThisLayer().toList()) { cx = cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2(); cy = cps.getPosition().getY() - GuiSettings.getPictureScaleDiv2(); if (x - GuiSettings.getPictureScale() <= cx && y - GuiSettings.getPictureScale() <= cy && x >= cx && y >= cy) { on = true; toolTipPos.setX(cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2()); toolTipPos.setY(cps.getPosition().getY() + GuiSettings.getPictureScaleDiv2()); toolTipText = cps.getName() + ", " + cps.getId(); } } if (on || (!on && toolTip)) repaint(); toolTip = on; } } /** * Draws or Deletes an Edge. */ void drawDeleteEdge() { if (getMousePosition() != null) { boolean node = true; boolean newEdge = true; boolean onEdge = true; boolean deleteNode = false; Edge e = null; for (AbstractCanvasObject cps : groupNode.getObjectsInThisLayer().toList()) { cx = cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2(); cy = cps.getPosition().getY() - GuiSettings.getPictureScaleDiv2(); if (x - GuiSettings.getPictureScale() <= cx && y - GuiSettings.getPictureScale() <= cy && x >= cx && y >= cy && cps != tempCps) { node = false; onEdge = false; if (!newEdge) { control.removeEdgesOnCanvas(e); // Node ohne Edge? if (e.getA().getClass() == Node.class) { tempCps = e.getA(); deleteNode = true; } if (e.getB().getClass() == Node.class) { deleteNode = true; } } else { if (!(cps instanceof GroupNode || tempCps instanceof GroupNode)) { e = new Edge(cps, tempCps, GuiSettings.maxCapacityForNewCreatedEdges); control.addEdgeOnCanvas(e); } else if (cps instanceof GroupNode groupnode && !(tempCps instanceof GroupNode)) { GroupNode thisUpperNode = groupnode; Object[] possibilities = thisUpperNode.getObjectsInThisLayer().map(aCps -> new ACpsHandle(aCps)) .filter(aCpsHandle -> !(aCpsHandle.object instanceof GroupNode)).toArray(); if (possibilities.length != 0) { ACpsHandle selected = (ACpsHandle) JOptionPane.showInputDialog(this, "Select a inside Object:", "Connection To?", JOptionPane.OK_OPTION, new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)), possibilities, ""); if (selected != null) { e = new Edge(selected.object, tempCps, GuiSettings.maxCapacityForNewCreatedEdges); control.addEdgeOnCanvas(e); } } else { Node n = new Node("Node"); n.setPosition(x, y); control.addObjectInGroupNode(n, thisUpperNode); e = new Edge(n, tempCps, GuiSettings.maxCapacityForNewCreatedEdges); control.addEdgeOnCanvas(e); } } } } } // Edge auf eine Edge gezogen? if (onEdge && !checkForReplacement(x, y)) { Edge p = mousePositionOnEdge(x, y); if (p != null) { Edge e1; Edge e2; node = false; Node n = new Node("Node"); n.setPosition(x, y); control.addObjectCanvas(n); AbstractCanvasObject r, k; r = p.getA(); k = p.getB(); e = new Edge(n, tempCps, GuiSettings.maxCapacityForNewCreatedEdges); e1 = new Edge(n, r, GuiSettings.maxCapacityForNewCreatedEdges); e2 = new Edge(n, k, GuiSettings.maxCapacityForNewCreatedEdges); control.removeEdgesOnCanvas(p); control.addEdgeOnCanvas(e); control.addEdgeOnCanvas(e1); control.addEdgeOnCanvas(e2); } } else { mayBeReplaced = null; } // ins leere Gedragged if (node && !checkForReplacement(x, y)) { Node n = new Node("Node"); n.setPosition(x, y); control.addObjectCanvas(n); e = new Edge(n, tempCps, GuiSettings.maxCapacityForNewCreatedEdges); control.addEdgeOnCanvas(e); } else { mayBeReplaced = null; } // Wenn ein Node ohne Connections da ist if (deleteNode) { control.delCanvasObject(tempCps, true); tempCps = null; } } } /** * Checks if the mouse is on an Edge. * * @param x Position of the Mouse * @param y Position of the Mouse * @return CpsEdge the Mouse is on, null if the mouse is not on an Edge */ protected Edge mousePositionOnEdge(int x, int y) { x += GuiSettings.getPictureScaleDiv2(); y += GuiSettings.getPictureScaleDiv2(); for (Edge p : model.getEdgesOnCanvas()) { Line2D l = new Line2D.Float(p.getA().getPosition().getX(), p.getA().getPosition().getY(), p.getB().getPosition().getX(), p.getB().getPosition().getY()); int[] positions = determineMousePositionOnEdge(p); int lx = positions[0]; int ly = positions[1]; int hx = positions[2]; int hy = positions[3]; // distance from a point to a line and between both Objects if (l.ptLineDistSq(x - GuiSettings.getPictureScaleDiv2(), y - GuiSettings.getPictureScaleDiv2()) < 20 && x > lx && x < hx && y > ly && y < hy) { return p; } } return null; } /** * set toolTip * * @param bool */ public void setToolTip(boolean bool) { this.toolTip = bool; } /** * Set the Mouse * * @param x * @param y */ public void setXY(int x, int y) { this.x = x; this.y = y; } @Override public boolean checkForReplacement(int x, int y) { return checkForReplacement(model.getCanvas().getObjectsInThisLayer(), null, x, y); } @Override public void tryToAlignObjects() { /** * Align all Objects */ model.getCanvas().getAllObjectsRecursive().forEach(cps -> { align(cps, 3 * GuiSettings.getPictureScaleDiv2()); }); /** * AutoSave new Positons */ control.tryAutoSave(); } @Override public void closeUpperNodeTab(int upperNodeId) { JTabbedPane tabbedPaneInner = (JTabbedPane) getParent().getParent().getParent().getParent(); for (int i = 1; i < tabbedPaneInner.getTabCount(); i++) { if (((Canvas) ((JScrollPane) tabbedPaneInner.getComponentAt(i)).getViewport().getComponent(0)) .getGroupNode().getId() == upperNodeId) { tabbedPaneInner.remove(i); break; } } } public GroupNode getGroupNode() { return this.groupNode; } public void setGroupNode(GroupNode groupNode) { this.groupNode = groupNode; } }