package com.vaadin.client.ui; | package com.vaadin.client.ui; | ||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Date; | |||||
import java.util.HashSet; | |||||
import java.util.List; | |||||
import java.util.Locale; | |||||
import java.util.Set; | |||||
import java.util.UUID; | |||||
import java.util.logging.Logger; | |||||
import com.google.gwt.animation.client.AnimationScheduler; | import com.google.gwt.animation.client.AnimationScheduler; | ||||
import com.google.gwt.aria.client.Roles; | import com.google.gwt.aria.client.Roles; | ||||
import com.google.gwt.core.client.JavaScriptObject; | import com.google.gwt.core.client.JavaScriptObject; | ||||
import com.vaadin.shared.ui.ComponentStateUtil; | import com.vaadin.shared.ui.ComponentStateUtil; | ||||
import com.vaadin.shared.util.SharedUtil; | import com.vaadin.shared.util.SharedUtil; | ||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Date; | |||||
import java.util.HashSet; | |||||
import java.util.List; | |||||
import java.util.Locale; | |||||
import java.util.Set; | |||||
import java.util.logging.Logger; | |||||
/** | /** | ||||
* Client side implementation of the ComboBox component. | * Client side implementation of the ComboBox component. | ||||
* | * | ||||
return $entry(function(e) { | return $entry(function(e) { | ||||
var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX; | var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX; | ||||
var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY; | var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY; | ||||
// IE8 has only delta y | // IE8 has only delta y | ||||
if (isNaN(deltaY)) { | if (isNaN(deltaY)) { | ||||
deltaY = -0.5*e.wheelDelta; | deltaY = -0.5*e.wheelDelta; | ||||
} | } | ||||
@com.vaadin.client.ui.VComboBox.JsniUtil::moveScrollFromEvent(*)(widget, deltaX, deltaY, e, e.deltaMode); | @com.vaadin.client.ui.VComboBox.JsniUtil::moveScrollFromEvent(*)(widget, deltaX, deltaY, e, e.deltaMode); | ||||
}); | }); | ||||
}-*/; | }-*/; | ||||
performSelection(selectedKey, oldSuggestionTextMatchTheOldSelection, | performSelection(selectedKey, oldSuggestionTextMatchTheOldSelection, | ||||
!isWaitingForFilteringResponse() || popupOpenerClicked); | !isWaitingForFilteringResponse() || popupOpenerClicked); | ||||
// currentSuggestion should be set to match the value of the | |||||
// ComboBox, especially when a new item is added. | |||||
resetCurrentSuggestionIfNecessary(selectedKey, selectedCaption, | |||||
selectedIconUri); | |||||
cancelPendingPostFiltering(); | cancelPendingPostFiltering(); | ||||
setSelectedCaption(selectedCaption); | setSelectedCaption(selectedCaption); | ||||
setSelectedItemIcon(selectedIconUri); | setSelectedItemIcon(selectedIconUri); | ||||
} | } | ||||
private void resetCurrentSuggestionIfNecessary(String selectedKey, | |||||
String selectedCaption, String selectedIconUri) { | |||||
if (currentSuggestion == null | |||||
&& (selectedKey != null || selectedCaption != null)) | |||||
currentSuggestion = new ComboBoxSuggestion(selectedKey, | |||||
selectedCaption, "", selectedIconUri); | |||||
else if (selectedKey == null && selectedCaption == null) | |||||
currentSuggestion = null; | |||||
} | |||||
} | } | ||||
// TODO decide whether this should change - affects themes and v7 | // TODO decide whether this should change - affects themes and v7 | ||||
currentSuggestion = null; // #13217 | currentSuggestion = null; // #13217 | ||||
selectedOptionKey = null; | selectedOptionKey = null; | ||||
setText(getEmptySelectionCaption()); | setText(getEmptySelectionCaption()); | ||||
return; | |||||
} | } | ||||
// some item selected | // some item selected | ||||
for (ComboBoxSuggestion suggestion : currentSuggestions) { | for (ComboBoxSuggestion suggestion : currentSuggestions) { |
@Override | @Override | ||||
public void createNewItem(String itemValue) { | public void createNewItem(String itemValue) { | ||||
// New option entered | // New option entered | ||||
boolean added = false; | |||||
boolean clientSideHandling = false; | |||||
if (itemValue != null && !itemValue.isEmpty()) { | if (itemValue != null && !itemValue.isEmpty()) { | ||||
if (getNewItemProvider() != null) { | if (getNewItemProvider() != null) { | ||||
Optional<T> item = getNewItemProvider().apply(itemValue); | |||||
added = item.isPresent(); | |||||
getNewItemProvider().apply(itemValue).ifPresent(value -> { | |||||
// Update state for the newly selected value | |||||
setSelectedItem(value, true); | |||||
getDataCommunicator().reset(); | |||||
}); | |||||
} else if (getNewItemHandler() != null) { | } else if (getNewItemHandler() != null) { | ||||
getNewItemHandler().accept(itemValue); | getNewItemHandler().accept(itemValue); | ||||
// Up to the user to tell if no item was added. | // Up to the user to tell if no item was added. | ||||
added = true; | |||||
clientSideHandling = true; | |||||
} | } | ||||
} | } | ||||
if (!added) { | |||||
// New item was not handled. | |||||
if (!clientSideHandling) { | |||||
// New item was maybe added with NewItemHandler | |||||
getRpcProxy(ComboBoxClientRpc.class).newItemNotAdded(itemValue); | getRpcProxy(ComboBoxClientRpc.class).newItemNotAdded(itemValue); | ||||
} | } | ||||
} | } |
@Override | @Override | ||||
protected void configureNewItemHandling() { | protected void configureNewItemHandling() { | ||||
comboBox.setNewItemProvider(text -> { | comboBox.setNewItemProvider(text -> { | ||||
if (Boolean.TRUE.equals(delay.getValue())) { | |||||
if (delay.getValue()) { | |||||
try { | try { | ||||
Thread.sleep(2000); | Thread.sleep(2000); | ||||
} catch (InterruptedException e1) { | } catch (InterruptedException e1) { | ||||
valueChangeLabel | valueChangeLabel | ||||
.setValue("adding new item... count: " + items.size()); | .setValue("adding new item... count: " + items.size()); | ||||
comboBox.getDataProvider().refreshAll(); | comboBox.getDataProvider().refreshAll(); | ||||
if (Boolean.TRUE.equals(noSelection.getValue())) { | |||||
if (noSelection.getValue()) { | |||||
return Optional.empty(); | return Optional.empty(); | ||||
} | } | ||||
} | } |
package com.vaadin.tests.components.combobox; | package com.vaadin.tests.components.combobox; | ||||
import static org.junit.Assert.assertTrue; | |||||
import static org.junit.Assert.assertEquals; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.openqa.selenium.Keys; | import org.openqa.selenium.Keys; | ||||
} | } | ||||
private void assertValueChange(int count) { | private void assertValueChange(int count) { | ||||
assertTrue(changeLabelElement.getText().equals(String.format( | |||||
assertEquals(String.format( | |||||
"Value change count: %s Selection change count: %s user originated: true", | "Value change count: %s Selection change count: %s user originated: true", | ||||
count, count))); | |||||
count, count), changeLabelElement.getText()); | |||||
} | } | ||||
private void assertRejected(String value) { | private void assertRejected(String value) { | ||||
assertTrue(changeLabelElement.getText() | |||||
.equals(String.format("item %s discarded", value))); | |||||
assertEquals(String.format("item %s discarded", value), | |||||
changeLabelElement.getText()); | |||||
} | } | ||||
private void assertItemCount(int count) { | private void assertItemCount(int count) { | ||||
assertTrue(changeLabelElement.getText() | |||||
.equals(String.format("adding new item... count: %s", count))); | |||||
assertEquals(String.format("adding new item... count: %s", count), | |||||
changeLabelElement.getText()); | |||||
} | } | ||||
private void reject(boolean reject) { | private void reject(boolean reject) { |