Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 200778

Summary: [DND] TreeViewer with ViewerDropAdapter returns null/LOCATION_NONE as last target/location
Product: [Eclipse Project] Platform Reporter: Wouter de Vaal <wouter_de_vaal>
Component: UIAssignee: Platform UI Triaged <platform-ui-triaged>
Status: CLOSED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: bokowski
Version: 3.3Keywords: helpwanted
Target Milestone: ---   
Hardware: PC   
OS: Linux-GTK   
Whiteboard: stalebug

Description Wouter de Vaal CLA 2007-08-22 04:38:23 EDT
Build ID:  I20070621-1340

Steps To Reproduce:
1. I have added some drag/drop code to an existing snippet
to demonstrate, run this
2. Expand item 0.9
3. Enlarge the window so enough empty room appears in the treeviewer to demonstrate the problem
4. Drag Item 0.1 all the way to the end. 
5. Hover over Item 0.9.8 and slowly move to the bottom
6. Observe system out changing:
current location: 3
current target: Item 0.9.8
current location: 2
current target: Item 0.9.8
current location: 4
current target: null

So when the cursor is above the very last tree element, still an insert point is shown, but the location and target change to null and LOCATION_NONE

More information:
/*******************************************************************************
 * Copyright (c) 2006 Tom Schindl and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Tom Schindl - initial API and implementation
 *******************************************************************************/

package org.eclipse.jface.snippets.viewers;

import java.util.ArrayList;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
 * A simple TreeViewer to demonstrate usage
 * 
 * @author Tom Schindl <tom.schindl@bestsolution.at>
 *
 */
public class Snippet002TreeViewerWithDropBug {
	private class MyContentProvider implements ITreeContentProvider {
		
		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
		 */
		public Object[] getElements(Object inputElement) {
			return ((MyModel)inputElement).child.toArray();
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
		 */
		public void dispose() {
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
		 */
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
		 */
		public Object[] getChildren(Object parentElement) {
			return getElements(parentElement);
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
		 */
		public Object getParent(Object element) {
			if( element == null) {
				return null;
			}
			
			return ((MyModel)element).parent;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
		 */
		public boolean hasChildren(Object element) {
			return ((MyModel)element).child.size() > 0;
		}
		
	}
	
	public class MyModel {
		public MyModel parent;
		public ArrayList child = new ArrayList();
		public int counter;
		
		public MyModel(int counter, MyModel parent) {
			this.parent = parent;
			this.counter = counter;
		}
		
		public String toString() {
			String rv = "Item ";
			if( parent != null ) {
				rv = parent.toString() + ".";
			}
			
			rv += counter;
			
			return rv;
		}
	}
	
	public Snippet002TreeViewerWithDropBug(Shell shell) {
		final TreeViewer v = new TreeViewer(shell);
		v.setLabelProvider(new LabelProvider());
		v.setContentProvider(new MyContentProvider());
		v.setInput(createModel());
		
		Transfer[] transfers = new Transfer[] { TextTransfer.getInstance() };
		v.addDragSupport(DND.DROP_MOVE, transfers, new DragSourceAdapter(){

			@Override
			public void dragStart(DragSourceEvent event) {
				ITreeSelection selection = (ITreeSelection) v.getSelection();
				if (selection.getFirstElement() instanceof MyModel){
					MyModel selectedModel = (MyModel) selection.getFirstElement();
					if (selectedModel.child.isEmpty()){
						event.doit = true;
						return;
					}
				}
				event.doit = false;
			}
			
			@Override
			public void dragSetData(DragSourceEvent event) {
				ITreeSelection selection = (ITreeSelection) v.getSelection();
				if (selection.getFirstElement() instanceof MyModel){
					MyModel selectedModel = (MyModel) selection.getFirstElement();
					event.data = Integer.toString(selectedModel.counter);
				}
			}
			
		});
		v.addDropSupport(DND.DROP_MOVE, transfers, new ViewerDropAdapter(v){

			@Override
			public boolean performDrop(Object data) {
				return false;
			}
			
			@Override
			public boolean validateDrop(Object target, int operation, TransferData transferType) {
				System.out.println("current location: " + getCurrentLocation());
				System.out.println("current target: " + getCurrentTarget());
				return true;
			}
		});
	}
	
	private MyModel createModel() {
		
		MyModel root = new MyModel(0,null);
		root.counter = 0;
		
		MyModel tmp;
		for( int i = 1; i < 10; i++ ) {
			tmp = new MyModel(i, root);
			root.child.add(tmp);
			for( int j = 1; j < i; j++ ) {
				tmp.child.add(new MyModel(j,tmp));
			}
		}
		
		return root;
	}
	
	public static void main(String[] args) {
		Display display = new Display ();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		new Snippet002TreeViewerWithDropBug(shell);
		shell.open ();
		
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		
		display.dispose ();
	}
}
Comment 1 Eclipse Webmaster CLA 2019-09-06 15:31:36 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.
Comment 2 Eclipse Genie CLA 2021-10-18 14:30:25 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.