ソースを参照

Add helper for Grid row DnD (#10255)

* Added Griddragger.

* Refactored the GridDragger to match FW style

Unit tests, Test UI and documentation to come next.

* Change DropMode to BETWEEN and add Test UIs

* Simplify GridDragger API

* Fixes and unit tests for GridDragger

Fixed issues regarding drop index calculation when sourche and target grid is the same.
When the ListDataProvider is not internally using List, always drops to the end.
Updates the old data provider instead of creating a new one to preserve filters&sorting.
tags/8.2.0.alpha3
Pekka Hyvönen 6年前
コミット
6e01211931
コミッターのメールアドレスに関連付けられたアカウントが存在しません

+ 2
- 0
all/src/main/templates/release-notes.html ファイルの表示

@@ -126,6 +126,8 @@
<li><tt>AbstractDateField</tt> is not a <tt>LegacyComponent</tt> anymore.</li>
<li><tt>AbstractDateField</tt>.<tt>formatDate</tt> is now abstract.</li>
<li><tt>VAbstractTextualDate</tt>.<tt>updateDateVariables()</tt> is now <tt>updateBufferedResolutions()</tt> and <tt>updateAndSendBufferedValues()</tt>.</li>
<li><tt></tt></li>
<li>For <tt>GridDragStartEvent</tt> and <tt>GridDragEndEvent</tt> classes, the method <tt>getDraggedItems</tt> now returns a <tt>List</tt> instead of a <tt>Set</tt>, with the first-to-last item ordering from client side.</li>

<h2>For incompatible or behavior-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2>

+ 49
- 0
server/src/main/java/com/vaadin/ui/components/grid/DropIndexCalculator.java ファイルの表示

@@ -0,0 +1,49 @@
/*
* 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.ui.components.grid;

import java.io.Serializable;

/**
* A handler for calculating the index of the dropped items on the drop target
* grid.
*
* @author Vaadin Ltd
* @since
* @see GridDragger
* @param <T>
* the bean type
*/
@FunctionalInterface
public interface DropIndexCalculator<T> extends Serializable {

/**
* Calculator for always dropping items to the end of the target grid,
* regardless of drop position.
*/
@SuppressWarnings("rawtypes")
static DropIndexCalculator ALWAYS_DROP_TO_END = (event -> Integer.MAX_VALUE);

/**
* Called when Items are dropped onto a target grid.
*
* @param event
* the GridDropEvent.
* @return index the target index, use {@link Integer#MAX_VALUE} for always
* dropping to end
*/
public int calculateDropIndex(GridDropEvent<T> event);
}

+ 5
- 5
server/src/main/java/com/vaadin/ui/components/grid/GridDragEndEvent.java ファイルの表示

@@ -16,7 +16,7 @@
package com.vaadin.ui.components.grid;

import java.util.Collections;
import java.util.Set;
import java.util.List;

import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.ui.Grid;
@@ -33,7 +33,7 @@ import com.vaadin.ui.dnd.event.DragEndEvent;
*/
public class GridDragEndEvent<T> extends DragEndEvent<Grid<T>> {

private final Set<T> draggedItems;
private final List<T> draggedItems;

/**
* Creates a drag end event.
@@ -46,7 +46,7 @@ public class GridDragEndEvent<T> extends DragEndEvent<Grid<T>> {
* Set of items having been dragged.
*/
public GridDragEndEvent(Grid<T> source, DropEffect dropEffect,
Set<T> draggedItems) {
List<T> draggedItems) {
super(source, dropEffect);

this.draggedItems = draggedItems;
@@ -57,7 +57,7 @@ public class GridDragEndEvent<T> extends DragEndEvent<Grid<T>> {
*
* @return an unmodifiable set of items that were being dragged.
*/
public Set<T> getDraggedItems() {
return Collections.unmodifiableSet(draggedItems);
public List<T> getDraggedItems() {
return Collections.unmodifiableList(draggedItems);
}
}

+ 13
- 3
server/src/main/java/com/vaadin/ui/components/grid/GridDragSource.java ファイルの表示

@@ -18,7 +18,6 @@ package com.vaadin.ui.components.grid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.vaadin.data.provider.DataGenerator;
@@ -97,6 +96,16 @@ public class GridDragSource<T> extends DragSourceExtension<Grid<T>> {
defaultGridGenerator);
}

/**
* Gets the grid this extension has been attached to.
*
* @return the grid for this extension
* @since
*/
public Grid<T> getGrid() {
return getParent();
}

@Override
protected void registerDragSourceRpc() {
registerRpc(new GridDragSourceRpc() {
@@ -126,7 +135,8 @@ public class GridDragSource<T> extends DragSourceExtension<Grid<T>> {
/**
* Collects the dragged items of a Grid given the list of item keys.
*/
private Set<T> getDraggedItems(Grid<T> grid, List<String> draggedItemKeys) {
private List<T> getDraggedItems(Grid<T> grid,
List<String> draggedItemKeys) {
if (draggedItemKeys == null || draggedItemKeys.isEmpty()) {
throw new IllegalStateException(
"The drag event does not contain dragged items");
@@ -134,7 +144,7 @@ public class GridDragSource<T> extends DragSourceExtension<Grid<T>> {

return draggedItemKeys.stream()
.map(key -> grid.getDataCommunicator().getKeyMapper().get(key))
.collect(Collectors.toSet());
.collect(Collectors.toList());
}

/**

+ 10
- 6
server/src/main/java/com/vaadin/ui/components/grid/GridDragStartEvent.java ファイルの表示

@@ -16,7 +16,7 @@
package com.vaadin.ui.components.grid;

import java.util.Collections;
import java.util.Set;
import java.util.List;

import com.vaadin.shared.ui.dnd.EffectAllowed;
import com.vaadin.ui.Grid;
@@ -33,7 +33,7 @@ import com.vaadin.ui.dnd.event.DragStartEvent;
*/
public class GridDragStartEvent<T> extends DragStartEvent<Grid<T>> {

private final Set<T> draggedItems;
private final List<T> draggedItems;

/**
* Creates a drag start event.
@@ -46,7 +46,7 @@ public class GridDragStartEvent<T> extends DragStartEvent<Grid<T>> {
* Set of items being dragged.
*/
public GridDragStartEvent(Grid<T> source, EffectAllowed effectAllowed,
Set<T> draggedItems) {
List<T> draggedItems) {
super(source, effectAllowed);

this.draggedItems = draggedItems;
@@ -54,10 +54,14 @@ public class GridDragStartEvent<T> extends DragStartEvent<Grid<T>> {

/**
* Get the dragged row items.
* <p>
* The ordering of the list is the following: first the item that the drag
* started from, optionally followed by all the other selected rows in
* first-to-last order on the client side.
*
* @return an unmodifiable set of items that are being dragged.
* @return an unmodifiable list of items that are being dragged.
*/
public Set<T> getDraggedItems() {
return Collections.unmodifiableSet(draggedItems);
public List<T> getDraggedItems() {
return Collections.unmodifiableList(draggedItems);
}
}

+ 483
- 0
server/src/main/java/com/vaadin/ui/components/grid/GridDragger.java ファイルの表示

@@ -0,0 +1,483 @@
/*
* 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.ui.components.grid;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

import com.vaadin.data.provider.DataProvider;
import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.grid.DropLocation;
import com.vaadin.shared.ui.grid.DropMode;
import com.vaadin.ui.Grid;

/**
* Allows dragging rows for reordering within a Grid and between separate Grids.
* <p>
* When dragging a selected row, all the visible selected rows are dragged. Note
* that ONLY currently visible rows are taken into account.
* <p>
* <em>NOTE: this helper works only with {@link ListDataProvider} on both grids.
* If you have another data provider, you should customize data provider
* updating on drop with
* {@link #setSourceDataProviderUpdater(SourceDataProviderUpdater)} &
* {@link #setTargetDataProviderUpdater(TargetDataProviderUpdater)} and add a
* custom drop index calculator with
* {@link #setDropIndexCalculator(DropIndexCalculator)}.</em>
* <p>
* In case you are not using a {@link ListDataProvider} and don't have custom
* handlers, {@link UnsupportedOperationException} is thrown on drop event.
*
* @param <T>
* The Grid bean type.
* @author Vaadin Ltd
* @since
*/
public class GridDragger<T> implements Serializable {

private final GridDropTarget<T> gridDropTarget;
private final GridDragSource<T> gridDragSource;

private DropIndexCalculator<T> dropTargetIndexCalculator = null;
private SourceDataProviderUpdater<T> sourceDataProviderUpdater = null;
private TargetDataProviderUpdater<T> targetDataProviderUpdater = null;

/**
* Set of items currently being dragged.
*/
private List<T> draggedItems;
private int shiftedDropIndex;

/**
* Enables DnD reordering for the rows in the given grid.
* <p>
* {@link DropMode#BETWEEN} is used.
*
* @param grid
* Grid to be extended.
*/
public GridDragger(Grid<T> grid) {
this(grid, DropMode.BETWEEN);
}

/**
* Enables DnD reordering the rows in the given grid with the given drop
* mode.
* <p>
* <em>NOTE: this only works when the grid has a
* {@link ListDataProvider}.</em> Use the custom handlers
* {@link #setSourceDataProviderUpdater(SourceDataProviderUpdater)} and
* {@link #setTargetDataProviderUpdater(TargetDataProviderUpdater)} for
* other data providers.
*
* @param grid
* the grid to enable row DnD reordering on
* @param dropMode
* DropMode to be used.
*/
public GridDragger(Grid<T> grid, DropMode dropMode) {
this(grid, grid, dropMode);
}

/**
* Enables DnD moving of rows from the source grid to the target grid.
* <p>
* {@link DropMode#BETWEEN} is used.
* <p>
* <em>NOTE: this only works when the grids have a
* {@link ListDataProvider}.</em> Use the custom handlers
* {@link #setSourceDataProviderUpdater(SourceDataProviderUpdater)} and
* {@link #setTargetDataProviderUpdater(TargetDataProviderUpdater)} for
* other data providers.
*
* @param source
* the source grid dragged from.
* @param target
* the target grid dropped to.
*/
public GridDragger(Grid<T> source, Grid<T> target) {
this(source, target, DropMode.BETWEEN);
}

/**
* Enables DnD moving of rows from the source grid to the target grid with
* the custom data provider updaters.
* <p>
* {@link DropMode#BETWEEN} is used.
*
* @param source
* grid dragged from
* @param target
* grid dragged to
* @param targetDataProviderUpdater
* handler for updating target grid data provider
* @param sourceDataProviderUpdater
* handler for updating source grid data provider
*/
public GridDragger(Grid<T> source, Grid<T> target,
TargetDataProviderUpdater<T> targetDataProviderUpdater,
SourceDataProviderUpdater<T> sourceDataProviderUpdater) {
this(source, target, DropMode.BETWEEN);
this.targetDataProviderUpdater = targetDataProviderUpdater;
this.sourceDataProviderUpdater = sourceDataProviderUpdater;
}

/**
* Enables DnD moving of rows from the source grid to the target grid with
* the given drop mode.
* <p>
* <em>NOTE: this only works when the grids have a
* {@link ListDataProvider}.</em> Use the other constructors or custom
* handlers {@link #setSourceDataProviderUpdater(SourceDataProviderUpdater)}
* and {@link #setTargetDataProviderUpdater(TargetDataProviderUpdater)} for
* other data providers.
*
* @param source
* the drag source grid
* @param target
* the drop target grid
* @param dropMode
* the drop mode to use
*/
public GridDragger(Grid<T> source, Grid<T> target, DropMode dropMode) {
gridDragSource = new GridDragSource<>(source);

gridDropTarget = new GridDropTarget<>(target, dropMode);

gridDragSource.addGridDragStartListener(event -> {
draggedItems = event.getDraggedItems();
});

gridDropTarget.addGridDropListener(this::handleDrop);
}

/**
* Sets the target data provider updater, which handles adding the dropped
* items to the target grid.
* <p>
* By default, items are added to the index where they were dropped on for
* any {@link ListDataProvider}. If another type of data provider is used,
* this updater should be set to handle updating instead.
*
* @param targetDataProviderUpdater
* the target drop handler to set, or {@code null} to remove
*/
public void setTargetDataProviderUpdater(
TargetDataProviderUpdater<T> targetDataProviderUpdater) {
this.targetDataProviderUpdater = targetDataProviderUpdater;
}

/**
* Returns the target grid data provider updater.
*
* @return target grid drop handler
*/
public TargetDataProviderUpdater<T> getTargetDataProviderUpdater() {
return targetDataProviderUpdater;
}

/**
* Sets the source data provider updater, which handles removing items from
* the drag source grid.
* <p>
* By default the items are removed from any {@link ListDataProvider}. If
* another type of data provider is used, this updater should be set to
* handle updating instead.
* <p>
* If you want to skip removing items from the source, you can use
* {@link SourceDataProviderUpdater#NOOP}.
*
* @param sourceDataProviderUpdater
* the drag source data provider updater to set, or {@code null}
* to remove
*/
public void setSourceDataProviderUpdater(
SourceDataProviderUpdater<T> sourceDataProviderUpdater) {
this.sourceDataProviderUpdater = sourceDataProviderUpdater;
}

/**
* Returns the source grid data provider updater.
* <p>
* Default is {@code null} and the items are just removed from the source
* grid, which only works for {@link ListDataProvider}.
*
* @return the source grid drop handler
*/
public SourceDataProviderUpdater<T> getSourceDataProviderUpdater() {
return sourceDataProviderUpdater;
}

/**
* Sets the drop index calculator for the target grid. With this callback
* you can have a custom drop location instead of the actual one.
* <p>
* By default, items are placed on the index they are dropped into in the
* target grid.
* <p>
* If you want to always drop items to the end of the target grid, you can
* use {@link DropIndexCalculator#ALWAYS_DROP_TO_END}.
*
* @param dropIndexCalculator
* the drop index calculator
*/
public void setDropIndexCalculator(
DropIndexCalculator<T> dropIndexCalculator) {
this.dropTargetIndexCalculator = dropIndexCalculator;
}

/**
* Gets the drop index calculator.
* <p>
* Default is {@code null} and the dropped items are placed on the drop
* location.
*
* @return the drop index calculator
*/
public DropIndexCalculator<T> getDropIndexCalculator() {
return dropTargetIndexCalculator;
}

/**
* Returns the drop target grid to allow performing customizations such as
* altering {@link DropEffect}.
*
* @return the drop target grid
*/
public GridDropTarget<T> getGridDropTarget() {
return gridDropTarget;
}

/**
* Returns the drag source grid, exposing it for customizations.
*
* @return the drag source grid
*/
public GridDragSource<T> getGridDragSource() {
return gridDragSource;
}

/**
* Returns the currently dragged items captured from the source grid no drag
* start event, or {@code null} if no drag active.
*
* @return the currenytly dragged items or {@code null}
*/
protected List<T> getDraggedItems() {
return draggedItems;
}

/**
* This method is triggered when there has been a drop on the target grid.
* <p>
* <em>This method is protected only for testing reasons, you should not
* override this</em> but instead use
* {@link #setSourceDataProviderUpdater(SourceDataProviderUpdater)},
* {@link #setTargetDataProviderUpdater(TargetDataProviderUpdater)} and
* {@link #setDropIndexCalculator(DropIndexCalculator)} to customize how to
* handle the drops.
*
* @param event
* the drop event on the target grid
*/
protected void handleDrop(GridDropEvent<T> event) {
// there is a case that the drop happened from some other grid than the
// source one
if (getDraggedItems() == null) {
return;
}

// don't do anything if not supported data providers used without custom
// handlers
verifySupportedDataProviders();

shiftedDropIndex = -1;
handleSourceGridDrop(event, getDraggedItems());

int index = calculateDropIndex(event);

handleTargetGridDrop(event, index, getDraggedItems());

draggedItems = null;
}

private void handleSourceGridDrop(GridDropEvent<T> event,
final Collection<T> droppedItems) {
Grid<T> source = getGridDragSource().getGrid();

if (getSourceDataProviderUpdater() != null) {
getSourceDataProviderUpdater().removeItems(event.getDropEffect(),
source.getDataProvider(), droppedItems);
return;
}

ListDataProvider<T> listDataProvider = (ListDataProvider<T>) source
.getDataProvider();

// use the existing data source to keep filters and sort orders etc. in
// place.
Collection<T> sourceItems = listDataProvider.getItems();

// if reordering the same grid and dropping on top of one of the dragged
// rows, need to calculate the new drop index before removing the items
if (getGridDragSource().getGrid() == getGridDropTarget().getGrid()
&& event.getDropTargetRow().isPresent()
&& getDraggedItems().contains(event.getDropTargetRow().get())) {
List<T> sourceItemsList = (List<T>) sourceItems;
shiftedDropIndex = sourceItemsList
.indexOf(event.getDropTargetRow().get());
shiftedDropIndex -= getDraggedItems().stream().filter(
item -> sourceItemsList.indexOf(item) < shiftedDropIndex)
.count();
}

sourceItems.removeAll(droppedItems);
listDataProvider.refreshAll();
}

private void handleTargetGridDrop(GridDropEvent<T> event, final int index,
Collection<T> droppedItems) {
Grid<T> target = getGridDropTarget().getGrid();

if (getTargetDataProviderUpdater() != null) {
getTargetDataProviderUpdater().onDrop(event.getDropEffect(),
target.getDataProvider(), index, droppedItems);
return;
}

ListDataProvider<T> listDataProvider = (ListDataProvider<T>) target
.getDataProvider();
// update the existing to keep filters etc.
List<T> targetItems = (List<T>) listDataProvider.getItems();

if (index != Integer.MAX_VALUE) {
targetItems.addAll(index, droppedItems);
} else {
targetItems.addAll(droppedItems);
}
// instead of using setItems or creating a new data provider,
// refresh the existing one to keep filters etc. in place
listDataProvider.refreshAll();
}

private int calculateDropIndex(GridDropEvent<T> event) {
// use custom calculator if present
if (getDropIndexCalculator() != null) {
return getDropIndexCalculator().calculateDropIndex(event);
}

// if the source and target grids are the same, then the index has been
// calculated before removing the items. In this case the drop location
// is always above, since the items will be starting from that point on
if (shiftedDropIndex != -1) {
return shiftedDropIndex;
}

ListDataProvider<T> targetDataProvider = (ListDataProvider<T>) getGridDropTarget()
.getGrid().getDataProvider();
List<T> items = (List<T>) targetDataProvider.getItems();
int index = items.size();

Optional<T> dropTargetRow = event.getDropTargetRow();
if (dropTargetRow.isPresent()) {
index = items.indexOf(dropTargetRow.get())
+ (event.getDropLocation() == DropLocation.BELOW ? 1 : 0);
}

return index;
}

private void verifySupportedDataProviders() {
verifySourceDataProvider();
verifyTargetDataProvider();
}

@SuppressWarnings("unchecked")
private void verifySourceDataProvider() {
if (getSourceDataProviderUpdater() != null) {
return; // custom updater is always fine
}

if (!(getSourceDataProvider() instanceof ListDataProvider)) {
throwUnsupportedOperationExceptionForUnsupportedDataProvider(true);
}

if (!(((ListDataProvider<T>) getSourceDataProvider())
.getItems() instanceof List)) {
throwUnsupportedOperationExceptionForUnsupportedCollectionInListDataProvider(
true);
}
}

@SuppressWarnings("unchecked")
private void verifyTargetDataProvider() {
if (getTargetDataProviderUpdater() != null
&& getDropIndexCalculator() != null) {
return; // custom updater and calculator is always fine
}

if (!(getTargetDataProvider() instanceof ListDataProvider)) {
throwUnsupportedOperationExceptionForUnsupportedDataProvider(false);
}

if (!(((ListDataProvider<T>) getTargetDataProvider())
.getItems() instanceof List)) {
throwUnsupportedOperationExceptionForUnsupportedCollectionInListDataProvider(
false);
}
}

private DataProvider<T, ?> getSourceDataProvider() {
return getGridDragSource().getGrid().getDataProvider();
}

private DataProvider<T, ?> getTargetDataProvider() {
return getGridDropTarget().getGrid().getDataProvider();
}

private static void throwUnsupportedOperationExceptionForUnsupportedDataProvider(
boolean sourceGrid) {
throw new UnsupportedOperationException(
new StringBuilder().append(sourceGrid ? "Source " : "Target ")
.append("grid does not have a ListDataProvider, cannot automatically ")
.append(sourceGrid ? "remove " : "add ")
.append("items. Use GridDragger.set")
.append(sourceGrid ? "Source" : "Target")
.append("DataProviderUpdater(...) ")
.append(sourceGrid ? ""
: "and setDropIndexCalculator(...) "
+ "to customize how to handle updating the data provider.")
.toString());
}

private static void throwUnsupportedOperationExceptionForUnsupportedCollectionInListDataProvider(
boolean sourceGrid) {
throw new UnsupportedOperationException(new StringBuilder()
.append(sourceGrid ? "Source " : "Target ")
.append("grid's ListDataProvider is not backed by a List-collection, cannot ")
.append(sourceGrid ? "remove " : "add ")
.append("items. Use a ListDataProvider backed by a List, or use GridDragger.set")
.append(sourceGrid ? "Source" : "Target")
.append("DataProviderUpdater(...) ")
.append(sourceGrid ? "" : "and setDropIndexCalculator(...) ")
.append(" to customize how to handle updating the data provider to customize how to handle updating the data provider.")
.toString());
}

}

+ 10
- 0
server/src/main/java/com/vaadin/ui/components/grid/GridDropTarget.java ファイルの表示

@@ -58,6 +58,16 @@ public class GridDropTarget<T> extends DropTargetExtension<Grid<T>> {
setDropMode(dropMode);
}

/**
* Gets the grid this extension has been attached to.
*
* @return the grid for this extension
* @since
*/
public Grid<T> getGrid() {
return getParent();
}

/**
* Sets the drop mode of this drop target.
* <p>

+ 57
- 0
server/src/main/java/com/vaadin/ui/components/grid/SourceDataProviderUpdater.java ファイルの表示

@@ -0,0 +1,57 @@
/*
* 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.ui.components.grid;

import java.io.Serializable;
import java.util.Collection;

import com.vaadin.data.provider.DataProvider;
import com.vaadin.shared.ui.dnd.DropEffect;

/**
* A handler for source grid data provider updater for {@link GridDragger}.
*
* Used to handle updates to the source grid's {@link DataProvider} after a
* drop.
*
* @author Vaadin Ltd
* @since
*
* @param <T>
* the bean type
*/
@FunctionalInterface
public interface SourceDataProviderUpdater<T> extends Serializable {

/**
* A NOOP updater that does not do anything for the source data provider.
*/
static SourceDataProviderUpdater NOOP = (e, dp, i) -> {
};

/**
* Called when Items have been dragged.
*
* @param dropEffect
* the reported drop effect from the drop event
* @param dataProvider
* the data provider for the source grid
* @param items
* dragged items.
*/
public void removeItems(DropEffect dropEffect,
DataProvider<T, ?> dataProvider, Collection<T> items);
}

+ 55
- 0
server/src/main/java/com/vaadin/ui/components/grid/TargetDataProviderUpdater.java ファイルの表示

@@ -0,0 +1,55 @@
/*
* 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.ui.components.grid;

import java.io.Serializable;
import java.util.Collection;

import com.vaadin.data.provider.DataProvider;
import com.vaadin.shared.ui.dnd.DropEffect;

/**
* A handler for target grid data provider updater for {@link GridDragger}.
*
* Used to handle updates to the target grid's {@link DataProvider} after a
* drop.
*
* @author Vaadin Ltd
* @since
*
* @param <T>
* the bean type
*/
@FunctionalInterface
public interface TargetDataProviderUpdater<T> extends Serializable {

/**
* Called when items have been dropped on the target Grid.
*
* @param dropEffect
* the reported drop effect from the drop event
* @param dataProvider
* the target grid data provider
* @param index
* the target index, {@link Integer#MAX_VALUE} is used for
* dropping things always to the end of the grid without having
* to fetch the size of the data provider
* @param items
* items to be added.
*/
public void onDrop(DropEffect dropEffect, DataProvider<T, ?> dataProvider,
int index, Collection<T> items);
}

+ 206
- 0
server/src/test/java/com/vaadin/tests/server/component/grid/GridDraggerOneGridTest.java ファイルの表示

@@ -0,0 +1,206 @@
package com.vaadin.tests.server.component.grid;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.shared.ui.grid.DropLocation;
import com.vaadin.ui.Grid;
import com.vaadin.ui.components.grid.DropIndexCalculator;
import com.vaadin.ui.components.grid.GridDragger;
import com.vaadin.ui.components.grid.GridDropEvent;
import com.vaadin.ui.components.grid.SourceDataProviderUpdater;

public class GridDraggerOneGridTest {

public class TestGridDragger extends GridDragger<String> {

public TestGridDragger(Grid<String> grid) {
super(grid);
}

@Override
public void handleDrop(GridDropEvent<String> event) {
super.handleDrop(event);
}

@Override
public List<String> getDraggedItems() {
return draggedItems;
}
}

private Grid<String> source;
private TestGridDragger dragger;
private List<String> draggedItems;

@Before
public void setupListCase() {
source = new Grid<>();
dragger = new TestGridDragger(source);
}

private void drop(String dropIndex, DropLocation dropLocation,
String... items) {
draggedItems = new ArrayList<>(Arrays.asList(items));
dragger.handleDrop(new GridDropEvent<>(source, null, null, null,
dropIndex, dropLocation, null));
}

private void verifyDataProvider(String... items) {
Collection<String> list = ((ListDataProvider<String>) source
.getDataProvider()).getItems();
Assert.assertArrayEquals("Invalid items in target data provider", items,
list.toArray());
}

private static void setCustomDataProvider(Grid<String> grid) {
grid.setDataProvider((so, i, l) -> null, null);
}

private static void setCustomDataProvider(Grid<String> grid,
String... items) {
grid.setDataProvider((so, i, l) -> Stream.of(items), null);
}

@Test
public void listDataProviders_basicOperation() {
source.setItems("0", "1", "2");

drop(null, null, "0");

verifyDataProvider("1", "2", "0");

drop("0", DropLocation.BELOW, "1");

verifyDataProvider("2", "0", "1");

drop("1", DropLocation.ABOVE, "2");

verifyDataProvider("0", "2", "1");
}

@Test
public void listDataProvider_dropAboveFirst() {
source.setItems("0", "1");

drop("0", DropLocation.ABOVE, "1");
verifyDataProvider("1", "0");
}

@Test
public void listDataProvider_customCalculator() {
source.setItems("0", "1");

AtomicInteger trigger = new AtomicInteger();
dragger.setDropIndexCalculator(event -> {
trigger.incrementAndGet();
return 0;
});

drop("1", DropLocation.BELOW, "0");

Assert.assertEquals("Custom calculator should be invoked", 1,
trigger.get());
verifyDataProvider("0", "1");
}

@Test
public void listDataProvider_customCalculatorReturnsMax_droppedToEnd() {
source.setItems("0", "1", "2");

dragger.setDropIndexCalculator(event -> {
return Integer.MAX_VALUE;
});

drop("1", DropLocation.ABOVE, "0");

verifyDataProvider("1", "2", "0");
}

@Test
public void noopSourceUpdater() {
source.setItems("0", "1", "2");

dragger.setSourceDataProviderUpdater(SourceDataProviderUpdater.NOOP);

drop("2", DropLocation.ABOVE, "0", "1");

verifyDataProvider("0", "1", "0", "1", "2");

}

@Test
public void alwaysDropToEndCalculator() {
source.setItems("0", "1", "2");

dragger.setDropIndexCalculator(DropIndexCalculator.ALWAYS_DROP_TO_END);

drop("1", DropLocation.ABOVE, "0");

verifyDataProvider("1", "2", "0");
}

@Test
public void dropTwoFromEnd_beginning() {
source.setItems("0", "1", "2", "3");

drop("0", DropLocation.ABOVE, "2", "3");

verifyDataProvider("2", "3", "0", "1");
}

@Test
public void dropTwoFromEnd_middle() {
source.setItems("0", "1", "2", "3");

drop("1", DropLocation.ABOVE, "2", "3");

verifyDataProvider("0", "2", "3", "1");
}

@Test
public void dropTwoFromEnd_aboveOneThatIsDragged_doesntExplode() {
source.setItems("0", "1", "2", "3");

drop("2", DropLocation.ABOVE, "2", "3");

verifyDataProvider("0", "1", "2", "3");
}

@Test
public void dragAndAboveFirst_thatIsAlsoDragged_doesntExplode() {
source.setItems("0", "1", "2", "3");

drop("2", DropLocation.ABOVE, "2", "3");

verifyDataProvider("0", "1", "2", "3");
}

@Test
public void dropFromBeginning_afterOneDragged_doesntExplode() {
source.setItems("0", "1", "2", "3", "4");

drop("3", DropLocation.BELOW, "0", "1", "3");

verifyDataProvider("2", "0", "1", "3", "4");
}

@Test
public void dropMixedSet_onOneOfTheDragged_doesntExplode() {
source.setItems("0", "1", "2", "3", "4");

drop("2", DropLocation.BELOW, "0", "2", "4");

verifyDataProvider("1", "0", "2", "4", "3");
}

}

+ 252
- 0
server/src/test/java/com/vaadin/tests/server/component/grid/GridDraggerTwoGridsTest.java ファイルの表示

@@ -0,0 +1,252 @@
package com.vaadin.tests.server.component.grid;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.shared.ui.grid.DropLocation;
import com.vaadin.ui.Grid;
import com.vaadin.ui.components.grid.DropIndexCalculator;
import com.vaadin.ui.components.grid.GridDragger;
import com.vaadin.ui.components.grid.GridDropEvent;
import com.vaadin.ui.components.grid.SourceDataProviderUpdater;

public class GridDraggerTwoGridsTest {

public class TestGridDragger extends GridDragger<String> {

public TestGridDragger(Grid<String> source, Grid<String> target) {
super(source, target);
}

@Override
public void handleDrop(GridDropEvent<String> event) {
super.handleDrop(event);
}

@Override
public List<String> getDraggedItems() {
return draggedItems;
}
}

private Grid<String> source;
private Grid<String> target;
private TestGridDragger dragger;
private List<String> draggedItems;

@Before
public void setupListCase() {
source = new Grid<>();
target = new Grid<>();
dragger = new TestGridDragger(source, target);

target.setItems(); // setup to use list data provider
}

private void drop(String dropIndex, DropLocation dropLocation,
String... items) {
draggedItems = new ArrayList<>(Arrays.asList(items));
dragger.handleDrop(new GridDropEvent<>(target, null, null, null,
dropIndex, dropLocation, null));
}

private void verifySourceDataProvider(String... items) {
Collection<String> list = ((ListDataProvider<String>) source
.getDataProvider()).getItems();
Assert.assertArrayEquals("Invalid items in source data provider", items,
list.toArray());
}

private void verifyTargetDataProvider(String... items) {
Collection<String> list = ((ListDataProvider<String>) target
.getDataProvider()).getItems();
Assert.assertArrayEquals("Invalid items in target data provider", items,
list.toArray());
}

private static void setCustomDataProvider(Grid<String> grid) {
grid.setDataProvider((so, i, l) -> null, null);
}

private static void setCustomDataProvider(Grid<String> grid,
String... items) {
grid.setDataProvider((so, i, l) -> Stream.of(items), null);
}

@Test
public void listDataProviders_basicOperation() {
source.setItems("0", "1", "2");

drop(null, null, "0");

verifySourceDataProvider("1", "2");
verifyTargetDataProvider("0");

drop("0", DropLocation.BELOW, "1");

verifySourceDataProvider("2");
verifyTargetDataProvider("0", "1");

drop("1", DropLocation.ABOVE, "2");

verifySourceDataProvider();
verifyTargetDataProvider("0", "2", "1");
}

@Test
public void listDataProvider_dropAboveFirst() {
source.setItems("0");
target.setItems("1");

drop("1", DropLocation.ABOVE, "0");
verifySourceDataProvider();
verifyTargetDataProvider("0", "1");
}

@Test
public void listDataProvider_customCalculator() {
source.setItems("0");
target.setItems("1");

AtomicInteger trigger = new AtomicInteger();
dragger.setDropIndexCalculator(event -> {
trigger.incrementAndGet();
return 0;
});

drop("1", DropLocation.BELOW, "0");

Assert.assertEquals("Custom calculator should be invoked", 1,
trigger.get());
verifySourceDataProvider();
verifyTargetDataProvider("0", "1");
}

@Test
public void listDataProvider_customCalculatorReturnsMax_droppedToEnd() {
source.setItems("0");
target.setItems("1", "2");

dragger.setDropIndexCalculator(event -> {
return Integer.MAX_VALUE;
});

drop("1", DropLocation.ABOVE, "0");

verifySourceDataProvider();
verifyTargetDataProvider("1", "2", "0");
}

@Test
public void customSourceDataProvider_isInvoked() {
setCustomDataProvider(source, "0", "1");
target.setItems("2");

AtomicInteger updaterTrigger = new AtomicInteger();
List<String> droppedItems = new ArrayList<>();
dragger.setSourceDataProviderUpdater((event, dp, items) -> {
updaterTrigger.incrementAndGet();
droppedItems.addAll(items);
});

drop("2", DropLocation.BELOW, "0", "1");

Assert.assertEquals("source updater not triggered", 1,
updaterTrigger.get());
Assert.assertArrayEquals(droppedItems.toArray(),
new Object[] { "0", "1" });
verifyTargetDataProvider("2", "0", "1");
}

@Test
public void noopSourceUpdater() {
source.setItems("0", "1");
target.setItems("2");

dragger.setSourceDataProviderUpdater(SourceDataProviderUpdater.NOOP);

drop("2", DropLocation.ABOVE, "0", "1");

verifySourceDataProvider("0", "1");
verifyTargetDataProvider("0", "1", "2");
}

@Test
public void alwaysDropToEndCalculator() {
source.setItems("0");
target.setItems("1", "2");

dragger.setDropIndexCalculator(DropIndexCalculator.ALWAYS_DROP_TO_END);

drop("1", DropLocation.ABOVE, "0");

verifySourceDataProvider();
verifyTargetDataProvider("1", "2", "0");
}

@Test(expected = UnsupportedOperationException.class)
public void customSourceDataProvider_noCustomSourceUpdater_unsupportedOperationExceptionThrown() {
setCustomDataProvider(source);

drop(null, DropLocation.BELOW, "0");
}

@Test(expected = UnsupportedOperationException.class)
public void customTargetDataProvider_noCustomCalculatorAndNoCustomTargetUpdater_unsupportedOperationExceptionThrown() {
setCustomDataProvider(target);

drop(null, DropLocation.BELOW, "0");
}

@Test(expected = UnsupportedOperationException.class)
public void customTargetDataProvider_customCalculatorAndNoCustomTargetUpdater_unsupportedOperationExceptionThrown() {
setCustomDataProvider(target);
dragger.setDropIndexCalculator(event -> 0);

drop(null, DropLocation.BELOW, "0");
}

@Test(expected = UnsupportedOperationException.class)
public void customTargetDataProvider_noCustomCalculatorAndCustomTargetUpdater_unsupportedOperationExceptionThrown() {
source.setItems("0");

setCustomDataProvider(target);
dragger.setTargetDataProviderUpdater((event, dp, index, items) -> {
});

drop(null, DropLocation.BELOW, "0");
}

@Test
public void customTargetDataProvider_customCalculatorAndCustomTargetUpdater_triggeredWithMaxIndex() {
source.setItems("0");
setCustomDataProvider(target, "1", "2", "3");

AtomicInteger updaterTrigger = new AtomicInteger(-1);
dragger.setTargetDataProviderUpdater(
(event, dp, index, items) -> updaterTrigger.set(index));

AtomicInteger calculatorTrigger = new AtomicInteger();
dragger.setDropIndexCalculator(event -> {
calculatorTrigger.incrementAndGet();
return 2;
});

drop("1", DropLocation.ABOVE, "2");

Assert.assertEquals("custom calculator not triggered", 1,
calculatorTrigger.get());
// getting value from custom calculator
Assert.assertEquals("given drop index to target updater is wrong", 2,
updaterTrigger.get());
}
}

+ 120
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/AbstractGridDnD.java ファイルの表示

@@ -0,0 +1,120 @@
package com.vaadin.tests.components.grid;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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.CheckBox;
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.GridDragger;
import com.vaadin.ui.components.grid.GridDropTarget;

public abstract class AbstractGridDnD extends AbstractTestUIWithLog {

protected final Layout controls = new HorizontalLayout();

protected void initializeTestFor(GridDragger<Person> gridDragger) {
initializeTestFor(gridDragger.getGridDragSource().getGrid(),
gridDragger.getGridDropTarget().getGrid(),
gridDragger.getGridDragSource(),
gridDragger.getGridDropTarget());
}

protected void initializeTestFor(Grid<Person> source, Grid<Person> target,
GridDragSource<Person> dragSource,
GridDropTarget<Person> dropTarget) {
// Layout the two grids
Layout layout = new HorizontalLayout();

layout.addComponent(source);
layout.addComponent(target); // noop if source == target
layout.setWidth("100%");

// 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 -> source.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()));

CheckBox transitionCheckBox = new CheckBox("Transition layout", false);
transitionCheckBox.addValueChangeListener(event -> {
if (event.getValue()) {
layout.addStyleName("transitioned");
} else {
layout.removeStyleName("transitioned");
}
});
CheckBox dropOnSortedGridRows = new CheckBox("Drop on Sorted Grid Rows",
dropTarget.isDropAllowedOnSortedGridRows());
dropOnSortedGridRows.addValueChangeListener(event -> {
dropTarget.setDropAllowedOnSortedGridRows(event.getValue());
});

RadioButtonGroup<Integer> frozenColumnSelect = new RadioButtonGroup<>(
"Frozen columns", Arrays.asList(new Integer[] { -1, 0, 1 }));
frozenColumnSelect.setValue(source.getFrozenColumnCount());
frozenColumnSelect.addValueChangeListener(event -> {
source.setFrozenColumnCount(event.getValue());
target.setFrozenColumnCount(event.getValue());
});

controls.addComponents(selectionModeSelect, dropLocationSelect,
transitionCheckBox, dropOnSortedGridRows, frozenColumnSelect);

addComponents(controls, layout);

getPage().getStyles()
.add(".transitioned { transform: translate(-30px, 30px);}");
}

protected Grid<Person> createGridAndFillWithData(int numberOfItems) {
Grid<Person> grid = new Grid<>();
grid.setWidth("100%");

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 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));
}
}

+ 3
- 95
uitest/src/main/java/com/vaadin/tests/components/grid/GridDragAndDrop.java ファイルの表示

@@ -15,12 +15,8 @@
*/
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;
@@ -30,22 +26,16 @@ 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.CheckBox;
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;

@Theme("valo")
@Widgetset("com.vaadin.DefaultWidgetSet")
public class GridDragAndDrop extends AbstractTestUIWithLog {
public class GridDragAndDrop extends AbstractGridDnD {

private Set<Person> draggedItems;
private List<Person> draggedItems;

@Override
protected void setup(VaadinRequest request) {
@@ -59,76 +49,7 @@ public class GridDragAndDrop extends AbstractTestUIWithLog {
Grid<Person> right = createGridAndFillWithData(0);
GridDropTarget<Person> dropTarget = applyDropTarget(right);

// Layout the two grids
Layout grids = new HorizontalLayout();

grids.addComponents(left, right);
grids.setWidth("100%");

// 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()));

CheckBox transitionCheckBox = new CheckBox("Transition layout", false);
transitionCheckBox.addValueChangeListener(event -> {
if (event.getValue()) {
grids.addStyleName("transitioned");
} else {
grids.removeStyleName("transitioned");
}
});

CheckBox dropOnSortedGridRows = new CheckBox("Drop on Sorted Grid Rows",
dropTarget.isDropAllowedOnSortedGridRows());
dropOnSortedGridRows.addValueChangeListener(event -> {
dropTarget.setDropAllowedOnSortedGridRows(event.getValue());
});

RadioButtonGroup<Integer> frozenColumnSelect = new RadioButtonGroup<>(
"Frozen columns", Arrays.asList(new Integer[] { -1, 0, 1 }));
frozenColumnSelect.setValue(left.getFrozenColumnCount());
frozenColumnSelect.addValueChangeListener(event -> {
left.setFrozenColumnCount(event.getValue());
right.setFrozenColumnCount(event.getValue());
});

Layout controls = new HorizontalLayout(selectionModeSelect,
dropLocationSelect, transitionCheckBox, frozenColumnSelect,
dropOnSortedGridRows);

addComponents(controls, grids);

getPage().getStyles()
.add(".transitioned { transform: translate(-30px, 30px);}");
}

private Grid<Person> createGridAndFillWithData(int numberOfItems) {
Grid<Person> grid = new Grid<>();
grid.setWidth("100%");

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;
initializeTestFor(left, right, dragSource, dropTarget);
}

private GridDragSource<Person> applyDragSource(Grid<Person> grid) {
@@ -220,17 +141,4 @@ public class GridDragAndDrop extends AbstractTestUIWithLog {
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));
}
}

+ 40
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/GridDraggerOneGrid.java ファイルの表示

@@ -0,0 +1,40 @@
/*
* 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 com.vaadin.annotations.Theme;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.util.Person;
import com.vaadin.ui.Grid;
import com.vaadin.ui.components.grid.GridDragger;

@Theme("valo")
@Widgetset("com.vaadin.DefaultWidgetSet")
public class GridDraggerOneGrid extends AbstractGridDnD {

@Override
protected void setup(VaadinRequest request) {
getUI().setMobileHtml5DndEnabled(true);

Grid<Person> grid = createGridAndFillWithData(50);

GridDragger<Person> gridDragger = new GridDragger<>(grid);

initializeTestFor(gridDragger);
}

}

+ 59
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/GridDraggerTwoGrids.java ファイルの表示

@@ -0,0 +1,59 @@
/*
* 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 com.vaadin.annotations.Theme;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.util.Person;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Grid;
import com.vaadin.ui.components.grid.DropIndexCalculator;
import com.vaadin.ui.components.grid.GridDragger;
import com.vaadin.ui.components.grid.SourceDataProviderUpdater;

@Theme("valo")
@Widgetset("com.vaadin.DefaultWidgetSet")
public class GridDraggerTwoGrids extends AbstractGridDnD {

@Override
protected void setup(VaadinRequest request) {
getUI().setMobileHtml5DndEnabled(true);

// Drag source Grid
Grid<Person> left = createGridAndFillWithData(50);

// Drop target Grid
Grid<Person> right = createGridAndFillWithData(0);

GridDragger<Person> gridDragger = new GridDragger<>(left, right);

CheckBox addItemsToEnd = new CheckBox("Add Items To End", false);
addItemsToEnd.addValueChangeListener(
event -> gridDragger.setDropIndexCalculator(event.getValue()
? DropIndexCalculator.ALWAYS_DROP_TO_END : null));
CheckBox removeItemsFromSource = new CheckBox(
"Remove items from source grid", true);
removeItemsFromSource.addValueChangeListener(event -> gridDragger
.setSourceDataProviderUpdater(event.getValue() ? null
: SourceDataProviderUpdater.NOOP));

controls.addComponents(addItemsToEnd, removeItemsFromSource);

initializeTestFor(gridDragger);
}

}

読み込み中…
キャンセル
保存