| /** |
| * 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.apache.trinidad.tagsupport.Messages; |
| import org.eclipse.jst.jsf.apache.trinidad.tagsupport.TrinidadUtils; |
| import org.eclipse.jst.pagedesigner.converter.ConvertPosition; |
| import org.eclipse.jst.pagedesigner.dtmanager.converter.ITransformOperation; |
| import org.eclipse.jst.pagedesigner.dtmanager.converter.operations.TransformOperationFactory; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| |
| /** |
| * ITransformOperation implementation specifically for the "panelTabbed" 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 PanelTabbedOperation extends AbstractTrinidadTransformOperation { |
| |
| private static final int SEP_POS_BETWEEN = -1; |
| private static final int SEP_POS_START = 0; |
| private static final int SEP_POS_END = 1; |
| |
| private static final String STYLECLASS_TABLE_ABOVE = "af_panelTabbed_orientation-top"; //$NON-NLS-1$ |
| private static final String STYLECLASS_TABLE_BELOW = "af_panelTabbed_orientation-bottom"; //$NON-NLS-1$ |
| private static final String STYLECLASS_SEPARATOR_START = "af_panelTabbed_cell-start"; //$NON-NLS-1$ |
| private static final String STYLECLASS_SEPARATOR_END = "af_panelTabbed_cell-end"; //$NON-NLS-1$ |
| private static final String STYLECLASS_CELL = "af_panelTabbed_tab-selected"; //$NON-NLS-1$ |
| private static final String STYLECLASS_CELL_NOTDISCLOSED_OR_DISABLED = "af_panelTabbed_tab"; //$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) { |
| //create outer span element and set style and class attributes |
| Element spanElement = createElement("span"); //$NON-NLS-1$ |
| ITransformOperation operation = |
| TransformOperationFactory.getInstance().getTransformOperation( |
| TransformOperationFactory.OP_CopyAttributeWithRenameOperation, |
| new String[]{"styleClass", "class"}); //$NON-NLS-1$ //$NON-NLS-2$ |
| operation.transform(srcElement, spanElement); |
| operation = |
| TransformOperationFactory.getInstance().getTransformOperation( |
| TransformOperationFactory.OP_CopyAttributeWithRenameOperation, |
| new String[]{"inlineStyle", "style"}); //$NON-NLS-1$ //$NON-NLS-2$ |
| operation.transform(srcElement, spanElement); |
| |
| //get child showDetailItem elements |
| @SuppressWarnings("unchecked") |
| List<Node> showDetailItems = getChildElements( |
| srcElement, "showDetailItem"); //$NON-NLS-1$ |
| if (showDetailItems.size() > 0) { |
| |
| //determine tabs position ("both", "above", or "below" - default "both") |
| String tabsPosition = srcElement.getAttribute("position"); //$NON-NLS-1$ |
| if (tabsPosition == null || |
| !(tabsPosition.equalsIgnoreCase("above") || //$NON-NLS-1$ |
| tabsPosition.equalsIgnoreCase("below"))) { //$NON-NLS-1$ |
| tabsPosition = "both"; //$NON-NLS-1$ |
| } |
| |
| //need to track where showDetailItem is in relation to "tabs" |
| int showDetailItemConvertPosition = 0; |
| |
| //write tabs "above" if specified |
| if ("above".equalsIgnoreCase(tabsPosition) || //$NON-NLS-1$ |
| "both".equalsIgnoreCase(tabsPosition)) { //$NON-NLS-1$ |
| appendTabs(srcElement, showDetailItems, spanElement, true); |
| showDetailItemConvertPosition++; |
| } |
| |
| //copy current child showDetailItem |
| int currentEditorItem = |
| getCurrentShowDetailItem(srcElement, showDetailItems); |
| int curItem = 0; |
| Iterator<Node> itItems = showDetailItems.iterator(); |
| while (itItems.hasNext()) { |
| Node nodeItem = itItems.next(); |
| if (currentEditorItem == curItem) { |
| if (nodeItem instanceof Element) { |
| Element elemItem = (Element)nodeItem; |
| tagConverterContext.addChild( |
| elemItem, |
| new ConvertPosition( |
| spanElement, |
| showDetailItemConvertPosition)); |
| break; |
| } |
| } |
| curItem++; |
| } |
| |
| //write tabs "below" if specified |
| if ("below".equalsIgnoreCase(tabsPosition) || //$NON-NLS-1$ |
| "both".equalsIgnoreCase(tabsPosition)) { //$NON-NLS-1$ |
| appendTabs(srcElement, showDetailItems, spanElement, false); |
| } |
| } else { |
| appendAttribute( |
| spanElement, |
| "style", //$NON-NLS-1$ |
| ITrinidadConstants.STYLE_EMPTYELEMENT); |
| appendChildText( |
| Messages.PanelTabbedOperation_EmptyPanelTabbedTag, |
| spanElement); |
| } |
| |
| return spanElement; |
| } |
| |
| private void appendTabs(Element srcElement, List<Node> showDetailItems, Element spanElement, boolean above) { |
| Element tableElement = appendChildElement("table", spanElement); //$NON-NLS-1$ |
| String tableStyleClass; |
| if (above) { |
| tableStyleClass = STYLECLASS_TABLE_ABOVE; |
| } else { |
| tableStyleClass = STYLECLASS_TABLE_BELOW; |
| } |
| appendAttribute(tableElement, "class", tableStyleClass); //$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$ |
| appendAttribute(tableElement, "summary", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| Element trElement = appendChildElement("tr", tableElement); //$NON-NLS-1$ |
| |
| //append first separator |
| appendSeparatorTD(trElement, SEP_POS_START); |
| |
| int currentItem = getCurrentShowDetailItem(srcElement, showDetailItems); |
| int disclosedItem = calculateDisclosedShowDetailItem(showDetailItems); |
| int curItem = 0; |
| |
| //iterate over showDetailItem elements |
| Iterator<Node> itItems = showDetailItems.iterator(); |
| while (itItems.hasNext()) { |
| Node nodeItem = itItems.next(); |
| if (nodeItem instanceof Element) { |
| Element elemItem = (Element)nodeItem; |
| appendShowDetailItemTD( |
| trElement, |
| elemItem, |
| currentItem == curItem, |
| disclosedItem == curItem); |
| if (curItem < showDetailItems.size() - 1) { |
| appendSeparatorTD(trElement); |
| } |
| curItem++; |
| } |
| } |
| |
| //append last separator |
| appendSeparatorTD(trElement, SEP_POS_END); |
| } |
| |
| private void appendSeparatorTD(Element trElement, int sepPosition) { |
| Element tdElement = appendChildElement("td", trElement); //$NON-NLS-1$ |
| if (sepPosition == SEP_POS_START) { |
| appendAttribute(tdElement, "class", STYLECLASS_SEPARATOR_START); //$NON-NLS-1$ |
| } else if (sepPosition == SEP_POS_END) { |
| appendAttribute(tdElement, "class", STYLECLASS_SEPARATOR_END); //$NON-NLS-1$ |
| } |
| Element bElement = appendChildElement("b", tdElement); //$NON-NLS-1$ |
| appendAttribute(bElement, "style", "margin-left:0px;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| private void appendSeparatorTD(Element trElement) { |
| appendSeparatorTD(trElement, SEP_POS_BETWEEN); |
| } |
| |
| private void appendShowDetailItemTD(Element trElement, Element showDetailItem, boolean isCurrent, boolean isDisclosed) { |
| boolean isDisabled = false; |
| String attrShowDetailItemDisabled = showDetailItem.getAttribute("disabled"); //$NON-NLS-1$ |
| if (Boolean.TRUE.toString().equalsIgnoreCase(attrShowDetailItemDisabled)) { |
| isDisabled = true; |
| } |
| Element tdElement = appendChildElement("td", trElement); //$NON-NLS-1$ |
| appendAttribute(tdElement, "height", "1"); //$NON-NLS-1$ //$NON-NLS-2$ |
| appendAttribute(tdElement, "nowrap", "nowrap"); //$NON-NLS-1$ //$NON-NLS-2$ |
| String tdStyleClass; |
| if (isDisclosed && !isDisabled) { |
| tdStyleClass = STYLECLASS_CELL; |
| } else { |
| tdStyleClass = STYLECLASS_CELL_NOTDISCLOSED_OR_DISABLED; |
| } |
| appendAttribute(tdElement, "class", tdStyleClass); //$NON-NLS-1$ |
| Element aElement = appendChildElement("a", tdElement); //$NON-NLS-1$ |
| String aStyle; |
| if (isDisabled) { |
| appendAttribute(aElement, "name", "name"); //$NON-NLS-1$ //$NON-NLS-2$ |
| aStyle = "color:#999999;"; //$NON-NLS-1$ |
| } else { |
| appendAttribute(aElement, "href", "#"); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (isDisclosed) { |
| aStyle = "color:#669966;text-decoration:none;"; //$NON-NLS-1$ |
| } else { |
| aStyle = "color:#003333;"; //$NON-NLS-1$ |
| } |
| } |
| if (isCurrent) { |
| aStyle += "border:1px solid #99cc99;padding:2px;"; //$NON-NLS-1$ |
| } |
| String attrShowDetailItemInlineStyle = showDetailItem.getAttribute("inlineStyle"); //$NON-NLS-1$ |
| if (attrShowDetailItemInlineStyle != null && |
| attrShowDetailItemInlineStyle.length() > 0) { |
| aStyle += attrShowDetailItemInlineStyle; |
| } |
| if (aStyle.length() > 0) { |
| appendAttribute(aElement, "style", aStyle); //$NON-NLS-1$ |
| } |
| ITransformOperation operation = |
| TransformOperationFactory.getInstance().getTransformOperation( |
| TransformOperationFactory.OP_CopyAttributeWithRenameOperation, |
| new String[]{"styleClass", "class"}); //$NON-NLS-1$ //$NON-NLS-2$ |
| operation.transform(showDetailItem, aElement); |
| String attrShowDetailItemTextAndAccessKey = showDetailItem.getAttribute("textAndAccessKey"); //$NON-NLS-1$ |
| if (attrShowDetailItemTextAndAccessKey != null && |
| attrShowDetailItemTextAndAccessKey.length() > 0) { |
| appendChildText(attrShowDetailItemTextAndAccessKey, aElement); |
| } else { |
| String attrShowDetailItemText = showDetailItem.getAttribute("text"); //$NON-NLS-1$ |
| if (attrShowDetailItemText != null && attrShowDetailItemText.length() > 0) { |
| appendChildText(attrShowDetailItemText, aElement); |
| } |
| } |
| } |
| |
| private int getCurrentShowDetailItem( |
| Element srcElement, List<Node> showDetailItems) { |
| int disclosedItem = TrinidadUtils.getCurrentChildIndex(srcElement); |
| if (disclosedItem == -1) { |
| disclosedItem = calculateDisclosedShowDetailItem(showDetailItems); |
| TrinidadUtils.setCurrentChildIndex(srcElement, disclosedItem); |
| } |
| return disclosedItem; |
| } |
| |
| private int calculateDisclosedShowDetailItem(List<Node> showDetailItems) { |
| int disclosedItem = -1; |
| int curItem = 0; |
| Iterator<Node> itItems = showDetailItems.iterator(); |
| while (itItems.hasNext()) { |
| Node item = itItems.next(); |
| if (item instanceof Element) { |
| Element elemItem = (Element)item; |
| String attrDisclosedVal = elemItem.getAttribute("disclosed"); //$NON-NLS-1$ |
| if (Boolean.TRUE.toString().equalsIgnoreCase( |
| attrDisclosedVal)) { |
| disclosedItem = curItem; |
| break; |
| } |
| } |
| curItem++; |
| } |
| //if none explicitly disclosed, consider first non-disabled tab disclosed |
| if (disclosedItem == -1) { |
| curItem = 0; |
| itItems = showDetailItems.iterator(); |
| while (itItems.hasNext()) { |
| Node item = itItems.next(); |
| if (item instanceof Element) { |
| Element elemItem = (Element)item; |
| String attrDisabledVal = elemItem.getAttribute("disabled"); //$NON-NLS-1$ |
| if (!(Boolean.TRUE.toString().equalsIgnoreCase(attrDisabledVal))) { |
| disclosedItem = curItem; |
| break; |
| } |
| } |
| curItem++; |
| } |
| } |
| //if none explicitly disclosed and all disabled, consider first tab disclosed |
| if (disclosedItem == -1) { |
| disclosedItem = 0; |
| } |
| return disclosedItem; |
| } |
| |
| } |