0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package com.sun.rave.web.ui.renderer;
0042:
0043: import com.sun.data.provider.RowKey;
0044: import com.sun.data.provider.SortCriteria;
0045: import com.sun.rave.web.ui.component.DropDown;
0046: import com.sun.rave.web.ui.component.Label;
0047: import com.sun.rave.web.ui.component.Table;
0048: import com.sun.rave.web.ui.component.TableActions;
0049: import com.sun.rave.web.ui.component.TableColumn;
0050: import com.sun.rave.web.ui.component.TableHeader;
0051: import com.sun.rave.web.ui.component.TablePanels;
0052: import com.sun.rave.web.ui.component.TableRowGroup;
0053: import com.sun.rave.web.ui.component.util.Util;
0054: import com.sun.rave.web.ui.model.Option;
0055: import com.sun.rave.web.ui.theme.Theme;
0056: import com.sun.rave.web.ui.theme.ThemeStyles;
0057: import com.sun.rave.web.ui.util.LogUtil;
0058: import com.sun.rave.web.ui.util.RenderingUtilities;
0059: import com.sun.rave.web.ui.util.ThemeUtilities;
0060: import com.sun.rave.web.ui.theme.ThemeImages;
0061: import com.sun.rave.web.ui.theme.ThemeJavascript;
0062:
0063: import java.io.IOException;
0064: import java.util.ArrayList;
0065: import java.util.Iterator;
0066: import java.util.List;
0067:
0068: import javax.faces.component.NamingContainer;
0069: import javax.faces.component.UIComponent;
0070: import javax.faces.context.FacesContext;
0071: import javax.faces.context.ResponseWriter;
0072: import javax.faces.render.Renderer;
0073:
0074: /**
0075: * This class renders Table components.
0076: * <p>
0077: * The table component provides a layout mechanism for displaying table actions.
0078: * UI guidelines describe specific behavior that can applied to the rows and
0079: * columns of data such as sorting, filtering, pagination, selection, and custom
0080: * user actions. In addition, UI guidelines also define sections of the table
0081: * that can be used for titles, row group headers, and placement of pre-defined
0082: * and user defined actions.
0083: * </p><p>
0084: * Note: Column headers and footers are rendered by TableRowGroupRenderer. Table
0085: * column footers are rendered by TableRenderer.
0086: * </p><p>
0087: * Note: To see the messages logged by this class, set the following global
0088: * defaults in your JDK's "jre/lib/logging.properties" file.
0089: * </p><p><pre>
0090: * java.util.logging.ConsoleHandler.level = FINE
0091: * com.sun.rave.web.ui.renderer.TableRenderer.level = FINE
0092: * </pre></p><p>
0093: * See TLD docs for more information.
0094: * </p>
0095: */
0096: public class TableRenderer extends Renderer {
0097: // Javascript object name.
0098: private static final String JAVASCRIPT_OBJECT_CLASS = "Table"; //NOI18N
0099:
0100: /**
0101: * The set of String pass-through attributes to be rendered.
0102: * <p>
0103: * Note: The BGCOLOR attribute is deprecated (in the HTML 4.0 spec) in favor
0104: * of style sheets. In addition, the DIR and LANG attributes are not
0105: * cuurently supported.
0106: * </p>
0107: */
0108: private static final String stringAttributes[] = { "align", //NOI18N
0109: "bgColor", //NOI18N
0110: "dir", //NOI18N
0111: "frame", //NOI18N
0112: "lang", //NOI18N
0113: "onClick", //NOI18N
0114: "onDblClick", //NOI18N
0115: "onKeyDown", //NOI18N
0116: "onKeyPress", //NOI18N
0117: "onKeyUp", //NOI18N
0118: "onMouseDown", //NOI18N
0119: "onMouseMove", //NOI18N
0120: "onMouseOut", //NOI18N
0121: "onMouseOver", //NOI18N
0122: "onMouseUp", //NOI18N
0123: "rules", //NOI18N
0124: "summary" }; //NOI18N
0125:
0126: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0127: // Renderer methods
0128: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0129:
0130: /**
0131: * Render the beginning of the specified UIComponent to the output stream or
0132: * writer associated with the response we are creating.
0133: *
0134: * @param context FacesContext for the current request.
0135: * @param component UIComponent to be rendered.
0136: *
0137: * @exception IOException if an input/output error occurs.
0138: * @exception NullPointerException if context or component is null.
0139: */
0140: public void encodeBegin(FacesContext context, UIComponent component)
0141: throws IOException {
0142: if (context == null || component == null) {
0143: log("encodeBegin", //NOI18N
0144: "Cannot render, FacesContext or UIComponent is null"); //NOI18N
0145: throw new NullPointerException();
0146: }
0147: if (!component.isRendered()) {
0148: log("encodeBegin",
0149: "Component not rendered, nothing to display"); //NOI18N
0150: return;
0151: }
0152:
0153: Table table = (Table) component;
0154: ResponseWriter writer = context.getResponseWriter();
0155: renderEnclosingTagStart(context, table, writer);
0156: renderTitle(context, table, writer);
0157: renderActionsTop(context, table, writer);
0158: renderEmbeddedPanels(context, table, writer);
0159: }
0160:
0161: /**
0162: * Render the children of the specified UIComponent to the output stream or
0163: * writer associated with the response we are creating.
0164: *
0165: * @param context FacesContext for the current request.
0166: * @param component UIComponent to be decoded.
0167: *
0168: * @exception IOException if an input/output error occurs.
0169: * @exception NullPointerException if context or component is null.
0170: */
0171: public void encodeChildren(FacesContext context,
0172: UIComponent component) throws IOException {
0173: if (context == null || component == null) {
0174: log("encodeChildren", //NOI18N
0175: "Cannot render, FacesContext or UIComponent is null"); //NOI18N
0176: throw new NullPointerException();
0177: }
0178: if (!component.isRendered()) {
0179: log("encodeChildren",
0180: "Component not rendered, nothing to display"); //NOI18N
0181: return;
0182: }
0183:
0184: Table table = (Table) component;
0185: ResponseWriter writer = context.getResponseWriter();
0186:
0187: // Render TableRowGroup children.
0188: Iterator kids = table.getTableRowGroupChildren();
0189: while (kids.hasNext()) {
0190: TableRowGroup group = (TableRowGroup) kids.next();
0191: RenderingUtilities.renderComponent(group, context);
0192: }
0193: }
0194:
0195: /**
0196: * Render the ending of the specified UIComponent to the output stream or
0197: * writer associated with the response we are creating.
0198: *
0199: * @param context FacesContext for the current request.
0200: * @param component UIComponent to be rendered.
0201: *
0202: * @exception IOException if an input/output error occurs.
0203: * @exception NullPointerException if context or component is null.
0204: */
0205: public void encodeEnd(FacesContext context, UIComponent component)
0206: throws IOException {
0207: if (context == null || component == null) {
0208: log("encodeEnd", //NOI18N
0209: "Cannot render, FacesContext or UIComponent is null"); //NOI18N
0210: throw new NullPointerException();
0211: }
0212: if (!component.isRendered()) {
0213: log("encodeEnd",
0214: "Component not rendered, nothing to display"); //NOI18N
0215: return;
0216: }
0217:
0218: Table table = (Table) component;
0219: ResponseWriter writer = context.getResponseWriter();
0220: renderActionsBottom(context, table, writer);
0221: renderTableFooter(context, table, writer);
0222: renderEnclosingTagEnd(writer);
0223: renderJavascript(context, table, writer);
0224: }
0225:
0226: /**
0227: * Return a flag indicating whether this Renderer is responsible
0228: * for rendering the children the component it is asked to render.
0229: * The default implementation returns false.
0230: */
0231: public boolean getRendersChildren() {
0232: return true;
0233: }
0234:
0235: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0236: // Action bar methods
0237: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0238:
0239: /**
0240: * Render the bottom actions for Table components.
0241: *
0242: * @param context FacesContext for the current request.
0243: * @param component Table to be rendered.
0244: * @param writer ResponseWriter to which the component should be rendered.
0245: *
0246: * @exception IOException if an input/output error occurs.
0247: */
0248: protected void renderActionsBottom(FacesContext context,
0249: Table component, ResponseWriter writer) throws IOException {
0250: if (component == null) {
0251: log("renderActionsBottom", //NOI18N
0252: "Cannot render actions bar, Table is null"); //NOI18N
0253: return;
0254: }
0255:
0256: // Get panel component.
0257: UIComponent actions = component.getTableActionsBottom();
0258: if (!(actions != null && actions.isRendered())) {
0259: log("renderActionsBottom", //NOI18N
0260: "Actions bar not rendered, nothing to display"); //NOI18N
0261: return;
0262: }
0263:
0264: writer.writeText("\n", null); //NOI18N
0265: writer.startElement("tr", component); //NOI18N
0266: writer.writeAttribute("id", getId(component, //NOI18N
0267: Table.TABLE_ACTIONS_BOTTOM_BAR_ID), null);
0268:
0269: // Render embedded panels.
0270: RenderingUtilities.renderComponent(actions, context);
0271: writer.endElement("tr"); //NOI18N
0272: }
0273:
0274: /**
0275: * Render the top actions for Table components.
0276: *
0277: * @param context FacesContext for the current request.
0278: * @param component Table to be rendered.
0279: * @param writer ResponseWriter to which the component should be rendered.
0280: *
0281: * @exception IOException if an input/output error occurs.
0282: */
0283: protected void renderActionsTop(FacesContext context,
0284: Table component, ResponseWriter writer) throws IOException {
0285: if (component == null) {
0286: log("renderActionsTop", //NOI18N
0287: "Cannot render actions bar, Table is null"); //NOI18N
0288: return;
0289: }
0290:
0291: // Get panel component.
0292: UIComponent actions = component.getTableActionsTop();
0293: if (!(actions != null && actions.isRendered())) {
0294: log("renderActionsTop", //NOI18N
0295: "Actions bar not rendered, nothing to display"); //NOI18N
0296: return;
0297: }
0298:
0299: writer.writeText("\n", null); //NOI18N
0300: writer.startElement("tr", component); //NOI18N
0301: writer.writeAttribute("id", getId(component, //NOI18N
0302: Table.TABLE_ACTIONS_TOP_BAR_ID), null);
0303:
0304: // Render embedded panels.
0305: RenderingUtilities.renderComponent(actions, context);
0306: writer.endElement("tr"); //NOI18N
0307: }
0308:
0309: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0310: // Embedded panel methods
0311: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0312:
0313: /**
0314: * Render embedded panels for Table components.
0315: *
0316: * @param context FacesContext for the current request.
0317: * @param component Table to be rendered.
0318: * @param writer ResponseWriter to which the component should be rendered.
0319: *
0320: * @exception IOException if an input/output error occurs.
0321: */
0322: protected void renderEmbeddedPanels(FacesContext context,
0323: Table component, ResponseWriter writer) throws IOException {
0324: if (component == null) {
0325: log("renderEmbeddedPanels", //NOI18N
0326: "Cannot render embedded panels, Table is null"); //NOI18N
0327: return;
0328: }
0329:
0330: // Get panel component.
0331: UIComponent panels = component.getEmbeddedPanels();
0332: if (!(panels != null && panels.isRendered())) {
0333: log("renderEmbeddedPanels", //NOI18N
0334: "Embedded panels not rendered, nothing to display"); //NOI18N
0335: return;
0336: }
0337:
0338: writer.writeText("\n", null); //NOI18N
0339: writer.startElement("tr", component); //NOI18N
0340: writer.writeAttribute("id", getId(component, //NOI18N
0341: Table.EMBEDDED_PANELS_BAR_ID), null);
0342:
0343: // Render embedded panels.
0344: RenderingUtilities.renderComponent(panels, context);
0345: writer.endElement("tr"); //NOI18N
0346: }
0347:
0348: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0349: // Footer methods
0350: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0351:
0352: /**
0353: * Render table footer for Table components.
0354: *
0355: * @param context FacesContext for the current request.
0356: * @param component Table to be rendered.
0357: * @param writer ResponseWriter to which the component should be rendered.
0358: *
0359: * @exception IOException if an input/output error occurs.
0360: */
0361: protected void renderTableFooter(FacesContext context,
0362: Table component, ResponseWriter writer) throws IOException {
0363: if (component == null) {
0364: log("renderTableFooter", //NOI18N
0365: "Cannot render table foter, Table is null"); //NOI18N
0366: return;
0367: }
0368:
0369: // Get footer.
0370: UIComponent footer = component.getTableFooter();
0371: if (!(footer != null && footer.isRendered())) {
0372: log("renderTableFooter", //NOI18N
0373: "Table footer not rendered, nothing to display"); //NOI18N
0374: return;
0375: }
0376:
0377: Theme theme = getTheme();
0378: writer.writeText("\n", null); //NOI18N
0379: writer.startElement("tr", component); //NOI18N
0380: writer.writeAttribute("id", getId(component,
0381: Table.TABLE_FOOTER_BAR_ID), //NOI18N
0382: null);
0383:
0384: // Render footer.
0385: RenderingUtilities.renderComponent(footer, context);
0386: writer.endElement("tr"); //NOI18N
0387: }
0388:
0389: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0390: // Title methods
0391: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0392:
0393: /**
0394: * Render title for Table components.
0395: *
0396: * @param context FacesContext for the current request.
0397: * @param component Table to be rendered.
0398: * @param writer ResponseWriter to which the component should be rendered.
0399: *
0400: * @exception IOException if an input/output error occurs.
0401: */
0402: protected void renderTitle(FacesContext context, Table component,
0403: ResponseWriter writer) throws IOException {
0404: if (component == null) {
0405: log("renderTitle", "Cannot render title, Table is null"); //NOI18N
0406: return;
0407: }
0408:
0409: // Render facet.
0410: UIComponent facet = component.getFacet(Table.TITLE_FACET);
0411: if (facet != null) {
0412: renderTitleStart(context, component, writer);
0413: RenderingUtilities.renderComponent(facet, context);
0414: renderTitleEnd(context, writer);
0415: return;
0416: }
0417:
0418: // Render default title.
0419: if (component.getTitle() == null) {
0420: log("renderTitle", "Title is null, nothing to display"); //NOI18N
0421: return;
0422: }
0423:
0424: // Get filter augment.
0425: Theme theme = getTheme();
0426: String filter = (component.getFilterText() != null) ? theme
0427: .getMessage("table.title.filterApplied", //NOI18N
0428: new String[] { component.getFilterText() })
0429: : ""; //NOI18N
0430:
0431: // Get TableRowGroup component.
0432: TableRowGroup group = component.getTableRowGroupChild();
0433: boolean paginated = (group != null) ? group.isPaginated()
0434: : false;
0435:
0436: // Initialize values.
0437: int totalRows = component.getRowCount();
0438: boolean emptyTable = (totalRows == 0);
0439:
0440: // Render title (e.g., "Title (25 - 50 of 1000) [Filter]").
0441: String title = component.getTitle();
0442: if (component.isAugmentTitle()) {
0443: if (!emptyTable && paginated) {
0444: // Get max values for paginated group table.
0445: int maxRows = component.getRows();
0446: int maxFirst = component.getFirst();
0447:
0448: // Get first and last rows augment.
0449: String first = Integer.toString(maxFirst + 1);
0450: String last = Integer.toString(Math.min(maxFirst
0451: + maxRows, totalRows));
0452:
0453: if (component.getItemsText() != null) {
0454: title = theme.getMessage(
0455: "table.title.paginatedItems", //NOI18N
0456: new String[] { component.getTitle(), first,
0457: last, Integer.toString(totalRows),
0458: component.getItemsText(), filter });
0459: } else {
0460: title = theme.getMessage("table.title.paginated", //NOI18N
0461: new String[] { component.getTitle(), first,
0462: last, Integer.toString(totalRows),
0463: filter });
0464: }
0465: } else {
0466: if (component.getItemsText() != null) {
0467: title = theme.getMessage("table.title.scrollItems", //NOI18N
0468: new String[] { component.getTitle(),
0469: Integer.toString(totalRows),
0470: component.getItemsText(), filter });
0471: } else {
0472: title = theme
0473: .getMessage(
0474: "table.title.scroll", //NOI18N
0475: new String[] {
0476: component.getTitle(),
0477: Integer.toString(totalRows),
0478: filter });
0479: }
0480: }
0481: } else {
0482: log("renderTitle", //NOI18N
0483: "Title not augmented, itemsText & filterText not displayed"); //NOI18N
0484: }
0485:
0486: renderTitleStart(context, component, writer);
0487:
0488: // Render title and hidden rows text.
0489: if (component.isHiddenSelectedRows()) {
0490: writer.startElement("span", component); //NOI18N
0491: writer
0492: .writeAttribute(
0493: "class", //NOI18N
0494: theme
0495: .getStyleClass(ThemeStyles.TABLE_TITLE_TEXT_SPAN),
0496: null);
0497: writer.writeText(title, null);
0498: writer.endElement("span"); //NOI18N
0499: writer.startElement("span", component); //NOI18N
0500: writer
0501: .writeAttribute(
0502: "class", //NOI18N
0503: theme
0504: .getStyleClass(ThemeStyles.TABLE_TITLE_MESSAGE_SPAN),
0505: null);
0506: writer.writeText(theme.getMessage("table.hiddenSelections", //NOI18N
0507: new String[] { Integer.toString(component
0508: .getHiddenSelectedRowsCount()) }), null);
0509: writer.endElement("span"); //NOI18N
0510: } else {
0511: // Render default title text.
0512: writer.writeText(title, null);
0513: }
0514: renderTitleEnd(context, writer);
0515: }
0516:
0517: /**
0518: * Render title for Table components.
0519: *
0520: * @param context FacesContext for the current request.
0521: * @param component The table component being rendered.
0522: * @param writer ResponseWriter to which the component should be rendered.
0523: *
0524: * @exception IOException if an input/output error occurs.
0525: */
0526: private void renderTitleStart(FacesContext context,
0527: Table component, ResponseWriter writer) throws IOException {
0528: writer.writeText("\n", null); //NOI18N
0529: writer.startElement("caption", component); //NOI18N
0530: writer.writeAttribute("id",
0531: getId(component, Table.TITLE_BAR_ID), //NOI18N
0532: null);
0533: writer.writeAttribute(
0534: "class", //NOI18N
0535: getTheme().getStyleClass(ThemeStyles.TABLE_TITLE_TEXT),
0536: null);
0537:
0538: // Render extra HTML.
0539: if (component.getExtraTitleHtml() != null) {
0540: RenderingUtilities.renderExtraHtmlAttributes(writer,
0541: component.getExtraTitleHtml());
0542: }
0543: }
0544:
0545: /**
0546: * Render title for Table components.
0547: *
0548: * @param context FacesContext for the current request.
0549: * @param writer ResponseWriter to which the component should be rendered.
0550: *
0551: * @exception IOException if an input/output error occurs.
0552: */
0553: private void renderTitleEnd(FacesContext context,
0554: ResponseWriter writer) throws IOException {
0555: writer.endElement("caption"); //NOI18N
0556: }
0557:
0558: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0559: // Enclosing tag methods
0560: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0561:
0562: /**
0563: * Render enclosing tag for Table components.
0564: *
0565: * @param context FacesContext for the current request.
0566: * @param component Table to be rendered.
0567: * @param writer ResponseWriter to which the component should be rendered.
0568: *
0569: * @exception IOException if an input/output error occurs.
0570: */
0571: protected void renderEnclosingTagStart(FacesContext context,
0572: Table component, ResponseWriter writer) throws IOException {
0573: if (component == null) {
0574: log("renderEnclosingTagStart", //NOI18N
0575: "Cannot render enclosing tag, Table is null"); //NOI18N
0576: return;
0577: }
0578:
0579: Theme theme = getTheme();
0580:
0581: // Render div used to set style and class properties -- bugtraq #6316179.
0582: writer.writeText("\n", null); //NOI18N
0583:
0584: //<RAVE> - Removing the outer div put around table to meet SWADE guidelines
0585: //writer.startElement("div", component); //NOI18N
0586: //writer.writeAttribute("id", component.getClientId(context), null); //NOI18N
0587:
0588: // Render style.
0589: //if (component.getStyle() != null) {
0590: // writer.writeAttribute("style", component.getStyle(), null); //NOI18N
0591: //}
0592:
0593: // Render style class.
0594: //RenderingUtilities.renderStyleClass(context, writer, component, null);
0595:
0596: // Render div used to set width.
0597: //writer.writeText("\n", null); //NOI18N
0598: //writer.startElement("div", component); //NOI18N
0599:
0600: // Render width.
0601: //if (component.getWidth() != null) {
0602: // String width = component.getWidth();
0603:
0604: // // If not a percentage, units are in pixels.
0605: // if (width.indexOf("%") == -1) { //NOI18N
0606: // width += "px"; //NOI18N
0607: // }
0608: // writer.writeAttribute("style", "width:" + width, null); //NOI18N
0609: //} else {
0610: // writer.writeAttribute("style", "width:100%", null); //NOI18N
0611: //}
0612: //</RAVE>
0613:
0614: // Render table.
0615: writer.writeText("\n", null); //NOI18N
0616: writer.startElement("table", component); //NOI18N
0617: //<RAVE>
0618: //writer.writeAttribute("id", getId(component, Table.TABLE_ID), null); //NOI18N
0619: writer.writeAttribute("id", component.getClientId(context),
0620: null); //NOI18N
0621: //</RAVE>
0622:
0623: //<RAVE> - Move the style and style class from outer div to table component
0624: // Render style.
0625: if (component.getStyle() != null) {
0626: String style = component.getStyle();
0627:
0628: if (component.getWidth() != null) {
0629: String width = component.getWidth();
0630:
0631: // If not a percentage, units are in pixels.
0632: if (width.indexOf("%") == -1) { //NOI18N
0633: width += "px"; //NOI18N
0634: }
0635: style = style + ";width: " + width;
0636: } else {
0637: style = style + ";width: 100%";
0638: }
0639: writer.writeAttribute("style", style, null); //NOI18N
0640: }
0641:
0642: // Get style class.
0643: String styleClass = theme.getStyleClass(ThemeStyles.TABLE);
0644:
0645: if (!component.isVisible()) {
0646: String hiddenStyle = theme
0647: .getStyleClass(ThemeStyles.HIDDEN);
0648: if (styleClass == null) {
0649: styleClass = hiddenStyle;
0650: } else {
0651: styleClass = styleClass + " " + hiddenStyle; //NOI18N
0652: }
0653: }
0654: // </RAVE>
0655: if (component.isLite()) {
0656: styleClass += " "
0657: + theme.getStyleClass(ThemeStyles.TABLE_LITE); //NOI18N
0658: }
0659:
0660: if (component.getStyleClass() != null) {
0661: styleClass += " " + component.getStyleClass();
0662: }
0663: //</RAVE>
0664:
0665: // Render style class.
0666: writer.writeAttribute("class", styleClass, null); //NOI18N
0667:
0668: //<RAVE>
0669: // Render width. Note: 100 percent ensures consistent right margins.
0670: //writer.writeAttribute("width", "100%", null); //NOI18N
0671: //</RAVE>
0672:
0673: // Render border.
0674: if (component.getBorder() > -1) {
0675: writer.writeAttribute("border", //NOI18N
0676: Integer.toString(component.getBorder()), null); //NOI18N
0677: } else {
0678: writer.writeAttribute("border", "0", null); //NOI18N
0679: }
0680:
0681: // Render cellpadding.
0682: if (component.getCellPadding() != null) {
0683: writer.writeAttribute("cellpadding", component
0684: .getCellPadding(), null); //NOI18N
0685: } else {
0686: writer.writeAttribute("cellpadding", "0", null); //NOI18N
0687: }
0688:
0689: // Render cellspacing.
0690: if (component.getCellSpacing() != null) {
0691: writer.writeAttribute("cellspacing", component
0692: .getCellSpacing(), null); //NOI18N
0693: } else {
0694: writer.writeAttribute("cellspacing", "0", null); //NOI18N
0695: }
0696:
0697: // Render tooltip.
0698: if (component.getToolTip() != null) {
0699: writer.writeAttribute("title", component.getToolTip(),
0700: "toolTip"); //NOI18N
0701: }
0702:
0703: // Render pass through attributes.
0704: RenderingUtilities.writeStringAttributes(component, writer,
0705: stringAttributes);
0706: }
0707:
0708: /**
0709: * Render enclosing tag for Table components.
0710: *
0711: * @param writer ResponseWriter to which the component should be rendered.
0712: *
0713: * @exception IOException if an input/output error occurs.
0714: */
0715: protected void renderEnclosingTagEnd(ResponseWriter writer)
0716: throws IOException {
0717: writer.endElement("table"); //NOI18N
0718: //<RAVE>
0719: //writer.endElement("div"); //NOI18N
0720: //writer.endElement("div"); //NOI18N
0721: //</RAVE>
0722: }
0723:
0724: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0725: // Private methods
0726: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0727:
0728: /**
0729: * Get component id.
0730: *
0731: * @param component The parent UIComponent component.
0732: * @param id The id of the the component to be rendered.
0733: */
0734: private String getId(UIComponent component, String id) {
0735: String clientId = component.getClientId(FacesContext
0736: .getCurrentInstance());
0737: return clientId + NamingContainer.SEPARATOR_CHAR + id;
0738: }
0739:
0740: /**
0741: * Helper method to get the column ID and selectId from nested TableColumn
0742: * components, used in Javascript functions (e.g., de/select all button
0743: * functionality).
0744: *
0745: * @param context FacesContext for the current request.
0746: * @param component TableColumn to be rendered.
0747: * @return The first selectId property found.
0748: */
0749: private String getSelectId(FacesContext context,
0750: TableColumn component) {
0751: String selectId = null;
0752: if (component == null) {
0753: log("getSelectId",
0754: "Cannot obtain select Id, TableColumn is null"); //NOI18N
0755: return selectId;
0756: }
0757:
0758: // Render nested TableColumn children.
0759: Iterator kids = component.getTableColumnChildren();
0760: if (kids.hasNext()) {
0761: while (kids.hasNext()) {
0762: TableColumn col = (TableColumn) kids.next();
0763: if (!col.isRendered()) {
0764: continue;
0765: }
0766: selectId = getSelectId(context, col);
0767: if (selectId != null) {
0768: break;
0769: }
0770: }
0771: } else {
0772: // Get selectId for possible nested TableColumn components.
0773: if (component.getSelectId() != null) {
0774: // Get TableRowGroup ancestor.
0775: TableRowGroup group = component
0776: .getTableRowGroupAncestor();
0777: if (group != null) {
0778: // Get column and group id.
0779: String colId = component.getClientId(context);
0780: String groupId = group.getClientId(context)
0781: + NamingContainer.SEPARATOR_CHAR;
0782: try {
0783: selectId = colId.substring(groupId.length(),
0784: colId.length())
0785: + NamingContainer.SEPARATOR_CHAR
0786: + component.getSelectId();
0787: } catch (IndexOutOfBoundsException e) {
0788: // Do nothing.
0789: }
0790: }
0791: }
0792: }
0793: return selectId;
0794: }
0795:
0796: /**
0797: * Helper method to get the sort menu option value for the select column.
0798: *
0799: * @param component Table to be rendered.
0800: *
0801: * @return The select option value.
0802: */
0803: private String getSelectSortMenuOptionValue(Table component) {
0804: TableRowGroup group = component.getTableRowGroupChild();
0805:
0806: // Get first select column found.
0807: if (group != null) {
0808: Iterator kids = group.getTableColumnChildren();
0809: while (kids.hasNext()) {
0810: TableColumn col = (TableColumn) kids.next();
0811: if (!col.isRendered() || col.getSelectId() == null) {
0812: continue;
0813: }
0814: String value = getSelectSortMenuOptionValue(col);
0815: if (value != null) {
0816: return value;
0817: }
0818: }
0819: } else {
0820: log("getSelectSortMenuOptionValue", //NOI18N
0821: "Cannot obtain select sort menu option value, TableRowGroup is null"); //NOI18N
0822: }
0823: return null;
0824: }
0825:
0826: /**
0827: * Helper method to get the sort menu option value for the select column.
0828: *
0829: * @param component TableColumn to be rendered.
0830: *
0831: * @return The select option value.
0832: */
0833: private String getSelectSortMenuOptionValue(TableColumn component) {
0834: Iterator kids = component.getTableColumnChildren();
0835: if (kids.hasNext()) {
0836: while (kids.hasNext()) {
0837: TableColumn col = (TableColumn) kids.next();
0838: if (!col.isRendered() || col.getSelectId() == null) {
0839: continue;
0840: }
0841: String value = getSelectSortMenuOptionValue(col);
0842: if (value != null) {
0843: return value;
0844: }
0845: }
0846: }
0847:
0848: // Return sort criteria key.
0849: SortCriteria criteria = component.getSortCriteria();
0850: return (criteria != null) ? criteria.getCriteriaKey() : null;
0851: }
0852:
0853: /**
0854: * Helper method to get Javascript array containing tool tips used for sort
0855: * order menus.
0856: *
0857: * @param component Table to be rendered.
0858: * @param boolean Flag indicating descending tooltips.
0859: * @return A Javascript array containing tool tips.
0860: */
0861: private String getSortToolTipJavascript(Table component,
0862: boolean descending) {
0863: // Get undetermined tooltip.
0864: String tooltip = (descending) ? "table.sort.augment.undeterminedDescending" //NOI18N
0865: : "table.sort.augment.undeterminedAscending"; //NOI18N
0866:
0867: // Append array of ascending sort order tooltips.
0868: StringBuffer buff = new StringBuffer(1024);
0869: buff.append("new Array('") //NOI18N
0870: .append(getTheme().getMessage(tooltip)).append("'"); //NOI18N
0871:
0872: // Use the first TableRowGroup child to obtain sort tool tip.
0873: TableRowGroup group = component.getTableRowGroupChild();
0874: if (group != null) {
0875: // For each TableColumn component, get the sort tool tip augment
0876: // based on the value for the align property of TableColumn.
0877: Iterator kids = group.getTableColumnChildren();
0878: while (kids.hasNext()) {
0879: TableColumn col = (TableColumn) kids.next();
0880: if (!col.isRendered()) {
0881: continue;
0882: }
0883: // Get tool tip augment.
0884: buff.append(",'")
0885: //NOI18N
0886: .append(col.getSortToolTipAugment(descending))
0887: .append("'"); //NOI18N
0888: }
0889: } else {
0890: log("getSortToolTipJavascript", //NOI18N
0891: "Cannot obtain Javascript array of sort tool tips, TableRowGroup is null"); //NOI18N
0892: }
0893: buff.append(")"); //NOI18N
0894: return buff.toString();
0895: }
0896:
0897: /**
0898: * Helper method to get table column footer style class for TableColumn
0899: * components.
0900: *
0901: * @param component TableColumn to be rendered.
0902: * @param level The current sort level.
0903: * @return The style class for the table column footer.
0904: */
0905: private String getTableColumnFooterStyleClass(
0906: TableColumn component, int level) {
0907: String styleClass = null;
0908:
0909: // Get appropriate style class.
0910: if (component.isSpacerColumn()) {
0911: styleClass = ThemeStyles.TABLE_COL_FOOTER_SPACER;
0912: } else if (level == 1) {
0913: styleClass = ThemeStyles.TABLE_COL_FOOTER_SORT;
0914: } else {
0915: styleClass = ThemeStyles.TABLE_COL_FOOTER;
0916: }
0917: return getTheme().getStyleClass(styleClass);
0918: }
0919:
0920: /** Helper method to get Theme objects. */
0921: private Theme getTheme() {
0922: return ThemeUtilities.getTheme(FacesContext
0923: .getCurrentInstance());
0924: }
0925:
0926: /**
0927: * Log fine messages.
0928: */
0929: private void log(String method, String message) {
0930: // Get class.
0931: Class clazz = this .getClass();
0932: if (LogUtil.fineEnabled(clazz)) {
0933: // Log method name and message.
0934: LogUtil.fine(clazz, clazz.getName() + "." + method + ": "
0935: + message); //NOI18N
0936: }
0937: }
0938:
0939: /**
0940: * Helper method to render Javascript to Table components.
0941: *
0942: * @param context FacesContext for the current request.
0943: * @param component Table to be rendered.
0944: * @param writer ResponseWriter to which the component should be rendered.
0945: *
0946: * @exception IOException if an input/output error occurs.
0947: */
0948: private void renderJavascript(FacesContext context,
0949: Table component, ResponseWriter writer) throws IOException {
0950: if (component == null) {
0951: log("renderJavascript",
0952: "Cannot render Javascript, Table is null"); //NOI18N
0953: return;
0954: }
0955:
0956: // Include table Javascript file.
0957: writer.writeText("\n", null); //NOI18N
0958: RenderingUtilities.renderJsInclude(context, component,
0959: getTheme(), writer, ThemeJavascript.TABLE);
0960:
0961: renderAssignFunctions(context, component, writer);
0962: renderAssignPanelProperties(context, component, writer);
0963: renderAssignFilterProperties(context, component, writer);
0964: renderAssignSortPanelProperties(context, component, writer);
0965: renderAssignGroupProperties(context, component, writer);
0966: renderAssignGroupPanelProperties(context, component, writer);
0967: }
0968:
0969: /**
0970: * Helper method to assign Javascript to Table components.
0971: *
0972: * @param context FacesContext for the current request.
0973: * @param component Table to be rendered.
0974: * @param writer ResponseWriter to which the component should be rendered.
0975: *
0976: * @exception IOException if an input/output error occurs.
0977: */
0978: private void renderAssignFunctions(FacesContext context,
0979: Table component, ResponseWriter writer) throws IOException {
0980: if (component == null) {
0981: log("renderAssignFunctions", //NOI18N
0982: "Cannot render assignFunctions Javascript function, Table is null"); //NOI18N
0983: return;
0984: }
0985:
0986: // Assign Javascript functions and properties.
0987: StringBuffer buff = new StringBuffer(1024);
0988: buff.append("sjwuic_table_assignFunctions('") //NOI18N
0989: .append(component.getClientId(context)).append("')"); //NOI18N
0990:
0991: writer.writeText("\n", null); //NOI18N
0992: writer.startElement("script", component); //NOI18N
0993: writer.writeAttribute("type", "text/javascript", null); //NOI18N
0994: writer.writeText(buff.toString(), null);
0995: writer.endElement("script"); //NOI18N
0996: }
0997:
0998: /**
0999: * Helper method to assign Javascript to Table components.
1000: *
1001: * @param context FacesContext for the current request.
1002: * @param component Table to be rendered.
1003: * @param writer ResponseWriter to which the component should be rendered.
1004: *
1005: * @exception IOException if an input/output error occurs.
1006: */
1007: private void renderAssignPanelProperties(FacesContext context,
1008: Table component, ResponseWriter writer) throws IOException {
1009: if (component == null) {
1010: log("renderAssignPanelProperties", //NOI18N
1011: "Cannot render assignProperties Javascript function, Table is null"); //NOI18N
1012: return;
1013: }
1014:
1015: // Don't invoke component.getEmbeddedPanels() here because it will
1016: // create new component instances which do not work with the action
1017: // listeners assigned to the rendered components.
1018: UIComponent panels = component
1019: .getFacet(Table.EMBEDDED_PANELS_ID);
1020: if (panels == null) {
1021: log(
1022: "renderAssignPanelProperties", //NOI18N
1023: "Cannot render assignProperties Javascript function, embedded panels facet is null"); //NOI18N
1024: return;
1025: }
1026:
1027: Theme theme = getTheme();
1028: String prefix = panels.getClientId(context)
1029: + NamingContainer.SEPARATOR_CHAR;
1030:
1031: // Assign Javascript functions and properties.
1032: StringBuffer buff = new StringBuffer(1024);
1033: buff.append("sjwuic_table_assignPanelProperties('") //NOI18N
1034: .append(component.getClientId(context)).append("'"); //NOI18N
1035:
1036: // Append array of panel Ids.
1037: buff.append(",new Array('")
1038: //NOI18N
1039: .append(prefix + TablePanels.SORT_PANEL_ID).append(
1040: "','")
1041: //NOI18N
1042: .append(prefix + TablePanels.PREFERENCES_PANEL_ID)
1043: .append("','") //NOI18N
1044: .append(prefix + TablePanels.FILTER_PANEL_ID).append(
1045: "')"); //NOI18N
1046:
1047: // Don't invoke component.getTableActionsTop() here because it will
1048: // create new component instances which do not work with the action
1049: // listeners assigned to the rendered components.
1050: UIComponent actions = component
1051: .getFacet(Table.TABLE_ACTIONS_TOP_ID);
1052: if (actions == null) {
1053: log("renderAssignPanelProperties", //NOI18N
1054: "Cannot render assignProperties Javascript function, actions top facet is null"); //NOI18N
1055: return;
1056: }
1057:
1058: // Append array of focus Ids.
1059: buff
1060: .append(",new Array('")
1061: //NOI18N
1062: .append(
1063: (component.getSortPanelFocusId() != null) ? component
1064: .getSortPanelFocusId()
1065: : prefix
1066: + TablePanels.PRIMARY_SORT_COLUMN_MENU_ID)
1067: .append("',") //NOI18N
1068: .append(
1069: (component.getPreferencesPanelFocusId() != null) ? "'"
1070: + component
1071: .getPreferencesPanelFocusId()
1072: + "'" //NOI18N
1073: : "null") //NOI18N
1074: .append(",") //NOI18N
1075: .append(
1076: (component.getFilterPanelFocusId() != null) ? "'"
1077: + component.getFilterPanelFocusId()
1078: + "'" //NOI18N
1079: : "null") //NOI18N
1080: .append(")"); //NOI18N
1081:
1082: prefix = actions.getClientId(context)
1083: + NamingContainer.SEPARATOR_CHAR;
1084:
1085: // Append array of panel toggle Ids.
1086: buff
1087: .append(",new Array('")
1088: //NOI18N
1089: .append(
1090: prefix
1091: + TableActions.SORT_PANEL_TOGGLE_BUTTON_ID)
1092: .append("','")
1093: //NOI18N
1094: .append(
1095: prefix
1096: + TableActions.PREFERENCES_PANEL_TOGGLE_BUTTON_ID)
1097: .append("','") //NOI18N
1098: .append(
1099: (component.getFilterId() != null) ? component
1100: .getFilterId() : "") //NOI18N
1101: .append("')"); //NOI18N
1102:
1103: // Append array of toggle icons for open panels.
1104: buff
1105: .append(",new Array('")
1106: //NOI18N
1107: .append(
1108: theme
1109: .getIcon(
1110: ThemeImages.TABLE_SORT_PANEL_FLIP)
1111: .getUrl())
1112: .append("','")
1113: //NOI18N
1114: .append(
1115: theme
1116: .getIcon(
1117: ThemeImages.TABLE_PREFERENCES_PANEL_FLIP)
1118: .getUrl()).append("', null)"); //NOI18N
1119:
1120: // Append array of toggle icons for closed panels.
1121: buff.append(",new Array('") //NOI18N
1122: .append(
1123: theme.getIcon(ThemeImages.TABLE_SORT_PANEL)
1124: .getUrl()).append("','") //NOI18N
1125: .append(
1126: theme.getIcon(
1127: ThemeImages.TABLE_PREFERENCES_PANEL)
1128: .getUrl()).append("', null))"); //NOI18N
1129:
1130: writer.writeText("\n", null); //NOI18N
1131: writer.startElement("script", component); //NOI18N
1132: writer.writeAttribute("type", "text/javascript", null); //NOI18N
1133: writer.writeText(buff.toString(), null);
1134: writer.endElement("script"); //NOI18N
1135: }
1136:
1137: /**
1138: * Helper method to assign Javascript to Table components.
1139: *
1140: * @param context FacesContext for the current request.
1141: * @param component Table to be rendered.
1142: * @param writer ResponseWriter to which the component should be rendered.
1143: *
1144: * @exception IOException if an input/output error occurs.
1145: */
1146: private void renderAssignFilterProperties(FacesContext context,
1147: Table component, ResponseWriter writer) throws IOException {
1148: if (component == null) {
1149: log("renderAssignFilterProperties", //NOI18N
1150: "Cannot render assignFilterProperties Javascript function, Table is null"); //NOI18N
1151: return;
1152: }
1153:
1154: Theme theme = getTheme();
1155:
1156: // Assign Javascript functions and properties.
1157: StringBuffer buff = new StringBuffer(1024);
1158: buff.append("sjwuic_table_assignFilterProperties('") //NOI18N
1159: .append(component.getClientId(context)).append("'"); //NOI18N
1160:
1161: // Append basic and custom filter menu style classes.
1162: buff
1163: .append(",'")
1164: //NOI18N
1165: .append(theme.getStyleClass(ThemeStyles.MENU_JUMP))
1166: .append("','")
1167: //NOI18N
1168: .append(
1169: theme
1170: .getStyleClass(ThemeStyles.TABLE_CUSTOM_FILTER_MENU))
1171: .append("'"); //NOI18N
1172:
1173: // Custom filter options.
1174: buff.append(",'") //NOI18N
1175: .append(Table.CUSTOM_FILTER).append("','") //NOI18N
1176: .append(Table.CUSTOM_FILTER_APPLIED).append("')"); //NOI18N
1177:
1178: writer.writeText("\n", null); //NOI18N
1179: writer.startElement("script", component); //NOI18N
1180: writer.writeAttribute("type", "text/javascript", null); //NOI18N
1181: writer.writeText(buff.toString(), null);
1182: writer.endElement("script"); //NOI18N
1183: }
1184:
1185: /**
1186: * Helper method to assign Javascript to Table components.
1187: *
1188: * @param context FacesContext for the current request.
1189: * @param component Table to be rendered.
1190: * @param writer ResponseWriter to which the component should be rendered.
1191: *
1192: * @exception IOException if an input/output error occurs.
1193: */
1194: private void renderAssignGroupProperties(FacesContext context,
1195: Table component, ResponseWriter writer) throws IOException {
1196: if (component == null) {
1197: log("renderAssignGroupProperties", //NOI18N
1198: "Cannot render assignGroupProperties Javascript function, Table is null"); //NOI18N
1199: return;
1200: }
1201:
1202: Theme theme = getTheme();
1203:
1204: // Assign Javascript functions and properties.
1205: StringBuffer buff = new StringBuffer(1024);
1206: buff.append("sjwuic_table_assignGroupProperties('") //NOI18N
1207: .append(component.getClientId(context)).append("'"); //NOI18N
1208:
1209: // Append select row style class.
1210: buff
1211: .append(",'")
1212: //NOI18N
1213: .append(
1214: theme
1215: .getStyleClass(ThemeStyles.TABLE_SELECT_ROW))
1216: .append("'"); //NOI18N
1217:
1218: // Append array of select IDs.
1219: buff.append(",new Array("); //NOI18N
1220: Iterator kids = component.getTableRowGroupChildren();
1221: while (kids.hasNext()) {
1222: TableRowGroup group = (TableRowGroup) kids.next();
1223:
1224: // Iterate over each TableColumn chlid to find selectId.
1225: String selectId = null;
1226: Iterator grandkids = group.getTableColumnChildren();
1227: while (grandkids.hasNext()) {
1228: TableColumn col = (TableColumn) grandkids.next();
1229: if (!col.isRendered()) {
1230: continue;
1231: }
1232: selectId = getSelectId(context, col);
1233: if (selectId != null) {
1234: break;
1235: }
1236: }
1237:
1238: // Append selectId, if applicable.
1239: buff.append("'") //NOI18N
1240: .append((selectId != null) ? selectId : "") //NOI18N
1241: .append("'"); //NOI18N
1242:
1243: // Append separator for next id.
1244: if (kids.hasNext()) {
1245: buff.append(","); //NOI18N
1246: }
1247: }
1248: buff.append(")"); //NOI18N
1249:
1250: // Append array of TableRowGroup IDs.
1251: buff.append(",new Array("); //NOI18N
1252: kids = component.getTableRowGroupChildren();
1253: while (kids.hasNext()) {
1254: TableRowGroup group = (TableRowGroup) kids.next();
1255: buff.append("'") //NOI18N
1256: .append(group.getClientId(context)).append("'"); //NOI18N
1257:
1258: // Append separator for next id.
1259: if (kids.hasNext()) {
1260: buff.append(","); //NOI18N
1261: }
1262: }
1263: buff.append(")"); //NOI18N
1264:
1265: // Append array of row IDs.
1266: buff.append(",new Array("); //NOI18N
1267: kids = component.getTableRowGroupChildren();
1268: while (kids.hasNext()) {
1269: TableRowGroup group = (TableRowGroup) kids.next();
1270: RowKey[] rowKeys = group.getRenderedRowKeys(); // Only rendered rows.
1271:
1272: // Append an array of row ids for each TableRowGroup child.
1273: if (rowKeys != null) {
1274: buff.append("new Array("); //NOI18N
1275: for (int i = 0; i < rowKeys.length; i++) {
1276: buff.append((i > 0) ? ",'" : "'") //NOI18N
1277: .append(rowKeys[i].getRowId()).append("'"); //NOI18N
1278: }
1279: buff.append(")"); //NOI18N
1280: } else {
1281: buff.append("null"); // TableRowGroup may have been empty. //NOI18N
1282: }
1283:
1284: // Append separator for next array.
1285: if (kids.hasNext()) {
1286: buff.append(","); //NOI18N
1287: }
1288: }
1289: buff.append(")"); //NOI18N
1290:
1291: // Append array of hidden selected row counts.
1292: buff.append(",new Array("); //NOI18N
1293: kids = component.getTableRowGroupChildren();
1294: while (kids.hasNext()) {
1295: TableRowGroup group = (TableRowGroup) kids.next();
1296:
1297: // Don't bother with calculations if this property is not set.
1298: if (component.isHiddenSelectedRows()) {
1299: buff.append("'")
1300: //NOI18N
1301: .append(
1302: Integer.toString(group
1303: .getHiddenSelectedRowsCount()))
1304: .append("'"); //NOI18N
1305: } else {
1306: // Note: Use chars; otherwise, a zero length array is created.
1307: buff.append("'0'"); //NOI18N
1308: }
1309:
1310: // Append separator for next array.
1311: if (kids.hasNext()) {
1312: buff.append(","); //NOI18N
1313: }
1314: }
1315: buff.append(")"); //NOI18N
1316:
1317: // Append confirm delete messages.
1318: buff
1319: .append(",'")
1320: //NOI18N
1321: .append(
1322: theme
1323: .getMessage("table.confirm.hiddenSelections")) //NOI18N
1324: .append("','") //NOI18N
1325: .append(
1326: theme
1327: .getMessage("table.confirm.totalSelections")) //NOI18N
1328: .append("','") //NOI18N
1329: .append(
1330: theme
1331: .getMessage("table.confirm.deleteSelections")) //NOI18N
1332: .append("')"); //NOI18N
1333:
1334: writer.writeText("\n", null); //NOI18N
1335: writer.startElement("script", component); //NOI18N
1336: writer.writeAttribute("type", "text/javascript", null); //NOI18N
1337: writer.writeText(buff.toString(), null);
1338: writer.endElement("script"); //NOI18N
1339: }
1340:
1341: /**
1342: * Helper method to assign Javascript to Table components.
1343: *
1344: * @param context FacesContext for the current request.
1345: * @param component Table to be rendered.
1346: * @param writer ResponseWriter to which the component should be rendered.
1347: *
1348: * @exception IOException if an input/output error occurs.
1349: */
1350: private void renderAssignGroupPanelProperties(FacesContext context,
1351: Table component, ResponseWriter writer) throws IOException {
1352: if (component == null) {
1353: log("renderAssignGroupPanelProperties", //NOI18N
1354: "Cannot render assignGroupPanelProperties Javascript function, Table is null"); //NOI18N
1355: return;
1356: }
1357:
1358: Theme theme = getTheme();
1359:
1360: // Assign Javascript functions and properties.
1361: StringBuffer buff = new StringBuffer(1024);
1362: buff.append("sjwuic_table_assignGroupPanelProperties('") //NOI18N
1363: .append(component.getClientId(context)).append("'"); //NOI18N
1364:
1365: // Append bar IDs.
1366: buff.append(",'")
1367: //NOI18N
1368: .append(TableRowGroup.COLUMN_FOOTER_BAR_ID).append(
1369: "','")
1370: //NOI18N
1371: .append(TableRowGroup.COLUMN_HEADER_BAR_ID).append(
1372: "','")
1373: //NOI18N
1374: .append(TableRowGroup.TABLE_COLUMN_FOOTER_BAR_ID)
1375: .append("','") //NOI18N
1376: .append(TableRowGroup.GROUP_FOOTER_BAR_ID).append("'"); //NOI18N
1377:
1378: // Get ID prefix for TableHeader components.
1379: String prefix = TableRowGroup.GROUP_HEADER_ID
1380: + NamingContainer.SEPARATOR_CHAR;
1381:
1382: // Append row group toggle button properties.
1383: buff
1384: .append(",'")
1385: //NOI18N
1386: .append(
1387: prefix
1388: + TableHeader.GROUP_PANEL_TOGGLE_BUTTON_ID)
1389: .append("','") //NOI18N
1390: .append(theme.getMessage("table.group.collapse")) //NOI18N
1391: .append("','") //NOI18N
1392: .append(theme.getMessage("table.group.expand")) //NOI18N
1393: .append("','") //NOI18N
1394: .append(
1395: theme.getIcon(
1396: ThemeImages.TABLE_GROUP_PANEL_FLIP)
1397: .getUrl()).append("','") //NOI18N
1398: .append(
1399: theme.getIcon(ThemeImages.TABLE_GROUP_PANEL)
1400: .getUrl()).append("'"); //NOI18N
1401:
1402: // Append warning icon properties.
1403: buff.append(",'")
1404: //NOI18N
1405: .append(prefix + TableHeader.WARNING_ICON_ID).append(
1406: "','")
1407: //NOI18N
1408: .append(getTheme().getIcon(ThemeImages.DOT).getUrl())
1409: .append("','") //NOI18N
1410: .append(
1411: getTheme().getIcon(
1412: ThemeImages.ALERT_WARNING_SMALL)
1413: .getUrl()).append("',") //NOI18N
1414: .append("null") //NOI18N -- No tooltip for place holder icon.
1415: .append(",'") //NOI18N
1416: .append(theme.getMessage("table.group.warning")) //NOI18N
1417: .append("'"); //NOI18N
1418:
1419: // Append collapsed hidden field properties.
1420: buff.append(",'")
1421: //NOI18N
1422: .append(prefix + TableHeader.COLLAPSED_HIDDEN_FIELD_ID)
1423: .append("'"); //NOI18N
1424:
1425: // Append select multiple toggle button properties.
1426: buff
1427: .append(",'")
1428: //NOI18N
1429: .append(
1430: prefix
1431: + TableHeader.SELECT_MULTIPLE_TOGGLE_BUTTON_ID)
1432: .append("','") //NOI18N
1433: .append(theme.getMessage("table.group.selectMultiple")) //NOI18N
1434: .append("','") //NOI18N
1435: .append(
1436: theme
1437: .getMessage("table.group.deselectMultiple")) //NOI18N
1438: .append("')"); //NOI18N
1439:
1440: writer.writeText("\n", null); //NOI18N
1441: writer.startElement("script", component); //NOI18N
1442: writer.writeAttribute("type", "text/javascript", null); //NOI18N
1443: writer.writeText(buff.toString(), null);
1444: writer.endElement("script"); //NOI18N
1445: }
1446:
1447: /**
1448: * Helper method to assign Javascript to Table components.
1449: *
1450: * @param context FacesContext for the current request.
1451: * @param component Table to be rendered.
1452: * @param writer ResponseWriter to which the component should be rendered.
1453: *
1454: * @exception IOException if an input/output error occurs.
1455: */
1456: private void renderAssignSortPanelProperties(FacesContext context,
1457: Table component, ResponseWriter writer) throws IOException {
1458: if (component == null) {
1459: log("renderAssignSortPanelProperties", //NOI18N
1460: "Cannot render assignSortPanelProperties Javascript function, Table is null"); //NOI18N
1461: return;
1462: }
1463:
1464: // Don't invoke component.getEmbeddedPanels() here because it will
1465: // create new component instances which do not work with the action
1466: // listeners assigned to the rendered components.
1467: UIComponent panels = component
1468: .getFacet(Table.EMBEDDED_PANELS_ID);
1469: if (panels == null) {
1470: log(
1471: "renderAssignSortPanelProperties", //NOI18N
1472: "Cannot render assignSortPanelProperties Javascript function, Embedded panels facet is null"); //NOI18N
1473: return;
1474: }
1475:
1476: Theme theme = getTheme();
1477: String prefix = panels.getClientId(context)
1478: + NamingContainer.SEPARATOR_CHAR;
1479:
1480: // Assign Javascript functions and properties.
1481: StringBuffer buff = new StringBuffer(1024);
1482: buff.append("sjwuic_table_assignSortPanelProperties('") //NOI18N
1483: .append(component.getClientId(context)).append("'"); //NOI18N
1484:
1485: // Append array of sort column menu Ids.
1486: buff
1487: .append(",new Array('")
1488: //NOI18N
1489: .append(
1490: prefix
1491: + TablePanels.PRIMARY_SORT_COLUMN_MENU_ID)
1492: .append("','")
1493: //NOI18N
1494: .append(
1495: prefix
1496: + TablePanels.SECONDARY_SORT_COLUMN_MENU_ID)
1497: .append("','")
1498: //NOI18N
1499: .append(
1500: prefix
1501: + TablePanels.TERTIARY_SORT_COLUMN_MENU_ID)
1502: .append("')"); //NOI18N
1503:
1504: // Append array of sort order menu Ids.
1505: buff
1506: .append(",new Array('")
1507: //NOI18N
1508: .append(prefix + TablePanels.PRIMARY_SORT_ORDER_MENU_ID)
1509: .append("','")
1510: //NOI18N
1511: .append(
1512: prefix
1513: + TablePanels.SECONDARY_SORT_ORDER_MENU_ID)
1514: .append("','")
1515: //NOI18N
1516: .append(
1517: prefix
1518: + TablePanels.TERTIARY_SORT_ORDER_MENU_ID)
1519: .append("')"); //NOI18N
1520:
1521: // Append array of ascending sort order tooltips.
1522: buff.append(",") //NOI18N
1523: .append(getSortToolTipJavascript(component, false));
1524:
1525: // Append array of descending sort order tooltips.
1526: buff.append(",") //NOI18N
1527: .append(getSortToolTipJavascript(component, true));
1528:
1529: // Append error messages.
1530: buff
1531: .append(",'")
1532: //NOI18N
1533: .append(
1534: theme
1535: .getMessage("table.panel.duplicateSelectionError")) //NOI18N
1536: .append("','") //NOI18N
1537: .append(
1538: theme
1539: .getMessage("table.panel.missingSelectionError")) //NOI18N
1540: .append("'"); //NOI18N
1541:
1542: // Append sort menu option value for select column and paginated flag.
1543: String value = getSelectSortMenuOptionValue(component);
1544: TableRowGroup group = component.getTableRowGroupChild();
1545: buff.append(",'") //NOI18N
1546: .append(value != null ? value : "null") //NOI18N
1547: .append("',") //NOI18N
1548: .append(component.isHiddenSelectedRows()).append(",") //NOI18N
1549: .append(
1550: group != null ? Boolean.toString(group
1551: .isPaginated()) : "false") //NOI18N
1552: .append(")"); //NOI18N
1553:
1554: writer.writeText("\n", null); //NOI18N
1555: writer.startElement("script", component); //NOI18N
1556: writer.writeAttribute("type", "text/javascript", null); //NOI18N
1557: writer.writeText(buff.toString(), null);
1558: writer.endElement("script"); //NOI18N
1559: }
1560: }
|