001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.renderer;
042:
043: import com.sun.rave.web.ui.component.Breadcrumbs;
044: import com.sun.rave.web.ui.component.Hyperlink;
045: import com.sun.rave.web.ui.component.util.Util;
046: import com.sun.rave.web.ui.theme.Theme;
047: import com.sun.rave.web.ui.theme.ThemeStyles;
048: import com.sun.rave.web.ui.util.ConversionUtilities;
049: import com.sun.rave.web.ui.util.RenderingUtilities;
050: import com.sun.rave.web.ui.util.ThemeUtilities;
051: import java.beans.Beans;
052:
053: import java.io.IOException;
054: import java.util.Iterator;
055: import java.util.Map;
056: import java.util.Arrays;
057: import java.util.List;
058:
059: import javax.faces.context.FacesContext;
060: import javax.faces.context.ResponseWriter;
061: import javax.faces.component.UIComponent;
062: import javax.faces.component.UIForm;
063:
064: /**
065: * <p>Renderer for a {@link Breadcrumbs} component.</p>
066: * <p>This class renders a breadcrumb or parentage path.</p>
067: */
068: public class BreadcrumbsRenderer extends AbstractRenderer {
069:
070: /** Creates a new instance of BreadcrumbsRenderer */
071: public BreadcrumbsRenderer() {
072: // default constructor
073: }
074:
075: /**
076: * Overrides encodeChildren of Renderer to do nothing. This
077: * class renders its own children, but not through this
078: * method.
079: *
080: * @param context The FacesContext of the request
081: * @param component The component associated with the
082: * renderer.
083: */
084: public void encodeChildren(FacesContext context,
085: UIComponent component) throws java.io.IOException {
086: return;
087: }
088:
089: /**
090: * Returns a flag indicating that this component is responsible
091: * for rendering it's children.
092: *
093: */
094: public boolean getRendersChildren() {
095: return true;
096: }
097:
098: /**
099: * Renders the attributes for the table containing the breadcrumbs.
100: *
101: * @param context The current FacesContext
102: * @param breadcrumbs The Breadcrumbs object to use
103: * @param theme The theme to use
104: * @param writer The current ResponseWriter
105: *
106: * @exception IOException if an input/output error occurs
107: */
108: protected void renderContainingTable(FacesContext context,
109: Breadcrumbs breadcrumbs, Theme theme, ResponseWriter writer)
110: throws IOException {
111: // Render the opening table
112:
113: writer.startElement("div", breadcrumbs); //NOI18N
114: String tdStyle = theme
115: .getStyleClass(ThemeStyles.BREADCRUMB_WHITE_DIV);
116: addCoreAttributes(context, breadcrumbs, writer, tdStyle);
117: writer.writeText("\n", null); //NOI18N
118: }
119:
120: /**
121: * Renders the separator between the elements of the breadcrumbs.
122: *
123: * @param context The current FacesContext
124: * @param breadcrumbs The Breadcrumbs object to use
125: * @param theme The theme to use
126: * @param writer The current ResponseWriter
127: *
128: * @exception IOException if an input/output error occurs
129: */
130: protected void renderBreadcrumbsSeparator(FacesContext context,
131: Breadcrumbs breadcrumbs, Theme theme, ResponseWriter writer)
132: throws IOException {
133: writer.startElement("span", breadcrumbs); //NOI18N
134: String separatorStyle = theme
135: .getStyleClass(ThemeStyles.BREADCRUMB_SEPARATOR);
136: writer.writeAttribute("class", separatorStyle, null); //NOI18N
137: // TODO: Replace spearator with themeable glyph/text
138: writer.write(">"); //NOI18N
139: writer.endElement("span"); //NOI18N
140: }
141:
142: /**
143: * Renders the hyperlinks which make up the breadcrumbs.
144: *
145: * @param context The current FacesContext
146: * @param link The component representing a page in the breadcrumbs.
147: * @param theme The theme to use
148: * This must be a Hyperlink or subclass of a Hyperlink.
149: *
150: * @exception IOException if an input/output error occurss
151: */
152: protected void renderBreadcrumbsLink(FacesContext context,
153: Hyperlink link, Theme theme) throws IOException {
154: String linkStyle = theme
155: .getStyleClass(ThemeStyles.BREADCRUMB_LINK);
156:
157: Map attributes = link.getAttributes();
158: if (attributes != null && attributes.get("styleClass") == null) { //NOI18N
159: attributes.put("styleClass", linkStyle); //NOI18N
160: }
161: RenderingUtilities.renderComponent(link, context);
162: }
163:
164: /**
165: * Renders the final breadcrumb text which represents the current page.
166: *
167: * @param context The current FacesContext
168: * @param breadcrumbs The Breadcrumbs object to use
169: * @param pageName The current page name.
170: * @param theme The theme to use
171: * @param writer The current ResponseWriter
172: *
173: * @exception IOException if an input/output error occurss
174: */
175: protected void renderBreadcrumbsText(FacesContext context,
176: Hyperlink crumb, Theme theme, ResponseWriter writer)
177: throws IOException {
178:
179: // <RAVE>
180: // String pageName = crumb.getText();
181: String pageName = ConversionUtilities.convertValueToString(
182: crumb, crumb.getText());
183: // </RAVE>
184: if (pageName == null || pageName.length() <= 0)
185: return;
186:
187: writer.startElement("span", crumb); //NOI18N
188: String textStyle = theme
189: .getStyleClass(ThemeStyles.BREADCRUMB_TEXT);
190: writer.writeAttribute("class", textStyle, null); //NOI18N
191: writer.writeText(pageName, null);
192: writer.endElement("span"); //NOI18N
193: writer.endElement("div"); //NOI18N
194: }
195:
196: /**
197: * Renders the breadcrumbs.
198: *
199: * @param context The current FacesContext
200: * @param component The Breadcrumbs object to use
201: * @param writer The current ResponseWriter
202: *
203: * @exception IOException if an input/output error occurss
204: */
205: protected void renderEnd(FacesContext context,
206: UIComponent component, ResponseWriter writer)
207: throws IOException {
208: if (context == null || component == null || writer == null) {
209: throw new NullPointerException();
210: }
211:
212: Breadcrumbs breadcrumbs = (Breadcrumbs) component;
213:
214: if (!breadcrumbs.isRendered()) {
215: return;
216: }
217:
218: // Get the list of pages. If pages are supplied as an array of hyperlink
219: // components, temporarily set their parent to this breadcrumb, so that
220: // when they render they will find this component's ancestor form
221: UIComponent[] pages = null;
222: if (breadcrumbs.getPages() != null) {
223: pages = breadcrumbs.getPages();
224: for (int i = 0; i < pages.length; i++)
225: pages[i].setParent(component);
226: } else if (breadcrumbs.getChildren() != null) {
227: List list = breadcrumbs.getChildren();
228: pages = (UIComponent[]) list.toArray(new UIComponent[list
229: .size()]);
230: }
231:
232: if (pages == null
233: || (pages.length <= 1 && !Beans.isDesignTime()))
234: return;
235:
236: Theme theme = ThemeUtilities.getTheme(context);
237:
238: // Render containing table
239: renderContainingTable(context, breadcrumbs, theme, writer);
240:
241: int length = pages.length;
242: // Iterate through the array of hyperlinks
243: for (int i = 0; i < length; i++) {
244: // pages must be hyperlinks (or a subclass of hyperlinks)
245: Hyperlink crumb = (Hyperlink) pages[i];
246:
247: // Check if this is the last breadcrumb
248: if (i < (length - 1)) {
249: // Render a hyperlink
250: renderBreadcrumbsLink(context, crumb, theme);
251: renderBreadcrumbsSeparator(context, breadcrumbs, theme,
252: writer);
253: } else {
254: // Render static text - for the final page in the breadcrumbs
255: renderBreadcrumbsText(context, crumb, theme, writer);
256: }
257: }
258: }
259: }
|