Home » Eclipse Projects » Eclipse Platform » [Howto] actually get Drag-and-Drop to work on a Viewer?
[Howto] actually get Drag-and-Drop to work on a Viewer? [message #28673] |
Wed, 07 May 2003 14:28  |
Eclipse User |
|
|
|
WinXp, R2.0.2
In a Plugin, trying to add DnD to various Viewers (we'd like to be able
to drag our internal data-type from Viewer to Viewer within our plugin;
it'd also be handy if we could handle people dragging text in from other
apps). I've read the Help (not much help -- I sucessfully added an
extension that seems never to get called), and the eclipse.tools
newsgroup (loads of messages, many answered by the ever-vigilant
Veronika Irvine), and these code snippets:
http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/
snippet78.html
snippet79.html
snippet84.html
snippet91.html
And I can't get anywhere (no drags, no drops, nada). Many people seem
to have gotten DnD to work on SWT stuff, but the interface for
"attaching" DnD to a Viewer is less well-covered in those messages and
snippets. What am I missing?
Thanks,
Paul K
here is everything I've done:
a) plugin.xml:
<extension
id="com.foo.bar.draganddrop"
name="the dragon drop"
point="org.eclipse.ui.dropActions">
<dropContribution>
<action
class="com.foo.bar.actions.Dropper"
id="com.foo.bar.dropAction">
</action>
</dropContribution>
</extension>
b) the action-delegate class (never gets called):
public class Dropper implements IDropActionDelegate {
public boolean run (Object source, Object target) {
System.err.println("Drop happens, from " +
source.getClass().getName() + " to " +
target.getClass().getName());
return false;
}
}
c) the "hookup" code in the Viewer-creation code (debugging sows it gets
called everytime one of the relevant viewers gets created):
protected void initDragAndDrop () {
final int ops = DND.DROP_COPY | DND.DROP_MOVE;
final Transfer[] transfers =
new Transfer[] {
NodeTransfer.getInstance()};
final TreeViewer viewer = getTreeViewer();
// note: NavigatorDragAdapter is a DragSourceAdapter
viewer.addDragSupport(
ops,
transfers,
new NavigatorDragAdapter((ISelectionProvider) viewer));
final NavigatorDropAdapter adapter = new
NavigatorDropAdapter(viewer);
adapter.setFeedbackEnabled(true);
viewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers,
adapter);
}
d) and the "NodeTransfer" class written according to the "snippets-spec"
(neither the javaToNative() nor the nativeToJava() method ever gets
called):
public class NodeTransfer extends ByteArrayTransfer {
public static class Data {
public Data (final String nodeID, final String nodesProject) {
_id = nodeID;
_proj = nodesProject;
}
public String id () {
return _id;
}
public String project () {
return _proj;
}
/**
* For use with default constructor and de-serialization in
nativeToJava()
*/
protected Data () {
}
/**
* For use with default constructor and de-serialization in
nativeToJava()
* @param id
*/
protected void setId (final String id) {
_id = id;
}
/**
* For use with default constructor and de-serialization in
nativeToJava()
* @param proj
*/
protected void setProject (final String proj) {
_proj = proj;
}
protected String _id;
protected String _proj;
}
/**
* Get the singleton instance of NodeTransfer
* @return NodeTransfer
*/
public static NodeTransfer getInstance () {
return _instance;
}
/**
* @see org.eclipse.swt.dnd.Transfer#getTypeIds()
*/
protected int[] getTypeIds () {
return new int[] { ID };
}
/**
* @see org.eclipse.swt.dnd.Transfer#getTypeNames()
*/
protected String[] getTypeNames () {
return new String[] { NAME };
}
/**
* @see org.eclipse.swt.dnd.ByteArrayTransfer#javaToNative(Object,
TransferData)
* code mostly copied from
http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/snippet79.html
*/
protected void javaToNative (final Object object, final TransferData
transferData) {
if (objectOK(object) && isSupportedType(transferData)) try {
final Data[] types = (Data[]) object;
// write data to a byte array and then ask super to convert
final ByteArrayOutputStream out = new
ByteArrayOutputStream();
final DataOutputStream writeOut = new DataOutputStream(out);
for (int i = 0, length = types.length; i < length; i++) {
writeString(types[i].id(), writeOut);
writeString(types[i].project(), writeOut);
}
final byte[] buffer = out.toByteArray();
writeOut.close();
super.javaToNative(buffer, transferData);
} catch (IOException ioe) {
}
}
/**
* @see
org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(TransferD ata)
*/
protected Object nativeToJava (final TransferData transferData) {
if (isSupportedType(transferData)) {
final byte[] buffer = (byte[])
super.nativeToJava(transferData);
if (null == buffer) {
return null;
}
try {
final Vector data = new Vector();
final ByteArrayInputStream in = new
ByteArrayInputStream(buffer);
final DataInputStream readIn = new DataInputStream(in);
while (readIn.available() > 20) {
Data datum = new Data();
data.add(datum);
datum.setId(readString(readIn));
datum.setProject(readString(readIn));
}
readIn.close();
} catch (IOException ioe) {
}
}
return super.nativeToJava(transferData);
}
/**
* Checks to see if the Object handed to javaToNative() is one we
handle
* @param object
* @return boolean
*/
protected boolean objectOK (final Object object) {
return ((null != object) && (object instanceof
NodeTransfer.Data[]));
}
/**
* Read a String from the given DataInputStream
* @param readIn the non-null DataInputStream
* @return String
* @throws IOException
*/
protected String readString (final DataInputStream readIn) throws
IOException {
int size = readIn.readInt();
byte[] name = new byte[size];
readIn.read(name);
return new String(name);
}
/**
* Write the given String to the given DataOutputStream in the proper
format
* (int length followed by bytes of String)
* @param string the non-null String
* @param dos the non-null DataOutputStream
* @throws IOException
*/
protected void writeString (final String string, final
DataOutputStream dos) throws IOException {
byte[] buffer = string.getBytes();
dos.writeInt(buffer.length);
dos.write(buffer);
}
protected static final NodeTransfer _instance = new NodeTransfer();
protected static final String NAME =
NodeTransfer.Data.class.getName();
protected static final int ID = registerType(NAME);
}
|
|
| |
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #29078 is a reply to message #28673] |
Thu, 08 May 2003 17:14   |
Eclipse User |
|
|
|
Originally posted by: John_Arthorne.oti.com_
Have a look at ViewerDropAdapter, and StructuredViewer.addDragSupport,
StructuredViewer.addDropSupport. You probably don't need the plugin
dropAction extension point stuff. You can refer to
NavigatorDrag/DropAdapter as an example implementation.
--
Paul T. Keyser wrote:
> WinXp, R2.0.2
>
> In a Plugin, trying to add DnD to various Viewers (we'd like to be able
> to drag our internal data-type from Viewer to Viewer within our plugin;
> it'd also be handy if we could handle people dragging text in from other
> apps). I've read the Help (not much help -- I sucessfully added an
> extension that seems never to get called), and the eclipse.tools
> newsgroup (loads of messages, many answered by the ever-vigilant
> Veronika Irvine), and these code snippets:
>
> http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/
>
> snippet78.html
> snippet79.html
> snippet84.html
> snippet91.html
>
> And I can't get anywhere (no drags, no drops, nada). Many people seem
> to have gotten DnD to work on SWT stuff, but the interface for
> "attaching" DnD to a Viewer is less well-covered in those messages and
> snippets. What am I missing?
>
> Thanks,
> Paul K
>
> here is everything I've done:
> a) plugin.xml:
> <extension
> id="com.foo.bar.draganddrop"
> name="the dragon drop"
> point="org.eclipse.ui.dropActions">
> <dropContribution>
> <action
> class="com.foo.bar.actions.Dropper"
> id="com.foo.bar.dropAction">
> </action>
> </dropContribution>
> </extension>
>
> b) the action-delegate class (never gets called):
> public class Dropper implements IDropActionDelegate {
> public boolean run (Object source, Object target) {
> System.err.println("Drop happens, from " +
> source.getClass().getName() + " to " +
> target.getClass().getName());
> return false;
> }
> }
>
> c) the "hookup" code in the Viewer-creation code (debugging sows it gets
> called everytime one of the relevant viewers gets created):
> protected void initDragAndDrop () {
> final int ops = DND.DROP_COPY | DND.DROP_MOVE;
> final Transfer[] transfers =
> new Transfer[] {
> NodeTransfer.getInstance()};
> final TreeViewer viewer = getTreeViewer();
> // note: NavigatorDragAdapter is a DragSourceAdapter
> viewer.addDragSupport(
> ops,
> transfers,
> new NavigatorDragAdapter((ISelectionProvider) viewer));
> final NavigatorDropAdapter adapter = new
> NavigatorDropAdapter(viewer);
> adapter.setFeedbackEnabled(true);
> viewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers,
> adapter);
> }
>
> d) and the "NodeTransfer" class written according to the "snippets-spec"
> (neither the javaToNative() nor the nativeToJava() method ever gets
> called):
>
> public class NodeTransfer extends ByteArrayTransfer {
>
> public static class Data {
> public Data (final String nodeID, final String nodesProject) {
> _id = nodeID;
> _proj = nodesProject;
> }
> public String id () {
> return _id;
> }
> public String project () {
> return _proj;
> }
> /**
> * For use with default constructor and de-serialization in
> nativeToJava()
> */
> protected Data () {
> }
> /**
> * For use with default constructor and de-serialization in
> nativeToJava()
> * @param id
> */
> protected void setId (final String id) {
> _id = id;
> }
> /**
> * For use with default constructor and de-serialization in
> nativeToJava()
> * @param proj
> */
> protected void setProject (final String proj) {
> _proj = proj;
> }
> protected String _id;
> protected String _proj;
> }
>
> /**
> * Get the singleton instance of NodeTransfer
> * @return NodeTransfer
> */
> public static NodeTransfer getInstance () {
> return _instance;
> }
>
> /**
> * @see org.eclipse.swt.dnd.Transfer#getTypeIds()
> */
> protected int[] getTypeIds () {
> return new int[] { ID };
> }
>
> /**
> * @see org.eclipse.swt.dnd.Transfer#getTypeNames()
> */
> protected String[] getTypeNames () {
> return new String[] { NAME };
> }
>
> /**
> * @see org.eclipse.swt.dnd.ByteArrayTransfer#javaToNative(Object,
> TransferData)
> * code mostly copied from
> http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/snippet79.html
>
> */
> protected void javaToNative (final Object object, final TransferData
> transferData) {
> if (objectOK(object) && isSupportedType(transferData)) try {
> final Data[] types = (Data[]) object;
> // write data to a byte array and then ask super to convert
> final ByteArrayOutputStream out = new
> ByteArrayOutputStream();
> final DataOutputStream writeOut = new DataOutputStream(out);
>
> for (int i = 0, length = types.length; i < length; i++) {
> writeString(types[i].id(), writeOut);
> writeString(types[i].project(), writeOut);
> }
> final byte[] buffer = out.toByteArray();
> writeOut.close();
>
> super.javaToNative(buffer, transferData);
>
> } catch (IOException ioe) {
> }
> }
>
> /**
> * @see
> org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(TransferD ata)
> */
> protected Object nativeToJava (final TransferData transferData) {
> if (isSupportedType(transferData)) {
> final byte[] buffer = (byte[])
> super.nativeToJava(transferData);
> if (null == buffer) {
> return null;
> }
> try {
> final Vector data = new Vector();
> final ByteArrayInputStream in = new
> ByteArrayInputStream(buffer);
> final DataInputStream readIn = new DataInputStream(in);
> while (readIn.available() > 20) {
> Data datum = new Data();
> data.add(datum);
> datum.setId(readString(readIn));
> datum.setProject(readString(readIn));
> }
> readIn.close();
>
> } catch (IOException ioe) {
> }
> }
> return super.nativeToJava(transferData);
> }
>
> /**
> * Checks to see if the Object handed to javaToNative() is one we
> handle
> * @param object
> * @return boolean
> */
> protected boolean objectOK (final Object object) {
> return ((null != object) && (object instanceof
> NodeTransfer.Data[]));
> }
>
> /**
> * Read a String from the given DataInputStream
> * @param readIn the non-null DataInputStream
> * @return String
> * @throws IOException
> */
> protected String readString (final DataInputStream readIn) throws
> IOException {
> int size = readIn.readInt();
> byte[] name = new byte[size];
> readIn.read(name);
> return new String(name);
> }
>
> /**
> * Write the given String to the given DataOutputStream in the proper
> format
> * (int length followed by bytes of String)
> * @param string the non-null String
> * @param dos the non-null DataOutputStream
> * @throws IOException
> */
> protected void writeString (final String string, final
> DataOutputStream dos) throws IOException {
> byte[] buffer = string.getBytes();
> dos.writeInt(buffer.length);
> dos.write(buffer);
> }
>
> protected static final NodeTransfer _instance = new NodeTransfer();
>
> protected static final String NAME =
> NodeTransfer.Data.class.getName();
> protected static final int ID = registerType(NAME);
> }
>
>
|
|
|
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #29670 is a reply to message #29078] |
Fri, 09 May 2003 11:34   |
Eclipse User |
|
|
|
Right -- just about the time you were writing your note, I was pair-programming and finding that very
class (ViewerDropAdapter); the failure of the event.data to be non-null was caused by my
misunderstanding of what the event.data field was used for (it has to be the same type as that expected
by our ByteArrayTransfer subclass).
I'm still, however, unclear on the relation b/w the extension point for draggery and all this (purely
java) stuff -- seems like they are unrelated, but then what is the extension point for? Handling drags
from other apps? Allowing future plugins to write draggers that we understand?
Thanks,
Paul K
John Arthorne wrote:
> Have a look at ViewerDropAdapter, and StructuredViewer.addDragSupport,
> StructuredViewer.addDropSupport. You probably don't need the plugin
> dropAction extension point stuff. You can refer to
> NavigatorDrag/DropAdapter as an example implementation.
> --
>
> Paul T. Keyser wrote:
> > WinXp, R2.0.2
> >
> > In a Plugin, trying to add DnD to various Viewers (we'd like to be able
> > to drag our internal data-type from Viewer to Viewer within our plugin;
> > it'd also be handy if we could handle people dragging text in from other
> > apps). I've read the Help (not much help -- I sucessfully added an
> > extension that seems never to get called), and the eclipse.tools
> > newsgroup (loads of messages, many answered by the ever-vigilant
> > Veronika Irvine), and these code snippets:
> >
> > http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/
> >
> > snippet78.html
> > snippet79.html
> > snippet84.html
> > snippet91.html
> >
> > And I can't get anywhere (no drags, no drops, nada). Many people seem
> > to have gotten DnD to work on SWT stuff, but the interface for
> > "attaching" DnD to a Viewer is less well-covered in those messages and
> > snippets. What am I missing?
> >
> > Thanks,
> > Paul K
> >
> > here is everything I've done:
> > a) plugin.xml:
> > <extension
> > id="com.foo.bar.draganddrop"
> > name="the dragon drop"
> > point="org.eclipse.ui.dropActions">
> > <dropContribution>
> > <action
> > class="com.foo.bar.actions.Dropper"
> > id="com.foo.bar.dropAction">
> > </action>
> > </dropContribution>
> > </extension>
> >
> > b) the action-delegate class (never gets called):
> > public class Dropper implements IDropActionDelegate {
> > public boolean run (Object source, Object target) {
> > System.err.println("Drop happens, from " +
> > source.getClass().getName() + " to " +
> > target.getClass().getName());
> > return false;
> > }
> > }
> >
> > c) the "hookup" code in the Viewer-creation code (debugging sows it gets
> > called everytime one of the relevant viewers gets created):
> > protected void initDragAndDrop () {
> > final int ops = DND.DROP_COPY | DND.DROP_MOVE;
> > final Transfer[] transfers =
> > new Transfer[] {
> > NodeTransfer.getInstance()};
> > final TreeViewer viewer = getTreeViewer();
> > // note: NavigatorDragAdapter is a DragSourceAdapter
> > viewer.addDragSupport(
> > ops,
> > transfers,
> > new NavigatorDragAdapter((ISelectionProvider) viewer));
> > final NavigatorDropAdapter adapter = new
> > NavigatorDropAdapter(viewer);
> > adapter.setFeedbackEnabled(true);
> > viewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers,
> > adapter);
> > }
> >
> > d) and the "NodeTransfer" class written according to the "snippets-spec"
> > (neither the javaToNative() nor the nativeToJava() method ever gets
> > called):
> >
> > public class NodeTransfer extends ByteArrayTransfer {
> >
> > public static class Data {
> > public Data (final String nodeID, final String nodesProject) {
> > _id = nodeID;
> > _proj = nodesProject;
> > }
> > public String id () {
> > return _id;
> > }
> > public String project () {
> > return _proj;
> > }
> > /**
> > * For use with default constructor and de-serialization in
> > nativeToJava()
> > */
> > protected Data () {
> > }
> > /**
> > * For use with default constructor and de-serialization in
> > nativeToJava()
> > * @param id
> > */
> > protected void setId (final String id) {
> > _id = id;
> > }
> > /**
> > * For use with default constructor and de-serialization in
> > nativeToJava()
> > * @param proj
> > */
> > protected void setProject (final String proj) {
> > _proj = proj;
> > }
> > protected String _id;
> > protected String _proj;
> > }
> >
> > /**
> > * Get the singleton instance of NodeTransfer
> > * @return NodeTransfer
> > */
> > public static NodeTransfer getInstance () {
> > return _instance;
> > }
> >
> > /**
> > * @see org.eclipse.swt.dnd.Transfer#getTypeIds()
> > */
> > protected int[] getTypeIds () {
> > return new int[] { ID };
> > }
> >
> > /**
> > * @see org.eclipse.swt.dnd.Transfer#getTypeNames()
> > */
> > protected String[] getTypeNames () {
> > return new String[] { NAME };
> > }
> >
> > /**
> > * @see org.eclipse.swt.dnd.ByteArrayTransfer#javaToNative(Object,
> > TransferData)
> > * code mostly copied from
> > http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/snippet79.html
> >
> > */
> > protected void javaToNative (final Object object, final TransferData
> > transferData) {
> > if (objectOK(object) && isSupportedType(transferData)) try {
> > final Data[] types = (Data[]) object;
> > // write data to a byte array and then ask super to convert
> > final ByteArrayOutputStream out = new
> > ByteArrayOutputStream();
> > final DataOutputStream writeOut = new DataOutputStream(out);
> >
> > for (int i = 0, length = types.length; i < length; i++) {
> > writeString(types[i].id(), writeOut);
> > writeString(types[i].project(), writeOut);
> > }
> > final byte[] buffer = out.toByteArray();
> > writeOut.close();
> >
> > super.javaToNative(buffer, transferData);
> >
> > } catch (IOException ioe) {
> > }
> > }
> >
> > /**
> > * @see
> > org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(TransferD ata)
> > */
> > protected Object nativeToJava (final TransferData transferData) {
> > if (isSupportedType(transferData)) {
> > final byte[] buffer = (byte[])
> > super.nativeToJava(transferData);
> > if (null == buffer) {
> > return null;
> > }
> > try {
> > final Vector data = new Vector();
> > final ByteArrayInputStream in = new
> > ByteArrayInputStream(buffer);
> > final DataInputStream readIn = new DataInputStream(in);
> > while (readIn.available() > 20) {
> > Data datum = new Data();
> > data.add(datum);
> > datum.setId(readString(readIn));
> > datum.setProject(readString(readIn));
> > }
> > readIn.close();
> >
> > } catch (IOException ioe) {
> > }
> > }
> > return super.nativeToJava(transferData);
> > }
> >
> > /**
> > * Checks to see if the Object handed to javaToNative() is one we
> > handle
> > * @param object
> > * @return boolean
> > */
> > protected boolean objectOK (final Object object) {
> > return ((null != object) && (object instanceof
> > NodeTransfer.Data[]));
> > }
> >
> > /**
> > * Read a String from the given DataInputStream
> > * @param readIn the non-null DataInputStream
> > * @return String
> > * @throws IOException
> > */
> > protected String readString (final DataInputStream readIn) throws
> > IOException {
> > int size = readIn.readInt();
> > byte[] name = new byte[size];
> > readIn.read(name);
> > return new String(name);
> > }
> >
> > /**
> > * Write the given String to the given DataOutputStream in the proper
> > format
> > * (int length followed by bytes of String)
> > * @param string the non-null String
> > * @param dos the non-null DataOutputStream
> > * @throws IOException
> > */
> > protected void writeString (final String string, final
> > DataOutputStream dos) throws IOException {
> > byte[] buffer = string.getBytes();
> > dos.writeInt(buffer.length);
> > dos.write(buffer);
> > }
> >
> > protected static final NodeTransfer _instance = new NodeTransfer();
> >
> > protected static final String NAME =
> > NodeTransfer.Data.class.getName();
> > protected static final int ID = registerType(NAME);
> > }
> >
> >
|
|
| |
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #29822 is a reply to message #29681] |
Mon, 12 May 2003 10:51   |
Eclipse User |
|
|
|
Um, well, I did read those docs, and that is part of what mislead me (my own stupidity being the rest) -- I
spent a day or so trying to get a DropActionDelegate class to work, and while it did compile, I could never
get it even to be called (let alone do anything). As far as I can tell, those docs talk about an extension
point that is orthogonal to what I am doing (i.e., it is not needed for what I am doing, and it does not use
what I am doing), and do not explain how/where/when/why one would use that extension point (I'm sorry, but
they just don't). I do have the examples plugins (they came with the 2.0.2 download), so I'd be glad to take
a look at the ReadmeDropActionDelegate or the ReadmeContentOutlineDragListener mentioned in the Help docs --
but I can't find those classes (Open Type does not recognize the names).
Meanwhile I have run afoul of another point in the {DragSource, DropTarget}Listener mechanism -- apparently,
the event.data in the DropTargetListener is not set until the user releases the mouse. That seems to be
confirmed by the javadocs for the methods of DropTargetListener, which list (for each method) the fields of
DropTargetEvent that "apply": the "data" field only "applies" to the drop() method (debugging seems to
confirm this, as event.data remains null, even in dropAccept(), until drop() is called). Is there any
workaround for this? I need to be able to access that data earlier in the lifecycle of a drag/drop, in
particular during dragOver(), so as the user drags things around I can correctly update whether or not the
selected items can be dropped on the current target. (That might vary depending not only on the target, but
also the items selected.)
Thanks,
Paul K
John Arthorne wrote:
> I suggest reading the extension point documentation for
> org.eclipse.ui.dropActions ((Help > Contents > Plugin Developer Guide >
> Reference > Extension points reference > Workbench). The UI readme
> example also includes an implementation of a plugin dropAction.
> --
>
> Paul T. Keyser wrote:
> > I'm still, however, unclear on the relation b/w the extension point for draggery and all this (purely
> > java) stuff -- seems like they are unrelated, but then what is the extension point for? Handling drags
> > from other apps? Allowing future plugins to write draggers that we understand?
|
|
|
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #31787 is a reply to message #29822] |
Wed, 14 May 2003 11:32   |
Eclipse User |
|
|
|
Originally posted by: John_Arthorne.oti.com_
Paul T. Keyser wrote:
> Um, well, I did read those docs, and that is part of what mislead me (my own stupidity being the rest) -- I
> spent a day or so trying to get a DropActionDelegate class to work, and while it did compile, I could never
> get it even to be called (let alone do anything). As far as I can tell, those docs talk about an extension
> point that is orthogonal to what I am doing (i.e., it is not needed for what I am doing, and it does not use
> what I am doing), and do not explain how/where/when/why one would use that extension point (I'm sorry, but
> they just don't). I do have the examples plugins (they came with the 2.0.2 download), so I'd be glad to take
> a look at the ReadmeDropActionDelegate or the ReadmeContentOutlineDragListener mentioned in the Help docs --
> but I can't find those classes (Open Type does not recognize the names).
The extension point is used to drop objects onto a viewer that doesn't
know anything about those objects. For example, you want to drop "Foo"
objects into the Navigator view, but the Navigator doesn't know anything
about "Foo" objects. The dropActions extension point delegates the drop
behaviour back to the viewer that initiated the drag. To view the
readme example code, you need to import the readme project into your
workspace... it's not sufficient to just have the example installed.
Checkout the readme example project from dev.eclipse.org, or import the
plugin into your workspace.
>
> Meanwhile I have run afoul of another point in the {DragSource, DropTarget}Listener mechanism -- apparently,
> the event.data in the DropTargetListener is not set until the user releases the mouse. That seems to be
> confirmed by the javadocs for the methods of DropTargetListener, which list (for each method) the fields of
> DropTargetEvent that "apply": the "data" field only "applies" to the drop() method (debugging seems to
> confirm this, as event.data remains null, even in dropAccept(), until drop() is called). Is there any
> workaround for this? I need to be able to access that data earlier in the lifecycle of a drag/drop, in
> particular during dragOver(), so as the user drags things around I can correctly update whether or not the
> selected items can be dropped on the current target. (That might vary depending not only on the target, but
> also the items selected.)
No, this is fundamental to how the SWT drag and drop support works. For
performance, it can't make the data available during the drag. Keep in
mind that drag and drop may be occurring between two different
applications and transferring the data is not always trivial. If you
know where the data is coming from, you can "cheat" by storing the
object being dragged in some well known place, and then sneak a peek at
it during the dragOver event. You can see how the Navigator does this
with the org.eclipse.ui.views.navigator.LocalSelectionTransfer object.
--
|
|
|
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #32588 is a reply to message #31787] |
Wed, 14 May 2003 18:14   |
Eclipse User |
|
|
|
I'll try those two suggestions (import to view; cheat on the framework).
Thanks,
Paul K
John Arthorne wrote:
> Paul T. Keyser wrote:
> > Um, well, I did read those docs, and that is part of what mislead me (my own stupidity being the rest) -- I
> > spent a day or so trying to get a DropActionDelegate class to work, and while it did compile, I could never
> > get it even to be called (let alone do anything). As far as I can tell, those docs talk about an extension
> > point that is orthogonal to what I am doing (i.e., it is not needed for what I am doing, and it does not use
> > what I am doing), and do not explain how/where/when/why one would use that extension point (I'm sorry, but
> > they just don't). I do have the examples plugins (they came with the 2.0.2 download), so I'd be glad to take
> > a look at the ReadmeDropActionDelegate or the ReadmeContentOutlineDragListener mentioned in the Help docs --
> > but I can't find those classes (Open Type does not recognize the names).
>
> The extension point is used to drop objects onto a viewer that doesn't
> know anything about those objects. For example, you want to drop "Foo"
> objects into the Navigator view, but the Navigator doesn't know anything
> about "Foo" objects. The dropActions extension point delegates the drop
> behaviour back to the viewer that initiated the drag. To view the
> readme example code, you need to import the readme project into your
> workspace... it's not sufficient to just have the example installed.
> Checkout the readme example project from dev.eclipse.org, or import the
> plugin into your workspace.
>
> >
> > Meanwhile I have run afoul of another point in the {DragSource, DropTarget}Listener mechanism -- apparently,
> > the event.data in the DropTargetListener is not set until the user releases the mouse. That seems to be
> > confirmed by the javadocs for the methods of DropTargetListener, which list (for each method) the fields of
> > DropTargetEvent that "apply": the "data" field only "applies" to the drop() method (debugging seems to
> > confirm this, as event.data remains null, even in dropAccept(), until drop() is called). Is there any
> > workaround for this? I need to be able to access that data earlier in the lifecycle of a drag/drop, in
> > particular during dragOver(), so as the user drags things around I can correctly update whether or not the
> > selected items can be dropped on the current target. (That might vary depending not only on the target, but
> > also the items selected.)
>
> No, this is fundamental to how the SWT drag and drop support works. For
> performance, it can't make the data available during the drag. Keep in
> mind that drag and drop may be occurring between two different
> applications and transferring the data is not always trivial. If you
> know where the data is coming from, you can "cheat" by storing the
> object being dragged in some well known place, and then sneak a peek at
> it during the dragOver event. You can see how the Navigator does this
> with the org.eclipse.ui.views.navigator.LocalSelectionTransfer object.
> --
|
|
|
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #34295 is a reply to message #31787] |
Thu, 15 May 2003 16:36   |
Eclipse User |
|
|
|
This is a multi-part message in MIME format.
--------------516E4B74EA8CD0DC49D3D0E7
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
OK, I did look at the readmetool code, and in the ReadmeContentOutlineDragListener I found some
code that "corresponded" (as I see it) with some code in NavigatorDropAdapter; both bits of code seem
relevant to my current Dnd-problem.
I have two Transfer classes derived from ByteArrayTransfer; sometimes I want to use one, sometimes
the other; unfortunately, I don't understand how to get the Eclipse Dnd-code to allow that (I can use one
or the other, but if I use both, I get an OutOfMemoryError, no callstack, and the dire warning that I'd
better close my runtime Eclipse).
=========================================================
In org.eclipse.ui.examples.readmetool.ReadmeContentOutlineDragL istener, I find:
public void dragSetData(DragSourceEvent event) {
if (PluginTransfer.getInstance().isSupportedType(event.dataType )) {
byte[] segmentData = getSegmentText().getBytes();
event.data = new PluginTransferData(ReadmeDropActionDelegate.ID, segmentData);
return;
}
if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
event.data = getSegmentText();
return;
}
}
and in org.eclipse.ui.views.navigator.NavigatorDropAdapter.performD rop() I find:
final TransferData currentTransfer = getCurrentTransfer();
if (ResourceTransfer.getInstance().isSupportedType(currentTrans fer) &&
getCurrentOperation() == DND.DROP_COPY) {
status[0] = performResourceCopy(getShell(), data);
//always return false because we don't want the source to clean up
result[0] = false;
} else {
// code creating an IRunnableWithProgress, inside of which is:
if (ResourceTransfer.getInstance().isSupportedType(currentTrans fer)) {
status[0] = performResourceMove(monitor, data);
//always return false because we don't want the source to clean up
result[0] = false;
} else if (FileTransfer.getInstance().isSupportedType(currentTransfer) ) {
status[0] = performFileDrop(monitor, data);
result[0] = status[0].isOK();
} else {
result[0] = NavigatorDropAdapter.super.performDrop(data);
}
The common denominator here is that when creating (in dragSetData()) or using (in performDrop()) the
event.data, it seems to be possible to query the TransferData instance to see what type it is, and
respond accordingly. This seems somehow to work, although no org.eclipse subclass of the
ByteArrayTransfer overrides the method isSupportedType().
=========================================================
But when I debug through the actually-executing code, I find the following sequence of operations:
a) dragSetData()
b) DragSource.GetData(), lines 378 ff. always gets the *first* Transfer that passes the test (which
when I use the *second* of my ByteArrayTransfer subclasses, is thus the *wrong* one) and so the
"FirstTransfer" calls its javaToNative() with event.data that is appropriate for type "SecondTransfer":
// get matching transfer agent to perform conversion
Transfer transfer = null;
for (int i = 0; i < transferAgents.length; i++){
if (transferAgents[i].isSupportedType(event.dataType )){
transfer = transferAgents[i];
break;
}
}
if (transfer == null) return COM.DV_E_FORMATETC;
transfer.javaToNative(event.data, transferData);
c) Because the two types, "FirstTransfer" and "SecondTransfer", delegate the actual writing to the
DataOutputStream in javaToNative() to a "Data" class, and the event.data are of the Data-subtype
associated with SecondTransfer, dynamic dispatch ensures that the correct bytes are written.
d) after rattling through various low-level calls, the execution arrives at my implementation of
Transfer.nativeToJava(), but of course in the wrong class (FirstTransfer, not SecondTransfer);
now since I am creating a new object of the "Data"-class, dynamic dispatch delegates to my
(First: wrong!)Transfer class' makeData() method, and then the wrong set of read methods are
called ...
e) OutOfMemoryError!
Now I understand that it is possible that I've done something wrong in my implementations
of the Transfer classes (attached, just FYI); but I still don't get how the code above in
DragSource (or that in the ReadmeContentOutlineDragListener or NavigatorDropAdapter, above)
can manage to allow the use of more than one type of Transfer.
Thanks,
Paul K
--------------516E4B74EA8CD0DC49D3D0E7
Content-Type: text/plain; charset=us-ascii;
name="ProtoTransfer .java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="ProtoTransfer .java"
/**
* ProtoTransfer is a ReferableTransfer that allows
* dragging-and-dropping of prototype Nodes
*
* @author Keyser
*/
public class ProtoTransfer extends ReferableTransfer {
/**
* ProData is a triple {type, hash, project} (via which it can access the proto-Node)
*
* @author Keyser
*/
public static class ProData extends Data {
/**
* Create a ProData for the given proto-Node
* @param proto, a non-null proto-Node
*/
public ProData (final Node proto) {
_type = proto.getType();
_hash = proto.hashCode();
_proj = Context.current().getEngagement();
}
public Referable retrieve () {
System.err.println("\t ProData.retrieve(" + _type + ", " + _hash + ")");
final Iterator candidates = Model.iterator(_type, _proj);
while (candidates.hasNext()) {
final Node node = (Node) candidates.next();
if (node.hashCode() == _hash) {
return (Referable) node;
}
}
return null; // @@ somehow seems wrong ...
}
public String toString () {
return "[PROTO: " + _type + "(" + _hash + ")" + ", in: " + _proj + "]";
}
/**
* Create a Data[] from a Collection of Nodes
* @param input, a non-null Collection of Nodes
* @return Data[]
* @throws ClassCastException if the Collection contains other than Nodes
*/
public static Data[] toArrayFromNodes (final Collection input) {
final Vector data = new Vector();
final Iterator nodes = input.iterator();
while (nodes.hasNext()) {
data.add(new ProData((Node) nodes.next()));
}
return toArray(data);
}
protected ProData () {
}
protected void init (final DataInputStream readIn) throws IOException {
_type = readString(readIn);
_hash = readIn.readInt();
_proj = readString(readIn);
}
protected void writeOut (final DataOutputStream writeOut) throws IOException {
writeString(_type, writeOut);
writeOut.writeInt(_hash);
writeString(_proj, writeOut);
}
protected String _type;
protected String _proj;
protected int _hash;
}
/**
* Get the singleton instance of ProtoTransfer
* @return ProtoTransfer
*/
public static ProtoTransfer getInstance () {
return _instance;
}
/**
* @see org.eclipse.swt.dnd.Transfer#getTypeIds()
*/
protected final int[] getTypeIds () {
return new int[] { ID };
}
/**
* @see org.eclipse.swt.dnd.Transfer#getTypeNames()
*/
protected final String[] getTypeNames () {
return new String[] { NAME };
}
/**
* @see ReferableTransfer#makeData()
*/
protected Data makeData () {
return new ProData();
}
protected static final ProtoTransfer _instance = new ProtoTransfer();
protected static final String NAME = ProData.class.getName();
protected static final int ID = registerType(NAME);
}
--------------516E4B74EA8CD0DC49D3D0E7
Content-Type: text/plain; charset=us-ascii;
name="ReferableTransfer .java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="ReferableTransfer .java"
/**
* ReferableTransfer is a ByteArrayTransfer that enables the drag-and-dropping of Referables
*
* code for this and subclasses mostly copied from
* http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/plat form-swt-home/snippits/snippet79.html
*
* @author Keyser
*/
public abstract class ReferableTransfer extends ByteArrayTransfer {
/**
* Data is the abstract base class of classes that are "pointers" to Model-elements
*
* implementers should be sure to provide a (protected) default constructor
* for use in ReferableTransfer.makeData()
*
* @author Keyser
*/
public static abstract class Data {
/**
* Create a Data[] from a Collection of Data
* @param data
* @return Data[]
*/
public static Data[] toArray (final Collection data) {
return (Data[]) data.toArray(EMPTY_ARRAY);
}
/**
* Retrieve from the Model the Referable to which this Data points
* @return Referable
*/
public abstract Referable retrieve () ;
/**
* Write out this Data to the given DataOutputStream (for javaToNative())
* implementers should be sure to make this the inverse of init()!
* @param writeOut a DataOutputStream
* @throws IOException
*/
protected abstract void writeOut (final DataOutputStream writeOut) throws IOException ;
/**
* Initialise this Data from the given DataInputStream (for nativeToJava())
* implementers should be sure to make this the inverse of writeOut()!
* @param readIn a DataInputStream
*/
protected abstract void init (final DataInputStream readIn) throws IOException ;
/**
* Read a String from the given DataInputStream
* @param readIn the non-null DataInputStream
* @return String
* @throws IOException
*/
protected final String readString (final DataInputStream readIn) throws IOException {
int size = readIn.readInt();
byte[] name = new byte[size];
readIn.read(name);
return new String(name);
}
/**
* Write the given String to the given DataOutputStream in the proper format
* (int length followed by bytes of String)
* @param string the non-null String
* @param dos the non-null DataOutputStream
* @throws IOException
*/
protected final void writeString(
final String string,
final DataOutputStream dos
) throws IOException {
byte[] buffer = string.getBytes();
dos.writeInt(buffer.length);
dos.write(buffer);
}
protected static final Data[] EMPTY_ARRAY = new Data[0];
}
/**
* Make a blank instance of the appropriate extension of Data
* @return Data, uninitialised
*/
protected abstract Data makeData () ;
/**
* @see org.eclipse.swt.dnd.ByteArrayTransfer#javaToNative(Object, TransferData)
*/
protected final void javaToNative (final Object object, final TransferData transferData) {
if (objectOK(object) && isSupportedType(transferData)) try {
final Data[] types = (Data[]) object;
// write data to a byte array and then ask super to convert
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final DataOutputStream writeOut = new DataOutputStream(out);
for (int i = 0; i < types.length; ++i) {
types[i].writeOut(writeOut);
}
final byte[] buffer = out.toByteArray();
writeOut.close();
super.javaToNative(buffer, transferData);
} catch (IOException ioe) {
}
}
/**
* @see org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(TransferD ata)
*/
protected final Object nativeToJava (final TransferData transferData) {
if (isSupportedType(transferData)) {
final byte[] buffer = (byte[]) super.nativeToJava(transferData);
if (null != buffer) try {
final Vector data = new Vector();
final ByteArrayInputStream in =
new ByteArrayInputStream(buffer);
final DataInputStream readIn = new DataInputStream(in);
while (readIn.available() > 20) {
final Data datum = makeData();
datum.init(readIn);
data.add(datum);
}
readIn.close();
return Data.toArray(data);
} catch (IOException ioe) {
}
}
return null; // not our type: not our problem
}
/**
* Is the Object handed to javaToNative() one of ours?
* @param object, must be an instanceof Data[], for us to be interested
* @return boolean
*/
protected final boolean objectOK (final Object object) {
return ((null != object) && (object instanceof Data[]));
}
}
--------------516E4B74EA8CD0DC49D3D0E7
Content-Type: text/plain; charset=us-ascii;
name="ExistingTransfer .java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="ExistingTransfer .java"
/**
* ReferableTransfer is an ReferableTransfer that allows
* dragging-and-dropping of existing Nodes and Relations in the Model;
*
* @author Keyser
*/
public class ExistingTransfer extends ReferableTransfer {
/**
* RefData is a pair of id and project (via which it can access the Referable)
*
* @author Keyser
*/
public static class RefData extends Data {
/**
* Create a RefData for the given Referable
* @param ref, a non-null existing Referable
*/
public RefData (final Referable ref) {
_id = ref.getID();
_isNode = (ref instanceof Node);
_proj = Context.current().getEngagement();
}
public Referable retrieve () { // @@ in fact ignoring multi-project just now
return _isNode
? (Referable) Model.findNode(_id)
: (Referable) Model.findRelation(_id);
}
public String toString () {
return "["
+ _id
+ "("
+ (_isNode ? "Node" : "Rel")
+ "), in: "
+ _proj
+ "]";
}
/**
* Create a Data[] from a Collection of Referables
* @param input, a non-null Collection of Referables
* @return Data[]
* @throws ClassCastException if the Collection contains other than Referables
*/
public static Data[] toArrayFromReferables (final Collection input) {
final Vector data = new Vector();
final Iterator refs = input.iterator();
while (refs.hasNext()) {
data.add(new RefData((Referable) refs.next()));
}
return toArray(data);
}
protected RefData () {
}
protected void init (final DataInputStream readIn) throws IOException {
_id = readString(readIn);
_isNode = readIn.readBoolean();
_proj = readString(readIn);
}
protected void writeOut(DataOutputStream writeOut) throws IOException {
writeString(_id, writeOut);
writeOut.writeBoolean(_isNode);
writeString(_proj, writeOut);
}
protected String _id;
protected String _proj;
protected boolean _isNode;
}
/**
* Get the singleton instance of ReferableTransfer
* @return ReferableTransfer
*/
public static ExistingTransfer getInstance () {
return _instance;
}
/**
* @see org.eclipse.swt.dnd.Transfer#getTypeIds()
*/
protected final int[] getTypeIds () {
return new int[] { ID };
}
/**
* @see org.eclipse.swt.dnd.Transfer#getTypeNames()
*/
protected final String[] getTypeNames () {
return new String[] { NAME };
}
/**
* @see ReferableTransfer#makeData()
*/
protected Data makeData () {
return new RefData();
}
protected static final ExistingTransfer _instance = new ExistingTransfer();
protected static final String NAME = RefData.class.getName();
protected static final int ID = registerType(NAME);
}
--------------516E4B74EA8CD0DC49D3D0E7--
|
|
|
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #37943 is a reply to message #31787] |
Mon, 19 May 2003 10:30   |
Eclipse User |
|
|
|
Hmm -- I have both org.eclipse.ui, plus ui.win32, imported as a "binary project" (kind of had to to get the
classpath stuff to work at all), and eclipse 2.0.2 has no other plugins in the plugins directory named
org.eclipse.ui.* (exc. the xamples and the external tools), but I still cannot "see" (in Ctrl-Shift-T) the class
LocalSelectionTransfer -- what am I doing wrong?
thanks,
Paul K
John Arthorne wrote:
> No, this is fundamental to how the SWT drag and drop support works. For
> performance, it can't make the data available during the drag. Keep in
> mind that drag and drop may be occurring between two different
> applications and transferring the data is not always trivial. If you
> know where the data is coming from, you can "cheat" by storing the
> object being dragged in some well known place, and then sneak a peek at
> it during the dragOver event. You can see how the Navigator does this
> with the org.eclipse.ui.views.navigator.LocalSelectionTransfer object.
|
|
| |
Re: [Howto] actually get Drag-and-Drop to work on a Viewer? [message #42290 is a reply to message #42061] |
Wed, 21 May 2003 11:39  |
Eclipse User |
|
|
|
Right: now that we have upgraded to 2.1, I can see it.
Thanks,
Paul K
John Arthorne wrote:
> LocalSelectionTransfer is new in Eclipse 2.1. That's what you get for
> being a year behind ;)
> --
>
> Paul T. Keyser wrote:
> > Hmm -- I have both org.eclipse.ui, plus ui.win32, imported as a "binary project" (kind of had to to get the
> > classpath stuff to work at all), and eclipse 2.0.2 has no other plugins in the plugins directory named
> > org.eclipse.ui.* (exc. the xamples and the external tools), but I still cannot "see" (in Ctrl-Shift-T) the class
> > LocalSelectionTransfer -- what am I doing wrong?
> >
|
|
|
Goto Forum:
Current Time: Fri Sep 19 16:02:58 EDT 2025
Powered by FUDForum. Page generated in 0.05584 seconds
|