CategoryPanel.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. package holeg.ui.view.category;
  2. import holeg.model.AbstractCanvasObject;
  3. import holeg.model.HolonObject;
  4. import holeg.model.HolonSwitch;
  5. import holeg.preferences.ColorPreference;
  6. import holeg.preferences.ImagePreference;
  7. import holeg.ui.controller.Control;
  8. import holeg.ui.model.GuiSettings;
  9. import holeg.ui.view.canvas.Canvas;
  10. import holeg.ui.view.dialog.CreateNewDialog;
  11. import holeg.ui.view.image.Import;
  12. import holeg.ui.view.main.Gui;
  13. import javax.swing.*;
  14. import javax.swing.tree.DefaultMutableTreeNode;
  15. import javax.swing.tree.DefaultTreeModel;
  16. import javax.swing.tree.TreeCellRenderer;
  17. import javax.swing.tree.TreePath;
  18. import java.awt.*;
  19. import java.awt.event.MouseAdapter;
  20. import java.awt.event.MouseEvent;
  21. import java.awt.event.MouseMotionAdapter;
  22. import java.util.Collection;
  23. import java.util.Objects;
  24. import java.util.Optional;
  25. import java.util.logging.Logger;
  26. public class CategoryPanel extends JScrollPane {
  27. private static final Logger log = Logger.getLogger(CategoryPanel.class.getName());
  28. private final Control control;
  29. private final Gui gui;
  30. private final JPanel buttonPanel = new JPanel();
  31. // Buttons
  32. private final JPopupMenu btnAddPopUp = new JPopupMenu("New");
  33. private final JButton btnAdd = new JButton(new ImageIcon(Import.loadImage(ImagePreference.Category.Add, 16, 16)));
  34. private final JButton btnDel = new JButton(new ImageIcon(Import.loadImage(ImagePreference.Category.Delete, 16, 16)));
  35. private final JToolBar toolBar = new JToolBar();
  36. private final JMenuItem mItemNew = new JMenuItem("New..");
  37. private final JMenuItem mItemCategory = new JMenuItem("Category");
  38. private final JMenuItem mItemObject = new JMenuItem("Object");
  39. private final JMenuItem mItemSwitch = new JMenuItem("Switch");
  40. private final JTree categoryTree = new JTree();
  41. private final String eraseCategoryMessage = "Do you really want to delete the Category ";
  42. private final String incorrectDeleteMessage = "Please select a Category or an Object in the left library in order to delete something.";
  43. private boolean dragging = false;
  44. public CategoryPanel(Control control, Gui gui) {
  45. this.control = control;
  46. this.gui = gui;
  47. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
  48. init();
  49. setColumnHeaderView(buttonPanel);
  50. setViewportView(categoryTree);
  51. this.setMinimumSize(new Dimension(200, 200));
  52. updateCategories(GuiSettings.getCategories());
  53. control.OnCategoryChanged.addListener(() -> this.updateCategoryUI(GuiSettings.getCategories()));
  54. }
  55. private void init() {
  56. toolBar.setAlignmentX(Component.LEFT_ALIGNMENT);
  57. toolBar.setFloatable(false);
  58. btnAddPopUp.add(mItemNew);
  59. mItemNew.addActionListener(actionEvent -> new CreateNewDialog(control, gui));
  60. btnAddPopUp.addSeparator();
  61. btnAddPopUp.add(mItemCategory);
  62. mItemCategory.addActionListener(actionEvent -> new CreateNewDialog(control, CreateNewDialog.Option.Category, gui));
  63. btnAddPopUp.add(mItemObject);
  64. mItemObject.addActionListener(actionEvent -> new CreateNewDialog(control, CreateNewDialog.Option.Object, gui));
  65. btnAddPopUp.add(mItemSwitch);
  66. mItemSwitch.addActionListener(actionEvent -> new CreateNewDialog(control, CreateNewDialog.Option.Switch, gui));
  67. btnAdd.addActionListener(actionEvent -> btnAddPopUp.show(btnAdd, -1, +20));
  68. btnAdd.setToolTipText("<html><b>New</b><br>Add a new Category or Item to the library.</html>");
  69. toolBar.add(btnAdd);
  70. // Del Button
  71. btnDel.addActionListener(actionEvent -> {
  72. Optional<DefaultMutableTreeNode> nodeInfo = Optional.ofNullable((DefaultMutableTreeNode) categoryTree.getLastSelectedPathComponent());
  73. nodeInfo.ifPresentOrElse(selectedNode -> {
  74. String nodeName = selectedNode.getUserObject().toString();
  75. int depthOfNode = selectedNode.getLevel();
  76. try {
  77. switch (depthOfNode) {
  78. case 1 -> {
  79. int dialogResult = JOptionPane.showConfirmDialog(gui, eraseCategoryMessage + nodeName + "?",
  80. "Warning", JOptionPane.YES_NO_OPTION);
  81. if (dialogResult == JOptionPane.YES_OPTION) {
  82. GuiSettings.getCategories().stream().filter(cat -> Objects.equals(cat.getName(), nodeName)).findAny()
  83. .ifPresent(control::deleteCategory);
  84. }
  85. }
  86. case 2 -> {
  87. DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
  88. control.findCategoryWithName(parent.getUserObject().toString()).ifPresent(cat -> {
  89. cat.removeObjectsWithName(nodeName);
  90. });
  91. }
  92. default -> JOptionPane.showMessageDialog(gui, incorrectDeleteMessage);
  93. }
  94. } catch (Exception ignored) {
  95. }
  96. categoryTree.repaint();
  97. }, () -> JOptionPane.showMessageDialog(gui, incorrectDeleteMessage));
  98. });
  99. btnDel.setToolTipText("<html><b>Delete</b><br>Removes a Category or a Category Item.</html>");
  100. toolBar.add(btnDel);
  101. buttonPanel.add(toolBar);
  102. categoryTree.setCellRenderer(new CategoryTreeRenderer());
  103. categoryTree.addMouseListener(new MouseAdapter() {
  104. public void mousePressed(MouseEvent e) {
  105. AbstractCanvasObject tempCps = null;
  106. TreePath path = categoryTree
  107. .getPathForLocation(e.getX(), e.getY());
  108. if(path == null){
  109. log.info("Path is null");
  110. return;
  111. }
  112. DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)path.getLastPathComponent();
  113. String clickedObjectName = selectedNode.toString();
  114. // if an Object was selected, the porperties are shown in
  115. // the table
  116. if (SwingUtilities.isRightMouseButton(e)) {
  117. for (Category cat : GuiSettings.getCategories()) {
  118. for (AbstractCanvasObject cps : cat.getObjects()) {
  119. if (clickedObjectName.equals(cps.getName())
  120. && !(cps instanceof HolonSwitch)) {
  121. // editItem.setEnabled(true);
  122. // popmenuEdit.show(e.getComponent(), e.getX(), e.getY());
  123. // catOfObjToBeEdited = selectedNode.getParent().toString();
  124. tempCps = cps;
  125. }
  126. }
  127. }
  128. } else {
  129. for (Category cat : GuiSettings.getCategories()) {
  130. for (AbstractCanvasObject cps : cat.getObjects()) {
  131. if (clickedObjectName.equals(cps.getName())) {
  132. Image img = Import.loadImage(cps.getImagePath(), 32, 32);
  133. tempCps = cps;
  134. dragging = true;
  135. Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(img, new Point(),
  136. "Image");
  137. gui.setCursor(cursor);
  138. }
  139. }
  140. }
  141. }
  142. if (dragging) {
  143. Canvas groupNodeCanvas = gui.getCanvas();
  144. Optional<Point> positionInCanvas = Optional.ofNullable(groupNodeCanvas.getMousePosition());
  145. AbstractCanvasObject finalTempCps = tempCps;
  146. positionInCanvas.ifPresent(pos -> {
  147. AbstractCanvasObject h = null;
  148. if (finalTempCps instanceof HolonObject hO) {
  149. h = new HolonObject(hO);
  150. }
  151. else if (finalTempCps instanceof HolonSwitch sw) {
  152. h = new HolonSwitch(sw);
  153. }
  154. h.setPosition(pos.x, pos.y);
  155. control.addObjectOnCanvas(control.getModel().getCanvas(), h);
  156. control.calculateStateAndVisualForCurrentTimeStep();
  157. });
  158. }
  159. gui.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  160. }
  161. });
  162. categoryTree.addMouseMotionListener(new MouseMotionAdapter() {
  163. public void mouseDragged(MouseEvent e) {
  164. checkForDragAndDrop();
  165. }
  166. /**
  167. * checks if an object of the current Panel could be replaced by the dragged
  168. * object
  169. */
  170. private void checkForDragAndDrop() {
  171. try {
  172. /**
  173. * if no object gets dragged -> finished
  174. */
  175. if (!dragging)
  176. return;
  177. Canvas groupNodeCanvas = gui.getCanvas();
  178. /**
  179. * check for replacements on the canvas
  180. */
  181. if (groupNodeCanvas.getMousePosition() == null)
  182. return;
  183. int x = (int) groupNodeCanvas.getMousePosition().getX() + 16;
  184. int y = (int) groupNodeCanvas.getMousePosition().getY() + 16;
  185. /**
  186. * check for replacement
  187. */
  188. groupNodeCanvas.checkForReplacement(x, y);
  189. } catch (Exception ignored) {
  190. }
  191. }
  192. });
  193. }
  194. /**
  195. * reloads the Categories from Model.
  196. *
  197. * @param categories the current categories
  198. */
  199. private void updateCategories(Collection<Category> categories) {
  200. DefaultTreeModel treemodel = new DefaultTreeModel(new DefaultMutableTreeNode("Categories") {
  201. {
  202. DefaultMutableTreeNode node1;
  203. for (Category c : categories) {
  204. node1 = new DefaultMutableTreeNode(c.getName());
  205. for (AbstractCanvasObject obj : c.getObjects()) {
  206. node1.add(new DefaultMutableTreeNode(obj.getName()));
  207. }
  208. add(node1);
  209. }
  210. }
  211. });
  212. categoryTree.setModel(treemodel);
  213. }
  214. /**
  215. * When changes are made to the Categories.
  216. *
  217. * @param categories the Categories
  218. */
  219. public void updateCategoryUI(Collection<Category> categories) {
  220. DefaultTreeModel model = (DefaultTreeModel) categoryTree.getModel();
  221. updateCategories(categories);
  222. model.reload();
  223. }
  224. private static class CategoryTreeRenderer implements TreeCellRenderer {
  225. @Override
  226. public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
  227. boolean leaf, int row, boolean hasFocus) {
  228. JLabel label = new JLabel();
  229. Image imgR;
  230. if (leaf) {
  231. for (Category cat : GuiSettings.getCategories()) {
  232. for (AbstractCanvasObject cps : cat.getObjects()) {
  233. if (value.toString().equals(cps.getName())) {
  234. imgR = Import.loadImage(cps.getImagePath(), 50, 50);
  235. if (imgR != null) {
  236. label.setIcon(new ImageIcon(imgR));
  237. }
  238. label.setText(cps.getName());
  239. }
  240. }
  241. }
  242. }
  243. tree.setRowHeight(50);
  244. if (hasFocus) {
  245. label.setForeground(ColorPreference.Category.Focus);
  246. label.setOpaque(true);
  247. }
  248. if (label.getText().isEmpty()) {
  249. label.setText(value.toString());
  250. if (!value.toString().equals("Categories")) {
  251. label.setIcon(new ImageIcon(Import.loadImage(ImagePreference.Category.Folder)));
  252. }
  253. }
  254. return label;
  255. }
  256. }
  257. }