/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.client.ui;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;

/**
 * The superclass for all user-interface objects. It simply wraps a DOM element,
 * and cannot receive events. Most interesting user-interface classes derive
 * from {@link com.google.gwt.user.client.ui.Widget}.
 * 
 * <h3>Styling With CSS</h3>
 * <p>
 * All <code>UIObject</code> objects can be styled using CSS. Style names that
 * are specified programmatically in Java source are implicitly associated with
 * CSS style rules. In terms of HTML and CSS, a GWT style name is the element's
 * CSS "class". By convention, GWT style names are of the form
 * <code>[project]-[widget]</code>.
 * </p>
 * 
 * <p>
 * For example, the {@link Button} widget has the style name
 * <code>gwt-Button</code>, meaning that within the <code>Button</code>
 * constructor, the following call occurs:
 * 
 * <pre class="code">
 * setStyleName("gwt-Button");</pre>
 * 
 * A corresponding CSS style rule can then be written as follows:
 * 
 * <pre class="code">
 * // Example of how you might choose to style a Button widget 
 * .gwt-Button {
 *   background-color: yellow;
 *   color: black;
 *   font-size: 24pt;
 * }</pre>
 * 
 * Note the dot prefix in the CSS style rule. This syntax is called a <a
 * href="http://www.w3.org/TR/REC-CSS2/selector.html#class-html">CSS class
 * selector</a>.
 * </p>
 * 
 * <h3>Style Name Specifics</h3>
 * <p>
 * Every <code>UIObject</code> has a <i>primary style name</i> that identifies
 * the key CSS style rule that should always be applied to it. Use
 * {@link #setStylePrimaryName(String)} to specify an object's primary style
 * name. In most cases, the primary style name is set in a widget's constructor
 * and never changes again during execution. In the case that no primary style
 * name is specified, it defaults to the first style name that is added.
 * </p>
 * 
 * <p>
 * More complex styling behavior can be achieved by manipulating an object's
 * <i>secondary style names</i>. Secondary style names can be added and removed
 * using {@link #addStyleName(String)}, {@link #removeStyleName(String)}, or
 * {@link #setStyleName(String, boolean)}. The purpose of secondary style names
 * is to associate a variety of CSS style rules over time as an object
 * progresses through different visual states.
 * </p>
 * 
 * <p>
 * There is an important special formulation of secondary style names called
 * <i>dependent style names</i>. A dependent style name is a secondary style
 * name prefixed with the primary style name of the widget itself. See
 * {@link #addStyleName(String)} for details.
 * </p>
 * 
 * <h3>Use in UiBinder Templates</h3>
 * <p>
 * Setter methods that follow JavaBean property conventions are exposed as
 * attributes in {@link com.google.gwt.uibinder.client.UiBinder UiBinder}
 * templates. For example, because UiObject implements {@link #setWidth(String)}
 * you can set the width of any widget like so:
 * 
 * <pre>
 * &lt;g:Label width='15em'>Hello there&lt;/g:Label></pre>
 * 
 * Generally speaking, values are parsed as if they were Java literals, so
 * methods like {@link #setVisible(boolean)} are also available:
 * 
 * <pre>
 * &lt;g:Label width='15em' visible='false'>Hello there&lt;/g:Label></pre>
 * Enum properties work this way too. Imagine a Bagel widget with a handy Type
 * enum and a setType(Type) method:
 * 
 * <pre>
 * enum Type { poppy, sesame, raisin, jalapeno }
 * 
 * &lt;my:Bagel type='poppy' /></pre>
 * 
 * There is also special case handling for two common method signatures,
 * <code>(int, int)</code> and <code>(double, {@link 
 * com.google.gwt.dom.client.Style.Unit Unit})</code>
 * 
 * <pre>
 * &lt;g:Label pixelSize='100, 100'>Hello there&lt;/g:Label></pre>
 * 
 * Finally, a few UiObject methods get special handling. The debug id (see
 * {@link #ensureDebugId}) of any UiObject can be set via the
 * <code>debugId</code> attribute, and addtional style names and dependent style
 * names can be set with the <code>addStyleNames</code> and
 * <code>addStyleDependentNames</code> attributes.<pre>
 * &lt;g:Label debugId='helloLabel' 
 *     addStyleNames='pretty rounded big'>Hello there&lt;/g:Label></pre>
 * 
 * Style names can be space or comma separated.
 */
