gt:     return impl.getUnitSizeInPixels(parentElem, unit, vertical);
context: /*
   * Copyright 2009 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.layout.client;
  
  import static com.google.gwt.dom.client.Style.Unit.PX;
  
  import com.google.gwt.animation.client.Animation;
  import com.google.gwt.core.client.GWT;
  import com.google.gwt.dom.client.Element;
  import com.google.gwt.dom.client.Style.Unit;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Helper class for laying out a container element and its children.
   * 
   * <p>
   * This class is typically used by higher-level widgets to implement layout on
   * their behalf. It is intended to wrap an element (usually a &lt;div&gt;), and
   * lay its children out in a predictable fashion, automatically accounting for
   * changes to the parent's size, and for all elements' margins, borders, and
   * padding.
   * </p>
   * 
   * <p>
   * To use this class, create a container element (again, usually a &lt;div&gt;)
   * and pass it to {@link #Layout(Element)}. Rather than attaching child elements
   * directly to the element managed by this {@link Layout}, use the
   * {@link Layout#attachChild(Element)} method. This will attach the child
   * element and return a {@link Layout.Layer} object which is used to manage the
   * child.
   * </p>
   * 
   * <p>
   * A separate {@link Layout.Layer} instance is associated with each child
   * element. There is a set of methods available on this class to manipulate the
   * child element's position and size. In order for changes to a layer to take
   * effect, you must finally call one of {@link #layout()} or
   * {@link #layout(int)}. This allows many changes to different layers to be
   * applied efficiently, and to be animated.
   * </p>
   * 
   * <p>
   * On most browsers, this is implemented using absolute positioning. It also
   * contains extra logic to make IE6 work properly.
   * </p>
   * 
   * <p>
   * <h3>Example</h3>
   * {@example com.google.gwt.examples.LayoutExample}
   * </p>
   * 
   * <p>
   * NOTE: This class will <em>only</em> work in standards mode, which requires
   * that the HTML page in which it is run have an explicit &lt;!DOCTYPE&gt;
   * declaration.
   * </p>
   * 
   * <p>
   * NOTE: This class is still very new, and its interface may change without
   * warning. Use at your own risk.
   * </p>
   */
  public class Layout {
  
    /**
     * Used to specify the alignment of child elements within a layer.
     */
    public enum Alignment {
  
      /**
       * Positions an element at the beginning of a given axis.
       */
      BEGIN,
  
      /**
       * Positions an element at the beginning of a given axis.
       */
      END,
  
      /**
       * Stretches an element to fill the layer on a given axis.
       */
      STRETCH;
    }
  
    /**
     * Callback interface used by {@link Layout#layout(int, AnimationCallback)}
     * to provide updates on animation progress.
     */
    public interface AnimationCallback {
  
      /**
       * Called immediately after the animation is complete, and the entire layout
       * is in its final state.
       */
      void onAnimationComplete();
  
      /**
       * Called at each step of the animation, for each layer being laid out.
       * 
       * @param layer the layer being laid out
       */
      void onLayout(Layer layer, double progress);
    }
  
    /**
     * This class is used to set the position and size of child elements.
     * 
     * <p>
     * Each child element has three values associated with each axis: {left,
     * right, width} on the horizontal axis, and {top, bottom, height} on the
     * vertical axis. Precisely two of three values may be set at a time, or the
     * system will be over- or under-contrained. For this reason, the following
     * methods are provided for setting these values:
     * <ul>
     * <li>{@link Layout.Layer#setLeftRight}</li>
     * <li>{@link Layout.Layer#setLeftWidth}</li>
     * <li>{@link Layout.Layer#setRightWidth}</li>
     * <li>{@link Layout.Layer#setTopBottom}</li>
     * <li>{@link Layout.Layer#setTopHeight}</li>
     * <li>{@link Layout.Layer#setBottomHeight}</li>
     * </ul>
     * </p>
     * 
     * <p>
     * By default, each layer is set to fill the entire parent (i.e., {left, top,
     * right, bottom} = {0, 0, 0, 0}).
     * </p>
     */
    public class Layer {
      final Element container, child;
      Object userObject;
  
      boolean setLeft, setRight, setTop, setBottom, setWidth, setHeight;
      boolean setTargetLeft = true, setTargetRight = true, setTargetTop = true,
          setTargetBottom = true, setTargetWidth, setTargetHeight;
      Unit leftUnit, topUnit, rightUnit, bottomUnit, widthUnit, heightUnit;
      Unit targetLeftUnit = PX, targetTopUnit = PX, targetRightUnit = PX,
          targetBottomUnit = PX, targetWidthUnit, targetHeightUnit;
      double left, top, right, bottom, width, height;
      double sourceLeft, sourceTop, sourceRight, sourceBottom, sourceWidth,
          sourceHeight;
      double targetLeft, targetTop, targetRight, targetBottom, targetWidth,
          targetHeight;
  
      Alignment hPos = Alignment.STRETCH, vPos = Alignment.STRETCH;
      boolean visible = true;
  
      Layer(Element container, Element child, Object userObject) {
        this.container = container;
        this.child = child;
        this.userObject = userObject;
      }
  
      /**
       * Gets the container element associated with this layer.
       * 
       * <p>
       * This is the element that sits between the parent and child elements. It
       * is normally necessary to operate on this element only when you need to
       * modify CSS properties that are not directly modeled by the Layer class.
       * </p>
       * 
       * @return the container element
       */
      public Element getContainerElement() {
        return container;
      }
  
      /**
       * Gets the user-data associated with this layer.
       * 
       * @return the layer's user-data object
       */
      public Object getUserObject() {
        return this.userObject;
      }
  
      /**
       * Sets the layer's bottom and height values.
       * 
       * @param bottom
       * @param bottomUnit
       * @param height
       * @param heightUnit
       */
      public void setBottomHeight(double bottom, Unit bottomUnit, double height,
          Unit heightUnit) {
        this.setTargetBottom = this.setTargetHeight = true;
        this.setTargetTop = false;
        this.targetBottom = bottom;
        this.targetHeight = height;
        this.targetBottomUnit = bottomUnit;
        this.targetHeightUnit = heightUnit;
      }
  
      /**
       * Sets the child element's horizontal position within the layer.
       * 
       * @param position
       */
      public void setChildHorizontalPosition(Alignment position) {
        this.hPos = position;
      }
  
      /**
       * Sets the child element's vertical position within the layer.
       * 
       * @param position
       */
      public void setChildVerticalPosition(Alignment position) {
        this.vPos = position;
      }
  
      /**
       * Sets the layer's left and right values.
       * 
       * @param left
       * @param leftUnit
       * @param right
       * @param rightUnit
       */
      public void setLeftRight(double left, Unit leftUnit, double right,
          Unit rightUnit) {
        this.setTargetLeft = this.setTargetRight = true;
        this.setTargetWidth = false;
        this.targetLeft = left;
        this.targetRight = right;
        this.targetLeftUnit = leftUnit;
        this.targetRightUnit = rightUnit;
      }
  
      /**
       * Sets the layer's left and width values.
       * 
       * @param left
       * @param leftUnit
       * @param width
       * @param widthUnit
       */
      public void setLeftWidth(double left, Unit leftUnit, double width,
          Unit widthUnit) {
        this.setTargetLeft = this.setTargetWidth = true;
        this.setTargetRight = false;
        this.targetLeft = left;
        this.targetWidth = width;
        this.targetLeftUnit = leftUnit;
        this.targetWidthUnit = widthUnit;
      }
  
      /**
       * Sets the layer's right and width values.
       * 
       * @param right
       * @param rightUnit
       * @param width
       * @param widthUnit
       */
      public void setRightWidth(double right, Unit rightUnit, double width,
          Unit widthUnit) {
        this.setTargetRight = this.setTargetWidth = true;
        this.setTargetLeft = false;
        this.targetRight = right;
        this.targetWidth = width;
        this.targetRightUnit = rightUnit;
        this.targetWidthUnit = widthUnit;
      }
  
      /**
       * Sets the layer's top and bottom values.
       * 
       * @param top
       * @param topUnit
       * @param bottom
       * @param bottomUnit
       */
      public void setTopBottom(double top, Unit topUnit, double bottom,
          Unit bottomUnit) {
        this.setTargetTop = this.setTargetBottom = true;
        this.setTargetHeight = false;
        this.targetTop = top;
        this.targetBottom = bottom;
        this.targetTopUnit = topUnit;
        this.targetBottomUnit = bottomUnit;
      }
  
      /**
       * Sets the layer's top and height values.
       * 
       * @param top
       * @param topUnit
       * @param height
       * @param heightUnit
       */
      public void setTopHeight(double top, Unit topUnit, double height,
          Unit heightUnit) {
        this.setTargetTop = this.setTargetHeight = true;
        this.setTargetBottom = false;
        this.targetTop = top;
        this.targetHeight = height;
        this.targetTopUnit = topUnit;
        this.targetHeightUnit = heightUnit;
      }
  
      /**
       * Sets the layer's visibility.
       * 
       * @param visible
       */
      public void setVisible(boolean visible) {
        this.visible = visible;
      }
    }
  
    private LayoutImpl impl = GWT.create(LayoutImpl.class);
  
    private List<Layer> layers = new ArrayList<Layer>();
    private final Element parentElem;
    private Animation animation;
  
    /**
     * Constructs a new layout associated with the given parent element.
     * 
     * @param parent the element to serve as the layout parent
     */
    public Layout(Element parent) {
      this.parentElem = parent;
      impl.initParent(parent);
    }
  
    /**
     * Asserts that the given child element is managed by this layout.
     * 
     * @param elem the element to be tested
     */
    public void assertIsChild(Element elem) {
      assert elem.getParentElement().getParentElement() == this.parentElem : "Element is not a child of this layout";
    }
  
    /**
     * Attaches a child element to this layout.
     * 
     * <p>
     * This method will attach the child to the layout, removing it from its
     * current parent element. Use the {@link Layer} it returns to manipulate the
     * child.
     * </p>
     * 
     * @param child the child to be attached
     * @return the {@link Layer} associated with the element
     */
    public Layer attachChild(Element child) {
      return attachChild(child, null);
    }
  
    /**
     * Attaches a child element to this layout.
     * 
     * <p>
     * This method will attach the child to the layout, removing it from its
     * current parent element. Use the {@link Layer} it returns to manipulate the
     * child.
     * </p>
     * 
     * @param child the child to be attached
     * @param before the child element before which to insert
     * @return the {@link Layer} associated with the element
     */
    public Layer attachChild(Element child, Element before) {
      return attachChild(child, before, null);
    }
  
    /**
     * Attaches a child element to this layout.
     * 
     * <p>
     * This method will attach the child to the layout, removing it from its
     * current parent element. Use the {@link Layer} it returns to manipulate the
     * child.
     * </p>
     * 
     * @param child the child to be attached
     * @param userObject an arbitrary object to be associated with this layer
     * @return the {@link Layer} associated with the element
     */
    public Layer attachChild(Element child, Object userObject) {
      return attachChild(child, null, userObject);
    }
  
    /**
     * Attaches a child element to this layout.
     * 
     * <p>
     * This method will attach the child to the layout, removing it from its
     * current parent element. Use the {@link Layer} it returns to manipulate the
     * child.
     * </p>
     * 
     * @param child the child to be attached
     * @param before the child element before which to insert
     * @param userObject an arbitrary object to be associated with this layer
     * @return the {@link Layer} associated with the element
     */
    public Layer attachChild(Element child, Element before, Object userObject) {
      Element container = impl.attachChild(parentElem, child, before);
      Layer layer = new Layer(container, child, userObject);
      layers.add(layer);
      return layer;
    }
  
    /**
     * Causes the parent element to fill its own parent.
     * 
     * <p>
     * This is most useful for top-level layouts that need to follow the size of
     * another element, such as the &lt;body&gt;.
     * </p>
     */
    public void fillParent() {
      impl.fillParent(parentElem);
    }
  
    /**
     * Returns the size of one unit, in pixels, in the context of this layout.
     * 
     * <p>
     * This will work for any unit type, but be aware that certain unit types,
     * such as {@link Unit#EM}, and {@link Unit#EX}, will return different values
     * based upon the parent's associated font size. {@link Unit#PCT} is dependent
     * upon the parent's actual size, and the axis to be measured.
     * </p>
     * 
     * @param unit the unit type to be measured
     * @param vertical whether the unit to be measured is on the vertical or
     *          horizontal axis (this matters only for {@link Unit#PCT})
     * @return the unit size, in pixels
     */
    public double getUnitSize(Unit unit, boolean vertical) {
  