com.sun.webui.jsf.renderkit.html.WizardRenderer Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007-2018 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
* or LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.webui.jsf.renderkit.html;
import com.sun.faces.annotation.Renderer;
import java.io.IOException;
import java.util.Iterator;
import java.text.MessageFormat;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import com.sun.webui.jsf.component.Icon;
import com.sun.webui.jsf.component.Wizard;
import com.sun.webui.jsf.component.WizardStep;
import com.sun.webui.jsf.model.WizardStepListItem;
import com.sun.webui.theme.Theme;
import com.sun.webui.jsf.theme.ThemeStyles;
import com.sun.webui.jsf.theme.ThemeImages;
import com.sun.webui.jsf.util.JavaScriptUtilities;
import com.sun.webui.jsf.util.RenderingUtilities;
import com.sun.webui.jsf.util.ThemeUtilities;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Render a Wizard component. This renderer is responsible for rendering
* children and directly renders the current WizardStep component.
* The wizard is comprised of several layout areas:
*
* - Wizard title
* - A step list and step help pane appearing to the left of the main
* body.
* - A step title appearing To the right of the steps and help pane and
* above the main body
* - A step detail appearing below the step title.
* - The step body appearing below the step detail and to the right
* of the step list and help pane containg the elements for the current
* step.
* - Sequencing controls appearing below the main body.
*
*
* There are also some decorative rules that
* separate the different areas. Scrollbars are provided as
* determined by the size of the content in each area.
*
*
* Rendering the Wizard is abstracted into the following call
* structure. Any method can be implemented to override
* default implementation. It is important to understand the
* layout context into which the new implementation is inserting
* its markup. See the javadoc for default implementation for
* rendered markup.
*
*
* encodeBegin(..)
* renderStart(...)
* renderWizardBegin(...)
* renderSkipLink(...) // private
*
* encodeChildren(...)
* // Currently does nothing.
*
* encodeEnd(...)
* renderEnd(...)
* renderWizard(...)
*
* renderTitle(...)
* renderTitleBegin(...)
* renderTitleText(...)
* renderTitleEnd(...)
*
* renderStepsBar(..)
* renderTabsBar(...)
*
* or
*
* renderEmptyBar(..)
*
* renderStepsPane(...)
* renderStepListBegin(...)
* renderStepList(...)
* renderSubstep(...) // For each step
* renderStepNumber(...)
* renderStepSummary(...)
*
* or
*
* renderStep(...)
* renderStepNumber(...)
* renderStepSummary(...)
* or
*
* renderCurrentStep(...)
* renderCurrentStepIndicator(...)
* renderStep(...)
* renderStepNumber(...)
* renderStepSummary(...)
* or
*
* renderBranchStep(...)
* renderPlaceholderText(...)
* renderStepListEnd(...)
*
* or
*
* renderStepHelp(...)
* renderStepHelpBegin(...)
* renderStepHelpText(...)
* renderStepHelpEnd(...)
*
* renderTask(context, component, theme, writer);
* renderTaskBegin(...)
* renderSkipAnchor(...)
* renderTaskHeader(...)
* renderStepTitle(...)
* renderStepTitleBegin(...)
* renderStepTitleLabelText(...)
* renderStepTitleText(...)
* renderStepTitleEnd(...)
* renderStepDetail(...)
* renderStepDetailBegin(...)
* renderStepDetailText(...)
* renderStepDetailEnd(...)
* renderStepTask(...)
* renderStepTaskBegin(...)
* // dispatch subview
* renderStepTaskEnd(...)
* renderTaskEnd(...)
*
* renderControlBar(...)
* renderControlBarBegin(...)
* renderControlBarSpacer(...)
* renderLeftControlBar(...)
* renderLeftControlBarBegin(...)
* renderPreviousControl(...)
* renderNextControl(...)
* or
* renderFinishControl(...)
* renderLeftControlBarEnd(...)
* renderRightControlBar(...)
* renderRightControlBarBegin(...)
* renderCancelControl(...)
* or
* renderCloseControl(...)
* renderRightControlBarEnd(...)
* renderControlBarEnd(...)
*
* renderWizardEnd(context, component, theme, writer);
*
* refer to HCI wizard guidelines for details.
*/
@Renderer(@Renderer.Renders(componentFamily = "com.sun.webui.jsf.Wizard"))
public class WizardRenderer extends AbstractRenderer {
/**
* Construct a WizardRenderer
.
*/
public WizardRenderer() {
}
/**
* The WizardRenderer
is responsible for rendering the
* WizardStep
children.
*/
@Override
public boolean getRendersChildren() {
return true;
}
/**
*
A wizard can be rendered in a popup or inline within a primary
* application page.
*
*
* When the wizard is in a popup it must be closed. This is accomplished
* by rendering some javascript to close the popup and if necessary
* forwarding to another application page.
* When the wizard is not in a popup then only forwarding is performed
* if necessary.
*
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
*/
/*
protected void renderWizardClose(FacesContext context,
UIComponent component, Theme theme,
ResponseWriter writer) throws IOException {
// Assumes that the wizard javascript has been included
// and a wizard js object has been created
//
writer.startElement(SCRIPT, component);
writer.writeAttribute(TYPE, TEXT_JAVASCRIPT, null);
renderJsClose(context, component, writer);
writer.endElement(SCRIPT);
}
*/
/**
* Render javascript to close the popup window. Output javascript
* specified in the onPopupDismiss
property.
* If the property is empty render an call to the Wizard javascript
* object closePopup() function.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected String getWizardCloseJavaScript(FacesContext context,
UIComponent component) throws IOException {
String onPopupDismiss = (String) component.getAttributes().get(
ONPOPUPDISMISS);
if (onPopupDismiss == null || onPopupDismiss.length() == 0) {
Object[] args = new Object[]{
JavaScriptUtilities.getModuleName("wizard")
};
onPopupDismiss = MessageFormat.format(CLOSEPOPUPJS, args);
}
return onPopupDismiss;
}
/**
* If the component is not a Wizard
component throw
* IllegalArgumentException
otherwise begin rendering
* the component. Call the wizard component's isComplete() method to
* determine if the wizard has completed and proceed appropriately if the
* wizard was rendered in a popup or inline one browser page.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
* @throws IllegalArgumentException
*/
@Override
protected void renderStart(FacesContext context, UIComponent component,
ResponseWriter writer) throws IOException {
// Is component "isa" Wizard ?
//
if (!(component instanceof Wizard)) {
throw new IllegalArgumentException(
getMessage(MSG_COMPONENT_NOT_WIZARD));
}
Theme theme = ThemeUtilities.getTheme(context);
// Always render outer div tags for HTML element functions to be valid.
// User may need to inokve document.getElementById(id).closeAndForward(...)
renderWizardBegin(context, component, theme, writer);
}
// We can use this to indicate that all body content has beed read
// and use this point logically to set up Wizard rendering.
// It is equivalent to encodeEnd and is called immediately before.
//
// We could consider this the Wizard Body and treat Step's as
// children here.
//
/**
* Does nothing.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
*/
@Override
public void encodeChildren(FacesContext context, UIComponent component) {
/*
if (((Wizard)component).isComplete()) {
return;
}
*/
}
/**
* Render the majority of the wizard component.
* Return immediately if isComplete() returns true.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
*/
@Override
protected void renderEnd(FacesContext context, UIComponent component,
ResponseWriter writer) throws IOException {
Theme theme = ThemeUtilities.getTheme(context);
if (!((Wizard) component).isComplete()) {
renderWizard(context, component, theme, writer);
}
renderWizardEnd(context, component, theme, writer);
}
/**
* Render the beginning of the layout container for the entire Wizard.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderWizardBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
String wizId = component.getClientId(context);
// Enclose the whole wizard in a div
//
// Not in Lockhart Wizard
//
writer.startElement(DIV, component);
writer.writeAttribute(ID, wizId, ID);
String style = (String) component.getAttributes().get(STYLE);
if (style != null) {
writer.writeAttribute(STYLE, style, STYLE);
}
String styles = RenderingUtilities.getStyleClasses(context,
component, theme.getStyleClass(ThemeStyles.WIZARD));
writer.writeAttribute(CLASS, styles, null);
// Create a "skip" link that identifies the top
// of the wizard. There will be a target anchor to the
// main wizard body.
//
// Use clientId for the anchor text, so it should be
// unique if there is more than one wizard on a page.
//
String toolTip = (String) component.getAttributes().get(TOOLTIP);
if (toolTip == null) {
toolTip = theme.getMessage(WIZARD_SKIP_LINK_ALT);
}
renderSkipLink(context, component, theme, writer,
component.getClientId(context), toolTip);
}
/**
* Render the five main areas of the wizard.
*
*
* - Wizard Title
* - Wizard Steps Bar
* - Steps Pane
* - Task
* - Navigation Buttons
*
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderWizard(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
renderTitle(context, component, theme, writer);
renderStepsBar(context, component, theme, writer);
renderStepsPane(context, component, theme, writer);
renderTask(context, component, theme, writer);
renderControlBar(context, component, theme, writer);
}
/**
* Render the end of the layout container for the entire Wizard.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderWizardEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
// Enclose the whole wizard in a div
//
writer.endElement(DIV);
try {
// Append properties.
StringBuffer buff = new StringBuffer(256);
JSONObject json = new JSONObject();
json.put("id", component.getClientId(context));
json.put("facesViewState",
javax.faces.render.ResponseStateManager.VIEW_STATE_PARAM);
// Append JavaScript.
buff.append(JavaScriptUtilities.getModule("wizard")).append("\n") // NOI18N
.append(JavaScriptUtilities.getModuleName("wizard.init")) // NOI18N
.append("(") //NOI18N
.append(json.toString(JavaScriptUtilities.INDENT_FACTOR)).append(");"); //NOI18N
// Render JavaScript to close wizard after init function is called.
if (((Wizard) component).isComplete()) {
buff.append(getWizardCloseJavaScript(context, component));
}
// Render JavaScript.
JavaScriptUtilities.renderJavaScript(component, writer,
buff.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Render the Wizard title and structural layout that surrounds the
* title text.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTitle(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
// Don't output anything if there is no title
//
if (!show(component, SHOWTITLE)) {
return;
}
renderTitleBegin(context, component, theme, writer);
renderTitleText(context, component, writer);
renderTitleEnd(context, component, theme, writer);
}
/**
* Render the beginning of the layout container for the Wizard title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTitleBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_TITLE_BAR), null);
}
/**
* Render the actual Wizard title text
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTitleText(FacesContext context,
UIComponent component, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent title = wizard.getTitleComponent();
if (title != null) {
RenderingUtilities.renderComponent(title, context);
}
}
/**
* Render the end of the layout container for the Wizard title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTitleEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.endElement(DIV);
}
/**
* Render the content of the steps bar.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepsBar(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
// See if the steps bar is owned by the application
//
UIComponent stepsBar = wizard.getStepsBarComponent();
if (stepsBar != null) {
RenderingUtilities.renderComponent(stepsBar, context);
return;
}
// We own it. Therefore it's composed of a TabSet component
// with possibly two tabs, Steps and Help. If the wizard
// does not support Help then it's just Steps and therefore
// there is no TabSet component.
//
// See if step help is turned off for the wizard
// If no step help don't render any tabs, just an empty bar.
//
if (wizard.hasStepHelp() && show(component, SHOWSTEPHELP)) {
renderTabsBar(context, component, theme, writer);
} else {
renderEmptyBar(component, theme, writer);
}
}
/**
* Render the content of the steps pane layout container.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepsPane(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
if (!show(component, SHOWSTEPSPANE)) {
return;
}
Wizard wizard = (Wizard) component;
// See if the steps pane is owned by the application
//
UIComponent stepsPane = wizard.getStepsPaneComponent();
if (stepsPane != null) {
RenderingUtilities.renderComponent(stepsPane, context);
return;
}
// Step tab always active if there is no help
// Always returns true if no help is available
//
if (wizard.isStepsTabActive()) {
renderStepListBegin(context, component, theme, writer);
// If no step help, include a steps pane title before rendering the
// steps list.
if (!wizard.hasStepHelp()) {
renderStepsPaneTitle(context, component, theme, writer);
}
renderStepList(context, component, theme, writer);
renderStepListEnd(context, component, theme, writer);
} else {
renderStepHelp(context, component, theme, writer);
}
}
/**
* Render the beginning of the layout container for the Wizard
* Steps list.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepListBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
String paneId =
component.getClientId(context).concat(STEPS_PANE_SUFFIX);
writer.startElement(DIV, component); // Steps Pane DIV
writer.writeAttribute(ID, paneId, null);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP), null);
}
/**
* Render the step list and help tabs in a bar.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTabsBar(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent tabs = wizard.getTabsComponent();
if (tabs == null) {
return;
}
writer.startElement(DIV, component); // Tabs DIV
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TAB), null);
// Looks like tabs is outputting extra div.
//
RenderingUtilities.renderComponent(tabs, context);
writer.endElement(DIV); // Tabs DIV
}
/**
* Render an empty bar for the wizard with no help.
*
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
*/
protected void renderEmptyBar(UIComponent component, Theme theme,
ResponseWriter writer) throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_BAR), null);
writer.endElement(DIV);
}
/**
* Render the steps pane title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepsPaneTitle(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent stepsPaneTitle = wizard.getStepsPaneTitleComponent();
if (stepsPaneTitle == null) {
return;
}
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TITLE), null);
RenderingUtilities.renderComponent(stepsPaneTitle, context);
writer.endElement(DIV);
}
/**
* Render the step list for the Wizard.
* If a UIComponent exists that represents the step list
* render it. Other wise obtain a Wizard.StepList
* iterator from the wizard. The iterator returns instances of
* WizardStepListItem
. It can be determined from
* this object whether the step is the current step, a substep
* or a branch. A component to render for each step can be
* obtained from the wizard component.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepList(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
// If there is a component responsible for the complete
// list render it.
//
UIComponent stepList = wizard.getStepListComponent();
if (stepList != null) {
RenderingUtilities.renderComponent(stepList, context);
return;
}
writer.startElement(TABLE, component);
writer.writeAttribute(BORDER, Integer.toString(0), null);
writer.writeAttribute(CELLSPACING, Integer.toString(0), null);
writer.writeAttribute(CELLPADDING, Integer.toString(0), null);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TABLE), null);
Iterator stepListIterator = wizard.getStepListIterator();
while (stepListIterator.hasNext()) {
WizardStepListItem stepItem =
(WizardStepListItem) stepListIterator.next();
if (stepItem.isSubstep()) {
renderSubstep(context, component, theme, writer, stepItem);
} else if (stepItem.isCurrentStep()) {
renderCurrentStep(context, component, theme, writer, stepItem);
} else if (stepItem.isBranch()) {
renderBranchStep(context, component, theme, writer, stepItem);
} else {
renderStep(context, component, theme, writer, stepItem);
}
}
writer.endElement(TABLE);
}
/**
* Render the indicator that identifies a step as being the current step.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderCurrentStepIndicator(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent stepIndicator = wizard.getStepIndicatorComponent();
if (stepIndicator != null) {
RenderingUtilities.renderComponent(stepIndicator, context);
}
}
/**
* Render a substep. Typically this has a step number of the form
* "n.m" where "n" is the previous step number and "m" is the substep.
* It is indented from the normal step number.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* substep.
*/
protected void renderSubstep(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step) throws IOException {
boolean isCurrentStep = step.isCurrentStep();
String stepTextStyle = isCurrentStep ? theme.getStyleClass(ThemeStyles.WIZARD_STEP_CURRENT_TEXT) : theme.getStyleClass(ThemeStyles.WIZARD_STEP_LINK);
writer.startElement(TR, component);
// The first cell may have the current step indicator.
// It is different from a normal step in that the
// step number is not part of the same cell.
//
if (isCurrentStep) {
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.writeAttribute(ALIGN, RIGHT, null);
writer.writeAttribute(NOWRAP, NOWRAP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_ARROW_DIV), null);
renderCurrentStepIndicator(context, component, theme, writer);
writer.endElement(DIV);
writer.endElement(TD);
} else {
// An empty cell if its not the current step.
//
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.endElement(TD);
}
// The cell for the step nummber. It has a different
// style if it is the current step.
//
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(TABLE, component);
writer.writeAttribute(BORDER, Integer.toString(0), null);
writer.writeAttribute(CELLSPACING, Integer.toString(0), null);
writer.writeAttribute(CELLPADDING, Integer.toString(0), null);
writer.startElement(TR, component);
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TEXT_DIV), null);
renderStepNumber(context, component, theme, writer, step,
stepTextStyle);
writer.endElement(DIV);
writer.endElement(TD);
// Cell for the step summary
//
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TEXT_DIV), null);
renderStepSummary(context, component, theme, writer, step,
stepTextStyle);
writer.endElement(DIV);
writer.endElement(TD);
writer.endElement(TR);
writer.endElement(TABLE);
writer.endElement(TD);
writer.endElement(TR);
}
/**
* Render a Branch step with place holder text.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* branch step.
*/
protected void renderBranchStep(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step) throws IOException {
// Start a branch with an emtpy cell
//
writer.startElement(TR, component);
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.writeAttribute(NOWRAP, NOWRAP, null);
writer.write(NBSP);
writer.endElement(TD);
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TEXT_DIV), null);
// This will be placeholder text for a branch step
//
renderStepPlaceholderText(context, component, theme, writer, step);
writer.endElement(DIV);
writer.endElement(TD);
writer.endElement(TR);
}
/**
* Render the current step in the step list. This step typically appears
* with an icon to the left of the step number, indicating the current step.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* branch step.
*/
protected void renderCurrentStep(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step) throws IOException {
// Begin step row
//
writer.startElement(TR, component);
// Current Step Indicator Cell
// Should this markup be part of renderCurrentStepIndicator ?
// But WIZARD_STEP_ARROW_DIV needs to include the number
//
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.writeAttribute(NOWRAP, NOWRAP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_ARROW_DIV), null);
renderCurrentStepIndicator(context, component, theme, writer);
// How about formatter methods, stepNumberFormat(stepNumber)
// How about WizardStepPane.renderStep(stepNumber, WizardStep.text)
// How about WizardStepPane.renderBranch(WizardStep.branch)
// COMPONENT TEXT : stepNumber "1."
//
renderStepNumber(context, component, theme, writer, step,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_CURRENT_TEXT));
writer.endElement(DIV);
writer.endElement(TD);
// Should this markup be part of renderStepSummary ?
//
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TEXT_DIV), null);
// APPLICATION TEXT : "Type number of users");
//
renderStepSummary(context, component, theme, writer, step,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_CURRENT_TEXT));
writer.endElement(DIV);
writer.endElement(TD);
writer.endElement(TR);
}
/**
* Render a step's sequence number in the step list.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
the information about this
* step.
* @param styleClass The styleClass for this component
*/
protected void renderStepNumber(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step, String styleClass) throws IOException {
UIComponent number = ((Wizard) component).getStepNumberComponent(
step.getStep(), step.getStepNumberString());
if (number == null) {
// Should log or throw something here.
return;
}
number.getAttributes().put(STYLE_CLASS, styleClass);
RenderingUtilities.renderComponent(number, context);
}
/**
* Render a step's summary in the step list.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* step.
*/
protected void renderStepSummary(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step, String styleClass)
throws IOException {
UIComponent text = ((Wizard) component).getStepSummaryComponent(
step.getStep());
if (text == null) {
return;
}
text.getAttributes().put(STYLE_CLASS, styleClass);
RenderingUtilities.renderComponent(text, context);
}
/**
* Render a baranch step's placeholder text in the step list.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* step.
*/
protected void renderStepPlaceholderText(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step)
throws IOException {
UIComponent text = ((Wizard) component).getStepPlaceholderTextComponent(
step.getStep());
if (text == null) {
return;
}
text.getAttributes().put(STYLE_CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TEXT));
RenderingUtilities.renderComponent(text, context);
}
/**
* Render a step in the step list.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* step.
*/
protected void renderStep(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step)
throws IOException {
writer.startElement(TR, component);
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_NUMBER_DIV), null);
renderStepNumber(context, component, theme, writer, step,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_LINK));
writer.endElement(DIV);
writer.endElement(TD);
writer.startElement(TD, component);
writer.writeAttribute(VALIGN, TOP, null);
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_TEXT_DIV), null);
// This will be placeholder text for a branch step
//
renderStepSummary(context, component, theme, writer, step,
theme.getStyleClass(ThemeStyles.WIZARD_STEP_LINK));
writer.endElement(DIV);
writer.endElement(TD);
writer.endElement(TR);
}
/**
* Render the help for the current Step in the Wizard.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepHelp(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
UIComponent stepHelp = ((Wizard) component).getStepHelpComponent();
if (stepHelp != null) {
RenderingUtilities.renderComponent(stepHelp, context);
}
WizardStep step = ((Wizard) component).getCurrentStep();
renderStepHelpBegin(context, component, theme, writer, step);
renderStepHelpText(context, component, theme, writer, step);
renderStepHelpEnd(context, component, theme, writer, step);
}
/**
* Render the beginning of the layout for the step help.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
the current step.
*/
protected void renderStepHelpBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step) throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_HELP_DIV), null);
// Probably shouldn't include the para
//
writer.startElement(PARA, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_HELP_TEXT), null);
}
/**
* Render the step help text.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
the current step.
*/
protected void renderStepHelpText(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
// Assumes current step.
//
UIComponent stepHelp = ((Wizard) component).getStepHelpTextComponent();
if (stepHelp != null) {
RenderingUtilities.renderComponent(stepHelp, context);
}
}
/**
* Render the end of the layout for the step help.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
the current step.
*/
protected void renderStepHelpEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.endElement(PARA);
writer.endElement(DIV);
}
/**
* Render the end of the layout container for the Wizard
* Steps list.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderStepListEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.endElement(DIV); // Steps Pane DIV
}
/**
* Render the step task. This includes a task header of title and
* step detail or instruction, and the components that make up the
* current wizard step.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTask(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
UIComponent task = ((Wizard) component).getTaskComponent();
if (task != null) {
RenderingUtilities.renderComponent(task, context);
return;
}
WizardStep step = ((Wizard) component).getCurrentStep();
if (step == null) {
// Should log
return;
}
renderTaskBegin(context, component, theme, writer);
renderTaskHeader(context, component, theme, writer, step);
renderStepTask(context, component, theme, writer, step);
renderTaskEnd(context, component, theme, writer);
}
/**
* Render the beginning of the layout container step task area.
* This includes an anchor from the beginning of the steps pane.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTaskBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
String idandclass = theme.getStyleClass(ThemeStyles.WIZARD_BODY);
writer.startElement(DIV, component); // WizBdy DIV
writer.writeAttribute(ID,
component.getClientId(context).concat(USCORE).concat(idandclass),
null);
writer.writeAttribute(CLASS, idandclass, null);
// The skip link anchor
//
renderSkipAnchor(context, component, theme, writer,
component.getClientId(context));
}
/**
* Render the end of the layout container for the Wizard step task area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderTaskEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.endElement(DIV); // WizBdy DIV
}
/**
* Render the step title and step detail for the current step.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderTaskHeader(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
UIComponent taskHeader = ((Wizard) component).getTaskHeaderComponent();
if (taskHeader != null) {
RenderingUtilities.renderComponent(taskHeader, context);
return;
}
renderStepTitle(context, component, theme, writer, step);
renderStepDetail(context, component, theme, writer, step);
}
/**
* Render the step title label.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTitleLabelText(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
UIComponent titleLabel =
((Wizard) component).getStepTitleLabelTextComponent();
if (titleLabel != null) {
titleLabel.getAttributes().put(STYLE_CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_SUB_TITLE_TEXT));
RenderingUtilities.renderComponent(titleLabel, context);
}
}
/**
* Render the step title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTitle(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
UIComponent stepTitle = ((Wizard) component).getStepTitleComponent();
if (stepTitle != null) {
RenderingUtilities.renderComponent(stepTitle, context);
return;
}
renderStepTitleBegin(context, component, theme, writer, step);
renderStepTitleLabelText(context, component, theme, writer, step);
renderStepTitleText(context, component, theme, writer, step);
renderStepTitleEnd(context, component, theme, writer, step);
}
/**
* Render the beginning of the layout for the step title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTitleBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_SUB_TITLE_DIV), null);
}
/**
* Render the step title text.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTitleText(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
UIComponent stepTitle = ((Wizard) component).getStepTitleTextComponent();
if (stepTitle != null) {
stepTitle.getAttributes().put(STYLE_CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_SUB_TITLE_TEXT));
RenderingUtilities.renderComponent(stepTitle, context);
}
}
/**
* Render the end of the layout for the step title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTitleEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.endElement(DIV);
}
/**
* Render the step detail for the current step.
* Each step may have optional detail text that appears
* below the current step title.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepDetail(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
UIComponent stepDetail = ((Wizard) component).getStepDetailComponent();
if (stepDetail != null) {
RenderingUtilities.renderComponent(stepDetail, context);
return;
}
renderStepDetailBegin(context, component, theme, writer, step);
renderStepDetailText(context, component, theme, writer, step);
renderStepDetailEnd(context, component, theme, writer, step);
}
/**
* Render the beginning of the layout container for the step detail.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepDetailBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_CONTENT_HELP_TEXT), null);
}
/**
* Render the step detail text.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepDetailText(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
UIComponent stepDetail =
((Wizard) component).getStepDetailTextComponent();
if (stepDetail != null) {
RenderingUtilities.renderComponent(stepDetail, context);
}
}
/**
* Render the end of the layout container for the step detail.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepDetailEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.endElement(DIV);
}
/**
* Render the beginning of the layout container for the step components.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTaskBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_TASK), null);
}
/**
* Render the step components.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTask(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
// This probably over kill ?
// Wrapper for a WizardStep ?
//
UIComponent task = ((Wizard) component).getTaskStepComponent();
if (task != null) {
RenderingUtilities.renderComponent(task, context);
return;
}
renderStepTaskBegin(context, component, theme, writer, step);
renderStepTaskComponents(context, component, theme, writer, step);
renderStepTaskEnd(context, component, theme, writer, step);
}
/**
* Render the end of the layout container for the step components
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTaskEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step)
throws IOException {
writer.endElement(DIV);
}
/**
* Render the components and layout for the navigation control area.
* This area contains the Previous, Next, Finish, Cancel and Close
* buttons.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderControlBar(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
if (!show(component, SHOWCONTROLS)) {
return;
}
UIComponent controlBar = ((Wizard) component).getControlBarComponent();
if (controlBar != null) {
RenderingUtilities.renderComponent(controlBar, context);
return;
}
renderControlBarBegin(context, component, theme, writer);
renderControlBarSpacer(context, component, theme, writer);
// layout container for the left and right sections in the control area.
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_BUTTON_BOTTOM), null);
renderLeftControlBar(context, component, theme, writer);
renderRightControlBar(context, component, theme, writer);
writer.endElement(DIV);
renderControlBarEnd(context, component, theme, writer);
}
/**
* Render the beginning of the layout container for the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderControlBarBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_BOTTOM), null);
}
/**
* Render the end of the layout container for the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderControlBarEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.endElement(DIV);
}
/**
* Render spacer for the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderControlBarSpacer(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_BOTTOM_SPACER), null);
writer.endElement(DIV);
}
/**
* Render the beginning of the layout container for the left side of
* the control area. The area containing the sequencing controls is
* split into two sections: Left and Right.
* The left side of the control area contains the Previous,
* Next or Finish controls. The right area contains the
* Cancel or Close control.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderLeftControlBar(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent leftControlBar = wizard.getLeftControlBarComponent();
if (leftControlBar != null) {
RenderingUtilities.renderComponent(leftControlBar, context);
return;
}
renderLeftControlBarBegin(context, component, theme, writer);
if (wizard.hasPrevious()) {
renderPreviousControl(context, component, theme, writer);
}
if (wizard.hasNext()) {
renderNextControl(context, component, theme, writer);
} else if (wizard.hasFinish()) {
renderFinishControl(context, component, theme, writer);
}
renderLeftControlBarEnd(context, component, theme, writer);
}
/**
* Render the beginning of the layout container for the
* left side of the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderLeftControlBarBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_LEFT), null);
}
/**
* Render the control that directs the Wizard to the previous step.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderPreviousControl(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent control = wizard.getPreviousComponent();
if (control == null) {
// Log this
return;
}
renderControl(context, theme, control);
}
/**
* Render the control that directs the Wizard to the next step.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderNextControl(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent nextControl = wizard.getNextComponent();
if (nextControl == null) {
// Log this
return;
}
renderControl(context, theme, nextControl);
}
/**
* Render the control that directs the Wizard to the perform task.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderFinishControl(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent control = wizard.getFinishComponent();
if (control == null) {
// Log this
return;
}
renderControl(context, theme, control);
}
/**
* Render the end of the layout container for the
* left side of the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderLeftControlBarEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.endElement(DIV);
}
/**
* Render the beginning of the layout container for the
* right side of the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderRightControlBar(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent rightControlBar = wizard.getRightControlBarComponent();
if (rightControlBar != null) {
RenderingUtilities.renderComponent(rightControlBar, context);
return;
}
renderRightControlBarBegin(context, component, theme, writer);
if (wizard.hasCancel()) {
renderCancelControl(context, component, theme, writer);
} else if (wizard.hasClose()) {
renderCloseControl(context, component, theme, writer);
}
renderRightControlBarEnd(context, component, theme, writer);
}
/**
* Render the beginning of the layout container for the
* right side of the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderRightControlBarBegin(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.WIZARD_RIGHT), null);
}
/**
* Render the control that cancels the Wizard task.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderCancelControl(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent control = wizard.getCancelComponent();
if (control == null) {
// Log this
return;
}
renderControl(context, theme, control);
}
/**
* Render the control that directs the Wizard to the end the
* Wizard task.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderCloseControl(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
Wizard wizard = (Wizard) component;
UIComponent control = wizard.getCloseComponent();
if (control == null) {
// Log this
return;
}
renderControl(context, theme, control);
}
/**
* Render the end of the layout container for the
* right side of the control area.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
*/
protected void renderRightControlBarEnd(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer)
throws IOException {
writer.endElement(DIV);
}
/**
* Create an invisible "skip" link to an anchor as an accessibility feature
* to navigate to the main task area in a Wizard from the steps pane.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
* @param theme Theme
to use for style, images, and text.
* @param alt the text that will appear to screen readers.
*/
private void renderSkipLink(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
String link, String alt)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.SKIP_WHITE), null);
writer.startElement(ANCHOR, component);
writer.writeAttribute(HREF, "#" + link, null);
// Can this be done with a style selector ?
// This is an invisible rule, used mainly for the alt
//
renderRule(context, component, theme, writer, 1, 1, alt);
writer.endElement(ANCHOR);
writer.endElement(DIV);
}
/**
* The anchor target of the "skip" link.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
* @param theme Theme
to use for style, images, and text.
* @param anchor the text that will appear to screen readers, specified as
* link
in a previous renderSkipLink
call.
*/
private void renderSkipAnchor(FacesContext context,
UIComponent component, Theme theme,
ResponseWriter writer, String anchor)
throws IOException {
writer.startElement(DIV, component);
writer.writeAttribute(CLASS,
theme.getStyleClass(ThemeStyles.SKIP_WHITE), null);
writer.startElement(ANCHOR, component);
writer.writeAttribute(NAME, anchor, null);
writer.writeAttribute(ID, anchor, null);
writer.endElement(ANCHOR);
writer.endElement(DIV);
}
/**
* Render a rule as separator line.
*
* NOTE: Need to determine if CSS can be used for this purpose.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param writer ResponseWriter
write the response using this
* writer.
* @param theme Theme
to use for style, images, and text.
* @param width the width of the rule.
* @param height the height of the rule.
* @param alt the text that will appear if the dot image cannot be
* displayed.
*/
private void renderRule(FacesContext context, UIComponent component,
Theme theme, ResponseWriter writer,
int width, int height, String alt)
throws IOException {
Icon icon = ThemeUtilities.getIcon(theme, ThemeImages.DOT);
// Originally alt was written out if it was "", does this
// still make sense ?
//
if (alt != null) {
icon.setAlt(alt);
}
icon.setHeight(height);
icon.setWidth(width);
RenderingUtilities.renderComponent(icon, context);
}
/**
* Return true if the feature has been configured to be displayed,
* false otherwise.
*
* @param component the UIComponent
being rendered.
* @param feature the attribute that controls a feature.
*/
private boolean show(UIComponent component, String feature) {
// Don't show controls if turned off
// Default is true
//
/* Not supported yet
Boolean showIt = (Boolean)component.getAttributes().get(feature);
return showIt == null || showIt.booleanValue();
*/
return true;
}
/**
* Render the current WizardStep component.
*
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStep
current step.
*/
protected void renderStepTaskComponents(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStep step) throws IOException {
// This could be a component tree
// Children of the step, an iterator, a jsp page, ...
//
/*
Object task = step.getStepTaskComponents();
if (task == null) {
task = ((Wizard)component).getStepTaskComponents();
}
if (task == null) {
// fake it
return;
}
// URL to a jsp page
//
if (task instanceof String) {
RenderingUtilities.includeJsp(context, writer, task);
} else
// component tree
//
if (task instanceof UIComponent) {
RenderingUtilities.renderComponent(task, context);
} else
// Array, List, or Map
//
if (task instanceof List) {
} else
if (task instanceof Array) {
} else
if (task instanceof Map) {
} else
if (step.getChildren() != null) {
}
String jspPath = step.getStepURL();
// Checks for null
//
RenderingUtilities.includeJsp(context, writer, jspPath);
*/
RenderingUtilities.renderComponent(step, context);
}
// This isn't perfect
//
private String mergeStyle(String styles, String newStyle) {
if (newStyle == null) {
return styles;
}
if (styles == null) {
return newStyle;
}
StringBuffer sb = new StringBuffer(styles);
String[] splitStyles = styles.split(SPACE);
for (int i = 0; i < splitStyles.length; ++i) {
if (splitStyles[i].equals(newStyle)) {
return sb.toString();
}
}
sb.append(SPACE).append(newStyle);
return sb.toString();
}
private void renderControl(FacesContext context, Theme theme,
UIComponent control) throws IOException {
RenderingUtilities.renderComponent(control, context);
}
// Nothing so far
//
@Override
public void decode(FacesContext context, UIComponent component) {
// Enforce NPE requirements in the Javadocs
if (context == null || component == null) {
throw new NullPointerException();
}
}
// Helpful constants.
// Elements
private static final String ANCHOR = "a"; //NOI18N
private static final String DIV = "div"; //NOI18N
private static final String IMG = "img"; //NOI18N
private static final String INPUT = "input"; //NOI18N
private static final String PARA = "p"; //NOI18N
private static final String SCRIPT = "script"; //NOI18N
private static final String SPAN = "span"; //NOI18N
private static final String TABLE = "table"; //NOI18N
private static final String TD = "td"; //NOI18N
private static final String TR = "tr"; //NOI18N
// Attributes
private static final String ALIGN = "align"; //NOI18N
private static final String ALT = "alt"; //NOI18N
private static final String BORDER = "border"; //NOI18N
private static final String CELLPADDING = "cellpadding"; //NOI18N
private static final String CELLSPACING = "cellspacing"; //NOI18N
private static final String CLASS = "class"; //NOI18N
private static final String STYLE_CLASS = "styleClass"; //NOI18N
private static final String DISABLED = "disabled"; //NOI18N
private static final String HEIGHT = "height"; //NOI18N
private static final String HREF = "href"; //NOI18N
private static final String HSPACE = "hspace"; //NOI18N
private static final String ID = "id"; //NOI18N
private static final String NAME = "name"; //NOI18N
private static final String NOWRAP = "nowrap"; //NOI18N
private static final String ONBLUR = "onblur"; //NOI18N
private static final String ONCLICK = "onclick"; //NOI18N
private static final String ONFOCUS = "onfocus"; //NOI18N
private static final String ONMOUSEOVER = "onmouseover"; //NOI18N
private static final String ONMOUSEOUT = "onmouseout"; //NOI18N
private static final String SRC = "src"; //NOI18N
private static final String STYLE = "style"; //NOI18N
private static final String TITLE = "title"; //NOI18N
private static final String TYPE = "type"; //NOI18N
private static final String VALIGN = "valign"; //NOI18N
private static final String VALUE = "valign"; //NOI18N
private static final String WIDTH = "width"; //NOI18N
// Values
private static final String _1_PERCENT = "1%"; //NOI18N
private static final String _90_PERCENT = "90%"; //NOI18N
private static final String _99_PERCENT = "99%"; //NOI18N
private static final String _100_PERCENT = "100%"; //NOI18N
private static final String BOTTOM = "bottom"; //NOI18N
private static final String LEFT = "left"; //NOI18N
private static final String RIGHT = "right"; //NOI18N
private static final String SUBMIT = "submit"; //NOI18N
private static final String TOP = "top"; //NOI18N
private static final String TEXT_JAVASCRIPT = "text/javascript"; //NOI18N
private static final String NBSP = " "; //NOI18N
// Constants
private static final String STEPS_PANE_SUFFIX = "_stepspane"; //NOI18N
private static final String SPACE = " "; //NOI18N
private static final String EMPTY_STRING = ""; //NOI18N
private static final String USCORE = "_"; //NOI18N
private static final String WIZARD_JSOBJECT_CLASS = "Wizard"; //NOI18N
private static final String SQUOTE = "'"; //NOI18N
private static final String CLOSEPOPUPJS = "{0}.closePopup();"; //NOI18N
// Wizard attributes
private static final String TOOLTIP = "toolTip"; //NOI18N
private static final String SHOWCONTROLS = "showControls"; //NOI18N
private static final String SHOWSTEPSPANE = "showStepsPane"; //NOI18N
private static final String SHOWSTEPHELP = "showStepHelp"; //NOI18N
private static final String SHOWTITLE = "showTitle"; //NOI18N
private static final String ONPOPUPDISMISS = "onPopupDismiss"; //NOI18N
private static final String WIZARD_SKIP_LINK_ALT = "Wizard.skipLinkAlt"; //NOI18N
private static final String MSG_COMPONENT_NOT_WIZARD =
"WizardLayoutRenderer only renders Wizard components."; //NOI18N
private String getMessage(String key) {
return key;
}
// Deprecations, which we may decide can just be removed.
// However, if not, these deprecated methods should probably provide the
// redundant spans to maintain the original behavior.
//
// Deprecate these method since we were adding redundant spans
// around static text. The problem is that using these methods
// will yield NO wizard style for the span.
//
/**
* Render a step's sequence number in the step list.
*
* @deprecated See {@link renderStepNumber(FacesContext,UIComponent,Theme,ResponseWriter,WizardStepListItem, String styleClass)}
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
the information about this
* step.
*/
protected void renderStepNumber(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step) throws IOException {
UIComponent number = ((Wizard) component).getStepNumberComponent(
step.getStep(), step.getStepNumberString());
if (number == null) {
// Should log or throw something here.
return;
}
RenderingUtilities.renderComponent(number, context);
}
/**
* Render a step's summary in the step list.
*
* @deprecated See {@link renderStepSummary(FacesContext,UIComponent,Theme,ResponseWriter,WizardStepListItem, String styleClass)}
* @param context FacesContext
for the current request.
* @param component UIComponent
a Wizard or Wizard subclass.
* @param theme Theme
to use for style, images, and text.
* @param writer ResponseWriter
write the response using this
* writer.
* @param step WizardStepListItem
information about this
* step.
*/
protected void renderStepSummary(FacesContext context,
UIComponent component, Theme theme, ResponseWriter writer,
WizardStepListItem step)
throws IOException {
UIComponent text = ((Wizard) component).getStepSummaryComponent(
step.getStep());
if (text == null) {
return;
}
RenderingUtilities.renderComponent(text, context);
}
}