Revision: 9043
Author: p...@google.com
Date: Wed Oct 13 06:23:15 2010
Log: Cherry picking bug fixes from trunk into release branch: 974801, 976801, 887804, 846801, 978801.

http://code.google.com/p/google-web-toolkit/source/detail?r=9043

Modified:
/releases/2.1/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/AddressProxy.java /releases/2.1/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java /releases/2.1/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java /releases/2.1/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java /releases/2.1/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
 /releases/2.1/user/src/com/google/gwt/user/cellview/client/CellList.java
 /releases/2.1/user/src/com/google/gwt/user/client/ui/CheckBox.java
 /releases/2.1/user/src/com/google/gwt/user/client/ui/MenuBar.java
 /releases/2.1/user/src/com/google/gwt/user/client/ui/MenuItem.java
 /releases/2.1/user/src/com/google/gwt/user/client/ui/ToggleButton.java
/releases/2.1/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css /releases/2.1/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css /releases/2.1/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css /releases/2.1/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css /releases/2.1/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css /releases/2.1/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css /releases/2.1/user/test/com/google/gwt/requestfactory/client/FindServiceTest.java /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java /releases/2.1/user/test/com/google/gwt/requestfactory/shared/SimpleBarProxy.java
 /releases/2.1/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java
 /releases/2.1/user/test/com/google/gwt/user/client/ui/MenuBarTest.java

=======================================
--- /releases/2.1/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/AddressProxy.java Tue Sep 21 12:24:16 2010 +++ /releases/2.1/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/AddressProxy.java Wed Oct 13 06:23:15 2010
@@ -27,8 +27,6 @@
 public interface AddressProxy extends EntityProxy {
   String getCity();

-  String getId();
-
   String getState();

   String getStreet();
=======================================
--- /releases/2.1/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java Sun Oct 3 11:35:25 2010 +++ /releases/2.1/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/shared/PersonProxy.java Wed Oct 13 06:23:15 2010
@@ -30,8 +30,6 @@

   String getDescription();

-  String getId();
-
   PersonProxy getMentor();

   String getName();
=======================================
--- /releases/2.1/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java Thu Sep 30 09:09:15 2010 +++ /releases/2.1/user/src/com/google/gwt/logging/server/RemoteLoggingServiceUtil.java Wed Oct 13 06:23:15 2010
@@ -16,8 +16,6 @@

 package com.google.gwt.logging.server;

-import org.json.JSONException;
-
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;

@@ -71,7 +69,9 @@
       lr = JsonLogRecordServerUtil.logRecordFromJson(
           serializedLogRecordJson);
       logOnServer(lr, strongName, deobfuscator, loggerNameOverride);
-    } catch (JSONException e) {
+    } catch (Exception e) {
+ // We don't want to import the JsonException, which will require the json
+      // jar when this class loads, so we just catch all exceptions here
       throw new RemoteLoggingException("Failed to deserialize JSON", e);
     }
   }
=======================================
--- /releases/2.1/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java Fri Oct 1 18:15:55 2010 +++ /releases/2.1/user/src/com/google/gwt/requestfactory/client/impl/EntityProxyCategory.java Wed Oct 13 06:23:15 2010
@@ -49,8 +49,7 @@
     return stableId(bean).hashCode();
   }

-  public static AbstractRequestContext requestContext(
-      AutoBean<? extends EntityProxy> bean) {
+  public static AbstractRequestContext requestContext(AutoBean<?> bean) {
     return (AbstractRequestContext) bean.getTag(REQUEST_CONTEXT);
   }

@@ -70,13 +69,11 @@
    * EntityProxy, that its return values are mutable.
    */
   // CHECKSTYLE_OFF
-  public static <T> T __intercept(AutoBean<? extends EntityProxy> bean,
-      T returnValue) {
+  public static <T> T __intercept(AutoBean<?> bean, T returnValue) {
     // CHECKSTYLE_ON
-    if (!(returnValue instanceof EntityProxy)) {
-      return returnValue;
-    }
+
     AbstractRequestContext context = requestContext(bean);
+
     /*
      * The context will be null if the bean is immutable. If the context is
      * locked, don't try to edit.
@@ -85,8 +82,26 @@
       return returnValue;
     }

-    @SuppressWarnings("unchecked")
-    T toReturn = (T) context.edit((EntityProxy) returnValue);
-    return toReturn;
+    /*
+ * EntityProxies need to be recorded specially by the RequestContext, so
+     * delegate to the edit() method for wiring up the context.
+     */
+    if (returnValue instanceof EntityProxy) {
+      @SuppressWarnings("unchecked")
+      T toReturn = (T) context.edit((EntityProxy) returnValue);
+      return toReturn;
+    }
+
+    /*
+     * We're returning some object that's not an EntityProxy, most likely a
+ * Collection type. At the very least, propagate the current RequestContext
+     * so that editable chains can be constructed.
+     */
+    AutoBean<T> otherBean = AutoBeanUtils.getAutoBean(returnValue);
+    if (otherBean != null) {
+      otherBean.setTag(EntityProxyCategory.REQUEST_CONTEXT,
+          bean.getTag(EntityProxyCategory.REQUEST_CONTEXT));
+    }
+    return returnValue;
   }
 }
=======================================
--- /releases/2.1/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java Wed Oct 6 08:01:28 2010 +++ /releases/2.1/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java Wed Oct 13 06:23:15 2010
@@ -440,19 +440,6 @@
       return encodePropertyValue(returnValue);
     }
   }
