All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.webui.jsf.renderkit.html.TabSetRenderer Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at
 * https://woodstock.dev.java.net/public/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at https://woodstock.dev.java.net/public/CDDLv1.0.html.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
 */

/*
 * TabSetRenderer.java
 */
package com.sun.webui.jsf.renderkit.html;

import com.sun.faces.annotation.Renderer;
import java.util.List;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;
import com.sun.webui.jsf.util.LogUtil;
import com.sun.webui.jsf.component.Tab;
import com.sun.webui.jsf.component.TabSet;
import com.sun.webui.theme.Theme;
import com.sun.webui.jsf.theme.ThemeStyles;
import com.sun.webui.jsf.util.ThemeUtilities;
import com.sun.webui.jsf.util.ConversionUtilities;
import com.sun.webui.jsf.util.RenderingUtilities;
import javax.el.MethodExpression;

/**
 * Renders a TabSet component.
 *
 * @author  Sean Comerford
 */
@Renderer(@Renderer.Renders(componentFamily = "com.sun.webui.jsf.TabSet"))
public class TabSetRenderer extends AbstractRenderer {

    private static final String SKIP_ANCHOR_NAME = "tabSetSkipAnchor"; // NOI18N
    private static final String SELECTED_TAB_ANCHOR_NAME = "selectedTabAnchor"; // NOI18N
    private static final String EMPTY_STR = ""; // NOI18N
    private static final String SPACE = " "; // NOI18N

    /** Default constructor */
    public TabSetRenderer() {
        super();
    }

