blob: 761893e431d2a3245a03e7554bca36c6fb242d2d [file] [log] [blame]
/**
* Copyright (c) 2008 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oracle Corporation - initial API and implementation
*/
package org.eclipse.jst.jsf.apache.trinidad.tagsupport.converter.operations;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jst.jsf.apache.trinidad.tagsupport.ITrinidadConstants;
import org.eclipse.jst.jsf.common.dom.TagIdentifier;
import org.eclipse.jst.jsf.core.internal.tld.TagIdentifierFactory;
import org.eclipse.jst.pagedesigner.converter.ConvertPosition;
import org.w3c.dom.Element;
/**
* ITransformOperation implementation specifically for the "panelFormLayout"
* JSF Element.
*
* <br><b>Note:</b> requires ITransformOperation.setTagConverterContext(...) to
* have been called to provide a valid ITagConverterContext instance prior to
* a call to the transform(...) method.
*
* @author Ian Trimble - Oracle
*/
public class PanelFormLayoutOperation extends AbstractTrinidadTransformOperation {
private static final String STYLECLASS_REQUIREDSPAN = "AFRequiredIconStyle"; //$NON-NLS-1$
private static final String STYLECLASS_GROUPSEPARATOR = "af_panelFormLayout_separator"; //$NON-NLS-1$
private static final String STYLECLASS_LABELCELL = "af_inputText_label af_panelFormLayout_label-cell"; //$NON-NLS-1$
private static final String STYLECLASS_FIELDCELL = "af_panelFormLayout_content-cell"; //$NON-NLS-1$
/* (non-Javadoc)
* @see org.eclipse.jst.pagedesigner.dtmanager.converter.operations.AbstractTransformOperation#transform(org.w3c.dom.Element, org.w3c.dom.Element)
*/
@Override
public Element transform(Element srcElement, Element curElement) {
//calculate required values
int columnCount = calculateColumnCount(srcElement);
int rowCount = calculateRowCount(srcElement);
String fieldWidth = calculateFieldWidth(srcElement);
String labelWidth = calculateLabelWidth(srcElement);
//initialize current column/row variables
int currentColumn = 1;
int currentRow = 1;
//build outer table
Element outerTableElement = createElement("table"); //$NON-NLS-1$
String styleClass = srcElement.getAttribute("styleClass"); //$NON-NLS-1$
if (styleClass != null && styleClass.length() > 0) {
appendAttribute(outerTableElement, "class", styleClass); //$NON-NLS-1$
}
String inlineStyle = srcElement.getAttribute("inlineStyle"); //$NON-NLS-1$
if (inlineStyle != null && inlineStyle.length() > 0) {
appendAttribute(outerTableElement, "style", inlineStyle + ";width:100%;"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
appendAttribute(outerTableElement, "style", "width:100%;"); //$NON-NLS-1$ //$NON-NLS-2$
}
appendAttribute(outerTableElement, "cellpadding", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(outerTableElement, "cellspacing", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(outerTableElement, "border", "0"); //$NON-NLS-1$ //$NON-NLS-2$
Element outerTBodyElement = appendChildElement("tbody", outerTableElement); //$NON-NLS-1$
Element outerTopTRElement = appendChildElement("tr", outerTBodyElement); //$NON-NLS-1$
//build start of column
Element currentTBodyElement = buildColumnStart(outerTopTRElement, columnCount, currentColumn, labelWidth, fieldWidth);
//build controls
List<Element> childElements = getChildElementsSkipFacets(srcElement);
Iterator<Element> itChildElements = childElements.iterator();
while (itChildElements.hasNext()) {
Element childElement = itChildElements.next();
if (ITrinidadConstants.TAG_IDENTIFIER_GROUP.isSameTagType(
TagIdentifierFactory.createDocumentTagWrapper(childElement))) {
if (currentRow > 1) {
buildGroupSeparatorRow(currentTBodyElement);
}
List<Element> groupChildElements = getChildElementsSkipFacets(childElement);
Iterator<Element> itGroupChildElements = groupChildElements.iterator();
while (itGroupChildElements.hasNext()) {
Element groupChildElement = itGroupChildElements.next();
buildControlRow(groupChildElement, currentTBodyElement);
}
currentRow += groupChildElements.size();
if (currentRow <= rowCount) {
buildGroupSeparatorRow(currentTBodyElement);
}
if (currentRow > rowCount && currentColumn < columnCount) {
currentRow = 1;
currentColumn++;
currentTBodyElement = buildColumnStart(
outerTopTRElement, columnCount, currentColumn, labelWidth, fieldWidth);
}
} else {
buildControlRow(childElement, currentTBodyElement);
currentRow++;
if (currentRow > rowCount && currentColumn < columnCount) {
currentRow = 1;
currentColumn++;
currentTBodyElement = buildColumnStart(
outerTopTRElement, columnCount, currentColumn, labelWidth, fieldWidth);
}
}
}
//handle "footer" facet
Element footerElement = getChildFacetByName(srcElement, "footer"); //$NON-NLS-1$
if (footerElement != null) {
List<Element> footerChildElements = getChildElementsSkipFacets(footerElement);
if (footerChildElements.size() > 0) {
Element outerBottomTRElement = appendChildElement("tr", outerTBodyElement); //$NON-NLS-1$
currentTBodyElement = buildFooterStart(
outerBottomTRElement, columnCount, labelWidth);
rowCount = countChildElements(footerElement);
currentRow = 1;
Iterator<Element> itFooterChildElements = footerChildElements.iterator();
while (itFooterChildElements.hasNext()) {
Element footerChildElement = itFooterChildElements.next();
if (ITrinidadConstants.TAG_IDENTIFIER_GROUP.isSameTagType(
TagIdentifierFactory.createDocumentTagWrapper(footerChildElement))) {
if (currentRow > 1) {
buildGroupSeparatorRow(currentTBodyElement);
}
List<Element> groupFooterChildElements = getChildElementsSkipFacets(footerChildElement);
Iterator<Element> itGroupFooterChildElements = groupFooterChildElements.iterator();
while (itGroupFooterChildElements.hasNext()) {
Element groupFooterChildElement = itGroupFooterChildElements.next();
if (ITrinidadConstants.TAG_IDENTIFIER_GROUP.isSameTagType(
TagIdentifierFactory.createDocumentTagWrapper(groupFooterChildElement))) {
if (currentRow > 1) {
buildGroupSeparatorRow(currentTBodyElement);
}
List<Element> subGroupFooterChildElements = getChildElementsSkipFacets(groupFooterChildElement);
Iterator<Element> itSubGroupFooterChildElements = subGroupFooterChildElements.iterator();
while (itSubGroupFooterChildElements.hasNext()) {
Element subGroupFooterChildElement = itSubGroupFooterChildElements.next();
buildControlRow(subGroupFooterChildElement, currentTBodyElement, true);
currentRow++;
}
if (currentRow <= rowCount) {
buildGroupSeparatorRow(currentTBodyElement);
}
} else {
buildControlRow(groupFooterChildElement, currentTBodyElement, true);
currentRow++;
}
}
if (currentRow <= rowCount) {
buildGroupSeparatorRow(currentTBodyElement);
}
} else {
buildControlRow(footerChildElement, currentTBodyElement, true);
currentRow++;
}
}
}
}
return outerTableElement;
}
private int calculateRowCount(Element srcElement) {
int rowCount = Integer.MAX_VALUE;
int specifiedRows = Integer.MAX_VALUE;
String rows = srcElement.getAttribute("rows"); //$NON-NLS-1$
if (rows != null && rows.length() > 0) {
try {
//not spec'ed, but observed that setting rows < 5 is ignored
specifiedRows = Math.max(5, Integer.parseInt(rows));
} catch(NumberFormatException nfe) {
//ignore - specifiedRows will default to Integer.MAX_VALUE
}
}
int specifiedMaxColumns = Integer.MAX_VALUE;
String maxColumns = srcElement.getAttribute("maxColumns"); //$NON-NLS-1$
if (maxColumns != null && maxColumns.length() > 0) {
try {
specifiedMaxColumns = Integer.parseInt(maxColumns);
} catch(NumberFormatException nfe) {
//ignore - specifiedMaxColumns will default to Integer.MAX_VALUE
}
}
int childElementCount = countChildElements(srcElement);
int calculatedColumns = childElementCount / specifiedRows;
if (childElementCount % specifiedRows > 0) {
calculatedColumns++;
}
if (calculatedColumns > specifiedMaxColumns) {
rowCount = childElementCount / specifiedMaxColumns;
} else {
rowCount = specifiedRows;
}
return rowCount;
}
private int calculateColumnCount(Element srcElement) {
int columnCount = Integer.MAX_VALUE;
int specifiedRows = Integer.MAX_VALUE;
String rows = srcElement.getAttribute("rows"); //$NON-NLS-1$
if (rows != null && rows.length() > 0) {
try {
//not spec'ed, but observed that setting rows < 5 is ignored
specifiedRows = Math.max(5, Integer.parseInt(rows));
} catch(NumberFormatException nfe) {
//ignore - specifiedRows will default to Integer.MAX_VALUE
}
}
int specifiedMaxColumns = Integer.MAX_VALUE;
String maxColumns = srcElement.getAttribute("maxColumns"); //$NON-NLS-1$
if (maxColumns != null && maxColumns.length() > 0) {
try {
specifiedMaxColumns = Integer.parseInt(maxColumns);
} catch(NumberFormatException nfe) {
//ignore - specifiedMaxColumns will default to Integer.MAX_VALUE
}
}
int childElementCount = countChildElements(srcElement);
int calculatedColumns = childElementCount / specifiedRows;
if (childElementCount % specifiedRows > 0) {
calculatedColumns++;
}
columnCount = Math.min(specifiedMaxColumns, calculatedColumns);
return columnCount;
}
private int countChildElements(Element srcElement) {
int count = 0;
List<Element> childElements = getChildElementsSkipFacets(srcElement);
Iterator<Element> itChildElements = childElements.iterator();
while (itChildElements.hasNext()) {
Element childElement = itChildElements.next();
if (ITrinidadConstants.TAG_IDENTIFIER_GROUP.isSameTagType(
TagIdentifierFactory.createDocumentTagWrapper(childElement))) {
count += countChildElements(childElement);
} else {
count++;
}
}
return count;
}
private String calculateFieldWidth(Element srcElement) {
String width = null;
String fieldWidth = srcElement.getAttribute("fieldWidth"); //$NON-NLS-1$
if (fieldWidth != null && fieldWidth.length() > 0) {
width = fieldWidth;
} else {
String labelWidth = srcElement.getAttribute("labelWidth"); //$NON-NLS-1$
if (labelWidth != null && labelWidth.length() > 1) {
if (labelWidth.endsWith("%")) { //$NON-NLS-1$
try {
int iLabelWidth = Integer.parseInt(labelWidth.substring(0, labelWidth.length() - 1));
if (iLabelWidth <= 100) {
width = String.valueOf(100 - iLabelWidth) + "%"; //$NON-NLS-1$
}
} catch(NumberFormatException nfe) {
//ignore - cannot calculate and so will return null
}
}
}
}
return width;
}
private String calculateLabelWidth(Element srcElement) {
String width = null;
String labelWidth = srcElement.getAttribute("labelWidth"); //$NON-NLS-1$
if (labelWidth != null && labelWidth.length() > 0) {
width = labelWidth;
} else {
String fieldWidth = srcElement.getAttribute("fieldWidth"); //$NON-NLS-1$
if (fieldWidth != null && fieldWidth.length() > 1) {
if (fieldWidth.endsWith("%")) { //$NON-NLS-1$
try {
int iFieldWidth = Integer.parseInt(fieldWidth.substring(0, fieldWidth.length() - 1));
if (iFieldWidth <= 100) {
width = String.valueOf(100 - iFieldWidth) + "%"; //$NON-NLS-1$
}
} catch(NumberFormatException nfe) {
//ignore - cannot calculate and so will return null
}
}
}
}
return width;
}
private Element buildColumnStart(
Element parentElement, int columnCount, int currentColumn,
String labelWidth, String fieldWidth) {
Element tdElement = appendChildElement("td", parentElement); //$NON-NLS-1$
appendAttribute(tdElement, "style", "vertical-align:top;"); //$NON-NLS-1$ //$NON-NLS-2$
if (currentColumn < columnCount) {
String width = String.valueOf(100 / columnCount) + "%"; //$NON-NLS-1$
appendAttribute(tdElement, "width", width); //$NON-NLS-1$
}
Element tableElement = appendChildElement("table", tdElement); //$NON-NLS-1$
appendAttribute(tableElement, "cellpadding", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tableElement, "cellspacing", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tableElement, "border", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tableElement, "width", "100%"); //$NON-NLS-1$ //$NON-NLS-2$
Element tBodyElement = appendChildElement("tbody", tableElement); //$NON-NLS-1$
Element trElement = appendChildElement("tr", tBodyElement); //$NON-NLS-1$
Element tdLabelElement = appendChildElement("td", trElement); //$NON-NLS-1$
if (labelWidth != null && labelWidth.length() > 0) {
appendAttribute(tdLabelElement, "style", "width:" + labelWidth); //$NON-NLS-1$ //$NON-NLS-2$
}
Element tdFieldElement = appendChildElement("td", trElement); //$NON-NLS-1$
if (fieldWidth != null && fieldWidth.length() > 0) {
appendAttribute(tdFieldElement, "style", "width:" + fieldWidth); //$NON-NLS-1$ //$NON-NLS-2$
}
return tBodyElement;
}
private void buildControlRow(Element srcElement, Element parentElement, boolean alignLabelsTop) {
Element trElement = appendChildElement("tr", parentElement); //$NON-NLS-1$
Element tdLabelElement = appendChildElement("td", trElement); //$NON-NLS-1$
appendAttribute(tdLabelElement, "class", STYLECLASS_LABELCELL); //$NON-NLS-1$
if (alignLabelsTop) {
appendAttribute(tdLabelElement, "valign", "top"); //$NON-NLS-1$ //$NON-NLS-2$
}
appendAttribute(tdLabelElement, "nowrap", ""); //$NON-NLS-1$ //$NON-NLS-2$
buildLabel(srcElement, tdLabelElement);
Element tdFieldElement = appendChildElement("td", trElement); //$NON-NLS-1$
appendAttribute(tdFieldElement, "class", STYLECLASS_FIELDCELL); //$NON-NLS-1$
appendAttribute(tdFieldElement, "valign", "top"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tdFieldElement, "nowrap", ""); //$NON-NLS-1$ //$NON-NLS-2$
tagConverterContext.addChild(srcElement, new ConvertPosition(tdFieldElement, 0));
}
private void buildControlRow(Element srcElement, Element parentElement) {
buildControlRow(srcElement, parentElement, false);
}
private void buildLabel(Element srcElement, Element parentElement) {
TagIdentifier tagID = TagIdentifierFactory.createDocumentTagWrapper(srcElement);
if (
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_INPUTCOLOR) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_INPUTDATE) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_INPUTFILE) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_INPUTLISTOFVALUES) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_INPUTNUMBERSPINBOX) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_INPUTTEXT) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTBOOLEANCHECKBOX) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTBOOLEANRADIO) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTMANYCHECKBOX) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTMANYLISTBOX) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTONECHOICE) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTONELISTBOX) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_SELECTONERADIO) ||
tagID.isSameTagType(ITrinidadConstants.TAG_IDENTIFIER_PANELLABELANDMESSAGE)) {
String required = srcElement.getAttribute("required"); //$NON-NLS-1$
String showRequired = srcElement.getAttribute("showRequired"); //$NON-NLS-1$
if (Boolean.parseBoolean(required) || Boolean.parseBoolean(showRequired)) {
Element spanElement = appendChildElement("span", parentElement); //$NON-NLS-1$
appendAttribute(spanElement, "title", "Required"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(spanElement, "class", STYLECLASS_REQUIREDSPAN); //$NON-NLS-1$
appendChildText("* ", spanElement); //$NON-NLS-1$
}
String label = srcElement.getAttribute("labelAndAccessKey"); //$NON-NLS-1$
if (label == null || label.length() < 1) {
label = srcElement.getAttribute("label"); //$NON-NLS-1$
}
if (label != null && label.length() > 0) {
Element labelElement = appendChildElement("label", parentElement); //$NON-NLS-1$
appendChildText(label, labelElement);
}
}
}
private void buildGroupSeparatorRow(Element parentElement) {
Element trElement = appendChildElement("tr", parentElement); //$NON-NLS-1$
Element tdElement = appendChildElement("td", trElement); //$NON-NLS-1$
appendAttribute(tdElement, "colspan", "2"); //$NON-NLS-1$ //$NON-NLS-2$
Element divElement = appendChildElement("div", tdElement); //$NON-NLS-1$
appendAttribute(divElement, "class", STYLECLASS_GROUPSEPARATOR); //$NON-NLS-1$
}
private Element buildFooterStart(
Element parentElement, int columnCount, String labelWidth) {
Element tdElement = appendChildElement("td", parentElement); //$NON-NLS-1$
appendAttribute(tdElement, "style", "vertical-align:top;"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tdElement, "colspan", String.valueOf(columnCount)); //$NON-NLS-1$
Element tableElement = appendChildElement("table", tdElement); //$NON-NLS-1$
appendAttribute(tableElement, "cellpadding", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tableElement, "cellspacing", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tableElement, "border", "0"); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tableElement, "width", "100%"); //$NON-NLS-1$ //$NON-NLS-2$
Element tBodyElement = appendChildElement("tbody", tableElement); //$NON-NLS-1$
Element trElement = appendChildElement("tr", tBodyElement); //$NON-NLS-1$
String footerLabelWidth = null;
String footerFieldWidth = null;
if (labelWidth != null && labelWidth.length() > 0) {
if (labelWidth.endsWith("%")) { //$NON-NLS-1$
try {
int iLabelWidth = Integer.parseInt(labelWidth.substring(0, labelWidth.length() - 1));
iLabelWidth = iLabelWidth / columnCount;
footerLabelWidth = String.valueOf(iLabelWidth) + "%"; //$NON-NLS-1$
footerFieldWidth = String.valueOf(100 - iLabelWidth) + "%"; //$NON-NLS-1$
} catch(NumberFormatException nfe) {
//ignore - cannot calculate, widths remain null
}
} else {
footerLabelWidth = labelWidth;
}
}
Element tdLabelElement = appendChildElement("td", trElement); //$NON-NLS-1$
if (footerLabelWidth != null && footerLabelWidth.length() > 0) {
//appendAttribute(tdLabelElement, "style", "width:" + footerLabelWidth); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tdLabelElement, "width", footerLabelWidth); //$NON-NLS-1$
}
Element tdFieldElement = appendChildElement("td", trElement); //$NON-NLS-1$
if (footerFieldWidth != null && footerFieldWidth.length() > 0) {
//appendAttribute(tdFieldElement, "style", "width:" + footerFieldWidth); //$NON-NLS-1$ //$NON-NLS-2$
appendAttribute(tdFieldElement, "width", footerFieldWidth); //$NON-NLS-1$
}
return tBodyElement;
}
}