-
-  /**
- * Generate an ID for a new record. The default behavior is to return null and
-   * let the data store generate the ID automatically.
-   *
-   * @param key the key of the record field
-   * @return the ID of the new record, or null to auto generate
-   */
- public String generateIdForCreate(@SuppressWarnings("unused") String key) {
-    // TODO(rjrjr) is there any point to this method if a service layer
-    // is coming?
-    return null;
-  }

   /**
* Find the entity in the server data store, apply its setters, capture any
@@ -474,28 +461,19 @@
     validateKeys(recordObject, propertiesInDomain.keySet());

     // get entityInstance
-    Object entityInstance = getEntityInstance(
-        writeOperation,
-        entityType,
- entityKey.decodedId(propertiesInProxy.get(Constants.ENTITY_ID_PROPERTY).getType()),
-        propertiesInProxy.get(Constants.ENTITY_ID_PROPERTY).getType());
-
+    Class<?> idType = getIdMethodForEntity(entityType).getReturnType();
+    Object entityInstance = getEntityInstance(writeOperation, entityType,
+        entityKey.decodedId(idType), idType);
     cachedEntityLookup.put(entityKey, entityInstance);

     Iterator<?> keys = recordObject.keys();
     while (keys.hasNext()) {
       String key = (String) keys.next();
-      Class<?> propertyType = propertiesInDomain.get(key);
       Property<?> dtoProperty = propertiesInProxy.get(key);
       if (writeOperation == WriteOperation.PERSIST
           && (Constants.ENTITY_ID_PROPERTY.equals(key))) {
-        String id = generateIdForCreate(key);
-        if (id != null) {
-          // TODO(rjrjr) generateIdForCreate returns null. Has this ever
-          // execute
-          entityType.getMethod(getMethodNameFromPropertyName(key, "set"),
-              propertyType).invoke(entityInstance, id);
-        }
+        // Don't allow the client to attempt to set the id
+        continue;
       } else {
         Object propertyValue = null;
         if (recordObject.isNull(key)) {
@@ -639,8 +617,10 @@
     for (Property<?> p : allProperties(entityKeyClass)) {
       if (requestedProperty(p, propertyContext)) {
         String propertyName = p.getName();
-        jsonObject.put(propertyName, encodePropertyValueFromDataStore(
-            entityElement, p, propertyName, propertyContext));
+        jsonObject.put(
+            propertyName,
+ encodePropertyValueFromDataStore(entityElement, p, propertyName,
+                propertyContext));
       }
     }
     return jsonObject;
@@ -1085,7 +1065,7 @@
      * will protected against ConcurrentModificationExceptions.
      */
     afterDvsDataMap = new HashMap<EntityKey, EntityData>();
-    Set<EntityKey> done = new HashSet<EntityKey>();
+    Set<EntityKey> done = new HashSet<EntityKey>();
     Set<EntityKey> queue = new HashSet<EntityKey>(involvedKeys);
     while (!queue.isEmpty()) {
       for (EntityKey entityKey : queue) {
@@ -1107,11 +1087,10 @@
            * unedited, existing object.
            */
           SerializedEntity serializedEntity = beforeDataMap.get(entityKey);
-          Object entityInstance = (serializedEntity == null) ?
- getEntityInstance(entityKey) : serializedEntity.entityInstance;
+          Object entityInstance = (serializedEntity == null)
+ ? getEntityInstance(entityKey) : serializedEntity.entityInstance;
           if (entityInstance != null) {
-            afterDvsDataMap.put(entityKey, new EntityData(entityInstance,
-                null));
+ afterDvsDataMap.put(entityKey, new EntityData(entityInstance, null));
           }
         }
       }