public abstract class UIObject {

  /**
   * Stores a regular expression object to extract float values from the
   * leading portion of an input string.
   */
  @SuppressWarnings("unused")
  private static JavaScriptObject numberRegex;

  /*
   * WARNING: For historical reasons, there are two Element classes being used
   * in this code. The dom.Element (com.google.gwt.dom.client.Element) class is
   * explicitly imported, while user.Element
   * (com.google.gwt.user.client.Element) is fully-qualified in the code.
   * 
   * All new methods should use dom.Element, because user.Element extends it but
   * adds no methods.
   */

  /**
   * The implementation of the set debug id method, which does nothing by
   * default.
   */
  public static class DebugIdImpl {
    @SuppressWarnings("unused")
    // parameters
    public void ensureDebugId(UIObject uiObject, String id) {
    }

    @SuppressWarnings("unused")
    // parameters
    public void ensureDebugId(Element elem, String baseID, String id) {
    }
  }

  /**
   * The implementation of the setDebugId method, which sets the id of the
   * {@link Element}s in this {@link UIObject}.
   */
  public static class DebugIdImplEnabled extends DebugIdImpl {
    @Override
    public void ensureDebugId(UIObject uiObject, String id) {
      uiObject.onEnsureDebugId(id);
    }

    @Override
    public void ensureDebugId(Element elem, String baseID, String id) {
      assert baseID != null;
      baseID = (baseID.length() > 0) ? baseID + "-" : "";
      DOM.setElementProperty(elem.<com.google.gwt.user.client.Element> cast(),
          "id", DEBUG_ID_PREFIX + baseID + id);
    }
  }

  public static final String DEBUG_ID_PREFIX = "gwt-debug-";

  static final String MISSING_ELEMENT_ERROR = "This UIObject's element is not set; "
      + "you may be missing a call to either Composite.initWidget() or "
      + "UIObject.setElement()";

  static final String SETELEMENT_TWICE_ERROR = "Element may only be set once";

  private static DebugIdImpl debugIdImpl = GWT.create(DebugIdImpl.class);

  private static final String EMPTY_STYLENAME_MSG = "Style names cannot be empty";

  private static final String NULL_HANDLE_MSG = "Null widget handle. If you "
      + "are creating a composite, ensure that initWidget() has been called.";

  /**
   * <p>
   * Ensure that elem has an ID property set, which allows it to integrate with
   * third-party libraries and test tools. If elem already has an ID, this
   * method WILL override it. The ID that you specify will be prefixed by the
   * static string {@link #DEBUG_ID_PREFIX}.
   * </p>
   * 
   * <p>
   * This method will be compiled out and will have no effect unless you inherit
   * the DebugID module in your gwt.xml file by adding the following line:
   * 
   * <pre class="code">
   * &lt;inherits name="com.google.gwt.user.Debug"/&gt;</pre>
   * </p>
   * 
   * @param elem the target {@link Element}
   * @param id the ID to set on the element
   */
  public static void ensureDebugId(Element elem, String id) {
    ensureDebugId(elem, "", id);
  }

  public static native boolean isVisible(Element elem) /*-{
    return (elem.style.display != 'none');
  }-*/;

  public static native void setVisible(Element elem, boolean visible) /*-{
    elem.style.display = visible ? '' : 'none';
  }-*/;

  /**
   * Set the debug id of a specific element. The id will be appended to the end
   * of the base debug id, with a dash separator. The base debug id is the ID of
   * the main element in this UIObject.
   * 
   * @param elem the element
   * @param baseID the base ID used by the main element
   * @param id the id to append to the base debug id
   */
  protected static void ensureDebugId(Element elem, String baseID, String id) {
    debugIdImpl.ensureDebugId(elem, baseID, id);
  }

