From 13488e71b0acc95b4c3ed382302b9317a9d5a84d Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Wed, 11 Nov 2015 12:27:03 +0200 Subject: [PATCH] Move combo box selection update logic to handler (#19929) Move logic related to updating the selection to the handler and VFilterSelect. Change-Id: I537d3cd23a3e990de1be578a506029c930c55da7 --- .../com/vaadin/client/ui/VFilterSelect.java | 127 ++++++++++++++++-- .../client/ui/combobox/ComboBoxConnector.java | 99 +++----------- 2 files changed, 136 insertions(+), 90 deletions(-) diff --git a/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java b/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java index ab62da6550..98f25cccbc 100644 --- a/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java @@ -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"); } diff --git a/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java index 34fd561388..f0c71d76a2 100644 --- a/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java @@ -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(); -- 2.39.5