package com.google.appinventor.client.utils; import com.google.gwt.core.client.JsArrayInteger; import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.ui.PopupPanel; /** * Implementation of PopupPanel.PositionCallback that can be alerted * when the browser is Pinch Zoomed in Google Chrome. Pinch Zooming in Chrome * causes both UIObject#getAbsoluteLeft() and UIObject#getAbsoluteTop() to return * inaccurate values. This class contains patched implementations for each. * * @author will2596@gmail.com (William Byrne) */ public abstract class PZAwarePositionCallback implements PopupPanel.PositionCallback { // Pinch Zoom flag which is tripped by a handler in Ode.java private static boolean pinchZoomed = false; // Element of the enclosing instance private final Element elem; public PZAwarePositionCallback(Element elem) { this.elem = elem; } public static boolean isPinchZoomed() { return pinchZoomed; } public static void setPinchZoomed(boolean pinchZoomed) { PZAwarePositionCallback.pinchZoomed = pinchZoomed; } public int getTrueAbsoluteLeft() { return getAbsolutePosition(elem).get(0); } public int getTrueAbsoluteTop() { return getAbsolutePosition(elem).get(1); } // Helper used to accurately determine the absolute left and absolute top // of the Element for use in positioning. Pinch Zooming breaks GWT's built-in // equivalents, DOMImpl#getSubPixelAbsoluteLeft(Element) and // DOMImpl#getSubPixelAbsoluteTop(Element). private native JsArrayInteger getAbsolutePosition(Element elem) /*-{ var curr = elem; var left = 0; var top = 0; if ($doc.getElementById) { do { left += elem.offsetLeft - elem.scrollLeft; top += elem.offsetTop - elem.scrollTop; elem = elem.offsetParent; curr = curr.parentNode; while (curr != elem) { left -= curr.scrollLeft; top -= curr.scrollTop; curr = curr.parentNode; } } while (elem.offsetParent); } return [left, top]; }-*/; }