  /**
   * Gets all of the element's style names, as a space-separated list.
   * 
   * @param elem the element whose style is to be retrieved
   * @return the objects's space-separated style names
   */
  protected static String getStyleName(Element elem) {
    return DOM.getElementProperty(
        elem.<com.google.gwt.user.client.Element> cast(), "className");
  }

  /**
   * Gets the element's primary style name.
   * 
   * @param elem the element whose primary style name is to be retrieved
   * @return the element's primary style name
   */
  protected static String getStylePrimaryName(Element elem) {
    String fullClassName = getStyleName(elem);

    // The primary style name is always the first token of the full CSS class
    // name. There can be no leading whitespace in the class name, so it's not
    // necessary to trim() it.
    int spaceIdx = fullClassName.indexOf(' ');
    if (spaceIdx >= 0) {
      return fullClassName.substring(0, spaceIdx);
    }
    return fullClassName;
  }

  /**
   * Clears all of the element's style names and sets it to the given style.
   * 
   * @param elem the element whose style is to be modified
   * @param styleName the new style name
   */
  protected static void setStyleName(Element elem, String styleName) {
    DOM.setElementProperty(elem.<com.google.gwt.user.client.Element> cast(),
        "className", styleName);
  }

  /**
   * This convenience method adds or removes a style name for a given element.
   * This method is typically used to add and remove secondary style names, but
   * it can be used to remove primary stylenames as well, but that is not
   * recommended. See {@link #setStyleName(String)} for a description of how
   * primary and secondary style names are used.
   * 
   * @param elem the element whose style is to be modified
   * @param style the secondary style name to be added or removed
   * @param add <code>true</code> to add the given style, <code>false</code> to
   *          remove it
   */
  protected static void setStyleName(Element elem, String style, boolean add) {
    if (elem == null) {
      throw new RuntimeException(NULL_HANDLE_MSG);
    }

    style = style.trim();
    if (style.length() == 0) {
      throw new IllegalArgumentException(EMPTY_STYLENAME_MSG);
    }

    if (add) {
      elem.addClassName(style);
    } else {
      elem.removeClassName(style);
    }
  }

  /**
   * Sets the element's primary style name and updates all dependent style
   * names.
   * 
   * @param elem the element whose style is to be reset
   * @param style the new primary style name
   * @see #setStyleName(Element, String, boolean)
   */
  protected static void setStylePrimaryName(Element elem, String style) {
    if (elem == null) {
      throw new RuntimeException(NULL_HANDLE_MSG);
    }

    // Style names cannot contain leading or trailing whitespace, and cannot
    // legally be empty.
    style = style.trim();
    if (style.length() == 0) {
      throw new IllegalArgumentException(EMPTY_STYLENAME_MSG);
    }

    updatePrimaryAndDependentStyleNames(elem, style);
  }

  /**
   * Replaces all instances of the primary style name with newPrimaryStyleName.
   */
  private static native void updatePrimaryAndDependentStyleNames(Element elem,
      String newPrimaryStyle) /*-{
    var classes = elem.className.split(/\s+/);
    if (!classes) {
      return;
    }

    var oldPrimaryStyle = classes[0];
    var oldPrimaryStyleLen = oldPrimaryStyle.length;

    classes[0] = newPrimaryStyle;
    for (var i = 1, n = classes.length; i < n; i++) {
      var name = classes[i];
      if (name.length > oldPrimaryStyleLen
          && name.charAt(oldPrimaryStyleLen) == '-'
          && name.indexOf(oldPrimaryStyle) == 0) {
        classes[i] = newPrimaryStyle + name.substring(oldPrimaryStyleLen);
      }
    }
    elem.className = classes.join(" ");
  }-*/;

  private Element element;

  /**
   * Adds a dependent style name by specifying the style name's suffix. The
   * actual form of the style name that is added is:
   * 
   * <pre class="code">
   * getStylePrimaryName() + '-' + styleSuffix
   * </pre>
   * 
   * @param styleSuffix the suffix of the dependent style to be added.
   * @see #setStylePrimaryName(String)
   * @see #removeStyleDependentName(String)
   * @see #setStyleDependentName(String, boolean)
   * @see #addStyleName(String)
   */
  public void addStyleDependentName(String styleSuffix) {
    setStyleDependentName(styleSuffix, true);
  }

