1
2
3
4
5
6
7
8
9
10
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
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
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
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 }