All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.layout.client.LayoutImplIE8 Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * 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 com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.layout.client.Layout.Layer;

/**
 * This implementation is used on IE8. Unlike {@code LayoutImpl}, it converts
 * all values to pixels before setting them. This is necessary because this
 * browser incorrectly calculates the relative sizes and positions of CSS
 * properties specified in certain units (e.g., when the value of an 'em' is
 * non-integral in pixels).
 */
public class LayoutImplIE8 extends LayoutImpl {

  private static native Layer getLayer(Element container) /*-{
    return container.__layer;
  }-*/;

  private static native void setLayer(Element container, Layer layer) /*-{
    // Potential leak: This is cleaned up in detach().
    container.__layer = layer;
  }-*/;

  @Override
  public void layout(Layer layer) {
    Style style = layer.container.getStyle();
    setLayer(layer.container, layer);

    // Whenever the visibility of a layer changes, we need to ensure that
    // layout() is run again for it. This is because the translation of units
    // to pixel values will be incorrect for invisible elements, and thus must
    // be fixed when they become visible.
    if (layer.visible) {
      String oldDisplay = style.getDisplay();
      style.clearDisplay();

      // We control the layer element, so assume that any non-zero display
      // property means it was set to 'none'.
      if (oldDisplay.length() > 0) {
        updateVisibility(layer.container);
      }
    } else {
      style.setDisplay(Display.NONE);
    }

    if (layer.setLeft) {
      setValue(layer, "left", layer.left, layer.leftUnit, false, false);
    } else {
      style.clearLeft();
    }
    if (layer.setRight) {
      setValue(layer, "right", layer.right, layer.rightUnit, false, false);
    } else {
      style.clearRight();
    }
    if (layer.setTop) {
      setValue(layer, "top", layer.top, layer.topUnit, true, false);
    } else {
      style.clearTop();
    }
    if (layer.setBottom) {
      setValue(layer, "bottom", layer.bottom, layer.bottomUnit, true, false);
    } else {
      style.clearBottom();
    }
    if (layer.setWidth) {
      setValue(layer, "width", layer.width, layer.widthUnit, false, true);
    } else {
      style.clearWidth();
    }
    if (layer.setHeight) {
      setValue(layer, "height", layer.height, layer.heightUnit, true, true);
    } else {
      style.clearHeight();
    }

    style = layer.child.getStyle();
    switch (layer.hPos) {
      case BEGIN:
        style.setLeft(0, Unit.PX);
        style.clearRight();
        break;
      case END:
        style.clearLeft();
        style.setRight(0, Unit.PX);
        break;
      case STRETCH:
        style.setLeft(0, Unit.PX);
        style.setRight(0, Unit.PX);
        break;
    }

    switch (layer.vPos) {
      case BEGIN:
        style.setTop(0, Unit.PX);
        style.clearBottom();
        break;
      case END:
        style.clearTop();
        style.setBottom(0, Unit.PX);
        break;
      case STRETCH:
        style.setTop(0, Unit.PX);
        style.setBottom(0, Unit.PX);
        break;
    }
  }

  @Override
  public void onDetach(Element parent) {
    removeLayerRefs(parent);
  }

  private native void removeLayerRefs(Element parent) /*-{
    for (var i = 0; i < parent.childNodes.length; ++i) {
      var container = parent.childNodes[i];
      if (container.__layer) {
        container.__layer = null;
      }
    }
  }-*/;

  private void setValue(Layer layer, String prop, double value, Unit unit,
      boolean vertical, boolean noNegative) {
    switch (unit) {
      case PX:
      case PCT:
        // Leave PX and PCT alone. PX doesn't need to be translated, and PCT
        // can't be.
        break;

      default:
        value = value * getUnitSizeInPixels(layer.container, unit, vertical);
        value = (int) (value + 0.5); // Round to the nearest pixel.
        unit = Unit.PX;
        break;
    }

    if (noNegative) {
      if (value < 0) {
        value = 0;
      }
    }

    layer.getContainerElement().getStyle().setProperty(prop, value, unit);
  }

  private void updateVisibility(Element container) {
    // If this element has an associated layer, re-run layout for it.
    Layer layer = getLayer(container);
    if (layer != null) {
      layout(layer);
    }

    // Walk all children, looking for elements with a '__layer' property. If one
    // exists, call layout() for that element. This is not cheap, but it's the
    // only way to correctly ensure that layout units get translated correctly.
    NodeList nodes = container.getChildNodes();
    for (int i = 0; i < nodes.getLength(); ++i) {
      Node node = nodes.getItem(i);
      if (node.getNodeType() == Node.ELEMENT_NODE) {
        updateVisibility(node.cast());
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy