1 16 package com.google.gwt.user.client.ui; 17 18 import com.google.gwt.user.client.ui.SuggestOracle.Callback; 19 import com.google.gwt.user.client.ui.SuggestOracle.Request; 20 import com.google.gwt.user.client.ui.SuggestOracle.Response; 21 import com.google.gwt.user.client.ui.impl.ItemPickerDropDownImpl; 22 import com.google.gwt.user.client.ui.impl.SuggestPickerImpl; 23 24 import java.util.Collection ; 25 26 69 public final class SuggestBox extends Composite implements HasText, HasFocus, 70 SourcesClickEvents, SourcesFocusEvents, SourcesChangeEvents, 71 SourcesKeyboardEvents { 72 73 private static final String STYLENAME_DEFAULT = "gwt-SuggestBox"; 74 75 private int limit = 20; 76 private int selectStart; 77 private int selectEnd; 78 private SuggestOracle oracle; 79 private char[] separators; 80 private String currentValue; 81 private final PopupPanel popup; 82 private final SuggestPickerImpl picker; 83 private final TextBoxBase box; 84 private DelegatingClickListenerCollection clickListeners; 85 private DelegatingChangeListenerCollection changeListeners; 86 private DelegatingFocusListenerCollection focusListeners; 87 private DelegatingKeyboardListenerCollection keyboardListeners; 88 private String separatorPadding = ""; 89 90 private final Callback callBack = new Callback() { 91 public void onSuggestionsReady(Request request, Response response) { 92 showSuggestions(response.getSuggestions()); 93 } 94 }; 95 96 101 public SuggestBox() { 102 this(new MultiWordSuggestOracle()); 103 } 104 105 111 public SuggestBox(SuggestOracle oracle) { 112 this(oracle, new TextBox()); 113 } 114 115 123 public SuggestBox(SuggestOracle oracle, TextBoxBase box) { 124 this.box = box; 125 initWidget(box); 126 this.picker = new SuggestPickerImpl(oracle.isDisplayStringHTML()); 127 this.popup = new ItemPickerDropDownImpl(this, picker); 128 addPopupChangeListener(); 129 addKeyboardSupport(); 130 setOracle(oracle); 131 setStyleName(STYLENAME_DEFAULT); 132 } 133 134 public final void addChangeListener(ChangeListener listener) { 135 if (changeListeners == null) { 136 changeListeners = new DelegatingChangeListenerCollection(this, box); 137 } 138 changeListeners.add(listener); 139 } 140 141 public final void addClickListener(ClickListener listener) { 142 if (clickListeners == null) { 143 clickListeners = new DelegatingClickListenerCollection(this, box); 144 } 145 clickListeners.add(listener); 146 } 147 148 public final void addFocusListener(FocusListener listener) { 149 if (focusListeners == null) { 150 focusListeners = new DelegatingFocusListenerCollection(this, box); 151 } 152 focusListeners.add(listener); 153 } 154 155 public final void addKeyboardListener(KeyboardListener listener) { 156 if (keyboardListeners == null) { 157 keyboardListeners = new DelegatingKeyboardListenerCollection(this, box); 158 } 159 keyboardListeners.add(listener); 160 } 161 162 169 public final int getLimit() { 170 return limit; 171 } 172 173 178 public final SuggestOracle getSuggestOracle() { 179 return oracle; 180 } 181 182 public final int getTabIndex() { 183 return box.getTabIndex(); 184 } 185 186 public final String getText() { 187 return box.getText(); 188 } 189 190 public final void removeChangeListener(ChangeListener listener) { 191 if (clickListeners != null) { 192 clickListeners.remove(listener); 193 } 194 } 195 196 public final void removeClickListener(ClickListener listener) { 197 if (clickListeners != null) { 198 clickListeners.remove(listener); 199 } 200 } 201 202 public final void removeFocusListener(FocusListener listener) { 203 if (focusListeners != null) { 204 focusListeners.remove(listener); 205 } 206 } 207 208 public final void removeKeyboardListener(KeyboardListener listener) { 209 if (keyboardListeners != null) { 210 keyboardListeners.remove(listener); 211 } 212 } 213 214 public final void setAccessKey(char key) { 215 box.setAccessKey(key); 216 } 217 218 public final void setFocus(boolean focused) { 219 box.setFocus(focused); 220 } 221 222 228 public final void setLimit(int limit) { 229 this.limit = limit; 230 } 231 232 public final void setTabIndex(int index) { 233 box.setTabIndex(index); 234 } 235 236 public final void setText(String text) { 237 box.setText(text); 238 } 239 240 245 private void showSuggestions(Collection suggestions) { 246 if (suggestions.size() > 0) { 247 picker.setItems(suggestions); 248 popup.show(); 249 } else { 250 popup.hide(); 251 } 252 } 253 254 private void addKeyboardSupport() { 255 box.addKeyboardListener(new KeyboardListenerAdapter() { 256 private boolean pendingCancel; 257 258 public void onKeyDown(Widget sender, char keyCode, int modifiers) { 259 pendingCancel = picker.delegateKeyDown(keyCode); 260 } 261 262 public void onKeyPress(Widget sender, char keyCode, int modifiers) { 263 if (pendingCancel) { 264 box.cancelKey(); 267 pendingCancel = false; 268 } else if (popup.isAttached()) { 269 if (separators != null && isSeparator(keyCode)) { 270 picker.commitSelection(); 274 275 box.cancelKey(); 279 } 280 } 281 } 282 283 public void onKeyUp(Widget sender, char keyCode, int modifiers) { 284 refreshSuggestions(); 286 } 287 288 291 private String getActiveSelection(String text) { 292 selectEnd = box.getCursorPos(); 293 294 selectStart = -1; 296 for (int i = 0; i < separators.length; i++) { 297 selectStart = Math.max( 298 text.lastIndexOf(separators[i], selectEnd - 1), selectStart); 299 } 300 ++selectStart; 301 302 return text.substring(selectStart, selectEnd).trim(); 303 } 304 305 private void refreshSuggestions() { 306 String text = box.getText(); 308 if (text.equals(currentValue)) { 309 return; 310 } else { 311 currentValue = text; 312 } 313 314 String selection; 316 if (separators == null) { 317 selection = text; 318 } else { 319 selection = getActiveSelection(text); 320 } 321 if (selection.length() == 0) { 323 popup.hide(); 324 } else { 325 showSuggestions(selection); 326 } 327 } 328 }); 329 } 330 331 334 private void addPopupChangeListener() { 335 picker.addChangeListener(new ChangeListener() { 336 public void onChange(Widget sender) { 337 if (separators != null) { 338 onChangeWithSeparators(); 339 } else { 340 currentValue = picker.getSelectedValue().toString(); 341 box.setText(currentValue); 342 } 343 if (changeListeners != null) { 344 changeListeners.fireChange(SuggestBox.this); 345 } 346 } 347 348 private void onChangeWithSeparators() { 349 String newValue = (String ) picker.getSelectedValue(); 350 351 StringBuffer accum = new StringBuffer (); 352 String text = box.getText(); 353 354 accum.append(text.substring(0, selectStart)); 356 357 if (selectStart > 0) { 359 accum.append(separatorPadding); 360 } 361 accum.append(newValue); 363 364 int savedCursorPos = accum.length(); 366 367 String ender = text.substring(selectEnd).trim(); 369 if (ender.length() == 0 || !isSeparator(ender.charAt(0))) { 370 accum.append(separators[0]).append(separatorPadding); 373 savedCursorPos = accum.length(); 374 } 375 accum.append(ender); 376 377 String replacement = accum.toString(); 379 currentValue = replacement.trim(); 380 box.setText(replacement); 381 box.setCursorPos(savedCursorPos); 382 } 383 }); 384 } 385 386 389 private boolean isSeparator(char candidate) { 390 for (int i = 0; i < separators.length; i++) { 392 if (candidate == separators[i]) { 393 return true; 394 } 395 } 396 return false; 397 } 398 399 404 private void setOracle(SuggestOracle oracle) { 405 this.oracle = oracle; 406 } 407 408 private void showSuggestions(String query) { 409 oracle.requestSuggestions(new Request(query, limit), callBack); 410 } 411 } 412 | Popular Tags |