GWT Java

/*
 * Copyright 2009 Sysmap Solutions Software e Consultoria Ltda.
 * 
 * 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 br.com.sysmap.crux.core.client.utils;
//import br.com.sysmap.crux.core.client.Crux;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.UIObject;
/**
 * Contains common operations for handling styles on HTML elements.
 *  
 * @author Gesse S. F. Dafe
 */
public class StyleUtils
{
  /**
   * Adds a dependent style name by specifying the style name's suffix. The
   * actual form of the style name that is added is:
   * 
   *  getStylePrimaryName() + '-' + styleSuffix 
   * 
   * @param styleSuffix
   *            the suffix of the dependent style to be added.
   * @see #setStylePrimaryName(String)
   * @see #removeStyleDependentName(String)
   * @see #addStyleName(String)
   */
  public static void addStyleDependentName(Element elem, String styleSuffix)
  {
    addStyleName(elem, getStylePrimaryName(elem) + '-' + styleSuffix);
  }
  /**
   * 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 #addStyleName(String)
   */
  public static void removeStyleDependentName(Element elem, String styleSuffix)
  {
    removeStyleName(elem, getStylePrimaryName(elem) + '-' + styleSuffix);
  }
  /**
   * 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 elem 
   * 
   * @param style
   *            the secondary style name to be removed
   * @see #addStyleName(String)
   */
  public static void removeStyleName(Element elem, String style)
  {
    setStyleName(elem, style, false);
  }
  /**
   * 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
   * class attribute for this object's root element.
   * 
   * 


   * The most important use for this method is to add a special kind of
   * secondary style name called a dependent style name. 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 gwt-TextBox. If the following
   * method is called as obj.setReadOnly(true):
   * 


   * 
   *  public void setReadOnly(boolean readOnly) {
   * isReadOnlyMode = readOnly;
   * 
   * // Create a dependent style name. String readOnlyStyle = "readonly";
   * 
   * if (readOnly) { addStyleDependentName(readOnlyStyle); } else {
   * removeStyleDependentName(readOnlyStyle); } }
   * 
   * 


   * then both of the CSS style rules below will be applied:
   * 


   * 
   * 
   * 
   * // 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; }
   * 
   * 


   * 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:
   * 


   * 
   * setStylePrimaryName("my-TextThingy");
   * 
   * 


   * then the object would be re-associated with following style rules,
   * removing those that were shown above.
   * 


   * 
   *  .my-TextThingy { font-size: 20pt; }
   * 
   * .my-TextThingy-readonly { background-color: red; border: 2px solid
   * yellow; }
   * 
   * 


   * Secondary style names that are not dependent style names are not
   * automatically updated when the primary style name changes.
   * 


   * 
   * @param elem
   * 
   * @param style
   *            the secondary style name to be added
   * @see UIObject
   * @see #removeStyleName(String)
   */
  public static void addStyleName(Element elem, String style)
  {
    setStyleName(elem, style, true);
  }
  /**
   * 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 style names 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
   *            true to add the given style, false
   *            to remove it
   */
  private static void setStyleName(Element elem, String style, boolean add)
  {
    if (elem == null)
    {
      //throw new IllegalArgumentException(Crux.getMessages().nullElementAtSetStyleName());
      ;
    }
    style = style.trim();
    if (style.length() == 0)
    {
      //throw new IllegalArgumentException(Crux.getMessages().emptyStringAsStyleNameValue());
      ;
    }
    // Get the current style string.
    String oldStyle = getStyleName(elem);
    int idx = oldStyle.indexOf(style);
    // Calculate matching index.
    while (idx != -1)
    {
      if (idx == 0 || oldStyle.charAt(idx - 1) == ' ')
      {
        int last = idx + style.length();
        int lastPos = oldStyle.length();
        if ((last == lastPos) || ((last < lastPos) && (oldStyle.charAt(last) == ' ')))
        {
          break;
        }
      }
      idx = oldStyle.indexOf(style, idx + 1);
    }
    if (add)
    {
      // Only add the style if it's not already present.
      if (idx == -1)
      {
        if (oldStyle.length() > 0)
        {
          oldStyle += " ";
        }
        DOM.setElementProperty(elem. cast(), "className", oldStyle + style);
      }
    }
    else
    {
      // Don't try to remove the style if it's not there.
      if (idx != -1)
      {
        // Get the leading and trailing parts, without the removed name.
        String begin = oldStyle.substring(0, idx).trim();
        String end = oldStyle.substring(idx + style.length()).trim();
        // Some contortions to make sure we don't leave extra spaces.
        String newClassName;
        if (begin.length() == 0)
        {
          newClassName = end;
        }
        else if (end.length() == 0)
        {
          newClassName = begin;
        }
        else
        {
          newClassName = begin + " " + end;
        }
        DOM.setElementProperty(elem. cast(), "className", newClassName);
      }
    }
  }
  /**
   * 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
   */
  private static String getStylePrimaryName(Element elem)
  {
    String fullClassName = getStyleName(elem);
    int spaceIdx = fullClassName.indexOf(' ');
    if (spaceIdx >= 0)
    {
      return fullClassName.substring(0, spaceIdx);
    }
    return fullClassName;
  }
  /**
   * 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
   */
  private static String getStyleName(Element elem)
  {
    return DOM.getElementProperty(elem. cast(), "className");
  }
  public static native void addStyleProperty(Element element, String camelizedName, String value)/*-{
    element.style[camelizedName] = value;
  }-*/;
}