You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ComboBoxConnector.java 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.Iterator;
  6. import com.google.gwt.core.client.GWT;
  7. import com.google.gwt.user.client.ui.Widget;
  8. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  9. import com.vaadin.terminal.gwt.client.UIDL;
  10. import com.vaadin.terminal.gwt.client.Util;
  11. import com.vaadin.terminal.gwt.client.ui.VFilterSelect.FilterSelectSuggestion;
  12. public class ComboBoxConnector extends AbstractComponentConnector implements
  13. SimpleManagedLayout {
  14. /*
  15. * (non-Javadoc)
  16. *
  17. * @see
  18. * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
  19. * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
  20. */
  21. @Override
  22. @SuppressWarnings("deprecation")
  23. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  24. // Save details
  25. getWidget().client = client;
  26. getWidget().paintableId = uidl.getId();
  27. getWidget().readonly = getState().isReadOnly();
  28. getWidget().enabled = !getState().isDisabled();
  29. getWidget().tb.setEnabled(getWidget().enabled);
  30. getWidget().updateReadOnly();
  31. super.updateFromUIDL(uidl, client);
  32. if (!isRealUpdate(uidl)) {
  33. return;
  34. }
  35. // Inverse logic here to make the default case (text input enabled)
  36. // work without additional UIDL messages
  37. boolean noTextInput = uidl
  38. .hasAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT)
  39. && uidl.getBooleanAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT);
  40. getWidget().setTextInputEnabled(!noTextInput);
  41. // not a FocusWidget -> needs own tabindex handling
  42. if (uidl.hasAttribute("tabindex")) {
  43. getWidget().tb.setTabIndex(uidl.getIntAttribute("tabindex"));
  44. }
  45. if (uidl.hasAttribute("filteringmode")) {
  46. getWidget().filteringmode = uidl.getIntAttribute("filteringmode");
  47. }
  48. getWidget().immediate = getState().isImmediate();
  49. getWidget().nullSelectionAllowed = uidl.hasAttribute("nullselect");
  50. getWidget().nullSelectItem = uidl.hasAttribute("nullselectitem")
  51. && uidl.getBooleanAttribute("nullselectitem");
  52. getWidget().currentPage = uidl.getIntVariable("page");
  53. if (uidl.hasAttribute("pagelength")) {
  54. getWidget().pageLength = uidl.getIntAttribute("pagelength");
  55. }
  56. if (uidl.hasAttribute(VFilterSelect.ATTR_INPUTPROMPT)) {
  57. // input prompt changed from server
  58. getWidget().inputPrompt = uidl
  59. .getStringAttribute(VFilterSelect.ATTR_INPUTPROMPT);
  60. } else {
  61. getWidget().inputPrompt = "";
  62. }
  63. getWidget().suggestionPopup.updateStyleNames(uidl, getState());
  64. getWidget().allowNewItem = uidl.hasAttribute("allownewitem");
  65. getWidget().lastNewItemString = null;
  66. getWidget().currentSuggestions.clear();
  67. if (!getWidget().waitingForFilteringResponse) {
  68. /*
  69. * Clear the current suggestions as the server response always
  70. * includes the new ones. Exception is when filtering, then we need
  71. * to retain the value if the user does not select any of the
  72. * options matching the filter.
  73. */
  74. getWidget().currentSuggestion = null;
  75. /*
  76. * Also ensure no old items in menu. Unless cleared the old values
  77. * may cause odd effects on blur events. Suggestions in menu might
  78. * not necessary exist in select at all anymore.
  79. */
  80. getWidget().suggestionPopup.menu.clearItems();
  81. }
  82. final UIDL options = uidl.getChildUIDL(0);
  83. if (uidl.hasAttribute("totalMatches")) {
  84. getWidget().totalMatches = uidl.getIntAttribute("totalMatches");
  85. } else {
  86. getWidget().totalMatches = 0;
  87. }
  88. // used only to calculate minimum popup width
  89. String captions = Util.escapeHTML(getWidget().inputPrompt);
  90. for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) {
  91. final UIDL optionUidl = (UIDL) i.next();
  92. final FilterSelectSuggestion suggestion = getWidget().new FilterSelectSuggestion(
  93. optionUidl);
  94. getWidget().currentSuggestions.add(suggestion);
  95. if (optionUidl.hasAttribute("selected")) {
  96. if (!getWidget().waitingForFilteringResponse
  97. || getWidget().popupOpenerClicked) {
  98. String newSelectedOptionKey = Integer.toString(suggestion
  99. .getOptionKey());
  100. if (!newSelectedOptionKey
  101. .equals(getWidget().selectedOptionKey)
  102. || suggestion.getReplacementString().equals(
  103. getWidget().tb.getText())) {
  104. // Update text field if we've got a new selection
  105. // Also update if we've got the same text to retain old
  106. // text selection behavior
  107. getWidget().setPromptingOff(
  108. suggestion.getReplacementString());
  109. getWidget().selectedOptionKey = newSelectedOptionKey;
  110. }
  111. }
  112. getWidget().currentSuggestion = suggestion;
  113. getWidget().setSelectedItemIcon(suggestion.getIconUri());
  114. }
  115. // Collect captions so we can calculate minimum width for textarea
  116. if (captions.length() > 0) {
  117. captions += "|";
  118. }
  119. captions += Util.escapeHTML(suggestion.getReplacementString());
  120. }
  121. if ((!getWidget().waitingForFilteringResponse || getWidget().popupOpenerClicked)
  122. && uidl.hasVariable("selected")
  123. && uidl.getStringArrayVariable("selected").length == 0) {
  124. // select nulled
  125. if (!getWidget().waitingForFilteringResponse
  126. || !getWidget().popupOpenerClicked) {
  127. if (!getWidget().focused) {
  128. /*
  129. * client.updateComponent overwrites all styles so we must
  130. * ALWAYS set the prompting style at this point, even though
  131. * we think it has been set already...
  132. */
  133. getWidget().prompting = false;
  134. getWidget().setPromptingOn();
  135. } else {
  136. // we have focus in field, prompting can't be set on,
  137. // instead just clear the input
  138. getWidget().tb.setValue("");
  139. }
  140. }
  141. getWidget().setSelectedItemIcon(null);
  142. getWidget().selectedOptionKey = null;
  143. }
  144. if (getWidget().waitingForFilteringResponse
  145. && getWidget().lastFilter.toLowerCase().equals(
  146. uidl.getStringVariable("filter"))) {
  147. getWidget().suggestionPopup.showSuggestions(
  148. getWidget().currentSuggestions, getWidget().currentPage,
  149. getWidget().totalMatches);
  150. getWidget().waitingForFilteringResponse = false;
  151. if (!getWidget().popupOpenerClicked
  152. && getWidget().selectPopupItemWhenResponseIsReceived != VFilterSelect.Select.NONE) {
  153. // we're paging w/ arrows
  154. if (getWidget().selectPopupItemWhenResponseIsReceived == VFilterSelect.Select.LAST) {
  155. getWidget().suggestionPopup.menu.selectLastItem();
  156. } else {
  157. getWidget().suggestionPopup.menu.selectFirstItem();
  158. }
  159. // This is used for paging so we update the keyboard selection
  160. // variable as well.
  161. MenuItem activeMenuItem = getWidget().suggestionPopup.menu
  162. .getSelectedItem();
  163. getWidget().suggestionPopup.menu
  164. .setKeyboardSelectedItem(activeMenuItem);
  165. // Update text field to contain the correct text
  166. getWidget().setTextboxText(activeMenuItem.getText());
  167. getWidget().tb.setSelectionRange(
  168. getWidget().lastFilter.length(),
  169. activeMenuItem.getText().length()
  170. - getWidget().lastFilter.length());
  171. getWidget().selectPopupItemWhenResponseIsReceived = VFilterSelect.Select.NONE; // reset
  172. }
  173. if (getWidget().updateSelectionWhenReponseIsReceived) {
  174. getWidget().suggestionPopup.menu
  175. .doPostFilterSelectedItemAction();
  176. }
  177. }
  178. // Calculate minumum textarea width
  179. getWidget().suggestionPopupMinWidth = getWidget().minWidth(captions);
  180. getWidget().popupOpenerClicked = false;
  181. if (!getWidget().initDone) {
  182. getWidget().updateRootWidth();
  183. }
  184. // Focus dependent style names are lost during the update, so we add
  185. // them here back again
  186. if (getWidget().focused) {
  187. getWidget().addStyleDependentName("focus");
  188. }
  189. getWidget().initDone = true;
  190. }
  191. @Override
  192. protected Widget createWidget() {
  193. return GWT.create(VFilterSelect.class);
  194. }
  195. @Override
  196. public VFilterSelect getWidget() {
  197. return (VFilterSelect) super.getWidget();
  198. }
  199. public void layout() {
  200. VFilterSelect widget = getWidget();
  201. if (widget.initDone) {
  202. widget.updateRootWidth();
  203. }
  204. }
  205. }