Move logic related to updating the selection to the handler and VFilterSelect. Change-Id: I537d3cd23a3e990de1be578a506029c930c55da7feature/eventbus
@@ -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"); | |||
} |
@@ -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(); |