KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > custom > newspaper > HtmlNewspaperTableRenderer


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.custom.newspaper;
17
18 import javax.faces.component.UIComponent;
19 import javax.faces.context.FacesContext;
20 import javax.faces.component.html.HtmlDataTable;
21 import javax.faces.context.ResponseWriter;
22 import javax.faces.component.UIColumn;
23 import javax.faces.component.UIData;
24 import org.apache.myfaces.renderkit.JSFAttr;
25 import org.apache.myfaces.renderkit.RendererUtils;
26 import org.apache.myfaces.renderkit.html.HtmlRendererUtils;
27 import org.apache.myfaces.renderkit.html.HTML;
28 import org.apache.myfaces.renderkit.html.HtmlTableRendererBase;
29 import org.apache.myfaces.util.ArrayUtils;
30 import org.apache.myfaces.util.StringUtils;
31 import java.io.IOException JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 /**
38  * Renderer for a table in multiple balanced columns.
39  *
40  * @author <a HREF="mailto:jesse@odel.on.ca">Jesse Wilson</a>
41  */

42 public class HtmlNewspaperTableRenderer
43         extends HtmlTableRendererBase
44 {
45     private static final Log log = LogFactory.getLog(HtmlNewspaperTableRenderer.class);
46
47     public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException JavaDoc {
48         RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
49         ResponseWriter writer = facesContext.getResponseWriter();
50         HtmlNewspaperTable newspaperTable = (HtmlNewspaperTable)uiComponent;
51         
52         // write out the table start tag
53
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
54         writer.startElement(HTML.TABLE_ELEM, newspaperTable);
55         writer.writeAttribute(HTML.ID_ATTR, newspaperTable.getClientId(facesContext), null);
56         HtmlRendererUtils.renderHTMLAttributes(writer, newspaperTable, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
57
58         // render the header
59
renderFacet(facesContext, writer, newspaperTable, true);
60     }
61     
62     public void encodeChildren(FacesContext facesContext, UIComponent uiComponent) throws IOException JavaDoc {
63         RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
64         ResponseWriter writer = facesContext.getResponseWriter();
65         HtmlNewspaperTable newspaperTable = (HtmlNewspaperTable)uiComponent;
66         
67         // begin the table
68
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
69         writer.startElement(HTML.TBODY_ELEM, newspaperTable);
70         
71         // get the CSS styles
72
Styles styles = getStyles(newspaperTable);
73
74         // count the number of actual rows
75
int first = newspaperTable.getFirst();
76         int rows = newspaperTable.getRows();
77         int rowCount = newspaperTable.getRowCount();
78         if(rows <= 0) {
79             rows = rowCount - first;
80         }
81         int last = first + rows;
82         if(last > rowCount) last = rowCount;
83         
84         // the number of slices to break the table up into */
85
int newspaperColumns = newspaperTable.getNewspaperColumns();
86         int newspaperRows;
87         if((last - first) % newspaperColumns == 0) newspaperRows = (last - first) / newspaperColumns;
88         else newspaperRows = ((last - first) / newspaperColumns) + 1;
89
90         // walk through the newspaper rows
91
for(int nr = 0; nr < newspaperRows; nr++) {
92
93             // write the row start
94
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
95             writer.startElement(HTML.TR_ELEM, newspaperTable);
96             if(styles.hasRowStyle()) {
97                 String JavaDoc rowStyle = styles.getRowStyle(nr);
98                 writer.writeAttribute(HTML.CLASS_ATTR, rowStyle, null);
99             }
100
101             // walk through the newspaper columns
102
for(int nc = 0; nc < newspaperColumns; nc++) {
103
104                 // the current row in the 'real' table
105
int currentRow = nc * newspaperRows + nr + first;
106                 
107                 // if this row is not to be rendered
108
if(currentRow >= last) continue;
109
110                 // bail if any row does not exist
111
newspaperTable.setRowIndex(currentRow);
112                 if(!newspaperTable.isRowAvailable()) {
113                     log.error("Row is not available. Rowindex = " + currentRow);
114                     return;
115                 }
116     
117                 // write each cell
118
List JavaDoc children = newspaperTable.getChildren();
119                 for(int j = 0; j < newspaperTable.getChildCount(); j++) {
120                     // skip this child if its not a rendered column
121
UIComponent child = (UIComponent)children.get(j);
122                     if(!(child instanceof UIColumn)) continue;
123                     UIColumn column = (UIColumn)child;
124                     if(!child.isRendered()) continue;
125                     // draw the element's cell
126
writer.startElement(HTML.TD_ELEM, newspaperTable);
127                     if(styles.hasColumnStyle()) writer.writeAttribute(HTML.CLASS_ATTR, styles.getColumnStyle(j), null);
128                     RendererUtils.renderChild(facesContext, child);
129                     writer.endElement(HTML.TD_ELEM);
130                 }
131
132                 // draw the spacer facet
133
if(nc < newspaperColumns - 1) renderSpacerCell(facesContext, writer, newspaperTable);
134             }
135             // write the row end
136
writer.endElement(HTML.TR_ELEM);
137         }
138         
139         // write the end of the table's body
140
writer.endElement(HTML.TBODY_ELEM);
141     }
142     
143     /**
144      * Fetch the number of columns to divide the table into.
145      */

146     private int getNewspaperColumns() {
147         return 3;
148     }
149
150     public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException JavaDoc {
151         RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
152         ResponseWriter writer = facesContext.getResponseWriter();
153         HtmlNewspaperTable newspaperTable = (HtmlNewspaperTable)uiComponent;
154         
155         // render the footer
156
renderFacet(facesContext, writer, newspaperTable, false);
157         
158         // write out the table end tag
159
writer.endElement(HTML.TABLE_ELEM);
160         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
161     }
162
163     
164     /**
165      * Count the number of columns in the speicifed Newspaper table..
166      */

167     private int countColumns(HtmlNewspaperTable newspaperTable) {
168         int columnCount = 0;
169         for(Iterator JavaDoc it = newspaperTable.getChildren().iterator(); it.hasNext(); ) {
170             UIComponent uiComponent = (UIComponent)it.next();
171             if (uiComponent instanceof UIColumn && ((UIColumn)uiComponent).isRendered()) {
172                 columnCount++;
173             }
174         }
175         return columnCount;
176     }
177     
178     /**
179      * Tests if the specified facet exists for the specified newspaper table.
180      */

181     private boolean hasFacet(HtmlNewspaperTable newspaperTable, boolean header) {
182         for(Iterator JavaDoc it = newspaperTable.getChildren().iterator(); it.hasNext(); ) {
183             // get the column
184
UIComponent uiComponent = (UIComponent)it.next();
185             if(!(uiComponent instanceof UIColumn)) continue;
186             UIColumn column = (UIColumn)uiComponent;
187             if(!column.isRendered()) continue;
188             
189             // test the facet
190
if(header && ((UIColumn)uiComponent).getHeader() != null) return true;
191             if(!header && ((UIColumn)uiComponent).getFooter() != null) return true;
192         }
193         return false;
194     }
195
196     /**
197      * Render table headers and footers.
198      */

199     private void renderFacet(FacesContext facesContext, ResponseWriter writer, HtmlNewspaperTable newspaperTable, boolean header) throws IOException JavaDoc {
200         int columnCount = countColumns(newspaperTable);
201         boolean hasColumnFacet = hasFacet(newspaperTable, header);
202         UIComponent facet = header ? newspaperTable.getHeader() : newspaperTable.getFooter();
203         
204         // quit if there's nothing to draw
205
if(facet == null && !hasColumnFacet) return;
206         
207         // start the row block
208
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
209         String JavaDoc elemName = header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM;
210         writer.startElement(elemName, newspaperTable);
211         
212         // fetch the style
213
String JavaDoc styleClass;
214         if(header) styleClass = getHeaderClass(newspaperTable);
215         else styleClass = getFooterClass(newspaperTable);
216         
217         // write the header row and column headers
218
if(header) {
219             if (facet != null) renderTableHeaderOrFooterRow(facesContext, writer, newspaperTable, facet, styleClass, HTML.TD_ELEM, columnCount);
220             if (hasColumnFacet) renderColumnHeaderOrFooterRow(facesContext, writer, newspaperTable, styleClass, header);
221         // write the footer row and column footers
222
} else {
223             if (hasColumnFacet) renderColumnHeaderOrFooterRow(facesContext, writer, newspaperTable, styleClass, header);
224             if (facet != null) renderTableHeaderOrFooterRow(facesContext, writer, newspaperTable, facet, styleClass, HTML.TD_ELEM, columnCount);
225         }
226         
227         // end the row block
228
writer.endElement(elemName);
229     }
230     
231     /**
232      * Renders the table header or footer row. This is one giant cell that spans
233      * the entire table header or footer.
234      */

235     private void renderTableHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer,
236         HtmlNewspaperTable newspaperTable, UIComponent facet, String JavaDoc styleClass, String JavaDoc colElementName, int tableColumns)
237         throws IOException JavaDoc {
238
239         // start the row
240
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
241         writer.startElement(HTML.TR_ELEM, newspaperTable);
242         writer.startElement(colElementName, newspaperTable);
243         if(styleClass != null) writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
244         if(colElementName.equals(HTML.TH_ELEM)) writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_COLGROUP_VALUE, null);
245
246         // span all the table's columns
247
int totalColumns = newspaperTable.getNewspaperColumns() * tableColumns;
248         if(newspaperTable.getSpacer() != null) totalColumns = totalColumns + getNewspaperColumns() - 1;
249         writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer JavaDoc(totalColumns), null);
250
251         // write the actual cell contents
252
if(facet != null) RendererUtils.renderChild(facesContext, facet);
253         
254         // finish
255
writer.endElement(colElementName);
256         writer.endElement(HTML.TR_ELEM);
257     }
258
259
260     /**
261      * Renders the column header or footer row.
262      */

