|
@@ -1,23 +1,21 @@
|
|
package holeg.ui.view.canvas;
|
|
package holeg.ui.view.canvas;
|
|
|
|
|
|
-import java.awt.Color;
|
|
|
|
-import java.awt.Font;
|
|
|
|
-import java.awt.Graphics;
|
|
|
|
-import java.util.logging.Logger;
|
|
|
|
-
|
|
|
|
-import javax.swing.JPanel;
|
|
|
|
-
|
|
|
|
|
|
+import holeg.model.AbstractCanvasObject;
|
|
import holeg.model.GroupNode;
|
|
import holeg.model.GroupNode;
|
|
-import holeg.model.HolonObject;
|
|
|
|
-import holeg.preferences.ColorPreference;
|
|
|
|
import holeg.ui.controller.Control;
|
|
import holeg.ui.controller.Control;
|
|
import holeg.ui.model.GuiSettings;
|
|
import holeg.ui.model.GuiSettings;
|
|
-import holeg.utility.image.Import;
|
|
|
|
|
|
+import holeg.utility.math.vector.Geometry;
|
|
import holeg.utility.math.vector.Vec2i;
|
|
import holeg.utility.math.vector.Vec2i;
|
|
|
|
|
|
-import java.awt.Graphics2D;
|
|
|
|
-import java.awt.Image;
|
|
|
|
-import java.awt.RenderingHints;
|
|
|
|
|
|
+import javax.swing.*;
|
|
|
|
+import java.awt.*;
|
|
|
|
+import java.awt.event.MouseEvent;
|
|
|
|
+import java.awt.event.MouseListener;
|
|
|
|
+import java.awt.event.MouseMotionListener;
|
|
|
|
+import java.util.HashSet;
|
|
|
|
+import java.util.Optional;
|
|
|
|
+import java.util.Set;
|
|
|
|
+import java.util.logging.Logger;
|
|
|
|
|
|
/**
|
|
/**
|
|
* This Class is the Canvas. All Objects will be visualized here
|
|
* This Class is the Canvas. All Objects will be visualized here
|
|
@@ -25,333 +23,198 @@ import java.awt.RenderingHints;
|
|
* @author Gruppe14
|
|
* @author Gruppe14
|
|
*/
|
|
*/
|
|
public class Canvas extends JPanel {
|
|
public class Canvas extends JPanel {
|
|
- private static final Logger log = Logger.getLogger(Canvas.class.getName());
|
|
|
|
- private boolean enabled = false;
|
|
|
|
-
|
|
|
|
- private GroupNode groupNode;
|
|
|
|
- private Control control;
|
|
|
|
- private static Color[] colors = { ColorPreference.HolonObject.Producer, ColorPreference.HolonObject.NotSupplied,
|
|
|
|
- ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.Supplied,
|
|
|
|
- ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.NoEnergy };
|
|
|
|
-
|
|
|
|
- public Canvas(Control control, GroupNode groupNode) {
|
|
|
|
- this.control = control;
|
|
|
|
- this.groupNode = groupNode;
|
|
|
|
- control.OnGuiSetEnabled.addListener(this::setCanvasEnabled);
|
|
|
|
- // TODO(Tom2022-01-14): remove listener when not needed anymore
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void setCanvasEnabled(boolean state) {
|
|
|
|
- enabled = state;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-// 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);
|
|
|
|
-//
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void paintComponent(Graphics g) {
|
|
|
|
- super.paintComponent(g);
|
|
|
|
- Graphics2D g2d = initGraphics2D(g);
|
|
|
|
- log.info("Draw");
|
|
|
|
-
|
|
|
|
- groupNode.getHolonObjects().forEach(hO -> {
|
|
|
|
- drawHolonObject(g2d, hO);
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
-//
|
|
|
|
-// Optional<VisualRepresentationalState> 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
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void drawHolonObject(Graphics2D g, HolonObject hO) {
|
|
|
|
- Vec2i pos = hO.getPosition();
|
|
|
|
-// Color statecolor = ColorPreference.HolonObject.getStateColor(hO.getState());
|
|
|
|
-// g.setColor(statecolor);
|
|
|
|
- g.setColor(Color.cyan);
|
|
|
|
- g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
|
|
|
|
- GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
|
|
|
|
- drawCanvasObject(g, hO.getImage(), pos);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void drawCanvasObject(Graphics2D g, String imageName, Vec2i pos) {
|
|
|
|
- int pictureScale = GuiSettings.getPictureScale();
|
|
|
|
- int pictureScaleDiv2 = GuiSettings.getPictureScaleDiv2();
|
|
|
|
- Image image = Import.loadImage(imageName, pictureScale, pictureScale);
|
|
|
|
- g.drawImage(image, pos.getX() - pictureScaleDiv2, pos.getY() - pictureScaleDiv2, pictureScale, pictureScale,
|
|
|
|
- null);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static final RenderingHints RenderingHint = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
|
|
|
|
- RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
- private static final Font CanvasFont = new Font("TimesNewRoman", Font.PLAIN,
|
|
|
|
- Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10));
|
|
|
|
-
|
|
|
|
- private static Graphics2D initGraphics2D(Graphics g) {
|
|
|
|
- Graphics2D g2d = (Graphics2D) g;
|
|
|
|
- g2d.setRenderingHints(RenderingHint);
|
|
|
|
- g2d.setFont(CanvasFont);
|
|
|
|
- return g2d;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public GroupNode getGroupNode() {
|
|
|
|
- return this.groupNode;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void setGroupNode(GroupNode groupNode) {
|
|
|
|
- this.groupNode = groupNode;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void checkForReplacement(int x, int y) {
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
|
|
+ private static final Logger log = Logger.getLogger(Canvas.class.getName());
|
|
|
|
+ private final GroupNode groupNode;
|
|
|
|
+ private final Control control;
|
|
|
|
+ private final CanvasMouseListener listener = new CanvasMouseListener();
|
|
|
|
+ private boolean enabled = true;
|
|
|
|
+
|
|
|
|
+ public Canvas(Control control, GroupNode groupNode) {
|
|
|
|
+ this.control = control;
|
|
|
|
+ this.groupNode = groupNode;
|
|
|
|
+ control.OnGuiSetEnabled.addListener(this::setCanvasEnabled);
|
|
|
|
+ control.OnSelectionChanged.addListener(this::repaint);
|
|
|
|
+ // TODO(Tom2022-01-14): remove listener when not needed anymore
|
|
|
|
+ this.addMouseListener(listener);
|
|
|
|
+ this.addMouseMotionListener(listener);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static Rectangle getBoundsOfObject(AbstractCanvasObject obj) {
|
|
|
|
+ int pictureScale = GuiSettings.getPictureScale();
|
|
|
|
+ int pictureScaleDiv2 = GuiSettings.getPictureScaleDiv2();
|
|
|
|
+ Vec2i pos = obj.getPosition();
|
|
|
|
+ return new Rectangle(pos.getX() - pictureScaleDiv2, pos.getY() - pictureScaleDiv2, pictureScale, pictureScale);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void setCanvasEnabled(boolean state) {
|
|
|
|
+ enabled = state;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public GroupNode getGroupNode() {
|
|
|
|
+ return this.groupNode;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void paintComponent(java.awt.Graphics g) {
|
|
|
|
+ super.paintComponent(g);
|
|
|
|
+ Graphics2D g2d = Rendering.initGraphics2D(g);
|
|
|
|
+ Rendering.drawSelection(g2d);
|
|
|
|
+ log.info("Draw");
|
|
|
|
+ groupNode.getHolonObjects().forEach(hO -> Rendering.drawHolonObject(g2d, hO));
|
|
|
|
+ groupNode.getSwitches().forEach(hS -> Rendering.drawSwitchObject(g2d, hS));
|
|
|
|
+ groupNode.getGroupNodes().forEach(groupNode -> Rendering.drawGroupNode(g2d, groupNode));
|
|
|
|
+ groupNode.getNodes().forEach(node -> Rendering.drawNode(g2d, node));
|
|
|
|
+ control.getModel().getEdgesOnCanvas().forEach(edge -> {
|
|
|
|
+ boolean edgeAinside = edge.getA().getGroupNode().get() == groupNode;
|
|
|
|
+ boolean edgeBinside = edge.getB().getGroupNode().get() == groupNode;
|
|
|
|
+ //both
|
|
|
|
+ if (edgeAinside && edgeBinside) {
|
|
|
|
+ Rendering.drawEdge(g2d, edge);
|
|
|
|
+ }
|
|
|
|
+ //TODO(Tom2022-01-16): oneside
|
|
|
|
+ //none
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (listener.boxSelection) {
|
|
|
|
+ Rendering.drawSelectionBox(g2d, listener.getRectangleOfSelectionBox());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Optional<AbstractCanvasObject> getObjectAtPosition(Vec2i pos) {
|
|
|
|
+ return groupNode.getObjectsInThisLayer().filter(obj ->
|
|
|
|
+ getBoundsOfObject(obj).contains(pos.getX(), pos.getY())
|
|
|
|
+ ).findAny();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //TODO(Tom2022-01-17): checkForReplacement replace with getObjectAtPosition
|
|
|
|
+ public Optional<AbstractCanvasObject> checkForReplacement(int x, int y) {
|
|
|
|
+ return Optional.empty();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Microsoft Windows10 selection & dragging behavior
|
|
|
|
+ */
|
|
|
|
+ private class CanvasMouseListener implements MouseListener, MouseMotionListener {
|
|
|
|
+ private Vec2i lastPosition = new Vec2i();
|
|
|
|
+ private Vec2i pressedPosition = new Vec2i();
|
|
|
|
+ private boolean dragDetected = false;
|
|
|
|
+ private boolean ctrlAdded = false;
|
|
|
|
+ private boolean boxSelection = false;
|
|
|
|
+ private Set<AbstractCanvasObject> selectionBeforeBoxSelection = new HashSet<>();
|
|
|
|
+
|
|
|
|
+ private static boolean LeftMouseButtonIsDown(MouseEvent e) {
|
|
|
|
+ int onMask = MouseEvent.BUTTON1_DOWN_MASK;
|
|
|
|
+ return (e.getModifiersEx() & onMask) == onMask;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mousePressed(MouseEvent e) {
|
|
|
|
+ if (!enabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ log.info("Pressed");
|
|
|
|
+ Vec2i pos = new Vec2i(e.getPoint());
|
|
|
|
+ if (e.isControlDown()) {
|
|
|
|
+ getObjectAtPosition(pos).ifPresentOrElse(obj -> {
|
|
|
|
+ if (!GuiSettings.getSelectedObjects().contains(obj)) {
|
|
|
|
+ control.addSelectedObject(obj);
|
|
|
|
+ ctrlAdded = true;
|
|
|
|
+ }
|
|
|
|
+ }, this::initBoxSelection);
|
|
|
|
+ } else {
|
|
|
|
+ getObjectAtPosition(pos).ifPresentOrElse(obj -> {
|
|
|
|
+ if (!GuiSettings.getSelectedObjects().contains(obj)) {
|
|
|
|
+ GuiSettings.getSelectedObjects().clear();
|
|
|
|
+ control.addSelectedObject(obj);
|
|
|
|
+ }
|
|
|
|
+ }, () -> {
|
|
|
|
+ control.clearSelection();
|
|
|
|
+ initBoxSelection();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lastPosition = pressedPosition = pos;
|
|
|
|
+ dragDetected = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void initBoxSelection() {
|
|
|
|
+ boxSelection = true;
|
|
|
|
+ selectionBeforeBoxSelection = Set.copyOf(GuiSettings.getSelectedObjects());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mouseReleased(MouseEvent e) {
|
|
|
|
+ log.info("Released");
|
|
|
|
+ if (enabled && !dragDetected) {
|
|
|
|
+ if (e.isControlDown()) {
|
|
|
|
+ getObjectAtPosition(lastPosition).ifPresent(obj -> {
|
|
|
|
+ if (!ctrlAdded && GuiSettings.getSelectedObjects().contains(obj)) {
|
|
|
|
+ control.removeObjectFromSelection(obj);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ } else if (!GuiSettings.getSelectedObjects().isEmpty()) {
|
|
|
|
+ getObjectAtPosition(lastPosition).ifPresent(obj -> {
|
|
|
|
+ GuiSettings.getSelectedObjects().clear();
|
|
|
|
+ control.addSelectedObject(obj);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ctrlAdded = false;
|
|
|
|
+ boxSelection = false;
|
|
|
|
+ repaint();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mouseDragged(MouseEvent e) {
|
|
|
|
+ if (!enabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ log.info("Dragged");
|
|
|
|
+ Vec2i actualPos = new Vec2i(e.getPoint());
|
|
|
|
+ dragDetected = dragDetected || (pressedPosition.getSquaredDistance(actualPos) > GuiSettings.dragThresholdDistance);
|
|
|
|
+ if (dragDetected) {
|
|
|
|
+ repaint();
|
|
|
|
+ }
|
|
|
|
+ if (boxSelection) {
|
|
|
|
+ log.info("BoxSelection");
|
|
|
|
+ Rectangle selectionBox = getRectangleOfSelectionBox();
|
|
|
|
+ groupNode.getObjectsInThisLayer().forEach(obj -> {
|
|
|
|
+ Rectangle bounds = getBoundsOfObject(obj);
|
|
|
|
+ if (selectionBox.intersects(bounds) ^ selectionBeforeBoxSelection.contains(obj)) {
|
|
|
|
+ control.addSelectedObject(obj);
|
|
|
|
+ } else {
|
|
|
|
+ control.removeObjectFromSelection(obj);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ } else if (LeftMouseButtonIsDown(e)) {
|
|
|
|
+ Vec2i delta = actualPos.subtract(lastPosition);
|
|
|
|
+ GuiSettings.getSelectedObjects().forEach(obj -> obj.getPosition().addAssign(delta));
|
|
|
|
+ }
|
|
|
|
+ lastPosition = actualPos;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Rectangle getRectangleOfSelectionBox() {
|
|
|
|
+ return Geometry.createRectangleFromCorners(lastPosition, pressedPosition);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mouseClicked(MouseEvent e) {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mouseEntered(MouseEvent e) {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mouseExited(MouseEvent e) {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void mouseMoved(MouseEvent e) {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|