package com.vaadin.tests.dd; import java.util.Collection; import com.vaadin.event.Transferable; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.event.dd.acceptcriteria.Or; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.dd.VerticalDropLocation; import com.vaadin.tests.components.AbstractReindeerTestUI; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.util.HierarchicalContainer; import com.vaadin.v7.event.DataBoundTransferable; import com.vaadin.v7.ui.AbstractSelect; import com.vaadin.v7.ui.Tree; import com.vaadin.v7.ui.Tree.TreeDragMode; import com.vaadin.v7.ui.Tree.TreeTargetDetails; /** * DD playground. Better quality example/prototype codes in {@link DDTest2}. */ public class DDTest8 extends AbstractReindeerTestUI { @Override protected void setup(VaadinRequest request) { final Tree tree = new Tree( "Tree with criteria from AbstractSelect (OverItem, ContainsItem). Foo can be dragged anywhere, anything can be dropped on Foo or Bar. Bar5 subtree is also valid drop target."); final HierarchicalContainer container = new HierarchicalContainer(); tree.setContainerDataSource(container); tree.addItem("Foo"); tree.addItem("Bar"); tree.addItem("Bar1"); tree.addItem("Bar2"); tree.addItem("Bar3"); tree.addItem("Bar4"); tree.addItem("Bar5"); tree.addItem("Child"); tree.setParent("Child", "Foo"); tree.setSizeFull(); tree.setDragMode(TreeDragMode.NODE); tree.setDropHandler(getDropHandler(tree, container)); getLayout().setSizeFull(); getLayout().getParent().setSizeFull(); addComponent(tree); } /** * Moves items in tree (and could work in Table too). Also supports * "building" tree. * * TODO fix algorithm, broken in some cases. * * @param tree * @param container * @return drop handler */ private DropHandler getDropHandler(final Tree tree, final HierarchicalContainer container) { return new DropHandler() { @SuppressWarnings({ "unused", "unchecked" }) private void populateSubTree(HierarchicalContainer idx, HierarchicalContainer subtree, Object itemId) { Collection<?> children = subtree.getChildren(itemId); if (children != null) { for (Object childId : children) { Item addItem = idx.addItem(childId); if (addItem != null) { // did not exist, populate properties Item item = subtree.getItem(itemId); Collection<?> itemPropertyIds = item .getItemPropertyIds(); for (Object propId : itemPropertyIds) { addItem.getItemProperty(propId).setValue(item .getItemProperty(propId).getValue()); } } idx.setParent(childId, itemId); populateSubTree(idx, subtree, childId); } } } @SuppressWarnings("unused") private HierarchicalContainer getSubTree(HierarchicalContainer idx, Object itemId) { HierarchicalContainer hierarchicalContainer = new HierarchicalContainer(); Collection<?> containerPropertyIds = idx .getContainerPropertyIds(); for (Object object : containerPropertyIds) { hierarchicalContainer.addContainerProperty(object, idx.getType(object), null); } hierarchicalContainer.addItem(itemId); copyChildren(idx, hierarchicalContainer, itemId); return hierarchicalContainer; } @SuppressWarnings("unchecked") private void copyChildren(HierarchicalContainer source, HierarchicalContainer target, Object itemId) { Collection<?> children = source.getChildren(itemId); if (children != null) { for (Object childId : children) { Item item = source.getItem(childId); Item addedItem = target.addItem(childId); target.setParent(childId, itemId); Collection<?> itemPropertyIds = item .getItemPropertyIds(); for (Object propertyId : itemPropertyIds) { addedItem.getItemProperty(propertyId).setValue(item .getItemProperty(propertyId).getValue()); } copyChildren(source, target, childId); } } } @Override public void drop(DragAndDropEvent event) { TreeTargetDetails details = (TreeTargetDetails) event .getTargetDetails(); // TODO set properties, so same sorter could be used in Table Transferable transferable = event.getTransferable(); if (transferable instanceof DataBoundTransferable) { DataBoundTransferable transferrable2 = (DataBoundTransferable) transferable; Object itemId = transferrable2.getItemId(); Object itemIdOver = details.getItemIdOver(); // TODO could use the "folder" node id to make the drop // logic simpler Object itemIdInto = details.getItemIdInto(); VerticalDropLocation dropLocation = details .getDropLocation(); Object itemIdAfter = details.getItemIdAfter(); if (itemIdOver.equals(itemIdInto)) { // directly on a node container.setParent(itemId, itemIdOver); return; } container.setParent(itemId, itemIdInto); if (dropLocation == null) { System.err.println("No detail of drop place available"); } container.moveAfterSibling(itemId, itemIdAfter); } return; } @Override public AcceptCriterion getAcceptCriterion() { return new Or( new AbstractSelect.TargetItemIs(tree, "Foo", "Bar"), new AbstractSelect.AcceptItem(tree, "Foo"), tree.new TargetInSubtree("Bar5") // ); } }; } @Override protected String getTestDescription() { return "Random DD tests"; } @Override protected Integer getTicketNumber() { return 119; } }