263     private void renderColumnHeaderOrFooterRow(FacesContext facesContext,
264         ResponseWriter writer, HtmlNewspaperTable newspaperTable, String JavaDoc styleClass, boolean header)
265         throws IOException JavaDoc {
266
267         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
268         writer.startElement(HTML.TR_ELEM, newspaperTable);
269         int newspaperColumns = newspaperTable.getNewspaperColumns();
270         for(int nc = 0; nc < newspaperColumns; nc++) {
271             for(Iterator JavaDoc it = newspaperTable.getChildren().iterator(); it.hasNext(); ) {
272                 UIComponent uiComponent = (UIComponent)it.next();
273                 if(!(uiComponent instanceof UIColumn)) continue;
274                 UIColumn column = (UIColumn)uiComponent;
275                 if(!column.isRendered()) continue;
276                 // get the component to render
277
UIComponent facet = null;
278                 if(header) facet = column.getHeader();
279                 else facet = column.getFooter();
280                 // do the rendering of the cells
281
renderColumnHeaderOrFooterCell(facesContext, writer, column, styleClass, facet);
282             }
283
284             // draw the spacer facet
285
if(nc < newspaperColumns - 1) renderSpacerCell(facesContext, writer, newspaperTable);
286         }
287         writer.endElement(HTML.TR_ELEM);
288     }
289
290     /**
291      * Renders a cell in the column header or footer.
292      */

