Gui.java 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. package holeg.ui.view.main;
  2. import holeg.interfaces.LocalMode;
  3. import holeg.model.*;
  4. import holeg.preferences.ColorPreference;
  5. import holeg.preferences.ImagePreference;
  6. import holeg.preferences.PreferenceKeys;
  7. import holeg.ui.controller.Control;
  8. import holeg.ui.model.GuiSettings;
  9. import holeg.ui.view.canvas.Canvas;
  10. import holeg.ui.view.category.Category;
  11. import holeg.ui.view.component.ButtonTabComponent;
  12. import holeg.ui.view.dialog.*;
  13. import holeg.ui.view.dialog.CreateNewDialog.Option;
  14. import holeg.ui.view.image.Import;
  15. import holeg.ui.view.information.HolonInformationPanel;
  16. import holeg.ui.view.inspector.Inspector;
  17. import holeg.ui.view.inspector.UnitGraph;
  18. import holeg.ui.view.window.AddOnWindow;
  19. import holeg.ui.view.window.FlexWindow;
  20. import holeg.ui.view.window.Outliner;
  21. import javax.swing.*;
  22. import javax.swing.filechooser.FileNameExtensionFilter;
  23. import javax.swing.filechooser.FileSystemView;
  24. import javax.swing.tree.DefaultMutableTreeNode;
  25. import javax.swing.tree.DefaultTreeModel;
  26. import javax.swing.tree.TreeCellRenderer;
  27. import java.awt.*;
  28. import java.awt.event.*;
  29. import java.io.File;
  30. import java.net.URI;
  31. import java.util.Collection;
  32. import java.util.logging.Logger;
  33. import java.util.prefs.Preferences;
  34. /**
  35. * Graphical User Interface.
  36. *
  37. * @author Gruppe14
  38. */
  39. public class Gui {
  40. private static final Logger log = Logger.getLogger(Model.class.getName());
  41. private static final Preferences prefs = Preferences.userNodeForPackage(Gui.class);
  42. private final JSplitPane splitPane = new JSplitPane();
  43. private final JSplitPane splitPane1 = new JSplitPane();
  44. private final JPanel myPanel = new JPanel(new BorderLayout());
  45. // the tabbed canvas containing the different sub-net tabs of the grid (Main
  46. // Grid + Nodes of Nodes)
  47. private final JTabbedPane tabbedPaneInnerOriginal = new JTabbedPane(JTabbedPane.TOP);
  48. // the main canvas where we can see the grid currently displayed
  49. private final JScrollPane canvasSP = new JScrollPane();
  50. private final JScrollPane scrollPane1 = new JScrollPane();
  51. // private final JScrollPane holonSP = new JScrollPane();
  52. // the original tabbed Pane (containing tabs for view, statistics, holon,
  53. // flexibility)
  54. private final JTabbedPane tabbedPaneOriginal = new JTabbedPane(JTabbedPane.TOP);
  55. private final JPopupMenu popmenuEdit = new JPopupMenu();
  56. private final JMenuItem editItem = new JMenuItem("Edit Object");
  57. private final JTree categoryTree = new JTree();
  58. /******************************************
  59. ************* Right Container*************
  60. ******************************************
  61. * Right Container: here comes the information about the HolonObject, such as
  62. * HolonElements Information, Properties and Consumption/Production graph.
  63. **/
  64. private final Inspector inspector;
  65. private final HolonInformationPanel informationPanel;
  66. private final JSplitPane splitHolonElPro = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
  67. private final JScrollPane scrollProperties = new JScrollPane();
  68. // In this section is the graph for the selected HolonElement of the clicked
  69. private final Control control;
  70. // In this section are all the Holonelements that correspond to the clicked
  71. // HolonObject with consumption/production, name and amount.
  72. private final JPanel panel = new JPanel();
  73. private final JButton btnAdd = new JButton();
  74. // Buttons
  75. private final JPopupMenu btnAddPopUp = new JPopupMenu("New");
  76. private final JMenuItem mItemNew = new JMenuItem("New..");
  77. private final JMenuItem mItemCategory = new JMenuItem("Category");
  78. private final JMenuItem mItemObject = new JMenuItem("Object");
  79. private final JMenuItem mItemSwitch = new JMenuItem("Switch");
  80. private final JButton btnDel = new JButton();
  81. private final JToolBar toolBar = new JToolBar();
  82. private final JToolBar toolBarHolonEl = new JToolBar();
  83. private final UnitGraph unitGraph;
  84. /**
  85. * Textfield to show the period of an element
  86. */
  87. private final JTextField unitGraphLocalPeriod = new JTextField(6);
  88. // Save / Load
  89. // Languages
  90. private Canvas canvas;
  91. // TODO(Tom2021-12-1) make GUI a JFRAME and remove holegJFrame
  92. private JFrame holegJFrame;
  93. // tabbedPaneOriginal or tabbedPaneSplit
  94. private JTabbedPane tabTemp;
  95. private String catOfObjToBeEdited;
  96. private Canvas unc;
  97. private JPanel contentPane;
  98. // Pop up Windows
  99. private AddObjectPopUp addObjectPopUP;
  100. private AboutUsPopUp aboutUsPopUp;
  101. // variables
  102. private boolean dragging = false;
  103. private String actualObjectClicked;
  104. private Image img = null;
  105. private AbstractCanvasObject tempCps = null;
  106. // Time Stuff
  107. private TimePanel timePanel;
  108. private AbstractCanvasObject temp = null;
  109. private String eraseCategory = "Do you really want to delete the Category ";
  110. private String selectObjBeforeErase = "Please select a Category or an Object in the left library in order to delete something.";
  111. private JMenuItem removeItem = new JMenuItem("Remove");
  112. /**
  113. * Create the application.
  114. *
  115. * @param control the Controller
  116. */
  117. public Gui(Control control) {
  118. this.control = control;
  119. this.informationPanel = new HolonInformationPanel(control);
  120. inspector = new Inspector(control);
  121. control.calculateStateAndVisualForCurrentTimeStep();
  122. this.unitGraph = new UnitGraph(control);
  123. this.canvas = new Canvas(control, control.getModel().getCanvas());
  124. initialize();
  125. updateCategories(GuiSettings.getCategories());
  126. control.OnCategoryChanged.addListener(() -> this.updateCategoryUI(GuiSettings.getCategories()));
  127. this.unc = this.canvas;
  128. }
  129. public TimePanel getTimePanel() {
  130. return timePanel;
  131. }
  132. /**
  133. * Initialize the contents of the frame.
  134. */
  135. private void initialize() {
  136. holegJFrame = new JFrame();
  137. holegJFrame.setTitle("HOLEG Simulator");
  138. holegJFrame.setBounds(new Rectangle(1200, 800));
  139. //Center
  140. holegJFrame.setLocationRelativeTo(null);
  141. holegJFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  142. holegJFrame.addWindowListener(new java.awt.event.WindowAdapter() {
  143. @Override
  144. public void windowClosing(java.awt.event.WindowEvent windowEvent) {
  145. if (JOptionPane.showConfirmDialog(holegJFrame, "Are you sure you want to exit?", "HOLEG",
  146. JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
  147. //TODO(Tom2022-01-27):
  148. System.exit(0);
  149. }
  150. }
  151. });
  152. contentPane = (JPanel) holegJFrame.getContentPane();
  153. int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
  154. InputMap inputMap = contentPane.getInputMap(condition);
  155. ActionMap actionMap = contentPane.getActionMap();
  156. String cntrlZDown = "controlZ";
  157. inputMap.put(KeyStroke.getKeyStroke("control Z"), cntrlZDown);
  158. actionMap.put(cntrlZDown, new AbstractAction() {
  159. @Override
  160. public void actionPerformed(ActionEvent e) {
  161. //TODO(Tom2022-01-27): CtrlZ
  162. }
  163. });
  164. String cntrlYDown = "controlY";
  165. inputMap.put(KeyStroke.getKeyStroke("control Y"), cntrlYDown);
  166. actionMap.put(cntrlYDown, new AbstractAction() {
  167. @Override
  168. public void actionPerformed(ActionEvent e) {
  169. //TODO Ctrl Y
  170. }
  171. });
  172. String cntrlADown = "controlA";
  173. inputMap.put(KeyStroke.getKeyStroke("control A"), cntrlADown);
  174. AbstractAction controlA = new AbstractAction() {
  175. @Override
  176. public void actionPerformed(ActionEvent e) {
  177. GuiSettings.getSelectedObjects().clear();
  178. //TODO(Tom2022-01-27): Ctrl A
  179. }
  180. };
  181. actionMap.put(cntrlADown, controlA);
  182. String delDown = "delete";
  183. inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false), delDown);
  184. actionMap.put(delDown, new AbstractAction() {
  185. private static final long serialVersionUID = 1L;
  186. @Override
  187. public void actionPerformed(ActionEvent e) {
  188. chooseTabTemp();
  189. //TODO(Tom2022-01-27): delete
  190. GuiSettings.getSelectedObjects().clear();
  191. }
  192. });
  193. String cntrlCDown = "controlC";
  194. inputMap.put(KeyStroke.getKeyStroke("control C"), cntrlCDown);
  195. AbstractAction controlC = new AbstractAction() {
  196. private static final long serialVersionUID = 1L;
  197. @Override
  198. public void actionPerformed(ActionEvent e) {
  199. chooseTabTemp();
  200. JScrollPane scrollPane = getScrollPaneFromTabbedPane();
  201. if (!GuiSettings.getSelectedObjects().isEmpty()) {
  202. if (scrollPane.getViewport().getComponent(0) instanceof Canvas groupNodeCanvas)
  203. control.copy(groupNodeCanvas.getGroupNode());
  204. else
  205. control.copy(null);
  206. if (!GuiSettings.getClipboardObjects().isEmpty()) {
  207. //TODO(Tom2022-01-14): old code changes itemPaste
  208. //OLD: canvas.itemPaste.setEnabled(true);
  209. }
  210. }
  211. }
  212. };
  213. actionMap.put(cntrlCDown, controlC);
  214. String cntrlVDown = "controlV";
  215. inputMap.put(KeyStroke.getKeyStroke("control V"), cntrlVDown);
  216. AbstractAction controlV = new AbstractAction() {
  217. private static final long serialVersionUID = 1L;
  218. @Override
  219. public void actionPerformed(ActionEvent e) {
  220. //TODO(Tom2022-01-27): Paste
  221. }
  222. };
  223. actionMap.put(cntrlVDown, controlV);
  224. String cntrlXDown = "controlX";
  225. inputMap.put(KeyStroke.getKeyStroke("control X"), cntrlXDown);
  226. AbstractAction controlX = new AbstractAction() {
  227. private static final long serialVersionUID = 1L;
  228. @Override
  229. public void actionPerformed(ActionEvent e) {
  230. chooseTabTemp();
  231. JScrollPane scrollPane = getScrollPaneFromTabbedPane();
  232. if (!GuiSettings.getSelectedObjects().isEmpty()) {
  233. if (scrollPane.getViewport().getComponent(0) instanceof Canvas groupNodeCanvas) {
  234. control.cut(groupNodeCanvas.getGroupNode());
  235. control.calculateStateAndVisualForCurrentTimeStep();
  236. scrollPane.getViewport().getComponent(0).repaint();
  237. } else {
  238. control.cut(null);
  239. control.calculateStateAndVisualForCurrentTimeStep();
  240. log.info("canvas.repaint3");
  241. canvas.repaint();
  242. }
  243. if (!GuiSettings.getClipboardObjects().isEmpty()) {
  244. //TODO(Tom2022-01-14): old code changes itemPaste
  245. //OLD: canvas.itemPaste.setEnabled(true);
  246. }
  247. }
  248. }
  249. };
  250. actionMap.put(cntrlXDown, controlX);
  251. holegJFrame.setJMenuBar(new GuiMenuBar());
  252. holegJFrame.setIconImage(Import.loadImage(ImagePreference.Logo, 30, 30));
  253. tabbedPaneInnerOriginal.addChangeListener(change -> {
  254. control.clearSelection();
  255. });
  256. /**
  257. * add Help Menu and its items
  258. */
  259. canvas.setBackground(Color.WHITE);
  260. canvas.setPreferredSize(new Dimension(GuiSettings.canvasSize.getX(), GuiSettings.canvasSize.getY()));
  261. /***********************
  262. * HolonElement Graph Actions
  263. **********************/
  264. /*
  265. * Update Local Period of an Element Graph
  266. */
  267. unitGraphLocalPeriod.addKeyListener(new KeyAdapter() {
  268. @Override
  269. public void keyReleased(KeyEvent e) {
  270. try {
  271. int localLength = Integer.parseInt(unitGraphLocalPeriod.getText());
  272. unitGraphLocalPeriod.setBackground(Color.WHITE);
  273. /**
  274. * set local graph Period
  275. */
  276. if (e.getKeyCode() == KeyEvent.VK_ENTER) {
  277. LocalMode.Period period = new LocalMode.Period(localLength);
  278. period.setInterval(localLength);
  279. unitGraph.setPeriod(period);
  280. }
  281. } catch (NumberFormatException ex) {
  282. unitGraphLocalPeriod.setBackground(ColorPreference.GUI.PALE_RED);
  283. }
  284. }
  285. });
  286. /*****************************
  287. * RIGHT CONTAINER DONE
  288. *****************************/
  289. holegJFrame.getContentPane().setLayout(new BorderLayout(0, 0));
  290. /****************
  291. * Tree Stuff
  292. ****************/
  293. // Override Key Actions
  294. inputMap = categoryTree.getInputMap();
  295. inputMap.put(KeyStroke.getKeyStroke("control C"), cntrlCDown);
  296. inputMap.put(KeyStroke.getKeyStroke("control V"), cntrlVDown);
  297. inputMap.put(KeyStroke.getKeyStroke("control X"), cntrlXDown);
  298. inputMap.put(KeyStroke.getKeyStroke("control A"), cntrlADown);
  299. TreeCellRenderer customRenderer = new TreeCellRenderer() {
  300. @Override
  301. public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
  302. boolean leaf, int row, boolean hasFocus) {
  303. JLabel label = new JLabel();
  304. Image imgR;
  305. if (leaf) {
  306. for (Category cat : GuiSettings.getCategories()) {
  307. for (AbstractCanvasObject cps : cat.getObjects()) {
  308. if (value.toString().equals(cps.getName())) {
  309. imgR = Import.loadImage(cps.getImagePath(), 50, 50);
  310. if (imgR != null) {
  311. label.setIcon(new ImageIcon(imgR));
  312. }
  313. label.setText(cps.getName());
  314. }
  315. }
  316. }
  317. }
  318. tree.setRowHeight(50);
  319. if (hasFocus) {
  320. label.setForeground(ColorPreference.Category.Focus);
  321. label.setOpaque(true);
  322. }
  323. if (label.getText().isEmpty()) {
  324. label.setText(value.toString());
  325. if (!value.toString().equals("Categories")) {
  326. label.setIcon(new ImageIcon(Import.loadImage(ImagePreference.Category.Folder)));
  327. }
  328. }
  329. return label;
  330. }
  331. };
  332. categoryTree.setCellRenderer(customRenderer);
  333. categoryTree.addMouseMotionListener(new MouseMotionAdapter() {
  334. public void mouseDragged(MouseEvent e) {
  335. checkForDragAndDrop(e);
  336. }
  337. /**
  338. * checks if an object of the current Panel could be replaced by the dragged
  339. * object
  340. *
  341. * @param e
  342. */
  343. private void checkForDragAndDrop(MouseEvent e) {
  344. try {
  345. /**
  346. * if no object gets dragged -> finished
  347. */
  348. if (!dragging)
  349. return;
  350. /**
  351. * select the current Panel
  352. */
  353. chooseTabTemp();
  354. JScrollPane scrollPane = getScrollPaneFromTabbedPane();
  355. if (scrollPane == null)
  356. return;
  357. Component canvasOrUpperNodeCanvas = scrollPane.getViewport().getComponent(0);
  358. /**
  359. * check for replacements on the canvas
  360. */
  361. if (canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) {
  362. if (unc.getMousePosition() == null)
  363. return;
  364. int x = (int) unc.getMousePosition().getX() + 16;
  365. int y = (int) unc.getMousePosition().getY() + 16;
  366. /**
  367. * check for replacement
  368. */
  369. groupNodeCanvas.checkForReplacement(x, y);
  370. /**
  371. * repaint
  372. */
  373. unc.invalidate();
  374. unc.repaint();
  375. } else {
  376. if (canvas.getMousePosition() == null)
  377. return;
  378. int x = (int) canvas.getMousePosition().getX() + 16;
  379. int y = (int) canvas.getMousePosition().getY() + 16;
  380. /**
  381. * check for replacement
  382. */
  383. canvas.checkForReplacement(x, y);
  384. /**
  385. * repaint
  386. */
  387. log.info("canvas.repaint5");
  388. canvas.repaint();
  389. }
  390. contentPane.updateUI();
  391. } catch (Exception eex) {
  392. eex.printStackTrace();
  393. }
  394. }
  395. });
  396. categoryTree.addMouseListener(new MouseAdapter() {
  397. public void mouseReleased(MouseEvent e) {
  398. try {
  399. if (dragging) {
  400. chooseTabTemp();
  401. JScrollPane scrollPane = getScrollPaneFromTabbedPane();
  402. Component canvasOrUpperNodeCanvas = scrollPane.getViewport().getComponent(0);
  403. if (canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) {
  404. int x = (int) groupNodeCanvas.getMousePosition().getX() + 16;
  405. int y = (int) groupNodeCanvas.getMousePosition().getY() + 16;
  406. AbstractCanvasObject h = null;
  407. if (tempCps instanceof HolonObject hO) {
  408. h = new HolonObject(hO);
  409. }
  410. if (tempCps instanceof HolonSwitch sw) {
  411. h = new HolonSwitch(sw);
  412. }
  413. h.setPosition(x, y);
  414. control.addObjectCanvas(control.getModel().getCanvas(), h);
  415. /**
  416. * object would be replaced
  417. */
  418. groupNodeCanvas.invalidate();
  419. control.calculateStateAndVisualForCurrentTimeStep();
  420. groupNodeCanvas.repaint();
  421. } else {
  422. int x = (int) canvas.getMousePosition().getX() + 16;
  423. int y = (int) canvas.getMousePosition().getY() + 16;
  424. AbstractCanvasObject h = null;
  425. if (tempCps instanceof HolonObject hO) {
  426. h = new HolonObject(hO);
  427. }
  428. if (tempCps instanceof HolonSwitch sw) {
  429. h = new HolonSwitch(sw);
  430. }
  431. h.setPosition(x, y);
  432. /**
  433. * close UpperNodeTabs of replaced UpperNode
  434. */
  435. //TODO(Tom2022-01-27):
  436. control.addObjectCanvas(control.getModel().getCanvas(), h);
  437. /**
  438. * no object should get replaced
  439. */
  440. log.info("canvas.repaint6");
  441. canvas.repaint();
  442. }
  443. control.calculateStateAndVisualForCurrentTimeStep();
  444. contentPane.updateUI();
  445. dragging = false;
  446. }
  447. } catch (Exception eex) {
  448. }
  449. holegJFrame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  450. }
  451. });
  452. popmenuEdit.add(editItem);
  453. popmenuEdit.add(removeItem);
  454. editItem.setEnabled(false);
  455. editItem.addActionListener(actionEvent -> {
  456. });
  457. categoryTree.addMouseListener(new MouseAdapter() {
  458. public void mousePressed(MouseEvent e) {
  459. try {
  460. actualObjectClicked = categoryTree.getPathForLocation(e.getX(), e.getY()).getLastPathComponent()
  461. .toString();
  462. // if an Object was selected, the porperties are shown in
  463. // the table
  464. DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) categoryTree
  465. .getPathForLocation(e.getX(), e.getY()).getLastPathComponent();
  466. if (SwingUtilities.isRightMouseButton(e)) {
  467. for (Category cat : GuiSettings.getCategories()) {
  468. for (AbstractCanvasObject cps : cat.getObjects()) {
  469. if (actualObjectClicked.equals(cps.getName())
  470. && !(cps instanceof HolonSwitch)) {
  471. editItem.setEnabled(true);
  472. popmenuEdit.show(e.getComponent(), e.getX(), e.getY());
  473. catOfObjToBeEdited = selectedNode.getParent().toString();
  474. tempCps = cps;
  475. }
  476. }
  477. }
  478. } else {
  479. for (Category cat : GuiSettings.getCategories()) {
  480. for (AbstractCanvasObject cps : cat.getObjects()) {
  481. if (actualObjectClicked.equals(cps.getName())) {
  482. File checkPath = new File(cps.getImagePath());
  483. if (checkPath.exists()) {
  484. img = new ImageIcon(cps.getImagePath()).getImage().getScaledInstance(32, 32,
  485. java.awt.Image.SCALE_SMOOTH);
  486. } else {
  487. img = Import.loadImage(cps.getImagePath(), 32, 32);
  488. }
  489. tempCps = cps;
  490. dragging = true;
  491. Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(img, new Point(0, 0),
  492. "Image");
  493. holegJFrame.setCursor(cursor);
  494. }
  495. }
  496. }
  497. }
  498. } catch (Exception eex) {
  499. }
  500. }
  501. });
  502. editItem.addActionListener(actionEvent -> {
  503. // Remove the selected Object object
  504. // AddObjectPopUp(boolean edit, AbstractCpsObject obj, String cat, JFrame
  505. // parentFrame)
  506. System.out.println("Edit");
  507. addObjectPopUP = new AddObjectPopUp(true, tempCps, catOfObjToBeEdited, holegJFrame);
  508. addObjectPopUP.setCategory(catOfObjToBeEdited);
  509. addObjectPopUP.setController(control);
  510. addObjectPopUP.setVisible(true);
  511. });
  512. removeItem.addActionListener(actionEvent -> {
  513. // Remove the selected Object object
  514. log.info("catOfObjToBeEdited:" + catOfObjToBeEdited + ", tempCps:" + tempCps);
  515. control.findCategoryWithName(catOfObjToBeEdited).ifPresent(cat -> {
  516. cat.removeObjectsWithName(tempCps.getName());
  517. });
  518. });
  519. scrollPane1.setViewportView(categoryTree);
  520. scrollPane1.setColumnHeaderView(panel);
  521. panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
  522. toolBar.setAlignmentX(Component.LEFT_ALIGNMENT);
  523. toolBar.setFloatable(false);
  524. panel.add(toolBar);
  525. btnAddPopUp.add(mItemNew);
  526. mItemNew.addActionListener(actionEvent -> {
  527. new CreateNewDialog(control, holegJFrame);
  528. });
  529. btnAddPopUp.addSeparator();
  530. btnAddPopUp.add(mItemCategory);
  531. mItemCategory.addActionListener(actionEvent -> {
  532. new CreateNewDialog(control, Option.Category, holegJFrame);
  533. });
  534. btnAddPopUp.add(mItemObject);
  535. mItemObject.addActionListener(actionEvent -> {
  536. new CreateNewDialog(control, Option.Object, holegJFrame);
  537. });
  538. btnAddPopUp.add(mItemSwitch);
  539. mItemSwitch.addActionListener(actionEvent -> {
  540. new CreateNewDialog(control, Option.Switch, holegJFrame);
  541. });
  542. btnAdd.addActionListener(actionEvent -> btnAddPopUp.show(btnAdd, -1, +20));
  543. btnAdd.setIcon(new ImageIcon(Import.loadImage("images/buttons/plus.png", 16, 16)));
  544. btnAdd.setToolTipText("<html><b>New</b><br>Add a new Category or Item to the library.</html>");
  545. toolBar.add(btnAdd);
  546. // Del Button
  547. btnDel.addActionListener(actionEvent -> {
  548. Object nodeInfo = categoryTree.getLastSelectedPathComponent();
  549. if (nodeInfo != null) {
  550. DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) nodeInfo;
  551. String nodeName = selectedNode.getUserObject().toString();
  552. int depthOfNode = selectedNode.getLevel();
  553. try {
  554. switch (depthOfNode) {
  555. case 1:
  556. int dialogResult = JOptionPane.showConfirmDialog(holegJFrame, eraseCategory + nodeName + "?",
  557. "Warning", JOptionPane.YES_NO_OPTION);
  558. if (dialogResult == JOptionPane.YES_OPTION) {
  559. GuiSettings.getCategories().stream().filter(cat -> cat.getName() == nodeName).findAny()
  560. .ifPresent(cat -> {
  561. control.deleteCategory(cat);
  562. });
  563. }
  564. break;
  565. case 2:
  566. DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
  567. control.findCategoryWithName(parent.getUserObject().toString()).ifPresent(cat -> {
  568. cat.removeObjectsWithName(nodeName);
  569. });
  570. break;
  571. default:
  572. JOptionPane.showMessageDialog(holegJFrame, selectObjBeforeErase);
  573. }
  574. } catch (Exception e2) {
  575. }
  576. } else {
  577. JOptionPane.showMessageDialog(holegJFrame, selectObjBeforeErase);
  578. }
  579. categoryTree.repaint();
  580. });
  581. btnDel.setIcon(new ImageIcon(Import.loadImage("images/buttons/minus.png", 16, 16)));
  582. btnDel.setToolTipText("<html><b>Delete</b><br>Removes a Category or a Category Item.</html>");
  583. toolBar.add(btnDel);
  584. holegJFrame.getContentPane().add(splitPane);
  585. timePanel = new TimePanel(control);
  586. timePanel.setBorder(null);
  587. timePanel.getTimeSlider().addChangeListener(changeEvent -> {
  588. // TimeSliderChanged event
  589. control.calculateStateAndVisualForTimeStep(timePanel.getTimeSlider().getValue());
  590. unitGraph.repaint();
  591. contentPane.updateUI();
  592. });
  593. splitPane1.setMinimumSize(new Dimension(0, 25));
  594. splitPane.setRightComponent(splitPane1);
  595. splitPane.setDividerLocation(200);
  596. splitPane1.setDividerLocation(500);
  597. splitPane.setLeftComponent(scrollPane1);
  598. tabbedPaneOriginal.addTab("View", tabbedPaneInnerOriginal);
  599. myPanel.add(canvasSP, BorderLayout.CENTER);
  600. tabbedPaneInnerOriginal.addTab("Main Grid", myPanel);
  601. splitPane1.setLeftComponent(tabbedPaneOriginal);
  602. splitPane1.setRightComponent(splitHolonElPro);
  603. splitPane1.setResizeWeight(0.9);
  604. splitHolonElPro.setDividerLocation(700);
  605. // containing the graph and the elements-list
  606. splitHolonElPro.setTopComponent(inspector);
  607. // containing the object's properties
  608. splitHolonElPro.setBottomComponent(scrollProperties);
  609. canvasSP.setViewportView(canvas);
  610. // Set up of the Properties section
  611. scrollProperties.setViewportView(this.informationPanel);
  612. scrollProperties.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  613. scrollProperties.getVerticalScrollBar().setUnitIncrement(16);
  614. tabbedPaneOriginal.setBorder(null);
  615. scrollProperties.setBorder(null);
  616. splitPane.setBorder(null);
  617. splitPane1.setBorder(null);
  618. splitHolonElPro.setBorder(null);
  619. canvasSP.setBorder(null);
  620. holegJFrame.getContentPane().add(timePanel, BorderLayout.SOUTH);
  621. canvasSP.addComponentListener(new ComponentAdapter() {
  622. @Override
  623. public void componentResized(ComponentEvent e) {
  624. GuiSettings.canvasSize.setX(Math.max(GuiSettings.canvasSize.getX(), canvasSP.getViewport().getWidth()));
  625. GuiSettings.canvasSize
  626. .setY(Math.max(GuiSettings.canvasSize.getY(), canvasSP.getViewport().getHeight()));
  627. log.info("canvas.repaint11");
  628. canvas.repaint();
  629. }
  630. });
  631. }
  632. /**
  633. * reloads the Categories from Model.
  634. *
  635. * @param categories the current categories
  636. */
  637. private void updateCategories(Collection<Category> categories) {
  638. DefaultTreeModel treemodel = new DefaultTreeModel(new DefaultMutableTreeNode("Categories") {
  639. {
  640. DefaultMutableTreeNode node1;
  641. for (Category c : categories) {
  642. node1 = new DefaultMutableTreeNode(c.getName());
  643. for (AbstractCanvasObject obj : c.getObjects()) {
  644. node1.add(new DefaultMutableTreeNode(obj.getName()));
  645. }
  646. add(node1);
  647. }
  648. }
  649. });
  650. categoryTree.setModel(treemodel);
  651. }
  652. /**
  653. * When changes are made to the Categories.
  654. *
  655. * @param categories the Categories
  656. */
  657. public void updateCategoryUI(Collection<Category> categories) {
  658. DefaultTreeModel model = (DefaultTreeModel) categoryTree.getModel();
  659. updateCategories(categories);
  660. model.reload();
  661. }
  662. public void setVisible(boolean value) {
  663. holegJFrame.setVisible(value);
  664. }
  665. /*
  666. * Open a new Tab with an UpperNodeCanvas
  667. */
  668. public void openNewUpperNodeTab(GroupNode node) {
  669. chooseTabTemp();
  670. JScrollPane scrollPane = getScrollPaneFromTabbedPane();
  671. if (scrollPane.getViewport().getComponent(0) instanceof Canvas canvasPanel) {
  672. unc = new Canvas(control, node);
  673. }
  674. // check if tab already open for clicked NodeOfNode
  675. boolean dupl = false;
  676. for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
  677. JScrollPane paneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i);
  678. if (paneOriginal != null && ((Canvas) paneOriginal.getViewport().getComponent(0)).getGroupNode()
  679. .getId() == node.getId()) {
  680. dupl = true;
  681. // set selected component to view
  682. tabbedPaneOriginal.setSelectedComponent(tabbedPaneInnerOriginal);
  683. // set selected tab in view to found upper-node-canvas
  684. tabbedPaneInnerOriginal.setSelectedComponent(tabbedPaneInnerOriginal.getComponentAt(i));
  685. }
  686. // if we found a duplicate, break
  687. if (dupl) {
  688. break;
  689. }
  690. }
  691. if (!dupl) {
  692. JScrollPane sp = new JScrollPane(unc);
  693. sp.setBorder(null);
  694. // Selected tabbed Pane = tabbedPaneOriginal or tabbedPaneSplit
  695. if (tabTemp == tabbedPaneOriginal) {
  696. this.tabbedPaneInnerOriginal.add(node.getName(), sp);
  697. this.tabbedPaneInnerOriginal.setSelectedComponent(sp);
  698. this.tabbedPaneInnerOriginal.setTabComponentAt(this.tabbedPaneInnerOriginal.getTabCount() - 1,
  699. new ButtonTabComponent(this.tabbedPaneInnerOriginal));
  700. }
  701. }
  702. }
  703. /**
  704. * Removes UpperNodeTab if UpperNode was deleted
  705. *
  706. * @param cps the CPS object that is currently selected
  707. */
  708. private void removeUpperNodeTab(AbstractCanvasObject cps) {
  709. if (cps instanceof GroupNode) {
  710. for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
  711. JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i);
  712. if (scrollPaneOriginal == null) {
  713. } else if (((Canvas) scrollPaneOriginal.getViewport().getComponent(0)).getGroupNode()
  714. .getId() == cps.getId()) {
  715. ((ButtonTabComponent) tabbedPaneInnerOriginal.getTabComponentAt(i)).removeTabs();
  716. break;
  717. }
  718. }
  719. }
  720. }
  721. /**
  722. * chooses whether to set the tabTemp to tabbedPaneOriginal or tabbedPaneSplit
  723. */
  724. private void chooseTabTemp() {
  725. // TODO(Tom2021-12-1) Remove tabTabbed
  726. tabTemp = tabbedPaneOriginal;
  727. }
  728. private JScrollPane getScrollPaneFromTabbedPane() {
  729. return getScrollPaneFromTabbedPane(-1);
  730. }
  731. private JScrollPane getScrollPaneFromTabbedPane(int index) {
  732. Component upperLevelSelectedComponent;
  733. if (tabTemp == null) {
  734. return null;
  735. }
  736. if (index == -1) {
  737. upperLevelSelectedComponent = tabTemp.getSelectedComponent();
  738. } else {
  739. upperLevelSelectedComponent = tabTemp.getComponentAt(index);
  740. }
  741. if (upperLevelSelectedComponent instanceof JTabbedPane) {
  742. Component nextLevel = ((JTabbedPane) upperLevelSelectedComponent).getSelectedComponent();
  743. if (nextLevel instanceof JPanel panel)
  744. return (JScrollPane) panel.getComponent(0);
  745. else
  746. return (JScrollPane) nextLevel;
  747. } else if (upperLevelSelectedComponent instanceof JScrollPane scrollPane) {
  748. return scrollPane;
  749. } else {
  750. return null;
  751. }
  752. }
  753. private void openWebpage(String URL) {
  754. try {
  755. java.awt.Desktop.getDesktop().browse(new URI(URL));
  756. } catch (Exception e) {
  757. e.printStackTrace();
  758. }
  759. }
  760. /**
  761. * closes all UpperNodeTabs, that don't have a valid UpperNode (e.g. if it was
  762. * ungrouped/deleted/replaced and so on)
  763. */
  764. private void closeInvalidUpperNodeTabs() {
  765. /**
  766. * close bugged Tabs
  767. */
  768. for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) {
  769. JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i);
  770. if (((Canvas) scrollPaneOriginal.getViewport().getComponent(0)).getGroupNode() == null) {
  771. ((ButtonTabComponent) tabbedPaneInnerOriginal.getTabComponentAt(i)).removeTabs();
  772. break;
  773. }
  774. }
  775. }
  776. private class GuiMenuBar extends JMenuBar {
  777. //Menus
  778. private final JMenu fileMenu = new JMenu("File");
  779. private final JMenu editMenu = new JMenu("Edit");
  780. private final JMenu viewMenu = new JMenu("View");
  781. private final JMenu windowMenu = new JMenu("Window");
  782. private final JMenu helpMenu = new JMenu("Help");
  783. // FileMenu
  784. private final JMenuItem newMenuButton = new JMenuItem("New");
  785. private final JMenuItem openMenuButton = new JMenuItem("Open..");
  786. private final JMenuItem saveMenuButton = new JMenuItem("Save");
  787. private final JMenuItem saveAsMenuButton = new JMenuItem("Save..");
  788. // EditMenu
  789. private final JMenuItem undoButton = new JMenuItem("Undo");
  790. private final JMenuItem redoButton = new JMenuItem("Redo");
  791. private final JMenuItem edgePropertiesButton = new JMenuItem("Edge Properties");
  792. private final JMenuItem alignAllButton = new JMenuItem("Align All");
  793. private final JMenu resetMenu = new JMenu("Reset");
  794. private final JMenuItem resetCategoryButton = new JMenuItem("Categories");
  795. //HelpMenu
  796. private final JMenuItem introductionButton = new JMenuItem("Introduction");
  797. private final JMenuItem userManualButton = new JMenuItem("User Manual");
  798. private final JMenuItem algorithmHelpButton = new JMenuItem("Algorithm Introduction");
  799. private final JMenuItem codeDocumentationButton = new JMenuItem("Code Documentation");
  800. private final JMenuItem aboutUsButton = new JMenuItem("About Us");
  801. //ViewMenu
  802. private final JMenu appearanceMenu = new JMenu("Appearance");
  803. private final JMenuItem canvasSizeButton = new JMenuItem("Set View Size");
  804. private final JCheckBoxMenuItem showSupplyBarsCheckBox = new JCheckBoxMenuItem("Show supply bars.", true);
  805. private final JFileChooser fileChooser = initFileChooser();
  806. //WindowMenu
  807. JMenuItem algorithmButton = new JMenuItem("Algorithm Panel", new ImageIcon(Import
  808. .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
  809. JMenuItem outlinerButton = new JMenuItem("Outliner", new ImageIcon(Import
  810. .loadImage(ImagePreference.Button.Menu.Outliner).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
  811. JMenuItem flexMenuButton = new JMenuItem("Flexibility Panel", new ImageIcon(Import
  812. .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
  813. GuiMenuBar() {
  814. initMenuLayout();
  815. initButtonActions();
  816. initButtonShortCuts();
  817. }
  818. private static JFileChooser initFileChooser() {
  819. JFileChooser safeLoadFileChooser = new JFileChooser(prefs.get(PreferenceKeys.Gui.DefaultFolder,
  820. FileSystemView.getFileSystemView().getDefaultDirectory().getPath()));
  821. safeLoadFileChooser.setFileFilter(new FileNameExtensionFilter("Holeg json files", "json"));
  822. safeLoadFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  823. safeLoadFileChooser.setAcceptAllFileFilterUsed(false);
  824. return safeLoadFileChooser;
  825. }
  826. private void initMenuLayout() {
  827. add(fileMenu);
  828. add(editMenu);
  829. add(viewMenu);
  830. add(windowMenu);
  831. add(helpMenu);
  832. fileMenu.add(newMenuButton);
  833. fileMenu.add(openMenuButton);
  834. fileMenu.addSeparator();
  835. fileMenu.add(saveMenuButton);
  836. fileMenu.add(saveAsMenuButton);
  837. editMenu.add(undoButton);
  838. editMenu.add(redoButton);
  839. editMenu.add(edgePropertiesButton);
  840. editMenu.add(alignAllButton);
  841. editMenu.add(resetMenu);
  842. resetMenu.add(resetCategoryButton);
  843. helpMenu.add(introductionButton);
  844. helpMenu.add(userManualButton);
  845. helpMenu.add(algorithmHelpButton);
  846. helpMenu.add(codeDocumentationButton);
  847. helpMenu.add(aboutUsButton);
  848. viewMenu.add(appearanceMenu);
  849. appearanceMenu.add(showSupplyBarsCheckBox);
  850. viewMenu.add(canvasSizeButton);
  851. windowMenu.add(algorithmButton);
  852. windowMenu.add(outlinerButton);
  853. windowMenu.add(flexMenuButton);
  854. }
  855. private void initButtonActions() {
  856. newMenuButton.addActionListener(clicked -> newFile());
  857. openMenuButton.addActionListener(clicked -> openFile());
  858. saveMenuButton.addActionListener(clicked -> saveFile());
  859. saveAsMenuButton.addActionListener(clicked -> saveNewFile());
  860. edgePropertiesButton.addActionListener(actionEvent -> new EditEdgesPopUp(holegJFrame, control));
  861. //TODO(Tom2022-01-14): recreateTryToAlignObjects
  862. alignAllButton.addActionListener(clicked -> {
  863. log.info("Not implemented yet.");
  864. });
  865. resetCategoryButton.addActionListener(clicked -> control.resetCategories());
  866. showSupplyBarsCheckBox.addActionListener(clicked -> toggleSupplyBarAppearance());
  867. canvasSizeButton.addActionListener(clicked -> new CanvasResizePopUp(control, canvas, tabbedPaneInnerOriginal,
  868. holegJFrame));
  869. algorithmButton.addActionListener(clicked -> new AddOnWindow(holegJFrame, control));
  870. outlinerButton.addActionListener(clicked -> new Outliner(holegJFrame, control));
  871. flexMenuButton.addActionListener(clicked -> new FlexWindow(holegJFrame, control));
  872. String tkWikiWebpage = "https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons/wiki/";
  873. introductionButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Introduction+V2.1"));
  874. userManualButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "User+Manual+V2.1"));
  875. algorithmHelpButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Algorithms+V2.1"));
  876. codeDocumentationButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Code+documentation+V2.1"));
  877. aboutUsButton.addActionListener(clicked -> new AboutUsPopUp(holegJFrame));
  878. }
  879. private void initButtonShortCuts() {
  880. int defaultModifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();
  881. saveMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier));
  882. saveAsMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier + InputEvent.SHIFT_DOWN_MASK));
  883. openMenuButton.setAccelerator(KeyStroke.getKeyStroke('O', defaultModifier));
  884. newMenuButton.setAccelerator(KeyStroke.getKeyStroke('N', defaultModifier));
  885. }
  886. private void toggleSupplyBarAppearance() {
  887. GuiSettings.showSupplyBars = showSupplyBarsCheckBox.isSelected();
  888. log.info("canvas.repaint4");
  889. canvas.repaint();
  890. }
  891. private void saveFile(){
  892. GuiSettings.getActualSaveFile().ifPresentOrElse(control::saveFile, this::saveNewFile);
  893. }
  894. private void saveNewFile() {
  895. if (fileChooser.showSaveDialog(holegJFrame) == JFileChooser.APPROVE_OPTION) {
  896. String path = fileChooser.getSelectedFile().getPath();
  897. if (!path.endsWith(".json")) {
  898. path += ".json";
  899. }
  900. prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath());
  901. control.saveFile(new File(path));
  902. }
  903. }
  904. private void openFile() {
  905. if (fileChooser.showOpenDialog(holegJFrame) == JFileChooser.APPROVE_OPTION) {
  906. prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath());
  907. control.loadFile(fileChooser.getSelectedFile());
  908. //TODO(Tom2022-01-27): make better
  909. canvas.setGroupNode(control.getModel().getCanvas());
  910. canvas.repaint();
  911. }
  912. }
  913. private void newFile() {
  914. if (control.getModel().getCanvas().getObjectsInThisLayer().findAny().isPresent()) {
  915. int selectedOption = JOptionPane.showConfirmDialog(holegJFrame, "Do you want to save your current model?",
  916. "Warning", JOptionPane.YES_NO_OPTION);
  917. if (selectedOption == JOptionPane.YES_OPTION) {
  918. saveNewFile();
  919. }
  920. }
  921. control.clearModel();
  922. }
  923. }
  924. }