Browse Source

Add criteria API to make it easier to set acceptance criteria for drag and drop (#9605)

Fixes #9600
tags/8.1.0.rc1
Adam Wagner 6 years ago
parent
commit
6ecef50286

+ 5
- 0
client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java View File

@@ -412,6 +412,11 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector {
for (String type : getState().types) {
orderedData.put(type, getState().data.get(type));
}

// Add payload for comparing against acceptance criteria
getState().payload.values().forEach(payload -> orderedData
.put(payload.getPayloadString(), payload.getValue()));

return orderedData;
}


+ 38
- 4
client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java View File

@@ -17,8 +17,10 @@ package com.vaadin.client.extensions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.DataTransfer;
@@ -34,6 +36,7 @@ import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.DropTargetRpc;
import com.vaadin.shared.ui.dnd.DropTargetState;
import com.vaadin.shared.ui.dnd.criteria.Payload;
import com.vaadin.ui.dnd.DropTargetExtension;

import elemental.events.Event;
@@ -320,12 +323,43 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector {
// Currently Safari, Edge and IE don't follow the spec by allowing drop
// if those don't match

if (getState().dropCriteria != null) {
return executeScript(event, getState().dropCriteria);
// Allow by default when criteria not set
boolean allowed = true;

// Execute criteria script
if (getState().criteriaScript != null) {
allowed = executeScript(event, getState().criteriaScript);
}

// Execute criterion defined via API
if (allowed && getState().criteria != null && !getState().criteria
.isEmpty()) {

// Collect payload data types
Set<Payload> payloadSet = new HashSet<>();
JsArrayString typesJsArray = getTypes(event.getDataTransfer());
for (int i = 0; i < typesJsArray.length(); i++) {
String type = typesJsArray.get(i);

if (type.startsWith(Payload.ITEM_PREFIX)) {
payloadSet.add(Payload.parse(type));
}
}

// Compare payload against criteria
switch (getState().criteriaMatch) {
case ALL:
allowed = getState().criteria.stream()
.allMatch(criterion -> criterion.resolve(payloadSet));
break;
case ANY:
default:
allowed = getState().criteria.stream()
.anyMatch(criterion -> criterion.resolve(payloadSet));
}
}

// Allow when criteria not set
return true;
return allowed;
}

/**

+ 76
- 7
server/src/main/java/com/vaadin/ui/dnd/DragSourceExtension.java View File

@@ -23,10 +23,12 @@ import java.util.Objects;
import com.vaadin.server.AbstractExtension;
import com.vaadin.server.Resource;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.dnd.criteria.ComparisonOperator;
import com.vaadin.shared.ui.dnd.DragSourceRpc;
import com.vaadin.shared.ui.dnd.DragSourceState;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.EffectAllowed;
import com.vaadin.shared.ui.dnd.criteria.Payload;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.dnd.event.DragEndEvent;
import com.vaadin.ui.dnd.event.DragEndListener;
@@ -38,7 +40,7 @@ import com.vaadin.ui.dnd.event.DragStartListener;
* functionality.
*
* @param <T>
* Type of the component to be extended.
* Type of the component to be extended.
* @author Vaadin Ltd
* @since 8.1
*/
@@ -58,7 +60,7 @@ public class DragSourceExtension<T extends AbstractComponent>
* Extends {@code target} component and makes it a drag source.
*
* @param target
* Component to be extended.
* Component to be extended.
*/
public DragSourceExtension(T target) {
super.extend(target);
@@ -125,7 +127,7 @@ public class DragSourceExtension<T extends AbstractComponent>
* side. Fires the {@link DragEndEvent}.
*
* @param dropEffect
* the drop effect on the dragend
* the drop effect on the dragend
*/
protected void onDragEnd(DropEffect dropEffect) {
DragEndEvent<T> event = new DragEndEvent<>(getParent(), dropEffect);
@@ -150,7 +152,7 @@ public class DragSourceExtension<T extends AbstractComponent>
* equivalent to {@link EffectAllowed#ALL}.
*
* @param effect
* Effects to allow for this draggable element. Cannot be {@code
* Effects to allow for this draggable element. Cannot be {@code
* null}.
*/
public void setEffectAllowed(EffectAllowed effect) {
@@ -293,6 +295,73 @@ public class DragSourceExtension<T extends AbstractComponent>
getState().data.clear();
}

/**
* Sets payload for this drag source to use with acceptance criterion. The
* payload is transferred as data type in the data transfer object in the
* following format: {@code "v-item:string:key:value"}. The given value is
* compared to the criterion value when the drag source is dragged on top of
* a drop target that has the suitable criterion.
* <p>
* Note that setting payload in Internet Explorer 11 is not possible due to
* the browser's limitations.
*
* @param key
* key of the payload to be transferred
* @param value
* value of the payload to be transferred
* @see DropTargetExtension#setDropCriterion(String, String)
*/
public void setPayload(String key, String value) {
setPayload(key, String.valueOf(value), Payload.ValueType.STRING);
}

/**
* Sets payload for this drag source to use with acceptance criterion. The
* payload is transferred as data type in the data transfer object in the
* following format: {@code "v-item:integer:key:value"}. The given value is
* compared to the criterion value when the drag source is dragged on top of
* a drop target that has the suitable criterion.
* <p>
* Note that setting payload in Internet Explorer 11 is not possible due to
* the browser's limitations.
*
* @param key
* key of the payload to be transferred
* @param value
* value of the payload to be transferred
* @see DropTargetExtension#setDropCriterion(String, ComparisonOperator,
* int)
*/
public void setPayload(String key, int value) {
setPayload(key, String.valueOf(value), Payload.ValueType.INTEGER);
}

/**
* Sets payload for this drag source to use with acceptance criterion. The
* payload is transferred as data type in the data transfer object in the
* following format: {@code "v-item:double:key:value"}. The given value is
* compared to the criterion value when the drag source is dragged on top of
* a drop target that has the suitable criterion.
* <p>
* Note that setting payload in Internet Explorer 11 is not possible due to
* the browser's limitations.
*
* @param key
* key of the payload to be transferred
* @param value
* value of the payload to be transferred
* @see DropTargetExtension#setDropCriterion(String, ComparisonOperator,
* double)
*/
public void setPayload(String key, double value) {
setPayload(key, String.valueOf(value), Payload.ValueType.DOUBLE);
}

private void setPayload(String key, String value,
Payload.ValueType valueType) {
getState().payload.put(key, new Payload(key, value, valueType));
}

/**
* Set server side drag data. This data is available in the drop event and
* can be used to transfer data between drag source and drop target if they
@@ -322,7 +391,7 @@ public class DragSourceExtension<T extends AbstractComponent>
* dragstart event happens on the client side.
*
* @param listener
* Listener to handle dragstart event.
* Listener to handle dragstart event.
* @return Handle to be used to remove this listener.
*/
public Registration addDragStartListener(DragStartListener<T> listener) {
@@ -337,7 +406,7 @@ public class DragSourceExtension<T extends AbstractComponent>
* event happens on the client side.
*
* @param listener
* Listener to handle dragend event.
* Listener to handle dragend event.
* @return Handle to be used to remove this listener.
*/
public Registration addDragEndListener(DragEndListener<T> listener) {
@@ -349,7 +418,7 @@ public class DragSourceExtension<T extends AbstractComponent>
* Set a custom drag image for the current drag source.
*
* @param imageResource
* Resource of the image to be displayed as drag image.
* Resource of the image to be displayed as drag image.
*/
public void setDragImage(Resource imageResource) {
setResource(DragSourceState.RESOURCE_DRAG_IMAGE, imageResource);

+ 133
- 15
server/src/main/java/com/vaadin/ui/dnd/DropTargetExtension.java View File

@@ -15,6 +15,7 @@
*/
package com.vaadin.ui.dnd;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -23,9 +24,11 @@ import java.util.Objects;
import com.vaadin.server.AbstractExtension;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.dnd.criteria.ComparisonOperator;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.DropTargetRpc;
import com.vaadin.shared.ui.dnd.DropTargetState;
import com.vaadin.shared.ui.dnd.criteria.Criterion;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.dnd.event.DropEvent;
import com.vaadin.ui.dnd.event.DropListener;
@@ -146,9 +149,13 @@ public class DropTargetExtension<T extends AbstractComponent>
/**
* Sets a criteria script in JavaScript to allow drop on this drop target.
* The script is executed when something is dragged on top of the target,
* and the drop is not allowed in case the script returns {@code false}. If
* no script is set, then the drop is always accepted, if the set
* {@link #setDropEffect(DropEffect) dropEffect} matches the drag source.
* and the drop is not allowed in case the script returns {@code false}.
* <p>
* Drop will be allowed if it passes both this criteria script and the
* criteria set via any of {@code setDropCriterion()} or {@code
* setDropCriteria()} methods. If no criteria is set, then the drop is
* always accepted, if the set {@link #setDropEffect(DropEffect) dropEffect}
* matches the drag source.
* <p>
* <b>IMPORTANT:</b> Construct the criteria script carefully and do not
* include untrusted sources such as user input. Always keep in mind that
@@ -157,22 +164,23 @@ public class DropTargetExtension<T extends AbstractComponent>
* Example:
*
* <pre>
* target.setDropCriteria(
* // If dragged source contains a URL, allow it to be dropped
* "if (event.dataTransfer.types.includes('text/uri-list')) {"
* + " return true;" + "}" +
* target.setDropCriterion(
* // If dragged source contains a URL, allow it to be dropped
* "if (event.dataTransfer.types.includes('text/uri-list')) {" +
* " return true;" +
* "}" +
*
* // Otherwise cancel the event"
* "return false;");
* // Otherwise cancel the event
* "return false;");
* </pre>
*
* @param criteriaScript
* JavaScript to be executed when drop event happens or
* {@code null} to clear.
*/
public void setDropCriteria(String criteriaScript) {
if (!Objects.equals(getState(false).dropCriteria, criteriaScript)) {
getState().dropCriteria = criteriaScript;
public void setDropCriteriaScript(String criteriaScript) {
if (!Objects.equals(getState(false).criteriaScript, criteriaScript)) {
getState().criteriaScript = criteriaScript;
}
}

@@ -182,10 +190,120 @@ public class DropTargetExtension<T extends AbstractComponent>
* allowed.
*
* @return JavaScript that executes when drop event happens.
* @see #setDropCriteria(String)
* @see #setDropCriteriaScript(String)
*/
public String getDropCriteriaScript() {
return getState(false).criteriaScript;
}

/**
* Set a drop criterion to allow drop on this drop target. When data is
* dragged on top of the drop target, the given value is compared to the
* drag source's payload with the same key. The drag passes this criterion
* if the value of the payload and the value given here are equal.
* <p>
* Note that calling this method will overwrite the previously set criteria.
* To set multiple criteria, call the {@link #setDropCriteria(Criterion.Match,
* Criterion...)} method.
* <p>
* To handle more complex criteria, define a custom script with {@link
* #setDropCriteriaScript(String)}. Drop will be allowed if both this
* criterion and the criteria script are passed.
*
* @param key
* key of the payload to be compared
* @param value
* value to be compared to the payload's value
* @see DragSourceExtension#setPayload(String, String)
*/
public void setDropCriterion(String key, String value) {
setDropCriteria(Criterion.Match.ANY, new Criterion(key, value));
}

/**
* Set a drop criterion to allow drop on this drop target. When data is
* dragged on top of the drop target, the given value is compared to the
* drag source's payload with the same key. The drag passes this criterion
* if the value of the payload compared to the given value using the given
* operator holds.
* <p>
* Note that calling this method will overwrite the previously set criteria.
* To set multiple criteria, call the {@link #setDropCriteria(Criterion.Match,
* Criterion...)} method.
* <p>
* To handle more complex criteria, define a custom script with {@link
* #setDropCriteriaScript(String)}. Drop will be allowed if both this
* criterion and the criteria script are passed.
*
* @param key
* key of the payload to be compared
* @param operator
* comparison operator to be used
* @param value
* value to be compared to the payload's value
* @see DragSourceExtension#setPayload(String, int)
*/
public void setDropCriterion(String key, ComparisonOperator operator,
int value) {
setDropCriteria(Criterion.Match.ANY,
new Criterion(key, operator, value));
}

/**
* Set a drop criterion to allow drop on this drop target. When data is
* dragged on top of the drop target, the given value is compared to the
* drag source's payload with the same key. The drag passes this criterion
* if the value of the payload compared to the given value using the given
* operator holds.
* <p>
* Note that calling this method will overwrite the previously set criteria.
* To set multiple criteria, call the {@link #setDropCriteria(Criterion.Match,
* Criterion...)} method.
* <p>
* To handle more complex criteria, define a custom script with {@link
* #setDropCriteriaScript(String)}. Drop will be allowed if both this
* criterion and the criteria script are passed.
*
* @param key
* key of the payload to be compared
* @param operator
* comparison operator to be used
* @param value
* value to be compared to the payload's value
* @see DragSourceExtension#setPayload(String, double)
*/
public void setDropCriterion(String key, ComparisonOperator operator,
double value) {
setDropCriteria(Criterion.Match.ANY,
new Criterion(key, operator, value));
}

/**
* Sets multiple drop criteria to allow drop on this drop target. When data
* is dragged on top of the drop target, the value of the given criteria is
* compared to the drag source's payload with the same key.
* <p>
* The drag passes these criteria if, depending on {@code match}, any or all
* of the criteria matches the payload, that is the value of the payload
* compared to the value of the criterion using the criterion's operator
* holds.
* <p>
* Note that calling this method will overwrite the previously set
* criteria.
* <p>
* To handle more complex criteria, define a custom script with {@link
* #setDropCriteriaScript(String)}. Drop will be allowed if both this
* criterion and the criteria script are passed.
*
* @param match
* defines whether any or all of the given criteria should match to
* allow drop on this drop target
* @param criteria
* criteria to be compared to the payload
*/
public String getDropCriteria() {
return getState(false).dropCriteria;
public void setDropCriteria(Criterion.Match match, Criterion... criteria) {
getState().criteriaMatch = match;
getState().criteria = Arrays.asList(criteria);
}

/**

+ 1
- 1
server/src/main/java/com/vaadin/ui/dnd/event/DragEndEvent.java View File

@@ -64,7 +64,7 @@ public class DragEndEvent<T extends AbstractComponent> extends Component.Event {
* dragend event.
* @see DragSourceExtension#setEffectAllowed(EffectAllowed)
* @see DropTargetExtension#setDropEffect(DropEffect)
* @see DropTargetExtension#setDropCriteria(String)
* @see DropTargetExtension#setDropCriteriaScript(String)
*/
public DropEffect getDropEffect() {
return dropEffect;

+ 7
- 0
shared/src/main/java/com/vaadin/shared/ui/dnd/DragSourceState.java View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map;

import com.vaadin.shared.communication.SharedState;
import com.vaadin.shared.ui.dnd.criteria.Payload;

/**
* State class containing parameters for DragSourceExtension.
@@ -75,4 +76,10 @@ public class DragSourceState extends SharedState {
* Used to store data in the {@code DataTransfer} object for the drag event.
*/
public Map<String, String> data = new HashMap<>();

/**
* Payload for comparing against acceptance criteria. Transferred in the
* {@code DataTransfer} object as data type.
*/
public Map<String, Payload> payload = new HashMap<>();
}

+ 16
- 1
shared/src/main/java/com/vaadin/shared/ui/dnd/DropTargetState.java View File

@@ -15,7 +15,11 @@
*/
package com.vaadin.shared.ui.dnd;

import java.util.ArrayList;
import java.util.List;

import com.vaadin.shared.communication.SharedState;
import com.vaadin.shared.ui.dnd.criteria.Criterion;

/**
* State class containing parameters for DropTargetExtension.
@@ -32,5 +36,16 @@ public class DropTargetState extends SharedState {
/**
* Criteria script to allow drop event on the element
*/
public String dropCriteria;
public String criteriaScript;

/**
* List of criteria to compare against the payload.
*/
public List<Criterion> criteria = new ArrayList<>();

/**
* Declares whether any or all of the given criteria should match the
* payload
*/
public Criterion.Match criteriaMatch = Criterion.Match.ANY;
}

+ 55
- 0
shared/src/main/java/com/vaadin/shared/ui/dnd/criteria/ComparisonOperator.java View File

@@ -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.shared.ui.dnd.criteria;

/**
* Comparison operator for drag and drop acceptance criterion.
*
* @author Vaadin Ltd.
* @since 8.1
*/
public enum ComparisonOperator {

/**
* Smaller than operator ("<").
*/
SMALLER_THAN,

/**
* Smaller than or equals to operator ("<=").
*/
SMALLER_THAN_OR_EQUALS,

/**
* Equals to operator ("==").
*/
EQUALS,

/**
* Greater than or equals to operator (">=").
*/
GREATER_THAN_OR_EQUALS,

/**
* Greater than operator (">").
*/
GREATER_THAN,

/**
* Not equals operator ("!=").
*/
NOT_EQUALS
}

+ 215
- 0
shared/src/main/java/com/vaadin/shared/ui/dnd/criteria/Criterion.java View File

@@ -0,0 +1,215 @@
/*
* 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.shared.ui.dnd.criteria;

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

/**
* Stores parameters for the drag and drop acceptance criterion defined using
* the criteria API.
* <p>
* When data is dragged over a drop target, the value here is compared to the
* payload added in DropTargetExtension with same key and value type.
*
* @author Vaadin Ltd
* @since 8.1
*/
public class Criterion implements Serializable {

/**
* Declares whether all or any of the given criteria should match when
* compared against the payload.
*/
public enum Match {
/**
* When compared to the payload, the drop will be accepted if any of the
* criteria matches.
*/
ANY,

/**
* When compared to the payload, the drop will be accepted only if all
* of the given criteria matches.
*/
ALL
}

private String key;
private String value;
private Payload.ValueType valueType;
private ComparisonOperator operator;

/**
* Mandatory zero param constructor.
*/
private Criterion() {

}

/**
* Creates a criterion object with the default comparison operator {@link
* ComparisonOperator#EQUALS}.
*
* @param key
* key of the payload to be compared
* @param value
* value of the payload to be compared
*/
public Criterion(String key, String value) {
this(key, ComparisonOperator.EQUALS, value, Payload.ValueType.STRING);
}

/**
* Creates a criterion object.
*
* @param key
* key of the payload to be compared
* @param operator
* comparison operator
* @param value
* value of the payload to be compared
*/
public Criterion(String key, ComparisonOperator operator, int value) {
this(key, operator, String.valueOf(value), Payload.ValueType.INTEGER);
}

/**
* Creates a criterion object.
*
* @param key
* key of the payload to be compared
* @param operator
* comparison operator
* @param value
* value of the payload to be compared
*/
public Criterion(String key, ComparisonOperator operator, double value) {
this(key, operator, String.valueOf(value), Payload.ValueType.DOUBLE);
}

/**
* Creates a criterion object.
*
* @param key
* key of the payload to be compared
* @param operator
* comparison operator
* @param value
* value of the payload to be compared
* @param valueType
* type of the payload to be compared
*/
private Criterion(String key, ComparisonOperator operator, String value,
Payload.ValueType valueType) {
this.key = key;
this.value = value;
this.valueType = valueType;
this.operator = operator;
}

/**
* Gets the key of the payload to be compared
*
* @return key of the payload to be compared
*/
public String getKey() {
return key;
}

/**
* Gets the value of the payload to be compared
*
* @return value of the payload to be compared
*/
public String getValue() {
return value;
}

/**
* Gets the type of the payload value to be compared
*
* @return type of the payload value to be compared
*/
public Payload.ValueType getValueType() {
return valueType;
}

/**
* Gets the comparison operator.
*
* @return operator to be used when comparing payload value with criterion
*/
public ComparisonOperator getOperator() {
return operator;
}

/**
* Compares this criterion's value to the given payload's value and returns
* whether the result matches the criterion's operator. The comparison is
* done with the payload whose key and value type match the criterion's key
* and value type.
*
* @param payloadCollection
* collection of payloads to compare the criterion against
* @return {@code false} if there exists a payload in the collection with
* the same key and value type and it doesn't match the criterion, {@code
* true} otherwise
*/
public boolean resolve(Collection<Payload> payloadCollection) {
Optional<Payload> payload = payloadCollection.stream()
.filter(p -> p.getKey().equals(key) && p.getValueType()
.equals(valueType)).findAny();

return payload.map(this::compareCriterionValue).orElse(true);
}

private boolean compareCriterionValue(Payload payload) {
int result;

switch (valueType) {
case STRING:
default:
result = value.compareTo(payload.getValue());
break;
case INTEGER:
result = Integer.valueOf(value)
.compareTo(Integer.valueOf(payload.getValue()));
break;
case DOUBLE:
result = Double.valueOf(value)
.compareTo(Double.valueOf(payload.getValue()));
break;
}

switch (operator) {
case SMALLER_THAN:
return result < 0;
case SMALLER_THAN_OR_EQUALS:
return result <= 0;
case EQUALS:
default:
return result == 0;
case GREATER_THAN_OR_EQUALS:
return result >= 0;
case GREATER_THAN:
return result > 0;
case NOT_EQUALS:
return result != 0;
}
}
}

+ 125
- 0
shared/src/main/java/com/vaadin/shared/ui/dnd/criteria/Payload.java View File

@@ -0,0 +1,125 @@
/*
* 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.shared.ui.dnd.criteria;

import java.io.Serializable;

/**
* Stores key/value pairs and the value type. Payload is set in
* DragSourceExtension and is transferred during drag operation. It is used for
* comparing values to acceptance criteria.
*/
public class Payload implements Serializable {

/**
* Type of the payload's value.
*/
public enum ValueType {
STRING, INTEGER, DOUBLE;
}

/**
* Prefix of the payload data type.
*/
public static final String ITEM_PREFIX = "v-item";

private String key;
private String value;
private ValueType valueType;

/**
* Mandatory zero arg constructor.
*/
private Payload() {

}

/**
* Creates a payload object.
*
* @param key
* key of the payload
* @param value
* value of the payload
* @param valueType
* type of the payload value
*/
public Payload(String key, String value, ValueType valueType) {
this.key = key;
this.value = value;
this.valueType = valueType;
}

/**
* Gets the key of this payload.
*
* @return key identifying this payload
*/
public String getKey() {
return key;
}

/**
* Gets the value of this payload.
*
* @return value of this payload
*/
public String getValue() {
return value;
}

/**
* Gets the value type of this payload.
*
* @return the type of the value of this payload
*/
public ValueType getValueType() {
return valueType;
}

/**
* Returns the string representation of this payload. It is used as the data
* type in the {@code DataTransfer} object.
*
* @return the string representation of this payload
*/
public String getPayloadString() {
return ITEM_PREFIX + ":" + valueType.name().toLowerCase() + ":" + key
+ ":" + value;
}

/**
* Parses a payload string and returns a payload object represented by that
* string.
*
* @param payloadString
* string that represents a payload object
* @return a payload object represented by the given string
*/
public static Payload parse(String payloadString) {
String[] parts = payloadString.split(":");

if (parts.length != 4 || !ITEM_PREFIX.equals(parts[0])) {
throw new IllegalArgumentException(
"Data type does not have a valid payload format");
}

// Create payload object of the given parts. Value type is converted to
// upper case to match the enum's case.
return new Payload(parts[2], parts[3],
ValueType.valueOf(parts[1].toUpperCase()));
}
}

+ 18
- 10
uitest/src/main/java/com/vaadin/tests/dnd/DragAndDropCardShuffle.java View File

@@ -22,6 +22,7 @@ import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.Page;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.ui.dnd.criteria.ComparisonOperator;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.EffectAllowed;
import com.vaadin.tests.components.AbstractTestUIWithLog;
@@ -86,20 +87,20 @@ public class DragAndDropCardShuffle extends AbstractTestUIWithLog {
// Create UI and add extensions

ace.setStyleName("card");
addDragSourceExtension(ace);
addDropTargetExtension(ace);
addDragSourceExtension(ace, 14);
addDropTargetExtension(ace, 14);

jack.setStyleName("card");
addDragSourceExtension(jack);
addDropTargetExtension(jack);
addDragSourceExtension(jack, 11);
addDropTargetExtension(jack, 11);

queen.setStyleName("card");
addDragSourceExtension(queen);
addDropTargetExtension(queen);
addDragSourceExtension(queen, 12);
addDropTargetExtension(queen, 12);

king.setStyleName("card");
addDragSourceExtension(king);
addDropTargetExtension(king);
addDragSourceExtension(king, 13);
addDropTargetExtension(king, 13);
}

private void removeExtensions() {
@@ -116,11 +117,14 @@ public class DragAndDropCardShuffle extends AbstractTestUIWithLog {
king.removeExtension(king.getExtensions().iterator().next());
}

private void addDragSourceExtension(Label source) {
private void addDragSourceExtension(Label source, int cardValue) {
// Create and attach extension
DragSourceExtension<Label> dragSource = new DragSourceExtension<>(
source);

// Set card value via criteria API for acceptance criteria
dragSource.setPayload("card_value", cardValue);

// Add listeners
dragSource.addDragStartListener(event -> {
log(event.getComponent().getValue() + " dragstart, effectsAllowed="
@@ -135,11 +139,15 @@ public class DragAndDropCardShuffle extends AbstractTestUIWithLog {
sources.add(dragSource);
}

private void addDropTargetExtension(Label target) {
private void addDropTargetExtension(Label target, int cardValue) {
// Create and attach extension
DropTargetExtension<Label> dropTarget = new DropTargetExtension<>(
target);

// Cards can be dropped onto others with smaller value
dropTarget.setDropCriterion("card_value", ComparisonOperator.SMALLER_THAN,
cardValue);

// Add listener
dropTarget.addDropListener(event -> {
event.getDragSourceExtension().ifPresent(dragSource -> {

Loading…
Cancel
Save