Skip to content

Commit

Permalink
Bringing the required changes to DropTarget.java (eclipse-platform#713)
Browse files Browse the repository at this point in the history
In the method dropTargetProc(long id, long sel, long arg0) the widget
was being recognised as label instead of the widget that actually has
the drop Target key. As soon as the first drop target key is acquired
the area is recognised as a Drop Target area and the Drag handlers are
added.

Also a new function called handleLabels( Control c, long cls) is
also added to bring the feature of droping on to the top of a label that
has an image view.This functions takes a control as a parameter to go up
till its parent to find the label which has an image view and add drag
handlers for that.
Fixes: eclipse-platform#649
  • Loading branch information
elsazac authored Apr 5, 2024
1 parent 648549b commit 5b437ee
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public class DropTarget extends Widget {
Transfer[] transferAgents = new Transfer[0];
DropTargetEffect dropEffect;
int feedback = DND.FEEDBACK_NONE;
boolean labelDragHandlersAdded = false;

// Track application selections
TransferData selectedDataType;
Expand All @@ -115,33 +116,58 @@ public class DropTarget extends Widget {
static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$NON-NLS-1$
static final String IS_ACTIVE = "org.eclipse.swt.internal.isActive"; //$NON-NLS-1$

void addDragHandlers() {
// Our strategy here is to dynamically add methods to the control's class that are required
// by NSDraggingDestination. Then, when setTransfer is called, we just register
// the types with the Control's NSView and AppKit will call the methods in the protocol
// when a drag goes over the view.
/**
* Recursively traverses the hierarchy of a control to handle labels with image
* views.
* If the child of a control is a label with an image view, drag handlers are added for
* the corresponding label class to enable it to act as a drop target.
* @param c the Control whose hierarchy needs to be iterated to check for label with imageView
*/
void handleLabels(Control c) {
if (labelDragHandlersAdded) return;
if (c instanceof Label) {
long labelViewClass = OS.object_getClass(c.view.id);
// adding the handlers to label class
addDragHandlers(labelViewClass);
/*
* If the content view can be an image view, then add the dragging methods to
* the image view too. This is used by Label so that dragging can work even when
* the Label has an image set on it.
*/
long imageView = 0;
if ((imageView = OS.objc_msgSend(c.view.id, OS.sel_getImageView)) != 0) {
long cls = OS.object_getClass(imageView);
addDragHandlers(cls);
labelDragHandlersAdded = true;
}
} else if (c instanceof Composite) {
Control[] cal = ((Composite) c).getChildren();
for (Control child : cal) {
handleLabels(child);
}
}
}

void addDragHandlers() {
/*
* Our strategy here is to dynamically add methods to the control's class that
* are required by NSDraggingDestination. Then, when setTransfer is called, we
* just register the types with the Control's NSView and AppKit will call the
* methods in the protocol when a drag goes over the view.
*/
long cls = OS.object_getClass(control.view.id);

if (cls == 0) {
DND.error(DND.ERROR_CANNOT_INIT_DROP);
}

// If we already added it, no need to do it again.
long procPtr = OS.class_getMethodImplementation(cls, OS.sel_draggingEntered_);
if (procPtr == proc3Args) return;
addDragHandlers(cls);

// If the content view can be image view, then add the dragging methods to image view too.
// This is used by Label so that dragging can work even when the Label has an image set on it.
long imageView = 0;
if ((imageView = OS.objc_msgSend(control.view.id, OS.sel_getImageView)) != 0) {
cls = OS.object_getClass(imageView);
addDragHandlers(cls);
}
handleLabels(control);
}

void addDragHandlers (long cls) {
// If we already added it, no need to do it again.
long procPtr = OS.class_getMethodImplementation(cls, OS.sel_draggingEntered_);
if (procPtr == proc3Args) return;
// Add the NSDraggingDestination callbacks
OS.class_addMethod(cls, OS.sel_draggingEntered_, proc3Args, "@:@");
OS.class_addMethod(cls, OS.sel_draggingUpdated_, proc3Args, "@:@");
Expand Down Expand Up @@ -434,7 +460,21 @@ static long dropTargetProc(long id, long sel, long arg0) {
if (display == null || display.isDisposed()) return 0;
Widget widget = display.findWidget(id);
if (widget == null) return 0;
DropTarget dt = (DropTarget)widget.getData(DND.DROP_TARGET_KEY);
Widget tempWidget = widget;
DropTarget dt = (DropTarget) tempWidget.getData(DND.DROP_TARGET_KEY);
if (dt == null && tempWidget instanceof Label) {
while (tempWidget != null && !(tempWidget instanceof Shell)) {
dt = (DropTarget) tempWidget.getData(DND.DROP_TARGET_KEY);
if (dt != null) {
break;
}
if (tempWidget instanceof Control) {
Composite widgetParent = ((Control) tempWidget).getParent();
tempWidget = widgetParent;
}
else break;
}
}
if (dt == null) return 0;

// arg0 is _always_ the sender, and implements NSDraggingInfo.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,9 @@ void drawBackground (long id, NSGraphicsContext context, NSRect rect) {

@Override
long imageView() {
return imageView.id;
//This function is modified to include a check for SWT Separator NSBox to handle cases where the image view is not present.
if (imageView != null) return imageView.id;
return 0L;
};

@Override
Expand Down

0 comments on commit 5b437ee

Please sign in to comment.