Gui.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. package holeg.ui.view.main;
  2. import holeg.model.*;
  3. import holeg.preferences.ImagePreference;
  4. import holeg.preferences.PreferenceKeys;
  5. import holeg.ui.controller.Control;
  6. import holeg.ui.model.GuiSettings;
  7. import holeg.ui.view.canvas.Canvas;
  8. import holeg.ui.view.canvas.CanvasCollectionPanel;
  9. import holeg.ui.view.category.CategoryPanel;
  10. import holeg.ui.view.dialog.*;
  11. import holeg.ui.view.image.Import;
  12. import holeg.ui.view.information.HolonInformationPanel;
  13. import holeg.ui.view.inspector.Inspector;
  14. import holeg.ui.view.window.AddOnWindow;
  15. import holeg.ui.view.window.FlexWindow;
  16. import holeg.ui.view.window.Outliner;
  17. import holeg.utility.listener.WindowClosingListener;
  18. import javax.swing.*;
  19. import javax.swing.filechooser.FileNameExtensionFilter;
  20. import javax.swing.filechooser.FileSystemView;
  21. import java.awt.*;
  22. import java.awt.event.*;
  23. import java.io.File;
  24. import java.net.URI;
  25. import java.util.logging.Logger;
  26. import java.util.prefs.Preferences;
  27. public class Gui extends JFrame{
  28. private static final Logger log = Logger.getLogger(Model.class.getName());
  29. private static final Preferences prefs = Preferences.userNodeForPackage(Gui.class);
  30. private final Control control;
  31. private final CategoryPanel categoryPanel;
  32. private final CanvasCollectionPanel canvasCollection;
  33. private final Inspector inspector;
  34. private final HolonInformationPanel informationPanel;
  35. private final TimePanel timePanel;
  36. /**
  37. * Create the application.
  38. * @param control the Controller
  39. */
  40. public Gui(Control control) {
  41. super("HOLEG Simulator");
  42. this.control = control;
  43. this.informationPanel = new HolonInformationPanel(control);
  44. this.inspector = new Inspector(control);
  45. this.categoryPanel = new CategoryPanel(control, this);
  46. this.canvasCollection = new CanvasCollectionPanel(control);
  47. this.timePanel = new TimePanel(control);
  48. init();
  49. }
  50. private void init() {
  51. initFrame();
  52. initLayout();
  53. }
  54. private void initFrame() {
  55. this.setIconImage(Import.loadImage(ImagePreference.Logo, 30, 30));
  56. this.setBounds(new Rectangle(prefs.getInt(PreferenceKeys.Gui.Width, 1200), prefs.getInt(PreferenceKeys.Gui.Height, 800)));
  57. if(prefs.get(PreferenceKeys.Gui.Width, null) != null){
  58. this.setLocation(prefs.getInt(PreferenceKeys.Gui.XPos, 1200), prefs.getInt(PreferenceKeys.Gui.YPos, 800));
  59. }else{
  60. this.setLocationRelativeTo(null);
  61. }
  62. this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  63. this.addWindowListener((WindowClosingListener) e -> {
  64. Rectangle bounds = this.getBounds();
  65. prefs.putInt(PreferenceKeys.Gui.XPos, bounds.x);
  66. prefs.putInt(PreferenceKeys.Gui.YPos, bounds.y);
  67. prefs.putInt(PreferenceKeys.Gui.Width, bounds.width);
  68. prefs.putInt(PreferenceKeys.Gui.Height, bounds.height);
  69. if (JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?", "HOLEG",
  70. JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
  71. System.exit(0);
  72. }
  73. });
  74. }
  75. private void initLayout() {
  76. final JSplitPane categorySplit = new JSplitPane();
  77. final JSplitPane canvasSplit = new JSplitPane();
  78. final JSplitPane elementSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
  79. final JScrollPane informationPanelScrollPane = new JScrollPane();
  80. this.setJMenuBar(new GuiMenuBar());
  81. this.getContentPane().setLayout(new BorderLayout(0, 0));
  82. this.getContentPane().add(categorySplit);
  83. categorySplit.setLeftComponent(categoryPanel);
  84. categorySplit.setRightComponent(canvasSplit);
  85. categorySplit.setDividerLocation(200);
  86. categorySplit.setBorder(null);
  87. canvasSplit.setMinimumSize(new Dimension(0, 25));
  88. canvasSplit.setDividerLocation(500);
  89. canvasSplit.setLeftComponent(canvasCollection);
  90. canvasSplit.setRightComponent(elementSplit);
  91. canvasSplit.setResizeWeight(0.9);
  92. canvasSplit.setBorder(null);
  93. elementSplit.setDividerLocation(700);
  94. elementSplit.setTopComponent(inspector);
  95. elementSplit.setBottomComponent(informationPanelScrollPane);
  96. elementSplit.setBorder(null);
  97. informationPanelScrollPane.setViewportView(this.informationPanel);
  98. informationPanelScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  99. informationPanelScrollPane.getVerticalScrollBar().setUnitIncrement(16);
  100. informationPanelScrollPane.setBorder(null);
  101. this.getContentPane().add(timePanel, BorderLayout.SOUTH);
  102. }
  103. public Canvas getActualCanvas() {
  104. return this.canvasCollection.getActualCanvas();
  105. }
  106. private class GuiMenuBar extends JMenuBar {
  107. //Menus
  108. private final JMenu fileMenu = new JMenu("File");
  109. private final JMenu editMenu = new JMenu("Edit");
  110. private final JMenu viewMenu = new JMenu("View");
  111. private final JMenu windowMenu = new JMenu("Window");
  112. private final JMenu helpMenu = new JMenu("Help");
  113. // FileMenu
  114. private final JMenuItem newMenuButton = new JMenuItem("New");
  115. private final JMenuItem openMenuButton = new JMenuItem("Open..");
  116. private final JMenuItem saveMenuButton = new JMenuItem("Save");
  117. private final JMenuItem saveAsMenuButton = new JMenuItem("Save..");
  118. // EditMenu
  119. private final JMenuItem undoButton = new JMenuItem("Undo");
  120. private final JMenuItem redoButton = new JMenuItem("Redo");
  121. private final JMenuItem copyButton = new JMenuItem("Copy");
  122. private final JMenuItem pasteButton = new JMenuItem("Paste");
  123. private final JMenuItem cutButton = new JMenuItem("Cut");
  124. private final JMenu selectionMenu = new JMenu("Selection");
  125. private final JMenuItem selectAllButton = new JMenuItem("All");
  126. private final JMenuItem clearSelectionButton = new JMenuItem("Clear");
  127. private final JMenuItem invertSelectionButton = new JMenuItem("Invert");
  128. private final JMenuItem edgePropertiesButton = new JMenuItem("Edge Properties");
  129. private final JMenuItem alignAllButton = new JMenuItem("Align All");
  130. private final JMenu resetMenu = new JMenu("Reset");
  131. private final JMenuItem resetCategoryButton = new JMenuItem("Categories");
  132. //HelpMenu
  133. private final JMenuItem introductionButton = new JMenuItem("Introduction");
  134. private final JMenuItem userManualButton = new JMenuItem("User Manual");
  135. private final JMenuItem algorithmHelpButton = new JMenuItem("Algorithm Introduction");
  136. private final JMenuItem codeDocumentationButton = new JMenuItem("Code Documentation");
  137. private final JMenuItem aboutUsButton = new JMenuItem("About Us");
  138. //ViewMenu
  139. private final JMenu appearanceMenu = new JMenu("Appearance");
  140. private final JMenuItem canvasSizeButton = new JMenuItem("Set View Size");
  141. private final JCheckBoxMenuItem showSupplyBarsCheckBox = new JCheckBoxMenuItem("Show supply bars.", true);
  142. private final JFileChooser fileChooser = initFileChooser();
  143. private final int IconSize = 15;
  144. //WindowMenu
  145. JMenuItem algorithmButton = new JMenuItem("Algorithm Panel", new ImageIcon(Import
  146. .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(IconSize, IconSize, java.awt.Image.SCALE_SMOOTH)));
  147. JMenuItem outlinerButton = new JMenuItem("Outliner", new ImageIcon(Import
  148. .loadImage(ImagePreference.Button.Menu.Outliner).getScaledInstance(IconSize, IconSize, java.awt.Image.SCALE_SMOOTH)));
  149. JMenuItem flexMenuButton = new JMenuItem("Flexibility Panel", new ImageIcon(Import
  150. .loadImage(ImagePreference.Button.Menu.Algo).getScaledInstance(IconSize, IconSize, java.awt.Image.SCALE_SMOOTH)));
  151. GuiMenuBar() {
  152. initMenuLayout();
  153. initButtonActions();
  154. initButtonShortCuts();
  155. }
  156. private static JFileChooser initFileChooser() {
  157. JFileChooser safeLoadFileChooser = new JFileChooser(prefs.get(PreferenceKeys.Gui.DefaultFolder,
  158. FileSystemView.getFileSystemView().getDefaultDirectory().getPath()));
  159. safeLoadFileChooser.setFileFilter(new FileNameExtensionFilter("Holeg json files", "json"));
  160. safeLoadFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  161. safeLoadFileChooser.setAcceptAllFileFilterUsed(false);
  162. return safeLoadFileChooser;
  163. }
  164. private void initMenuLayout() {
  165. add(fileMenu);
  166. add(editMenu);
  167. add(viewMenu);
  168. add(windowMenu);
  169. add(helpMenu);
  170. fileMenu.add(newMenuButton);
  171. fileMenu.add(openMenuButton);
  172. fileMenu.addSeparator();
  173. fileMenu.add(saveMenuButton);
  174. fileMenu.add(saveAsMenuButton);
  175. editMenu.add(undoButton);
  176. editMenu.add(redoButton);
  177. editMenu.addSeparator();
  178. editMenu.add(copyButton);
  179. editMenu.add(pasteButton);
  180. editMenu.add(cutButton);
  181. editMenu.addSeparator();
  182. editMenu.add(selectionMenu);
  183. selectionMenu.add(selectAllButton);
  184. selectionMenu.add(clearSelectionButton);
  185. selectionMenu.add(invertSelectionButton);
  186. editMenu.addSeparator();
  187. editMenu.add(edgePropertiesButton);
  188. editMenu.add(alignAllButton);
  189. editMenu.add(resetMenu);
  190. resetMenu.add(resetCategoryButton);
  191. helpMenu.add(introductionButton);
  192. helpMenu.add(userManualButton);
  193. helpMenu.add(algorithmHelpButton);
  194. helpMenu.add(codeDocumentationButton);
  195. helpMenu.add(aboutUsButton);
  196. viewMenu.add(appearanceMenu);
  197. appearanceMenu.add(showSupplyBarsCheckBox);
  198. viewMenu.add(canvasSizeButton);
  199. windowMenu.add(algorithmButton);
  200. windowMenu.add(outlinerButton);
  201. windowMenu.add(flexMenuButton);
  202. }
  203. private void initButtonActions() {
  204. newMenuButton.addActionListener(clicked -> newFile());
  205. openMenuButton.addActionListener(clicked -> openFile());
  206. saveMenuButton.addActionListener(clicked -> saveFile());
  207. saveAsMenuButton.addActionListener(clicked -> saveNewFile());
  208. edgePropertiesButton.addActionListener(actionEvent -> new EditEdgesPopUp(Gui.this, control));
  209. alignAllButton.addActionListener(clicked -> {
  210. //TODO(Tom2022-01-14): recreateTryToAlignObjects
  211. log.info("Not implemented yet.");
  212. });
  213. resetCategoryButton.addActionListener(clicked -> control.resetCategories());
  214. showSupplyBarsCheckBox.addActionListener(clicked -> toggleSupplyBarAppearance());
  215. canvasSizeButton.addActionListener(clicked -> new CanvasResizePopUp(control, Gui.this));
  216. algorithmButton.addActionListener(clicked -> new AddOnWindow(Gui.this, control));
  217. outlinerButton.addActionListener(clicked -> new Outliner(Gui.this, control));
  218. flexMenuButton.addActionListener(clicked -> new FlexWindow(Gui.this, control));
  219. String tkWikiWebpage = "https://git.tk.informatik.tu-darmstadt.de/carlos.garcia/praktikum-holons/wiki/";
  220. introductionButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Introduction+V2.1"));
  221. userManualButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "User+Manual+V2.1"));
  222. algorithmHelpButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Algorithms+V2.1"));
  223. codeDocumentationButton.addActionListener(clicked -> openWebpage(tkWikiWebpage + "Code+documentation+V2.1"));
  224. aboutUsButton.addActionListener(clicked -> new AboutUsPopUp(Gui.this));
  225. }
  226. private void openWebpage(String URL) {
  227. try {
  228. java.awt.Desktop.getDesktop().browse(new URI(URL));
  229. } catch (Exception e) {
  230. e.printStackTrace();
  231. }
  232. }
  233. private void initButtonShortCuts() {
  234. int defaultModifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();
  235. saveMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier));
  236. saveAsMenuButton.setAccelerator(KeyStroke.getKeyStroke('S', defaultModifier + InputEvent.SHIFT_DOWN_MASK));
  237. openMenuButton.setAccelerator(KeyStroke.getKeyStroke('O', defaultModifier));
  238. newMenuButton.setAccelerator(KeyStroke.getKeyStroke('N', defaultModifier));
  239. undoButton.setAccelerator(KeyStroke.getKeyStroke('Z', defaultModifier));
  240. redoButton.setAccelerator(KeyStroke.getKeyStroke('Y', defaultModifier));
  241. copyButton.setAccelerator(KeyStroke.getKeyStroke('C', defaultModifier));
  242. pasteButton.setAccelerator(KeyStroke.getKeyStroke('V', defaultModifier));
  243. cutButton.setAccelerator(KeyStroke.getKeyStroke('X', defaultModifier));
  244. selectAllButton.setAccelerator(KeyStroke.getKeyStroke('A', defaultModifier));
  245. clearSelectionButton.setAccelerator(KeyStroke.getKeyStroke('A', defaultModifier + InputEvent.SHIFT_DOWN_MASK));
  246. invertSelectionButton.setAccelerator(KeyStroke.getKeyStroke('I', defaultModifier));
  247. }
  248. private void toggleSupplyBarAppearance() {
  249. GuiSettings.showSupplyBars = showSupplyBarsCheckBox.isSelected();
  250. log.info("canvas.repaint4");
  251. }
  252. private void saveFile(){
  253. GuiSettings.getActualSaveFile().ifPresentOrElse(control::saveFile, this::saveNewFile);
  254. }
  255. private void saveNewFile() {
  256. if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
  257. String path = fileChooser.getSelectedFile().getPath();
  258. if (!path.endsWith(".json")) {
  259. path += ".json";
  260. }
  261. prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath());
  262. control.saveFile(new File(path));
  263. }
  264. }
  265. private void openFile() {
  266. if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
  267. prefs.put(PreferenceKeys.Gui.DefaultFolder, fileChooser.getCurrentDirectory().getPath());
  268. control.loadFile(fileChooser.getSelectedFile());
  269. //TODO(Tom2022-01-27): make better
  270. }
  271. }
  272. private void newFile() {
  273. if (control.getModel().getCanvas().getObjectsInThisLayer().findAny().isPresent()) {
  274. int selectedOption = JOptionPane.showConfirmDialog(this, "Do you want to save your current model?",
  275. "Warning", JOptionPane.YES_NO_OPTION);
  276. if (selectedOption == JOptionPane.YES_OPTION) {
  277. saveNewFile();
  278. }
  279. }
  280. control.clearModel();
  281. }
  282. }
  283. }