293     private void renderColumnHeaderOrFooterCell(FacesContext facesContext, ResponseWriter writer,
294         UIColumn uiColumn, String JavaDoc styleClass, UIComponent facet) throws IOException JavaDoc {
295
296         writer.startElement(HTML.TH_ELEM, uiColumn);
297         if(styleClass != null) writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
298         if(facet != null) RendererUtils.renderChild(facesContext, facet);
299         writer.endElement(HTML.TH_ELEM);
300     }
301     
302     /**
303      * Renders a spacer between adjacent newspaper columns.
304      */

305     private void renderSpacerCell(FacesContext facesContext, ResponseWriter writer,
306         HtmlNewspaperTable newspaperTable) throws IOException JavaDoc {
307         if(newspaperTable.getSpacer() == null) return;
308         
309         writer.startElement(HTML.TD_ELEM, newspaperTable);
310         RendererUtils.renderChild(facesContext, newspaperTable.getSpacer());
311         writer.endElement(HTML.TD_ELEM);
312     }
313
314     /**
315      * Gets the style class for the table header.
316      */

317     private static String JavaDoc getHeaderClass(HtmlNewspaperTable newspaperTable) {
318         if(newspaperTable instanceof HtmlDataTable) {
319             return ((HtmlDataTable)newspaperTable).getHeaderClass();
320         } else {
321             return (String JavaDoc)newspaperTable.getAttributes().get(JSFAttr.HEADER_CLASS_ATTR);
322         }
323     }
324     /**
325      * Gets the style class for the table footer.
326      */

