Browse Source

Move combo box selection update logic to handler (#19929)

Move logic related to updating the selection to the handler and
VFilterSelect.

Change-Id: I537d3cd23a3e990de1be578a506029c930c55da7
feature/eventbus
Henri Sara 8 years ago
parent
commit
13488e71b0

+ 119
- 8
client/src/main/java/com/vaadin/client/ui/VFilterSelect.java View File

@@ -1487,14 +1487,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
popupOpenerClicked = true;
}

/**
* Returns true if the popup opener has been clicked. This method is for
* internal use only and will most likely be removed in the future.
*/
public boolean isPopupOpenerClicked() {
return popupOpenerClicked;
}

/**
* Cancel a pending request to perform post-filtering actions.
*/
@@ -1540,6 +1532,46 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
suggestionPopup.menu.doPostFilterSelectedItemAction();
}
}

/**
* Perform selection (if appropriate) based on a reply from the server.
* When this method is called, the suggestions have been reset if new
* ones (different from the previous list) were received from the
* server.
*
* @param selectedKey
* new selected key or null if none given by the server
* @param selectedCaption
* new selected item caption if sent by the server or null -
* this is used when the selected item is not on the current
* page
* @param oldSuggestionTextMatchTheOldSelection
* true if the old filtering text box contents matched
* exactly the old selection
*/
public void updateSelectionFromServer(String selectedKey,
String selectedCaption,
boolean oldSuggestionTextMatchTheOldSelection) {
// when filtering with empty filter, server sets the selected key
// to "", which we don't select here. Otherwise we won't be able to
// reset back to the item that was selected before filtering
// started.
if (selectedKey != null && !selectedKey.equals("")) {
performSelection(selectedKey,
oldSuggestionTextMatchTheOldSelection,
!isWaitingForFilteringResponse() || popupOpenerClicked);
} else if (!isWaitingForFilteringResponse()
&& selectedCaption != null) {
// scrolling to correct page is disabled, caption is passed as a
// special parameter
tb.setText(selectedCaption);
} else {
if (!isWaitingForFilteringResponse() || popupOpenerClicked) {
resetSelection();
}
}
}

}

@Deprecated
@@ -2040,6 +2072,85 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
}

/**
* Perform selection based on a message from the server.
*
* This method is called when the server gave a non-empty selected item key,
* whereas null selection is handled by {@link #resetSelection()} and the
* special case where the selected item is not on the current page is
* handled separately by the caller.
*
* @param selectedKey
* non-empty selected item key
* @param oldSuggestionTextMatchTheOldSelection
* true if the suggestion box text matched the previous selection
* before the message from the server updating the selection
* @param updatePromptAndSelectionIfMatchFound
*/
private void performSelection(String selectedKey,
boolean oldSuggestionTextMatchTheOldSelection,
boolean updatePromptAndSelectionIfMatchFound) {
// some item selected
for (FilterSelectSuggestion suggestion : currentSuggestions) {
String suggestionKey = suggestion.getOptionKey();
if (!suggestionKey.equals(selectedKey)) {
continue;
}
// at this point, suggestion key matches the new selection key
if (updatePromptAndSelectionIfMatchFound) {
if (!suggestionKey.equals(selectedOptionKey)
|| suggestion.getReplacementString().equals(
tb.getText())
|| oldSuggestionTextMatchTheOldSelection) {
// Update text field if we've got a new
// selection
// Also update if we've got the same text to
// retain old text selection behavior
// OR if selected item caption is changed.
setPromptingOff(suggestion.getReplacementString());
selectedOptionKey = suggestionKey;
}
}
currentSuggestion = suggestion;
setSelectedItemIcon(suggestion.getIconUri());
// only a single item can be selected
break;
}
}

/**
* Reset the selection of the combo box to an empty string if focused, the
* input prompt if not.
*
* This method also clears the current suggestion and the selected option
* key.
*/
private void resetSelection() {
// select nulled
if (!focused) {
/*
* client.updateComponent overwrites all styles so we must ALWAYS
* set the prompting style at this point, even though we think it
* has been set already...
*/
setPromptingOff("");
if (enabled && !readonly) {
setPromptingOn();
}
} else {
// we have focus in field, prompting can't be set on,
// instead just clear the input if the value has changed from
// something else to null
if (selectedOptionKey != null
|| (allowNewItem && !tb.getValue().isEmpty())) {
tb.setValue("");
}
}
currentSuggestion = null; // #13217
setSelectedItemIcon(null);
selectedOptionKey = null;
}

private void forceReflow() {
WidgetUtil.setStyleTemporarily(tb.getElement(), "zoom", "1");
}

+ 17
- 82
client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java View File

@@ -47,10 +47,6 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
protected FocusAndBlurServerRpc focusAndBlurRpc = RpcProxy.create(
FocusAndBlurServerRpc.class, this);

