package com.vaadin.tests.dd;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
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.And;
import com.vaadin.event.dd.acceptcriteria.Or;
import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.server.Resource;
import com.vaadin.server.ThemeResource;
import com.vaadin.tests.components.TestBase;
import com.vaadin.tests.util.Person;
import com.vaadin.tests.util.PersonContainer;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.v7.data.Container;
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.AbstractSelect.AbstractSelectTargetDetails;
import com.vaadin.v7.ui.AbstractSelect.AcceptItem;
import com.vaadin.v7.ui.Table;
import com.vaadin.v7.ui.Table.TableTransferable;
import com.vaadin.v7.ui.Tree;
import com.vaadin.v7.ui.Tree.TargetItemAllowsChildren;
import com.vaadin.v7.ui.Tree.TreeDragMode;
public class DDTest2 extends TestBase {
java.util.Random r = new java.util.Random(1);
HorizontalLayout hl = new HorizontalLayout();
Tree tree1 = new Tree("Tree that accepts table rows to folders");
Table table = new Table("Drag rows to Tree on left or right");
Tree tree2 = new Tree("Accepts items, copies values");
private Tree tree3;
@Override
protected void setup() {
UI w = getLayout().getUI();
/* darn reindeer has no icons */
/* Make all trees (their nodes actually) draggable */
tree1.setDragMode(TreeDragMode.NODE);
tree2.setDragMode(TreeDragMode.NODE);
hl.addComponent(tree1);
hl.addComponent(table);
hl.addComponent(tree2);
hl.setWidth("100%");
hl.setSpacing(true);
hl.setExpandRatio(table, 1);
popuplateTrees();
table.setWidth("100%");
table.setPageLength(10);
populateTable();
addComponent(hl);
tree3 = new Tree(
"Tree with lazy loading criteria, of first server visit caches accept rules for all captions");
tree3.setDragMode(TreeDragMode.NODE);
tree3.addItem("Drag on me");
tree3.addItem("Or me");
/*
* An example of lazy initializing drop criterion with component
* specific api for easy rule writing.
*
* Example is pretty stupid (accepts drop on all nodes, but by
* explicitly defining them here), but demonstrates lazy initialization
* option if rules are heavy.
*/
final AcceptCriterion crit = new Tree.TreeDropCriterion() {
@Override
protected Set<Object> getAllowedItemIds(DragAndDropEvent dragEvent,
Tree tree) {
return new HashSet<>(tree.getItemIds());
}
};
tree3.setDropHandler(new DropHandler() {
@Override
public void drop(DragAndDropEvent dropEvent) {
Transferable transferable = dropEvent.getTransferable();
String data = (String) transferable.getData("Text");
if (transferable instanceof TableTransferable) {
TableTransferable tr = (TableTransferable) transferable;
System.out.println("From table row" + tr.getPropertyId());
Object value = tr.getSourceContainer()
.getItem(tr.getItemId())
.getItemProperty(tr.getPropertyId()).getValue();
data = (null != value) ? value.toString() : null;
}
if (data == null) {
data = "-no Text data flavor-";
}
tree3.addItem(data);
AbstractSelect.AbstractSelectTargetDetails dropTargetData = (AbstractSelect.AbstractSelectTargetDetails) dropEvent
.getTargetDetails();
tree3.setParent(data, dropTargetData.getItemIdOver());
}
@Override
public AcceptCriterion getAcceptCriterion() {
return crit;
}
});
addComponent(tree3);
/*
* Make table rows draggable
*/
table.setDragMode(Table.TableDragMode.ROW);
TargetItemAllowsChildren onNode = TargetItemAllowsChildren.get();
SourceIs fromTable = new SourceIs(table);
SourceIs fromTree = new SourceIs(tree1);
final Or fromTree1OrTable = new Or(fromTable, fromTree);
// Or could in the case be replaced with, keeping here as an example and
// test
@SuppressWarnings("unused")
SourceIs treeOrTable = new SourceIs(table, tree1);
final And and = new And(fromTree1OrTable, onNode);
DropHandler dropHandler = new DropHandler() {
@Override
public void drop(DragAndDropEvent event) {
/*
* We know transferrable is from table, so it is of type
* DataBoundTransferrable
*/
DataBoundTransferable tr = (DataBoundTransferable) event
.getTransferable();
Object itemId = tr.getItemId();
Container sourceContainer = tr.getSourceContainer();
if (tr.getSourceComponent() != tree1) {
// if the source is from table (not from tree1 itself),
// transfer Name property and use it as an identifier in
// tree1
Object nameValue = sourceContainer.getItem(itemId)
.getItemProperty("Name").getValue();
String name = (null != nameValue) ? nameValue.toString()
: null;
tree1.addItem(name);
tree1.setChildrenAllowed(name, false);
/*
* Remove the item from table
*/
sourceContainer.removeItem(itemId);
itemId = name;
}
/*
* As we also accept only drops on folders, we know dropDetails
* is from Tree and it contains itemIdOver.
*/
AbstractSelectTargetDetails details = (AbstractSelectTargetDetails) event
.getTargetDetails();
Object idOver = details.getItemIdOver();
tree1.setParent(itemId, idOver);
}
@Override
public AcceptCriterion getAcceptCriterion() {
return and;
}
};
tree1.setDropHandler(dropHandler);
/*
* First step done. tree1 now accepts drags only from table and only
* over tree nodes aka "folders"
*/
/*
* Now set the rightmost tree accept any item drag. On drop, copy from
* source. Also make drags from tree1 possible.
*/
dropHandler = new DropHandler() {
@Override
public void drop(DragAndDropEvent event) {
AbstractSelectTargetDetails details = (AbstractSelectTargetDetails) event
.getTargetDetails();
Transferable transferable = event.getTransferable();
if (transferable instanceof DataBoundTransferable) {
DataBoundTransferable tr = (DataBoundTransferable) transferable;
Object itemId = tree2.addItem();
tree2.setParent(itemId, details.getItemIdOver());
if (tr.getSourceComponent() == tree1) {
// use item id from tree1 as caption
tree2.setItemCaption(itemId, (String) tr.getItemId());
// if comes from tree1, move subtree too
copySubTree(tr.getItemId(), itemId);
} else if (tr.getSourceComponent() == table) {
// comes from table, override caption with name
String name = (String) table.getItem(tr.getItemId())
.getItemProperty("Name").getValue();
tree2.setItemCaption(itemId, name);
} else if (tr.getSourceComponent() == tree2) {
tree2.setItemCaption(itemId,
tree2.getItemCaption(tr.getItemId()));
}
}
}
private void copySubTree(Object itemId, Object itemIdTo) {
Collection<?> children = tree1.getChildren(itemId);
if (children != null) {
for (Object childId : children) {
Object newItemId = tree2.addItem();
tree2.setItemCaption(newItemId, (String) childId);
tree2.setParent(newItemId, itemIdTo);
copySubTree(childId, newItemId);
}
}
}
@Override
public AcceptCriterion getAcceptCriterion() {
return AcceptItem.ALL;
}
};
tree2.setDropHandler(dropHandler);
/*
* Finally add two windows with DragDropPane. First accept anything,
* second has server side accept rule to allow only drops from Tree1.
* Check the code in implementing classes.
*/
Window acceptAnyThing = new AcceptAnythingWindow();
Window acceptFromTree1viaServerCheck = new AcceptFromComponent(tree1);
w.addWindow(acceptAnyThing);
acceptAnyThing.setPositionY(450);
acceptAnyThing.setPositionX(150);
w.addWindow(acceptFromTree1viaServerCheck);
acceptFromTree1viaServerCheck.setPositionY(450);
acceptFromTree1viaServerCheck.setPositionX(450);
}
private void populateTable() {
table.addContainerProperty("Name", String.class, "");
table.addContainerProperty("Weight", Integer.class, 0);
PersonContainer testData = PersonContainer.createWithTestData();
for (int i = 0; i < 10; i++) {
Item addItem = table.addItem("Item" + i);
Person p = testData.getIdByIndex(i);
addItem.getItemProperty("Name")
.setValue(p.getFirstName() + " " + p.getLastName());
addItem.getItemProperty("Weight").setValue(50 + r.nextInt(60));
}
}
private final static ThemeResource FOLDER = new ThemeResource(
"../runo/icons/16/folder.png");
private final static ThemeResource DOC = new ThemeResource(
"../runo/icons/16/document.png");
private void popuplateTrees() {
HierarchicalContainer hc = new HierarchicalContainer();
hc.addContainerProperty("icon", Resource.class, DOC);
Item addItem = hc.addItem("Fats");
addItem.getItemProperty("icon").setValue(FOLDER);
hc.addItem("Tarja");
hc.setParent("Tarja", "Fats");
hc.setChildrenAllowed("Tarja", false);
addItem = hc.addItem("Thins");
addItem.getItemProperty("icon").setValue(FOLDER);
addItem = hc.addItem("Anorectic");
addItem.getItemProperty("icon").setValue(FOLDER);
hc.setParent("Anorectic", "Thins");
addItem = hc.addItem("Normal weighted");
addItem.getItemProperty("icon").setValue(FOLDER);
tree1.setContainerDataSource(hc);
tree1.setItemIconPropertyId("icon");
tree2.setContainerDataSource(new HierarchicalContainer());
tree2.addItem("/");
}
@Override
protected String getDescription() {
return "dd";
}
@Override
protected Integer getTicketNumber() {
return 119;
}
}