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.Collections;
15  
16  import org.eclipse.draw2d.Cursors;
17  import org.eclipse.gef.EditPart;
18  import org.eclipse.gef.EditPartViewer;
19  import org.eclipse.gef.GraphicalEditPart;
20  import org.eclipse.gef.EditPartViewer.Conditional;
21  import org.eclipse.gef.tools.SelectionTool;
22  import org.eclipse.swt.SWT;
23  import org.eclipse.swt.events.KeyEvent;
24  import org.eclipse.swt.widgets.Event;
25  import org.w3c.dom.Node;
26  
27  import sk.baka.ikslibs.DOMUtils;
28  import sk.baka.ikslibs.interval.DOMInterval;
29  import sk.baka.ikslibs.interval.DOMIntervalSet;
30  import sk.baka.ikslibs.ptr.DomPointer;
31  import sk.baka.ikslibs.ptr.DomPointerFactory;
32  import sk.uniba.euromath.document.XMLAccess;
33  import sk.uniba.euromath.editor.textEditor.ITextPieceKeeper;
34  import sk.uniba.euromath.editor.xmlEditor.IXMLEditPart;
35  import sk.uniba.euromath.editor.xmlEditor.XMLEditDomain;
36  import sk.uniba.euromath.editor.xmlEditor.viewers.IXMLGraphicalViewer;
37  
38  /***
39   * <b>XMLStructureTool</b> - tool to make whole nodes selection<br>
40   * Structure is defined by tree of nodes, so this tool can select nodes of xml
41   * document.
42   * <ol>
43   * <li> Supports structure selection - selection is composed of nodes.</li>
44   * <li> Selections are performed by mouse and keyboard.</li>
45   * <li> Editing is performed through menu and keyboard.</li>
46   * <li> Suports clipboard, undo, redo</li>
47   * </ol>
48   * Key and mouse functionality control:
49   * <ul>
50   * <li><i>up, down arrow</i> - selects brother of selected node; if more nodes
51   * are selected, deselects all</li>
52   * <li><i>CTRL + wheel</i> - selects parent/child of selected node; if more
53   * nodes are selected, deselects all</li>
54   * <li><b><i>click in special place - square, triangel</i> selects element
55   * assigned to that place. So elements are bounded by visible border with square
56   * at corner.</b></li>
57   * <li><i>some mechanism</i> - selects elements only of selected type</li>
58   * </ul>
59   * 
60   * @author Martin Kollar Created on 6.6.2005
61   */
62  
63  public class XMLStructureTool extends SelectionTool {
64  
65          public static final int PREV_SIBLING = 1;
66  
67          public static final int NEXT_SIBLING = 2;
68  
69          /***
70           * Constructor.
71           */
72          public XMLStructureTool() {
73                  super();
74                  setDefaultCursor(Cursors.CROSS);
75          }
76  
77          /***
78           * @return the EditPart that has focus
79           */
80          protected GraphicalEditPart getFocusEditPart() {
81                  return (GraphicalEditPart) getCurrentViewer()
82                                  .getFocusEditPart();
83          }
84  
85          @Override
86          protected boolean handleKeyDown(KeyEvent event) {
87                  switch (event.keyCode) {
88                  case SWT.ARROW_LEFT:
89                          return true;
90                  case SWT.ARROW_RIGHT:
91                          return true;
92                  case SWT.ARROW_UP:
93                          selectSiblingNode(XMLStructureTool.PREV_SIBLING);
94                          return true;
95                  case SWT.ARROW_DOWN:
96                          selectSiblingNode(XMLStructureTool.NEXT_SIBLING);
97                          return true;
98                  default:
99                          return false;
100                 }
101         }
102 
103         /***
104          * Selects previous or next sibling of selected node(if not exists such
105          * sibling, does nothing). If more nodes are selected, selects nothing.
106          */
107         protected void selectSiblingNode(int direction) {
108                 DOMIntervalSet selection = this.getXMLGraphicalViewer()
109                                 .getDOMSelection();
110                 // if is not selected one node
111                 if (selection.getContents().size() != 1)
112                         return;
113 
114                 Node node = selection.getContents().get(0);
115                 Node nodeToSelect = null;
116 
117                 switch (direction) {
118                 case XMLStructureTool.PREV_SIBLING: {
119                         nodeToSelect = node.getPreviousSibling();
120                 }
121                 case XMLStructureTool.NEXT_SIBLING:
122                         nodeToSelect = node.getNextSibling();
123                 }
124                 if (nodeToSelect == null)
125                         return;
126                 DomPointer pointer = DomPointerFactory.create(node
127                                 .getParentNode());
128                 this.getXMLGraphicalViewer().setSelection(
129                                 new DOMIntervalSet(new DOMInterval(pointer,
130                                                 pointer.getNextSibling())));
131         }
132 
133         @Override
134         protected boolean handleKeyUp(KeyEvent e) {
135                 return super.handleKeyUp(e);
136         }
137 
138         /***
139          * Selects parent of selected node. If more nodes are selected, does *
140          * nothing.
141          */
142         protected void ScrollUp(EditPartViewer viewer) {
143                 DOMIntervalSet selection = this.getXMLGraphicalViewer()
144                                 .getDOMSelection();
145                 // if is not selected one node
146                 if (selection.getContents().size() != 1)
147                         return;
148 
149                 Node node = selection.getContents().get(0);
150                 if (!DOMUtils.isContentNode(node.getParentNode()))
151                         return;
152 
153                 DomPointer pointer = DomPointerFactory.create(node
154                                 .getParentNode());
155                 this.getXMLGraphicalViewer().setSelection(
156                                 new DOMIntervalSet(new DOMInterval(pointer,
157                                                 pointer.getNextSibling())));
158         }
159 
160         /***
161          * Selects first child of selected node(TODO Studva some alg to
162          * select not first child). If more nodes are selected, selects nothing.
163          */
164         protected void ScrollDown(EditPartViewer viewer) {
165                 DOMIntervalSet selection = this.getXMLGraphicalViewer()
166                                 .getDOMSelection();
167                 // if is not selected one node
168                 if (selection.getContents().size() != 1)
169                         return;
170 
171                 Node node = selection.getContents().get(0);
172                 if (!node.hasChildNodes())
173                         return;
174 
175                 DomPointer pointer = DomPointerFactory.create(node
176                                 .getChildNodes().item(0));
177                 this.getXMLGraphicalViewer().setSelection(
178                                 new DOMIntervalSet(new DOMInterval(pointer,
179                                                 pointer.getNextSibling())));
180         }
181 
182         /***
183          * Delegates the scrolling to the DragTracker (if there is one). If not,
184          * invokes the super method.
185          * 
186          * @see org.eclipse.gef.Tool#mouseWheelScrolled(org.eclipse.swt.widgets.Event,
187          *      org.eclipse.gef.EditPartViewer)
188          */
189         @Override
190         public void mouseWheelScrolled(Event event, EditPartViewer viewer) {
191                 if (getDragTracker() != null) {
192                         getDragTracker().mouseWheelScrolled(event, viewer);
193                         event.doit = false;
194                 } else if (getFocusEditPart() instanceof IXMLEditPart) {
195                         if ((event.type == SWT.MouseWheel) && canScroll()) {
196                                 if (event.count > 0)
197                                         ScrollUp(viewer);
198                                 else if (event.count < 0)
199                                         ScrollDown(viewer);
200                         }
201                 } else
202                         super.mouseWheelScrolled(event, viewer);
203 
204         }
205 
206         protected boolean canScroll() {
207                 return getCurrentInput().isControlKeyDown();
208         }
209 
210         protected IXMLGraphicalViewer getXMLGraphicalViewer() {
211                 return (IXMLGraphicalViewer) this.getCurrentViewer();
212         }
213 
214         protected XMLAccess getXMLAcces() {
215                 return ((XMLEditDomain) this.getDomain()).getXMLEditor()
216                                 .getXMLAccess();
217         }
218 
219         /***
220          * Simpler implementation than super, as target is directly taken
221          * editpart at mouse cursor location.
222          */
223         @Override
224         protected boolean updateTargetUnderMouse() {
225                 if (!isTargetLocked()) {
226                         EditPart editPart = getCurrentViewer()
227                                         .findObjectAtExcluding(getLocation(),
228                                                         Collections.EMPTY_SET,
229                                                         new Conditional() {
230 
231                                                                 public boolean evaluate(
232                                                                                 EditPart editpart) {
233                                                                         return !(editpart instanceof ITextPieceKeeper);
234                                                                 }
235 
236                                                         });
237                         boolean changed = getTargetEditPart() != editPart;
238                         setTargetEditPart(editPart);
239                         return changed;
240                 }
241                 return false;
242         }
243 
244         /***
245          * Process only left mouse clicks (as selection or anything).
246          */
247         @Override
248         protected boolean handleButtonDown(int button) {
249                 if (button != 1)
250                         return false;
251                 return super.handleButtonDown(button);
252         }
253 }