Canvas.java 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. package holeg.ui.view.canvas;
  2. import java.awt.BasicStroke;
  3. import java.awt.Color;
  4. import java.awt.Font;
  5. import java.awt.Graphics;
  6. import java.awt.Graphics2D;
  7. import java.awt.RenderingHints;
  8. import java.awt.datatransfer.UnsupportedFlavorException;
  9. import java.awt.event.MouseEvent;
  10. import java.awt.event.MouseListener;
  11. import java.awt.event.MouseMotionListener;
  12. import java.awt.geom.Line2D;
  13. import java.awt.image.BufferedImage;
  14. import java.io.IOException;
  15. import java.util.ArrayList;
  16. import java.util.Optional;
  17. import javax.swing.ImageIcon;
  18. import javax.swing.JFrame;
  19. import javax.swing.JLabel;
  20. import javax.swing.JOptionPane;
  21. import javax.swing.JScrollPane;
  22. import javax.swing.JTabbedPane;
  23. import javax.swing.SwingUtilities;
  24. import com.google.gson.JsonParseException;
  25. import holeg.model.AbstractCanvasObject;
  26. import holeg.model.Edge;
  27. import holeg.model.GroupNode;
  28. import holeg.model.HolonObject;
  29. import holeg.model.HolonSwitch;
  30. import holeg.model.Node;
  31. import holeg.preferences.ColorPreference;
  32. import holeg.ui.controller.Control;
  33. import holeg.ui.model.Consumer;
  34. import holeg.ui.model.DecoratedGroupNode;
  35. import holeg.ui.model.DecoratedHolonObject;
  36. import holeg.ui.model.DecoratedHolonObject.HolonObjectState;
  37. import holeg.ui.model.DecoratedSwitch;
  38. import holeg.ui.model.DecoratedSwitch.SwitchState;
  39. import holeg.ui.model.ExitCable;
  40. import holeg.ui.model.GuiSettings;
  41. import holeg.ui.model.Model;
  42. import holeg.ui.model.Passiv;
  43. import holeg.ui.model.Supplier;
  44. import holeg.ui.model.VisualRepresentationalState;
  45. import holeg.ui.view.inspector.UnitGraph;
  46. import holeg.utility.ImageImport;
  47. import holeg.utility.Vector2Int;
  48. /**
  49. * This Class is the Canvas. All Objects will be visualized here
  50. *
  51. * @author Gruppe14
  52. */
  53. public class Canvas extends AbstractCanvas implements MouseListener, MouseMotionListener {
  54. private static final long serialVersionUID = 1L;
  55. public boolean disabled = false;
  56. GroupNode groupNode = null;
  57. private static Color[] colors = { ColorPreference.HolonObject.Producer, ColorPreference.HolonObject.NotSupplied,
  58. ColorPreference.HolonObject.PartiallySupplied, ColorPreference.HolonObject.Supplied,
  59. ColorPreference.HolonObject.OverSupplied, ColorPreference.HolonObject.NoEnergy };
  60. /**
  61. * Constructor.
  62. *
  63. * @param mod the Model
  64. * @param control the Controller
  65. * @param unitGraph
  66. */
  67. public Canvas(Model mod, Control control, UnitGraph unitGraph) {
  68. toolTip = false;
  69. this.control = control;
  70. this.model = mod;
  71. scalediv20 = GuiSettings.getPictureScale() / 20;
  72. showConnectionInformation = true;
  73. popmenu.add(itemCut);
  74. popmenu.add(itemCopy);
  75. popmenu.add(itemPaste);
  76. popmenu.add(itemDelete);
  77. popmenu.add(itemAlign);
  78. popmenu.addSeparator();
  79. popmenu.add(itemGroup);
  80. popmenu.add(itemUngroup);
  81. popmenu.add(itemCreateTemplate);
  82. itemDelete.setEnabled(false);
  83. itemCut.setEnabled(false);
  84. itemCopy.setEnabled(false);
  85. itemPaste.setEnabled(true);
  86. itemAlign.setEnabled(false);
  87. itemGroup.setEnabled(false);
  88. itemUngroup.setEnabled(false);
  89. itemCut.setText("Cut");
  90. itemGroup.addActionListener(actionEvent -> {
  91. // calculate uppernode pos (taken from the controller)
  92. unPos = new Vector2Int(0, 0);
  93. animCps = new ArrayList<>();
  94. for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) {
  95. animCps.add(cps); // add to animation Cps ArrayList
  96. unPos = unPos.add(cps.getPosition());
  97. }
  98. unPos = unPos.divide(animCps.size());
  99. // save old Position
  100. savePos = new ArrayList<>();
  101. for (int i = 0; i < animCps.size(); i++) {
  102. savePos.add(new Vector2Int(animCps.get(i).getPosition()));
  103. }
  104. animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
  105. if (animDuration - animDelay > 0 && animCps.size() > 1) {
  106. for (AbstractCanvasObject animCpObject : animCps) {
  107. Vector2Int pos = animCpObject.getPosition();
  108. Vector2Int difference = pos.subtract(unPos);
  109. Vector2Int result = pos.subtract(difference.divide(animSteps));
  110. pos.set(result);
  111. }
  112. repaint();
  113. animDuration -= animDelay;
  114. animSteps--;
  115. } else {
  116. animDuration = ANIMTIME;
  117. animSteps = animDuration / animDelay;
  118. animT.stop();
  119. for (int i = 0; i < animCps.size(); i++) {
  120. animCps.get(i).getPosition().set(savePos.get(i));
  121. }
  122. control.addUpperNode("GroupNode", groupNode, animCps);
  123. control.calculateStateAndVisualForCurrentTimeStep();
  124. control.clearSelection();
  125. repaint();
  126. }
  127. });
  128. animT.start();
  129. });
  130. itemUngroup.addActionListener(actionEvent -> {
  131. // save old Position
  132. int upperNodeId = tempCps.getId();
  133. closeUpperNodeTab(upperNodeId);
  134. savePos = new ArrayList<>();
  135. animCps = ((GroupNode) tempCps).getAllObjectsRecursive().toList();
  136. control.ungroupGroupNode((GroupNode) tempCps, groupNode);
  137. for (int i = 0; i < animCps.size(); i++) {
  138. savePos.add(new Vector2Int(animCps.get(i).getPosition()));
  139. }
  140. for (AbstractCanvasObject cps : animCps) {
  141. int x = tempCps.getPosition().getX();
  142. int y = tempCps.getPosition().getY();
  143. cps.setPosition(new Vector2Int(x, y));
  144. }
  145. animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
  146. control.clearSelection();
  147. if (animDuration - animDelay >= 0) {
  148. for (int i = 0; i < animCps.size(); i++) {
  149. Vector2Int pos = animCps.get(i).getPosition();
  150. Vector2Int difference = pos.subtract(savePos.get(i));
  151. Vector2Int result = pos.subtract(difference.divide(animSteps));
  152. pos.set(result);
  153. }
  154. repaint();
  155. animDuration -= animDelay;
  156. animSteps--;
  157. } else {
  158. animDuration = ANIMTIME;
  159. animSteps = animDuration / animDelay;
  160. animT.stop();
  161. for (int i = 0; i < animCps.size(); i++) {
  162. animCps.get(i).getPosition().set(savePos.get(i));
  163. }
  164. control.calculateStateAndVisualForCurrentTimeStep();
  165. repaint();
  166. }
  167. });
  168. animT.start();
  169. });
  170. // adds the selected object(s) to the statistic panel
  171. itemDelete.addActionListener(actionEvent -> {
  172. // Remove the selected Object objects
  173. // Edge Deleting
  174. if (tempCps == null && edgeHighlight != null) {
  175. control.removeEdgesOnCanvas(edgeHighlight);
  176. // Look for a CPSNode with no Connections and delete them
  177. if (edgeHighlight.getA() instanceof Node) {
  178. control.delCanvasObject(edgeHighlight.getA(), false);
  179. }
  180. if (edgeHighlight.getB() instanceof Node) { // Look on the other end of the cable
  181. control.delCanvasObject(edgeHighlight.getB(), false);
  182. }
  183. edgeHighlight = null;
  184. }
  185. for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) {
  186. control.delCanvasObject(cps, false);
  187. toolTip = false;
  188. }
  189. control.tryAutoSave();
  190. control.clearSelection();
  191. tempCps = null;
  192. repaint();
  193. });
  194. itemCut.addActionListener(actionEvent -> {
  195. control.cut(null);
  196. itemPaste.setEnabled(true);
  197. repaint();
  198. });
  199. itemCopy.addActionListener(actionEvent -> {
  200. if (tempCps instanceof GroupNode)
  201. control.getObjectsInDepth();
  202. control.copy(null);
  203. itemPaste.setEnabled(true);
  204. repaint();
  205. });
  206. itemAlign.addActionListener(actionEvent -> {
  207. for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects())
  208. align(cps, GuiSettings.getPictureScaleDiv2());
  209. repaint();
  210. });
  211. itemPaste.addActionListener(actionEvent -> {
  212. try {
  213. control.paste(null, mousePosition);
  214. } catch (JsonParseException | UnsupportedFlavorException | IOException e1) {
  215. JLabel message = new JLabel("The Clipboard information cannot be pastet into Application.");
  216. JOptionPane.showMessageDialog(null, message, "", JOptionPane.ERROR_MESSAGE);
  217. }
  218. repaint();
  219. });
  220. /*
  221. * create Template
  222. */
  223. itemCreateTemplate.addActionListener(actionEvent -> {
  224. control.createTemplate((HolonObject) tempCps, (JFrame) SwingUtilities.getRoot(this));
  225. });
  226. this.addMouseListener(this);
  227. this.addMouseMotionListener(this);
  228. }
  229. /**
  230. * Paints all Components on the Canvas.
  231. *
  232. * @param g Graphics
  233. */
  234. protected void paintCanvasObject(Graphics2D g, DecoratedHolonObject decoratedHolonObject) {
  235. Vector2Int pos = decoratedHolonObject.getModel().getPosition();
  236. Color statecolor = ColorPreference.HolonObject.getStateColor(decoratedHolonObject.getState());
  237. g.setColor(statecolor);
  238. g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
  239. GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
  240. drawCanvasObject(g, decoratedHolonObject.getModel().getImage(), pos);
  241. }
  242. protected void drawCanvasObjectString(Graphics2D g, Vector2Int posOfCanvasObject, float energy) {
  243. g.setColor(Color.BLACK);
  244. g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (GuiSettings.getPictureScale() / 4f)));
  245. g.drawString((energy > 0) ? "+" + Float.toString(energy) : Float.toString(energy),
  246. posOfCanvasObject.getX() - GuiSettings.getPictureScaleDiv2(),
  247. posOfCanvasObject.getY() - GuiSettings.getPictureScaleDiv2() - 1);
  248. }
  249. protected void paintConsumer(Graphics2D g, Consumer con) {
  250. paintCanvasObject(g, con);
  251. drawCanvasObjectString(g, con.getModel().getPosition(), -con.getEnergyNeededFromNetwork());
  252. if (GuiSettings.showSupplyBars) {
  253. paintSupplyBar(g, con.getSupplyBarPercentage(), ColorPreference.HolonObject.getStateColor(con.getState()),
  254. con.getModel().getPosition());
  255. }
  256. }
  257. protected void paintSupplier(Graphics2D g, Supplier sup) {
  258. paintCanvasObject(g, sup);
  259. drawCanvasObjectString(g, sup.getModel().getPosition(), sup.getEnergyToSupplyNetwork());
  260. }
  261. protected void drawCanvasObject(Graphics2D g, String Image, Vector2Int pos) {
  262. g.drawImage(ImageImport.loadImage(Image, GuiSettings.getPictureScale(), GuiSettings.getPictureScale()),
  263. pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScale(),
  264. GuiSettings.getPictureScale(), null);
  265. }
  266. protected void paintCable(Graphics2D g, Edge cable, boolean isSelected) {
  267. Vector2Int start = cable.getA().getPosition();
  268. Vector2Int end = cable.getB().getPosition();
  269. float currentEnergy = cable.getActualFlow();
  270. float capacity = cable.maxCapacity;
  271. boolean unlimited = cable.isUnlimitedCapacity();
  272. switch (cable.getState()) {
  273. case Burned:
  274. g.setColor(ColorPreference.Edge.Burned);
  275. g.setStroke(new BasicStroke(2));
  276. break;
  277. case Working:
  278. g.setColor(ColorPreference.Edge.Working);
  279. g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
  280. break;
  281. }
  282. if (isSelected) {
  283. g.setColor(Color.lightGray);
  284. }
  285. g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
  286. if (showConnectionInformation) {
  287. Vector2Int middle = new Vector2Int((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
  288. g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
  289. g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
  290. }
  291. }
  292. protected void paintSwitch(Graphics2D g, DecoratedSwitch dSwitch) {
  293. drawCanvasObject(g, dSwitch.getState() == SwitchState.Open ? HolonSwitch.getSwitchOpenImage()
  294. : HolonSwitch.getSwitchClosedImage(), dSwitch.getModel().getPosition());
  295. }
  296. protected void paintExitCable(Graphics2D g, ExitCable eCable) {
  297. Vector2Int start = eCable.getStart().getPosition();
  298. Vector2Int end = eCable.getFinish().getPosition();
  299. float currentEnergy;
  300. float capacity = eCable.getEdge().maxCapacity;
  301. boolean unlimited = eCable.getEdge().isUnlimitedCapacity();
  302. if(eCable.getEdge().getState() == null) {
  303. System.err.print(eCable.getEdge());
  304. }
  305. switch (eCable.getEdge().getState()) {
  306. case Burned:
  307. currentEnergy = 0.0f;
  308. g.setColor(Color.RED);
  309. g.setStroke(new BasicStroke(2));
  310. break;
  311. case Working:
  312. default:
  313. currentEnergy = eCable.getEdge().getActualFlow();
  314. g.setColor(new Color(13, 175, 28));
  315. g.setStroke(new BasicStroke(unlimited ? 2f : (currentEnergy / capacity * 2f) + 1));
  316. break;
  317. }
  318. g.drawLine(start.getX(), start.getY(), end.getX(), end.getY());
  319. Vector2Int middle = new Vector2Int((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
  320. g.setFont(new Font("TimesRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
  321. g.drawString(currentEnergy + "/" + (unlimited ? "\u221E" : capacity), middle.getX(), middle.getY());
  322. }
  323. protected void paintGroupNode(Graphics2D g, DecoratedGroupNode dGroupNode) {
  324. Vector2Int pos = dGroupNode.getModel().getPosition();
  325. g.setColor(Color.lightGray);
  326. g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() - GuiSettings.getPictureScaleDiv2(),
  327. GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
  328. drawCanvasObject(g, "/Images/upper_node.png", pos);
  329. paintGroupNodeBar(g, dGroupNode, pos);
  330. }
  331. private void paintGroupNodeBar(Graphics2D g, DecoratedGroupNode dGroupNode, Vector2Int pos) {
  332. // +1, -2, -1 little Adjustment for pixel perfect alignment
  333. int barWidth = (int) (GuiSettings.getPictureScale());
  334. int barHeight = (int) (GuiSettings.getPictureScale() / 5);
  335. g.setColor(Color.WHITE);
  336. g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth,
  337. barHeight);
  338. float[] percentages = getGroupNodeBarPercentages(dGroupNode);
  339. for (int i = 5; i >= 0; i--) {
  340. g.setColor(colors[i]);
  341. g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1,
  342. (int) (barWidth * percentages[i] - 1), barHeight);
  343. }
  344. // g.setColor(color);
  345. // g.fillRect(pos.getX() - GuiSettings.GetPictureScaleDiv2(), pos.getY() + GuiSettings.GetPictureScaleDiv2() - 1, (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
  346. g.setColor(Color.BLACK);
  347. g.setStroke(new BasicStroke(1));
  348. g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1,
  349. barHeight);
  350. }
  351. /**
  352. * HardCoded Stuff dont try at Home ;)
  353. *
  354. * @param dGroupNode
  355. * @return
  356. */
  357. public float[] getGroupNodeBarPercentages(DecoratedGroupNode dGroupNode) {
  358. int[] amountOfObjects = new int[6];
  359. amountOfObjects[0] = dGroupNode.getAmountOfSupplier();
  360. amountOfObjects[1] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED);
  361. amountOfObjects[2] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED);
  362. amountOfObjects[3] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED);
  363. amountOfObjects[4] = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED);
  364. amountOfObjects[5] = dGroupNode.getAmountOfPassiv();
  365. int countHolonObjects = amountOfObjects[0] + amountOfObjects[1] + amountOfObjects[2] + amountOfObjects[3]
  366. + amountOfObjects[4] + amountOfObjects[5];
  367. float[] percentages = new float[6];
  368. int count = 0;
  369. for (int i = 0; i < 6; i++) {
  370. count += amountOfObjects[i];
  371. percentages[i] = (float) count / (float) countHolonObjects;
  372. }
  373. return percentages;
  374. }
  375. private void paintSupplyBar(Graphics2D g, float percentage, Color color, Vector2Int pos) {
  376. // +1, -2, -1 little Adjustment for pixel perfect alignment
  377. int barWidth = (int) (GuiSettings.getPictureScale());
  378. int barHeight = (int) (GuiSettings.getPictureScale() / 5);
  379. g.setColor(Color.WHITE);
  380. g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, (int) barWidth,
  381. barHeight);
  382. g.setColor(color);
  383. g.fillRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1,
  384. (int) (barWidth * (percentage < 1 ? percentage : 1.0f) - 1), barHeight);
  385. g.setColor(Color.BLACK);
  386. g.setStroke(new BasicStroke(1));
  387. g.drawRect(pos.getX() - GuiSettings.getPictureScaleDiv2(), pos.getY() + GuiSettings.getPictureScaleDiv2() - 1, barWidth - 1,
  388. barHeight);
  389. g.setFont(new Font("TimesNewRoman", Font.PLAIN, (int) (barHeight * 1.5) - 2));
  390. String percentageString = (Math.round((percentage * 100))) + "%";
  391. int stringWidth = (int) g.getFontMetrics().getStringBounds(percentageString, g).getWidth();
  392. if (percentage > 1.0f)
  393. g.setColor(Color.WHITE); // Just to see better on purple
  394. g.drawString(percentageString, pos.getX() + 1 - stringWidth / 2,
  395. pos.getY() + GuiSettings.getPictureScaleDiv2() - 1 + barHeight);
  396. }
  397. // old code
  398. void drawMarker(Graphics2D g) {
  399. Color transparentGrey = ColorPreference.Panel.ObjectSelection;
  400. if (sx > x && sy > y) {
  401. g.drawRect(x, y, sx - x, sy - y);
  402. g.setColor(transparentGrey);
  403. g.fillRect(x, y, sx - x, sy - y);
  404. } else if (sx < x && sy < y) {
  405. g.drawRect(sx, sy, x - sx, y - sy);
  406. g.setColor(transparentGrey);
  407. g.fillRect(sx, sy, x - sx, y - sy);
  408. } else if (sx >= x) {
  409. g.drawRect(x, sy, sx - x, y - sy);
  410. g.setColor(transparentGrey);
  411. g.fillRect(x, sy, sx - x, y - sy);
  412. } else if (sy >= y) {
  413. g.drawRect(sx, y, x - sx, sy - y);
  414. g.setColor(transparentGrey);
  415. g.fillRect(sx, y, x - sx, sy - y);
  416. }
  417. }
  418. public void paintComponent(Graphics g) {
  419. super.paintComponent(g);
  420. Graphics2D g2d = (Graphics2D) g;
  421. g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
  422. // -->Old code TODO(Tom2021-12-1): remove
  423. if (drawEdge) {
  424. g2d.setColor(Color.BLACK);
  425. g2d.setStroke(new BasicStroke(1));
  426. g2d.drawLine(tempCps.getPosition().getX(), tempCps.getPosition().getY(), x, y);
  427. }
  428. // <--
  429. // timstep:
  430. g.setFont(new Font("TimesNewRoman", Font.PLAIN, Math.max((int) (GuiSettings.getPictureScale() / 3.5f), 10)));
  431. g2d.setColor(Color.BLACK);
  432. Optional<VisualRepresentationalState> optVisualState = control.getSimManager().getActualVisualRepresentationalState();
  433. // VisualState Representation:
  434. if (optVisualState.isEmpty()) {
  435. return;
  436. }
  437. VisualRepresentationalState visualState = optVisualState.get();
  438. for (ExitCable cable : visualState.getExitCableList()) {
  439. paintExitCable(g2d, cable);
  440. }
  441. for (Edge cable : visualState.getCableList()) {
  442. paintCable(g2d, cable, GuiSettings.getSelectedEdges().contains(cable));
  443. }
  444. for (DecoratedGroupNode dGroupNode : visualState.getGroupNodeList()) {
  445. paintGroupNode(g2d, dGroupNode);
  446. }
  447. for (Consumer con : visualState.getConsumerList()) {
  448. paintConsumer(g2d, con);
  449. }
  450. for (Supplier sup : visualState.getSupplierList()) {
  451. paintSupplier(g2d, sup);
  452. }
  453. for (Passiv pas : visualState.getPassivList()) {
  454. paintCanvasObject(g2d, pas);
  455. }
  456. for (DecoratedSwitch dSwitch : visualState.getSwitchList()) {
  457. paintSwitch(g2d, dSwitch);
  458. }
  459. for (Node node : visualState.getNodeList()) {
  460. drawCanvasObject(g2d, "/Images/node.png", node.getPosition());
  461. }
  462. // -->oldCode
  463. if (doMark) {
  464. g2d.setColor(Color.BLACK);
  465. g2d.setStroke(new BasicStroke(0));
  466. drawMarker(g2d);
  467. }
  468. // Test Selection
  469. // Objects:
  470. g2d.setColor(Color.BLUE);
  471. g2d.setStroke(new BasicStroke(1));
  472. Color transparentGrey = ColorPreference.Panel.ObjectSelection;
  473. for (AbstractCanvasObject aCps : GuiSettings.getSelectedObjects()) {
  474. if (aCps instanceof Node) {
  475. Vector2Int pos = aCps.getPosition();
  476. g2d.setColor(transparentGrey);
  477. g2d.fillOval(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2()),
  478. pos.getY() - (int) (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
  479. g2d.setColor(Color.LIGHT_GRAY);
  480. g2d.setStroke(new BasicStroke(2));
  481. g2d.drawOval(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2()),
  482. pos.getY() - (int) (GuiSettings.getPictureScaleDiv2()), GuiSettings.getPictureScale(), GuiSettings.getPictureScale());
  483. } else {
  484. Vector2Int pos = aCps.getPosition();
  485. g2d.setColor(transparentGrey);
  486. g2d.fillRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f),
  487. pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f),
  488. (int) (GuiSettings.getPictureScale() * 1.5f));
  489. g2d.setColor(Color.LIGHT_GRAY);
  490. g2d.setStroke(new BasicStroke(2));
  491. g2d.drawRect(pos.getX() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f),
  492. pos.getY() - (int) (GuiSettings.getPictureScaleDiv2() * 1.5f), (int) (GuiSettings.getPictureScale() * 1.5f),
  493. (int) (GuiSettings.getPictureScale() * 1.5f));
  494. }
  495. }
  496. // maybeReplace:
  497. if (mayBeReplaced != null) {
  498. g2d.setColor(Color.RED);
  499. Vector2Int pos = mayBeReplaced.getPosition();
  500. g2d.drawImage(ImageImport.loadImage("/Images/replace.png"), pos.getX() + GuiSettings.getPictureScaleDiv2(),
  501. pos.getY() - GuiSettings.getPictureScale(), GuiSettings.getPictureScaleDiv2(), GuiSettings.getPictureScaleDiv2(), null);
  502. }
  503. // <-- OldCode
  504. }
  505. @Override
  506. public void mouseClicked(MouseEvent e) {
  507. }
  508. @Override
  509. public void mouseEntered(MouseEvent e) {
  510. }
  511. @Override
  512. public void mouseExited(MouseEvent e) {
  513. }
  514. @Override
  515. public void mousePressed(MouseEvent e) {
  516. this.grabFocus();
  517. if (!disabled) {
  518. tempCps = null;
  519. edgeHighlight = null;
  520. GuiSettings.getSelectedEdges().clear();
  521. // Object Selection
  522. for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
  523. cx = cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2();
  524. cy = cps.getPosition().getY() - GuiSettings.getPictureScaleDiv2();
  525. if (x - GuiSettings.getPictureScale() <= cx && y - GuiSettings.getPictureScale() <= cy && x >= cx && y >= cy) {
  526. tempCps = cps;
  527. dragging = true;
  528. if (e.isControlDown() && tempCps != null) {
  529. System.out.println("Add Remove Selection CANVAS");
  530. if (GuiSettings.getSelectedObjects().contains(tempCps)) {
  531. control.removeObjectFromSelection(tempCps);
  532. } else {
  533. control.addSelectedObject(tempCps);
  534. }
  535. }
  536. // If drawing an Edge (CTRL down)
  537. if (tempCps.getClass() == HolonObject.class) {
  538. HolonObject tempObj = ((HolonObject) tempCps);
  539. dataSelected = tempObj.getElements();
  540. }
  541. if (e.isShiftDown()) {
  542. drawEdge = true;
  543. dragging = false;
  544. }
  545. }
  546. }
  547. // Edge Selection
  548. if (tempCps == null) {
  549. edgeHighlight = mousePositionOnEdge(x, y);
  550. GuiSettings.getSelectedEdges().add(edgeHighlight);
  551. if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) {
  552. control.clearSelection();
  553. }
  554. }
  555. if (edgeHighlight == null && tempCps == null) {
  556. sx = e.getX();
  557. sy = e.getY();
  558. doMark = true;
  559. }
  560. repaint();
  561. }
  562. }
  563. @Override
  564. public void mouseReleased(MouseEvent e) {
  565. if (!disabled) {
  566. x = e.getX();
  567. y = e.getY();
  568. dragging = false;
  569. if (drawEdge) {
  570. drawEdge = false;
  571. drawDeleteEdge();
  572. }
  573. if (dragged) {
  574. try {
  575. /**
  576. * Save before further Dragged interactions happen
  577. */
  578. control.autoSave();
  579. } catch (IOException ex) {
  580. System.err.println("AutoSave error by dragging");
  581. ex.printStackTrace();
  582. }
  583. /**
  584. * check if a unique tempCps could replace an Object on the canvas
  585. */
  586. if (GuiSettings.getSelectedObjects().size() == 1 && checkForReplacement(model.getObjectsOnCanvas(),
  587. tempCps, tempCps.getPosition().getX(), tempCps.getPosition().getY())) {
  588. /**
  589. * if UpperNode would be replaced, close its tabs
  590. */
  591. if (mayBeReplaced instanceof GroupNode)
  592. closeUpperNodeTab(mayBeReplaced.getId());
  593. /**
  594. * replace on canvas (will save)
  595. */
  596. control.replaceCanvasObject(mayBeReplaced, tempCps);
  597. mayBeReplaced = null;
  598. }
  599. }
  600. if (!e.isControlDown() && !dragged && tempCps != null && MouseEvent.BUTTON3 != e.getButton()) {
  601. control.clearSelection();
  602. control.addSelectedObject(tempCps);
  603. if (tempCps instanceof GroupNode)
  604. control.getObjectsInDepth();
  605. }
  606. dragged = false;
  607. // Rightclick List
  608. setRightClickMenu(e);
  609. markObjects();
  610. boolean doubleclick = doubleClick();
  611. if (doubleclick && tempCps instanceof HolonSwitch sw && MouseEvent.BUTTON3 != e.getButton()
  612. && tempCps != null) {
  613. sw.switchState();
  614. }
  615. if (doubleclick && tempCps != null && tempCps instanceof GroupNode groupnode) {
  616. control.getGui().openNewUpperNodeTab(groupnode);
  617. }
  618. control.calculateStateAndVisualForTimeStep(model.getCurrentIteration());
  619. repaint();
  620. }
  621. }
  622. @Override
  623. public void mouseDragged(MouseEvent e) {
  624. if (!disabled) {
  625. // If Edge is drawn
  626. x = e.getX();
  627. y = e.getY();
  628. if (!GuiSettings.getSelectedObjects().contains(tempCps) && !doMark) {
  629. control.clearSelection();
  630. if (tempCps != null) {
  631. control.addSelectedObject(tempCps);
  632. }
  633. }
  634. if (dragging) {
  635. try {
  636. dragged = true;
  637. float xDist, yDist; // Distance
  638. x = e.getX();
  639. y = e.getY();
  640. // Make sure its in bounds
  641. int scaleDiv2 = GuiSettings.getPictureScaleDiv2();
  642. if (e.getX() < scaleDiv2)
  643. x = scaleDiv2;
  644. else if (e.getX() > this.getWidth() - scaleDiv2)
  645. x = this.getWidth() - scaleDiv2;
  646. if (e.getY() < scaleDiv2)
  647. y = scaleDiv2;
  648. else if (e.getY() > this.getHeight() - scaleDiv2)
  649. y = this.getHeight() - scaleDiv2;
  650. // Distance
  651. xDist = x - tempCps.getPosition().getX();
  652. yDist = y - tempCps.getPosition().getY();
  653. tempCps.setPosition(x, y); // Drag Position
  654. // ToolTipText Position and name
  655. toolTip = true;
  656. toolTipText = tempCps.getName() + ", " + tempCps.getId();
  657. toolTipPos.setX(tempCps.getPosition().getX() - scaleDiv2);
  658. toolTipPos.setY(tempCps.getPosition().getY() + scaleDiv2);
  659. // All Selected Objects
  660. for (AbstractCanvasObject cps : GuiSettings.getSelectedObjects()) {
  661. if (cps != tempCps) {
  662. x = (int) (cps.getPosition().getX() + xDist);
  663. y = (int) (cps.getPosition().getY() + yDist);
  664. // Make sure its in bounds
  665. if (x <= scaleDiv2)
  666. x = scaleDiv2;
  667. else if (x > this.getWidth() - scaleDiv2)
  668. x = this.getWidth() - scaleDiv2;
  669. if (y <= scaleDiv2)
  670. y = scaleDiv2;
  671. else if (y > this.getHeight() - scaleDiv2)
  672. y = this.getHeight() - scaleDiv2;
  673. cps.setPosition(x, y);
  674. }
  675. }
  676. /**
  677. * check if something might be replaced
  678. */
  679. if (GuiSettings.getSelectedObjects().size() == 1)
  680. checkForReplacement(model.getObjectsOnCanvas(), tempCps, x, y);
  681. repaint();
  682. } catch (Exception eex) {
  683. }
  684. }
  685. // Mark Objects
  686. if (doMark) {
  687. tempSelected.clear();
  688. for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
  689. int x1 = sx, x2 = x, y1 = sy, y2 = y;
  690. if (sx >= x) {
  691. x1 = x;
  692. x2 = sx;
  693. }
  694. if (sy >= y) {
  695. y1 = y;
  696. y2 = sy;
  697. }
  698. if (x1 <= cps.getPosition().getX() + GuiSettings.getPictureScaleDiv2()
  699. && y1 <= cps.getPosition().getY() + GuiSettings.getPictureScaleDiv2() && x2 >= cps.getPosition().getX()
  700. && y2 >= cps.getPosition().getY()) {
  701. tempSelected.add(cps);
  702. }
  703. }
  704. }
  705. repaint();
  706. }
  707. }
  708. @Override
  709. public void mouseMoved(MouseEvent e) {
  710. if (!disabled) {
  711. x = e.getX();
  712. y = e.getY();
  713. // Everything for the tooltip :)
  714. boolean on = false;
  715. for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
  716. cx = cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2();
  717. cy = cps.getPosition().getY() - GuiSettings.getPictureScaleDiv2();
  718. if (x - GuiSettings.getPictureScale() <= cx && y - GuiSettings.getPictureScale() <= cy && x >= cx && y >= cy) {
  719. on = true;
  720. toolTipPos.setX(cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2());
  721. toolTipPos.setY(cps.getPosition().getY() + GuiSettings.getPictureScaleDiv2());
  722. toolTipText = cps.getName() + ", " + cps.getId();
  723. }
  724. }
  725. if (on || (!on && toolTip))
  726. repaint();
  727. toolTip = on;
  728. }
  729. }
  730. /**
  731. * Draws or Deletes an Edge.
  732. */
  733. void drawDeleteEdge() {
  734. if (getMousePosition() != null) {
  735. boolean node = true;
  736. boolean newEdge = true;
  737. boolean onEdge = true;
  738. boolean deleteNode = false;
  739. Edge e = null;
  740. for (AbstractCanvasObject cps : model.getObjectsOnCanvas()) {
  741. cx = cps.getPosition().getX() - GuiSettings.getPictureScaleDiv2();
  742. cy = cps.getPosition().getY() - GuiSettings.getPictureScaleDiv2();
  743. if (x - GuiSettings.getPictureScale() <= cx && y - GuiSettings.getPictureScale() <= cy && x >= cx && y >= cy
  744. && cps != tempCps) {
  745. node = false;
  746. onEdge = false;
  747. if (!newEdge) {
  748. control.removeEdgesOnCanvas(e);
  749. // Node ohne Edge?
  750. if (e.getA().getClass() == Node.class) {
  751. tempCps = e.getA();
  752. deleteNode = true;
  753. }
  754. if (e.getB().getClass() == Node.class) {
  755. deleteNode = true;
  756. }
  757. } else {
  758. if (!(cps instanceof GroupNode || tempCps instanceof GroupNode)) {
  759. e = new Edge(cps, tempCps, GuiSettings.maxCapacityForNewCreatedEdges);
  760. control.addEdgeOnCanvas(e);
  761. } else if (cps instanceof GroupNode groupnode && !(tempCps instanceof GroupNode)) {
  762. GroupNode thisUpperNode = groupnode;
  763. Object[] possibilities = thisUpperNode.getObjectsInThisLayer().map(aCps -> new ACpsHandle(aCps))
  764. .filter(aCpsHandle -> !(aCpsHandle.object instanceof GroupNode)).toArray();
  765. if (possibilities.length != 0) {
  766. ACpsHandle selected = (ACpsHandle) JOptionPane.showInputDialog(this,
  767. "Select a inside Object:", "Connection To?", JOptionPane.OK_OPTION,
  768. new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)),
  769. possibilities, "");
  770. if (selected != null) {
  771. e = new Edge(selected.object, tempCps, GuiSettings.maxCapacityForNewCreatedEdges);
  772. control.addEdgeOnCanvas(e);
  773. }
  774. } else {
  775. Node n = new Node("Node");
  776. n.setPosition(x, y);
  777. control.addObjUpperNode(n, thisUpperNode);
  778. e = new Edge(n, tempCps, GuiSettings.maxCapacityForNewCreatedEdges);
  779. control.addEdgeOnCanvas(e);
  780. }
  781. }
  782. }
  783. }
  784. }
  785. // Edge auf eine Edge gezogen?
  786. if (onEdge && !checkForReplacement(x, y)) {
  787. Edge p = mousePositionOnEdge(x, y);
  788. if (p != null) {
  789. Edge e1;
  790. Edge e2;
  791. node = false;
  792. Node n = new Node("Node");
  793. n.setPosition(x, y);
  794. control.addObjectCanvas(n);
  795. AbstractCanvasObject r, k;
  796. r = p.getA();
  797. k = p.getB();
  798. e = new Edge(n, tempCps, GuiSettings.maxCapacityForNewCreatedEdges);
  799. e1 = new Edge(n, r, GuiSettings.maxCapacityForNewCreatedEdges);
  800. e2 = new Edge(n, k, GuiSettings.maxCapacityForNewCreatedEdges);
  801. control.removeEdgesOnCanvas(p);
  802. control.addEdgeOnCanvas(e);
  803. control.addEdgeOnCanvas(e1);
  804. control.addEdgeOnCanvas(e2);
  805. }
  806. } else {
  807. mayBeReplaced = null;
  808. }
  809. // ins leere Gedragged
  810. if (node && !checkForReplacement(x, y)) {
  811. Node n = new Node("Node");
  812. n.setPosition(x, y);
  813. control.addObjectCanvas(n);
  814. e = new Edge(n, tempCps, GuiSettings.maxCapacityForNewCreatedEdges);
  815. control.addEdgeOnCanvas(e);
  816. } else {
  817. mayBeReplaced = null;
  818. }
  819. // Wenn ein Node ohne Connections da ist
  820. if (deleteNode) {
  821. control.delCanvasObject(tempCps, true);
  822. tempCps = null;
  823. }
  824. }
  825. }
  826. /**
  827. * Checks if the mouse is on an Edge.
  828. *
  829. * @param x Position of the Mouse
  830. * @param y Position of the Mouse
  831. * @return CpsEdge the Mouse is on, null if the mouse is not on an Edge
  832. */
  833. protected Edge mousePositionOnEdge(int x, int y) {
  834. x += GuiSettings.getPictureScaleDiv2();
  835. y += GuiSettings.getPictureScaleDiv2();
  836. for (Edge p : model.getEdgesOnCanvas()) {
  837. Line2D l = new Line2D.Float(p.getA().getPosition().getX(), p.getA().getPosition().getY(),
  838. p.getB().getPosition().getX(), p.getB().getPosition().getY());
  839. int[] positions = determineMousePositionOnEdge(p);
  840. int lx = positions[0];
  841. int ly = positions[1];
  842. int hx = positions[2];
  843. int hy = positions[3];
  844. // distance from a point to a line and between both Objects
  845. if (l.ptLineDistSq(x - GuiSettings.getPictureScaleDiv2(), y - GuiSettings.getPictureScaleDiv2()) < 20 && x > lx && x < hx && y > ly
  846. && y < hy) {
  847. return p;
  848. }
  849. }
  850. return null;
  851. }
  852. /**
  853. * set toolTip
  854. *
  855. * @param bool
  856. */
  857. public void setToolTip(boolean bool) {
  858. this.toolTip = bool;
  859. }
  860. /**
  861. * Set the Mouse
  862. *
  863. * @param x
  864. * @param y
  865. */
  866. public void setXY(int x, int y) {
  867. this.x = x;
  868. this.y = y;
  869. }
  870. @Override
  871. public boolean checkForReplacement(int x, int y) {
  872. return checkForReplacement(model.getObjectsOnCanvas(), null, x, y);
  873. }
  874. @Override
  875. public void tryToAlignObjects() {
  876. /**
  877. * Align all Objects
  878. */
  879. for (AbstractCanvasObject cps : model.getObjectsOnCanvas())
  880. align(cps, 3 * GuiSettings.getPictureScaleDiv2());
  881. /**
  882. * AutoSave new Positons
  883. */
  884. try {
  885. control.autoSave();
  886. } catch (IOException ex) {
  887. System.err.println("AutoSave error by aligning");
  888. ex.printStackTrace();
  889. }
  890. }
  891. @Override
  892. public void closeUpperNodeTab(int upperNodeId) {
  893. JTabbedPane tabbedPaneInner = (JTabbedPane) getParent().getParent().getParent().getParent();
  894. for (int i = 1; i < tabbedPaneInner.getTabCount(); i++) {
  895. if (((GroupNodeCanvas) ((JScrollPane) tabbedPaneInner.getComponentAt(i)).getViewport().getComponent(0))
  896. .getGroupNode().getId() == upperNodeId) {
  897. tabbedPaneInner.remove(i);
  898. break;
  899. }
  900. }
  901. }
  902. }