package holeg.ui.view.main; import holeg.interfaces.LocalMode; import holeg.model.*; import holeg.preferences.ColorPreference; import holeg.preferences.ImagePreference; import holeg.preferences.PreferenceKeys; import holeg.ui.controller.Control; import holeg.ui.model.GuiSettings; import holeg.ui.view.canvas.Canvas; import holeg.ui.view.category.Category; import holeg.ui.view.component.ButtonTabComponent; import holeg.ui.view.dialog.*; import holeg.ui.view.dialog.CreateNewDialog.Option; import holeg.ui.view.image.Import; 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 javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileSystemView; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeCellRenderer; import java.awt.*; import java.awt.event.*; import java.io.File; import java.net.URI; import java.util.Collection; import java.util.logging.Logger; import java.util.prefs.Preferences; /** * Graphical User Interface. * * @author Gruppe14 */ public class Gui { private static final Logger log = Logger.getLogger(Model.class.getName()); private static final Preferences prefs = Preferences.userNodeForPackage(Gui.class); private final JSplitPane splitPane = new JSplitPane(); private final JSplitPane splitPane1 = new JSplitPane(); private final JPanel myPanel = new JPanel(new BorderLayout()); // the tabbed canvas containing the different sub-net tabs of the grid (Main // Grid + Nodes of Nodes) 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 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); private final JScrollPane scrollProperties = new JScrollPane(); // In this section is the graph for the selected HolonElement of the clicked 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 JButton btnAdd = new JButton(); // Buttons private final JPopupMenu btnAddPopUp = new JPopupMenu("New"); 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(); private final UnitGraph unitGraph; /** * Textfield to show the period of an element */ private final JTextField unitGraphLocalPeriod = new JTextField(6); // Save / Load // Languages private Canvas canvas; // 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; private AbstractCanvasObject temp = null; 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"); /** * Create the application. * * @param control the Controller */ public Gui(Control control) { this.control = control; this.informationPanel = new HolonInformationPanel(control); inspector = new Inspector(control); control.calculateStateAndVisualForCurrentTimeStep(); this.unitGraph = new UnitGraph(control); this.canvas = new Canvas(control, control.getModel().getCanvas()); initialize(); updateCategories(GuiSettings.getCategories()); control.OnCategoryChanged.addListener(() -> this.updateCategoryUI(GuiSettings.getCategories())); this.unc = this.canvas; } public TimePanel getTimePanel() { return timePanel; } /** * 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(new GuiMenuBar()); holegJFrame.setIconImage(Import.loadImage(ImagePreference.Logo, 30, 30)); tabbedPaneInnerOriginal.addChangeListener(change -> { control.clearSelection(); }); /** * add Help Menu and its items */ canvas.setBackground(Color.WHITE); canvas.setPreferredSize(new Dimension(GuiSettings.canvasSize.getX(), GuiSettings.canvasSize.getY())); /*********************** * 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(control.getModel().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(control.getModel().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); // 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 + "?", "Warning", 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); 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); canvasSP.setBorder(null); holegJFrame.getContentPane().add(timePanel, BorderLayout.SOUTH); 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(); } }); } /** * reloads the Categories from Model. * * @param categories the current categories */ private void updateCategories(Collection categories) { DefaultTreeModel treemodel = new DefaultTreeModel(new DefaultMutableTreeNode("Categories") { { 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(); } public 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; } } } private class GuiMenuBar extends JMenuBar { //Menus private final JMenu fileMenu = new JMenu("File"); private final JMenu editMenu = new JMenu("Edit"); private final JMenu viewMenu = new JMenu("View"); private final JMenu windowMenu = new JMenu("Window"); private final JMenu helpMenu = new JMenu("Help"); // FileMenu private final JMenuItem newMenuButton = new JMenuItem("New"); private final JMenuItem openMenuButton = new JMenuItem("Open.."); private final JMenuItem saveMenuButton = new JMenuItem("Save"); private final JMenuItem saveAsMenuButton = new JMenuItem("Save.."); // EditMenu private final JMenuItem undoButton = new JMenuItem("Undo"); private final JMenuItem redoButton = new JMenuItem("Redo"); private final JMenuItem edgePropertiesButton = new JMenuItem("Edge Properties"); private final JMenuItem alignAllButton = new JMenuItem("Align All"); private final JMenu resetMenu = new JMenu("Reset"); private final JMenuItem resetCategoryButton = new JMenuItem("Categories"); //HelpMenu private final JMenuItem introductionButton = new JMenuItem("Introduction"); private final JMenuItem userManualButton = new JMenuItem("User Manual"); private final JMenuItem algorithmHelpButton = new JMenuItem("Algorithm Introduction"); private final JMenuItem codeDocumentationButton = new JMenuItem("Code Documentation"); private final JMenuItem aboutUsButton = new JMenuItem("About Us"); //ViewMenu private final JMenu appearanceMenu = new JMenu("Appearance"); private final JMenuItem canvasSizeButton = new JMenuItem("Set View Size"); private final JCheckBoxMenuItem showSupplyBarsCheckBox = new JCheckBoxMenuItem("Show supply bars.", true); private final JFileChooser fileChooser = initFileChooser(); //WindowMenu JMenuItem algorithmButton = new JMenuItem("Algorithm Panel", new ImageIcon(Import .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH))); JMenuItem outlinerButton = new JMenuItem("Outliner", new ImageIcon(Import .loadImage(ImagePreference.Button.Menu.Outliner).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH))); JMenuItem flexMenuButton = new JMenuItem("Flexibility Panel", new ImageIcon(Import .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH))); GuiMenuBar() { initMenuLayout(); initButtonActions(); initButtonShortCuts(); } private static JFileChooser initFileChooser() { JFileChooser safeLoadFileChooser = new JFileChooser(prefs.get(PreferenceKeys.Gui.DefaultFolder, FileSystemView.getFileSystemView().getDefaultDirectory().getPath())); safeLoadFileChooser.setFileFilter(new FileNameExtensionFilter("Holeg json files", "json")); safeLoadFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); safeLoadFileChooser.setAcceptAllFileFilterUsed(false); return safeLoadFileChooser; } private void initMenuLayout() { add(fileMenu); add(editMenu); add(viewMenu); add(windowMenu); add(helpMenu); fileMenu.add(newMenuButton); fileMenu.add(openMenuButton); fileMenu.addSeparator(); fileMenu.add(saveMenuButton); fileMenu.add(saveAsMenuButton); editMenu.add(undoButton); editMenu.add(redoButton); editMenu.add(edgePropertiesButton); editMenu.add(alignAllButton); editMenu.add(resetMenu); resetMenu.add(resetCategoryButton); helpMenu.add(introductionButton); helpMenu.add(userManualButton); helpMenu.add(algorithmHelpButton); helpMenu.add(codeDocumentationButton); helpMenu.add(aboutUsButton); viewMenu.add(appearanceMenu); appearanceMenu.add(showSupplyBarsCheckBox); viewMenu.add(canvasSizeButton); windowMenu.add(algorithmButton); windowMenu.add(outlinerButton); windowMenu.add(flexMenuButton); } private void initButtonActions() { newMenuButton.addActionListener(clicked -> newFile()); openMenuButton.addActionListener(clicked -> openFile()); saveMenuButton.addActionListener(clicked -> saveFile()); saveAsMenuButton.addActionListener(clicked -> saveNewFile()); edgePropertiesButton.addActionListener(actionEvent -> new EditEdgesPopUp(holegJFrame, control)); //TODO(Tom2022-01-14): recreateTryToAlignObjects alignAllButton.addActionListener(clicked -> { log.info("Not implemented yet."); }); resetCategoryButton.addActionListener(clicked -> control.resetCategories()); showSupplyBarsCheckBox.addActionListener(clicked -> toggleSupplyBarAppearance()); canvasSizeButton.addActionListener(clicked -> new CanvasResizePopUp(control, canvas, tabbedPaneInnerOriginal, holegJFrame)); algorithmButton.addActionListener(clicked -> new AddOnWindow(holegJFrame, control)); outlinerButton.addActionListener(clicked -> new Outliner(holegJFrame, control)); flexMenuButton.addActionListener(clicked -> new FlexWindow(holegJFrame, control)); String tkWikiWebpage = "https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons/wiki/"; introductionButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Introduction+V2.1")); userManualButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "User+Manual+V2.1")); algorithmHelpButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Algorithms+V2.1")); codeDocumentationButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Code+documentation+V2.1")); aboutUsButton.addActionListener(clicked -> new AboutUsPopUp(holegJFrame)); } private void initButtonShortCuts() { int defaultModifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); saveMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier)); saveAsMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier + InputEvent.SHIFT_DOWN_MASK)); openMenuButton.setAccelerator(KeyStroke.getKeyStroke('O', defaultModifier)); newMenuButton.setAccelerator(KeyStroke.getKeyStroke('N', defaultModifier)); } private void toggleSupplyBarAppearance() { GuiSettings.showSupplyBars = showSupplyBarsCheckBox.isSelected(); log.info("canvas.repaint4"); canvas.repaint(); } private void saveFile(){ GuiSettings.getActualSaveFile().ifPresentOrElse(control::saveFile, this::saveNewFile); } private void saveNewFile() { if (fileChooser.showSaveDialog(holegJFrame) == JFileChooser.APPROVE_OPTION) { String path = fileChooser.getSelectedFile().getPath(); if (!path.endsWith(".json")) { path += ".json"; } prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath()); control.saveFile(new File(path)); } } private void openFile() { if (fileChooser.showOpenDialog(holegJFrame) == JFileChooser.APPROVE_OPTION) { prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath()); control.loadFile(fileChooser.getSelectedFile()); //TODO(Tom2022-01-27): make better canvas.setGroupNode(control.getModel().getCanvas()); canvas.repaint(); } } private void newFile() { if (control.getModel().getCanvas().getObjectsInThisLayer().findAny().isPresent()) { int selectedOption = JOptionPane.showConfirmDialog(holegJFrame, "Do you want to save your current model?", "Warning", JOptionPane.YES_NO_OPTION); if (selectedOption == JOptionPane.YES_OPTION) { saveNewFile(); } } control.clearModel(); } } }