Makes SuggestBox implement HasEnabled, fixing GWT issue 6530

Review by rjrjr: http://gwt-code-reviews.appspot.com/1567803/

Review by: skybrian@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10703 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestBox.java b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
index 7a1f431..8f72305 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestBox.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
@@ -105,7 +105,7 @@
  */
 @SuppressWarnings("deprecation")
 public class SuggestBox extends Composite implements HasText, HasFocus,
-    HasAnimation, SourcesClickEvents, SourcesChangeEvents,
+    HasAnimation, HasEnabled, SourcesClickEvents, SourcesChangeEvents,
     SourcesKeyboardEvents, FiresSuggestionEvents, HasAllKeyHandlers,
     HasValue<String>, HasSelectionHandlers<Suggestion>,
     IsEditor<LeafValueEditor<String>> {
@@ -567,15 +567,6 @@
       setFocusOnHoverEnabled(false);
     }
 
-    public void doSelectedItemAction() {
-      // In order to perform the action of the item that is currently
-      // selected, the menu must be showing.
-      MenuItem selectedItem = getSelectedItem();
-      if (selectedItem != null) {
-        doItemAction(selectedItem, true, false);
-      }
-    }
-
     public int getNumItems() {
       return getItems().size();
     }
@@ -618,7 +609,6 @@
    */
   private static class SuggestionMenuItem extends MenuItem {
 
-    @SuppressWarnings("hiding")
     private static final String STYLENAME_DEFAULT = "item";
 
     private Suggestion suggestion;
@@ -679,6 +669,10 @@
   private final TextBoxBase box;
   private final Callback callback = new Callback() {
     public void onSuggestionsReady(Request request, Response response) {
+      // If disabled while request was in-flight, drop it
+      if (!isEnabled()) {
+        return;
+      }
       display.setMoreSuggestions(response.hasMoreSuggestions(), 
           response.getMoreSuggestionsCount());
       display.showSuggestions(SuggestBox.this, response.getSuggestions(),
@@ -923,6 +917,15 @@
   }
 
   /**
+   * Gets whether this widget is enabled.
+   * 
+   * @return <code>true</code> if the widget is enabled
+   */
+  public boolean isEnabled() {
+    return box.isEnabled();
+  }
+
+  /**
    * Check if the {@link DefaultSuggestionDisplay} is showing. Note that this
    * method only has a meaningful return value when the
    * {@link DefaultSuggestionDisplay} is used.
@@ -1012,6 +1015,19 @@
     this.selectsFirstItem = selectsFirstItem;
   }
 
+  /**
+   * Sets whether this widget is enabled.
+   * 
+   * @param enabled <code>true</code> to enable the widget, <code>false</code>
+   *          to disable it
+   */
+  public void setEnabled(boolean enabled) {
+    box.setEnabled(enabled);
+    if (!enabled) {
+      display.hideSuggestions();
+    }
+  }
+
   public void setFocus(boolean focused) {
     box.setFocus(focused);
   }
diff --git a/user/test/com/google/gwt/user/client/ui/SuggestBoxTest.java b/user/test/com/google/gwt/user/client/ui/SuggestBoxTest.java
index 7d2f02a..6492f18 100644
--- a/user/test/com/google/gwt/user/client/ui/SuggestBoxTest.java
+++ b/user/test/com/google/gwt/user/client/ui/SuggestBoxTest.java
@@ -17,8 +17,10 @@
 
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.user.client.ui.MultiWordSuggestOracle.MultiWordSuggestion;
 import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
 import com.google.gwt.user.client.ui.SuggestBox.SuggestionCallback;
+import com.google.gwt.user.client.ui.SuggestOracle.Response;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
 import java.util.ArrayList;
@@ -32,6 +34,20 @@
 public class SuggestBoxTest extends WidgetTestBase {
 
   /**
+   * A SuggestOracle used for testing.
+   */
+  private static class TestOracle extends SuggestOracle {
+    private Request request;
+    private Callback callback;
+
+    @Override
+    public void requestSuggestions(Request request, Callback callback) {
+      this.request = request;
+      this.callback = callback;
+    }
+  }
+
+  /**
    * A SuggestionDisplay used for testing.
    */
   private static class TestSuggestionDisplay extends DefaultSuggestionDisplay {
@@ -195,6 +211,58 @@
     assertFalse(display.isSuggestionListShowing());
   }
 
+  public void testEnabled() {
+    SuggestBox box = createSuggestBox();
+    TestSuggestionDisplay display = (TestSuggestionDisplay) box.getSuggestionDisplay();
+    assertFalse(display.isSuggestionListShowing());
+
+    // Adds suggest box with suggestion showing
+    RootPanel.get().add(box);
+    box.setText("t");
+    box.showSuggestionList();
+    assertTrue(display.isSuggestionListShowing());
+
+    // When the box is disabled
+    box.setEnabled(false);
+
+    // The suggestion list was hidden and the inner text box disabled
+    assertFalse(display.isSuggestionListShowing());
+    assertFalse(box.getTextBox().isEnabled());
+
+    // When the box is re-enabled
+    box.setEnabled(true);
+
+    // The box is re-enabled, but the suggestion list not re-shown
+    assertTrue(box.getTextBox().isEnabled());
+    assertFalse(display.isSuggestionListShowing());
+  }
+
+  public void testDisabledIgnoresLateResponses() {
+    TestOracle oracle = new TestOracle();
+    SuggestBox box = new SuggestBox(oracle, new TextBox(), new TestSuggestionDisplay());
+    TestSuggestionDisplay display = (TestSuggestionDisplay) box.getSuggestionDisplay();
+    assertFalse(display.isSuggestionListShowing());
+
+    // Adds suggest box with suggestion showing
+    RootPanel.get().add(box);
+    box.setText("t");
+    box.showSuggestionList();
+
+    // Waiting for response
+    assertFalse(display.isSuggestionListShowing());
+
+    // The box becomes disabled
+    box.setEnabled(false);
+
+    // Response comes back after that
+    Collection<MultiWordSuggestion> suggestions = new ArrayList<MultiWordSuggestion>();
+    suggestions.add(new MultiWordSuggestion("one", "one"));
+    oracle.callback.onSuggestionsReady(oracle.request, new Response(suggestions));
+
+    // The suggestion list stays hidden
+    assertFalse(display.isSuggestionListShowing());
+  }
+
   public void testDefaults() {
     MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
     oracle.setDefaultSuggestionsFromText(Arrays.asList("A", "B"));