package holeg.ui.view.main; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.io.File; import java.net.URI; import java.util.Collection; import java.util.logging.Logger; import java.util.prefs.Preferences; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeCellRenderer; import holeg.interfaces.LocalMode; import holeg.model.AbstractCanvasObject; import holeg.model.GroupNode; import holeg.model.HolonObject; import holeg.model.HolonSwitch; import holeg.preferences.ColorPreference; import holeg.preferences.ImagePreference; import holeg.ui.controller.Control; import holeg.ui.model.GuiSettings; import holeg.ui.model.IdCounter; import holeg.model.Model; import holeg.model.Model.FairnessModel; import holeg.ui.view.canvas.Canvas; import holeg.ui.view.component.ButtonTabComponent; import holeg.ui.view.dialog.AboutUsPopUp; import holeg.ui.view.dialog.AddObjectPopUp; import holeg.ui.view.dialog.CanvasResizePopUp; import holeg.ui.view.dialog.CreateNewDialog; import holeg.ui.view.dialog.CreateNewDialog.Option; import holeg.ui.view.dialog.EditEdgesPopUp; import holeg.ui.view.information.HolonInformationPanel; import holeg.ui.view.inspector.Inspector; import holeg.ui.view.inspector.UnitGraph; import holeg.ui.view.window.AddOnWindow; import holeg.ui.view.window.FlexWindow; import holeg.ui.view.window.Outliner; import holeg.ui.view.image.Import; /** * Graphical User Interface. * * @author Gruppe14 */ public class GUI { private static final Logger log = Logger.getLogger(Model.class.getName()); /** * Menu on the Top containing File, Edit View Help etc */ private final JMenuBar menuBar = new JMenuBar(); private final JMenu mnNewMenu = new JMenu("File"); private final JMenu mnNewMenuEdit = new JMenu("Edit"); private final JMenu mnNewMenuOptions = new JMenu("Options"); private final JMenu mnNewMenuView = new JMenu("View"); private final JMenu menuWindow = new JMenu("Window"); /** Help Menu containing helpful Informations and the AboutUs Popup */ private final JMenu mnHelp = new JMenu("Help"); /** * Help -> Introduction A small Introduction of the Application, SmartGrids and * Holons */ private final JMenuItem mntmIntroduction = new JMenuItem("Introduction"); /** * Help -> UserManual */ private final JMenuItem mntmUserManual = new JMenuItem("User Manual"); /** Help -> Algorithm Help Menu */ private final JMenuItem mntmAlgorithmHelp = new JMenuItem("Algorithm Introduction"); /** Help -> CodeDocumentation */ private final JMenuItem mntmCodeDoc = new JMenuItem("Code Documentation"); /** Help -> AboutUs */ private final JMenuItem mntmAboutUs = new JMenuItem("About Us"); /** checked if supplyBars should be shown */ private final JCheckBoxMenuItem showSupplyBarsCheckBox = new JCheckBoxMenuItem("Show supply bars."); /** menu for the different fairness Models */ private final JMenu mnFairnessModel = new JMenu("Fairness Model"); /** press to supply minimum demand first */ private final JMenuItem mntmFairMinFirst = new JMenuItem("Minimum demand first"); /** press to give everyone the same energy */ private final JMenuItem mntmFairAlleEqual = new JMenuItem("Equal supply for everyone"); private final JMenuItem mntmOpen = new JMenuItem("Open"); private final JMenuItem mntmNew = new JMenuItem("New"); private final JMenuItem mntmSave = new JMenuItem("Save"); private final JMenuItem mntmCanvasSize = new JMenuItem("Set View Size"); private final JSplitPane splitPane = new JSplitPane(); private final JSplitPane splitPane1 = new JSplitPane(); // the tabbed canvas containing the different sub-net tabs of the grid (Main // Grid + Nodes of Nodes) private final JPanel myPanel = new JPanel(new BorderLayout()); private final JTabbedPane tabbedPaneInnerOriginal = new JTabbedPane(JTabbedPane.TOP); // the main canvas where we can see the grid currently displayed private final JScrollPane canvasSP = new JScrollPane(); private final JScrollPane scrollPane1 = new JScrollPane(); // private final JScrollPane holonSP = new JScrollPane(); // the original tabbed Pane (containing tabs for view, statistics, holon, // flexibility) private final JTabbedPane tabbedPaneOriginal = new JTabbedPane(JTabbedPane.TOP); private final JPopupMenu popmenuEdit = new JPopupMenu(); private final JMenuItem editItem = new JMenuItem("Edit Object"); private final JLabel elementGraph = new JLabel("None "); private final JTree categoryTree = new JTree(); /****************************************** ************* Right Container************* ****************************************** * Right Container: here comes the information about the HolonObject, such as * HolonElements Information, Properties and Consumption/Production graph. **/ private final Inspector inspector; private final HolonInformationPanel informationPanel; private final JSplitPane splitHolonElPro = new JSplitPane(JSplitPane.VERTICAL_SPLIT); // Prechoosed local Periods private final JScrollPane scrollProperties = new JScrollPane(); // In this section is the graph for the selected HolonElement of the clicked private final Model model; private final Control control; // In this section are all the Holonelements that correspond to the clicked // HolonObject with consumption/production, name and amount. private final JPanel panel = new JPanel(); private final JPanel panelHolonEl = new JPanel(); // Buttons private final JButton btnAdd = new JButton(); private final JPopupMenu btnAddPopUp = new JPopupMenu("Newacac"); private final JMenuItem mItemNew = new JMenuItem("New.."); private final JMenuItem mItemCategory = new JMenuItem("Category"); private final JMenuItem mItemObject = new JMenuItem("Object"); private final JMenuItem mItemSwitch = new JMenuItem("Switch"); private final JButton btnDel = new JButton(); private final JToolBar toolBar = new JToolBar(); private final JToolBar toolBarHolonEl = new JToolBar(); // Languages private Canvas canvas; private final UnitGraph unitGraph; /** Textfield to show the period of an element */ private final JTextField unitGraphLocalPeriod = new JTextField(6); private final JMenuItem mntmUndo = new JMenuItem("Undo"); private final JMenuItem mntmRedo = new JMenuItem("Redo"); private final JMenuItem mntmEditEdges = new JMenuItem("Edge Properties"); private final JMenuItem mntmAlignAll = new JMenuItem("Align All"); private final JMenuItem mntmResetCategory = new JMenuItem("Reset Categories"); // TODO(Tom2021-12-1) make GUI a JFRAME and remove holegJFrame private JFrame holegJFrame; // tabbedPaneOriginal or tabbedPaneSplit private JTabbedPane tabTemp; private String catOfObjToBeEdited; private Canvas unc; private JPanel contentPane; // Pop up Windows private AddObjectPopUp addObjectPopUP; private AboutUsPopUp aboutUsPopUp; // variables private boolean dragging = false; private String actualObjectClicked; private Image img = null; private AbstractCanvasObject tempCps = null; // Time Stuff private TimePanel timePanel; public TimePanel getTimePanel() { return timePanel; } private AbstractCanvasObject temp = null; private String warningText = "Warning"; private String saveBeforeNew = "Do you want to save your current data?"; private String eraseCategory = "Do you really want to delete the Category "; private String selectObjBeforeErase = "Please select a Category or an Object in the left library in order to delete something."; private JMenuItem removeItem = new JMenuItem("Remove"); // Save / Load private final JFileChooser safeLoadFileChooser = initSaveLoadFileChooser(); /** * Create the application. * * @param control the Controller */ GUI(Control control) { this.control = control; this.informationPanel = new HolonInformationPanel(control); this.model = control.getModel(); inspector = new Inspector(control); control.calculateStateAndVisualForCurrentTimeStep(); this.unitGraph = new UnitGraph(control); this.canvas = new Canvas(control, model.getCanvas()); initialize(); updateCategories(GuiSettings.getCategories()); control.OnCategoryChanged.addListener(() -> this.updateCategoryUI(GuiSettings.getCategories())); this.unc = this.canvas; } /** * Initialize the contents of the frame. */ private void initialize() { holegJFrame = new JFrame(); holegJFrame.setTitle("HOLEG Simulator"); holegJFrame.setBounds(new Rectangle(1200, 800)); //Center holegJFrame.setLocationRelativeTo(null); holegJFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); holegJFrame.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent windowEvent) { if (JOptionPane.showConfirmDialog(holegJFrame, "Are you sure you want to exit?", "HOLEG", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { //TODO(Tom2022-01-27): System.exit(0); } } }); contentPane = (JPanel) holegJFrame.getContentPane(); int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT; InputMap inputMap = contentPane.getInputMap(condition); ActionMap actionMap = contentPane.getActionMap(); String cntrlZDown = "controlZ"; inputMap.put(KeyStroke.getKeyStroke("control Z"), cntrlZDown); actionMap.put(cntrlZDown, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { //TODO(Tom2022-01-27): CtrlZ } }); String cntrlYDown = "controlY"; inputMap.put(KeyStroke.getKeyStroke("control Y"), cntrlYDown); actionMap.put(cntrlYDown, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { //TODO Ctrl Y } }); String cntrlADown = "controlA"; inputMap.put(KeyStroke.getKeyStroke("control A"), cntrlADown); AbstractAction controlA = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { GuiSettings.getSelectedObjects().clear(); //TODO(Tom2022-01-27): Ctrl A } }; actionMap.put(cntrlADown, controlA); String delDown = "delete"; inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false), delDown); actionMap.put(delDown, new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { chooseTabTemp(); //TODO(Tom2022-01-27): delete GuiSettings.getSelectedObjects().clear(); } }); String cntrlCDown = "controlC"; inputMap.put(KeyStroke.getKeyStroke("control C"), cntrlCDown); AbstractAction controlC = new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { chooseTabTemp(); JScrollPane scrollPane = getScrollPaneFromTabbedPane(); if (!GuiSettings.getSelectedObjects().isEmpty()) { if (scrollPane.getViewport().getComponent(0)instanceof Canvas groupNodeCanvas) control.copy(groupNodeCanvas.getGroupNode()); else control.copy(null); if (!GuiSettings.getClipboardObjects().isEmpty()) { //TODO(Tom2022-01-14): old code changes itemPaste //OLD: canvas.itemPaste.setEnabled(true); } } } }; actionMap.put(cntrlCDown, controlC); String cntrlVDown = "controlV"; inputMap.put(KeyStroke.getKeyStroke("control V"), cntrlVDown); AbstractAction controlV = new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { //TODO(Tom2022-01-27): Paste } }; actionMap.put(cntrlVDown, controlV); String cntrlXDown = "controlX"; inputMap.put(KeyStroke.getKeyStroke("control X"), cntrlXDown); AbstractAction controlX = new AbstractAction() { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { chooseTabTemp(); JScrollPane scrollPane = getScrollPaneFromTabbedPane(); if (!GuiSettings.getSelectedObjects().isEmpty()) { if (scrollPane.getViewport().getComponent(0)instanceof Canvas groupNodeCanvas) { control.cut(groupNodeCanvas.getGroupNode()); control.calculateStateAndVisualForCurrentTimeStep(); scrollPane.getViewport().getComponent(0).repaint(); } else { control.cut(null); control.calculateStateAndVisualForCurrentTimeStep(); log.info("canvas.repaint3"); canvas.repaint(); } if (!GuiSettings.getClipboardObjects().isEmpty()) { //TODO(Tom2022-01-14): old code changes itemPaste //OLD: canvas.itemPaste.setEnabled(true); } } } }; actionMap.put(cntrlXDown, controlX); holegJFrame.setJMenuBar(menuBar); holegJFrame.setIconImage(Import.loadImage(ImagePreference.Logo, 30, 30)); menuBar.add(mnNewMenu); mnNewMenu.add(mntmNew); mnNewMenu.add(mntmOpen); mnNewMenu.add(mntmSave); menuBar.add(mnNewMenuEdit); mnNewMenuEdit.add(mntmUndo); mnNewMenuEdit.add(mntmRedo); mnNewMenuEdit.add(mntmEditEdges); mntmEditEdges.addActionListener(actionEvent -> { EditEdgesPopUp edgePopUp = new EditEdgesPopUp(holegJFrame); edgePopUp.setCanvas(canvas); edgePopUp.setController(control); edgePopUp.setVisible(true); }); // Edit -> Align All mnNewMenuEdit.add(mntmAlignAll); mntmAlignAll.addActionListener(actionEvent -> { // getScrollPaneFromTabbedPane().getViewport().getComponent(0) is always the // active canvas tryToAlignObjects(); }); menuBar.add(mnNewMenuOptions); mnNewMenuOptions.add(mntmResetCategory); mntmResetCategory.addActionListener(actionEvent -> { control.resetCategories(); categoryTree.revalidate(); categoryTree.repaint(); }); /** * Add Fairness Model Option to the option Menu */ mnNewMenuOptions.add(mnFairnessModel); mnFairnessModel.add(mntmFairMinFirst); mntmFairMinFirst.setForeground(Color.BLUE); mntmFairMinFirst .setToolTipText("HolonObjects with the smallest mininum Demand will be partially supplied first.\n" + "After that as many HolonObjects as possible will get fully supplied."); mntmFairMinFirst.addActionListener(arg0 -> { control.getModel().setFairnessModel(FairnessModel.MininumDemandFirst); mntmFairMinFirst.setForeground(Color.BLUE); mntmFairAlleEqual.setForeground(mnFairnessModel.getForeground()); control.calculateStateAndVisualForCurrentTimeStep(); // Update UpperNodes Component canvasOrUpperNodeCanvas = getScrollPaneFromTabbedPane().getViewport().getComponent(0); if (canvasOrUpperNodeCanvas != null && canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) { groupNodeCanvas.repaint(); } }); mnFairnessModel.add(mntmFairAlleEqual); mntmFairAlleEqual.setToolTipText("HolonObjects will all get the same amount of energy."); mntmFairAlleEqual.addActionListener(arg0 -> { control.getModel().setFairnessModel(FairnessModel.AllEqual); mntmFairAlleEqual.setForeground(Color.BLUE); mntmFairMinFirst.setForeground(mnFairnessModel.getForeground()); control.calculateStateAndVisualForCurrentTimeStep(); // Update UpperNodes Component canvasOrUpperNodeCanvas = getScrollPaneFromTabbedPane().getViewport().getComponent(0); if (canvasOrUpperNodeCanvas != null && canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) { groupNodeCanvas.repaint(); } }); menuBar.add(mnNewMenuView); mnNewMenuView.add(mntmCanvasSize); mntmCanvasSize.addActionListener(actionEvent -> { CanvasResizePopUp popUp = new CanvasResizePopUp(model, control, canvas, this.tabbedPaneInnerOriginal, holegJFrame); popUp.setVisible(true); }); tabbedPaneInnerOriginal.addChangeListener(change -> { control.clearSelection(); }); mnNewMenuView.add(mntmCanvasSize); /* * Adds Checkbox to turn supply bars on/off */ mnNewMenuView.add(showSupplyBarsCheckBox); showSupplyBarsCheckBox.setSelected(true); showSupplyBarsCheckBox.addActionListener(arg0 -> { GuiSettings.showSupplyBars = showSupplyBarsCheckBox.isSelected(); log.info("canvas.repaint4"); canvas.repaint(); // Update UpperNodes JScrollPane spane = getScrollPaneFromTabbedPane(); if (spane != null) { Component canvasOrUpperNodeCanvas = spane.getViewport().getComponent(0); if (canvasOrUpperNodeCanvas != null && canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) { groupNodeCanvas.repaint(); } } }); initWindowMenu(); /** * add Help Menu and its items */ menuBar.add(mnHelp); mnHelp.add(mntmIntroduction); mnHelp.add(mntmUserManual); mnHelp.add(mntmAlgorithmHelp); mnHelp.add(mntmCodeDoc); mnHelp.add(mntmAboutUs); canvas.setBackground(Color.WHITE); canvas.setPreferredSize(new Dimension(GuiSettings.canvasSize.getX(), GuiSettings.canvasSize.getY())); /******************** * RIGHT CONTAINER (INFORMATION) **********************/ panelHolonEl.setLayout(new BoxLayout(panelHolonEl, BoxLayout.X_AXIS)); toolBarHolonEl.setFloatable(false); panelHolonEl.add(toolBarHolonEl); /*********************** * HolonElement Graph Actions **********************/ /* * Update Local Period of an Element Graph */ unitGraphLocalPeriod.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { try { int localLength = Integer.parseInt(unitGraphLocalPeriod.getText()); unitGraphLocalPeriod.setBackground(Color.WHITE); /** * set local graph Period */ if (e.getKeyCode() == KeyEvent.VK_ENTER){ LocalMode.Period period = new LocalMode.Period(localLength); period.setInterval(localLength); unitGraph.setPeriod(period); } } catch (NumberFormatException ex) { unitGraphLocalPeriod.setBackground(ColorPreference.GUI.PALE_RED); } } }); /***************************** * RIGHT CONTAINER DONE *****************************/ holegJFrame.getContentPane().setLayout(new BorderLayout(0, 0)); /**************** * Tree Stuff ****************/ // Override Key Actions inputMap = categoryTree.getInputMap(); inputMap.put(KeyStroke.getKeyStroke("control C"), cntrlCDown); inputMap.put(KeyStroke.getKeyStroke("control V"), cntrlVDown); inputMap.put(KeyStroke.getKeyStroke("control X"), cntrlXDown); inputMap.put(KeyStroke.getKeyStroke("control A"), cntrlADown); TreeCellRenderer customRenderer = new TreeCellRenderer() { @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { JLabel label = new JLabel(); Image imgR; if (leaf) { for (Category cat : GuiSettings.getCategories()) { for (AbstractCanvasObject cps : cat.getObjects()) { if (value.toString().equals(cps.getName())) { imgR = Import.loadImage(cps.getImagePath(), 50, 50); if (imgR != null) { label.setIcon(new ImageIcon(imgR)); } label.setText(cps.getName()); } } } } tree.setRowHeight(50); if (hasFocus) { label.setForeground(ColorPreference.Category.Focus); label.setOpaque(true); } if (label.getText().isEmpty()) { label.setText(value.toString()); if (!value.toString().equals("Categories")) { label.setIcon(new ImageIcon(Import.loadImage(ImagePreference.Category.Folder))); } } return label; } }; categoryTree.setCellRenderer(customRenderer); categoryTree.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { checkForDragAndDrop(e); } /** * checks if an object of the current Panel could be replaced by the dragged * object * * @param e */ private void checkForDragAndDrop(MouseEvent e) { try { /** * if no object gets dragged -> finished */ if (!dragging) return; /** * select the current Panel */ chooseTabTemp(); JScrollPane scrollPane = getScrollPaneFromTabbedPane(); if (scrollPane == null) return; Component canvasOrUpperNodeCanvas = scrollPane.getViewport().getComponent(0); /** * check for replacements on the canvas */ if (canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) { if (unc.getMousePosition() == null) return; int x = (int) unc.getMousePosition().getX() + 16; int y = (int) unc.getMousePosition().getY() + 16; /** * check for replacement */ groupNodeCanvas.checkForReplacement(x, y); /** * repaint */ unc.invalidate(); unc.repaint(); } else { if (canvas.getMousePosition() == null) return; int x = (int) canvas.getMousePosition().getX() + 16; int y = (int) canvas.getMousePosition().getY() + 16; /** * check for replacement */ canvas.checkForReplacement(x, y); /** * repaint */ log.info("canvas.repaint5"); canvas.repaint(); } contentPane.updateUI(); } catch (Exception eex) { eex.printStackTrace(); } } }); categoryTree.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent e) { try { if (dragging) { chooseTabTemp(); JScrollPane scrollPane = getScrollPaneFromTabbedPane(); Component canvasOrUpperNodeCanvas = scrollPane.getViewport().getComponent(0); if (canvasOrUpperNodeCanvas instanceof Canvas groupNodeCanvas) { int x = (int) groupNodeCanvas.getMousePosition().getX() + 16; int y = (int) groupNodeCanvas.getMousePosition().getY() + 16; AbstractCanvasObject h = null; if (tempCps instanceof HolonObject hO) { h = new HolonObject(hO); } if (tempCps instanceof HolonSwitch sw) { h = new HolonSwitch(sw); } h.setPosition(x, y); control.addObjectCanvas(model.getCanvas(), h); /** * object would be replaced */ groupNodeCanvas.invalidate(); control.calculateStateAndVisualForCurrentTimeStep(); groupNodeCanvas.repaint(); } else { int x = (int) canvas.getMousePosition().getX() + 16; int y = (int) canvas.getMousePosition().getY() + 16; AbstractCanvasObject h = null; if (tempCps instanceof HolonObject hO) { h = new HolonObject(hO); } if (tempCps instanceof HolonSwitch sw) { h = new HolonSwitch(sw); } h.setPosition(x, y); /** * close UpperNodeTabs of replaced UpperNode */ //TODO(Tom2022-01-27): control.addObjectCanvas(model.getCanvas(), h); /** * no object should get replaced */ log.info("canvas.repaint6"); canvas.repaint(); } control.calculateStateAndVisualForCurrentTimeStep(); contentPane.updateUI(); dragging = false; } } catch (Exception eex) { } holegJFrame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } }); popmenuEdit.add(editItem); popmenuEdit.add(removeItem); editItem.setEnabled(false); editItem.addActionListener(actionEvent -> { }); categoryTree.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { try { actualObjectClicked = categoryTree.getPathForLocation(e.getX(), e.getY()).getLastPathComponent() .toString(); // if an Object was selected, the porperties are shown in // the table DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) categoryTree .getPathForLocation(e.getX(), e.getY()).getLastPathComponent(); if (SwingUtilities.isRightMouseButton(e)) { for (Category cat : GuiSettings.getCategories()) { for (AbstractCanvasObject cps : cat.getObjects()) { if (actualObjectClicked.equals(cps.getName()) && !(cps instanceof HolonSwitch)) { editItem.setEnabled(true); popmenuEdit.show(e.getComponent(), e.getX(), e.getY()); catOfObjToBeEdited = selectedNode.getParent().toString(); tempCps = cps; } } } } else { for (Category cat : GuiSettings.getCategories()) { for (AbstractCanvasObject cps : cat.getObjects()) { if (actualObjectClicked.equals(cps.getName())) { File checkPath = new File(cps.getImagePath()); if (checkPath.exists()) { img = new ImageIcon(cps.getImagePath()).getImage().getScaledInstance(32, 32, java.awt.Image.SCALE_SMOOTH); } else { img = Import.loadImage(cps.getImagePath(), 32, 32); } tempCps = cps; dragging = true; Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(img, new Point(0, 0), "Image"); holegJFrame.setCursor(cursor); } } } } } catch (Exception eex) { } } }); editItem.addActionListener(actionEvent -> { // Remove the selected Object object // AddObjectPopUp(boolean edit, AbstractCpsObject obj, String cat, JFrame // parentFrame) System.out.println("Edit"); addObjectPopUP = new AddObjectPopUp(true, tempCps, catOfObjToBeEdited, holegJFrame); addObjectPopUP.setCategory(catOfObjToBeEdited); addObjectPopUP.setController(control); addObjectPopUP.setVisible(true); }); removeItem.addActionListener(actionEvent -> { // Remove the selected Object object log.info("catOfObjToBeEdited:" + catOfObjToBeEdited + ", tempCps:" + tempCps); control.findCategoryWithName(catOfObjToBeEdited).ifPresent(cat -> { cat.removeObjectsWithName(tempCps.getName()); }); }); scrollPane1.setViewportView(categoryTree); scrollPane1.setColumnHeaderView(panel); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); toolBar.setAlignmentX(Component.LEFT_ALIGNMENT); toolBar.setFloatable(false); panel.add(toolBar); btnAddPopUp.add(mItemNew); mItemNew.addActionListener(actionEvent -> { new CreateNewDialog(control, holegJFrame); }); btnAddPopUp.addSeparator(); btnAddPopUp.add(mItemCategory); mItemCategory.addActionListener(actionEvent -> { new CreateNewDialog(control, Option.Category, holegJFrame); }); btnAddPopUp.add(mItemObject); mItemObject.addActionListener(actionEvent -> { new CreateNewDialog(control, Option.Object, holegJFrame); }); btnAddPopUp.add(mItemSwitch); mItemSwitch.addActionListener(actionEvent -> { new CreateNewDialog(control, Option.Switch, holegJFrame); }); btnAdd.addActionListener(actionEvent -> btnAddPopUp.show(btnAdd, -1, +20)); btnAdd.setIcon(new ImageIcon(Import.loadImage("images/buttons/plus.png", 16, 16))); btnAdd.setToolTipText("New
Add a new Category or Item to the library."); toolBar.add(btnAdd); /** * Help Menu Action Listeners */ /** * URL of the telecommunication git Wiki */ String tkWikiWebpage = "https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons/wiki/"; /** open Introduction Web Page */ mntmIntroduction.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { openWebpage(tkWikiWebpage + "Introduction+V2.1"); } }); /** open UserManual WebPage */ mntmUserManual.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { openWebpage(tkWikiWebpage + "User+Manual+V2.1"); } }); /** open Algorithm Help Web Page */ mntmAlgorithmHelp.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { openWebpage(tkWikiWebpage + "Algorithms+V2.1"); } }); /** open Code Documentation Web Page */ mntmCodeDoc.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { openWebpage(tkWikiWebpage + "Code+documentation+V2.1"); } }); /** * Pop up - About Us with some important information about the developers, * source and programming stuff */ mntmAboutUs.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { aboutUsPopUp = new AboutUsPopUp(holegJFrame); aboutUsPopUp.setVisible(true); } }); // Del Button btnDel.addActionListener(actionEvent -> { Object nodeInfo = categoryTree.getLastSelectedPathComponent(); if (nodeInfo != null) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) nodeInfo; String nodeName = selectedNode.getUserObject().toString(); int depthOfNode = selectedNode.getLevel(); try { switch (depthOfNode) { case 1: int dialogResult = JOptionPane.showConfirmDialog(holegJFrame, eraseCategory + nodeName + "?", warningText, JOptionPane.YES_NO_OPTION); if (dialogResult == JOptionPane.YES_OPTION) { GuiSettings.getCategories().stream().filter(cat -> cat.getName() == nodeName).findAny() .ifPresent(cat -> { control.deleteCategory(cat); }); } break; case 2: DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent(); control.findCategoryWithName(parent.getUserObject().toString()).ifPresent(cat -> { cat.removeObjectsWithName(nodeName); }); break; default: JOptionPane.showMessageDialog(holegJFrame, selectObjBeforeErase); } } catch (Exception e2) { } } else { JOptionPane.showMessageDialog(holegJFrame, selectObjBeforeErase); } categoryTree.repaint(); }); btnDel.setIcon(new ImageIcon(Import.loadImage("images/buttons/minus.png", 16, 16))); btnDel.setToolTipText("Delete
Removes a Category or a Category Item."); toolBar.add(btnDel); holegJFrame.getContentPane().add(splitPane); mntmNew.addActionListener(actionEvent -> { if (model.getCanvas().getObjectsInThisLayer().findAny().isPresent()) { int newWarning = JOptionPane.YES_NO_OPTION; int dialogForNewWarning = JOptionPane.showConfirmDialog(holegJFrame, saveBeforeNew, warningText, newWarning); if (dialogForNewWarning == JOptionPane.YES_OPTION) { mntmSave.doClick(); } } // Remove all but main tab while (tabbedPaneInnerOriginal.getTabCount() > 1) { tabbedPaneInnerOriginal.remove(1); } control.clearSelection(); model.clear(); control.OnSelectionChanged.broadcast(); GuiSettings.getSelectedEdges().clear(); control.getModel().setCurrentIteration(0); elementGraph.setText("None"); log.info("canvas.repaint7"); canvas.repaint(); IdCounter.reset(); IdCounter.reset(); control.calculateStateAndVisualForCurrentTimeStep(); }); mntmOpen.addActionListener(clicked -> { if(safeLoadFileChooser.showOpenDialog(this.holegJFrame) == JFileChooser.APPROVE_OPTION){ control.loadFile(safeLoadFileChooser.getSelectedFile()); //TODO(Tom2022-01-27): make better this.canvas.setGroupNode(control.getModel().getCanvas()); this.canvas.repaint(); } }); mntmSave.addActionListener(clicked -> { log.info("Save Button Pressed"); if(safeLoadFileChooser.showSaveDialog(this.holegJFrame) == JFileChooser.APPROVE_OPTION){ String path = safeLoadFileChooser.getSelectedFile().getPath(); if(!path.endsWith(".json")){ path += ".json"; } control.saveFile(new File(path)); } }); mntmUndo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { menuUndoActionPerformed(); } private void menuUndoActionPerformed() { // try { // control.loadAutoSave(control.getUndoSave()); // // closeInvalidUpperNodeTabs(); // // control.calculateStateAndVisualForCurrentTimeStep(); // log.info("canvas.repaint9"); // canvas.repaint(); // } catch (IOException e) { // e.printStackTrace(); // } } }); mntmRedo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { menuRedoActionPerformed(); } private void menuRedoActionPerformed() { // try { // control.loadAutoSave(control.getRedoSave()); // // closeInvalidUpperNodeTabs(); // // control.calculateStateAndVisualForCurrentTimeStep(); // log.info("canvas.repaint10"); // canvas.repaint(); // } catch (IOException e) { // e.printStackTrace(); // } } }); timePanel = new TimePanel(control); timePanel.setBorder(null); timePanel.getTimeSlider().addChangeListener(changeEvent -> { // TimeSliderChanged event control.calculateStateAndVisualForTimeStep(timePanel.getTimeSlider().getValue()); unitGraph.repaint(); contentPane.updateUI(); }); splitPane1.setMinimumSize(new Dimension(0, 25)); splitPane.setRightComponent(splitPane1); splitPane.setDividerLocation(200); splitPane1.setDividerLocation(500); splitPane.setLeftComponent(scrollPane1); tabbedPaneOriginal.addTab("View", tabbedPaneInnerOriginal); myPanel.add(canvasSP, BorderLayout.CENTER); tabbedPaneInnerOriginal.addTab("Main Grid", myPanel); splitPane1.setLeftComponent(tabbedPaneOriginal); splitPane1.setRightComponent(splitHolonElPro); splitPane1.setResizeWeight(0.9); splitHolonElPro.setDividerLocation(700); // containing the graph and the elements-list splitHolonElPro.setTopComponent(inspector); // containing the object's properties splitHolonElPro.setBottomComponent(scrollProperties); canvasSP.setViewportView(canvas); // Set up of the Properties section scrollProperties.setViewportView(this.informationPanel); scrollProperties.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scrollProperties.getVerticalScrollBar().setUnitIncrement(16); tabbedPaneOriginal.setBorder(null); scrollProperties.setBorder(null); splitPane.setBorder(null); splitPane1.setBorder(null); splitHolonElPro.setBorder(null); panelHolonEl.setBorder(null); canvasSP.setBorder(null); holegJFrame.getContentPane().add(timePanel, BorderLayout.SOUTH); // try { // control.loadAutoSave(System.getProperty("user.home") + "/.config/HolonGUI/Category/Category.json"); // } catch (IOException e1) { // } canvasSP.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { GuiSettings.canvasSize.setX(Math.max(GuiSettings.canvasSize.getX(), canvasSP.getViewport().getWidth())); GuiSettings.canvasSize .setY(Math.max(GuiSettings.canvasSize.getY(), canvasSP.getViewport().getHeight())); log.info("canvas.repaint11"); canvas.repaint(); } }); } private void tryToAlignObjects() { //TODO(Tom2022-01-14): recreateTryToAlignObjects } private JFileChooser initSaveLoadFileChooser(){ JFileChooser safeLoadFileChooser = new JFileChooser(Preferences.userRoot().absolutePath()); safeLoadFileChooser.setFileFilter(new FileNameExtensionFilter("Holeg json files", "json")); safeLoadFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); safeLoadFileChooser.setAcceptAllFileFilterUsed(false); return safeLoadFileChooser; } private void initWindowMenu() { menuBar.add(menuWindow); // Algo JMenuItem openMenu = new JMenuItem("Open Algorithm Panel", new ImageIcon(Import .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH))); openMenu.addActionListener(actionEvent -> { new AddOnWindow(holegJFrame, control); }); openMenu.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); menuWindow.add(openMenu); // Outliner JMenuItem openOutliner = new JMenuItem("Open Outliner", new ImageIcon(Import .loadImage(ImagePreference.Button.Menu.Outliner).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH))); openOutliner.addActionListener(actionEvent -> { new Outliner(holegJFrame, model, control); }); openOutliner .setAccelerator(KeyStroke.getKeyStroke('O', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); menuWindow.add(openOutliner); // FlexWindow JMenuItem openFlexMenuItem = new JMenuItem("Open Flexibility Panel", new ImageIcon(Import .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH))); openFlexMenuItem.addActionListener(actionEvent -> { new FlexWindow(holegJFrame, control); }); openFlexMenuItem .setAccelerator(KeyStroke.getKeyStroke('L', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); menuWindow.add(openFlexMenuItem); } /** * reloads the Categories from Model. * * @param categories the current categories */ private void updateCategories(Collection categories) { DefaultTreeModel treemodel = new DefaultTreeModel(new DefaultMutableTreeNode("Categories") { private static final long serialVersionUID = 1L; { DefaultMutableTreeNode node1; for (Category c : categories) { node1 = new DefaultMutableTreeNode(c.getName()); for (AbstractCanvasObject obj : c.getObjects()) { node1.add(new DefaultMutableTreeNode(obj.getName())); } add(node1); } } }); categoryTree.setModel(treemodel); } /** * When changes are made to the Categories. * * @param categories the Categories */ public void updateCategoryUI(Collection categories) { DefaultTreeModel model = (DefaultTreeModel) categoryTree.getModel(); updateCategories(categories); model.reload(); } void setVisible(boolean value) { holegJFrame.setVisible(value); } /* * Open a new Tab with an UpperNodeCanvas */ public void openNewUpperNodeTab(GroupNode node) { chooseTabTemp(); JScrollPane scrollPane = getScrollPaneFromTabbedPane(); if (scrollPane.getViewport().getComponent(0)instanceof Canvas canvasPanel) { unc = new Canvas(control, node); } // check if tab already open for clicked NodeOfNode boolean dupl = false; for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) { JScrollPane paneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i); if (paneOriginal != null && ((Canvas) paneOriginal.getViewport().getComponent(0)).getGroupNode() .getId() == node.getId()) { dupl = true; // set selected component to view tabbedPaneOriginal.setSelectedComponent(tabbedPaneInnerOriginal); // set selected tab in view to found upper-node-canvas tabbedPaneInnerOriginal.setSelectedComponent(tabbedPaneInnerOriginal.getComponentAt(i)); } // if we found a duplicate, break if (dupl) { break; } } if (!dupl) { JScrollPane sp = new JScrollPane(unc); sp.setBorder(null); // Selected tabbed Pane = tabbedPaneOriginal or tabbedPaneSplit if (tabTemp == tabbedPaneOriginal) { this.tabbedPaneInnerOriginal.add(node.getName(), sp); this.tabbedPaneInnerOriginal.setSelectedComponent(sp); this.tabbedPaneInnerOriginal.setTabComponentAt(this.tabbedPaneInnerOriginal.getTabCount() - 1, new ButtonTabComponent(this.tabbedPaneInnerOriginal)); } } } /** * Removes UpperNodeTab if UpperNode was deleted * * @param cps the CPS object that is currently selected */ private void removeUpperNodeTab(AbstractCanvasObject cps) { if (cps instanceof GroupNode) { for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) { JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i); if (scrollPaneOriginal == null) { } else if (((Canvas) scrollPaneOriginal.getViewport().getComponent(0)).getGroupNode() .getId() == cps.getId()) { ((ButtonTabComponent) tabbedPaneInnerOriginal.getTabComponentAt(i)).removeTabs(); break; } } } } /** * chooses whether to set the tabTemp to tabbedPaneOriginal or tabbedPaneSplit */ private void chooseTabTemp() { // TODO(Tom2021-12-1) Remove tabTabbed tabTemp = tabbedPaneOriginal; } private JScrollPane getScrollPaneFromTabbedPane() { return getScrollPaneFromTabbedPane(-1); } private JScrollPane getScrollPaneFromTabbedPane(int index) { Component upperLevelSelectedComponent; if (tabTemp == null) { return null; } if (index == -1) { upperLevelSelectedComponent = tabTemp.getSelectedComponent(); } else { upperLevelSelectedComponent = tabTemp.getComponentAt(index); } if (upperLevelSelectedComponent instanceof JTabbedPane) { Component nextLevel = ((JTabbedPane) upperLevelSelectedComponent).getSelectedComponent(); if (nextLevel instanceof JPanel panel) return (JScrollPane) panel.getComponent(0); else return (JScrollPane) nextLevel; } else if (upperLevelSelectedComponent instanceof JScrollPane scrollPane) { return scrollPane; } else { return null; } } private void openWebpage(String URL) { try { java.awt.Desktop.getDesktop().browse(new URI(URL)); } catch (Exception e) { e.printStackTrace(); } } /** * closes all UpperNodeTabs, that don't have a valid UpperNode (e.g. if it was * ungrouped/deleted/replaced and so on) */ private void closeInvalidUpperNodeTabs() { /** * close bugged Tabs */ for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) { JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i); if (((Canvas) scrollPaneOriginal.getViewport().getComponent(0)).getGroupNode() == null) { ((ButtonTabComponent) tabbedPaneInnerOriginal.getTabComponentAt(i)).removeTabs(); break; } } } public void repaintCanvas() { log.info("repaintCanvas"); tabbedPaneInnerOriginal.revalidate(); tabbedPaneInnerOriginal.repaint(); for (int i = 1; i < tabbedPaneInnerOriginal.getTabCount(); i++) { JScrollPane scrollPaneOriginal = (JScrollPane) tabbedPaneInnerOriginal.getComponentAt(i); scrollPaneOriginal.revalidate(); } } }