View Javadoc
1   package org.opentrafficsim.editor;
2   
3   import java.util.List;
4   
5   import javax.swing.CellEditor;
6   import javax.swing.tree.TreePath;
7   
8   import org.opentrafficsim.editor.Undo.ActionType;
9   
10  import de.javagl.treetable.JTreeTable;
11  
12  /**
13   * This class houses actions that can be performed on tree nodes. The actions will always be executed. Any check on whether the
14   * state of a node is appropriate for an action, is up to the caller. Callers are typically mouse event or key listeners on the
15   * tree.
16   * <p>
17   * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
18   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
19   * </p>
20   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
21   */
22  public class NodeActions
23  {
24  
25      /** Editor. */
26      private final OtsEditor editor;
27  
28      /** Tree table. */
29      private final JTreeTable treeTable;
30  
31      /**
32       * Constructor.
33       * @param editor OtsEditor; editor.
34       * @param treeTable JTreeTable; tree table.
35       */
36      public NodeActions(final OtsEditor editor, final JTreeTable treeTable)
37      {
38          this.editor = editor;
39          this.treeTable = treeTable;
40      }
41  
42      /**
43       * Add node.
44       * @param node XsdTreeNode; node.
45       */
46      public void add(final XsdTreeNode node)
47      {
48          this.editor.getUndo().startAction(ActionType.ADD, node, null);
49          XsdTreeNode added = node.add();
50          this.editor.getUndo().setPostActionShowNode(added);
51          this.editor.show(added, null);
52      }
53  
54      /**
55       * Duplicate node.
56       * @param node XsdTreeNode; node.
57       */
58      public void duplicate(final XsdTreeNode node)
59      {
60          this.editor.getUndo().startAction(ActionType.DUPLICATE, node, null);
61          XsdTreeNode added = node.duplicate();
62          this.editor.getUndo().setPostActionShowNode(added);
63          this.editor.show(added, null);
64      }
65  
66      /**
67       * Remove node.
68       * @param node XsdTreeNode; node.
69       */
70      public void remove(final XsdTreeNode node)
71      {
72          CellEditor editor = this.treeTable.getCellEditor();
73          if (editor != null)
74          {
75              editor.stopCellEditing();
76          }
77          this.editor.getUndo().startAction(ActionType.REMOVE, node, null);
78          XsdTreeNode parent = node.getParent();
79          int index = parent.getChildren().indexOf(node);
80          node.remove();
81          index = Math.min(index, parent.getChildren().size() - 1);
82          XsdTreeNode replaced = parent.getChild(index);
83          this.editor.getUndo().setPostActionShowNode(replaced);
84          this.editor.show(replaced, null);
85      }
86  
87      /**
88       * Copy node.
89       * @param node XsdTreeNode; node.
90       */
91      public void copy(final XsdTreeNode node)
92      {
93          this.editor.setClipboard(node, false);
94      }
95  
96      /**
97       * Cut node.
98       * @param node XsdTreeNode; node.
99       */
100     public void cut(final XsdTreeNode node)
101     {
102         this.editor.setClipboard(node, true);
103         this.editor.getUndo().startAction(ActionType.CUT, node, null);
104         node.setInactive();
105         this.editor.show(node, null);
106     }
107 
108     /**
109      * Insert node.
110      * @param node XsdTreeNode; node.
111      */
112     public void insert(final XsdTreeNode node)
113     {
114         this.editor.getUndo().startAction(ActionType.INSERT, node, null);
115         XsdTreeNode newNode = node.emptyCopy();
116         newNode.getRoot().fireEvent(XsdTreeNodeRoot.NODE_CREATED,
117                 new Object[] {newNode, newNode.getParent(), newNode.getParent().getChildren().indexOf(newNode)});
118         newNode.move(-1);
119         this.editor.getClipboard().copyInto(newNode);
120         this.editor.removeClipboardWhenCut();
121         this.editor.getUndo().setPostActionShowNode(newNode);
122         this.editor.show(newNode, null);
123     }
124 
125     /**
126      * Paste node.
127      * @param node XsdTreeNode; node.
128      */
129     public void paste(final XsdTreeNode node)
130     {
131         this.editor.getUndo().startAction(ActionType.PASTE, node, null);
132         XsdTreeNode newNode;
133         if (!node.isActive())
134         {
135             node.setActive();
136             newNode = node;
137         }
138         else
139         {
140             newNode = node.emptyCopy();
141             newNode.getRoot().fireEvent(XsdTreeNodeRoot.NODE_CREATED,
142                     new Object[] {newNode, newNode.getParent(), newNode.getParent().getChildren().indexOf(newNode)});
143         }
144         this.editor.getClipboard().copyInto(newNode);
145         if (!node.equals(newNode))
146         {
147             this.editor.removeClipboardWhenCut();
148         }
149         else
150         {
151             this.editor.setClipboard(null, false);
152         }
153         this.editor.getUndo().setPostActionShowNode(newNode);
154         this.editor.show(newNode, null);
155     }
156 
157     /**
158      * Revolve to the next option of the node.
159      * @param node XsdTreeNode; node.
160      * @param options List&lt;XsdOption&gt;; options of the node. These are obtainable from the node, but already gathered by
161      *            the caller of this method and therefore forwarded for efficieny.
162      */
163     public void revolveOption(final XsdTreeNode node, final List<XsdOption> options)
164     {
165         int optionIndex = 0;
166         for (int i = 0; i < options.size(); i++)
167         {
168             if (options.get(i).optionNode().equals(node))
169             {
170                 optionIndex = i + 1;
171                 break;
172             }
173         }
174         if (optionIndex >= options.size())
175         {
176             optionIndex = 0;
177         }
178         this.editor.getUndo().startAction(ActionType.OPTION, node, null);
179         XsdTreeNode next = options.get(optionIndex).optionNode();
180         node.setOption(next);
181         this.editor.show(next, null);
182     }
183 
184     /**
185      * Expand, or collapse, node.
186      * @param node XsdTreeNode; node.
187      * @param path TreePath; path in the tree of the node.
188      * @param expanded boolean; whether the node is currently expanded.
189      */
190     public void expand(final XsdTreeNode node, final TreePath path, final boolean expanded)
191     {
192         if (expanded)
193         {
194             this.treeTable.getTree().collapsePath(path);
195         }
196         else
197         {
198             if (!node.isActive())
199             {
200                 this.editor.getUndo().startAction(ActionType.ACTIVATE, node, null);
201                 node.setActive();
202             }
203             this.treeTable.getTree().expandPath(path);
204         }
205         this.editor.show(node, null);
206     }
207 
208     /**
209      * Move node.
210      * @param node XsdTreeNode; node.
211      * @param down int; number of rows to move the node down.
212      */
213     public void move(final XsdTreeNode node, final int down)
214     {
215         this.editor.getUndo().startAction(ActionType.MOVE, node, null);
216         node.move(down);
217         this.editor.show(node, null);
218     }
219 
220 }