Community
Participate
Working Groups
I want to set correct DND.FEEDBACK_INSERT_BEFORE and DND.FEEDBACK_INSERT_AFTER when dragging TableItems inside dragOver method. Although feedback indicator appears, this can result in wrong indication where item will be dropped; expected drop position is different from the actual position after drop. Please, consider this DND example: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTDNDDrag andDropcomprehensiveExample.htm Run the example and check the following options: Inside the left-hand pane: - select "Table" from the Combo, - check Drag Source check box, - check DND.DROP_MOVE, - check the Text Transfer check box Inside the right-hand pane: - select "Table" from the Combo, - check Drag Target check box, - check the Text Transfer check box, - check DND.DROP_MOVE, - check DND.FEEDBACK_INSERT_BEFORE, - check DND.FEEDBACK_INSERT_AFTER Now if you drag a TableItem from the left-hand Table UP the destination table so that mouse pointer is at highest possible position before insertion line jumps one item higher (not so simple to achieve, since we have to move mouse pixel by pixel up the destination Table), insertion line indicates that this item will be dropped AFTER the item. But once we release the mouse button, and drop takes place, item is unexpectedly dropped BEFORE the item. This happens only on Mac, while it works perfectly on Windows (haven't tried with GTK yet though). The other issue (I think it's related to this one, so I'm not opening another bug) is the following: inside the dragOver method, where I want to set correct feedback (insertion line) depending on mouse pointer location inside the TableItem, this results in chaotic jumping of insertion line. This is a bit hard to describe, but the point is that this straight forward piece of code that I can use without problems when dragging over TreeItems fails on Mac. Code for determining event location that I use: TableItem item = (TableItem) event.item; Point point = item.getParent().getDisplay().map(null, item.getParent(), event.x, event.y); Rectangle bounds = item.getBounds(); if (point.y < bounds.y + bounds.height / 2) { // Event location in the upper half of TableItem event.feedback |= DND.FEEDBACK_INSERT_BEFORE; } else if (point.y >= bounds.y + bounds.height / 2) { // Event location in the lower half of TableItem event.feedback |= DND.FEEDBACK_INSERT_AFTER; } Again, this code works perfectly on Windows with Tree and also with Table. It won't work with Table on Mac. Here is a complete runnable snippet that demonstrates insertion line jumping inside dragOver method on Mac. Methods dragEnter and drop are not implemented: import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceAdapter; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetAdapter; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; public class DragOverTable { private final static int UPPER_HALF = 1; private final static int LOWER_HALF = -1; private static Table table; public static void main (String [] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new GridLayout()); table = new Table(shell, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 200; data.widthHint = 200; table.setLayoutData(data); table.setLinesVisible(true); table.setHeaderVisible(true); int count = 40; for (int i = 0; i < count; i++) { TableItem item = new TableItem(table, SWT.NONE); item.setText("TableItem " + i); } // Drag and drop Transfer[] types = new Transfer[] {TextTransfer.getInstance()}; // Define drag source DragSource source = new DragSource(table, DND.DROP_MOVE); source.setTransfer(types); source.addDragListener(new DragSourceAdapter() { public void dragSetData(DragSourceEvent event) { // Set some dummy data to prevent crash due to a // "Data does not have correct format for type" exception // when releasing mouse button event.data = " "; } }); // Define the drop target DropTarget target = new DropTarget(table, DND.DROP_MOVE | DND.DROP_DEFAULT); target.setTransfer(types); target.addDropListener(new DropTargetAdapter() { public void dragEnter(DropTargetEvent event) { // Not implemented } public void dragOver(DropTargetEvent event) { if (event.item == null) { event.feedback = DND.DROP_NONE; return; } event.feedback = DND.FEEDBACK_SCROLL; // Set correct insertion line depending on the pointer position // inside a table item switch (eventLocation(event)) { case UPPER_HALF: event.feedback |= DND.FEEDBACK_INSERT_BEFORE; break; case LOWER_HALF: event.feedback |= DND.FEEDBACK_INSERT_AFTER; break; default: break; } } public void drop(DropTargetEvent event) { // Not implemented } }); shell.pack (); shell.open (); while (!shell.isDisposed ()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose (); } private static int eventLocation(DropTargetEvent event) { TableItem item = (TableItem) event.item; Point point = item.getParent().getDisplay().map(null, item.getParent(), event.x, event.y); Rectangle bounds = item.getBounds(); if (point.y < bounds.y + bounds.height / 2) { // Pointer is in the upper half of TableItem return UPPER_HALF; } else if (point.y >= bounds.y + bounds.height / 2) { // Pointer is in the lower half of TableItem return LOWER_HALF; } else { return 0; } } Is this a bug? I can't see a programming mistake here, am I overlooking something?
Yes, this is a bug in the handling of drop feedback. Your code is calculating the upper and lower half value properly, but it looks like we're returning the wrong feedback value to Cocoa. I'll have a look.
We compute the drop feedback based on the row under the mouse during the drag, but then we were setting the Cocoa feedback value based on the row passed into tableView:validateDrop:proposedRow:proposedOperation:. These two values aren't necessarily the same. Fixed > 20110131.
(In reply to comment #2) > We compute the drop feedback based on the row under the mouse during the drag, > but then we were setting the Cocoa feedback value based on the row passed into > tableView:validateDrop:proposedRow:proposedOperation:. These two values aren't > necessarily the same. > > Fixed > 20110131. Thank you for your effort, you fixed this really fast. I don't have any experience in patching SWT builds, so I wonder if it's possible to patch 3.650 with this fix? I guess I would have to rebuild jnilibs in this case. Could applying this patch to 3.6 result in some other problems? Could you be please so kind and provide me some info on how to do this?
(In reply to comment #4) > Thank you for your effort, you fixed this really fast. > I don't have any experience in patching SWT builds, so I wonder if it's > possible to patch 3.650 with this fix? I guess I would have to rebuild jnilibs > in this case. Could applying this patch to 3.6 result in some other problems? > Could you be please so kind and provide me some info on how to do this? Sure. For building, take a look at http://eclipse.org/swt/faq.php#howbuildplugin which will tell you how to build the SWT plugin. The short version: you want to check out org.eclipse.swt and org.eclipse.swt.cocoa.macosx and org.eclipse.swt.cocoa.macosx.x86_64 and export those last two plugins. Generally speaking, the SWT is backwards compatible, though there may be some feature in the rest of the platform depending on the behavior of a bug in the SWT. In this case, one file changed, so it's probably easier to build 3.6.x with the patch.
Created attachment 188254 [details] Patch against R3_6_maintenance branch This will not be checked in to the 3.6 branch, but here's a patch with the fix.
I checked out SWT from CVS (version 3.650), applied the patch you provided and successfully built swt.jar. The problem is gone, DND feedback now behaves as it should. Thank you for your help!