// oldSuggestionTextMatchTheOldSelection is used to detect when it's safe to
// update textbox text by a changed item caption.
private boolean oldSuggestionTextMatchTheOldSelection;

private boolean immediate;

@Override
@@ -152,10 +148,12 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
// popup. Popup needs to be repopulated with suggestions from UIDL.
boolean popupOpenAndCleared = false;

oldSuggestionTextMatchTheOldSelection = false;
// oldSuggestionTextMatchTheOldSelection is used to detect when it's
// safe to update textbox text by a changed item caption.
boolean oldSuggestionTextMatchesTheOldSelection = false;

if (suggestionsChanged) {
oldSuggestionTextMatchTheOldSelection = isWidgetsCurrentSelectionTextInTextBox();
oldSuggestionTextMatchesTheOldSelection = isWidgetsCurrentSelectionTextInTextBox();
getWidget().currentSuggestions.clear();

if (!getDataReceivedHandler().isWaitingForFilteringResponse()) {
@@ -191,24 +189,21 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
//
) {

// single selected key (can be empty string) or empty array for null
// selection
String[] selectedKeys = uidl.getStringArrayVariable("selected");

// when filtering with empty filter, server sets the selected key
// to "", which we don't select here. Otherwise we won't be able to
// reset back to the item that was selected before filtering
// started.
if (selectedKeys.length > 0 && !selectedKeys[0].equals("")) {
performSelection(selectedKeys[0]);
} else if (!getDataReceivedHandler()
.isWaitingForFilteringResponse()
&& uidl.hasAttribute("selectedCaption")) {
// scrolling to correct page is disabled, caption is passed as a
// special parameter
getWidget().tb.setText(uidl
.getStringAttribute("selectedCaption"));
} else {
resetSelection();
String selectedKey = null;
if (selectedKeys.length == 1) {
selectedKey = selectedKeys[0];
}
// selected item caption in case it is not on the current page
String selectedCaption = null;
if (uidl.hasAttribute("selectedCaption")) {
selectedCaption = uidl.getStringAttribute("selectedCaption");
}

getDataReceivedHandler().updateSelectionFromServer(selectedKey,
selectedCaption, oldSuggestionTextMatchesTheOldSelection);
}

// TODO even this condition should probably be moved to the handler
@@ -241,72 +236,12 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
getDataReceivedHandler().serverReplyHandled();
}

private void performSelection(String selectedKey) {
// some item selected
for (FilterSelectSuggestion suggestion : getWidget().currentSuggestions) {
String suggestionKey = suggestion.getOptionKey();
if (!suggestionKey.equals(selectedKey)) {
continue;
}
if (!getDataReceivedHandler().isWaitingForFilteringResponse()
|| getDataReceivedHandler().isPopupOpenerClicked()) {
if (!suggestionKey.equals(getWidget().selectedOptionKey)
|| suggestion.getReplacementString().equals(
getWidget().tb.getText())
|| oldSuggestionTextMatchTheOldSelection) {
// Update text field if we've got a new
// selection
// Also update if we've got the same text to
// retain old text selection behavior
// OR if selected item caption is changed.
getWidget().setPromptingOff(
suggestion.getReplacementString());
getWidget().selectedOptionKey = suggestionKey;
}
}
getWidget().currentSuggestion = suggestion;
getWidget().setSelectedItemIcon(suggestion.getIconUri());
// only a single item can be selected
break;
}
}

private boolean isWidgetsCurrentSelectionTextInTextBox() {
return getWidget().currentSuggestion != null
&& getWidget().currentSuggestion.getReplacementString().equals(
getWidget().tb.getText());
}

private void resetSelection() {
if (!getDataReceivedHandler().isWaitingForFilteringResponse()
|| getDataReceivedHandler().isPopupOpenerClicked()) {
// select nulled
if (!getWidget().focused) {
/*
* client.updateComponent overwrites all styles so we must
* ALWAYS set the prompting style at this point, even though we
* think it has been set already...
*/
getWidget().setPromptingOff("");
if (getWidget().enabled && !getWidget().readonly) {
getWidget().setPromptingOn();
}
} else {
// we have focus in field, prompting can't be set on, instead
// just clear the input if the value has changed from something
// else to null
if (getWidget().selectedOptionKey != null
|| (getWidget().allowNewItem && !getWidget().tb
.getValue().isEmpty())) {
getWidget().tb.setValue("");
}
}
getWidget().currentSuggestion = null; // #13217
getWidget().setSelectedItemIcon(null);
getWidget().selectedOptionKey = null;
}
}

@Override
public VFilterSelect getWidget() {
return (VFilterSelect) super.getWidget();

Loading…
Cancel
Save