Browse Source

added TableDropCriterion, quite similar to TreeDropCriterion and uses same client side criterion

svn changeset:11971/svn branch:6.3
tags/6.7.0.beta1
Matti Tahvonen 14 years ago
parent
commit
0013d48975
2 changed files with 294 additions and 0 deletions
  1. 98
    0
      src/com/vaadin/ui/Table.java
  2. 196
    0
      tests/src/com/vaadin/tests/dd/DDTest7.java

+ 98
- 0
src/com/vaadin/ui/Table.java View File

@@ -28,15 +28,19 @@ import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.event.ItemClickEvent.ItemClickSource;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.acceptCriteria.ClientCriterion;
import com.vaadin.event.dd.acceptCriteria.ServerSideCriterion;
import com.vaadin.terminal.KeyMapper;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VScrollTable;
import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;

/**
* <p>
@@ -3418,4 +3422,98 @@ public class Table extends AbstractSelect implements Action.Container,
Map<String, Object> clientVariables) {
return new AbstractSelectDropTargetDetails(clientVariables);
}

/**
* Lazy loading accept criterion for Table. Accepted target rows are loaded
* from server once per drag and drop operation. Developer must override one
* method that decides on which rows the currently dragged data can be
* dropped.
*
* <p>
* Initially pretty much no data is sent to client. On first required
* criterion check (per drag request) the client side data structure is
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
@ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TableDropCriterion extends ServerSideCriterion {

private Table table;

private Set<Object> allowedItemIds;

/*
* (non-Javadoc)
*
* @see
* com.vaadin.event.dd.acceptCriteria.ServerSideCriterion#getIdentifier
* ()
*/
@Override
protected String getIdentifier() {
return TableDropCriterion.class.getCanonicalName();
}

/*
* (non-Javadoc)
*
* @see
* com.vaadin.event.dd.acceptCriteria.AcceptCriterion#accepts(com.vaadin
* .event.dd.DragAndDropEvent)
*/
public boolean accepts(DragAndDropEvent dragEvent) {
AbstractSelectDropTargetDetails dropTargetData = (AbstractSelectDropTargetDetails) dragEvent
.getDropTargetDetails();
table = (Table) dragEvent.getDropTargetDetails().getTarget();
ArrayList<Object> visibleItemIds = new ArrayList<Object>(table
.getPageLength());
visibleItemIds.size();
Object id = table.getCurrentPageFirstItemId();
for (int i = 0; i < table.getPageLength() && id != null; i++) {
visibleItemIds.add(id);
id = table.nextItemId(id);
}
allowedItemIds = getAllowedItemIds(dragEvent, table, visibleItemIds);

return allowedItemIds.contains(dropTargetData.getItemIdOver());
}

/*
* (non-Javadoc)
*
* @see
* com.vaadin.event.dd.acceptCriteria.AcceptCriterion#paintResponse(
* com.vaadin.terminal.PaintTarget)
*/
@Override
public void paintResponse(PaintTarget target) throws PaintException {
/*
* send allowed nodes to client so subsequent requests can be
* avoided
*/
Object[] array = allowedItemIds.toArray();
for (int i = 0; i < array.length; i++) {
String key = table.itemIdMapper.key(array[i]);
array[i] = key;
}
target.addAttribute("allowedIds", array);
}

/**
* @param dragEvent
* @param table
* the table for which the allowed item identifiers are
* defined
* @param visibleItemIds
* the list of currently rendered item identifiers, accepted
* item id's need to be detected only for these visible items
* @return the set of identifiers for items on which the dragEvent will
* be accepted
*/
protected abstract Set<Object> getAllowedItemIds(
DragAndDropEvent dragEvent, Table table,
Collection<Object> visibleItemIds);

}

}

+ 196
- 0
tests/src/com/vaadin/tests/dd/DDTest7.java View File

@@ -0,0 +1,196 @@
package com.vaadin.tests.dd;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.demo.tutorial.addressbook.data.Person;
import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
import com.vaadin.event.DataBoundTransferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptCriteria.AcceptCriterion;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.tests.components.TestBase;
import com.vaadin.tests.util.TestUtils;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.Window;
import com.vaadin.ui.AbstractSelect.AbstractSelectDropTargetDetails;

public class DDTest7 extends TestBase {

java.util.Random r = new java.util.Random(1);

HorizontalLayout hl = new HorizontalLayout();
Table table = new Table(
"Drag and drop sortable table with lazy loading rule. Dragged row can only be accepted after hevier row (weigh column). If starting from topmost row in viewport, hevies will end up on top.");

@Override
protected void setup() {
Window w = getLayout().getWindow();

TestUtils
.injectCSS(
w,
".v-table-row-drag-middle .v-table-cell-content {"
+ " background-color: inherit ; border-bottom: 1px solid cyan;"
+ "}"
+ ".v-table-row-drag-middle .v-table-cell-wrapper {"
+ " margin-bottom: -1px;"
+ "}"
+ ""
// always show the drop hint below
+ ".v-table-row-drag-top .v-table-cell-content {"
+ "border-top: 0; margin-top:0;border-bottom:1px solid cyan;"
+ " margin-bottom: -1px;" + "}" + ""

);

// hl.addComponent(tree1);
hl.addComponent(table);
// hl.addComponent(tree2);
hl.setWidth("100%");
hl.setSpacing(true);
hl.setExpandRatio(table, 1);
table.setWidth("100%");
table.setPageLength(10);
table.setRowHeaderMode(Table.ROW_HEADER_MODE_ID);
table.setSelectable(true);
table.setMultiSelect(true);
populateTable();
addComponent(hl);

/*
* Make table rows draggable
*/
table.setDragMode(Table.TableDragMode.ROWS);

table.setDropHandler(new DropHandler() {
// accept only drags from this table
AcceptCriterion crit = new Table.TableDropCriterion() {
@Override
protected Set<Object> getAllowedItemIds(
DragAndDropEvent dragEvent, Table table,
Collection<Object> visibleItemIds) {

Object draggedItemId = ((Table.TableTransferable) dragEvent
.getTransferable()).getItemId();
Integer weightOfDraggedRow = (Integer) table.getItem(
draggedItemId).getItemProperty("Weight").getValue();

HashSet<Object> accepted = new HashSet<Object>();
for (Object itemId : visibleItemIds) {
Item item = table.getItem(itemId);
Integer w = (Integer) item.getItemProperty("Weight")
.getValue();
if (weightOfDraggedRow < w) {
accepted.add(itemId);
}

}
return accepted;
}
};

public AcceptCriterion getAcceptCriterion() {
return crit;
}

public void drop(DragAndDropEvent dropEvent) {
AbstractSelectDropTargetDetails dropTargetData = (AbstractSelectDropTargetDetails) dropEvent
.getDropTargetDetails();
DataBoundTransferable transferable = (DataBoundTransferable) dropEvent
.getTransferable();
Object itemIdOver = dropTargetData.getItemIdOver();
Object itemId = transferable.getItemId();
if (itemId == null || itemIdOver == null
|| itemId.equals(itemIdOver)) {
return; // no move happened
}

// IndexedContainer goodies... (hint: don't use it in real apps)
IndexedContainer containerDataSource = (IndexedContainer) table
.getContainerDataSource();
int newIndex = containerDataSource.indexOfId(itemIdOver) - 1;
// always add after
newIndex++;
if (newIndex < 0) {
newIndex = 0;
}
Object idAfter = containerDataSource.getIdByIndex(newIndex);
Collection selections = (Collection) table.getValue();
if (selections != null && selections.contains(itemId)) {
// dragged a selected item, if multiple rows selected, drag
// them too (functionality similar to apple mail)
for (Object object : selections) {
moveAfter(containerDataSource, object, idAfter);
}

} else {
// move just the dragged row, not considering selection at
// all
moveAfter(containerDataSource, itemId, idAfter);
}

}

private void moveAfter(IndexedContainer containerDataSource,
Object itemId, Object idAfter) {
try {
IndexedContainer clone = null;
clone = (IndexedContainer) containerDataSource.clone();
containerDataSource.removeItem(itemId);
Item newItem = containerDataSource.addItemAfter(idAfter,
itemId);
Item item = clone.getItem(itemId);
for (Object propId : item.getItemPropertyIds()) {
newItem.getItemProperty(propId).setValue(
item.getItemProperty(propId).getValue());
}

// TODO Auto-generated method stub
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
});

}

private void populateTable() {
table.addContainerProperty("Name", String.class, "");
table.addContainerProperty("Weight", Integer.class, 0);

PersonContainer testData = PersonContainer.createWithTestData();

for (int i = 0; i < 40; 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");

@Override
protected String getDescription() {
return "dd";
}

@Override
protected Integer getTicketNumber() {
return 119;
}

}

Loading…
Cancel
Save