/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.tests.components.grid;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Widgetset;
import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.EffectAllowed;
import com.vaadin.shared.ui.grid.DropLocation;
import com.vaadin.shared.ui.grid.DropMode;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.tests.util.Person;
import com.vaadin.tests.util.TestDataGenerator;
import com.vaadin.ui.Grid;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
import com.vaadin.ui.RadioButtonGroup;
import com.vaadin.ui.components.grid.GridDragSource;
import com.vaadin.ui.components.grid.GridDropTarget;
import elemental.json.Json;
import elemental.json.JsonObject;
@Theme("valo")
@Widgetset("com.vaadin.DefaultWidgetSet")
public class GridDragAndDrop extends AbstractTestUIWithLog {
private Set<Person> draggedItems;
@Override
protected void setup(VaadinRequest request) {
getUI().setMobileHtml5DndEnabled(true);
// Drag source Grid
Grid<Person> left = createGridAndFillWithData(50);
GridDragSource<Person> dragSource = applyDragSource(left);
// Drop target Grid
Grid<Person> right = createGridAndFillWithData(5);
GridDropTarget<Person> dropTarget = applyDropTarget(right);
// Layout the two grids
Layout grids = new HorizontalLayout();
grids.addComponents(left, right);
// Selection modes
List<Grid.SelectionMode> selectionModes = Arrays
.asList(Grid.SelectionMode.SINGLE, Grid.SelectionMode.MULTI);
RadioButtonGroup<Grid.SelectionMode> selectionModeSelect = new RadioButtonGroup<>(
"Selection mode", selectionModes);
selectionModeSelect.setSelectedItem(Grid.SelectionMode.SINGLE);
selectionModeSelect.addValueChangeListener(
event -> left.setSelectionMode(event.getValue()));
// Drop locations
List<DropMode> dropLocations = Arrays.asList(DropMode.values());
RadioButtonGroup<DropMode> dropLocationSelect = new RadioButtonGroup<>(
"Allowed drop location", dropLocations);
dropLocationSelect.setSelectedItem(DropMode.BETWEEN);
dropLocationSelect.addValueChangeListener(
event -> dropTarget.setDropMode(event.getValue()));
Layout controls = new HorizontalLayout(selectionModeSelect,
dropLocationSelect);
addComponents(controls, grids);
}
private Grid<Person> createGridAndFillWithData(int numberOfItems) {
Grid<Person> grid = new Grid<>();
grid.setItems(generateItems(numberOfItems));
grid.addColumn(
person -> person.getFirstName() + " " + person.getLastName())
.setCaption("Name");
grid.addColumn(person -> person.getAddress().getStreetAddress())
.setCaption("Street Address");
grid.addColumn(person -> person.getAddress().getCity())
.setCaption("City");
return grid;
}
private GridDragSource<Person> applyDragSource(Grid<Person> grid) {
GridDragSource<Person> dragSource = new GridDragSource<>(grid);
dragSource.setEffectAllowed(EffectAllowed.MOVE);
// Set data generator
dragSource.setDragDataGenerator(person -> {
JsonObject data = Json.createObject();
data.put("name",
person.getFirstName() + " " + person.getLastName());
data.put("city", person.getAddress().getCity());
return data;
});
// Add drag start listener
dragSource.addGridDragStartListener(event -> {
draggedItems = event.getDraggedItems();
log("START: " + draggedItems.size() + ", :"
+ draggedItems.stream().map(person -> person.getLastName())
.collect(Collectors.joining(" ")));
});
// Add drag end listener
dragSource.addGridDragEndListener(event -> {
log("END: dropEffect=" + event.getDropEffect());
if (event.getDropEffect() == DropEffect.MOVE
&& draggedItems != null) {
// If drop is successful, remove dragged item from source Grid
((ListDataProvider<Person>) grid.getDataProvider()).getItems()
.removeAll(draggedItems);
grid.getDataProvider().refreshAll();
// Remove reference to dragged items
draggedItems = null;
}
});
return dragSource;
}
private GridDropTarget<Person> applyDropTarget(Grid<Person> grid) {
// Create and attach extension
GridDropTarget<Person> dropTarget = new GridDropTarget<>(grid,
DropMode.BETWEEN);
dropTarget.setDropEffect(DropEffect.MOVE);
// Add listener
dropTarget.addGridDropListener(event -> {
event.getDragSourceExtension().ifPresent(source -> {
if (source instanceof GridDragSource) {
ListDataProvider<Person> dataProvider = (ListDataProvider<Person>) event
.getComponent().getDataProvider();
List<Person> items = (List<Person>) dataProvider.getItems();
// Calculate the target row's index
int index = items.indexOf(event.getDropTargetRow())
+ (event.getDropLocation() == DropLocation.BELOW ? 1
: 0);
// Add dragged items to the target Grid
items.addAll(index, draggedItems);
dataProvider.refreshAll();
log("DROP: dragData=" + event.getDataTransferText()
+ ", target="
+ event.getDropTargetRow().getFirstName() + " "
+ event.getDropTargetRow().getLastName()
+ ", location=" + event.getDropLocation());
}
});
});
return dropTarget;
}
private List<Person> generateItems(int num) {
return Stream.generate(() -> generateRandomPerson(new Random()))
.limit(num).collect(Collectors.toList());
}
private Person generateRandomPerson(Random r) {
return new Person(TestDataGenerator.getFirstName(r),
TestDataGenerator.getLastName(r), "foo@bar.com",
TestDataGenerator.getPhoneNumber(r),
TestDataGenerator.getStreetAddress(r),
TestDataGenerator.getPostalCode(r),
TestDataGenerator.getCity(r));
}
}