@@ -1265,7 +1244,8 @@
       IllegalAccessException, InvocationTargetException {
     JSONObject jsonObject = new JSONObject();
     jsonObject.put(Constants.ENCODED_ID_PROPERTY, encodedId);
-    jsonObject.put(Constants.ENCODED_VERSION_PROPERTY,
+    jsonObject.put(
+        Constants.ENCODED_VERSION_PROPERTY,
         encodePropertyValueFromDataStore(entityElement,
             Constants.ENTITY_VERSION_PROPERTY,
             Constants.ENTITY_VERSION_PROPERTY.getName(), propertyContext));
@@ -1429,11 +1409,11 @@
         if (entityKey.isFuture) {
           returnObject.put(Constants.ENCODED_FUTUREID_PROPERTY,
               entityKey.encodedId);
-          returnObject.put(Constants.ENCODED_ID_PROPERTY, getSchemaAndId(
-              entityKey.proxyType, null));
+          returnObject.put(Constants.ENCODED_ID_PROPERTY,
+              getSchemaAndId(entityKey.proxyType, null));
         } else {
-          returnObject.put(Constants.ENCODED_ID_PROPERTY, getSchemaAndId(
-              entityKey.proxyType, entityKey.encodedId));
+          returnObject.put(Constants.ENCODED_ID_PROPERTY,
+              getSchemaAndId(entityKey.proxyType, entityKey.encodedId));
         }
         violations.put(returnObject);
       }
@@ -1446,8 +1426,9 @@
       SecurityException, IllegalAccessException, InvocationTargetException,
       NoSuchMethodException, JSONException, InstantiationException {
     SerializedEntity beforeEntity = beforeDataMap.get(entityKey);
-    if (beforeEntity != null && hasChanged(beforeEntity.serializedEntity,
-        serializeEntity(entityInstanceAfterOperation, entityKey))) {
+    if (beforeEntity != null
+        && hasChanged(beforeEntity.serializedEntity,
+            serializeEntity(entityInstanceAfterOperation, entityKey))) {
       return true;
     }
     return false;
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/cellview/client/CellList.java Wed Oct 6 14:58:29 2010 +++ /releases/2.1/user/src/com/google/gwt/user/cellview/client/CellList.java Wed Oct 13 06:23:15 2010
@@ -115,7 +115,7 @@
   }

   interface Template extends SafeHtmlTemplates {
- @Template("<div onclick=\"\" __idx=\"{0}\" class=\"{1}\" style=\"outline:none;\">{2}</div>") + @Template("<div onclick=\"\" __idx=\"{0}\" class=\"{1}\" style=\"outline:none;\" >{2}</div>")
     SafeHtml div(int idx, String classes, SafeHtml cellContents);

@Template("<div onclick=\"\" __idx=\"{0}\" class=\"{1}\" style=\"outline:none;\" tabindex=\"{2}\">{3}</div>")
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/client/ui/CheckBox.java Tue Sep 21 07:53:19 2010 +++ /releases/2.1/user/src/com/google/gwt/user/client/ui/CheckBox.java Wed Oct 13 06:23:15 2010
@@ -71,7 +71,7 @@

   /**
    * Creates a check box with the specified text label.
-   *
+   *
    * @param label the check box's label
    */
   public CheckBox(SafeHtml label) {
@@ -80,7 +80,7 @@

   /**
    * Creates a check box with the specified text label.
-   *
+   *
    * @param label the check box's label
    */
   public CheckBox(String label) {
@@ -170,14 +170,14 @@
   }

   /**
-   * Determines whether this check box is currently checked.
+   * Determines whether this check box is currently checked.
    * <p>
* Note that this <em>is not</em> return the value property of the checkbox
    * input element wrapped by this widget. For access to that property, see
    * {...@link #getFormValue()}
    *
* @return <code>true</code> if the check box is checked, false otherwise.
-   * Will not return null
+   *         Will not return null
    */
   public Boolean getValue() {
     if (isAttached()) {
@@ -200,7 +200,7 @@
   @Deprecated
   public boolean isChecked() {
     // Funny comparison b/c getValue could in theory return null
-    return getValue() == true;
+    return getValue() == true;
   }

   @Override
@@ -285,31 +285,29 @@
   }

   /**
-   * Checks or unchecks the text box.
+   * Checks or unchecks the check box.
    * <p>
* Note that this <em>does not</em> set the value property of the checkbox
    * input element wrapped by this widget. For access to that property, see
    * {...@link #setFormValue(String)}
    *
-   * @param value true to check, false to uncheck; must not be null
-   * @throws IllegalArgumentException if value is null
+   * @param value true to check, false to uncheck; null value implies false
    */
   public void setValue(Boolean value) {
     setValue(value, false);
   }

   /**
-   * Checks or unchecks the text box, firing {...@link ValueChangeEvent} if
+   * Checks or unchecks the check box, firing {...@link ValueChangeEvent} if
    * appropriate.
    * <p>
* Note that this <em>does not</em> set the value property of the checkbox
    * input element wrapped by this widget. For access to that property, see
    * {...@link #setFormValue(String)}
-   *
+   *
    * @param value true to check, false to uncheck; null value implies false
    * @param fireEvents If true, and value has changed, fire a
    *          {...@link ValueChangeEvent}
-   * @throws IllegalArgumentException if value is null
    */
   public void setValue(Boolean value, boolean fireEvents) {
     if (value == null) {
@@ -337,8 +335,8 @@
   @Override
   public void sinkEvents(int eventBitsToAdd) {
     if (isOrWasAttached()) {
-      Event.sinkEvents(inputElem,
-          eventBitsToAdd | Event.getEventsSunk(inputElem));
+      Event.sinkEvents(inputElem, eventBitsToAdd
+          | Event.getEventsSunk(inputElem));
     } else {
       super.sinkEvents(eventBitsToAdd);
     }
@@ -395,10 +393,9 @@
   }

   /**
-   * Replace the current input element with a new one. Preserves
-   * all state except for the name property, for nasty reasons
-   * related to radio button grouping. (See implementation of
-   * {...@link RadioButton#setName}.)
+   * Replace the current input element with a new one. Preserves all state
+ * except for the name property, for nasty reasons related to radio button
+   * grouping. (See implementation of {...@link RadioButton#setName}.)
    *
    * @param elem the new input element
    */
@@ -411,7 +408,7 @@
     String formValue = getFormValue();
     String uid = inputElem.getId();
     String accessKey = inputElem.getAccessKey();
-    int sunkEvents = Event.getEventsSunk(inputElem);
+    int sunkEvents = Event.getEventsSunk(inputElem);

     // Clear out the old input element
     setEventListener(asOld(inputElem), null);
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/client/ui/MenuBar.java Tue Sep 21 07:53:19 2010 +++ /releases/2.1/user/src/com/google/gwt/user/client/ui/MenuBar.java Wed Oct 13 06:23:15 2010
@@ -147,6 +147,7 @@
 @SuppressWarnings("deprecation")
 public class MenuBar extends Widget implements PopupListener, HasAnimation,
     HasCloseHandlers<PopupPanel> {
+
   /**
    * An {...@link ImageBundle} that provides images for {...@link MenuBar}.
    *
@@ -872,6 +873,11 @@
    * otherwise.
    */
void doItemAction(final MenuItem item, boolean fireCommand, boolean focus) {
+    // Should not perform any action if the item is disabled
+    if (!item.isEnabled()) {
+      return;
+    }
+
     // Ensure that the item is selected.
     selectItem(item);

@@ -937,6 +943,10 @@
         return;
       }
     }
+
+    if (item != null && !item.isEnabled()) {
+      return;
+    }

     // Style the item selected when the mouse enters.
     selectItem(item);
@@ -1281,14 +1291,16 @@
    */
   private boolean selectFirstItemIfNoneSelected() {
     if (selectedItem == null) {
-      if (items.size() > 0) {
-        MenuItem nextItem = items.get(0);
-        selectItem(nextItem);
+      for (MenuItem nextItem : items) {
+        if (nextItem.isEnabled()) {
+          selectItem(nextItem);
+          break;
+        }
       }
       return true;
     }
     return false;
-  }
+ }

   private void selectNextItem() {
     if (selectedItem == null) {
@@ -1303,10 +1315,22 @@

     MenuItem itemToBeSelected;

-    if (index < items.size() - 1) {
-      itemToBeSelected = items.get(index + 1);
-    } else { // we're at the end, loop around to the start
-      itemToBeSelected = items.get(0);
+    int firstIndex = index;
+    while (true) {
+      index = index + 1;
+      if (index == items.size()) {
+        // we're at the end, loop around to the start
+        index = 0;
+      }
+      if (index == firstIndex) {
+        itemToBeSelected = items.get(firstIndex);
+        break;
+      } else {
+        itemToBeSelected = items.get(index);
+        if (itemToBeSelected.isEnabled()) {
+          break;
+        }
+      }
     }

     selectItem(itemToBeSelected);
@@ -1327,11 +1351,23 @@
     assert (index != -1);

     MenuItem itemToBeSelected;
-    if (index > 0) {
-      itemToBeSelected = items.get(index - 1);
-
-    } else { // we're at the start, loop around to the end
-      itemToBeSelected = items.get(items.size() - 1);
+
+    int firstIndex = index;
+    while (true) {
+      index = index - 1;
+      if (index < 0) {
+        // we're at the start, loop around to the end
+        index = items.size() - 1;
+      }
+      if (index == firstIndex) {
+        itemToBeSelected = items.get(firstIndex);
+        break;
+      } else {
+        itemToBeSelected = items.get(index);
+        if (itemToBeSelected.isEnabled()) {
+          break;
+        }
+      }
     }

     selectItem(itemToBeSelected);
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/client/ui/MenuItem.java Tue Sep 21 07:53:19 2010 +++ /releases/2.1/user/src/com/google/gwt/user/client/ui/MenuItem.java Wed Oct 13 06:23:15 2010
@@ -29,12 +29,14 @@
  * Each menu item is assigned a unique DOM id in order to support ARIA. See
* {...@link com.google.gwt.user.client.ui.Accessibility} for more information.
  */
-public class MenuItem extends UIObject implements HasHTML, HasSafeHtml {
+public class MenuItem extends UIObject implements HasHTML, HasEnabled, HasSafeHtml {

private static final String DEPENDENT_STYLENAME_SELECTED_ITEM = "selected"; + private static final String DEPENDENT_STYLENAME_DISABLED_ITEM = "disabled";

   private Command command;
   private MenuBar parentMenu, subMenu;
+  private boolean enabled = true;

   /**
    * Constructs a new menu item that fires a command when it is selected.
@@ -56,14 +58,13 @@
   }

   /**
-   * Constructs a new menu item that fires a command when it is selected.
+ * Constructs a new menu item that cascades to a sub-menu when it is selected.
    *
-   * @param text the item's text
-   * @param cmd the command to be fired when it is selected
+   * @param html the item's text
+   * @param subMenu the sub-menu to be displayed when it is selected
    */
-  public MenuItem(String text, Command cmd) {
-    this(text, false);
-    setCommand(cmd);
+  public MenuItem(SafeHtml html, MenuBar subMenu) {
+    this(html.asString(), true, subMenu);
   }

   /**
@@ -81,33 +82,34 @@
   /**
* Constructs a new menu item that cascades to a sub-menu when it is selected.
    *
-   * @param html the item's text
+   * @param text the item's text
+   * @param asHTML <code>true</code> to treat the specified text as html
    * @param subMenu the sub-menu to be displayed when it is selected
    */
-  public MenuItem(SafeHtml html, MenuBar subMenu) {
-    this(html.asString(), true, subMenu);
+  public MenuItem(String text, boolean asHTML, MenuBar subMenu) {
+    this(text, asHTML);
+    setSubMenu(subMenu);
   }

   /**
- * Constructs a new menu item that cascades to a sub-menu when it is selected.
+   * Constructs a new menu item that fires a command when it is selected.
    *
    * @param text the item's text
-   * @param subMenu the sub-menu to be displayed when it is selected
+   * @param cmd the command to be fired when it is selected
    */
-  public MenuItem(String text, MenuBar subMenu) {
+  public MenuItem(String text, Command cmd) {
     this(text, false);
-    setSubMenu(subMenu);
+    setCommand(cmd);
   }

   /**
* Constructs a new menu item that cascades to a sub-menu when it is selected.
    *
    * @param text the item's text
-   * @param asHTML <code>true</code> to treat the specified text as html
    * @param subMenu the sub-menu to be displayed when it is selected
    */
-  public MenuItem(String text, boolean asHTML, MenuBar subMenu) {
-    this(text, asHTML);
+  public MenuItem(String text, MenuBar subMenu) {
+    this(text, false);
     setSubMenu(subMenu);
   }

@@ -161,6 +163,10 @@
   public String getText() {
     return DOM.getInnerText(getElement());
   }
+
+  public boolean isEnabled() {
+    return enabled;
+  }

   /**
    * Sets the command associated with this item.
@@ -171,13 +177,22 @@
     command = cmd;
   }

-  public void setHTML(String html) {
-    DOM.setInnerHTML(getElement(), html);
+  public void setEnabled(boolean enabled) {
+    if (enabled) {
+      removeStyleDependentName(DEPENDENT_STYLENAME_DISABLED_ITEM);
+    } else {
+      addStyleDependentName(DEPENDENT_STYLENAME_DISABLED_ITEM);
+    }
+    this.enabled = enabled;
   }

   public void setHTML(SafeHtml html) {
     setHTML(html.asString());
   }
+
+  public void setHTML(String html) {
+    DOM.setInnerHTML(getElement(), html);
+  }

   /**
    * Sets the sub-menu associated with this item.
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/client/ui/ToggleButton.java Tue Jan 26 10:25:12 2010 +++ /releases/2.1/user/src/com/google/gwt/user/client/ui/ToggleButton.java Wed Oct 13 06:23:15 2010
@@ -17,6 +17,9 @@
 package com.google.gwt.user.client.ui;

 import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;

 /**
* A <code>ToggleButton</code> is a stylish stateful button which allows the
@@ -26,15 +29,18 @@
  * <img class='gallery' src='doc-files/ToggleButton.png'/>
  * </p>
  *
- * <h3>CSS Style Rules</h3> <ul class="css"> <li>
+ * <h3>CSS Style Rules</h3>
+ * <ul class="css">
+ * <li>
* .gwt-ToggleButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled
- * {.html-face}</li> </ul>
+ * {.html-face}</li>
+ * </ul>
  *
  * <p>
  * <h3>Example</h3> {...@example com.google.gwt.examples.ToggleButtonExample}
  * </p>
  */
-public class ToggleButton extends CustomButton {
+public class ToggleButton extends CustomButton implements HasValue<Boolean> {
   private static String STYLENAME_DEFAULT = "gwt-ToggleButton";

   {
@@ -63,12 +69,10 @@
    * construct the default face of the button.
    *
    * @param upImage image for the default (up) face of the button
-   * @param listener the click listener
-   * @deprecated Use {...@link #ToggleButton(Image, ClickHandler)} instead
+   * @param handler the click handler
    */
-  @Deprecated
-  public ToggleButton(Image upImage, ClickListener listener) {
-    super(upImage, listener);
+  public ToggleButton(Image upImage, ClickHandler handler) {
+    super(upImage, handler);
   }

   /**
@@ -76,10 +80,12 @@
    * construct the default face of the button.
    *
    * @param upImage image for the default (up) face of the button
-   * @param handler the click handler
+   * @param listener the click listener
+   * @deprecated Use {...@link #ToggleButton(Image, ClickHandler)} instead
    */
-  public ToggleButton(Image upImage, ClickHandler handler) {
-    super(upImage, handler);
+  @Deprecated
+  public ToggleButton(Image upImage, ClickListener listener) {
+    super(upImage, listener);
   }

   /**
@@ -97,12 +103,10 @@
    *
    * @param upImage image for the default(up) face of the button
    * @param downImage image for the down face of the button
-   * @param listener clickListener
- * @deprecated Use {...@link #ToggleButton(Image, Image, ClickHandler)} instead
+   * @param handler the click handler
    */
-  @Deprecated
- public ToggleButton(Image upImage, Image downImage, ClickListener listener) {
-    super(upImage, downImage, listener);
+ public ToggleButton(Image upImage, Image downImage, ClickHandler handler) {
+    super(upImage, downImage, handler);
   }

   /**
@@ -110,10 +114,12 @@
    *
    * @param upImage image for the default(up) face of the button
    * @param downImage image for the down face of the button
-   * @param handler the click handler
+   * @param listener clickListener
+ * @deprecated Use {...@link #ToggleButton(Image, Image, ClickHandler)} instead
    */
- public ToggleButton(Image upImage, Image downImage, ClickHandler handler) {
-    super(upImage, downImage, handler);
+  @Deprecated
+ public ToggleButton(Image upImage, Image downImage, ClickListener listener) {
+    super(upImage, downImage, listener);
   }

   /**
@@ -125,6 +131,17 @@
   public ToggleButton(String upText) {
     super(upText);
   }
+
+  /**
+ * Constructor for <code>ToggleButton</code>. The supplied text is used to
+   * construct the default face of the button.
+   *
+   * @param upText the text for the default (up) face of the button
+   * @param handler the click handler
+   */
+  public ToggleButton(String upText, ClickHandler handler) {
+    super(upText, handler);
+  }

   /**
* Constructor for <code>ToggleButton</code>. The supplied text is used to
@@ -140,14 +157,13 @@
   }

   /**
- * Constructor for <code>ToggleButton</code>. The supplied text is used to
-   * construct the default face of the button.
+   * Constructor for <code>ToggleButton</code>.
    *
    * @param upText the text for the default (up) face of the button
-   * @param handler the click handler
+   * @param downText the text for down face of the button
    */
-  public ToggleButton(String upText, ClickHandler handler) {
-    super(upText, handler);
+  public ToggleButton(String upText, String downText) {
+    super(upText, downText);
   }

   /**
@@ -155,9 +171,25 @@
    *
    * @param upText the text for the default (up) face of the button
    * @param downText the text for down face of the button
+   * @param handler the click handler
    */
-  public ToggleButton(String upText, String downText) {
-    super(upText, downText);
+ public ToggleButton(String upText, String downText, ClickHandler handler) {
+    super(upText, downText, handler);
+  }
+
+  public HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<Boolean> handler) {
+    return addHandler(handler, ValueChangeEvent.getType());
+  }
+
+  /**
+   * Determines whether this button is currently down.
+   *
+ * @return <code>true</code> if the button is pressed, false otherwise. Will
+   *         not return null
+   */
+  public Boolean getValue() {
+    return isDown();
   }

   @Override
@@ -166,15 +198,50 @@
     return super.isDown();
   }

+  /**
+   * {...@inheritdoc} Does not fire {...@link ValueChangeEvent}. (If you want 
the
+   * event to fire, use {...@link #setValue(Boolean, boolean)})
+   */
   @Override
   public void setDown(boolean down) {
     // Changes access to public.
     super.setDown(down);
   }
+
+  /**
+   * Sets whether this button is down.
+   *
+ * @param value true to press the button, false otherwise; null value implies
+   *          false
+   */
+  public void setValue(Boolean value) {
+    setValue(value, false);
+  }
+
+  /**
+   * Sets whether this button is down, firing {...@link ValueChangeEvent} if
+   * appropriate.
+   *
+ * @param value true to press the button, false otherwise; null value implies
+   *          false
+   * @param fireEvents If true, and value has changed, fire a
+   *          {...@link ValueChangeEvent}
+   */
+  public void setValue(Boolean value, boolean fireEvents) {
+    if (value == null) {
+      value = Boolean.FALSE;
+    }
+    boolean oldValue = isDown();
+    setDown(value);
+    if (fireEvents) {
+      ValueChangeEvent.fireIfNotEqual(this, oldValue, value);
+    }
+  }

   @Override
   protected void onClick() {
     toggleDown();
     super.onClick();
+    ValueChangeEvent.fire(this, isDown());
   }
 }
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css Wed Feb 10 08:44:48 2010 +++ /releases/2.1/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css Wed Oct 13 06:23:15 2010
@@ -263,6 +263,9 @@
 .gwt-MenuBar .gwt-MenuItem-selected {
   background: #cdcdcd;
 }
+.gwt-MenuBar .gwt-MenuItem-disabled {
+  color: #cdcdcd;
+}
 .gwt-MenuBar-horizontal {
   background: #ebebeb url(images/hborder.png) repeat-x 0px -2003px;
   border: 1px solid #BBBBBB;
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css Wed Feb 10 08:44:48 2010 +++ /releases/2.1/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css Wed Oct 13 06:23:15 2010
@@ -263,6 +263,9 @@
 .gwt-MenuBar .gwt-MenuItem-selected {
   background: #cdcdcd;
 }
+.gwt-MenuBar .gwt-MenuItem-disabled {
+  color: #cdcdcd;
+}
 .gwt-MenuBar-horizontal {
   background: #ebebeb url(images/hborder.png) repeat-x 0px -2003px;
   border: 1px solid #BBBBBB;
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css Wed Feb 10 08:44:48 2010 +++ /releases/2.1/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css Wed Oct 13 06:23:15 2010
@@ -247,6 +247,9 @@
   background: #666;
   color: #0cf;
 }
+.gwt-MenuBar .gwt-MenuItem-disabled {
+  color: #ccc;
+}
 .gwt-MenuBar-horizontal {
   background: #222222;
   border: 1px solid #777;
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css Wed Feb 10 08:44:48 2010 +++ /releases/2.1/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css Wed Oct 13 06:23:15 2010
@@ -247,6 +247,9 @@
   background: #666;
   color: #0cf;
 }
+.gwt-MenuBar .gwt-MenuItem-disabled {
+  color: #ccc;
+}
 .gwt-MenuBar-horizontal {
   background: #222222;
   border: 1px solid #777;
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css Wed Feb 10 08:44:48 2010 +++ /releases/2.1/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css Wed Oct 13 06:23:15 2010
@@ -263,6 +263,9 @@
 .gwt-MenuBar .gwt-MenuItem-selected {
   background: #E0EDFE;
 }
+.gwt-MenuBar .gwt-MenuItem-disabled {
+  color: #c0c0c0;
+}
 .gwt-MenuBar-horizontal {
   background: #e3e8f3 url(images/hborder.png) repeat-x 0px -2003px;
   border: 1px solid #BBBBBB;
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css Wed Feb 10 08:44:48 2010 +++ /releases/2.1/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css Wed Oct 13 06:23:15 2010
@@ -263,6 +263,9 @@
 .gwt-MenuBar .gwt-MenuItem-selected {
   background: #E0EDFE;
 }
+.gwt-MenuBar .gwt-MenuItem-disabled {
+  color: #c0c0c0;
+}
 .gwt-MenuBar-horizontal {
   background: #e3e8f3 url(images/hborder.png) repeat-x 0px -2003px;
   border: 1px solid #BBBBBB;
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/client/FindServiceTest.java Fri Oct 1 18:15:55 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/client/FindServiceTest.java Wed Oct 13 06:23:15 2010
@@ -133,7 +133,6 @@
               @Override
               public void onSuccess(SimpleBarProxy returnedProxy) {
                 assertEquals(stableId, returnedProxy.stableId());
-                assertEquals("999L", returnedProxy.getId());
                 finishTestAndReset();
               }
             });
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java Wed Oct 6 08:01:28 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java Wed Oct 13 06:23:15 2010
@@ -148,16 +148,11 @@

     SimpleBarRequest context = req.simpleBarRequest();
     final SimpleBarProxy foo = context.create(SimpleBarProxy.class);
-    Object futureId = foo.getId();
-    assertEquals(futureId, foo.getId());
Request<SimpleBarProxy> fooReq = context.persistAndReturnSelf().using(foo);
     fooReq.fire(new Receiver<SimpleBarProxy>() {

       @Override
       public void onSuccess(final SimpleBarProxy returned) {
-        Object futureId = foo.getId();
-        assertEquals(futureId, foo.getId());
-
         checkStableIdEquals(foo, returned);
         finishTestAndReset();
       }
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java Wed Oct 6 08:01:28 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java Wed Oct 13 06:23:15 2010
@@ -456,16 +456,12 @@

     SimpleBarRequest context = simpleBarRequest();
     final SimpleBarProxy foo = context.create(SimpleBarProxy.class);
-    Object futureId = foo.getId();
-    assertEquals(futureId, foo.getId());
     assertTrue(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());
Request<SimpleBarProxy> fooReq = context.persistAndReturnSelf().using(foo);
     fooReq.fire(new Receiver<SimpleBarProxy>() {

       @Override
       public void onSuccess(final SimpleBarProxy returned) {
-        Object futureId = foo.getId();
-        assertEquals(futureId, foo.getId());
assertFalse(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());

         checkStableIdEquals(foo, returned);
@@ -479,16 +475,12 @@

     SimpleBarRequest context = simpleBarRequest();
     final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
-    Object futureId = bar.getId();
-    assertEquals(futureId, bar.getId());
     assertTrue(((SimpleEntityProxyId<?>) bar.stableId()).isEphemeral());
Request<SimpleBarProxy> fooReq = context.returnFirst(Collections.singletonList(bar));
     fooReq.fire(new Receiver<SimpleBarProxy>() {

       @Override
       public void onSuccess(final SimpleBarProxy returned) {
-        Object futureId = bar.getId();
-        assertEquals(futureId, bar.getId());
assertFalse(((SimpleEntityProxyId<?>) bar.stableId()).isEphemeral()); assertFalse(((SimpleEntityProxyId<?>) returned.stableId()).isEphemeral());

@@ -1770,6 +1762,10 @@
       @Override
       public void onSuccess(SimpleFooProxy response) {
         assertEquals(2, response.getOneToManyField().size());
+
+ // Check lists of proxies returned from a mutable object are mutable
+        response = simpleFooRequest().edit(response);
+        response.getOneToManyField().get(0).setUserName("canMutate");
         finishTestAndReset();
       }
     });
=======================================
--- /releases/2.1/user/test/com/google/gwt/requestfactory/shared/SimpleBarProxy.java Fri Sep 24 12:10:50 2010 +++ /releases/2.1/user/test/com/google/gwt/requestfactory/shared/SimpleBarProxy.java Wed Oct 13 06:23:15 2010
@@ -25,7 +25,10 @@
 public interface SimpleBarProxy extends EntityProxy {
   Boolean getFindFails();

-  String getId();
+  /*
+ * NB: The lack of a getId() here is intentional, to ensure that the system
+   * does not assume that the id property is available to the client.
+   */

   String getUserName();

=======================================
--- /releases/2.1/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java Tue Sep 21 07:53:19 2010 +++ /releases/2.1/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java Wed Oct 13 06:23:15 2010
@@ -19,6 +19,8 @@
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.safehtml.shared.SafeHtmlUtils;
 import com.google.gwt.user.client.DOM;
@@ -38,6 +40,14 @@
  */
 public class CustomButtonTest extends GWTTestCase {

+  private static class Handler implements ValueChangeHandler<Boolean> {
+    Boolean received = null;
+
+    public void onValueChange(ValueChangeEvent<Boolean> event) {
+      received = event.getValue();
+    }
+  }
+
   private static final String html = "<b>hello</b><i>world</i>";

   public String getModuleName() {
@@ -159,14 +169,16 @@
   }

   public void testSyntheticClick() {
-    PushButton b = new PushButton();
+    ToggleButton b = new ToggleButton();
     final ArrayList<String> events = new ArrayList<String>();
+    Handler h = new Handler();

     b.addClickHandler(new ClickHandler() {
       public void onClick(ClickEvent event) {
         events.add(event.getNativeEvent().getType());
       }
     });
+    b.addValueChangeHandler(h);

     RootPanel.get().add(b);

@@ -183,6 +195,7 @@
             false, Event.BUTTON_LEFT));
     assertEquals("Expecting one click event", 1, events.size());
     assertEquals("Expecting one click event", "click", events.get(0));
+    assertNotNull("Expecting a value change event", h.received);
   }

   public void testTransitions() {
@@ -219,4 +232,28 @@
     assertFalse(b.isDown());
     assertFalse(b.isEnabled());
   }
-}
+
+  public void testToogleButtonHasValue() {
+    ToggleButton tb = new ToggleButton();
+    Handler h = new Handler();
+    tb.addValueChangeHandler(h);
+    tb.setDown(false);
+    assertNull(h.received);
+    tb.setDown(true);
+    assertNull(h.received);
+
+    tb.setValue(false);
+    assertNull(h.received);
+    tb.setValue(true);
+    assertNull(h.received);
+
+    tb.setValue(true, true);
+    assertNull(h.received);
+
+    tb.setValue(false, true);
+    assertFalse(h.received);
+
+    tb.setValue(true, true);
+    assertTrue(h.received);
+  }
+}
=======================================
--- /releases/2.1/user/test/com/google/gwt/user/client/ui/MenuBarTest.java Tue Sep 21 07:53:19 2010 +++ /releases/2.1/user/test/com/google/gwt/user/client/ui/MenuBarTest.java Wed Oct 13 06:23:15 2010
@@ -202,6 +202,26 @@
       }
     });
   }
+
+  public void testDisabledItem() {
+    MenuBar bar = new MenuBar(true);
+    MenuItem item1 = new MenuItem("item1", BLANK_COMMAND);
+    MenuItem item2 = new MenuItem("item2", BLANK_COMMAND);
+    MenuItem item3 = new MenuItem("item3", BLANK_COMMAND);
+    bar.addItem(item1);
+    bar.addItem(item2);
+    bar.addItem(item3);
+    RootPanel.get().add(bar);
+
+    item2.setEnabled(false);
+
+    bar.moveSelectionDown();
+    assertEquals(item1, bar.getSelectedItem());
+    bar.moveSelectionDown();
+    assertEquals(item3, bar.getSelectedItem());
+    bar.moveSelectionUp();
+    assertEquals(item1, bar.getSelectedItem());
+  }

   public void testEscapeKey() {
     // Create a menu bar with children.

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to