/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH (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.ui.UIObject;
/**
* Bean holding the position data of a HTML DOM element.<p>
*
* @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
}
/** 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.<p>
*/
public CmsPositionBean() {
// default constructor
}
/**
* Copy constructor. Generating a copy of the given model.<p>
*
* @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();
}
/**
* Collects the position information of the given UI object and returns a position info bean.<p>
*
* @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.<p>
*
* @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 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.<p>
*
* @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 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()))) {
if (first) {
first = false;
top = child.getAbsoluteTop();
left = child.getAbsoluteLeft();
bottom = top + child.getOffsetHeight();
right = left + child.getOffsetWidth();
} else {
int wTop = child.getAbsoluteTop();
top = top < wTop ? top : wTop;
int wLeft = child.getAbsoluteLeft();
left = left < wLeft ? left : wLeft;
int wBottom = wTop + child.getOffsetHeight();
bottom = bottom > wBottom ? bottom : wBottom;
int wRight = wLeft + child.getOffsetWidth();
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 generatePositionInfo(panel);
}
}
/**
* Returns over which area of this the given position is. Will return <code>null</code> if the provided position is not within this position.<p>
*
* @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.<p>
*
* @return the height
*/
public int getHeight() {
return m_height;
}
/**
* Returns the left.<p>
*
* @return the left
*/
public int getLeft() {
return m_left;
}
/**
* Returns the top.<p>
*
* @return the top
*/
public int getTop() {
return m_top;
}
/**
* Returns the width.<p>
*
* @return the width
*/
public int getWidth() {
return m_width;
}
/**
* Returns if given position is inside the position beans coordinates.<p>
*
* @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.<p>
*
* @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.<p>
*
* @param height the height to set
*/
public void setHeight(int height) {
m_height = height;
}
/**
* Sets the left.<p>
*
* @param left the left to set
*/
public void setLeft(int left) {
m_left = left;
}
/**
* Sets the top.<p>
*
* @param top the top to set
*/
public void setTop(int top) {
m_top = top;
}
/**
* Sets the width.<p>
*
* @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;
}
}