com.allen_sauer.gwt.dnd.client.util.DOMUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.allen_sauer.gwt.dnd.client.util.DOMUtil.java

Source

/*
 * Copyright 2009 Fred Sauer
 * 
 * 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.allen_sauer.gwt.dnd.client.util;

import com.allen_sauer.gwt.dnd.client.util.impl.DOMUtilImpl;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.IndexedPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Provides DOM utility methods.
 */
public class DOMUtil {

    /**
     * Whether or not debugging is enabled.
     */
    public static final boolean DEBUG = false;

    private static DOMUtilImpl impl;

    static {
        impl = (DOMUtilImpl) GWT.create(DOMUtilImpl.class);
    }

    /**
     * Adjust line breaks within in the provided title for optimal readability and display length for
     * the current user agent.
     * 
     * @param title the desired raw text
     * @return formatted and escaped text
     */
    public static String adjustTitleForBrowser(String title) {
        return impl.adjustTitleForBrowser(title).replaceAll("</?code>", "`");
    }

    /**
     * Cancel all currently selected region(s) on the current page.
     */
    public static void cancelAllDocumentSelections() {
        impl.cancelAllDocumentSelections();
    }

    /**
     * Set a widget's border style for debugging purposes.
     * 
     * @param widget the widget to color
     * @param color the desired border color
     */
    public static void debugWidgetWithColor(Widget widget, String color) {
        if (DEBUG) {
            widget.getElement().getStyle().setProperty("border", "2px solid " + color);
        }
    }

    /**
     * Set an element's location as fast as possible, avoiding some of the overhead in
     * {@link com.google.gwt.user.client.ui.AbsolutePanel#setWidgetPosition(Widget, int, int)} .
     * 
     * @param elem the element's whose position is to be modified
     * @param left the left pixel offset
     * @param top the top pixel offset
     */
    public static void fastSetElementPosition(Element elem, int left, int top) {
        elem.getStyle().setPropertyPx("left", left);
        elem.getStyle().setPropertyPx("top", top);
    }

    /**
     * Find child widget intersection at the provided location using the provided comparator strategy.
     * 
     * TODO Change IndexedPanel -> InsertPanel
     * 
     * @param parent the parent widget which contains the children to be compared
     * @param location the location of the intersection
     * @param comparator the comparator strategy
     * @return the index of the matching child
     */
    public static int findIntersect(IndexedPanel parent, Location location, LocationWidgetComparator comparator) {
        int widgetCount = parent.getWidgetCount();

        // short circuit in case dropTarget has no children
        if (widgetCount == 0) {
            return 0;
        }

        // use the first widget as a proxy for parent's direction
        boolean rtl = isRtl(parent.getWidget(0));

        if (DEBUG) {
            for (int i = 0; i < widgetCount; i++) {
                debugWidgetWithColor(parent, i, "white");
            }
        }

        // binary search over range of widgets to find intersection
        int low = 0;
        int high = widgetCount;

        while (true) {
            int mid = (low + high) / 2;
            assert mid >= low;
            assert mid < high;
            Widget widget = parent.getWidget(mid);
            WidgetArea midArea = new WidgetArea(widget, null);
            if (mid == low) {
                if (mid == 0) {
                    if (comparator.locationIndicatesIndexFollowingWidget(midArea, location)) {
                        debugWidgetWithColor(parent, high, "green");
                        return high;
                    } else {
                        debugWidgetWithColor(parent, mid, "green");
                        return mid;
                    }
                } else {
                    debugWidgetWithColor(parent, high, "green");
                    return high;
                }
            }
            if (midArea.getBottom() < location.getTop()) {
                debugWidgetWithColor(parent, mid, "blue");
                low = mid;
            } else if (midArea.getTop() > location.getTop()) {
                debugWidgetWithColor(parent, mid, "red");
                high = mid;
            } else if (midArea.getRight() < location.getLeft()) {
                debugWidgetWithColor(parent, mid, "blue");
                if (rtl) {
                    high = mid;
                } else {
                    low = mid;
                }
            } else if (midArea.getLeft() > location.getLeft()) {
                debugWidgetWithColor(parent, mid, "red");
                if (rtl) {
                    low = mid;
                } else {
                    high = mid;
                }
            } else {
                if (comparator.locationIndicatesIndexFollowingWidget(midArea, location)) {
                    debugWidgetWithColor(parent, mid + 1, "green");
                    return mid + 1;
                } else {
                    debugWidgetWithColor(parent, mid, "green");
                    return mid;
                }
            }
        }
    }

