/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2012 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.server.headlessclient.dataui;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Hashtable;
import java.util.Properties;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.model.AbstractReadOnlyModel;
import com.servoy.j2db.IServiceProvider;
import com.servoy.j2db.component.ComponentFactory;
import com.servoy.j2db.persistence.Field;
import com.servoy.j2db.persistence.IAnchorConstants;
import com.servoy.j2db.persistence.IFormElement;
import com.servoy.j2db.persistence.ISupportAnchors;
import com.servoy.j2db.server.headlessclient.WrapperContainer;
import com.servoy.j2db.ui.ISupportWebBounds;
import com.servoy.j2db.util.Utils;
/**
* Helper class for web anchoring
* @author gboros
*/
public class WebAnchoringHelper
{
public static Component getWrapperComponent(Component comp, IFormElement obj, int start, Dimension panelSize, boolean leftToRight, boolean isInListView)
{
MarkupContainer compWrapper = new WrapperContainer(ComponentFactory.getWebID(null, obj) + TemplateGenerator.WRAPPER_SUFFIX, comp);
Point l = (obj).getLocation();
if (isInListView)
{
// substract left indicator
l.x = Math.max(l.x - 3, 0);
}
Dimension s = (obj).getSize();
int anchors = 0;
if (obj instanceof ISupportAnchors) anchors = ((ISupportAnchors)obj).getAnchors();
int offsetWidth = s.width;
int offsetHeight = s.height;
if (comp instanceof ISupportWebBounds)
{
Rectangle b = ((ISupportWebBounds)comp).getWebBounds();
offsetWidth = b.width;
offsetHeight = b.height;
}
final String styleToReturn = WebAnchoringHelper.computeWrapperDivStyle(l.y, l.x, offsetWidth, offsetHeight, s.width, s.height, anchors, start, start +
panelSize.height, panelSize.width, leftToRight);
// first the default
compWrapper.add(new StyleAppendingModifier(new AbstractReadOnlyModel<String>()
{
@Override
public String getObject()
{
return styleToReturn;
}
}));
// then the style t hat can be set on the wrapped component
compWrapper.add(StyleAttributeModifierModel.INSTANCE);
// TODO: this needs to be done in a cleaner way. See what is the relation between
// margin, padding and border when calculating the websize in ChangesRecorder vs. TemplateGenerator.
// Looks like one of the three is not taken into account during calculations. For now decided to remove
// the margin and leave the padding and border.
comp.add(new StyleAppendingModifier(new AbstractReadOnlyModel<String>()
{
@Override
public String getObject()
{
return "margin: 0px;"; //$NON-NLS-1$
}
}));
return compWrapper;
}
public static boolean needsWrapperDivForAnchoring(Field field)
{
// this needs to be in sync with DesignModeBehavior.needsWrapperDivForAnchoring(String type)
return (field.getDisplayType() == Field.PASSWORD) || (field.getDisplayType() == Field.TEXT_AREA) || (field.getDisplayType() == Field.COMBOBOX) ||
(field.getDisplayType() == Field.TYPE_AHEAD) || (field.getDisplayType() == Field.TEXT_FIELD) || (field.getDisplayType() == Field.LIST_BOX) ||
(field.getDisplayType() == Field.MULTISELECT_LISTBOX) || (field.getDisplayType() == Field.HTML_AREA && field.getEditable());
}
private static String computeWrapperDivStyle(int top, int left, int width, int height, int offsetWidth, int offsetHeight, int anchorFlags, int partStartY,
int partEndY, int partWidth, boolean leftToRight)
{
Hashtable<String, String> style = new Hashtable<String, String>();
if (top != -1) style.put("top", top + "px"); //$NON-NLS-1$ //$NON-NLS-2$
if (left != -1) style.put("left", left + "px"); //$NON-NLS-1$ //$NON-NLS-2$
if (width != -1) style.put("width", width + "px"); //$NON-NLS-1$ //$NON-NLS-2$
if (height != -1) style.put("height", height + "px"); //$NON-NLS-1$ //$NON-NLS-2$
boolean anchoredTop = (anchorFlags & IAnchorConstants.NORTH) != 0;
boolean anchoredRight = (anchorFlags & IAnchorConstants.EAST) != 0;
boolean anchoredBottom = (anchorFlags & IAnchorConstants.SOUTH) != 0;
boolean anchoredLeft = (anchorFlags & IAnchorConstants.WEST) != 0;
if (!anchoredLeft && !anchoredRight) anchoredLeft = true;
if (!anchoredTop && !anchoredBottom) anchoredTop = true;
int deltaLeft = leftToRight ? 0 : offsetWidth - width;
int deltaRight = leftToRight ? offsetWidth - width : 0;
int deltaBottom = offsetHeight - height;
if (anchoredTop) style.put("top", (top - partStartY) + "px"); //$NON-NLS-1$ //$NON-NLS-2$
else style.remove("top"); //$NON-NLS-1$
if (anchoredBottom) style.put("bottom", (partEndY - top - offsetHeight + deltaBottom) + "px"); //$NON-NLS-1$ //$NON-NLS-2$
if (!anchoredTop || !anchoredBottom) style.put("height", height + "px"); //$NON-NLS-1$ //$NON-NLS-2$
else style.remove("height"); //$NON-NLS-1$
if (anchoredLeft) style.put("left", (left + deltaLeft) + "px"); //$NON-NLS-1$ //$NON-NLS-2$
else style.remove("left"); //$NON-NLS-1$
if (anchoredRight) style.put("right", (partWidth - left - offsetWidth + deltaRight) + "px"); //$NON-NLS-1$ //$NON-NLS-2$
if (!anchoredLeft || !anchoredRight) style.put("width", width + "px"); //$NON-NLS-1$ //$NON-NLS-2$
else style.remove("width"); //$NON-NLS-1$
style.put("position", "absolute"); //$NON-NLS-1$ //$NON-NLS-2$
if (width != -1) style.put("min-width", width + "px"); //$NON-NLS-1$ //$NON-NLS-2$
StringBuffer sb = new StringBuffer();
for (String key : style.keySet())
{
String value = style.get(key);
sb.append(key);
sb.append(": "); //$NON-NLS-1$
sb.append(value);
sb.append("; "); //$NON-NLS-1$
}
return sb.toString();
}
public static void addMinSize(int anchors, IServiceProvider application, Properties cssProperties, Dimension size, IFormElement formElement)
{
if (size != null && (application == null || Utils.getAsBoolean(application.getRuntimeProperties().get("enableAnchors"))) &&
!TemplateGenerator.isTableViewComponent(formElement))
{
if (((anchors & IAnchorConstants.EAST) > 0) && ((anchors & IAnchorConstants.WEST) > 0))
{
cssProperties.setProperty("min-width", size.width + "px");
}
if (((anchors & IAnchorConstants.NORTH) > 0) && ((anchors & IAnchorConstants.SOUTH) > 0) && size != null)
{
cssProperties.setProperty("min-height", size.height + "px");
}
}
}
}