  /**
   * Adds a secondary or dependent style name to this object. A secondary style
   * name is an additional style name that is, in HTML/CSS terms, included as a
   * space-separated token in the value of the CSS <code>class</code> attribute
   * for this object's root element.
   * 
   * <p>
   * The most important use for this method is to add a special kind of
   * secondary style name called a <i>dependent style name</i>. To add a
   * dependent style name, use {@link #addStyleDependentName(String)}, which
   * will prefix the 'style' argument with the result of
   * {@link #getStylePrimaryName()} (followed by a '-'). For example, suppose
   * the primary style name is <code>gwt-TextBox</code>. If the following method
   * is called as <code>obj.setReadOnly(true)</code>:
   * </p>
   * 
   * <pre class="code">
   * public void setReadOnly(boolean readOnly) {
   *   isReadOnlyMode = readOnly;
   *   
   *   // Create a dependent style name.
   *   String readOnlyStyle = "readonly";
   *    
   *   if (readOnly) {
   *     addStyleDependentName(readOnlyStyle);
   *   } else {
   *     removeStyleDependentName(readOnlyStyle);
   *   }
   * }</pre>
   * 
   * <p>
   * then both of the CSS style rules below will be applied:
   * </p>
   * 
   * <pre class="code">
   *
   * // This rule is based on the primary style name and is always active.
   * .gwt-TextBox {
   *   font-size: 12pt;
   * }
   * 
   * // This rule is based on a dependent style name that is only active
   * // when the widget has called addStyleName(getStylePrimaryName() +
   * // "-readonly").
   * .gwt-TextBox-readonly {
   *   background-color: lightgrey;
   *   border: none;
   * }</pre>
   *
   * <p>
   * The code can also be simplified with
   * {@link #setStyleDependentName(String, boolean)}:
   * </p>
   *
   * <pre class="code">
   * public void setReadOnly(boolean readOnly) {
   *   isReadOnlyMode = readOnly;
   *   setStyleDependentName("readonly", readOnly);
   * }</pre>
   * 
   * <p>
   * Dependent style names are powerful because they are automatically updated
   * whenever the primary style name changes. Continuing with the example above,
   * if the primary style name changed due to the following call:
   * </p>
   * 
   * <pre class="code">setStylePrimaryName("my-TextThingy");</pre>
   * 
   * <p>
   * then the object would be re-associated with following style rules, removing
   * those that were shown above.
   * </p>
   * 
   * <pre class="code">
   * .my-TextThingy {
   *   font-size: 20pt;
   * }
   * 
   * .my-TextThingy-readonly {
   *   background-color: red;
   *   border: 2px solid yellow;
   * }</pre>
   * 
   * <p>
   * Secondary style names that are not dependent style names are not
   * automatically updated when the primary style name changes.
   * </p>
   * 
   * @param style the secondary style name to be added
   * @see UIObject
   * @see #removeStyleName(String)
   */
  public void addStyleName(String style) {
    setStyleName(style, true);
  }

  /**
   * Ensure that the main {@link Element} for this {@link UIObject} has an ID
   * property set, which allows it to integrate with third-party libraries and
   * test tools. Complex {@link Widget}s will also set the IDs of their
   * important sub-elements.
   * 
   * If the main element already has an ID, this method WILL override it.
   * 
   * The ID that you specify will be prefixed by the static string
   * {@link #DEBUG_ID_PREFIX}.
   * 
   * This method will be compiled out and will have no effect unless you inherit
   * the DebugID module in your gwt.xml file by adding the following line:
   * 
   * <pre class="code">
   * &lt;inherits name="com.google.gwt.user.Debug"/&gt;</pre>
   * 
   * @param id the ID to set on the main element
   */
  public final void ensureDebugId(String id) {
    debugIdImpl.ensureDebugId(this, id);
  }

  /**
   * Gets the object's absolute left position in pixels, as measured from the
   * browser window's client area.
   * 
   * @return the object's absolute left position
   */
  public int getAbsoluteLeft() {
    return DOM.getAbsoluteLeft(getElement());
  }

  /**
   * Gets the object's absolute top position in pixels, as measured from the
   * browser window's client area.
   * 
   * @return the object's absolute top position
   */
  public int getAbsoluteTop() {
    return DOM.getAbsoluteTop(getElement());
  }

  /**
   * Gets a handle to the object's underlying DOM element.
   * 
   * This method should not be overridden. It is non-final solely to support
   * legacy code that depends upon overriding it. If it is overridden, the
   * subclass implementation must not return a different element than was
   * previously set using
   * {@link #setElement(com.google.gwt.user.client.Element)}.
   * 
   * @return the object's browser element
   */
  public com.google.gwt.user.client.Element getElement() {
    assert (element != null) : MISSING_ELEMENT_ERROR;
    return (com.google.gwt.user.client.Element) element;
  }

  /**
   * Gets the object's offset height in pixels. This is the total height of the
   * object, including decorations such as border, margin, and padding.
   * 
   * @return the object's offset height
   */
  public int getOffsetHeight() {
    return DOM.getElementPropertyInt(getElement(), "offsetHeight");
  }

  /**
   * Gets the object's offset width in pixels. This is the total width of the
   * object, including decorations such as border, margin, and padding.
   * 
   * @return the object's offset width
   */
  public int getOffsetWidth() {
    return DOM.getElementPropertyInt(getElement(), "offsetWidth");
  }

  /**
   * Gets all of the object's style names, as a space-separated list. If you
   * wish to retrieve only the primary style name, call
   * {@link #getStylePrimaryName()}.
   * 
   * @return the objects's space-separated style names
   * @see #getStylePrimaryName()
   */
  public String getStyleName() {
    return getStyleName(getStyleElement());
  }

  /**
   * Gets the primary style name associated with the object.
   * 
   * @return the object's primary style name
   * @see #setStyleName(String)
   * @see #addStyleName(String)
   * @see #removeStyleName(String)
   */
  public String getStylePrimaryName() {
    return getStylePrimaryName(getStyleElement());
  }

  /**
   * Gets the title associated with this object. The title is the 'tool-tip'
   * displayed to users when they hover over the object.
   * 
   * @return the object's title
   */
  public String getTitle() {
    return DOM.getElementProperty(getElement(), "title");
  }

  /**
   * Determines whether or not this object is visible.
   * 
   * @return <code>true</code> if the object is visible
   */
  public boolean isVisible() {
    return isVisible(getElement());
  }

  /**
   * Removes a dependent style name by specifying the style name's suffix.
   * 
   * @param styleSuffix the suffix of the dependent style to be removed
   * @see #setStylePrimaryName(Element, String)
   * @see #addStyleDependentName(String)
   * @see #setStyleDependentName(String, boolean)
   */
  public void removeStyleDependentName(String styleSuffix) {
    setStyleDependentName(styleSuffix, false);
  }

  /**
   * Removes a style name. This method is typically used to remove secondary
   * style names, but it can be used to remove primary stylenames as well. That
   * use is not recommended.
   * 
   * @param style the secondary style name to be removed
   * @see #addStyleName(String)
   * @see #setStyleName(String, boolean)
   */
  public void removeStyleName(String style) {
    setStyleName(style, false);
  }

  /**
   * Sets the object's height. This height does not include decorations such as
   * border, margin, and padding.
   * 
   * @param height the object's new height, in CSS units (e.g. "10px", "1em")
   */
  public void setHeight(String height) {
    // This exists to deal with an inconsistency in IE's implementation where
    // it won't accept negative numbers in length measurements
    assert extractLengthValue(height.trim().toLowerCase()) >= 0 : "CSS heights should not be negative";
    DOM.setStyleAttribute(getElement(), "height", height);
  }

  /**
   * Sets the object's size, in pixels, not including decorations such as
   * border, margin, and padding.
   * 
   * @param width the object's new width, in pixels
   * @param height the object's new height, in pixels
   */
  public void setPixelSize(int width, int height) {
    if (width >= 0) {
      setWidth(width + "px");
    }
    if (height >= 0) {
      setHeight(height + "px");
    }
  }

