123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- package holeg.ui.view.main;
- import holeg.model.GroupNode;
- import holeg.model.Model;
- 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.canvas.CanvasCollectionPanel;
- import holeg.ui.view.category.CategoryPanel;
- import holeg.ui.view.dialog.CanvasResizePopUp;
- import holeg.ui.view.dialog.EditEdgesPopUp;
- import holeg.ui.view.image.Import;
- import holeg.ui.view.information.HolonInformationPanel;
- import holeg.ui.view.inspector.Inspector;
- import holeg.ui.view.window.AddOnWindow;
- import holeg.ui.view.window.FlexWindow;
- import holeg.ui.view.window.Outliner;
- import holeg.utility.listener.WindowClosingListener;
- import holeg.utility.math.vector.Vec2i;
- import java.awt.BorderLayout;
- import java.awt.Container;
- import java.awt.Dimension;
- import java.awt.Rectangle;
- import java.awt.Toolkit;
- import java.awt.event.InputEvent;
- import java.awt.event.KeyEvent;
- import java.io.File;
- import java.net.URI;
- import java.util.Optional;
- import java.util.logging.Logger;
- import java.util.prefs.Preferences;
- import java.util.stream.Collectors;
- import javax.swing.ImageIcon;
- import javax.swing.JCheckBoxMenuItem;
- import javax.swing.JFileChooser;
- import javax.swing.JFrame;
- import javax.swing.JMenu;
- import javax.swing.JMenuBar;
- import javax.swing.JMenuItem;
- import javax.swing.JOptionPane;
- import javax.swing.JScrollPane;
- import javax.swing.JSplitPane;
- import javax.swing.KeyStroke;
- import javax.swing.filechooser.FileNameExtensionFilter;
- import javax.swing.filechooser.FileSystemView;
- /**
- * The main frame of this program.
- */
- public class Gui extends JFrame {
- private static final Logger log = Logger.getLogger(Model.class.getName());
- private static final Preferences prefs = Preferences.userNodeForPackage(Gui.class);
- public final CanvasCollectionPanel canvasCollection;
- private final Control control;
- private final CategoryPanel categoryPanel;
- private final Inspector inspector;
- private final HolonInformationPanel informationPanel;
- private final TimePanel timePanel;
- /**
- * Create the application.
- *
- * @param control the Controller
- */
- public Gui(Control control) {
- super("HOLEG Simulator");
- this.control = control;
- this.informationPanel = new HolonInformationPanel(control);
- this.inspector = new Inspector(control);
- this.categoryPanel = new CategoryPanel(control, this);
- this.canvasCollection = new CanvasCollectionPanel(control);
- this.timePanel = new TimePanel(control);
- init();
- }
- /**
- * Initialize the gui.
- */
- private void init() {
- initFrame();
- initLayout();
- }
- private void initFrame() {
- this.setIconImage(Import.loadImage(ImagePreference.Logo, 30, 30));
- this.setBounds(new Rectangle(prefs.getInt(PreferenceKeys.Gui.Width, 1200),
- prefs.getInt(PreferenceKeys.Gui.Height, 800)));
- Appearance.loadPrefs();
- if (prefs.get(PreferenceKeys.Gui.Width, null) != null) {
- this.setLocation(prefs.getInt(PreferenceKeys.Gui.XPos, 1200),
- prefs.getInt(PreferenceKeys.Gui.YPos, 800));
- } else {
- this.setLocationRelativeTo(null);
- }
- this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
- this.addWindowListener((WindowClosingListener) e -> {
- Rectangle bounds = this.getBounds();
- prefs.putInt(PreferenceKeys.Gui.XPos, bounds.x);
- prefs.putInt(PreferenceKeys.Gui.YPos, bounds.y);
- prefs.putInt(PreferenceKeys.Gui.Width, bounds.width);
- prefs.putInt(PreferenceKeys.Gui.Height, bounds.height);
- Appearance.savePrefs();
- control.saveCategories();
- if (JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?", "HOLEG",
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
- System.exit(0);
- }
- });
- }
- private void initLayout() {
- this.setJMenuBar(new GuiMenuBar());
- final JSplitPane categorySplit = new JSplitPane();
- final JSplitPane canvasSplit = new JSplitPane();
- final JSplitPane elementSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
- final JScrollPane informationPanelScrollPane = new JScrollPane();
- Container contentPanel = this.getContentPane();
- contentPanel.setLayout(new BorderLayout(0, 0));
- contentPanel.add(categorySplit);
- categorySplit.setLeftComponent(categoryPanel);
- categorySplit.setRightComponent(canvasSplit);
- categorySplit.setDividerLocation(200);
- categorySplit.setBorder(null);
- canvasSplit.setMinimumSize(new Dimension(0, 25));
- canvasSplit.setDividerLocation(500);
- canvasSplit.setLeftComponent(canvasCollection);
- canvasSplit.setRightComponent(elementSplit);
- canvasSplit.setResizeWeight(0.9);
- canvasSplit.setBorder(null);
- elementSplit.setDividerLocation(700);
- elementSplit.setTopComponent(inspector);
- elementSplit.setBottomComponent(informationPanelScrollPane);
- elementSplit.setBorder(null);
- informationPanelScrollPane.setViewportView(this.informationPanel);
- informationPanelScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- informationPanelScrollPane.getVerticalScrollBar().setUnitIncrement(16);
- informationPanelScrollPane.setBorder(null);
- contentPanel.add(timePanel, BorderLayout.SOUTH);
- }
- public Canvas getActualCanvas() {
- return this.canvasCollection.getActualCanvas();
- }
- /**
- * This class handles all Menu of the gui.
- */
- private class GuiMenuBar extends JMenuBar {
- private final static int IconSize = 15;
- private final static Vec2i DefaultOffset = new Vec2i(20, 20);
- //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 copyButton = new JMenuItem("Copy");
- private final JMenuItem pasteButton = new JMenuItem("Paste");
- private final JMenuItem cutButton = new JMenuItem("Cut");
- private final JMenu selectionMenu = new JMenu("Selection");
- private final JMenuItem selectAllButton = new JMenuItem("All");
- private final JMenuItem clearSelectionButton = new JMenuItem("Clear");
- private final JMenuItem invertSelectionButton = new JMenuItem("Invert");
- private final JMenuItem groupButton = new JMenuItem("Group");
- private final JMenuItem ungroupButton = new JMenuItem("Ungroup");
- private final JMenuItem removeButton = new JMenuItem("Remove");
- 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");
- //ViewMenu
- private final JMenu appearanceMenu = new JMenu("Appearance");
- private final JMenuItem canvasSizeButton = new JMenuItem("Set View Size");
- private final JCheckBoxMenuItem showSupplyBarsCheckBox = new JCheckBoxMenuItem("Supply bars",
- Appearance.supplyBarVisible);
- private final JCheckBoxMenuItem edgeCapacityVisibleCheckBox = new JCheckBoxMenuItem(
- "Edge capacity", Appearance.edgeCapacityVisible);
- private final JCheckBoxMenuItem canvasObjectEnergyVisibleCheckBox = new JCheckBoxMenuItem(
- "HolonObject energy", Appearance.canvasObjectEnergyVisible);
- private final JFileChooser fileChooser = initFileChooser();
- //WindowMenu
- JMenuItem algorithmButton = new JMenuItem("Algorithm Panel", new ImageIcon(Import
- .loadImage(ImagePreference.Button.Menu.Algo)
- .getScaledInstance(IconSize, IconSize, java.awt.Image.SCALE_SMOOTH)));
- JMenuItem outlinerButton = new JMenuItem("Outliner", new ImageIcon(Import
- .loadImage(ImagePreference.Button.Menu.Outliner)
- .getScaledInstance(IconSize, IconSize, java.awt.Image.SCALE_SMOOTH)));
- JMenuItem flexMenuButton = new JMenuItem("Flexibility Panel", new ImageIcon(Import
- .loadImage(ImagePreference.Button.Menu.Algo)
- .getScaledInstance(IconSize, IconSize, 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.addSeparator();
- editMenu.add(copyButton);
- editMenu.add(pasteButton);
- editMenu.add(cutButton);
- editMenu.addSeparator();
- editMenu.add(selectionMenu);
- selectionMenu.add(selectAllButton);
- selectionMenu.add(clearSelectionButton);
- selectionMenu.add(invertSelectionButton);
- editMenu.addSeparator();
- editMenu.add(groupButton);
- editMenu.add(ungroupButton);
- editMenu.addSeparator();
- editMenu.add(removeButton);
- editMenu.addSeparator();
- editMenu.add(edgePropertiesButton);
- editMenu.add(alignAllButton);
- editMenu.add(resetMenu);
- resetMenu.add(resetCategoryButton);
- helpMenu.add(introductionButton);
- helpMenu.add(userManualButton);
- helpMenu.add(algorithmHelpButton);
- helpMenu.add(codeDocumentationButton);
- viewMenu.add(appearanceMenu);
- appearanceMenu.add(showSupplyBarsCheckBox);
- appearanceMenu.add(edgeCapacityVisibleCheckBox);
- appearanceMenu.add(canvasObjectEnergyVisibleCheckBox);
- 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());
- groupButton.addActionListener(clicked -> control.group());
- ungroupButton.addActionListener(clicked -> control.ungroup());
- edgePropertiesButton.addActionListener(actionEvent -> new EditEdgesPopUp(Gui.this, control));
- alignAllButton.addActionListener(clicked -> {
- getActualCanvas().getGroupNode()
- .getObjectsInThisLayer().forEach(obj -> {
- int distance = GuiSettings.getPictureScaleDiv2() * 3;
- Vec2i pos = obj.getPosition();
- // offset relative to a grid with lines every distance pixels
- Vec2i offset = new Vec2i(pos.getX() % distance, pos.getY() % distance);
- //align to the other Line, if it is nearer
- if (offset.getX() > distance / 2) {
- offset.setX(offset.getX() - distance);
- }
- if (offset.getY() > distance / 2) {
- offset.setY(offset.getY() - distance);
- }
- obj.setPosition(obj.getPosition().subtract(offset));
- });
- control.OnCanvasUpdate.broadcast();
- });
- resetCategoryButton.addActionListener(clicked -> control.resetCategories());
- showSupplyBarsCheckBox.addActionListener(clicked -> {
- Appearance.supplyBarVisible = showSupplyBarsCheckBox.isSelected();
- control.OnCanvasUpdate.broadcast();
- });
- edgeCapacityVisibleCheckBox.addActionListener(clicked -> {
- Appearance.edgeCapacityVisible = edgeCapacityVisibleCheckBox.isSelected();
- control.OnCanvasUpdate.broadcast();
- });
- canvasObjectEnergyVisibleCheckBox.addActionListener(clicked -> {
- Appearance.canvasObjectEnergyVisible = canvasObjectEnergyVisibleCheckBox.isSelected();
- control.OnCanvasUpdate.broadcast();
- });
- canvasSizeButton.addActionListener(clicked -> new CanvasResizePopUp(control, Gui.this));
- algorithmButton.addActionListener(clicked -> new AddOnWindow(Gui.this, control));
- outlinerButton.addActionListener(clicked -> new Outliner(Gui.this, control));
- flexMenuButton.addActionListener(clicked -> new FlexWindow(Gui.this, control));
- selectAllButton.addActionListener(clicked -> selectAll());
- clearSelectionButton.addActionListener(clicked -> control.clearSelection());
- invertSelectionButton.addActionListener(clicked -> invertSelection());
- copyButton.addActionListener(clicked -> control.copy());
- cutButton.addActionListener(clicked -> control.cut());
- pasteButton.addActionListener(clicked -> paste());
- undoButton.addActionListener(clicked -> control.undo());
- redoButton.addActionListener(clicked -> control.redo());
- removeButton.addActionListener(clicked -> removeSelectedObjects());
- 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"));
- }
- private void openWebpage(String URL) {
- try {
- java.awt.Desktop.getDesktop().browse(new URI(URL));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * Initialize all shortcuts of the program.
- */
- private void initButtonShortCuts() {
- int defaultModifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();
- int defaultShiftModifier = defaultModifier + InputEvent.SHIFT_DOWN_MASK;
- saveMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier));
- saveAsMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultShiftModifier));
- openMenuButton.setAccelerator(KeyStroke.getKeyStroke('O', defaultModifier));
- newMenuButton.setAccelerator(KeyStroke.getKeyStroke('N', defaultModifier));
- undoButton.setAccelerator(KeyStroke.getKeyStroke('Z', defaultModifier));
- redoButton.setAccelerator(KeyStroke.getKeyStroke('Y', defaultModifier));
- copyButton.setAccelerator(KeyStroke.getKeyStroke('C', defaultModifier));
- pasteButton.setAccelerator(KeyStroke.getKeyStroke('V', defaultModifier));
- cutButton.setAccelerator(KeyStroke.getKeyStroke('X', defaultModifier));
- selectAllButton.setAccelerator(KeyStroke.getKeyStroke('A', defaultModifier));
- clearSelectionButton.setAccelerator(KeyStroke.getKeyStroke('A', defaultShiftModifier));
- invertSelectionButton.setAccelerator(KeyStroke.getKeyStroke('I', defaultModifier));
- groupButton.setAccelerator(KeyStroke.getKeyStroke('G', defaultModifier));
- ungroupButton.setAccelerator(KeyStroke.getKeyStroke('U', defaultModifier));
- alignAllButton.setAccelerator(KeyStroke.getKeyStroke('L', defaultModifier));
- removeButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
- algorithmButton.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.ALT_DOWN_MASK));
- outlinerButton.setAccelerator(KeyStroke.getKeyStroke('O', InputEvent.ALT_DOWN_MASK));
- flexMenuButton.setAccelerator(KeyStroke.getKeyStroke('F', InputEvent.ALT_DOWN_MASK));
- }
- /**
- * Save if save file is selected else open the dialog.
- */
- private void saveFile() {
- GuiSettings.getActualSaveFile().ifPresentOrElse(control::saveFile, this::saveNewFile);
- }
- private void saveNewFile() {
- if (fileChooser.showSaveDialog(Gui.this) == 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(Gui.this) == JFileChooser.APPROVE_OPTION) {
- prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath());
- control.loadFile(fileChooser.getSelectedFile());
- }
- }
- private void newFile() {
- if (control.getModel().getCanvas().getObjectsInThisLayer().findAny().isPresent()) {
- int selectedOption = JOptionPane.showConfirmDialog(Gui.this,
- "Do you want to save your current model?",
- "Warning", JOptionPane.YES_NO_OPTION);
- if (selectedOption == JOptionPane.YES_OPTION) {
- saveNewFile();
- }
- }
- control.clearModel();
- }
- private void selectAll() {
- control.setSelection(getActualCanvas().getGroupNode()
- .getObjectsInThisLayer().collect(Collectors.toSet()));
- }
- private void invertSelection() {
- control.toggleSelectedObjects(getActualCanvas().getGroupNode()
- .getObjectsInThisLayer().collect(Collectors.toSet()));
- }
- private void removeSelectedObjects() {
- control.deleteCanvasObjects(GuiSettings.getSelectedObjects());
- control.clearSelection();
- }
- private void paste() {
- Vec2i middlePosition = GroupNode.calculateMiddlePosition(GuiSettings.getClipboardObjects());
- Optional<Vec2i> offset = Optional.ofNullable(getActualCanvas().getMousePosition())
- .map(point -> new Vec2i(point).subtract(middlePosition));
- control.paste(getActualCanvas().getGroupNode(), offset.orElse(DefaultOffset));
- }
- }
- }
|