1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.renderkit.html.ext;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.myfaces.component.NewspaperTable;
25 import org.apache.myfaces.component.html.ext.HtmlDataTable;
26 import org.apache.myfaces.custom.column.HtmlColumn;
27 import org.apache.myfaces.custom.column.HtmlSimpleColumn;
28 import org.apache.myfaces.custom.crosstable.UIColumns;
29 import org.apache.myfaces.renderkit.html.util.ColumnInfo;
30 import org.apache.myfaces.renderkit.html.util.RowInfo;
31 import org.apache.myfaces.renderkit.html.util.TableContext;
32 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
33 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
34 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
35 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
36 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase;
37 import org.apache.myfaces.shared_tomahawk.util.ArrayUtils;
38
39 import javax.faces.component.UIComponent;
40 import javax.faces.component.UIData;
41 import javax.faces.component.ValueHolder;
42 import javax.faces.context.FacesContext;
43 import javax.faces.context.ResponseWriter;
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Set;
51
52
53
54
55
56
57
58
59
60
61
62
63 public class HtmlTableRenderer extends HtmlTableRendererBase {
64 private static final Log log = LogFactory.getLog(HtmlTableRenderer.class);
65
66
67
68
69 public static final String DETAIL_STAMP_FACET_NAME = "detailStamp";
70 private static final String BODY_STYLE_CLASS = "bodyStyleClass";
71 private static final String BODY_STYLE = "bodyStyle";
72
73
74
75
76
77 protected int getNewspaperColumns(UIComponent component) {
78 if (component instanceof NewspaperTable) {
79
80 NewspaperTable newspaperTable = (NewspaperTable) component;
81 return newspaperTable.getNewspaperColumns();
82 }
83 return super.getNewspaperColumns(component);
84 }
85
86
87
88
89
90 protected UIComponent getNewspaperTableSpacer(UIComponent component) {
91 if (component instanceof NewspaperTable) {
92
93 NewspaperTable newspaperTable = (NewspaperTable) component;
94 return newspaperTable.getSpacer();
95 }
96 return super.getNewspaperTableSpacer(component);
97 }
98
99
100
101
102
103 protected boolean hasNewspaperTableSpacer(UIComponent component) {
104 if (null != getNewspaperTableSpacer(component)) {
105 return true;
106 }
107 return super.hasNewspaperTableSpacer(component);
108 }
109
110
111
112
113
114 protected boolean isNewspaperHorizontalOrientation(UIComponent component) {
115 if (component instanceof NewspaperTable) {
116
117
118 NewspaperTable newspaperTable = (NewspaperTable) component;
119 return NewspaperTable.NEWSPAPER_HORIZONTAL_ORIENTATION.equals(newspaperTable.getNewspaperOrientation());
120 }
121 return super.isNewspaperHorizontalOrientation(component);
122 }
123
124 protected void startTable(FacesContext facesContext, UIComponent uiComponent) throws IOException {
125 boolean embedded = isEmbeddedTable(uiComponent);
126
127 if (!embedded) {
128 super.startTable(facesContext, uiComponent);
129 }
130 }
131
132 protected String determineHeaderFooterTag(FacesContext facesContext, UIComponent component, boolean header) {
133 if (isEmbeddedTable(component)) {
134
135 return null;
136 }
137
138 return super.determineHeaderFooterTag(facesContext, component, header);
139 }
140
141 protected String determineHeaderCellTag(FacesContext facesContext, UIComponent component) {
142 if (isEmbeddedTable(component)) {
143 return HTML.TD_ELEM;
144 }
145
146 return HTML.TH_ELEM;
147 }
148
149 protected void renderTableHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, UIComponent facet, String styleClass, String colElementName, int colspan, boolean isHeader) throws IOException {
150 if (isEmbeddedTable(component)) {
151
152 colElementName = HTML.TD_ELEM;
153 }
154
155 super.renderTableHeaderOrFooterRow(facesContext, writer, component, facet, styleClass, colElementName, colspan, isHeader);
156 }
157
158 protected boolean isEmbeddedTable(UIComponent uiComponent) {
159 boolean embedded = false;
160 if (uiComponent instanceof HtmlDataTable) {
161 HtmlDataTable table = (HtmlDataTable) uiComponent;
162 embedded = table.isEmbedded();
163 }
164 return embedded;
165 }
166
167 protected boolean isDetailStampAfterRow(UIComponent uiComponent) {
168 if (uiComponent instanceof HtmlDataTable) {
169 return "after".equals(((HtmlDataTable) uiComponent).getDetailStampLocation());
170 }
171
172 return true;
173 }
174
175 protected void endTable(FacesContext facesContext, UIComponent uiComponent) throws IOException {
176 boolean embedded = isEmbeddedTable(uiComponent);
177
178 if (!embedded) {
179 super.endTable(facesContext, uiComponent);
180 }
181 }
182
183 protected void beforeRow(FacesContext facesContext, UIData uiData) throws IOException {
184 super.beforeRow(facesContext, uiData);
185
186 if (!isDetailStampAfterRow(uiData)) {
187 renderDetailRow(facesContext, uiData);
188 }
189 }
190
191 protected void afterRow(FacesContext facesContext, UIData uiData) throws IOException {
192 super.afterRow(facesContext, uiData);
193
194 if (isDetailStampAfterRow(uiData)) {
195 renderDetailRow(facesContext, uiData);
196 }
197 }
198
199
200
201
202
203
204 private void renderDetailRow(FacesContext facesContext, UIData uiData) throws IOException {
205 UIComponent detailStampFacet = uiData.getFacet(DETAIL_STAMP_FACET_NAME);
206
207 if (uiData instanceof HtmlDataTable) {
208 HtmlDataTable htmlDataTable = (HtmlDataTable) uiData;
209
210 if (htmlDataTable.isCurrentDetailExpanded()) {
211
212 boolean embedded = false;
213 if (detailStampFacet != null) {
214 embedded = isEmbeddedTable(detailStampFacet);
215 }
216
217 ResponseWriter writer = facesContext.getResponseWriter();
218
219 if (!embedded) {
220 writer.startElement(HTML.TR_ELEM, uiData);
221 writer.startElement(HTML.TD_ELEM, uiData);
222
223
224
225
226
227 int childCount = 0;
228 for (Iterator childIter = uiData.getChildren().iterator();
229 childIter.hasNext();)
230 {
231 UIComponent childComp = (UIComponent) childIter.next();
232 if (childComp instanceof UIColumns)
233 {
234 UIColumns v = (UIColumns) childComp;
235 childCount += v.getRowCount();
236 }
237 else
238 {
239 childCount++;
240 }
241 }
242 writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(
243 childCount), null);
244 }
245
246 if (detailStampFacet != null) {
247 RendererUtils.renderChild(facesContext, detailStampFacet);
248 }
249
250 if (!embedded) {
251 writer.endElement(HTML.TD_ELEM);
252 writer.endElement(HTML.TR_ELEM);
253 }
254 }
255 }
256 }
257
258
259
260
261 public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException {
262 if (uiComponent instanceof HtmlDataTable) {
263 HtmlDataTable htmlDataTable = (HtmlDataTable) uiComponent;
264 if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
265 super.encodeBegin(facesContext, uiComponent);
266 }
267 }
268 else {
269 super.encodeBegin(facesContext, uiComponent);
270 }
271 }
272
273
274
275
276 public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
277 if (component instanceof HtmlDataTable) {
278 HtmlDataTable htmlDataTable = (HtmlDataTable) component;
279 if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
280 super.encodeChildren(facesContext, component);
281 }
282 }
283 else {
284 super.encodeChildren(facesContext, component);
285 }
286 }
287
288 private boolean isGroupedTable(UIData uiData) {
289 if (uiData instanceof HtmlDataTable) {
290 List children = getChildren(uiData);
291 for (int j = 0, size = getChildCount(uiData); j < size; j++) {
292 UIComponent child = (UIComponent) children.get(j);
293 if (child instanceof HtmlSimpleColumn) {
294 HtmlSimpleColumn column = (HtmlSimpleColumn) child;
295 if (column.isGroupBy()) {
296 return true;
297 }
298 }
299 }
300 }
301
302 return false;
303 }
304
305 protected void beforeBody(FacesContext facesContext, UIData uiData) throws IOException {
306 if (isGroupedTable(uiData)) {
307 createColumnInfos((HtmlDataTable) uiData, facesContext);
308 }
309 super.beforeBody(facesContext, uiData);
310 }
311
312 private void createColumnInfos(HtmlDataTable htmlDataTable, FacesContext facesContext)
313 throws IOException {
314 int first = htmlDataTable.getFirst();
315 int rows = htmlDataTable.getRows();
316 int last;
317 int currentRowSpan = -1;
318 int currentRowInfoIndex = -1;
319
320 TableContext tableContext = htmlDataTable.getTableContext();
321 RowInfo rowInfo = null;
322 ColumnInfo columnInfo = null;
323 HtmlSimpleColumn currentColumn = null;
324 Map groupHashTable = new HashMap();
325
326 if (rows <= 0) {
327 last = htmlDataTable.getRowCount();
328 }
329 else {
330 last = first + rows;
331 }
332
333
334 List children = getChildren(htmlDataTable);
335 int nChildren = getChildCount(htmlDataTable);
336
337 for (int j = 0, size = nChildren; j < size; j++) {
338 UIComponent child = (UIComponent) children.get(j);
339 if (child instanceof HtmlSimpleColumn) {
340 currentColumn = (HtmlSimpleColumn) child;
341 if (currentColumn.isGroupBy()) {
342 groupHashTable.put(new Integer(j), null);
343 }
344 }
345 }
346
347 boolean groupEndReached = false;
348
349 for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++) {
350 htmlDataTable.setRowIndex(rowIndex);
351 rowInfo = new RowInfo();
352
353 if (!htmlDataTable.isRowAvailable()) {
354 break;
355 }
356
357 Set groupIndexList = groupHashTable.keySet();
358 List currentColumnContent = null;
359 for (Iterator it = groupIndexList.iterator(); it.hasNext();) {
360 currentColumnContent = new ArrayList();
361 Integer currentIndex = (Integer) it.next();
362 currentColumn = (HtmlSimpleColumn) children.get(currentIndex.intValue());
363
364 if (currentColumn.isGroupByValueSet()) {
365 currentColumnContent.add(currentColumn.getGroupByValue());
366 }
367 else {
368
369 List currentColumnChildren = currentColumn.getChildren();
370 if (currentColumnChildren != null) {
371 collectChildrenValues(currentColumnContent, currentColumnChildren.iterator());
372 }
373 }
374
375 if (!isListEqual(currentColumnContent, (List) groupHashTable.get(currentIndex)) &&
376 currentRowInfoIndex > -1) {
377 groupEndReached = true;
378 groupHashTable.put(currentIndex, currentColumnContent);
379 }
380 else if (currentRowInfoIndex == -1) {
381 groupHashTable.put(currentIndex, currentColumnContent);
382 }
383 }
384 currentRowSpan++;
385
386
387 for (int j = 0, size = nChildren; j < size; j++) {
388 columnInfo = new ColumnInfo();
389 if (groupHashTable.containsKey(new Integer(j)))
390 {
391 if (currentRowSpan > 0) {
392 if (groupEndReached) {
393 ((ColumnInfo)
394 ((RowInfo)
395 tableContext.getRowInfos().get(currentRowInfoIndex - currentRowSpan + 1)).
396 getColumnInfos().get(j)).
397 setRowSpan(currentRowSpan);
398 columnInfo.setStyle(htmlDataTable.getRowGroupStyle());
399 columnInfo.setStyleClass(htmlDataTable.getRowGroupStyleClass());
400 }
401 else {
402 columnInfo.setRendered(false);
403 }
404 }
405 else {
406 columnInfo.setStyle(htmlDataTable.getRowGroupStyle());
407 columnInfo.setStyleClass(htmlDataTable.getRowGroupStyleClass());
408 }
409
410 }
411 else
412 {
413 if (groupEndReached) {
414 ((ColumnInfo)
415 ((RowInfo)
416 tableContext.getRowInfos().get(currentRowInfoIndex)).
417 getColumnInfos().get(j)).
418 setStyle(htmlDataTable.getRowGroupStyle());
419 ((ColumnInfo)
420 ((RowInfo)
421 tableContext.getRowInfos().get(currentRowInfoIndex)).
422 getColumnInfos().get(j)).
423 setStyleClass(htmlDataTable.getRowGroupStyleClass());
424 }
425 }
426 rowInfo.getColumnInfos().add(columnInfo);
427 }
428 if (groupEndReached) {
429 currentRowSpan = 0;
430 groupEndReached = false;
431 }
432 tableContext.getRowInfos().add(rowInfo);
433 currentRowInfoIndex++;
434 }
435
436
437 if (currentRowInfoIndex > -1) {
438 for (int j = 0, size = nChildren; j < size; j++) {
439 if (groupHashTable.containsKey(new Integer(j)))
440 {
441 ((ColumnInfo)
442 ((RowInfo)
443 tableContext.getRowInfos().get(currentRowInfoIndex - currentRowSpan)).
444 getColumnInfos().get(j)).
445 setRowSpan(currentRowSpan + 1);
446 }
447 else
448 {
449 ((ColumnInfo)
450 ((RowInfo)
451 tableContext.getRowInfos().get(currentRowInfoIndex)).
452 getColumnInfos().get(j)).
453 setStyle(htmlDataTable.getRowGroupStyle());
454 ((ColumnInfo)
455 ((RowInfo)
456 tableContext.getRowInfos().get(currentRowInfoIndex)).
457 getColumnInfos().get(j)).
458 setStyleClass(htmlDataTable.getRowGroupStyleClass());
459 }
460 }
461 }
462
463 htmlDataTable.setRowIndex(-1);
464 }
465
466 protected void collectChildrenValues(List container, Iterator iterChildren) {
467 while (iterChildren.hasNext()) {
468 UIComponent child = (UIComponent) iterChildren.next();
469 if (child.isRendered()) {
470 if (child instanceof ValueHolder) {
471 Object value = ((ValueHolder) child).getValue();
472 container.add(value);
473 }
474
475
476 collectChildrenValues(container, child.getFacetsAndChildren());
477 }
478 }
479 }
480
481
482
483
484
485
486 protected boolean isListEqual(List list1, List list2) {
487 if (list1 == list2) {
488 return list1 != null && list1.size() > 0;
489 }
490 if (list1 == null || list2 == null || list1.size() != list2.size()) {
491 return false;
492 }
493
494 for (int i = 0; i < list1.size(); i++) {
495 Object o1 = list1.get(i);
496 Object o2 = list2.get(i);
497
498 if (o1 != null && !o1.equals(o2)) {
499 return false;
500 }
501 if (o2 != null && !o2.equals(o1)) {
502 return false;
503 }
504 }
505
506 return true;
507 }
508
509
510
511
512
513 public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {
514 if (uiComponent instanceof HtmlDataTable) {
515 HtmlDataTable htmlDataTable = (HtmlDataTable) uiComponent;
516 if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
517 super.encodeEnd(facesContext, uiComponent);
518 }
519 }
520 else {
521 super.encodeEnd(facesContext, uiComponent);
522 }
523 }
524
525 protected void renderRowStart(FacesContext facesContext,
526 ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex)
527 throws IOException {
528 super.renderRowStart(facesContext, writer, uiData, styles, rowStyleIndex);
529
530
531 HtmlDataTable table = (HtmlDataTable) uiData;
532
533 renderRowAttribute(writer, HTML.ONCLICK_ATTR, table.getRowOnClick());
534 renderRowAttribute(writer, HTML.ONDBLCLICK_ATTR, table.getRowOnDblClick());
535 renderRowAttribute(writer, HTML.ONKEYDOWN_ATTR, table.getRowOnKeyDown());
536 renderRowAttribute(writer, HTML.ONKEYPRESS_ATTR, table.getRowOnKeyPress());
537 renderRowAttribute(writer, HTML.ONKEYUP_ATTR, table.getRowOnKeyUp());
538 renderRowAttribute(writer, HTML.ONMOUSEDOWN_ATTR, table.getRowOnMouseDown());
539 renderRowAttribute(writer, HTML.ONMOUSEMOVE_ATTR, table.getRowOnMouseMove());
540 renderRowAttribute(writer, HTML.ONMOUSEOUT_ATTR, table.getRowOnMouseOut());
541 renderRowAttribute(writer, HTML.ONMOUSEOVER_ATTR, table.getRowOnMouseOver());
542 renderRowAttribute(writer, HTML.ONMOUSEUP_ATTR, table.getRowOnMouseUp());
543 }
544
545
546
547
548 protected void renderRowStyle(FacesContext facesContext, ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex) throws IOException {
549 String rowStyleClass;
550 String rowStyle;
551 if (uiData instanceof HtmlDataTable) {
552 HtmlDataTable datatable = (HtmlDataTable) uiData;
553 rowStyleClass = datatable.getRowStyleClass();
554 rowStyle = datatable.getRowStyle();
555 }
556 else {
557 rowStyleClass = (String) uiData.getAttributes().get(JSFAttr.ROW_STYLECLASS_ATTR);
558 rowStyle = (String) uiData.getAttributes().get(JSFAttr.ROW_STYLE_ATTR);
559 }
560 if (rowStyleClass == null) {
561 super.renderRowStyle(facesContext, writer, uiData, styles, rowStyleIndex);
562 }
563 else {
564 writer.writeAttribute(HTML.CLASS_ATTR, rowStyleClass, null);
565 }
566 if (rowStyle != null) {
567 writer.writeAttribute(HTML.STYLE_ATTR, rowStyle, null);
568 }
569 }
570
571 protected void renderRowAttribute(ResponseWriter writer,
572 String htmlAttribute, Object value) throws IOException {
573 if (value != null) {
574 writer.writeAttribute(htmlAttribute, value, null);
575 }
576 }
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606 protected void encodeColumnChild(FacesContext facesContext,
607 ResponseWriter writer, UIData uiData,
608 UIComponent component, Styles styles, int columnStyleIndex)
609 throws IOException {
610
611
612
613
614 columnStyleIndex = getColumnStyleIndex(uiData, columnStyleIndex);
615 super.encodeColumnChild(facesContext, writer, uiData, component,
616 styles, columnStyleIndex);
617 if (component instanceof UIColumns)
618 {
619 UIColumns columns = (UIColumns) component;
620 for (int k = 0, colSize = columns.getRowCount(); k < colSize; k++)
621 {
622 columns.setRowIndex(k);
623 renderColumnBody(facesContext, writer, uiData, component,
624 styles, columnStyleIndex + k);
625 }
626 columns.setRowIndex(-1);
627 }
628 }
629
630
631
632
633
634
635
636
637
638 private int getColumnStyleIndex(UIData uiData, int columnStyleIndex)
639 {
640 int colStyleIndex = 0;
641 for (int i = 0; i < columnStyleIndex; i++)
642 {
643 UIComponent child = (UIComponent) uiData.getChildren().get(i % uiData.getChildCount());
644 if (child instanceof UIColumns)
645 {
646 colStyleIndex += ((UIColumns) child).getRowCount();
647 continue;
648 }
649 colStyleIndex++;
650 }
651 return colStyleIndex;
652 }
653
654
655
656
657
658 protected void renderColumnBody(FacesContext facesContext,
659 ResponseWriter writer, UIData uiData,
660 UIComponent component, Styles styles, int columnStyleIndex)
661 throws IOException {
662 if (isGroupedTable(uiData)) {
663
664 HtmlDataTable htmlDataTable = (HtmlDataTable) uiData;
665 List tableChildren = htmlDataTable.getChildren();
666
667 int first = htmlDataTable.getFirst();
668 int rowInfoIndex = htmlDataTable.getRowIndex() - first;
669 int columnInfoIndex = tableChildren.indexOf(component);
670
671 RowInfo rowInfo = (RowInfo) htmlDataTable.getTableContext().getRowInfos().get(rowInfoIndex);
672 ColumnInfo columnInfo = (ColumnInfo) rowInfo.getColumnInfos().get(columnInfoIndex);
673
674 if (!columnInfo.isRendered()) {
675 return;
676 }
677
678 if (component instanceof HtmlColumn && amISpannedOver(null, component)) {
679 return;
680 }
681 writer.startElement(HTML.TD_ELEM, uiData);
682 String styleClass = null;
683 if (component instanceof HtmlColumn) {
684 styleClass = ((HtmlColumn) component).getStyleClass();
685 }
686 if (columnInfo.getStyleClass() != null) {
687 styleClass = columnInfo.getStyleClass();
688 }
689
690 if (styles.hasColumnStyle()) {
691 if (styleClass == null) {
692 styleClass = styles.getColumnStyle(columnStyleIndex);
693 }
694 }
695 if (styleClass != null) {
696 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
697 }
698
699 if (columnInfo.getStyle() != null) {
700 writer.writeAttribute(HTML.STYLE_ATTR, columnInfo.getStyle(), null);
701 }
702
703 if (columnInfo.getRowSpan() > 1) {
704 writer.writeAttribute("rowspan", new Integer(columnInfo.getRowSpan()).toString(), null);
705 if (columnInfo.getStyle() == null) {
706 writer.writeAttribute(HTML.STYLE_ATTR, "vertical-align:top", null);
707 }
708 }
709
710 renderHtmlColumnAttributes(writer, component, null);
711
712 RendererUtils.renderChild(facesContext, component);
713 writer.endElement(HTML.TD_ELEM);
714 }
715 else if (component instanceof HtmlColumn) {
716 if (amISpannedOver(null, component)) {
717 return;
718 }
719 writer.startElement(HTML.TD_ELEM, uiData);
720 String styleClass = ((HtmlColumn) component).getStyleClass();
721 if (styles.hasColumnStyle()) {
722 if (styleClass == null) {
723 styleClass = styles.getColumnStyle(columnStyleIndex);
724 }
725 }
726 if (styleClass != null) {
727 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
728 }
729 renderHtmlColumnAttributes(writer, component, null);
730
731 RendererUtils.renderChild(facesContext, component);
732 writer.endElement(HTML.TD_ELEM);
733 }
734 else {
735 super.renderColumnBody(facesContext, writer, uiData, component,
736 styles, columnStyleIndex);
737 }
738 }
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761 protected void renderColumnChildHeaderOrFooterRow(
762 FacesContext facesContext, ResponseWriter writer,
763 UIComponent uiComponent, String styleClass, boolean header)
764 throws IOException {
765 super.renderColumnChildHeaderOrFooterRow(facesContext, writer,
766 uiComponent, styleClass, header);
767 if (uiComponent instanceof UIColumns) {
768 UIColumns columns = (UIColumns) uiComponent;
769 for (int i = 0, size = columns.getRowCount(); i < size; i++) {
770 columns.setRowIndex(i);
771 if (header) {
772 renderColumnHeaderCell(facesContext, writer, columns,
773 columns.getHeader(), styleClass, 0);
774 }
775 else {
776 renderColumnFooterCell(facesContext, writer, columns,
777 columns.getFooter(), styleClass, 0);
778 }
779 }
780 columns.setRowIndex(-1);
781 }
782 }
783
784
785
786
787 protected void renderColumnHeaderCell(FacesContext facesContext,
788 ResponseWriter writer, UIComponent uiComponent,
789 UIComponent facet, String headerStyleClass, int colspan)
790 throws IOException {
791 if (uiComponent instanceof HtmlColumn) {
792
793 HtmlColumn column = (HtmlColumn) uiComponent;
794
795 if (amISpannedOver("header", uiComponent)) {
796 return;
797 }
798
799 writer.startElement(determineHeaderCellTag(facesContext, uiComponent.getParent()), uiComponent);
800
801 String columnId = column.getColumnId();
802 if (columnId != null)
803 {
804 writer.writeAttribute(HTML.ID_ATTR, columnId, null);
805 }
806
807 if (colspan > 1) {
808 writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan),
809 null);
810 }
811 String styleClass = ((HtmlColumn) uiComponent)
812 .getHeaderstyleClass();
813 if (styleClass == null) {
814 styleClass = headerStyleClass;
815 }
816 if (styleClass != null) {
817 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
818 }
819 renderHtmlColumnAttributes(writer, uiComponent, "header");
820 if (facet != null) {
821 RendererUtils.renderChild(facesContext, facet);
822 }
823 writer.endElement(determineHeaderCellTag(facesContext, uiComponent.getParent()));
824 }
825 else {
826 super.renderColumnHeaderCell(facesContext, writer, uiComponent,
827 facet, headerStyleClass, colspan);
828 }
829 }
830
831
832
833
834 protected void renderColumnFooterCell(FacesContext facesContext,
835 ResponseWriter writer, UIComponent uiComponent,
836 UIComponent facet, String footerStyleClass, int colspan)
837 throws IOException {
838 if (uiComponent instanceof HtmlColumn) {
839 if (amISpannedOver("footer", uiComponent)) {
840 return;
841 }
842 writer.startElement(HTML.TD_ELEM, uiComponent);
843 if (colspan > 1) {
844 writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan),
845 null);
846 }
847 String styleClass = ((HtmlColumn) uiComponent)
848 .getFooterstyleClass();
849 if (styleClass == null) {
850 styleClass = footerStyleClass;
851 }
852 if (styleClass != null) {
853 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
854 }
855 renderHtmlColumnAttributes(writer, uiComponent, "footer");
856 if (facet != null) {
857 RendererUtils.renderChild(facesContext, facet);
858 }
859 writer.endElement(HTML.TD_ELEM);
860 }
861 else {
862 super.renderColumnFooterCell(facesContext, writer, uiComponent,
863 facet, footerStyleClass, colspan);
864 }
865 }
866
867 protected void renderHtmlColumnAttributes(ResponseWriter writer,
868 UIComponent uiComponent, String prefix) throws IOException {
869 String[] attrs = (String[]) ArrayUtils.concat(HTML.COMMON_PASSTROUGH_ATTRIBUTES_WITHOUT_STYLE, new String[]{HTML.COLSPAN_ATTR});
870 for (int i = 0, size = attrs.length; i < size; i++) {
871 String attributeName = attrs[i];
872 String compAttrName = prefix != null ? prefix + attributeName : attributeName;
873 HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
874 compAttrName, attributeName);
875 }
876 String compAttrName = prefix != null ? prefix + HTML.STYLE_ATTR : HTML.STYLE_ATTR;
877 HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
878 compAttrName, HTML.STYLE_ATTR);
879
880 HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
881 HTML.WIDTH_ATTR, HTML.WIDTH_ATTR);
882 }
883
884
885
886
887
888
889
890
891
892
893
894 protected int determineChildColSpan(UIComponent uiComponent) {
895 int result = super.determineChildColSpan(uiComponent);
896 if (uiComponent instanceof UIColumns) {
897 result += ((UIColumns) uiComponent).getRowCount();
898 }
899 return result;
900 }
901
902
903
904
905
906
907
908 protected boolean hasFacet(boolean header, UIComponent uiComponent) {
909 boolean result = super.hasFacet(header, uiComponent);
910 if (!result && uiComponent instanceof UIColumns) {
911
912
913 UIColumns columns = (UIColumns) uiComponent;
914 result = header ? columns.getHeader() != null : columns.getFooter() != null;
915 }
916 return result;
917 }
918
919
920
921
922
923 protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, String footerStyleClass) throws IOException {
924 if (determineRenderFacet(component, false)) {
925 super.renderColumnFooterRow(facesContext, writer, component, footerStyleClass);
926 }
927 }
928
929
930
931
932
933 protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, String headerStyleClass) throws IOException {
934 if (determineRenderFacet(component, true)) {
935 super.renderColumnHeaderRow(facesContext, writer, component, headerStyleClass);
936 }
937 }
938
939
940
941
942 protected boolean determineRenderFacet(UIComponent component, boolean header) {
943 for (Iterator it = getChildren(component).iterator(); it.hasNext();) {
944 UIComponent uiComponent = (UIComponent) it.next();
945 if (uiComponent.isRendered() && determineChildColSpan(uiComponent) > 0) {
946 UIComponent facet = header ? (UIComponent) uiComponent.getFacets().get(HEADER_FACET_NAME)
947 : (UIComponent) uiComponent.getFacets().get(FOOTER_FACET_NAME);
948
949 if (facet != null && facet.isRendered()) {
950 return true;
951 }
952 }
953 }
954
955 return false;
956 }
957
958 protected void beforeColumn(FacesContext facesContext, UIData uiData, int columnIndex) throws IOException {
959 super.beforeColumn(facesContext, uiData, columnIndex);
960
961 if (uiData instanceof HtmlDataTable) {
962 HtmlDataTable dataTable = (HtmlDataTable) uiData;
963
964 putSortedReqScopeParam(facesContext, dataTable, columnIndex);
965 }
966 }
967
968 protected void beforeColumnHeaderOrFooter(FacesContext facesContext, UIData uiData, boolean header, int columnIndex) throws IOException {
969 super.beforeColumnHeaderOrFooter(facesContext, uiData, header, columnIndex);
970
971 if (header && uiData instanceof HtmlDataTable) {
972 HtmlDataTable dataTable = (HtmlDataTable) uiData;
973
974 putSortedReqScopeParam(facesContext, dataTable, columnIndex);
975 }
976 }
977
978 protected void putSortedReqScopeParam(FacesContext facesContext, HtmlDataTable dataTable, int columnIndex) {
979 String sortedColumnVar = dataTable.getSortedColumnVar();
980 Map requestMap = facesContext.getExternalContext().getRequestMap();
981
982 if (columnIndex == dataTable.getSortColumnIndex()) {
983 if (sortedColumnVar != null) {
984 requestMap.put(sortedColumnVar, Boolean.TRUE);
985 }
986 }
987 else if (sortedColumnVar != null) {
988 requestMap.remove(sortedColumnVar);
989 }
990 }
991
992
993
994
995
996
997
998
999 protected boolean amISpannedOver(String prefix, UIComponent component) {
1000 UIComponent table = component.getParent();
1001 int span = 0;
1002 for (Iterator it = table.getChildren().iterator(); it.hasNext();) {
1003 UIComponent columnComponent = (UIComponent) it.next();
1004 if (!(columnComponent instanceof HtmlColumn)) {
1005 continue;
1006 }
1007 if (span > 0) {
1008 span--;
1009 }
1010 if (columnComponent == component) {
1011 return span > 0;
1012 }
1013 if (span == 0) {
1014 try {
1015 if (prefix == null && ((HtmlColumn) columnComponent).getColspan() != null) {
1016 span = Integer.parseInt(((HtmlColumn) columnComponent).getColspan());
1017 }
1018 if ("header".equals(prefix) && ((HtmlColumn) columnComponent).getHeadercolspan() != null) {
1019 span = Integer.parseInt(((HtmlColumn) columnComponent).getHeadercolspan());
1020 }
1021 if ("footer".equals(prefix) && ((HtmlColumn) columnComponent).getFootercolspan() != null) {
1022 span = Integer.parseInt(((HtmlColumn) columnComponent).getFootercolspan());
1023 }
1024 }
1025 catch (NumberFormatException ex) {
1026 log.warn("Invalid " + ((prefix == null) ? "" : prefix) + "colspan attribute ignored");
1027 }
1028 }
1029 }
1030 return false;
1031 }
1032
1033
1034
1035
1036
1037
1038
1039
1040 protected void inBodyStart(FacesContext facesContext, UIData uiData) throws IOException {
1041 String bodyStyleClass;
1042 String bodyStyle;
1043
1044 if (uiData instanceof HtmlDataTable) {
1045 bodyStyleClass = ((HtmlDataTable) uiData).getBodyStyleClass();
1046 bodyStyle = ((HtmlDataTable) uiData).getBodyStyle();
1047 }
1048 else {
1049 bodyStyleClass = (String) uiData.getAttributes().get(BODY_STYLE_CLASS);
1050 bodyStyle = (String) uiData.getAttributes().get(BODY_STYLE);
1051 }
1052
1053 ResponseWriter writer = facesContext.getResponseWriter();
1054 if (bodyStyleClass != null) {
1055 writer.writeAttribute(HTML.CLASS_ATTR, bodyStyleClass,
1056 BODY_STYLE_CLASS);
1057 }
1058 if (bodyStyle != null) {
1059 writer.writeAttribute(HTML.STYLE_ATTR, bodyStyle, BODY_STYLE);
1060 }
1061 }
1062
1063
1064 }