blob: 17335ae3f05fb83ca69aea45030080ba50e6f070 [file] [log] [blame]
david_williamscfdb2cd2004-11-11 08:37:49 +00001/*******************************************************************************
2 * Copyright (c) 2001, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Jens Lukowski/Innoopract - initial renaming/restructuring
11 *
12 *******************************************************************************/
david_williamsf3680f02005-04-13 22:43:54 +000013package org.eclipse.wst.sse.ui.internal;
david_williamscfdb2cd2004-11-11 08:37:49 +000014
david_williams76ae86b2005-04-20 00:29:00 +000015import org.eclipse.jface.text.BadLocationException;
16import org.eclipse.jface.text.IRegion;
david_williamscfdb2cd2004-11-11 08:37:49 +000017import org.eclipse.jface.text.ITextViewer;
18import org.eclipse.swt.custom.ST;
19import org.eclipse.swt.custom.StyledText;
20import org.eclipse.swt.dnd.DND;
21import org.eclipse.swt.dnd.DropTargetAdapter;
22import org.eclipse.swt.dnd.DropTargetEvent;
23import org.eclipse.swt.dnd.FileTransfer;
24import org.eclipse.swt.dnd.Transfer;
25import org.eclipse.swt.dnd.TransferData;
26import org.eclipse.swt.graphics.Color;
27import org.eclipse.swt.graphics.GC;
28import org.eclipse.swt.graphics.Point;
29import org.eclipse.swt.graphics.Rectangle;
30import org.eclipse.swt.widgets.Caret;
nitind50897002005-06-03 20:33:54 +000031import org.eclipse.ui.IEditorPart;
david_williamscfdb2cd2004-11-11 08:37:49 +000032
33/**
34 * ExtendedEditorDropTargetAdapter
35 */
36public class ExtendedEditorDropTargetAdapter extends DropTargetAdapter {
37
38 private Point caret = null;
39 private String[] editorIds;
40 private int orgOffset = 0;
nitind50897002005-06-03 20:33:54 +000041 private IEditorPart targetEditor = null;
david_williamscfdb2cd2004-11-11 08:37:49 +000042 private ITextViewer textViewer = null;
43
44 private Transfer[] transfers = null;
45
46 public ExtendedEditorDropTargetAdapter() {
47 super();
48 }
49
50 protected boolean doDrop(Transfer transfer, DropTargetEvent event) {
51 TransferBuilder tb = new TransferBuilder();
52
53 IDropAction[] as = null;
54 if (editorIds != null && editorIds.length > 0)
55 as = tb.getDropActions(editorIds, transfer.getClass().getName());
56 else
57 as = tb.getDropActions(getTargetEditor().getClass().getName(), transfer.getClass().getName());
58
59 for (int i = 0; i < as.length; ++i) {
60 IDropAction da = as[i];
61 if (transfer instanceof FileTransfer) {
62 if (event.data == null) {
63 Logger.log(Logger.ERROR, "No data in DropTargetEvent from " + event.widget); //$NON-NLS-1$
64 return false;
65 }
66 String[] strs = (String[]) event.data;
67 boolean[] bs = new boolean[strs.length];
68 int c = 0;
69 for (int j = 0; j < strs.length; ++j) {
70 bs[j] = false;
71 if (da.isSupportedData(strs[j])) {
72 event.data = new String[]{strs[j]};
73 if (!da.run(event, targetEditor)) {
74 bs[j] = true;
75 c++;
76 }
77 } else {
78 bs[j] = true;
79 c++;
80 }
81 }
82 if (c == 0) {
83 return true;
84 }
85
86 int k = 0;
87 String[] rests = new String[c];
88 for (int j = 0; j < strs.length; ++j) {
89 if (bs[j])
90 rests[k++] = strs[j];
91 }
92 event.data = rests;
93 } else if (da.isSupportedData(event.data)) {
94 if (da.run(event, targetEditor)) {
95 return true;
96 }
97 }
98 }
99
100 return false;
101 }
102
103 /**
104 */
105 public void dragEnter(DropTargetEvent event) {
106 caret = null;
107 TransferData data = null;
108 Transfer[] ts = getTransfers();
109 for (int i = 0; i < ts.length; i++) {
110 for (int j = 0; j < event.dataTypes.length; j++) {
111 if (ts[i].isSupportedType(event.dataTypes[j])) {
112 data = event.dataTypes[j];
113 break;
114 }
115 }
116 if (data != null) {
117 event.currentDataType = data;
118 break;
119 }
120 }
121
122 if (textViewer != null) {
123 orgOffset = textViewer.getTextWidget().getCaretOffset();
124 }
125 }
126
127 public void dragLeave(DropTargetEvent event) {
128 if (textViewer != null) {
129 StyledText st = textViewer.getTextWidget();
130 st.setCaretOffset(orgOffset);
131 st.redraw();
132 st.update();
133 }
134 }
135
136 /**
137 */
138 public void dragOver(DropTargetEvent event) {
139 event.operations &= ~DND.DROP_MOVE;
140 event.detail = DND.DROP_COPY;
141
142 if (textViewer != null) {
143 Point pt = toControl(new Point(event.x, event.y));
144 StyledText st = textViewer.getTextWidget();
145
146 // auto scroll
147 Rectangle ca = st.getClientArea();
148 int margin = st.getLineHeight();
149
150 if (pt.y < margin) { // up
151 st.invokeAction(ST.LINE_UP);
152 } else if (pt.y > ca.height - margin) { // down
153 st.invokeAction(ST.LINE_DOWN);
154 }
155
156 // draw insertion point
157 int offset = getDropOffset(st, pt);
158 if (offset != st.getCaretOffset()) {
159 st.setCaretOffset(offset);
160 st.setSelection(offset);
161 }
162
163 Point newCaret = st.getLocationAtOffset(offset);
164 if (newCaret.equals(caret))
165 return;
166
167 Caret ct = st.getCaret();
168 Point size = ct.getSize();
169
170 GC gc = new GC(st);
171 gc.setXORMode(true);
172 gc.setLineWidth(size.x);
173
174 // erase old caret
175 if (caret != null) {
176 Color originalForeground = gc.getForeground();
177 gc.setForeground(st.getBackground());
178 gc.drawLine(caret.x, caret.y, caret.x, caret.y + size.y);
179 gc.setForeground(originalForeground);
180 }
181
182 st.redraw();
183 st.update();
184
185 // draw new caret
186 caret = newCaret;
187 if (ct.getImage() != null)
188 gc.drawImage(ct.getImage(), caret.x, caret.y);
189 else
190 gc.drawLine(caret.x, caret.y, caret.x, caret.y + size.y);
191
192 gc.dispose();
193 }
194 }
195
196 /**
197 */
198 public void drop(DropTargetEvent event) {
199 if (event.operations == DND.DROP_NONE)
200 return;
201
202 if (textViewer != null) {
203 Point pt = toControl(new Point(event.x, event.y));
204 StyledText st = textViewer.getTextWidget();
205
206 int offset = getDropOffset(st, pt);
207 if (offset != st.getCaretOffset()) {
208 st.setCaretOffset(offset);
209 }
210
david_williams76ae86b2005-04-20 00:29:00 +0000211 // ISelectionProvider sp = textViewer.getSelectionProvider();
212 // ISelection sel = new TextSelection(offset, 0);
213 // sp.setSelection(sel);
david_williamscfdb2cd2004-11-11 08:37:49 +0000214 textViewer.setSelectedRange(offset, 0);
215 }
216
217 Transfer[] ts = getTransfers();
218 for (int i = 0; i < ts.length; i++) {
219 if (ts[i].isSupportedType(event.currentDataType)) {
220 if (doDrop(ts[i], event)) {
221 break;
222 }
223 }
224 }
225 }
226
227 protected int getDropOffset(DropTargetEvent event) {
228 Point pt = getTextViewer().getTextWidget().toControl(new Point(event.x, event.y));
229 StyledText st = textViewer.getTextWidget();
230 return getDropOffset(st, pt);
231 }
232
233 private int getDropOffset(StyledText st, Point pt) {
234 int offset = st.getCaretOffset();
235 try {
236 offset = st.getOffsetAtLocation(pt);
237 } catch (IllegalArgumentException e) {
238 // This is normal case if mouse cursor is on outside of valid
239 // text.
240 boolean found = false;
241 Point p = new Point((pt.x > 0 ? pt.x : 0), pt.y);
242 // search nearest character
243 for (; p.x > -1; p.x--) {
244 try {
david_williams76ae86b2005-04-20 00:29:00 +0000245 offset = st.getOffsetAtLocation(p);
246
247 /*
248 * Now that a valid offset has been found, try to place at
249 * the end of the line
250 */
251 if (textViewer != null && textViewer.getDocument() != null) {
252 IRegion lineInfo = null;
253 try {
254 lineInfo = textViewer.getDocument().getLineInformationOfOffset(offset);
255 } catch (BadLocationException e1) {
256 }
257 if (lineInfo != null)
258 offset = lineInfo.getOffset() + lineInfo.getLength();
259 }
260
david_williamscfdb2cd2004-11-11 08:37:49 +0000261 found = true;
262 break;
263 } catch (IllegalArgumentException ex) {
264 }
265 }
266
267 if (!found) {
268 offset = st.getCharCount();
269 }
270 }
271 return offset;
272 }
273
nitind50897002005-06-03 20:33:54 +0000274 public IEditorPart getTargetEditor() {
david_williamscfdb2cd2004-11-11 08:37:49 +0000275 return targetEditor;
276 }
277
278 public ITextViewer getTextViewer() {
279 return textViewer;
280 }
281
282 /**
283 * @return org.eclipse.swt.dnd.Transfer[]
284 */
285 public Transfer[] getTransfers() {
286 if (transfers == null) {
287 TransferBuilder tb = new TransferBuilder();
288 if (editorIds == null || editorIds.length == 0)
289 transfers = tb.getDropTargetTransfers(getTargetEditor().getClass().getName());
290 else
291 transfers = tb.getDropTargetTransfers(editorIds);
292 }
293 return transfers;
294 }
295
296 /**
297 */
nitind50897002005-06-03 20:33:54 +0000298 public void setTargetEditor(IEditorPart targetEditor) {
david_williamscfdb2cd2004-11-11 08:37:49 +0000299 this.targetEditor = targetEditor;
300 }
301
302 public void setTargetIDs(String[] ids) {
303 editorIds = ids;
304 }
305
306 public void setTextViewer(ITextViewer textViewer) {
307 this.textViewer = textViewer;
308 }
309
310 private Point toControl(Point point) {
311 return (textViewer != null ? textViewer.getTextWidget().toControl(point) : point);
312 }
313}