327     private static String JavaDoc getFooterClass(HtmlNewspaperTable newspaperTable) {
328         if(newspaperTable instanceof HtmlDataTable) {
329             return ((HtmlDataTable)newspaperTable).getFooterClass();
330         } else {
331             return (String JavaDoc)newspaperTable.getAttributes().get(JSFAttr.FOOTER_CLASS_ATTR);
332         }
333     }
334
335     /**
336      * Gets styles for the specified component.
337      */

338     public static Styles getStyles(HtmlNewspaperTable newspaperTable) {
339         String JavaDoc rowClasses;
340         String JavaDoc columnClasses;
341         if(newspaperTable instanceof HtmlDataTable) {
342             rowClasses = ((HtmlDataTable)newspaperTable).getRowClasses();
343             columnClasses = ((HtmlDataTable)newspaperTable).getColumnClasses();
344         } else {
345             rowClasses = (String JavaDoc)newspaperTable.getAttributes().get(JSFAttr.ROW_CLASSES_ATTR);
346             columnClasses = (String JavaDoc)newspaperTable.getAttributes().get(JSFAttr.COLUMN_CLASSES_ATTR);
347         }
348         return new Styles(rowClasses, columnClasses);
349     }
350
351     /**
352      * Class manages the styles from String lists.
353      */

354     private static class Styles {
355
356         private String JavaDoc[] _columnStyle;
357         private String JavaDoc[] _rowStyle;
358
359         Styles(String JavaDoc rowStyles, String JavaDoc columnStyles) {
360             _rowStyle = (rowStyles == null)
361                 ? ArrayUtils.EMPTY_STRING_ARRAY
362                 : StringUtils.trim(
363                     StringUtils.splitShortString(rowStyles, ','));
364             _columnStyle = (columnStyles == null)
365                 ? ArrayUtils.EMPTY_STRING_ARRAY
366                 : StringUtils.trim(
367                     StringUtils.splitShortString(columnStyles, ','));
368         }
369
370         public String JavaDoc getRowStyle(int idx) {
371             if(!hasRowStyle()) {
372                 return null;
373             }
374             return _rowStyle[idx % _rowStyle.length];
375         }
376
377         public String JavaDoc getColumnStyle(int idx) {
378             if(!hasColumnStyle()) {
379                 return null;
380             }
381             return _columnStyle[idx % _columnStyle.length];
382         }
383
384         public boolean hasRowStyle() {
385             return _rowStyle.length > 0;
386         }
387
388         public boolean hasColumnStyle() {
389             return _columnStyle.length > 0;
390         }
391     }
392 }
Popular Tags