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.9KB

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