CategoryPanel.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 java.awt.*;
  18. import java.awt.event.MouseAdapter;
  19. import java.awt.event.MouseEvent;
  20. import java.util.Collection;
  21. import java.util.Objects;
  22. import java.util.Optional;
  23. import java.util.logging.Logger;
  24. public class CategoryPanel extends JScrollPane {
  25. private static final Logger log = Logger.getLogger(CategoryPanel.class.getName());
  26. private final static int NODE_SIZE = 25;
  27. private final Control control;
  28. private final Gui gui;
  29. private final JPanel buttonPanel = new JPanel();
  30. // Buttons
  31. private final JPopupMenu btnAddPopUp = new JPopupMenu("New");
  32. private final JButton btnAdd = new JButton(new ImageIcon(Import.loadImage(ImagePreference.Category.Add, 16, 16)));
  33. private final JButton btnDel = new JButton(new ImageIcon(Import.loadImage(ImagePreference.Category.Delete, 16, 16)));
  34. private final JToolBar toolBar = new JToolBar();
  35. private final JMenuItem mItemNew = new JMenuItem("New..");
  36. private final JMenuItem mItemCategory = new JMenuItem("Category");
  37. private final JMenuItem mItemObject = new JMenuItem("Object");
  38. private final JMenuItem mItemSwitch = new JMenuItem("Switch");
  39. private final JTree categoryTree = new JTree();
  40. public CategoryPanel(Control control, Gui gui) {
  41. this.control = control;
  42. this.gui = gui;
  43. init();
  44. updateCategories(GuiSettings.getCategories());
  45. control.OnCategoryChanged.addListener(() -> this.updateCategories(GuiSettings.getCategories()));
  46. }
  47. private void init() {
  48. this.setMinimumSize(new Dimension(200, 200));
  49. toolBar.setAlignmentX(Component.LEFT_ALIGNMENT);
  50. toolBar.setFloatable(false);
  51. initLayout();
  52. initButtons();
  53. categoryTree.setCellRenderer(new CategoryTreeRenderer());
  54. categoryTree.setRowHeight(NODE_SIZE);
  55. CategoryMouseListener mouseListener = new CategoryMouseListener();
  56. categoryTree.addMouseListener(mouseListener);
  57. categoryTree.addMouseMotionListener(mouseListener);
  58. setColumnHeaderView(buttonPanel);
  59. setViewportView(categoryTree);
  60. }
  61. private void initLayout(){
  62. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
  63. btnAddPopUp.add(mItemNew);
  64. btnAddPopUp.addSeparator();
  65. btnAddPopUp.add(mItemCategory);
  66. btnAddPopUp.add(mItemObject);
  67. btnAddPopUp.add(mItemSwitch);
  68. toolBar.add(btnAdd);
  69. toolBar.add(btnDel);
  70. buttonPanel.add(toolBar);
  71. }
  72. private void initButtons(){
  73. mItemNew.addActionListener(clicked -> new CreateNewDialog(control, gui));
  74. mItemCategory.addActionListener(clicked -> new CreateNewDialog(control, CreateNewDialog.Option.Category, gui));
  75. mItemObject.addActionListener(clicked -> new CreateNewDialog(control, CreateNewDialog.Option.Object, gui));
  76. mItemSwitch.addActionListener(clicked -> new CreateNewDialog(control, CreateNewDialog.Option.Switch, gui));
  77. btnAdd.addActionListener(clicked -> btnAddPopUp.show(btnAdd, -1, +20));
  78. btnDel.addActionListener(clicked -> TryDeleteSelectedCategory());
  79. btnAdd.setToolTipText("<html><b>New</b><br>Add a new Category or Item to the library.</html>");
  80. btnDel.setToolTipText("<html><b>Delete</b><br>Removes a Category or a Category Item.</html>");
  81. }
  82. private void TryDeleteSelectedCategory(){
  83. Optional<DefaultMutableTreeNode> selectedNode = Optional.ofNullable((DefaultMutableTreeNode) categoryTree.getLastSelectedPathComponent());
  84. selectedNode.ifPresentOrElse(node -> {
  85. if (node instanceof CategoryTreeNode catNode) {
  86. int dialogResult = JOptionPane.showConfirmDialog(gui, "Do you really want to delete the Category " + catNode + "?",
  87. "Warning", JOptionPane.YES_NO_OPTION);
  88. if (dialogResult == JOptionPane.YES_OPTION) {
  89. GuiSettings.getCategories().stream().filter(cat -> Objects.equals(cat.getName(), catNode.toString())).findAny()
  90. .ifPresent(control::deleteCategory);
  91. }
  92. } else if (node instanceof ObjectTreeNode objNode) {
  93. objNode.getCategory().getObjects().remove(objNode.object);
  94. }
  95. categoryTree.repaint();
  96. }, () -> JOptionPane.showMessageDialog(gui, "Please select a Category or an Object in the left library in order to delete something."));
  97. }
  98. /**
  99. * When changes are made to the Categories.
  100. *
  101. * @param categories the Categories
  102. */
  103. private void updateCategories(Collection<Category> categories) {
  104. DefaultMutableTreeNode root = new DefaultMutableTreeNode("Categories");
  105. categories.stream().map(CategoryTreeNode::new).forEach(root::add);
  106. categoryTree.setModel(new DefaultTreeModel(root));
  107. }
  108. private static class CategoryTreeRenderer implements TreeCellRenderer {
  109. @Override
  110. public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
  111. boolean leaf, int row, boolean hasFocus) {
  112. JLabel label = new JLabel(value.toString());
  113. if (value instanceof CategoryTreeNode) {
  114. label.setIcon(new ImageIcon(Import.loadImage(ImagePreference.Category.Folder)));
  115. } else if (value instanceof ObjectTreeNode node) {
  116. Image image = Import.loadImage(node.getObject().getImagePath(), tree.getRowHeight(), tree.getRowHeight());
  117. label.setIcon(new ImageIcon(image));
  118. }
  119. if (hasFocus) {
  120. label.setForeground(ColorPreference.Category.Focus);
  121. label.setOpaque(true);
  122. }
  123. return label;
  124. }
  125. }
  126. private class CategoryMouseListener extends MouseAdapter{
  127. AbstractCanvasObject selected = null;
  128. @Override
  129. public void mousePressed(MouseEvent e) {
  130. Optional<DefaultMutableTreeNode> selectedNode = Optional.ofNullable(
  131. (DefaultMutableTreeNode) categoryTree.getLastSelectedPathComponent());
  132. selectedNode.ifPresent(node -> {
  133. int depthOfNode = node.getLevel();
  134. if (depthOfNode != 2) {
  135. return;
  136. }
  137. ObjectTreeNode objectNode = (ObjectTreeNode) node;
  138. selected = objectNode.getObject();
  139. log.info("Test" + selected);
  140. Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(Import.loadImage(selected.getImagePath(), 32, 32), new Point(),
  141. "Image");
  142. gui.setCursor(cursor);
  143. });
  144. }
  145. @Override
  146. public void mouseReleased(MouseEvent e) {
  147. if(selected == null){
  148. return;
  149. }
  150. gui.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  151. Canvas groupNodeCanvas = gui.getCanvas();
  152. Optional<Point> positionInCanvas = Optional.ofNullable(groupNodeCanvas.getMousePosition());
  153. AbstractCanvasObject finalTempCps = selected;
  154. final int halfCursorSize = GuiSettings.getPictureScaleDiv2();
  155. positionInCanvas.ifPresent(pos -> {
  156. AbstractCanvasObject obj = null;
  157. if (finalTempCps instanceof HolonObject hO) {
  158. obj = new HolonObject(hO);
  159. obj.setPosition(pos.x + halfCursorSize, pos.y + halfCursorSize);
  160. } else if (finalTempCps instanceof HolonSwitch sw) {
  161. obj = new HolonSwitch(sw);
  162. obj.setPosition(pos.x + halfCursorSize, pos.y + halfCursorSize);
  163. }
  164. control.addObjectOnCanvas(groupNodeCanvas.getGroupNode(), obj);
  165. control.calculateStateAndVisualForCurrentTimeStep();
  166. });
  167. selected = null;
  168. }
  169. }
  170. private static class CategoryTreeNode extends DefaultMutableTreeNode {
  171. private final Category category;
  172. public CategoryTreeNode(Category category) {
  173. super(category.getName());
  174. this.category = category;
  175. category.getObjects().stream().map(obj -> new ObjectTreeNode(category, obj)).forEach(this::add);
  176. }
  177. public Category getCategory() {
  178. return category;
  179. }
  180. }
  181. private static class ObjectTreeNode extends DefaultMutableTreeNode {
  182. private final AbstractCanvasObject object;
  183. private final Category category;
  184. public ObjectTreeNode(Category category, AbstractCanvasObject object) {
  185. super(object.getName());
  186. this.category = category;
  187. this.object = object;
  188. }
  189. public AbstractCanvasObject getObject() {
  190. return object;
  191. }
  192. public Category getCategory() {
  193. return category;
  194. }
  195. }
  196. }