001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.ui.part;
011:
012: import java.io.ByteArrayInputStream;
013: import java.io.ByteArrayOutputStream;
014: import java.io.DataInputStream;
015: import java.io.DataOutputStream;
016: import java.io.IOException;
017:
018: import org.eclipse.core.resources.IMarker;
019: import org.eclipse.core.resources.IResource;
020: import org.eclipse.core.resources.IWorkspace;
021: import org.eclipse.core.runtime.IPath;
022: import org.eclipse.core.runtime.Path;
023: import org.eclipse.swt.dnd.ByteArrayTransfer;
024: import org.eclipse.swt.dnd.TransferData;
025:
026: /**
027: * A <code>MarkerTransfer</code> is used to transfer an array of
028: * <code>IMarker</code>s from one part to another in a drag and drop
029: * operation.
030: * <p>
031: * In every drag and drop operation there is a <code>DragSource</code> and
032: * a <code>DropTarget</code>. When a drag occurs a <code>Transfer</code> is
033: * used to marshall the drag data from the source into a byte array. If a drop
034: * occurs another <code>Transfer</code> is used to marshall the byte array into
035: * drop data for the target.
036: * </p><p>
037: * This class can be used for a <code>Viewer<code> or an SWT component directly.
038: * A singleton is provided which may be serially reused (see <code>getInstance</code>).
039: * It is not intended to be subclassed.
040: * </p>
041: *
042: * @see org.eclipse.jface.viewers.StructuredViewer
043: * @see org.eclipse.swt.dnd.DropTarget
044: * @see org.eclipse.swt.dnd.DragSource
045: */
046: public class MarkerTransfer extends ByteArrayTransfer {
047:
048: /**
049: * Singleton instance.
050: */
051: private static final MarkerTransfer instance = new MarkerTransfer();
052:
053: // Create a unique ID to make sure that different Eclipse
054: // applications use different "types" of <code>MarkerTransfer</code>
055: private static final String TYPE_NAME = "marker-transfer-format" + System.currentTimeMillis() + ":" + instance.hashCode();//$NON-NLS-2$//$NON-NLS-1$
056:
057: private static final int TYPEID = registerType(TYPE_NAME);
058:
059: private IWorkspace workspace;
060:
061: /**
062: * Creates a new transfer object.
063: */
064: private MarkerTransfer() {
065: }
066:
067: /**
068: * Locates and returns the marker associated with the given attributes.
069: *
070: * @param pathString the resource path
071: * @param id the id of the marker to get (as per {@link IResource#getMarker
072: * IResource.getMarker})
073: * @return the specified marker
074: */
075: private IMarker findMarker(String pathString, long id) {
076: IPath path = new Path(pathString);
077: IResource resource = workspace.getRoot().findMember(path);
078: if (resource != null) {
079: return resource.getMarker(id);
080: }
081: return null;
082: }
083:
084: /**
085: * Returns the singleton instance.
086: *
087: * @return the singleton instance
088: */
089: public static MarkerTransfer getInstance() {
090: return instance;
091: }
092:
093: /* (non-Javadoc)
094: * Method declared on Transfer.
095: */
096: protected int[] getTypeIds() {
097: return new int[] { TYPEID };
098: }
099:
100: /* (non-Javadoc)
101: * Returns the type names.
102: *
103: * @return the list of type names
104: */
105: protected String[] getTypeNames() {
106: return new String[] { TYPE_NAME };
107: }
108:
109: /* (non-Javadoc)
110: * Method declared on Transfer.
111: * On a successful conversion, the transferData.result field will be set to
112: * OLE.S_OK. If this transfer agent is unable to perform the conversion, the
113: * transferData.result field will be set to the failure value of OLE.DV_E_TYMED.
114: */
115: protected void javaToNative(Object object, TransferData transferData) {
116: /**
117: * Transfer data is an array of markers. Serialized version is:
118: * (int) number of markers
119: * (Marker) marker 1
120: * (Marker) marker 2
121: * ... repeat last four for each subsequent marker
122: * see writeMarker for the (Marker) format.
123: */
124: Object[] markers = (Object[]) object;
125: lazyInit(markers);
126:
127: ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
128: DataOutputStream out = new DataOutputStream(byteOut);
129:
130: byte[] bytes = null;
131:
132: try {
133: /* write number of markers */
134: out.writeInt(markers.length);
135:
136: /* write markers */
137: for (int i = 0; i < markers.length; i++) {
138: writeMarker((IMarker) markers[i], out);
139: }
140: out.close();
141: bytes = byteOut.toByteArray();
142: } catch (IOException e) {
143: //when in doubt send nothing
144: }
145:
146: if (bytes != null) {
147: super .javaToNative(bytes, transferData);
148: }
149: }
150:
151: /**
152: * Initializes the transfer mechanism if necessary.
153: */
154: private void lazyInit(Object[] markers) {
155: if (workspace == null) {
156: if (markers != null && markers.length > 0) {
157: this .workspace = ((IMarker) markers[0]).getResource()
158: .getWorkspace();
159: }
160: }
161: }
162:
163: /* (non-Javadoc)
164: * Method declared on Transfer.
165: */
166: protected Object nativeToJava(TransferData transferData) {
167: byte[] bytes = (byte[]) super .nativeToJava(transferData);
168: DataInputStream in = new DataInputStream(
169: new ByteArrayInputStream(bytes));
170:
171: try {
172: /* read number of markers */
173: int n = in.readInt();
174:
175: /* read markers */
176: IMarker[] markers = new IMarker[n];
177: for (int i = 0; i < n; i++) {
178: IMarker marker = readMarker(in);
179: if (marker == null) {
180: return null;
181: }
182: markers[i] = marker;
183: }
184: return markers;
185: } catch (IOException e) {
186: return null;
187: }
188: }
189:
190: /**
191: * Reads and returns a single marker from the given stream.
192: *
193: * @param dataIn the input stream
194: * @return the marker
195: * @exception IOException if there is a problem reading from the stream
196: */
197: private IMarker readMarker(DataInputStream dataIn)
198: throws IOException {
199: /**
200: * Marker serialization format is as follows:
201: * (String) path of resource for marker
202: * (int) marker ID
203: */
204: String path = dataIn.readUTF();
205: long id = dataIn.readLong();
206: return findMarker(path, id);
207: }
208:
209: /**
210: * Writes the given marker to the given stream.
211: *
212: * @param marker the marker
213: * @param dataOut the output stream
214: * @exception IOException if there is a problem writing to the stream
215: */
216: private void writeMarker(IMarker marker, DataOutputStream dataOut)
217: throws IOException {
218: /**
219: * Marker serialization format is as follows:
220: * (String) path of resource for marker
221: * (int) marker ID
222: */
223:
224: dataOut.writeUTF(marker.getResource().getFullPath().toString());
225: dataOut.writeLong(marker.getId());
226: }
227: }
|