    /**
     * 

Return a flag indicating whether this Renderer is responsible * for rendering the children the component it is asked to render. * The default implementation returns false.

*/ @Override public boolean getRendersChildren() { return true; } /** *

Render the end tag for this component.

* * @param context The current FacesContext. * @param component The current TabSet component. * @param writer The current ResponseWriter. */ @Override public void renderEnd(FacesContext context, UIComponent component, ResponseWriter writer) throws IOException { // render any kids of the selected tab component now TabSet tabSet = (TabSet) component; String selectedTabId = tabSet.getSelected(); Theme theme = ThemeUtilities.getTheme(context); String lite = theme.getStyleClass(ThemeStyles.TABGROUPBOX); if (selectedTabId == null) { if (tabSet.isMini() && tabSet.isLite()) { writer.startElement("div", tabSet); //NOI18N writer.writeAttribute("class", lite, null); //NOI18N writer.endElement("div"); //NOI18N } writer.endElement("div"); //NOI18N return; } Tab selectedTab = tabSet.findChildTab(selectedTabId); if (selectedTab == null) { if (tabSet.isMini() && tabSet.isLite()) { writer.startElement("div", tabSet); //NOI18N writer.writeAttribute("class", lite, null); //NOI18N writer.endElement("div"); //NOI18N } writer.endElement("div"); //NOI18N return; } if (tabSet.isMini() && tabSet.isLite()) { writer.startElement("div", tabSet); //NOI18N writer.writeAttribute("class", lite, null); //NOI18N } while (selectedTab.getTabChildCount() > 0) { selectedTabId = selectedTab.getSelectedChildId(); if (selectedTabId == null) { selectedTabId = ((Tab) selectedTab.getChildren().get(0)).getId(); } selectedTab = (Tab) selectedTab.findComponent(selectedTabId); } int numKids = selectedTab.getChildCount(); if (numKids > 0) { // render the contentHeader facet if specified UIComponent facet = tabSet.getFacet("contentHeader"); if (facet != null) { RenderingUtilities.renderComponent(facet, context); } // render the children of the selected Tab component List kids = selectedTab.getChildren(); for (int i = 0; i < numKids; i++) { UIComponent kid = (UIComponent) kids.get(i); RenderingUtilities.renderComponent(kid, context); } facet = tabSet.getFacet("contentFooter"); if (facet != null) { RenderingUtilities.renderComponent(facet, context); } } if (tabSet.isMini() && tabSet.isLite()) { writer.endElement("div"); //NOI18N } writer.endElement("div"); //NOI18N } /** *

Encode the Tab children of this TabSet component.

* * @param context The current FacesContext * @param component The current TabSet component */ @Override public void encodeChildren(FacesContext context, UIComponent component) throws IOException { TabSet tabSet = (TabSet) component; ResponseWriter writer = context.getResponseWriter(); Theme theme = ThemeUtilities.getTheme(context); List level1 = tabSet.getChildren(); if (level1.size() < 1) { // no tab children and hence no tabset if (LogUtil.infoEnabled()) { LogUtil.info(TabSetRenderer.class, "WEBUI0005", new String[]{tabSet.getId()}); } return; } // open the initial div containing the entire tab set startTabSetDiv(context, writer, tabSet, theme); // render the a11y skip link renderSkipLink(context, tabSet, theme); // render the first level of tabs and get the 2nd level if any List level2Tabs = renderLevel(context, tabSet, writer, 1, tabSet.getChildren()); // if there are any level 2 tabs render those now if (level2Tabs != null) { List level3Tabs = renderLevel(context, tabSet, writer, 2, level2Tabs); // if there are any level 3 tabs render those now if (level3Tabs != null) { renderLevel(context, tabSet, writer, 3, level3Tabs); } } // output the bookmark for the SkipHyperlink RenderingUtilities.renderAnchor(SKIP_ANCHOR_NAME, tabSet, context); } /** * Helper function called by encodeChildren to open the TabSet div. */ private void startTabSetDiv(FacesContext context, ResponseWriter writer, TabSet tabSet, Theme theme) throws IOException { String style = tabSet.getStyle(); String styleClass = tabSet.getStyleClass(); String lite = theme.getStyleClass(ThemeStyles.TABGROUP); if (tabSet.isMini() && tabSet.isLite()) { if (styleClass != null) { styleClass = styleClass.concat(SPACE).concat(lite); } else { styleClass = lite; } } if (!tabSet.isVisible()) { String hiddenStyle = theme.getStyleClass(ThemeStyles.HIDDEN); if (styleClass == null) { styleClass = hiddenStyle; } else { styleClass = styleClass.concat(SPACE).concat(hiddenStyle); } } writer.startElement("div", tabSet); writer.writeAttribute("id", tabSet.getClientId(context), "id"); // NOI18N if (style != null) { writer.writeAttribute("style", style, null); // NOI18N } if (styleClass != null) { writer.writeAttribute("class", styleClass, null); // NOI18N } } private String[] getStyles(TabSet tabSet, Theme theme, int level) { // get the various level specific tab styles we'll need String divStyle = EMPTY_STR; String tableStyle = EMPTY_STR; String linkStyle = EMPTY_STR; String selectedTdStyle = EMPTY_STR; String selectedTextStyle = EMPTY_STR; switch (level) { case 1: // get the level 1 tab styles if (tabSet.isMini()) { divStyle = theme.getStyleClass(ThemeStyles.MINI_TAB_DIV); tableStyle = theme.getStyleClass(ThemeStyles.MINI_TAB_TABLE); linkStyle = theme.getStyleClass(ThemeStyles.MINI_TAB_LINK); selectedTdStyle = theme.getStyleClass( ThemeStyles.MINI_TAB_TABLE_SELECTED_TD); selectedTextStyle = theme.getStyleClass(ThemeStyles.MINI_TAB_SELECTED_TEXT); } else { divStyle = theme.getStyleClass(ThemeStyles.TAB1_DIV); tableStyle = theme.getStyleClass(ThemeStyles.TAB1_TABLE_NEW); linkStyle = theme.getStyleClass(ThemeStyles.TAB1_LINK); selectedTdStyle = theme.getStyleClass(ThemeStyles.TAB1_TABLE_SELECTED_TD); selectedTextStyle = theme.getStyleClass(ThemeStyles.TAB1_SELECTED_TEXT_NEW); } break; case 2: // get the level 2 tab styles divStyle = theme.getStyleClass(ThemeStyles.TAB2_DIV); tableStyle = theme.getStyleClass(ThemeStyles.TAB2_TABLE_NEW); linkStyle = theme.getStyleClass(ThemeStyles.TAB2_LINK); selectedTdStyle = theme.getStyleClass(ThemeStyles.TAB2_TABLE_SELECTED_TD); selectedTextStyle = theme.getStyleClass(ThemeStyles.TAB2_SELECTED_TEXT); break; case 3: // get the level 3 tab styles divStyle = theme.getStyleClass(ThemeStyles.TAB3_DIV); tableStyle = theme.getStyleClass(ThemeStyles.TAB3_TABLE_NEW); linkStyle = theme.getStyleClass(ThemeStyles.TAB3_LINK); selectedTdStyle = theme.getStyleClass(ThemeStyles.TAB3_TABLE_SELECTED_TD); selectedTextStyle = theme.getStyleClass(ThemeStyles.TAB3_SELECTED_TEXT); break; } String[] styles = new String[]{ divStyle, tableStyle, linkStyle, selectedTdStyle, selectedTextStyle }; return styles; } /** * Helper function called by encodeChildren to write out the a11y skip link. */ private void renderSkipLink(FacesContext context, TabSet tabSet, Theme theme) throws IOException { // need the label of currently selected tab for skip alt text Tab selectedTab = tabSet.findChildTab(tabSet.getSelected()); String[] args = new String[]{EMPTY_STR}; if (selectedTab != null) { Object obj = selectedTab.getText(); if (obj != null) { args[0] = ConversionUtilities.convertValueToString( selectedTab, obj); } } // render the skip link for a11y String toolTip = theme.getMessage("tab.skipTagAltText", args); //NOI18N String styleClass = theme.getStyleClass(ThemeStyles.SKIP_MEDIUM_GREY1); RenderingUtilities.renderSkipLink(SKIP_ANCHOR_NAME, styleClass, null, toolTip, null, tabSet, context); } private void layoutLevel(ResponseWriter writer, TabSet tabSet, String[] styles) throws IOException { writer.startElement("div", tabSet); writer.writeAttribute("class", styles[0], null); // NOI18N writer.startElement("table", tabSet); // NOI18N writer.writeAttribute("border", "0", null); // NOI18N writer.writeAttribute("cellspacing", "0", null); // NOI18N writer.writeAttribute("cellpadding", "0", null); // NOI18N writer.writeAttribute("class", styles[1], null); // NOI18N writer.writeAttribute("title", EMPTY_STR, null); // NOI18N writer.startElement("tr", tabSet); //NOI18N } /** * This method renders each of the Tab components in the given level. * * @param context The current FacesContext * @param tabSet The current TabSet component * @param writer The current ResponseWriter * @param level The level (1, 2 or 3) of the Tab set to be rendered * @param currentLevelTabs A List containing the Tab objects for the current * level */ protected List renderLevel(FacesContext context, TabSet tabSet, ResponseWriter writer, int level, List currentLevelTabs) throws IOException { int numTabs = currentLevelTabs.size(); if (numTabs == 0) { // no tabs in given level return null; } Theme theme = ThemeUtilities.getTheme(context); String[] styles = getStyles(tabSet, theme, level); String hidden = theme.getStyleClass(ThemeStyles.HIDDEN); String selectedTabId = tabSet.getSelected(); Tab currentLevelSelection = null; // need to ensure at least one tab in this level is selected boolean levelHasSelection = false; for (int i = 0; i < numTabs; i++) { try { currentLevelSelection = (Tab) currentLevelTabs.get(i); } catch (ClassCastException cce) { // not a Tab instance continue; } if (isSelected(currentLevelSelection, selectedTabId)) { // sTab is either selected or part of selection levelHasSelection = true; break; } } if (!levelHasSelection) { try { selectedTabId = ((Tab) currentLevelTabs.get(0)).getId(); tabSet.setSelected(selectedTabId); } catch (ClassCastException cce) { // gave it a shot but failed... no tab will be selected } } if (currentLevelSelection != null && (currentLevelSelection.getTabChildCount() > 0)) { // selected tab in this level has children - must adjust table style switch (level) { case 1: styles[1] = theme.getStyleClass(ThemeStyles.TAB1_TABLE2_NEW); break; case 2: styles[1] = theme.getStyleClass(ThemeStyles.TAB2_TABLE3_NEW); break; default: break; } } // open the div, table and tr element for this level of tabs layoutLevel(writer, tabSet, styles); // get the developer specified binding for action listener MethodExpression actionListenerExpression = tabSet.getActionListenerExpression(); // need a variable to save next level of tabs if we have one List nextLevelToRender = null; // render each tab in this level for (int i = 0; i < numTabs; i++) { Tab tab = null; try { tab = (Tab) currentLevelTabs.get(i); } catch (ClassCastException cce) { // expected if a child of current Tab is not another Tab continue; } if (!tab.isRendered()) { continue; } // each tab goes in its own table cell writer.startElement("td", tabSet); String newSelectedClass = styles[3]; String newNonSelectedClass = null; if (!tab.isVisible()) { newSelectedClass = newSelectedClass.concat(SPACE).concat(hidden); newNonSelectedClass = hidden; } if (selectedTabId != null && isSelected(tab, selectedTabId)) { // this tab or one of it's children is selected nextLevelToRender = renderSelectedTab(context, writer, theme, tabSet, tab, styles, newSelectedClass); } else { // not part of current selection tab.setStyleClass(styles[2]); RenderingUtilities.renderComponent(tab, context); } writer.endElement("td"); } writer.endElement("tr"); writer.endElement("table"); writer.endElement("div"); return nextLevelToRender; } private List renderSelectedTab(FacesContext context, ResponseWriter writer, Theme theme, TabSet tabSet, Tab tab, String[] styles, String selectedClass) throws IOException { UIComponent parent = tab.getParent(); if (parent != null && parent instanceof Tab) { if (tabSet.isLastSelectedChildSaved()) { // ensure that the parent tab knows this one is selected ((Tab) parent).setSelectedChildId(tab.getId()); } else { // forget last selected child ((Tab) parent).setSelectedChildId(null); } } String label = EMPTY_STR; Object obj = tab.getText(); if (obj != null) { label = ConversionUtilities.convertValueToString(tab, obj); } String selectionDivClass = styles[4]; if (label.length() < 6) { // short label, apply TabPad style class to div enclosing selection String padClass = theme.getStyleClass(ThemeStyles.TAB_PADDING); selectionDivClass = selectionDivClass.concat(SPACE).concat(padClass); } writer.writeAttribute("class", selectedClass, null); // NOI18N writer.startElement("div", tab); //NOI18N writer.writeAttribute("class", selectionDivClass, null); // NOI18N String titleString = theme.getMessage( "tabSet.selectedTab", new Object[]{label}); //NOI18N writer.writeAttribute("title", titleString, null); //NOI18N // Write a named anchor for the selected tab, so that focus will return to // the current tab after it is selected. In that way tab focus will next // shift to the first input component that is a child of the selected tab. writer.startElement("a", tab); //NOI18N writer.writeAttribute("id", tab.getClientId(context), "id"); // NOI18N writer.writeAttribute("name", SELECTED_TAB_ANCHOR_NAME, "name"); // NOI18N writer.endElement("a"); //NOI18N // just write the label of the selected tab writer.write(label); writer.endElement("div"); //NOI18N // return any children of the selected tab to render as next level return tab.getTabChildCount() == 0 ? null : tab.getTabChildren(); } /** * Utility method that determines if the given Tab component or any one * of its descendants is the selected tab. * * @param tab The Tab component to check for selection * @param selectedTabId The id of the currently selected Tab */ protected boolean isSelected(Tab tab, String selectedTabId) { if (selectedTabId == null) { return false; } if (selectedTabId.equals(tab.getId())) { return true; } if (tab.getTabChildCount() == 0) { return false; } for (Tab child : tab.getTabChildren()) { if (isSelected(child, selectedTabId)) { return true; } } return false; } @Override public void decode(FacesContext context, UIComponent component) { // TabSet does not encode or decode its input value. The input // value is determined by the selected and/or current child // tab component. } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy