/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 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; import java.awt.Dimension; import java.awt.Rectangle; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.SortedSet; import org.apache.wicket.Component; import com.servoy.j2db.persistence.Part; import com.servoy.j2db.server.headlessclient.dataui.WebDataButton; import com.servoy.j2db.server.headlessclient.dataui.WebDataHtmlArea; import com.servoy.j2db.server.headlessclient.dataui.WebDataImgMediaField.ImageDisplay; import com.servoy.j2db.server.headlessclient.dataui.WebDataLabel; import com.servoy.j2db.server.headlessclient.dataui.WebDataSubmitLink; import com.servoy.j2db.server.headlessclient.dataui.WebScriptButton; import com.servoy.j2db.server.headlessclient.dataui.WebScriptLabel; import com.servoy.j2db.server.headlessclient.dataui.WebScriptSubmitLink; import com.servoy.j2db.server.headlessclient.dataui.WebTabPanel; import com.servoy.j2db.util.PersistHelper; import com.servoy.j2db.util.UUID; import com.servoy.j2db.util.Utils; /** * Holds the anchoring informations for one form. These informations are sent to web clients * and then used on client side. * * @author acostache, gerzse */ public final class FormAnchorInfo implements Comparable<FormAnchorInfo> { public String formName; public Dimension formSize; public UUID formID; public String navigatorWebId; public boolean isTableView; public boolean isTopLevelForm; public boolean isTopLevelNavigator; public String bodyContainerId; private Map<String, FormPartAnchorInfo> parts; private static final String BODY_PART_VAR = "bodyPart"; //$NON-NLS-1$ private static final String NON_BODY_PARTS_VAR = "nonBodyParts"; //$NON-NLS-1$ private static final String NON_BODY_PARTS_IDS_VAR = "nonBodyPartsIds"; //$NON-NLS-1$ private static final String ANCHOR_INFO_VAR = "ai"; //$NON-NLS-1$ private static final String HEIGHTS_VAR = "heights"; //$NON-NLS-1$ private static final String FORM_VAR = "f"; //$NON-NLS-1$ public FormAnchorInfo(String name, Dimension size, UUID id) { formName = name; formSize = size; formID = id; } public FormPartAnchorInfo addPart(String partName, String webID, int height) { if (parts == null) parts = new HashMap<String, FormPartAnchorInfo>(); FormPartAnchorInfo newPart = new FormPartAnchorInfo(partName, webID, height); parts.put(partName, newPart); return newPart; } public FormPartAnchorInfo getPart(String partName) { if (parts.containsKey(partName)) return parts.get(partName); else return null; } private void generateAnchoringCode(StringBuffer sb) { if (parts != null) { sb.append("\n"); sb.append("\t").append(FORM_VAR).append(" = {};\n"); sb.append("\t").append(FORM_VAR).append(".formName = '").append(formName).append("';\n"); if (isTopLevelForm) sb.append("\t").append(FORM_VAR).append(".isTopLevelForm = ").append(isTopLevelForm).append(";\n"); if (isTopLevelNavigator) sb.append("\t").append(FORM_VAR).append(".isTopLevelNavigator = ").append(isTopLevelNavigator).append(";\n"); sb.append("\t").append(FORM_VAR).append(".isTableView = ").append(isTableView).append(";\n"); sb.append("\t").append(FORM_VAR).append(".width = ").append(formSize.width).append(";\n"); sb.append("\t").append(FORM_VAR).append(".height = ").append(formSize.height).append(";\n"); sb.append("\t").append(FORM_VAR).append(".bodyContainerId = '").append(bodyContainerId).append("';\n"); sb.append("\t").append(FORM_VAR).append(".").append(NON_BODY_PARTS_VAR).append(" = {};\n"); sb.append("\t").append(FORM_VAR).append(".").append(NON_BODY_PARTS_IDS_VAR).append(" = {};\n"); sb.append("\t").append(FORM_VAR).append(".").append(BODY_PART_VAR).append(" = undefined;\n"); sb.append("\t").append(FORM_VAR).append(".").append(HEIGHTS_VAR).append(" = {};\n"); String bodyPartWebId = null; for (String key : parts.keySet()) { FormPartAnchorInfo part = parts.get(key); part.generateAnchoringCode(sb); if (Part.getDisplayName(Part.BODY).equals(part.partName)) bodyPartWebId = part.webID; } sb.append("\t").append(FORM_VAR).append(".bodyPartId = '").append(bodyPartWebId).append("';\n"); sb.append("\t").append(FORM_VAR).append(".navigatorId = "); if (navigatorWebId == null) sb.append("undefined"); else sb.append("'").append(navigatorWebId).append("'"); sb.append(";\n"); sb.append("\tdesigninfo['").append(formName).append("']=").append(FORM_VAR).append(";\n"); } } public static String generateAnchoringFunctions(SortedSet<FormAnchorInfo> formAnchorInfos, String orientation) { StringBuffer sb = new StringBuffer(); sb.append("getOrientation = function()\n"); sb.append("{\n"); sb.append("\treturn '").append(orientation.toLowerCase()).append("';\n"); sb.append("}\n"); sb.append("\n"); sb.append("getAnchoredFormsInfo = function()\n"); sb.append("{\n"); sb.append("\tvar ").append(ANCHOR_INFO_VAR).append(";\n"); sb.append("\tvar ").append(FORM_VAR).append(";\n"); sb.append("\tvar designinfo = {};\n"); Iterator<FormAnchorInfo> fit = formAnchorInfos.iterator(); while (fit.hasNext()) { FormAnchorInfo fai = fit.next(); fai.generateAnchoringCode(sb); } sb.append("\n\treturn designinfo;\n"); sb.append("}\n"); return sb.toString(); } public static String generateAnchoringParams(SortedSet<FormAnchorInfo> formAnchorInfos, Component component) { Iterator<FormAnchorInfo> it = formAnchorInfos.iterator(); FormAnchorInfo fai; String webId = component.getMarkupId(); while (it.hasNext()) { fai = it.next(); if (fai.parts != null) { for (FormPartAnchorInfo p : fai.parts.values()) { if (p.elementAnchorInfo != null && p.elementAnchorInfo.containsKey(webId)) { // found it StringBuffer sb = new StringBuffer(); p.appendElementAnchoringCode(webId, p.elementAnchorInfo.get(webId), sb); return sb.toString(); } } } } return null; } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof FormAnchorInfo) { FormAnchorInfo fai = (FormAnchorInfo)obj; return Utils.equalObjects(fai.formID, formID) && Utils.equalObjects(fai.formName, formName) && Utils.equalObjects(fai.formSize, formSize) && Utils.equalObjects(fai.bodyContainerId, bodyContainerId) && Utils.equalObjects(fai.navigatorWebId, navigatorWebId) && Utils.equalObjects(fai.parts, parts) && fai.isTableView == isTableView && fai.isTopLevelForm == isTopLevelForm && fai.isTopLevelNavigator == isTopLevelNavigator; } return false; } public void clear() { if (parts != null) parts.clear(); } @Override public String toString() { StringBuffer sb = new StringBuffer("\n[FormAnchorInfo:\n"); sb.append("\tform name=").append(formName).append("\n"); sb.append("\tform size=").append(formSize).append("\n"); sb.append("\tform id=").append(formID).append("\n"); if (parts == null) sb.append("\tnull anchor info\n"); else { sb.append("\tparts count=").append(parts.size()).append("\n"); for (String key : parts.keySet()) { FormPartAnchorInfo val = parts.get(key); sb.append("\t\t").append(key).append(": ").append(val.toString()).append("\n"); } } sb.append("]\n"); return sb.toString(); } public int compareTo(FormAnchorInfo o) { int nameCompare = this.formName.compareTo(o.formName); if (nameCompare != 0) return nameCompare; return (this.formID.equals(o.formID) ? (this.equals(o) ? nameCompare : 1) : this.formID.compareTo(o.formID)); } /** * Holds anchoring info for one element. */ public final class ElementAnchorInfo { private final String webID; private final int anchors; private final Rectangle bounds; private final int hAlign; private final int vAlign; private final String hint; private final String imageURL; private final boolean appendRandomParamToImageUrl; public ElementAnchorInfo(String webID, int anchors, Rectangle bounds, int hAlign, int vAlign, String hint, String imageURL, boolean appendRandomParamToImageUrl) { this.webID = webID; this.anchors = anchors; this.bounds = bounds; this.hAlign = hAlign; this.vAlign = vAlign; this.hint = hint; this.imageURL = imageURL; this.appendRandomParamToImageUrl = appendRandomParamToImageUrl; } public String getWebID() { return webID; } public int getAnchors() { return anchors; } public Rectangle getBounds() { return bounds; } public int getHorizontalAlign() { return hAlign; } public int getVerticalAlign() { return vAlign; } public String getHint() { return hint; } public String getImageUrl() { return (appendRandomParamToImageUrl && imageURL != null) ? imageURL + "&r=" + Math.random() : imageURL; //$NON-NLS-1$ } @Override public boolean equals(Object other) { if (other instanceof ElementAnchorInfo) { ElementAnchorInfo eai = (ElementAnchorInfo)other; return Utils.equalObjects(this.bounds, eai.bounds) && Utils.equalObjects(this.hint, eai.hint) && Utils.equalObjects(this.webID, eai.webID) && (this.anchors == eai.anchors) && (this.hAlign == eai.hAlign) && (this.vAlign == eai.vAlign) && Utils.equalObjects(this.imageURL, eai.imageURL); } return false; } } /** * Holds anchoring info for all elements inside a form part (header/body/footer/etc.). */ public final class FormPartAnchorInfo { private final String partName; private final String webID; private final int height; public FormPartAnchorInfo(String partName, String webID, int height) { this.partName = partName; this.webID = webID; this.height = height; } public Map<String, ElementAnchorInfo> elementAnchorInfo; public void addAnchoredElement(String webID, int anchors, Rectangle rectangle, int hAlign, int vAlign, Class hintClass, String imageUrl, boolean appendRandomParamToImageUrl) { if (elementAnchorInfo == null) elementAnchorInfo = new HashMap<String, ElementAnchorInfo>(); String hint = null; if (WebTabPanel.class.equals(hintClass)) { hint = "TabPanel"; //$NON-NLS-1$ } else if (WebDataLabel.class.equals(hintClass) || WebScriptLabel.class.equals(hintClass) || WebDataSubmitLink.class.equals(hintClass) || WebScriptSubmitLink.class.equals(hintClass)) { hint = "Label"; //$NON-NLS-1$ } else if (WebDataButton.class.equals(hintClass) || WebScriptButton.class.equals(hintClass)) { hint = "Button"; //$NON-NLS-1$ } else if (ImageDisplay.class.equals(hintClass)) { hint = "ImgField"; //$NON-NLS-1$ } else if (WebDataHtmlArea.class.equals(hintClass)) { hint = "HTMLArea"; //$NON-NLS-1$ } ElementAnchorInfo elementInfo = new ElementAnchorInfo(webID, anchors, rectangle, hAlign, vAlign, hint, imageUrl, appendRandomParamToImageUrl); elementAnchorInfo.put(webID, elementInfo); } public void generateAnchoringCode(StringBuffer sb) { if (elementAnchorInfo != null) { sb.append("\t").append(ANCHOR_INFO_VAR).append(" = new Array();\n"); Iterator<Map.Entry<String, ElementAnchorInfo>> eit = elementAnchorInfo.entrySet().iterator(); int anchorInfoIdx = 0; while (eit.hasNext()) { Map.Entry<String, ElementAnchorInfo> entry = eit.next(); sb.append("\t").append(ANCHOR_INFO_VAR).append(".push("); appendElementAnchoringCode(entry.getKey(), entry.getValue(), sb); sb.append(");"); sb.append("\n"); } sb.append("\t").append(FORM_VAR).append("."); if (!Part.getDisplayName(Part.BODY).equals(partName)) { sb.append(NON_BODY_PARTS_VAR).append("['").append(webID).append("']"); } else { sb.append(BODY_PART_VAR); } sb.append(" = ").append(ANCHOR_INFO_VAR).append(";\n"); sb.append("\t").append(FORM_VAR).append(".").append(HEIGHTS_VAR).append("['").append(webID).append("'] = ").append(height).append(";\n"); } if (!Part.getDisplayName(Part.BODY).equals(partName)) { sb.append("\t").append(FORM_VAR).append("."); sb.append(NON_BODY_PARTS_IDS_VAR).append("['").append(webID).append("']"); sb.append(" = true;\n"); } } private void appendElementAnchoringCode(String webId, ElementAnchorInfo ei, StringBuffer sb) { sb.append("new Array('").append(webId).append("', "); sb.append(ei.getAnchors()); sb.append(","); sb.append(PersistHelper.createRectangleString(ei.getBounds())); sb.append(","); sb.append("'").append(ei.getHint()).append("'"); sb.append(","); sb.append(ei.getHorizontalAlign()); sb.append(","); sb.append(ei.getVerticalAlign()); if (ei.getImageUrl() != null) { sb.append(",'"); sb.append(ei.getImageUrl()); sb.append("'"); } sb.append(")"); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof FormPartAnchorInfo) { FormPartAnchorInfo fai = (FormPartAnchorInfo)obj; return Utils.equalObjects(fai.partName, partName) && Utils.equalObjects(fai.webID, webID) && fai.height == height && Utils.equalObjects(fai.elementAnchorInfo, elementAnchorInfo); } return false; } public void clear() { if (elementAnchorInfo != null) elementAnchorInfo.clear(); } @Override public String toString() { StringBuffer sb = new StringBuffer("\n\t\t\t[FormPartAnchorInfo:\n"); sb.append("\t\t\t\tpart name=").append(partName).append("\n"); sb.append("\t\t\t\tweb ID=").append(webID).append("\n"); if (elementAnchorInfo == null) sb.append("\t\t\t\tnull anchor info\n"); else { sb.append("\t\t\t\tanchor info count=").append(elementAnchorInfo.size()).append("\n"); for (String key : elementAnchorInfo.keySet()) { ElementAnchorInfo val = elementAnchorInfo.get(key); sb.append("\t\t\t\t\t").append(key).append(": <").append(val.getAnchors()).append(",").append(val.getBounds()).append(">\n"); } } sb.append("\t\t\t]\n"); return sb.toString(); } } }