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

org.opencms.gwt.client.util.CmsPositionBean Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

There is a newer version: 18.0
Show newest version
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.gwt.client.util;

import org.opencms.gwt.client.util.CmsDomUtil.Style;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.UIObject;

/**
 * Bean holding the position data of a HTML DOM element.

* * @since 8.0.0 */ public class CmsPositionBean { /** Position area. */ public static enum Area { /** Bottom border. */ BORDER_BOTTOM, /** Left border. */ BORDER_LEFT, /** Right border. */ BORDER_RIGHT, /** Top border. */ BORDER_TOP, /** The center. */ CENTER, /** Bottom left corner. */ CORNER_BOTTOM_LEFT, /** Bottom right corner. */ CORNER_BOTTOM_RIGHT, /** Top left corner. */ CORNER_TOP_LEFT, /** Top right corner. */ CORNER_TOP_RIGHT } /** The directions. */ static enum Direction { /** Bottom. */ bottom, /** Left. */ left, /** Right. */ right, /** Top. */ top } /** Element height. */ private int m_height; /** Position left. */ private int m_left; /** Position top. */ private int m_top; /** Element width. */ private int m_width; /** * Constructor.

*/ public CmsPositionBean() { // default constructor } /** * Copy constructor. Generating a copy of the given model.

* * @param model the model to copy */ public CmsPositionBean(CmsPositionBean model) { m_height = model.getHeight(); m_left = model.getLeft(); m_top = model.getTop(); m_width = model.getWidth(); } /** * Manipulates the position infos to ensure a minimum margin between the rectangles.

* * @param posA the first position to check * @param posB the second position to check * @param margin the required margin */ public static void avoidCollision(CmsPositionBean posA, CmsPositionBean posB, int margin) { Direction dir = null; int diff = 0; int diffTemp = (posB.getLeft() + posB.getWidth()) - posA.getLeft(); if (diffTemp > -margin) { dir = Direction.left; diff = diffTemp; } diffTemp = (posA.getLeft() + posA.getWidth()) - posB.getLeft(); if ((diffTemp > -margin) && (diffTemp < diff)) { dir = Direction.right; diff = diffTemp; } diffTemp = (posB.getTop() + posB.getHeight()) - posA.getTop(); if ((diffTemp > -margin) && (diffTemp < diff)) { dir = Direction.top; diff = diffTemp; } diffTemp = (posA.getTop() + posA.getHeight()) - posB.getTop(); if ((diffTemp > -margin) && (diffTemp < diff)) { dir = Direction.bottom; diff = diffTemp; } diff = (int)Math.ceil((1.0 * (diff + margin)) / 2); if (dir != null) { switch (dir) { case left: // move the left border of a posA.setLeft(posA.getLeft() + diff); posA.setWidth(posA.getWidth() - diff); // move the right border of b posB.setWidth(posB.getWidth() - diff); break; case right: // move the left border of b posB.setLeft(posB.getLeft() + diff); posB.setWidth(posB.getWidth() - diff); // move the right border of a posA.setWidth(posA.getWidth() - diff); break; case top: posA.setTop(posA.getTop() + diff); posA.setHeight(posA.getHeight() - diff); posB.setHeight(posB.getHeight() - diff); break; case bottom: posB.setTop(posB.getTop() + diff); posB.setHeight(posB.getHeight() - diff); posA.setHeight(posA.getHeight() - diff); break; default: // nothing to do } } } /** * Checks whether the two position rectangles collide.

* * @param posA the first position to check * @param posB the second position to check * @param margin the required margin * * @return true if the two position rectangles collide */ public static boolean checkCollision(CmsPositionBean posA, CmsPositionBean posB, int margin) { // check for non collision is easier if ((posA.getLeft() - margin) >= (posB.getLeft() + posB.getWidth())) { // posA is right of posB return false; } if ((posA.getLeft() + posA.getWidth()) <= (posB.getLeft() - margin)) { // posA is left of posB return false; } if ((posA.getTop() - margin) >= (posB.getTop() + posB.getHeight())) { // posA is bellow posB return false; } if ((posA.getTop() + posA.getHeight()) <= (posB.getTop() - margin)) { // posA is above posB return false; } // in any other case the position rectangles collide return true; } /** * Collects the position information of the given UI object and returns a position info bean.

* * @param element the object to read the position data from * * @return the position data */ public static CmsPositionBean generatePositionInfo(Element element) { CmsPositionBean result = new CmsPositionBean(); result.setHeight(element.getOffsetHeight()); result.setWidth(element.getOffsetWidth()); result.setTop(element.getAbsoluteTop()); result.setLeft(element.getAbsoluteLeft()); return result; } /** * Collects the position information of the given UI object and returns a position info bean.

* * @param uiObject the object to read the position data from * * @return the position data */ public static CmsPositionBean generatePositionInfo(UIObject uiObject) { return generatePositionInfo(uiObject.getElement()); } /** * Returns the bounding rectangle dimensions of the element including all floated elements.

* * @param panel the panel * * @return the position info */ public static CmsPositionBean getBoundingClientRect(Element panel) { return getBoundingClientRect(panel, true); } /** * Returns the bounding rectangle dimensions of the element including all floated elements.

* * @param panel the panel * @param addScroll if true, the result will contain the coordinates in the document's coordinate system, not the viewport coordinate system * * @return the position info */ public static CmsPositionBean getBoundingClientRect(Element panel, boolean addScroll) { CmsPositionBean result = new CmsPositionBean(); getBoundingClientRect( panel, result, addScroll ? Window.getScrollLeft() : 0, addScroll ? Window.getScrollTop() : 0); return result; } /** * Returns a position info representing the dimensions of all visible child elements of the given panel (excluding elements with position:absolute). * If the panel has no visible child elements, it's outer dimensions are returned.

* * @param panel the panel * * @return the position info */ public static CmsPositionBean getInnerDimensions(Element panel) { boolean first = true; int top = 0; int left = 0; int bottom = 0; int right = 0; Element child = panel.getFirstChildElement(); while (child != null) { String tagName = child.getTagName(); if (tagName.equalsIgnoreCase("br") || tagName.equalsIgnoreCase("tr") || tagName.equalsIgnoreCase("thead") || tagName.equalsIgnoreCase("tfoot") || tagName.equalsIgnoreCase("script") || tagName.equalsIgnoreCase("style")) { // ignore tags with no relevant position info child = child.getNextSiblingElement(); continue; } String positioning = CmsDomUtil.getCurrentStyle(child, Style.position); if (!Display.NONE.getCssName().equals(CmsDomUtil.getCurrentStyle(child, Style.display)) && !(positioning.equalsIgnoreCase(Position.ABSOLUTE.getCssName()) || positioning.equalsIgnoreCase(Position.FIXED.getCssName()))) { CmsPositionBean childDimensions = getBoundingClientRect(child); if (first) { first = false; top = childDimensions.getTop(); left = childDimensions.getLeft(); bottom = top + childDimensions.getHeight(); right = left + childDimensions.getWidth(); } else { int wTop = childDimensions.getTop(); top = top < wTop ? top : wTop; int wLeft = childDimensions.getLeft(); left = left < wLeft ? left : wLeft; int wBottom = wTop + childDimensions.getHeight(); bottom = bottom > wBottom ? bottom : wBottom; int wRight = wLeft + childDimensions.getWidth(); right = right > wRight ? right : wRight; } } child = child.getNextSiblingElement(); } if (!first) { CmsPositionBean result = new CmsPositionBean(); result.setHeight(bottom - top); result.setWidth(right - left); result.setTop(top); result.setLeft(left); return result; } else { return getBoundingClientRect(panel); } } /** * Checks whether a value is in a given interval (including the end points).

* * @param min the minimum of the interval * @param max the maximum of the interval * @param value the value to check * * @return true if the value is in the given interval */ public static boolean isInRangeInclusive(int min, int max, int value) { return (min <= value) && (value <= max); } /** * Uses the getBoundingClientRect method to evaluate the element dimensions.

* * @param element the element * @param pos the position bean * @param scrollLeft the window scroll position left * @param scrollTop the window scroll position top */ private static native void getBoundingClientRect( Element element, CmsPositionBean pos, int scrollLeft, int scrollTop)/*-{ var rect = element.getBoundingClientRect(); [email protected]::m_top=Math.round(rect.top+scrollTop); [email protected]::m_left=Math.round(rect.left+scrollLeft); [email protected]::m_height=Math.round(rect.height); [email protected]::m_width=Math.round(rect.width); }-*/; /** * Checks if the rectangle defined by this bean contains the given point.

* * @param x the horizontal coordinate * @param y the vertical coordinate * * @return true if this object contains the given point */ public boolean containsPoint(int x, int y) { return isInRangeInclusive(getLeft(), (getLeft() + getWidth()) - 1, x) && isInRangeInclusive(getTop(), (getTop() + getHeight()) - 1, y); } /** * Increases the dimensions to completely surround the child.

* * @param child the child position info * @param padding the padding to apply */ public void ensureSurrounds(CmsPositionBean child, int padding) { // increase the size of the outer rectangle if ((getLeft() + padding) > child.getLeft()) { int diff = getLeft() - child.getLeft(); // ensure padding diff += padding; setLeft(getLeft() - diff); setWidth(getWidth() + diff); } if ((getTop() + padding) > child.getTop()) { int diff = getTop() - child.getTop(); diff += padding; setTop(getTop() - diff); setHeight(getHeight() + diff); } if ((getLeft() + getWidth()) < (child.getLeft() + child.getWidth() + padding)) { int diff = (child.getLeft() + child.getWidth()) - (getLeft() + getWidth()); diff += padding; setWidth(getWidth() + diff); } if ((getTop() + getHeight()) < (child.getTop() + child.getHeight() + padding)) { int diff = (child.getTop() + child.getHeight()) - (getTop() + getHeight()); diff += padding; setHeight(getHeight() + diff); } } /** * Returns over which area of this the given position is. Will return null if the provided position is not within this position.

* * @param absLeft the left position * @param absTop the right position * @param offset the border offset * * @return the area */ public Area getArea(int absLeft, int absTop, int offset) { if (isOverElement(absLeft, absTop)) { if (absLeft < (m_left + 10)) { // left border if (absTop < (m_top + offset)) { // top left corner return Area.CORNER_TOP_LEFT; } else if (absTop > ((m_top + m_height) - offset)) { // bottom left corner return Area.CORNER_BOTTOM_LEFT; } return Area.BORDER_LEFT; } if (absLeft > ((m_left + m_width) - offset)) { // right border if (absTop < (m_top + offset)) { // top right corner return Area.CORNER_TOP_RIGHT; // fixing opposite corner } else if (absTop > ((m_top + m_height) - offset)) { // bottom right corner return Area.CORNER_BOTTOM_RIGHT; // fixing opposite corner } return Area.BORDER_RIGHT; } if (absTop < (m_top + offset)) { // border top return Area.BORDER_TOP; } else if (absTop > ((m_top + m_height) - offset)) { // border bottom return Area.BORDER_BOTTOM; } return Area.CENTER; } return null; } /** * Returns the height.

* * @return the height */ public int getHeight() { return m_height; } /** * Returns the left.

* * @return the left */ public int getLeft() { return m_left; } /** * Returns the top.

* * @return the top */ public int getTop() { return m_top; } /** * Returns the width.

* * @return the width */ public int getWidth() { return m_width; } /** * Checks whether the given position is completely surrounded by this position.

* * @param child the child position * @param padding the padding to use * * @return true if the child position is completely surrounded */ public boolean isInside(CmsPositionBean child, int padding) { return ((getLeft() + padding) < child.getLeft()) // checking left border && ((getTop() + padding) < child.getTop()) // checking top border && (((getLeft() + getWidth()) - padding) > (child.getLeft() + child.getWidth())) // checking right border && (((getTop() + getHeight()) - padding) > (child.getTop() + child.getHeight())); // checking bottom border } /** * Returns if given position is inside the position beans coordinates.

* * @param absLeft the absolute left position * @param absTop the absolute top position * * @return true if the given position if within the beans coordinates */ public boolean isOverElement(int absLeft, int absTop) { if ((absTop > m_top) && (absTop < (m_top + m_height)) && (absLeft > m_left) && (absLeft < (m_left + m_width))) { return true; } /* */ return false; } /** * Returns if given absolute top is above the vertical middle of the position beans coordinates.

* * @param absTop the absolute top position * @return true if given absolute top is above the vertical middle */ public boolean isOverTopHalf(int absTop) { if (absTop < (m_top + (m_height / 2))) { return true; } return false; } /** * Sets the height.

* * @param height the height to set */ public void setHeight(int height) { m_height = height; } /** * Sets the left.

* * @param left the left to set */ public void setLeft(int left) { m_left = left; } /** * Sets the top.

* * @param top the top to set */ public void setTop(int top) { m_top = top; } /** * Sets the width.

* * @param width the width to set */ public void setWidth(int width) { m_width = width; } /** * @see java.lang.Object#toString() */ @Override public String toString() { return "top: " + m_top + " left: " + m_left + " height: " + m_height + " width: " + m_width; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy