001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.editor;
011:
012: import java.io.IOException;
013: import java.io.PrintWriter;
014: import java.io.StringWriter;
015:
016: import org.eclipse.pde.core.IWritable;
017: import org.eclipse.pde.internal.core.plugin.IWritableDelimiter;
018: import org.eclipse.swt.dnd.DND;
019: import org.eclipse.swt.dnd.DragSource;
020: import org.eclipse.swt.dnd.DragSourceEvent;
021: import org.eclipse.swt.dnd.DragSourceListener;
022: import org.eclipse.swt.dnd.TextTransfer;
023: import org.eclipse.swt.widgets.Control;
024: import org.eclipse.swt.widgets.Item;
025: import org.eclipse.swt.widgets.Table;
026: import org.eclipse.swt.widgets.Tree;
027:
028: /**
029: * PDEDragAdapter
030: *
031: */
032: public class PDEDragAdapter implements DragSourceListener,
033: IPDESourceParticipant {
034:
035: private IPDEDragParticipant fParticipant;
036:
037: // Needs to be static to allow dragging objects from one viewer to another
038: private static Object[] fSourceObjects;
039:
040: private static int fTransferType;
041:
042: public static final int F_TRANSFER_TYPE_NONE = 0x00;
043:
044: public static final int F_TRANSFER_TYPE_MODEL = 0x01;
045:
046: public static final int F_TRANSFER_TYPE_TEXT = 0x02;
047:
048: /**
049: * @param participant
050: */
051: public PDEDragAdapter(IPDEDragParticipant participant) {
052: fParticipant = participant;
053: resetSourceObjects();
054: }
055:
056: /**
057: * @param objects
058: */
059: protected void setSourceObjects(Object[] objects) {
060: fSourceObjects = objects;
061: }
062:
063: /* (non-Javadoc)
064: * @see org.eclipse.pde.internal.ui.editor.IPDESourceParticipant#getSourceObjects()
065: */
066: public Object[] getSourceObjects() {
067: return fSourceObjects;
068: }
069:
070: /**
071: *
072: */
073: protected void resetSourceObjects() {
074: fSourceObjects = null;
075: fTransferType = F_TRANSFER_TYPE_NONE;
076: }
077:
078: /**
079: * @return
080: */
081: protected boolean isCopyOperationSupported() {
082: if ((fParticipant.getSupportedDNDOperations() & DND.DROP_COPY) == DND.DROP_COPY) {
083: return true;
084: }
085: return false;
086: }
087:
088: /**
089: * @return
090: */
091: protected boolean isMoveOperationSupported() {
092: if ((fParticipant.getSupportedDNDOperations() & DND.DROP_MOVE) == DND.DROP_MOVE) {
093: return true;
094: }
095: return false;
096: }
097:
098: /**
099: * @return
100: */
101: protected boolean isLinkOperationSupported() {
102: if ((fParticipant.getSupportedDNDOperations() & DND.DROP_LINK) == DND.DROP_LINK) {
103: return true;
104: }
105: return false;
106: }
107:
108: /* (non-Javadoc)
109: * @see org.eclipse.swt.dnd.DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent)
110: */
111: public void dragFinished(DragSourceEvent event) {
112: // Nothing to do if drag event is not enabled
113: if (event.doit == false) {
114: return;
115: }
116: // TODO: MP: DND: BUG: On text transfer the object is removed, need to force operation into a copy
117: // TODO: MP: DND: BUG: On text transfer no object selected in tree - related to above
118: // Ensure we have a move operation and a model transfer type
119: if (event.detail != DND.DROP_MOVE) {
120: return;
121: } else if ((fTransferType & F_TRANSFER_TYPE_MODEL) != F_TRANSFER_TYPE_MODEL) {
122: return;
123: }
124: // Is a move operation
125: // Is a model transfer type
126: // Remove the original source objects
127: fParticipant.doDragRemove(getSourceObjects());
128: }
129:
130: /**
131: * @param event
132: */
133: protected void validateDrag(DragSourceEvent event) {
134: // Nothing to do if drag event is not enabled
135: if (event.doit == false) {
136: return;
137: }
138: // Get the source objects (selection in tree);
139: // TODO: MP: DND: Adapt for tables in the future
140: // Get the source of the event
141: Object source = event.getSource();
142: // Ensure we have a drag source
143: if ((source instanceof DragSource) == false) {
144: event.doit = false;
145: return;
146: }
147: // Get the control of the source
148: Control control = ((DragSource) source).getControl();
149: // Get the items selected in the tree or table
150: Item[] items = null;
151: if (control instanceof Tree) {
152: // Get the tree's selection
153: items = ((Tree) control).getSelection();
154: } else if (control instanceof Table) {
155: // Get the table's selection
156: items = ((Table) control).getSelection();
157: } else {
158: event.doit = false;
159: return;
160: }
161: // Ensure there are selected objects
162: if (items.length == 0) {
163: event.doit = false;
164: return;
165: }
166: // Create the container for the source objects
167: Object[] sourceObjects = new Object[items.length];
168: // Store all source objects
169: for (int i = 0; i < items.length; i++) {
170: sourceObjects[i] = items[i].getData();
171: }
172: // Store the source objects for later use
173: setSourceObjects(sourceObjects);
174: // event.doit is true by default
175: }
176:
177: /* (non-Javadoc)
178: * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent)
179: */
180: public void dragSetData(DragSourceEvent event) {
181: // Check to see if the drag event is valid
182: if (event.doit == false) {
183: return;
184: }
185: // Determine data required by target
186: if (ModelDataTransfer.getInstance().isSupportedType(
187: event.dataType)) {
188: // Model transfer target
189: // e.g. Tree viewer, Table viewer
190: event.data = getSourceObjects();
191: fTransferType = F_TRANSFER_TYPE_MODEL;
192: } else if (TextTransfer.getInstance().isSupportedType(
193: event.dataType)) {
194: // Text transfer target
195: // e.g. Word, Source page
196: event.data = createTextualRepresentation();
197: fTransferType = F_TRANSFER_TYPE_TEXT;
198: }
199: }
200:
201: /**
202: * @return
203: */
204: protected Object createTextualRepresentation() {
205: String textualRepresentation = null;
206: StringWriter stringWriter = new StringWriter();
207: PrintWriter printWriter = new PrintWriter(stringWriter);
208: boolean firstIteration = true;
209: Object[] sourceObjects = getSourceObjects();
210: // Serialize each source object to text
211: for (int i = 0; i < sourceObjects.length; i++) {
212: Object object = sourceObjects[i];
213: if (object instanceof IWritable) {
214: if ((firstIteration == false)
215: && (object instanceof IWritableDelimiter)) {
216: // Add a customized delimiter in between all serialized
217: // objects to format the text representation
218: ((IWritableDelimiter) object)
219: .writeDelimeter(printWriter);
220: }
221: // Write the textual representation of the object
222: ((IWritable) object).write("", printWriter); //$NON-NLS-1$
223: } else if (object instanceof String) {
224: // Delimiter is always a newline
225: printWriter.println((String) object);
226: }
227: firstIteration = false;
228: }
229: // Flush the writer
230: printWriter.flush();
231: // Get the String representation
232: textualRepresentation = stringWriter.toString();
233: // Close the print writer
234: printWriter.close();
235: // Close the string writer
236: try {
237: stringWriter.close();
238: } catch (IOException e) {
239: // Ignore
240: }
241: return textualRepresentation;
242: }
243:
244: /* (non-Javadoc)
245: * @see org.eclipse.swt.dnd.DragSourceListener#dragStart(org.eclipse.swt.dnd.DragSourceEvent)
246: */
247: public void dragStart(DragSourceEvent event) {
248: // Clear the previous source objects
249: // New drag starting
250: resetSourceObjects();
251: // Validate the drag event
252: validateDrag(event);
253: // Check to see if the drag event is valid
254: if (event.doit == false) {
255: return;
256: }
257: // TODO: MP: DND: Want to support some operations for some items - not all or nothing
258: // Disable the drag event if the copy operation is supported; but, the
259: // selection cannot be copied
260: if (isCopyOperationSupported()
261: && (fParticipant.canDragCopy(getSourceObjects()) == false)) {
262: event.doit = false;
263: return;
264: }
265: // Disable the drag event if the move operation is supported; but, the
266: // selection cannot be cut
267: if (isMoveOperationSupported()
268: && (fParticipant.canDragMove(getSourceObjects()) == false)) {
269: event.doit = false;
270: return;
271: }
272: // Disable the drag event if the link operation is supported; but, the
273: // selection cannot be linked
274: if (isLinkOperationSupported()
275: && (fParticipant.canDragLink(getSourceObjects()) == false)) {
276: event.doit = false;
277: return;
278: }
279: // Drag event is enabled
280: }
281:
282: }
|