    public static boolean isRtl(Widget widget) {
        Element elem = widget.getElement();
        return "rtl".equals(getEffectiveStyle(elem, "direction"));
    }

    /**
     * Gets an element's CSS based 'border-left-width' in pixels or <code>0</code> (zero) when the
     * element is hidden.
     * 
     * @param elem the element to be measured
     * @return the width of the left CSS border in pixels
     */
    public static int getBorderLeft(Element elem) {
        return impl.getBorderLeft(elem);
    }

    /**
     * Gets an element's CSS based 'border-top-widget' in pixels or <code>0</code> (zero) when the
     * element is hidden.
     * 
     * @param elem the element to be measured
     * @return the width of the top CSS border in pixels
     */
    public static int getBorderTop(Element elem) {
        return impl.getBorderTop(elem);
    }

    /**
     * Gets an element's client height in pixels or <code>0</code> (zero) when the element is hidden.
     * This is equal to offset height minus the top and bottom CSS borders.
     * 
     * @param elem the element to be measured
     * @return the element's client height in pixels
     */
    public static int getClientHeight(Element elem) {
        return impl.getClientHeight(elem);
    }

    /**
     * Gets an element's client widget in pixels or <code>0</code> (zero) when the element is hidden.
     * This is equal to offset width minus the left and right CSS borders.
     * 
     * @param elem the element to be measured
     * @return the element's client width in pixels
     */
    public static int getClientWidth(Element elem) {
        return impl.getClientWidth(elem);
    }

    public static String getEffectiveStyle(Element elem, String styleName) {
        return impl.getEffectiveStyle(elem, styleName);
    }

    /**
     * Gets the sum of an element's left and right CSS borders in pixels.
     * 
     * @param widget the widget to be measured
     * @return the total border width in pixels
     */
    public static int getHorizontalBorders(Widget widget) {
        return impl.getHorizontalBorders(widget);
    }

    /**
     * Determine an element's node name via the <code>nodeName</code> property.
     * 
     * @param elem the element whose node name is to be determined
     * @return the element's node name
     */
    public static String getNodeName(Element elem) {
        return elem.getNodeName();
    }

    /**
     * Gets the sum of an element's top and bottom CSS borders in pixels.
     * 
     * @param widget the widget to be measured
     * @return the total border height in pixels
     */
    public static int getVerticalBorders(Widget widget) {
        return impl.getVerticalBorders(widget);
    }

    /**
     * Report a fatal exception via <code>Window.alert()</code> than throw a
     * <code>RuntimeException</code>.
     * 
     * @param msg the message to report
     * @throws RuntimeException a new exception based on the provided message
     */
    public static void reportFatalAndThrowRuntimeException(String msg) throws RuntimeException {
        msg = "gwt-dnd warning: " + msg;
        Window.alert(msg);
        throw new RuntimeException(msg);
    }

    /**
     * Set the browser's status bar text, if supported and enabled in the client browser.
     * 
     * @param text the message to use as the window status
     */
    public static void setStatus(String text) {
        Window.setStatus(text);
    }

    /**
     * TODO Change IndexedPanel -> InsertPanel
     */
    private static void debugWidgetWithColor(IndexedPanel parent, int index, String color) {
        if (DEBUG) {
            if (index >= parent.getWidgetCount()) {
                debugWidgetWithColor(parent.getWidget(parent.getWidgetCount() - 1), color);
            } else {
                debugWidgetWithColor(parent.getWidget(index), color);
            }
        }
    }

    public native static NativeEvent createTouchEndEvent(boolean bubbles, boolean cancelable, int detail,
            boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
            JsArray<Touch> changedTouches) /*-{
                                           var evt = $doc.createEvent('TouchEvent');
                                           var view = null;
                                           evt.initUIEvent("touchend", bubbles, cancelable, view, detail);
                                           evt.changedTouches = changedTouches;
                                           return evt;
                                           }-*/;

}