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.component;
0042:
0043: import com.sun.rave.web.ui.component.util.Util;
0044: import com.sun.rave.web.ui.event.TablePaginationActionListener;
0045: import com.sun.rave.web.ui.event.TableSortActionListener;
0046: import com.sun.rave.web.ui.model.Option;
0047: import com.sun.rave.web.ui.model.Separator;
0048: import com.sun.rave.web.ui.theme.Theme;
0049: import com.sun.rave.web.ui.theme.ThemeStyles;
0050: import com.sun.rave.web.ui.util.LogUtil;
0051: import com.sun.rave.web.ui.util.ThemeUtilities;
0052:
0053: import java.io.IOException;
0054: import java.util.ArrayList;
0055: import java.util.HashMap;
0056: import java.util.Iterator;
0057: import java.util.List;
0058: import java.util.Map;
0059:
0060: import javax.faces.context.ExternalContext;
0061: import javax.faces.context.FacesContext;
0062: import javax.faces.component.NamingContainer;
0063: import javax.faces.component.UIComponent;
0064:
0065: /**
0066: * Component that represents a table.
0067: *
0068: * The table component provides a layout mechanism for displaying table actions.
0069: * UI guidelines describe specific behavior that can applied to the rows and
0070: * columns of data such as sorting, filtering, pagination, selection, and custom
0071: * user actions. In addition, UI guidelines also define sections of the table
0072: * that can be used for titles, row group headers, and placement of pre-defined
0073: * and user defined actions.
0074: * <p>
0075: * Note: Column headers and footers are rendered by TableRowGroupRenderer. Table
0076: * column footers are rendered by TableRenderer.
0077: * </p><p>
0078: * Note: To see the messages logged by this class, set the following global
0079: * defaults in your JDK's "jre/lib/logging.properties" file.
0080: * </p><pre>
0081: * java.util.logging.ConsoleHandler.level = FINE
0082: * com.sun.rave.web.ui.component.Table.level = FINE
0083: * </pre><p>
0084: * See TLD docs for more information.
0085: * </p>
0086: */
0087: public class Table extends TableBase implements NamingContainer {
0088: /** The facet name for the bottom actions area. */
0089: public static final String ACTIONS_BOTTOM_FACET = "actionsBottom"; //NOI18N
0090:
0091: /** The facet name for top actions area. */
0092: public static final String ACTIONS_TOP_FACET = "actionsTop"; //NOI18N
0093:
0094: /** The value for the custom filter option. */
0095: public static final String CUSTOM_FILTER = "_customFilter"; //NOI18N
0096:
0097: /** The value for the custom filter applied option. */
0098: public static final String CUSTOM_FILTER_APPLIED = "_customFilterApplied"; //NOI18N
0099:
0100: /** The id for the embedded panels bar. */
0101: public static final String EMBEDDED_PANELS_BAR_ID = "_embeddedPanelsBar"; //NOI18N
0102:
0103: /** The component id for embedded panels. */
0104: public static final String EMBEDDED_PANELS_ID = "_embeddedPanels"; //NOI18N
0105:
0106: /** The facet name for embedded panels. */
0107: public static final String EMBEDDED_PANELS_FACET = "embeddedPanels"; //NOI18N
0108:
0109: /** The facet name for the filter area. */
0110: public static final String FILTER_FACET = "filter"; //NOI18N
0111:
0112: /** The facet name for the filter panel. */
0113: public static final String FILTER_PANEL_FACET = "filterPanel"; //NOI18N
0114:
0115: /** The facet name for the footer area. */
0116: public static final String FOOTER_FACET = "footer"; //NOI18N
0117:
0118: /** The facet name for the preferences panel. */
0119: public static final String PREFERENCES_PANEL_FACET = "preferencesPanel"; //NOI18N
0120:
0121: /** The facet name for the sort panel. */
0122: public static final String SORT_PANEL_FACET = "sortPanel"; //NOI18N
0123:
0124: /** The id for the table. */
0125: public static final String TABLE_ID = "_table"; //NOI18N
0126:
0127: /** The id for the bottom actions bar. */
0128: public static final String TABLE_ACTIONS_BOTTOM_BAR_ID = "_tableActionsBottomBar"; //NOI18N
0129:
0130: /** The component id for bottom actions. */
0131: public static final String TABLE_ACTIONS_BOTTOM_ID = "_tableActionsBottom"; //NOI18N
0132:
0133: /** The facet name for bottom actions. */
0134: public static final String TABLE_ACTIONS_BOTTOM_FACET = "tableActionsBottom"; //NOI18N
0135:
0136: /** The id for the top actions bar. */
0137: public static final String TABLE_ACTIONS_TOP_BAR_ID = "_tableActionsTopBar"; //NOI18N
0138:
0139: /** The component id for top actions. */
0140: public static final String TABLE_ACTIONS_TOP_ID = "_tableActionsTop"; //NOI18N
0141:
0142: /** The facet name for top actions. */
0143: public static final String TABLE_ACTIONS_TOP_FACET = "tableActionsTop"; //NOI18N
0144:
0145: /** The id for the table footer. */
0146: public static final String TABLE_FOOTER_BAR_ID = "_tableFooterBar"; //NOI18N
0147:
0148: /** The component id for the table footer. */
0149: public static final String TABLE_FOOTER_ID = "_tableFooter"; //NOI18N
0150:
0151: /** The facet name for the table footer. */
0152: public static final String TABLE_FOOTER_FACET = "tableFooter"; //NOI18N
0153:
0154: /** The id for the title bar. */
0155: public static final String TITLE_BAR_ID = "_titleBar"; //NOI18N
0156:
0157: /** The facet name for the title area. */
0158: public static final String TITLE_FACET = "title"; //NOI18N
0159:
0160: // Key prefix for properties cached in the request map.
0161: private static final String REQUEST_KEY_PREFIX = "com.sun.rave.web.ui_"; //NOI18N
0162:
0163: // Key for properties cached in the request map.
0164: private static final String PROPERTIES = "_properties"; //NOI18N
0165:
0166: /** Default constructor */
0167: public Table() {
0168: super ();
0169: }
0170:
0171: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0172: // Child methods
0173: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0174:
0175: /**
0176: * Get the number of column header bars for all TableRowGroup children.
0177: *
0178: * @return The number of column headers.
0179: */
0180: public int getColumnHeadersCount() {
0181: // Get properties cached in request map.
0182: Properties properties = getProperties();
0183: int columnHeadersCount = (properties != null) ? properties
0184: .getColumnHeadersCount() : -1;
0185:
0186: // Get column header count.
0187: if (columnHeadersCount == -1) {
0188: columnHeadersCount = 0; // Initialize min value.
0189:
0190: // Iterate over each TableRowGroup child to determine if each group
0191: // displays its own column header or if one column header is
0192: // dispalyed for all row groups.
0193: Iterator kids = getTableRowGroupChildren();
0194: while (kids.hasNext()) {
0195: TableRowGroup group = (TableRowGroup) kids.next();
0196: Iterator grandkids = group.getTableColumnChildren();
0197: while (grandkids.hasNext()) {
0198: TableColumn col = (TableColumn) grandkids.next();
0199: if (col.getHeaderText() != null) {
0200: columnHeadersCount++;
0201: break; // Break if at least one column header is found.
0202: }
0203: }
0204: }
0205: // Save property in request map.
0206: if (properties != null) {
0207: properties.setColumnHeadersCount(columnHeadersCount);
0208: }
0209: }
0210: return columnHeadersCount;
0211: }
0212:
0213: /**
0214: * Get the number of hidden selected rows for all TableRowGroup children.
0215: *
0216: * @return The number of hidden selected rows.
0217: */
0218: public int getHiddenSelectedRowsCount() {
0219: // Get properties cached in request map.
0220: Properties properties = getProperties();
0221: int hiddenSelectedRowsCount = (properties != null) ? properties
0222: .getHiddenSelectedRowsCount() : -1;
0223:
0224: // Get hidden selected rows count.
0225: if (hiddenSelectedRowsCount == -1) {
0226: hiddenSelectedRowsCount = 0; // Initialize min value.
0227: Iterator kids = getTableRowGroupChildren();
0228: while (kids.hasNext()) {
0229: TableRowGroup group = (TableRowGroup) kids.next();
0230: hiddenSelectedRowsCount += group
0231: .getHiddenSelectedRowsCount();
0232: }
0233: // Save property in request map.
0234: if (properties != null) {
0235: properties
0236: .setHiddenSelectedRowsCount(hiddenSelectedRowsCount);
0237: }
0238: }
0239: return hiddenSelectedRowsCount;
0240: }
0241:
0242: /**
0243: * Get the zero-relative row number of the first row to be displayed for
0244: * a paginated table for all TableRowGroup children.
0245: *
0246: * @return The first row to be displayed.
0247: */
0248: public int getFirst() {
0249: // Get properties cached in request map.
0250: Properties properties = getProperties();
0251: int first = (properties != null) ? properties.getFirst() : -1;
0252:
0253: // Get first row.
0254: if (first == -1) {
0255: first = 0; // Initialize min value.
0256: Iterator kids = getTableRowGroupChildren();
0257: while (kids.hasNext()) {
0258: TableRowGroup group = (TableRowGroup) kids.next();
0259: first += group.getFirst();
0260: }
0261: // Save property in request map.
0262: if (properties != null) {
0263: properties.setFirst(first);
0264: }
0265: }
0266: return first;
0267: }
0268:
0269: /**
0270: * Get the max number of pages for all TableRowGroup children.
0271: *
0272: * @return The max number of pages.
0273: */
0274: public int getPageCount() {
0275: // Get properties cached in request map.
0276: Properties properties = getProperties();
0277: int pageCount = (properties != null) ? properties
0278: .getPageCount() : -1;
0279:
0280: // Get page count.
0281: if (pageCount == -1) {
0282: pageCount = 1; // Initialize min value.
0283: Iterator kids = getTableRowGroupChildren();
0284: while (kids.hasNext()) {
0285: TableRowGroup group = (TableRowGroup) kids.next();
0286: int pages = group.getPages();
0287: if (pageCount < pages) {
0288: pageCount = pages;
0289: }
0290: }
0291: // Save property in request map.
0292: if (properties != null) {
0293: properties.setPageCount(pageCount);
0294: }
0295: }
0296: return pageCount;
0297: }
0298:
0299: /**
0300: * Get the number of rows to be displayed per page for a paginated table
0301: * for all TableRowGroup children.
0302: *
0303: * @return The number of rows to be displayed per page for a paginated table.
0304: */
0305: public int getRows() {
0306: // Get properties cached in request map.
0307: Properties properties = getProperties();
0308: int rows = (properties != null) ? properties.getRows() : -1;
0309:
0310: // Get rows per page.
0311: if (rows == -1) {
0312: rows = 0; // Initialize min value.
0313: Iterator kids = getTableRowGroupChildren();
0314: while (kids.hasNext()) {
0315: TableRowGroup group = (TableRowGroup) kids.next();
0316: rows += group.getRows();
0317: }
0318: // Save property in request map.
0319: if (properties != null) {
0320: properties.setRows(rows);
0321: }
0322: }
0323: return rows;
0324: }
0325:
0326: /**
0327: * Get the number of rows in the underlying TableDataProvider for all
0328: * TableRowGroup children.
0329: *
0330: * @return The number of rows.
0331: */
0332: public int getRowCount() {
0333: // Get properties cached in request map.
0334: Properties properties = getProperties();
0335: int rowCount = (properties != null) ? properties.getRowCount()
0336: : -1;
0337:
0338: // Get row count.
0339: if (rowCount == -1) {
0340: rowCount = 0; // Initialize min value.
0341: Iterator kids = getTableRowGroupChildren();
0342: while (kids.hasNext()) {
0343: TableRowGroup group = (TableRowGroup) kids.next();
0344: rowCount += group.getRowCount();
0345: }
0346: // Save property in request map.
0347: if (properties != null) {
0348: properties.setRowCount(rowCount);
0349: }
0350: }
0351: return rowCount;
0352: }
0353:
0354: /**
0355: * Get the max number of columns found for all TableRowGroup children.
0356: *
0357: * @return The max number of columns.
0358: */
0359: public int getColumnCount() {
0360: // Get properties cached in request map.
0361: Properties properties = getProperties();
0362: int columnCount = (properties != null) ? properties
0363: .getColumnCount() : -1;
0364:
0365: // Get column count.
0366: if (columnCount == -1) {
0367: columnCount = 1; // Initialize min value.
0368: Iterator kids = getTableRowGroupChildren();
0369: while (kids.hasNext()) {
0370: TableRowGroup group = (TableRowGroup) kids.next();
0371: int count = group.getColumnCount();
0372: if (columnCount < count) {
0373: columnCount = count;
0374: }
0375: }
0376: // Save property in request map.
0377: if (properties != null) {
0378: properties.setColumnCount(columnCount);
0379: }
0380: }
0381: return columnCount;
0382: }
0383:
0384: /**
0385: * Get the number of table column footer bars for all TableRowGroup children.
0386: *
0387: * @return The number of table column footers.
0388: */
0389: public int getTableColumnFootersCount() {
0390: // Get properties cached in request map.
0391: Properties properties = getProperties();
0392: int tableColumnFootersCount = (properties != null) ? properties
0393: .getTableColumnFootersCount() : -1;
0394:
0395: // Get table column footer count.
0396: if (tableColumnFootersCount == -1) {
0397: tableColumnFootersCount = 0; // Initialize min value.
0398:
0399: // Iterate over each TableRowGroup child to determine if each group
0400: // displays its own table column footer or if one table column
0401: // footer is dispalyed for all row groups.
0402: Iterator kids = getTableRowGroupChildren();
0403: while (kids.hasNext()) {
0404: TableRowGroup group = (TableRowGroup) kids.next();
0405: Iterator grandkids = group.getTableColumnChildren();
0406: while (grandkids.hasNext()) {
0407: TableColumn col = (TableColumn) grandkids.next();
0408: if (col.isRendered()
0409: && col.getTableFooterText() != null) {
0410: tableColumnFootersCount++;
0411: break; // Break if at least one table column footer is shown.
0412: }
0413: }
0414: }
0415: // Save property in request map.
0416: if (properties != null) {
0417: properties
0418: .setTableColumnFootersCount(tableColumnFootersCount);
0419: }
0420: }
0421: return tableColumnFootersCount;
0422: }
0423:
0424: /**
0425: * Get the first TableRowGroup child found for the specified component that
0426: * have a rendered property of true.
0427: *
0428: * @return The first TableRowGroup child found.
0429: */
0430: public TableRowGroup getTableRowGroupChild() {
0431: TableRowGroup group = null;
0432: Iterator kids = getTableRowGroupChildren();
0433: if (kids.hasNext()) {
0434: group = (TableRowGroup) kids.next();
0435: }
0436: return group;
0437: }
0438:
0439: /**
0440: * Get an Iterator over the TableRowGroup children found for this component.
0441: *
0442: * @return An Iterator over the TableRowGroup children.
0443: */
0444: public Iterator getTableRowGroupChildren() {
0445: // Get properties cached in request map.
0446: Properties properties = getProperties();
0447: List tableRowGroupChildren = (properties != null) ? properties
0448: .getTableRowGroupChildren() : null;
0449:
0450: // Get TableRowGroup children.
0451: if (tableRowGroupChildren == null) {
0452: tableRowGroupChildren = new ArrayList();
0453: Iterator kids = getChildren().iterator();
0454: while (kids.hasNext()) {
0455: UIComponent kid = (UIComponent) kids.next();
0456: if ((kid instanceof TableRowGroup)) {
0457: tableRowGroupChildren.add(kid);
0458: }
0459: }
0460: // Save property in request map.
0461: if (properties != null) {
0462: properties
0463: .setTableRowGroupChildren(tableRowGroupChildren);
0464: }
0465: }
0466: return tableRowGroupChildren.iterator();
0467: }
0468:
0469: /**
0470: * Get the number of child TableRowGroup components found for this component
0471: * that have a rendered property of true.
0472: *
0473: * @return The number of TableRowGroup children.
0474: */
0475: public int getTableRowGroupCount() {
0476: // Get properties cached in request map.
0477: Properties properties = getProperties();
0478: int tableRowGroupCount = (properties != null) ? properties
0479: .getTableRowGroupCount() : -1;
0480:
0481: // Get TableRowGroup children count.
0482: if (tableRowGroupCount == -1) {
0483: tableRowGroupCount = 0; // Initialize min value.
0484: Iterator kids = getTableRowGroupChildren();
0485: while (kids.hasNext()) {
0486: UIComponent kid = (UIComponent) kids.next();
0487: if (kid.isRendered()) {
0488: tableRowGroupCount++;
0489: }
0490: }
0491: // Save property in request map.
0492: if (properties != null) {
0493: properties.setTableRowGroupCount(tableRowGroupCount);
0494: }
0495: }
0496: return tableRowGroupCount;
0497: }
0498:
0499: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0500: // Action methods
0501: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0502:
0503: /**
0504: * Get bottom actions.
0505: *
0506: * @return The bottom actions.
0507: */
0508: public UIComponent getTableActionsBottom() {
0509: UIComponent facet = getFacet(TABLE_ACTIONS_BOTTOM_FACET);
0510: if (facet != null) {
0511: return facet;
0512: }
0513:
0514: // Get child.
0515: TableActions child = new TableActions();
0516: child.setId(TABLE_ACTIONS_BOTTOM_ID);
0517: child.setColSpan(getColumnCount());
0518: child.setExtraHtml(getExtraActionBottomHtml());
0519: child.setNoWrap(true);
0520: child.setActionsBottom(true);
0521:
0522: // We must determine if all TableRowGroup components are empty. Controls
0523: // are only hidden when all row groups are empty. Likewise, pagination
0524: // controls are only hidden when all groups fit on a single page.
0525: int totalRows = getRowCount();
0526: boolean emptyTable = (totalRows == 0);
0527: boolean singleRow = (totalRows == 1);
0528: boolean singlePage = (totalRows < getRows());
0529:
0530: // Get facets.
0531: UIComponent actions = getFacet(ACTIONS_BOTTOM_FACET);
0532:
0533: // Get flag indicating which facets to render.
0534: boolean renderActions = !emptyTable && !singleRow
0535: && actions != null && actions.isRendered();
0536:
0537: // Hide pagination controls when all rows fit on a page.
0538: boolean renderPaginationControls = !emptyTable && !singlePage
0539: && isPaginationControls();
0540:
0541: // Hide paginate button for a single row.
0542: boolean renderPaginateButton = !emptyTable && !singlePage
0543: && isPaginateButton();
0544:
0545: // Set rendered.
0546: if (!(renderActions || renderPaginationControls || renderPaginateButton)) {
0547: log("getTableActionsBottom", //NOI18N
0548: "Action bar not rendered, nothing to display"); //NOI18N
0549: child.setRendered(false);
0550: }
0551:
0552: // Save facet and return child.
0553: getFacets().put(child.getId(), child);
0554: return child;
0555: }
0556:
0557: /**
0558: * Get top actions.
0559: *
0560: * @return The top actions.
0561: */
0562: public UIComponent getTableActionsTop() {
0563: UIComponent facet = getFacet(TABLE_ACTIONS_TOP_FACET);
0564: if (facet != null) {
0565: return facet;
0566: }
0567:
0568: // Get child.
0569: TableActions child = new TableActions();
0570: child.setId(TABLE_ACTIONS_TOP_ID);
0571: child.setColSpan(getColumnCount());
0572: child.setExtraHtml(getExtraActionTopHtml());
0573: child.setNoWrap(true);
0574:
0575: // We must determine if all TableRowGroup components are empty. Controls
0576: // are only hidden when all row groups are empty. Likewise, pagination
0577: // controls are only hidden when all groups fit on a single page.
0578: int totalRows = getRowCount();
0579: boolean emptyTable = (totalRows == 0);
0580: boolean singleRow = (totalRows == 1);
0581: boolean singlePage = (totalRows < getRows());
0582:
0583: // Get facets.
0584: UIComponent actions = getFacet(ACTIONS_TOP_FACET);
0585: UIComponent filter = getFacet(FILTER_FACET);
0586: UIComponent sort = getFacet(SORT_PANEL_FACET);
0587: UIComponent prefs = getFacet(PREFERENCES_PANEL_FACET);
0588:
0589: // Flags indicating which facets to render.
0590: boolean renderActions = actions != null && actions.isRendered();
0591: boolean renderFilter = filter != null && filter.isRendered();
0592: boolean renderSort = sort != null && sort.isRendered();
0593: boolean renderPrefs = prefs != null && prefs.isRendered();
0594:
0595: // Hide sorting and pagination controls for an empty table or when there
0596: // is only a single row.
0597: boolean renderSelectMultipleButton = !emptyTable
0598: && isSelectMultipleButton();
0599: boolean renderDeselectMultipleButton = !emptyTable
0600: && isDeselectMultipleButton();
0601: boolean renderDeselectSingleButton = !emptyTable
0602: && isDeselectSingleButton();
0603: boolean renderClearTableSortButton = !emptyTable && !singleRow
0604: && isClearSortButton();
0605: boolean renderTableSortPanelToggleButton = !emptyTable
0606: && !singleRow
0607: && (isSortPanelToggleButton() || renderSort);
0608: boolean renderPaginateButton = !emptyTable && !singlePage
0609: && isPaginateButton();
0610:
0611: // Return if nothing is rendered.
0612: if (!(renderActions || renderFilter || renderPrefs
0613: || renderSelectMultipleButton
0614: || renderDeselectMultipleButton
0615: || renderDeselectSingleButton
0616: || renderClearTableSortButton
0617: || renderTableSortPanelToggleButton || renderPaginateButton)) {
0618: log("getTableActionsTop", //NOI18N
0619: "Action bar not rendered, nothing to display"); //NOI18N
0620: child.setRendered(false);
0621: }
0622:
0623: // Save facet and return child.
0624: getFacets().put(child.getId(), child);
0625: return child;
0626: }
0627:
0628: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0629: // Filter methods
0630: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0631:
0632: /**
0633: * Get the HTML element ID of the dropDown component used to display table
0634: * filter options.
0635: * <p>
0636: * Note: This is the fully qualified ID rendered in the outter tag enclosing
0637: * the HTML element. Required for Javascript functions to set the dropDown
0638: * styles when the embedded filter panel is opened and to reset the default
0639: * selected value when the panel is closed.
0640: * </p>
0641: * @return The HTML element ID of the filter menu.
0642: */
0643: public String getFilterId() {
0644: String filterId = super .getFilterId();
0645: if (filterId == null) {
0646: log("getFilterId",
0647: "filterId is null, using facet client ID"); //NOI18N
0648: UIComponent filter = getFacet(FILTER_FACET);
0649: filterId = (filter != null) ? filter
0650: .getClientId(getFacesContext()) : null;
0651: }
0652: return filterId;
0653: }
0654:
0655: /**
0656: * Get the "custom filter" options used for a table filter menu.
0657: * <p>
0658: * Note: UI guidelines state that a "Custom Filter" option should be added
0659: * to the filter menu, used to open the table filter panel. Thus, if the
0660: * CUSTOM_FILTER option is selected, Javascript invoked via the onChange
0661: * event will open the table filter panel.
0662: * </p><p>
0663: * UI guidelines also state that a "Custom Filter Applied" option should be
0664: * added to the filter menu, indicating that a custom filter has been
0665: * applied. In this scenario, set the selected property of the filter menu
0666: * as CUSTOM_FILTER_APPLIED. This selection should persist until another
0667: * menu option has been selected.
0668: * </p>
0669: * @param options An array of options to append to -- may be null.
0670: * @param customFilterApplied Flag indicating custom filter is applied.
0671: * @return A new array containing appended "custom filter" options.
0672: */
0673: static public Option[] getFilterOptions(Option[] options,
0674: boolean customFilterApplied) {
0675: FacesContext context = FacesContext.getCurrentInstance();
0676: Theme theme = ThemeUtilities.getTheme(context);
0677: ArrayList newOptions = new ArrayList();
0678:
0679: // Get old options.
0680: if (options != null) {
0681: for (int i = 0; i < options.length; i++) {
0682: newOptions.add(options[i]);
0683: }
0684: }
0685:
0686: // Add options separator.
0687: newOptions.add(new Separator());
0688:
0689: // Add custom filter applied option.
0690: if (customFilterApplied) {
0691: Option option = new Option(
0692: CUSTOM_FILTER_APPLIED,
0693: theme
0694: .getMessage("table.viewActions.customFilterApplied")); //NOI18N
0695: option.setDisabled(true);
0696: newOptions.add(option);
0697: }
0698:
0699: // Add custom filter option.
0700: newOptions.add(new Option(CUSTOM_FILTER, theme
0701: .getMessage("table.viewActions.customFilter"))); //NOI18N
0702:
0703: // Return options.
0704: Option[] result = new Option[newOptions.size()];
0705: return (Option[]) newOptions.toArray(result);
0706: }
0707:
0708: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0709: // Footer methods
0710: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0711:
0712: /**
0713: * Get table footer.
0714: *
0715: * @return The table footer.
0716: */
0717: public UIComponent getTableFooter() {
0718: UIComponent facet = getFacet(TABLE_FOOTER_FACET);
0719: if (facet != null) {
0720: return facet;
0721: }
0722:
0723: // Get child.
0724: TableFooter child = new TableFooter();
0725: child.setId(TABLE_FOOTER_ID);
0726: child.setColSpan(getColumnCount());
0727: child.setExtraHtml(getExtraFooterHtml());
0728: child.setTableFooter(true);
0729:
0730: // Set rendered.
0731: if (!(facet != null && facet.isRendered()
0732: || getFooterText() != null || isHiddenSelectedRows())) {
0733: // Note: Footer may be initialized to force rendering. This allows
0734: // developers to omit the footer text property for select columns.
0735: log("getTableFooter", //NOI18N
0736: "Table footer not rendered, nothing to display"); //NOI18N
0737: child.setRendered(false);
0738: }
0739:
0740: // Save facet and return child.
0741: getFacets().put(child.getId(), child);
0742: return child;
0743: }
0744:
0745: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0746: // Panel methods
0747: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0748:
0749: /**
0750: * Get embedded panels.
0751: *
0752: * @return The embedded panels.
0753: */
0754: public UIComponent getEmbeddedPanels() {
0755: UIComponent facet = getFacet(EMBEDDED_PANELS_FACET);
0756: if (facet != null) {
0757: return facet;
0758: }
0759:
0760: // Get child.
0761: TablePanels child = new TablePanels();
0762: child.setId(EMBEDDED_PANELS_ID);
0763: child.setColSpan(getColumnCount());
0764: child.setExtraHtml(getExtraPanelHtml());
0765: child.setNoWrap(true);
0766:
0767: // Get facets.
0768: UIComponent sort = getFacet(SORT_PANEL_FACET);
0769: UIComponent filter = getFacet(FILTER_PANEL_FACET);
0770: UIComponent prefs = getFacet(PREFERENCES_PANEL_FACET);
0771:
0772: // Set flags indicating which facets to render.
0773: boolean renderFilter = filter != null && filter.isRendered();
0774: boolean renderPrefs = prefs != null && prefs.isRendered();
0775: boolean renderSort = sort != null && sort.isRendered();
0776:
0777: // Set type of panel to render.
0778: child.setFilterPanel(renderFilter);
0779: child.setPreferencesPanel(renderPrefs);
0780:
0781: // Set rendered.
0782: if (!(renderFilter || renderSort || renderPrefs || isSortPanelToggleButton())) {
0783: log("getEmbeddedPanels", //NOI18N
0784: "Embedded panels not rendered, nothing to display"); //NOI18N
0785: child.setRendered(false);
0786: }
0787:
0788: // Save facet and return child.
0789: getFacets().put(child.getId(), child);
0790: return child;
0791: }
0792:
0793: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0794: // UIComponent methods
0795: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0796:
0797: /**
0798: * If the rendered property is true, render the begining of the current
0799: * state of this UIComponent to the response contained in the specified
0800: * FacesContext.
0801: *
0802: * If a Renderer is associated with this UIComponent, the actual encoding
0803: * will be delegated to Renderer.encodeBegin(FacesContext, UIComponent).
0804: *
0805: * @param context FacesContext for the current request.
0806: *
0807: * @exception IOException if an input/output error occurs while rendering.
0808: * @exception NullPointerException if FacesContext is null.
0809: */
0810: public void encodeBegin(FacesContext context) throws IOException {
0811: // No query data means the page is rendered for the first time and there
0812: // is no need to clear cached properties -- the lifecycle jumps right to
0813: // the renderResponse phase.
0814: Map requestParamMap = context.getExternalContext()
0815: .getRequestParameterMap();
0816: if (requestParamMap.size() != 0) {
0817: // Member variables may have been cached via the apply request
0818: // values, validate, and update phases and must be re-evaluated
0819: // during the render response phase. The underlying DataProvider may
0820: // have changed and TableRenderer may need new calculations for the
0821: // title and action bar.
0822: Map requestMap = context.getExternalContext()
0823: .getRequestMap();
0824: requestMap.put(REQUEST_KEY_PREFIX + getClientId(context)
0825: + PROPERTIES, null); // Clear all properties.
0826: } else {
0827: log("encodeBegin", //NOI18N
0828: "Properties not cleared, request parameter map size is zero"); //NOI18N
0829: }
0830:
0831: // Initialize the internal virtual form used by this component.
0832: if (isInternalVirtualForm()) {
0833: // Get Form component.
0834: Form form = (Form) Util.getForm(getFacesContext(), this );
0835: if (form != null) {
0836: // Create VirtualFormDescriptor object.
0837: String id = getClientId(context) + "_virtualForm"; //NOI18N
0838: Form.VirtualFormDescriptor descriptor = new Form.VirtualFormDescriptor(
0839: id);
0840: String wildSuffix = String
0841: .valueOf(NamingContainer.SEPARATOR_CHAR)
0842: + String.valueOf(Form.ID_WILD_CHAR);
0843: descriptor.setParticipatingIds(new String[] { getId()
0844: + wildSuffix });
0845: descriptor.setSubmittingIds(new String[] { getId()
0846: + wildSuffix });
0847:
0848: // Add virtual form.
0849: form.addInternalVirtualForm(descriptor);
0850: } else {
0851: log("encodeBegin", //NOI18N
0852: "Internal virtual form not set, form ancestor is null"); //NOI18N
0853: }
0854: }
0855: super .encodeBegin(context);
0856: }
0857:
0858: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0859: // Private methods
0860: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0861:
0862: /**
0863: * Get the properties for this component cached in the request map.
0864: * <p>
0865: * Note: Properties may have been cached via the apply request values,
0866: * validate, and update phases and must be initialized for the render
0867: * response phase. Table components are forced to reinitialize by setting
0868: * the cached properties map to null when the table title and actions bar
0869: * are rendered. New column and row counts are required each time the table
0870: * is redisplayed, for example.
0871: * </p>
0872: * @return The properties for this component.
0873: */
0874: private Properties getProperties() {
0875: // Get properties for all components.
0876: FacesContext context = getFacesContext();
0877: Map requestMap = context.getExternalContext().getRequestMap();
0878: String propertiesMapId = REQUEST_KEY_PREFIX
0879: + getClientId(context) + PROPERTIES;
0880: Map propertiesMap = (Map) requestMap.get(propertiesMapId);
0881: if (propertiesMap == null) {
0882: propertiesMap = new HashMap();
0883: requestMap.put(propertiesMapId, propertiesMap);
0884: }
0885:
0886: // Get properties for this component.
0887: String propertiesId = getClientId(context);
0888: Properties properties = (Properties) propertiesMap
0889: .get(propertiesId);
0890: if (properties == null) {
0891: properties = new Properties();
0892: propertiesMap.put(propertiesId, properties);
0893: }
0894:
0895: return properties;
0896: }
0897:
0898: /**
0899: * Log fine messages.
0900: */
0901: private void log(String method, String message) {
0902: // Get class.
0903: Class clazz = this .getClass();
0904: if (LogUtil.fineEnabled(clazz)) {
0905: // Log method name and message.
0906: LogUtil.fine(clazz, clazz.getName() + "." + method + ": "
0907: + message); //NOI18N
0908: }
0909: }
0910:
0911: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0912: // Inner classes
0913: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0914:
0915: /**
0916: * Object used to cache properties in the request.
0917: */
0918: private class Properties {
0919: // The number of column headers.
0920: private int columnHeadersCount = -1;
0921:
0922: // The number of hidden selected rows.
0923: private int hiddenSelectedRowsCount = -1;
0924:
0925: // The max number of pages.
0926: private int first = -1;
0927:
0928: // The max number of pages.
0929: private int pageCount = -1;
0930:
0931: // The number of rows to be displayed per page for a paginated table.
0932: private int rows = -1;
0933:
0934: // The number of rows.
0935: private int rowCount = -1;
0936:
0937: // The max number of columns.
0938: private int columnCount = -1;
0939:
0940: // The number of column footers.
0941: private int tableColumnFootersCount = -1;
0942:
0943: // A List containing TableRowGroup children.
0944: private List tableRowGroupChildren = null;
0945:
0946: // The number of TableRowGroup children.
0947: private int tableRowGroupCount = -1;
0948:
0949: /** Default constructor. */
0950: public Properties() {
0951: }
0952:
0953: /**
0954: * Get the number of column header bars for all TableRowGroup children.
0955: *
0956: * @return The number of column headers.
0957: */
0958: public int getColumnHeadersCount() {
0959: return columnHeadersCount;
0960: }
0961:
0962: /**
0963: * Set the number of column header bars for all TableRowGroup children.
0964: *
0965: * @param columnHeadersCount The number of column headers.
0966: */
0967: public void setColumnHeadersCount(int columnHeadersCount) {
0968: this .columnHeadersCount = columnHeadersCount;
0969: }
0970:
0971: /**
0972: * Get the number of hidden selected rows for all TableRowGroup children.
0973: *
0974: * @return The number of hidden selected rows.
0975: */
0976: public int getHiddenSelectedRowsCount() {
0977: return hiddenSelectedRowsCount;
0978: }
0979:
0980: /**
0981: * set the number of hidden selected rows for all TableRowGroup children.
0982: *
0983: * @param hiddenSelectedRowsCount The number of hidden selected rows.
0984: */
0985: public void setHiddenSelectedRowsCount(
0986: int hiddenSelectedRowsCount) {
0987: this .hiddenSelectedRowsCount = hiddenSelectedRowsCount;
0988: }
0989:
0990: /**
0991: * Get the zero-relative row number of the first row to be displayed for
0992: * a paginated table for all TableRowGroup children.
0993: *
0994: * @return The max number of pages.
0995: */
0996: public int getFirst() {
0997: return first;
0998: }
0999:
1000: /**
1001: * Set the zero-relative row number of the first row to be displayed for
1002: * a paginated table for all TableRowGroup children.
1003: *
1004: * @param first The max number of pages.
1005: */
1006: public void setFirst(int first) {
1007: this .first = first;
1008: }
1009:
1010: /**
1011: * Get the max number of pages for all TableRowGroup children.
1012: *
1013: * @return The max number of pages.
1014: */
1015: public int getPageCount() {
1016: return pageCount;
1017: }
1018:
1019: /**
1020: * Get the max number of pages for all TableRowGroup children.
1021: *
1022: * @return The max number of pages.
1023: */
1024: public void setPageCount(int pageCount) {
1025: this .pageCount = pageCount;
1026: }
1027:
1028: /**
1029: * Get the number of rows to be displayed per page for a paginated table
1030: * for all TableRowGroup children.
1031: *
1032: * @return The number of rows to be displayed per page for a paginated table.
1033: */
1034: public int getRows() {
1035: return rows;
1036: }
1037:
1038: /**
1039: * Set the number of rows to be displayed per page for a paginated table
1040: * for all TableRowGroup children.
1041: *
1042: * @param rows The number of rows to be displayed per page for a paginated table.
1043: */
1044: public void setRows(int rows) {
1045: this .rows = rows;
1046: }
1047:
1048: /**
1049: * Get the number of rows for all TableRowGroup children.
1050: *
1051: * @return The number of rows.
1052: */
1053: public int getRowCount() {
1054: return rowCount;
1055: }
1056:
1057: /**
1058: * Set the number of rows for all TableRowGroup children.
1059: *
1060: * @param rowCount The number of rows.
1061: */
1062: public void setRowCount(int rowCount) {
1063: this .rowCount = rowCount;
1064: }
1065:
1066: /**
1067: * Get the max number of columns found for all TableRowGroup children.
1068: *
1069: * @return The max number of columns.
1070: */
1071: public int getColumnCount() {
1072: return columnCount;
1073: }
1074:
1075: /**
1076: * Set the max number of columns found for all TableRowGroup children.
1077: *
1078: * @param columnCount The max number of columns.
1079: */
1080: public void setColumnCount(int columnCount) {
1081: this .columnCount = columnCount;
1082: }
1083:
1084: /**
1085: * Get the number of table column footer bars for all TableRowGroup children.
1086: *
1087: * @return The number of column footers.
1088: */
1089: public int getTableColumnFootersCount() {
1090: return tableColumnFootersCount;
1091: }
1092:
1093: /**
1094: * Set the number of table column footer bars for all TableRowGroup children.
1095: *
1096: * @param tableColumnFootersCount The number of column footers.
1097: */
1098: public void setTableColumnFootersCount(
1099: int tableColumnFootersCount) {
1100: this .tableColumnFootersCount = tableColumnFootersCount;
1101: }
1102:
1103: /**
1104: * Get the TableRowGroup children found for this component.
1105: *
1106: * @return The TableRowGroup children.
1107: */
1108: public List getTableRowGroupChildren() {
1109: return tableRowGroupChildren;
1110: }
1111:
1112: /**
1113: * Set the TableRowGroup children found for this component.
1114: *
1115: * @param tableRowGroupChildren The TableRowGroup children.
1116: */
1117: public void setTableRowGroupChildren(List tableRowGroupChildren) {
1118: this .tableRowGroupChildren = tableRowGroupChildren;
1119: }
1120:
1121: /**
1122: * Get the number of child TableRowGroup components found for this component
1123: * that have a rendered property of true.
1124: *
1125: * @return The number of TableRowGroup children.
1126: */
1127: public int getTableRowGroupCount() {
1128: return tableRowGroupCount;
1129: }
1130:
1131: /**
1132: * Set the number of child TableRowGroup components found for this component
1133: * that have a rendered property of true.
1134: *
1135: * @param tableRowGroupCount The number of TableRowGroup children.
1136: */
1137: public void setTableRowGroupCount(int tableRowGroupCount) {
1138: this.tableRowGroupCount = tableRowGroupCount;
1139: }
1140: }
1141: }
|