/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.jsf.vpe.richfaces.template; import static org.jboss.tools.vpe.xulrunner.util.XPCOM.queryInterface; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jboss.tools.jsf.vpe.richfaces.ComponentUtil; import org.jboss.tools.vpe.editor.VpeVisualDomBuilder; import org.jboss.tools.vpe.editor.context.VpePageContext; import org.jboss.tools.vpe.editor.template.VpeAbstractTemplate; import org.jboss.tools.vpe.editor.template.VpeChildrenInfo; import org.jboss.tools.vpe.editor.template.VpeCreationData; import org.jboss.tools.vpe.editor.template.VpeToggableTemplate; import org.jboss.tools.vpe.editor.util.Constants; import org.jboss.tools.vpe.editor.util.HTML; import org.mozilla.interfaces.nsIDOMDocument; import org.mozilla.interfaces.nsIDOMElement; import org.mozilla.interfaces.nsIDOMNode; import org.mozilla.xpcom.XPCOMException; import org.w3c.dom.Element; import org.w3c.dom.Node; public class RichFacesTabPanelTemplate extends VpeAbstractTemplate implements VpeToggableTemplate { public static final String CSS_PANEL = "rich-tabpanel"; //$NON-NLS-1$ public static final String CSS_CONTENT = "rich-tabpanel-content"; //$NON-NLS-1$ public static final String CSS_CONTENT_POSITION = "rich-tabpanel-content-position"; //$NON-NLS-1$ public static final String CSS_SIDE_BORDER = "rich-tabhdr-side-border"; //$NON-NLS-1$ public static final String CSS_SIDE_CELL = "rich-tabhdr-side-cell"; //$NON-NLS-1$ public static final String CSS_CELL_ACTIVE = "rich-tabhdr-cell-active"; //$NON-NLS-1$ public static final String CSS_CELL_INACTIVE = "rich-tabhdr-cell-inactive"; //$NON-NLS-1$ public static final String CSS_CELL_DISABLED = "rich-tabhdr-cell-disabled"; //$NON-NLS-1$ private static final String RICH_FACES_TAB_PANEL = "richFacesTabPanel"; //$NON-NLS-1$ private static final String CSS_FILE_PATH = "tabPanel/tabPanel.css"; //$NON-NLS-1$ private static final String SPACER_FILE_PATH = "common/spacer.gif"; //$NON-NLS-1$ private static final String INCLUDE_TAG = ":include"; //$NON-NLS-1$ private static final String YES = "yes"; //$NON-NLS-1$ private final String HEADER_ALINGMENT = "headerAlignment"; //$NON-NLS-1$ private final String HEADER_SPACING = "headerSpacing"; //$NON-NLS-1$ private final String SELECTED_TAB = "selectedTab"; //$NON-NLS-1$ private final String DIR = "dir"; //$NON-NLS-1$ private final String DIR_RTL = "RTL"; //$NON-NLS-1$ private final String DIR_LTR = "LTR"; //$NON-NLS-1$ private final String HEADER_CLASS = "headerClass"; //$NON-NLS-1$ private final String CONTENT_CLASS = "contentClass"; //$NON-NLS-1$ private final String CONTENT_STYLE = "contentStyle"; //$NON-NLS-1$ private final String TAB_CLASS = "tabClass"; //$NON-NLS-1$ private final String ACTIVE_TAB_CLASS = "activeTabClass"; //$NON-NLS-1$ private final String INACTIVE_TAB_CLASS = "inactiveTabClass"; //$NON-NLS-1$ private final String DISABLED_TAB_CLASS = "disabledTabClass"; //$NON-NLS-1$ private final String ZERO = "0"; //$NON-NLS-1$ private final String ONE = "1"; //$NON-NLS-1$ private final String TWO = "2"; //$NON-NLS-1$ private final String SPACE = " "; //$NON-NLS-1$ private final String EMPTY = ""; //$NON-NLS-1$ private final String TAB = ":tab"; //$NON-NLS-1$ private final String NAME = "name"; //$NON-NLS-1$ private List<nsIDOMElement> storedTabHeaders = new ArrayList<nsIDOMElement>(); private static Map toggleMap = new HashMap(); public VpeCreationData create(VpePageContext pageContext, Node sourceNode, nsIDOMDocument visualDocument) { Element sourceElement = (Element)sourceNode; nsIDOMElement table = visualDocument.createElement(HTML.TAG_TABLE); VpeCreationData creationData = new VpeCreationData(table); ComponentUtil.setCSSLink(pageContext, CSS_FILE_PATH, RICH_FACES_TAB_PANEL); setDirAttr(table, sourceElement); table.setAttribute(HTML.ATTR_CLASS, ComponentUtil.getAttribute(sourceElement, RichFaces.ATTR_STYLE_CLASS) + SPACE + CSS_PANEL); table.setAttribute(HTML.ATTR_BORDER, ZERO); table.setAttribute(HTML.ATTR_CELLPADDING, ZERO); table.setAttribute(HTML.ATTR_CELLSPACING, ZERO); table.setAttribute(HTML.ATTR_STYLE, getStyle(sourceElement)); nsIDOMElement tbody = visualDocument.createElement(HTML.TAG_TBODY); table.appendChild(tbody); nsIDOMElement tr = visualDocument.createElement(HTML.TAG_TR); tbody.appendChild(tr); nsIDOMElement td = visualDocument.createElement(HTML.TAG_TD); tr.appendChild(td); td.setAttribute(HTML.ATTR_ALIGN, getHeaderAlignment(sourceElement)); td.setAttribute(HTML.ATTR_CLASS, ComponentUtil .getAttribute(sourceElement, HEADER_CLASS)); nsIDOMElement inerTable = visualDocument.createElement(HTML.TAG_TABLE); td.appendChild(inerTable); inerTable.setAttribute(HTML.ATTR_BORDER, ZERO); inerTable.setAttribute(HTML.ATTR_CELLPADDING, ZERO); inerTable.setAttribute(HTML.ATTR_CELLSPACING, ZERO); // Encode header nsIDOMElement inerTr = visualDocument.createElement(HTML.TAG_TR); inerTable.appendChild(inerTr); nsIDOMElement inerTd = visualDocument.createElement(HTML.TAG_TD); inerTr.appendChild(inerTd); nsIDOMElement img = visualDocument.createElement(HTML.TAG_IMG); inerTd.appendChild(img); ComponentUtil.setImg(img, SPACER_FILE_PATH); img.setAttribute(HTML.ATTR_WIDTH, TWO); img.setAttribute(HTML.ATTR_HEIGHT, ONE); img.setAttribute(HTML.ATTR_BORDER, ZERO); List<Node> children = ComponentUtil.getChildren(sourceElement); int activeId = getActiveId(sourceElement, children); int i = 0; for (Node child : children) { boolean active = (i == activeId); if (child.getNodeName().endsWith(INCLUDE_TAG)) { VpeChildrenInfo vpeChildrenInfo = new VpeChildrenInfo(inerTr); creationData.addChildrenInfo(vpeChildrenInfo); vpeChildrenInfo.addSourceChild(child); } if(child.getNodeName().endsWith(TAB)) { String headerSpacing = sourceElement.hasAttribute(HEADER_SPACING) ? sourceElement.getAttribute(HEADER_SPACING) : ONE; /* * Adds spacer before first tab */ if (i == 0) { addSpacer(visualDocument, inerTr, headerSpacing); } nsIDOMElement headerTd = RichFacesTabTemplate.encodeHeader( pageContext, creationData, (Element) child, visualDocument, inerTr, active, ComponentUtil.getAttribute(sourceElement, TAB_CLASS), (ComponentUtil.getAttribute(sourceElement, ACTIVE_TAB_CLASS) + SPACE + CSS_CELL_ACTIVE).trim(), (ComponentUtil.getAttribute(sourceElement, INACTIVE_TAB_CLASS) + SPACE + CSS_CELL_INACTIVE).trim(), (ComponentUtil.getAttribute(sourceElement, DISABLED_TAB_CLASS) + SPACE + CSS_CELL_DISABLED).trim(), String.valueOf(i)); i++; addSpacer(visualDocument, inerTr, headerSpacing); storedTabHeaders.add(headerTd); } } inerTd = visualDocument.createElement(HTML.TAG_TD); inerTr.appendChild(inerTd); img = visualDocument.createElement(HTML.TAG_IMG); inerTd.appendChild(img); ComponentUtil.setImg(img, SPACER_FILE_PATH); img.setAttribute(HTML.ATTR_WIDTH, ONE); img.setAttribute(HTML.ATTR_HEIGHT, ONE); img.setAttribute(HTML.ATTR_BORDER, ZERO); // Encode first child tab inerTr = visualDocument.createElement(HTML.TAG_TR); tbody.appendChild(inerTr); children = ComponentUtil.getChildren(sourceElement); i = 0; for (Node child : children) { boolean active = (i == activeId); if(child.getNodeName().endsWith(TAB)) { i++; if (active) { RichFacesTabTemplate.encodeBody(pageContext, creationData, (Element) child, visualDocument, inerTr, true, ComponentUtil.getAttribute(sourceElement, CONTENT_CLASS) + SPACE + CSS_PANEL + SPACE + CSS_CONTENT + SPACE + CSS_CONTENT_POSITION, ComponentUtil.getAttribute(sourceElement, CONTENT_STYLE)); break; } } } return creationData; } /** * Adds the spacer. * Add <td><img src="#{spacer}" height="1" alt="" border="0" style="#{this:encodeHeaderSpacing(context, component)}"/></td> * * @param visualDocument the visual document * @param parentTr the parent tr * @param headerSpacing the header spacing */ private void addSpacer(nsIDOMDocument visualDocument, nsIDOMElement parentTr, String headerSpacing) { nsIDOMElement spaceTd = visualDocument.createElement(HTML.TAG_TD); parentTr.appendChild(spaceTd); nsIDOMElement spaceImg = visualDocument.createElement(HTML.TAG_IMG); spaceTd.appendChild(spaceImg); ComponentUtil.setImg(spaceImg, SPACER_FILE_PATH); spaceImg.setAttribute(HTML.ATTR_HEIGHT, ONE); spaceImg.setAttribute(HTML.ATTR_BORDER, ZERO); spaceImg.setAttribute(HTML.ATTR_STYLE, "width: " + headerSpacing + Constants.PIXEL); //$NON-NLS-1$ } private int getActiveId(Element sourceElement, List<Node> children) { int activeId = -1; try { activeId = Integer.valueOf((String)toggleMap.get(sourceElement)); } catch (NumberFormatException nfe) { activeId = -1; } if (activeId == -1) { if (sourceElement.hasAttribute(SELECTED_TAB)) { activeId = getTabId(children, sourceElement.getAttribute(SELECTED_TAB)); } } if (activeId == -1) activeId = 0; int count = getChildrenCount(children); if (count - 1 < activeId) { activeId = count - 1; } return activeId; } private int getChildrenCount(List<Node> children) { int count = 0; for (Node child : children) { if (child.getNodeName().endsWith(TAB)) { count++; } } return count; } private int getTabId(List<Node> children, String tabName) { int count = 0; for (Node child : children) { if (child.getNodeName().endsWith(TAB)) { if (!(child instanceof Element)) continue; String name = ((Element)child).getAttribute(NAME); if (tabName.equals(name)) return count; count++; } } return -1; } private String getStyle(Element sourceElement) { String styleAttrValue = sourceElement.getAttribute(HTML.ATTR_STYLE); String style = sourceElement.hasAttribute(HTML.ATTR_STYLE) ? styleAttrValue : EMPTY; if (!ComponentUtil.parameterPresent(styleAttrValue, HTML.ATTR_WIDTH)) { String width = sourceElement.hasAttribute(HTML.ATTR_WIDTH) ? sourceElement.getAttribute(HTML.ATTR_WIDTH) : "100%"; //$NON-NLS-1$ style = ComponentUtil.addParameter(style, "width:" + width); //$NON-NLS-1$ } if (!ComponentUtil.parameterPresent(styleAttrValue, HTML.ATTR_HEIGHT)) { String height = sourceElement.hasAttribute(HTML.ATTR_HEIGHT) ? sourceElement.getAttribute(HTML.ATTR_HEIGHT) : EMPTY; if (height.length() > 0) { style =ComponentUtil.addParameter(style, "height:" + height); //$NON-NLS-1$ } } return style; } /** * Sets the dir attribute to the element. * * @param element the element * @param dir the dir value */ private void setDirAttr(nsIDOMElement element, Element sourceElement) { String dir = ComponentUtil.getAttribute(sourceElement, DIR); if ((null != dir) && (!EMPTY.equals(dir))){ if ((DIR_LTR.equalsIgnoreCase(dir)) || (DIR_RTL.equalsIgnoreCase(dir))) { element.setAttribute(DIR, dir); } } } private String getHeaderAlignment(Element sourceElement) { return sourceElement.hasAttribute(HEADER_ALINGMENT) ? sourceElement.getAttribute(HEADER_ALINGMENT) : HTML.VALUE_ALIGN_LEFT; } public void toggle(VpeVisualDomBuilder builder, Node sourceNode, String toggleId) { toggleMap.put(sourceNode, toggleId); } public void stopToggling(Node sourceNode) { toggleMap.remove(sourceNode); } /* (non-Javadoc) * @see org.jboss.tools.vpe.editor.template.VpeAbstractTemplate#isRecreateAtAttrChange(org.jboss.tools.vpe.editor.context.VpePageContext, org.w3c.dom.Element, org.mozilla.interfaces.nsIDOMDocument, org.mozilla.interfaces.nsIDOMElement, java.lang.Object, java.lang.String, java.lang.String) */ @Override public boolean recreateAtAttrChange(VpePageContext pageContext, Element sourceElement, nsIDOMDocument visualDocument, nsIDOMElement visualNode, Object data, String name, String value) { return true; } /** * Is invoked after construction of all child nodes of the current visual node. * @param pageContext Contains the information on edited page. * @param sourceNode The current node of the source tree. * @param visualDocument The document of the visual tree. * @param data Object <code>VpeCreationData</code>, built by a method <code>create</code> */ public void validate(VpePageContext pageContext, Node sourceNode, nsIDOMDocument visualDocument, VpeCreationData data) { List<nsIDOMNode> elements = new ArrayList<nsIDOMNode>(); ComponentUtil.findAllElementsByName(data.getNode(), elements, HTML.TAG_TABLE); for (nsIDOMNode node : elements) { try { nsIDOMElement element = queryInterface(node, nsIDOMElement.class); if (ComponentUtil.getAttribute(element, RichFacesTabTemplate.TAB_HEADER_ATTR).equalsIgnoreCase(YES)) { element.removeAttribute(HTML.ATTR_STYLE); } if (ComponentUtil.getAttribute(element, RichFacesTabTemplate.TAB_BODY_ATTR).equalsIgnoreCase(YES)) { element.setAttribute(HTML.ATTR_STYLE, HTML.ATTR_DISPLAY + Constants.COLON + RichFacesTabTemplate.DISABLED_ELEMENT_STYLE + Constants.SEMICOLON); } } catch (XPCOMException exeption) { // Ignore } } super.validate(pageContext, sourceNode, visualDocument, data); if ((storedTabHeaders == null) || (storedTabHeaders.size() < 1)){ return; } for (nsIDOMElement tab : storedTabHeaders) { String value = tab.getAttribute(VpeVisualDomBuilder.VPE_USER_TOGGLE_ID); ComponentUtil.applyAttributeValueOnChildren( VpeVisualDomBuilder.VPE_USER_TOGGLE_ID, value,ComponentUtil.getElementChildren(tab)); ComponentUtil.applyAttributeValueOnChildren( VpeVisualDomBuilder.VPE_USER_TOGGLE_LOOKUP_PARENT, Constants.TRUE, ComponentUtil.getElementChildren(tab)); } } }