001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: HtmlTableRenderer.java,v 1.15 2007/03/27 21:59:43 mlipp Exp $
021: *
022: * $Log: HtmlTableRenderer.java,v $
023: * Revision 1.15 2007/03/27 21:59:43 mlipp
024: * Fixed lots of checkstyle warnings.
025: *
026: * Revision 1.14 2007/02/27 10:56:59 drmlipp
027: * Really fixed problems with decreasing table.
028: *
029: * Revision 1.13 2007/02/26 22:12:28 mlipp
030: * Updated to MyFaces core 1.1.5/Tomahawk 1.1.3.
031: *
032: * Revision 1.12 2007/02/25 21:45:23 mlipp
033: * Fixed comparison.
034: *
035: * Revision 1.11 2007/02/25 20:40:28 mlipp
036: * Workaround for reduced model size.
037: *
038: * Revision 1.10 2006/12/12 09:55:30 drmlipp
039: * Cleaned up imports.
040: *
041: * Revision 1.9 2006/11/01 16:15:33 mlipp
042: * Make our JSF components depend on tomahawk only.
043: *
044: * Revision 1.8 2006/09/29 12:32:09 drmlipp
045: * Consistently using WfMOpen as projct name now.
046: *
047: * Revision 1.7 2006/09/01 11:14:38 drmlipp
048: * Fixed exceeding row index problem.
049: *
050: * Revision 1.6 2006/08/30 21:02:46 mlipp
051: * Updated MyFaces to 1.1.5-SNAPSHOT.
052: *
053: * Revision 1.5 2006/08/30 11:53:50 drmlipp
054: * Adapted to MyFaces 1.1.3.
055: *
056: * Revision 1.4 2006/08/28 21:22:44 mlipp
057: * Updated MyFaces to 1.1.3.
058: *
059: * Revision 1.3 2005/10/27 15:02:47 drmlipp
060: * Finshed rowspan/colspan support.
061: *
062: * Revision 1.2 2005/10/26 21:24:02 mlipp
063: * Type fixes.
064: *
065: * Revision 1.1 2005/10/26 15:31:36 drmlipp
066: * Extended table implementation continued.
067: *
068: */
069: package de.danet.an.util.jsf.taglib;
070:
071: import java.io.IOException;
072: import java.util.HashMap;
073: import java.util.List;
074: import java.util.Map;
075:
076: import javax.faces.component.UIColumn;
077: import javax.faces.component.UIComponent;
078: import javax.faces.component.UIData;
079: import javax.faces.context.FacesContext;
080: import javax.faces.context.ResponseWriter;
081:
082: import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
083:
084: /**
085: * A HTML table renderer that handles rowspan and colspan.
086: * @author lipp
087: */
088: public class HtmlTableRenderer extends
089: org.apache.myfaces.renderkit.html.ext.HtmlTableRenderer {
090:
091: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
092: .getLog(HtmlTableRenderer.class);
093:
094: /**
095: * Renders everything inside the TBODY tag by iterating over the row objects
096: * between offsets first and first+rows and applying the UIColumn components
097: * to those objects.
098: * <p>
099: * This method is separated from the encodeChildren so that it can be
100: * overridden by subclasses. One class that uses this functionality is
101: * autoUpdateDataTable.
102: */
103: public void encodeInnerHtml(FacesContext facesContext,
104: UIComponent component) throws IOException {
105:
106: UIData uiData = (UIData) component;
107: ResponseWriter writer = facesContext.getResponseWriter();
108:
109: // begin the table
110: // get the CSS styles
111: Styles styles = getStyles(uiData);
112:
113: int first = uiData.getFirst();
114: int rows = uiData.getRows();
115: int rowCount = uiData.getRowCount();
116: int last;
117: if (rows <= 0) {
118: last = rowCount;
119: } else {
120: last = first + rows;
121: if (last > rowCount) {
122: last = rowCount;
123: }
124: }
125:
126: String repetitionCounterVar = ((HtmlExtendedDataTable) component)
127: .getRepetitionCounter();
128: int repetitionCounter = 0;
129: int repetitions = 0; // force new row
130: Map rowspansCounters = new HashMap();
131:
132: // walk through the rows
133: for (int i = first; i < last; i++, repetitionCounter++) {
134: if (repetitionCounter < repetitions) {
135: // repeat row, i.e. undo increment
136: i -= 1;
137: } else {
138: // new row
139: uiData.setRowIndex(i);
140: if (!uiData.isRowAvailable()) {
141: logger.error("Row is not available. Rowindex = "
142: + i);
143: return;
144: }
145: repetitionCounter = 0;
146: Long rv = ((HtmlExtendedDataTable) component)
147: .getRepetitions();
148: repetitions = (rv == null ? 1 : rv.intValue());
149: }
150: if (repetitionCounterVar != null) {
151: facesContext.getExternalContext().getRequestMap().put(
152: repetitionCounterVar,
153: new Integer(repetitionCounter));
154: }
155:
156: beforeRow(facesContext, uiData);
157:
158: HtmlRendererUtils.writePrettyLineSeparator(facesContext);
159: renderRowStart(facesContext, writer, uiData, styles, i);
160:
161: // bail if any row does not exist
162: uiData.setRowIndex(i);
163: if (!uiData.isRowAvailable()) {
164: logger.error("Row is not available. Rowindex = " + i);
165: return;
166: }
167:
168: List children = getChildren(component);
169: long colSkipCounter = 0;
170: for (int j = 0, size = getChildCount(component); j < size; j++) {
171: UIComponent child = (UIComponent) children.get(j);
172: if (!child.isRendered()) {
173: continue;
174: }
175: Long rowspanCounter = (Long) rowspansCounters
176: .get(child);
177: long rsc = (rowspanCounter == null ? 0 : rowspanCounter
178: .longValue());
179: boolean encode = false;
180: if (rsc > 1) {
181: // skipped due to previous rowspan
182: rowspansCounters.put(child, new Long(rsc - 1));
183: } else {
184: if (rowspanCounter != null) {
185: rowspansCounters.remove(child);
186: }
187: // encode unless skipped due to colspan
188: encode = (colSkipCounter == 0);
189: }
190: if (encode) {
191: boolean columnRendering = child instanceof UIColumn;
192: if (columnRendering) {
193: beforeColumn(facesContext, uiData, j);
194: }
195: encodeColumnChild(facesContext, writer, uiData,
196: child, styles, j);
197: if (child instanceof HtmlExtendedColumn) {
198: // get new colspan/rowspan values
199: HtmlExtendedColumn xCol = (HtmlExtendedColumn) child;
200: if (xCol.getRowspan() != null
201: && Long.parseLong(xCol.getRowspan()) > 1) {
202: rowspansCounters.put(child, new Long(xCol
203: .getRowspan()));
204: }
205: if (xCol.getColspan() != null
206: && Long.parseLong(xCol.getColspan()) > 1) {
207: colSkipCounter = Long.parseLong(xCol
208: .getColspan());
209: }
210: }
211: if (columnRendering) {
212: afterColumn(facesContext, uiData, j);
213: }
214: }
215: if (colSkipCounter > 0) {
216: colSkipCounter -= 0;
217: }
218: }
219: renderRowEnd(facesContext, writer, uiData);
220: afterRow(facesContext, uiData);
221: }
222: }
223:
224: /**
225: * @param writer
226: * @param uiComponent
227: * @param prefix header, footer or null
228: * @throws IOException
229: */
230: protected void renderHtmlColumnAttributes(ResponseWriter writer,
231: UIComponent uiComponent, String prefix) throws IOException {
232: super .renderHtmlColumnAttributes(writer, uiComponent, prefix);
233:
234: HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
235: prefix != null ? prefix + "colspan" : "colspan",
236: "colspan");
237: HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
238: "rowspan", "rowspan");
239: }
240: }
|