Canvas.java 33 KB

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