  /**
   * Sets the object's size. This size does not include decorations such as
   * border, margin, and padding.
   * 
   * @param width the object's new width, in CSS units (e.g. "10px", "1em")
   * @param height the object's new height, in CSS units (e.g. "10px", "1em")
   */
  public void setSize(String width, String height) {
    setWidth(width);
    setHeight(height);
  }

  /**
   * Adds or removes a dependent style name by specifying the style name's
   * suffix. The actual form of the style name that is added is:
   * 
   * <pre class="code">
   * getStylePrimaryName() + '-' + styleSuffix
   * </pre>
   * 
   * @param styleSuffix the suffix of the dependent style to be added or removed
   * @param add <code>true</code> to add the given style, <code>false</code> to
   *          remove it
   * @see #setStylePrimaryName(Element, String)
   * @see #addStyleDependentName(String)
   * @see #setStyleName(String, boolean)
   * @see #removeStyleDependentName(String)
   */
  public void setStyleDependentName(String styleSuffix, boolean add) {
    setStyleName(getStylePrimaryName() + '-' + styleSuffix, add);
  }

  /**
   * Adds or removes a style name. This method is typically used to remove
   * secondary style names, but it can be used to remove primary stylenames as
   * well. That use is not recommended.
   * 
   * @param style the style name to be added or removed
   * @param add <code>true</code> to add the given style, <code>false</code> to
   *          remove it
   * @see #addStyleName(String)
   * @see #removeStyleName(String)
   */
  public void setStyleName(String style, boolean add) {
    setStyleName(getStyleElement(), style, add);
  }

  /**
   * Clears all of the object's style names and sets it to the given style. You
   * should normally use {@link #setStylePrimaryName(String)} unless you wish to
   * explicitly remove all existing styles.
   * 
   * @param style the new style name
   * @see #setStylePrimaryName(String)
   */
  public void setStyleName(String style) {
    setStyleName(getStyleElement(), style);
  }

  /**
   * Sets the object's primary style name and updates all dependent style names.
   * 
   * @param style the new primary style name
   * @see #addStyleName(String)
   * @see #removeStyleName(String)
   */
  public void setStylePrimaryName(String style) {
    setStylePrimaryName(getStyleElement(), style);
  }

  /**
   * Sets the title associated with this object. The title is the 'tool-tip'
   * displayed to users when they hover over the object.
   * 
   * @param title the object's new title
   */
  public void setTitle(String title) {
    if (title == null || title.length() == 0) {
      DOM.removeElementAttribute(getElement(), "title");
    } else {
      DOM.setElementAttribute(getElement(), "title", title);
    }
  }

  /**
   * Sets whether this object is visible.
   * 
   * @param visible <code>true</code> to show the object, <code>false</code> to
   *          hide it
   */
  public void setVisible(boolean visible) {
    setVisible(getElement(), visible);
  }

  /**
   * Sets the object's width. This width does not include decorations such as
   * border, margin, and padding.
   * 
   * @param width the object's new width, in CSS units (e.g. "10px", "1em")
   */
  public void setWidth(String width) {
    // This exists to deal with an inconsistency in IE's implementation where
    // it won't accept negative numbers in length measurements
    assert extractLengthValue(width.trim().toLowerCase()) >= 0 : "CSS widths should not be negative";
    DOM.setStyleAttribute(getElement(), "width", width);
  }

  /**
   * Adds a set of events to be sunk by this object. Note that only
   * {@link Widget widgets} may actually receive events, but can receive events
   * from all objects contained within them.
   * 
   * @param eventBitsToAdd a bitfield representing the set of events to be added
   *          to this element's event set
   * @see com.google.gwt.user.client.Event
   */
  public void sinkEvents(int eventBitsToAdd) {
    DOM.sinkEvents(getElement(), eventBitsToAdd
        | DOM.getEventsSunk(getElement()));
  }

  /**
   * This method is overridden so that any object can be viewed in the debugger
   * as an HTML snippet.
   * 
   * @return a string representation of the object
   */
  @Override
  public String toString() {
    if (element == null) {
      return "(null handle)";
    }
    return DOM.toString(getElement());
  }

