TreeTable and DragAndDropWrapper

Hi,

I’ve got several questions about TreeTable and DragAndDropWrapper.

My goal is to build a Tree and drag and drop file(s) (from Desktop for example) on an item (node).
I quickly understood that it was not possible with a Tree component:
Vaadin forum

and

So I decided to use a TreeTable and DragAndDropWrapper.

This is a small part of my test program:


final Window w = new Window("Tree FilesystemContainer demo");
        setMainWindow(w);
        
        Panel mainPanel = new Panel("Main Panel !");
        
        Label label = new Label("ZZZZZZZZZZZz");
		DragAndDropWrapper dragAndDropWrapper = new DragAndDropWrapper(label);
		dragAndDropWrapper.setStyleName("v-multifileupload-dropzone");
		dragAndDropWrapper.setSizeUndefined();
		dragAndDropWrapper.setDropHandler(this);
		
        Label label2 = new Label("222ZZZZZZZZZZZz");
		DragAndDropWrapper dragAndDropWrapper2 = new DragAndDropWrapper(label2);
		dragAndDropWrapper2.setStyleName("v-multifileupload-dropzone");
		dragAndDropWrapper2.setSizeUndefined();
		dragAndDropWrapper2.setDropHandler(this);
        
        TreeTable tr = new TreeTable("Simple test with builtin container");
        tr.setSelectable(true);

        tr.setDragMode(TableDragMode.ROW);
        // populate table
        tr.addContainerProperty("Foo", String.class, "foo");
        tr.addContainerProperty("DropZone", DragAndDropWrapper.class, null);
        
        Object addItem = tr.addItem();
        tr.getContainerProperty(addItem, "Foo").setValue("First");
        tr.getContainerProperty(addItem, "DropZone").setValue(dragAndDropWrapper);
       
        Object addItem2 = tr.addItem();
        tr.getContainerProperty(addItem2, "Foo").setValue("Second");
        tr.getContainerProperty(addItem2, "DropZone").setValue(dragAndDropWrapper2);
        
        Object addItem3 = tr.addItem();
        tr.getContainerProperty(addItem3, "Foo").setValue("Third");
        tr.getContainerProperty(addItem3, "DropZone").setValue(dragAndDropWrapper);

        // build hierarchy
        tr.setParent(addItem3, addItem2);
        tr.setParent(addItem2, addItem);

        // flag to last item to be leaf
        tr.setChildrenAllowed(addItem3, false);

        // reserve excess space for the "treecolumn"
        tr.setWidth("100%");
        tr.setColumnExpandRatio("Foo", 1);
        
        mainPanel.addComponent(tr);
		
		w.setContent(mainPanel);

But I’ve got some questions…:

  • Using only one DragAndDropWrapper :
    Is it possible to only create one instance of DragAndDropWrapper, and use this instance for several nodes ?
    I try it but DragAndDropWrapper is only available with the last node.

  • Add a dragAndDropWrapper to an item:
    Is it possible to add the DragAndDropWrapper to an Item of the TreeTable ?
    Therefore, user will
    drag and drop his file on the Caption of the node
    , instead of having one column with the item and a second column with the DragAndDropWrapper ?
  • When user drops a file on the DragAndDropWrapper, how can I get the corresponding node of the Tree ?

My last question: Do you know where I could find an example to realize what I explained above ?

My apologies if someone has already asked these questions and I could not figure out yet.

Regards.

My knowledge is quite limited in this field but maybe it will help you start.

  • DragAndDropWrapper is a Component wrapping another component. In Vaadin an instance of a component can only be in only one place. So you can’t have the same wrapped component or the same wrapper in several nodes.
  • You should be able to use a generated columns or field factories to automatically wrap your node name into a D&DWrapper. That’s where my knowledge is limited as I don’t know how they work with a TreeTable. Check the
    book
    or look around the forum for some examples (as they come up quite often in here)
  • If you have some ID which can be used to find each node, you can use setData() and getData() for this for instance when creating the wrapper :
    Label l = new Label("some label"); l.setData(myNodeId);
    And use getData() from the event target component to get the data back.
  • As for an example, I don’t think there is one doing everything. You can check the sampler tree demos which have some code to attach and detach nodes (in the tree drag and drop samples) which you might be able to reuse as the container should work the same.
    The forum might have some data on HTML5 drop handlers (file d&d).

Make sure you check the limitations of desktop to browser file d&d as they sometime will require you to change your plans. For security purpose there are lots of things which can not be done easily with browsers (like I think getting a file name list and starting the download later). At least such limitations do exist for normal html file input…

I hope that help you get started

Hi Mathias,

You helped me !

I just provide some pieces of code of my test program. I hope it could be useful for other people in my case


		final Window w = new Window("Tree FilesystemContainer demo");
		setMainWindow(w);

		Panel mainPanel = new Panel("Main Panel !");

		TreeTable tr = new TreeTable("Simple test with builtin container");
		tr.setContainerDataSource(getContainer());
		tr.setDragMode(TableDragMode.ROW);

		tr.setWidth("70%");
		mainPanel.addComponent(tr);

		w.setContent(mainPanel);

...

	private Container getContainer() {
		HierarchicalContainer container = new HierarchicalContainer();
		container.addContainerProperty("id", Integer.class, null);
		container.addContainerProperty("dragAndDropWrapper", DragAndDropWrapper.class, null);

		for (int i = 0; i < 100; i++) {
			Object itemId = new Object();
			Item item = container.addItem(itemId);
			item.getItemProperty("id").setValue(i + 1);

			if (i % 3 == 2) {
				// every third item gets its predecessor as the parent
				container.setParent(itemId, container.prevItemId(itemId));
			} else if (i % 2 == 1) {
				// mix the deck even further
				container.setParent(itemId, container.prevItemId(itemId));
			}
			
			Label label = new Label("row " + (i + 1));
			label.setData(itemId);
			DragAndDropWrapper dragAndDropWrapper = new DragAndDropWrapper(label);
			dragAndDropWrapper.setData(itemId);
			dragAndDropWrapper.setDropHandler(this);
			item.getItemProperty("dragAndDropWrapper").setValue(dragAndDropWrapper);
		}

		return container;
	}

	@Override
	public void drop(DragAndDropEvent event) {
		DragAndDropWrapper.WrapperTransferable transferable = (WrapperTransferable) event.getTransferable();
		DragAndDropWrapper wrapper = (DragAndDropWrapper) event.getTargetDetails().getTarget();
		Component component = wrapper.getComponentIterator().next();
		TreeTable tr = (TreeTable) wrapper.getParent();
		
		Item item = tr.getItem(wrapper.getData());
		Property name = item.getItemProperty("id");
		
		System.out.println(item.toString());
		System.out.println(wrapper.getData());
		
		System.out.println(component.getClass().getName());
		System.out.println(component);
...
}

Regards