View Javadoc

1   /*
2    * Copyright 1999-2006 Faculty of Mathematics, Physics
3    * and Informatics, Comenius University, Bratislava. This file is protected by
4    * the Mozilla Public License version 1.1 (the License); you may not use this
5    * file except in compliance with the License. You may obtain a copy of the
6    * License at http://euromath2.sourceforge.net/license.html Unless required by
7    * applicable law or agreed to in writing, software distributed under the
8    * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
9    * OF ANY KIND, either express or implied. See the License for the specific
10   * language governing permissions and limitations under the License.
11   */
12  package sk.uniba.euromath.editor.xmlEditor.tools;
13  
14  import java.util.ArrayList;
15  import java.util.List;
16  
17  import org.eclipse.gef.EditPartViewer;
18  import org.eclipse.gef.GraphicalEditPart;
19  import org.eclipse.gef.tools.SelectionTool;
20  import org.eclipse.swt.SWT;
21  import org.eclipse.swt.events.KeyEvent;
22  import org.eclipse.swt.widgets.Event;
23  import org.w3c.dom.Node;
24  
25  import sk.baka.ikslibs.interval.DOMInterval;
26  import sk.baka.ikslibs.interval.DOMIntervalSet;
27  import sk.baka.ikslibs.ptr.DomPointer;
28  import sk.baka.ikslibs.ptr.DomPointerFactory;
29  import sk.uniba.euromath.document.XMLAccess;
30  import sk.uniba.euromath.editor.xmlEditor.XMLEditDomain;
31  import sk.uniba.euromath.editor.xmlEditor.editParts.XMLEditPart;
32  import sk.uniba.euromath.editor.xmlEditor.viewers.IXMLGraphicalViewer;
33  
34  /***
35   * <b>XMLStructureTool</b> - tool to make whole nodes selection<br>
36   * Structure is defined by tree of nodes, so this tool can select nodes of xml
37   * document.
38   * <ol>
39   * <li> Supports structure selection - selection is composed of nodes.</li>
40   * <li> Selections are performed by mouse and keyboard.</li>
41   * <li> Editing is performed through menu and keyboard.</li>
42   * <li> Suports clipboard, undo, redo</li>
43   * </ol>
44   * Key and mouse functionality control:
45   * <ul>
46   * <li><i>up, down arrow</i> - selects brother of selected node; if more nodes
47   * are selected, deselects all</li>
48   * <li><i>CTRL + wheel</i> - selects parent/child of selected node; if more
49   * nodes are selected, deselects all</li>
50   * <li><b><i>click in special place - square, triangel</i> selects element
51   * assigned to that place. So elements are bounded by visible border with square
52   * at corner.</b></li>
53   * <li><i>some mechanism</i> - selects elements only of selected type</li>
54   * </ul>
55   * 
56   * @author Martin Kollar Created on 6.6.2005
57   */
58  
59  public class XMLStructureTool extends SelectionTool {
60  
61      public static final int PREV_SIBLING = 1;
62  
63      public static final int NEXT_SIBLING = 2;
64  
65      /***
66       * Stores KeyCodes of keys that are pressed down.
67       */
68      private List<Integer> keysDown = new ArrayList<Integer>();
69  
70      /***
71       * Constructor.
72       */
73      public XMLStructureTool() {
74          super();
75      }
76  
77      /***
78       * @return the EditPart that has focus
79       */
80      protected GraphicalEditPart getFocusEditPart() {
81          if (getCurrentViewer() == null)
82              return null;
83          return (GraphicalEditPart) getCurrentViewer().getFocusEditPart();
84      }
85  
86      @Override
87      protected boolean handleKeyDown(KeyEvent event) {
88          addKey(event.keyCode);
89  
90          switch (event.keyCode) {
91          case SWT.ARROW_LEFT:
92              return true;
93          case SWT.ARROW_RIGHT:
94              return true;
95          case SWT.ARROW_UP:
96              selectSiblingNode(XMLStructureTool.PREV_SIBLING);
97              return true;
98          case SWT.ARROW_DOWN:
99              selectSiblingNode(XMLStructureTool.NEXT_SIBLING);
100             return true;
101         default:
102             return false;
103         }
104     }
105 
106     /***
107      * Selects previous or next sibling of selected node(if not exists such
108      * sibling, does nothing). If more nodes are selected, selects nothing.
109      */
110     protected void selectSiblingNode(int direction) {
111         DOMIntervalSet selection = null;// this.getXMLGraphicalViewer().getSelection();
112         // if is not selected one node
113         if (selection.getContentIds(getXMLAcces().getIdManager()).size() != 1) {
114             selection.clear();
115             this.getXMLGraphicalViewer().setSelection(selection);
116         }
117 
118         Node node = selection.getIntervals().get(0).getContents().get(0);
119         Node nodeToSelect = null;
120         switch (direction) {
121         case XMLStructureTool.PREV_SIBLING: {
122             nodeToSelect = node.getPreviousSibling();
123         }
124         case XMLStructureTool.NEXT_SIBLING:
125             nodeToSelect = node.getNextSibling();
126         }
127         if (nodeToSelect == null)
128             return;
129         selection.clear();
130         DomPointer pointer = DomPointerFactory.create(nodeToSelect);
131         selection.union(new DOMInterval(pointer, pointer.getNextSibling()));
132 
133         this.getXMLGraphicalViewer().setSelection(selection);
134     }
135 
136     @Override
137     protected boolean handleKeyUp(KeyEvent e) {
138         removeKey(e.keyCode);
139         return super.handleKeyUp(e);
140     }
141 
142     /***
143      * Selects parent of selected node. If more nodes are selected, selects
144      * nothing.
145      */
146     protected void ScrollUp(EditPartViewer viewer) {
147         DOMIntervalSet selection = null;// this.getXMLGraphicalViewer().getSelection();
148         // if is not selected one node
149         if (selection.getContentIds(getXMLAcces().getIdManager()).size() != 1) {
150             selection.clear();
151             this.getXMLGraphicalViewer().setSelection(selection);
152         }
153         Node node = selection.getIntervals().get(0).getContents().get(0);
154         Node nodeToSelect = node.getParentNode();
155 
156         if (nodeToSelect == null)
157             return;
158         selection.clear();
159         DomPointer pointer = DomPointerFactory.create(nodeToSelect);
160         selection.union(new DOMInterval(pointer, pointer.getNextSibling()));
161 
162         this.getXMLGraphicalViewer().setSelection(selection);
163     }
164 
165     /***
166      * Selects first child of selected node(TODO LOW PRIORITY some alg to select
167      * not first child). If more nodes are selected, selects nothing.
168      */
169     protected void ScrollDown(EditPartViewer viewer) {
170         DOMIntervalSet selection = null;// this.getXMLGraphicalViewer().getSelection();
171         // if is not selected one node
172         if (selection.getContentIds(getXMLAcces().getIdManager()).size() != 1) {
173             selection.clear();
174             this.getXMLGraphicalViewer().setSelection(selection);
175         }
176         Node node = selection.getIntervals().get(0).getContents().get(0);
177         Node nodeToSelect = node.getChildNodes().item(0);
178 
179         if (nodeToSelect == null)
180             return;
181         selection.clear();
182         DomPointer pointer = DomPointerFactory.create(nodeToSelect);
183         selection.union(new DOMInterval(pointer, pointer.getNextSibling()));
184 
185         this.getXMLGraphicalViewer().setSelection(selection);
186     }
187 
188     /***
189      * Delegates the scrolling to the DragTracker (if there is one). If not,
190      * invokes the super method.
191      * 
192      * @see org.eclipse.gef.Tool#mouseWheelScrolled(org.eclipse.swt.widgets.Event,
193      *      org.eclipse.gef.EditPartViewer)
194      */
195     @Override
196     public void mouseWheelScrolled(Event event, EditPartViewer viewer) {
197         if (getDragTracker() != null) {
198             getDragTracker().mouseWheelScrolled(event, viewer);
199             event.doit = false;
200         } else if (getFocusEditPart() instanceof XMLEditPart) {
201             if ((event.type == SWT.MouseWheel) && canScroll()) {
202                 if (event.count > 0)
203                     ScrollUp(viewer);
204                 else if (event.count < 0)
205                     ScrollDown(viewer);
206             }
207         } else
208             super.mouseWheelScrolled(event, viewer);
209 
210     }
211 
212     protected List<Integer> getKeysDown() {
213         return this.keysDown;
214     }
215 
216     /***
217      * @param code
218      *            KeyCode of pressed key
219      */
220     protected void addKey(Integer code) {
221         if (getKeysDown().contains(code))
222             return;
223         getKeysDown().add(code);
224     }
225 
226     protected void removeKey(Integer code) {
227         if (getKeysDown().contains(code))
228             getKeysDown().remove(code);
229         else {
230             // before creating tool some keys could be pressed
231             // so this state can happen
232             // throw new IllegalStateException();
233         }
234 
235     }
236 
237     protected boolean canScroll() {
238         return ((getKeysDown().size() == 1) && (getKeysDown().get(0) == SWT.CTRL));
239     }
240 
241     protected IXMLGraphicalViewer getXMLGraphicalViewer() {
242         return (IXMLGraphicalViewer) this.getCurrentViewer();
243     }
244 
245     protected XMLAccess getXMLAcces() {
246         return ((XMLEditDomain) this.getDomain()).getXMLEditor().getXMLAccess();
247     }
248 }