  /**
   * Removes a set of events from this object's event list.
   * 
   * @param eventBitsToRemove a bitfield representing the set of events to be
   *          removed from this element's event set
   * @see #sinkEvents
   * @see com.google.gwt.user.client.Event
   */
  public void unsinkEvents(int eventBitsToRemove) {
    DOM.sinkEvents(getElement(), DOM.getEventsSunk(getElement())
        & (~eventBitsToRemove));
  }

  /**
   * Template method that returns the element to which style names will be
   * applied. By default it returns the root element, but this method may be
   * overridden to apply styles to a child element.
   * 
   * @return the element to which style names will be applied
   */
  protected com.google.gwt.user.client.Element getStyleElement() {
    return getElement();
  }

  /**
   * Called when the user sets the id using the {@link #ensureDebugId(String)}
   * method. Subclasses of {@link UIObject} can override this method to add IDs
   * to their sub elements. If a subclass does override this method, it should
   * list the IDs (relative to the base ID), that will be applied to each sub
   * {@link Element} with a short description. For example:
   * <ul>
   * <li>-mysubelement = Applies to my sub element.</li>
   * </ul>
   * 
   * Subclasses should make a super call to this method to ensure that the ID of
   * the main element is set.
   * 
   * This method will not be called unless you inherit the DebugID module in
   * your gwt.xml file by adding the following line:
   * 
   * <pre class="code">
   * &lt;inherits name="com.google.gwt.user.Debug"/&gt;</pre>
   * 
   * @param baseID the base ID used by the main element
   */
  protected void onEnsureDebugId(String baseID) {
    ensureDebugId(getElement(), "", baseID);
  }

  /**
   * Sets this object's browser element. UIObject subclasses must call this
   * method before attempting to call any other methods, and it may only be
   * called once.
   * 
   * @param elem the object's element
   */
  protected final void setElement(Element elem) {
    setElement((com.google.gwt.user.client.Element) elem);
  }

  /**
   * Sets this object's browser element. UIObject subclasses must call this
   * method before attempting to call any other methods, and it may only be
   * called once.
   * 
   * This method exists for backwards compatibility with pre-1.5 code. As of GWT
   * 1.5, {@link #setElement(Element)} is the preferred method.
   * 
   * @param elem the object's element
   */
  protected void setElement(com.google.gwt.user.client.Element elem) {
    assert (element == null) : SETELEMENT_TWICE_ERROR;
    this.element = elem;
  }

  /**
   * Replaces this object's browser element.
   * 
   * This method exists only to support a specific use-case in Image, and should
   * not be used by other classes.
   * 
   * @param elem the object's new element
   */
  void replaceElement(Element elem) {
    if (element != null) {
      // replace this.element in its parent with elem.
      replaceNode(element, elem);
    }

    this.element = elem;
  }

  /**
   * Intended to be used to pull the value out of a CSS length. If the
   * value is "auto" or "inherit", 0 will be returned.
   * 
   * @param s The CSS length string to extract
   * @return The leading numeric portion of <code>s</code>, or 0 if "auto" or
   *         "inherit" are passed in.
   */
  private native double extractLengthValue(String s) /*-{
    if (s == "auto" || s == "inherit" || s == "") {
      return 0;
    } else {
      // numberRegex is similar to java.lang.Number.floatRegex, but divides
      // the string into a leading numeric portion followed by an arbitrary
      // portion.
      var numberRegex = @com.google.gwt.user.client.ui.UIObject::numberRegex;
      if (!numberRegex) {
        numberRegex = @com.google.gwt.user.client.ui.UIObject::numberRegex =
          /^(\s*[+-]?((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?)(.*)$/;
      }

      // Extract the leading numeric portion of s
      s = s.replace(numberRegex, "$1");
      return parseFloat(s);
    }
  }-*/;

  private native void replaceNode(Element node, Element newNode) /*-{
    var p = node.parentNode;
    if (!p) {
      return;
    }
    p.insertBefore(newNode, node);
    p.removeChild(node);
  }-*/;
}
