Canvas.java 33 KB

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