1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.logging.Logger;
25
26 import javax.faces.component.UIColumn;
27 import javax.faces.component.UIComponent;
28 import javax.faces.component.UIData;
29 import javax.faces.component.behavior.ClientBehavior;
30 import javax.faces.component.behavior.ClientBehaviorHolder;
31 import javax.faces.component.html.HtmlColumn;
32 import javax.faces.component.html.HtmlDataTable;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35
36 import org.apache.myfaces.shared.renderkit.JSFAttr;
37 import org.apache.myfaces.shared.renderkit.RendererUtils;
38 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
39 import org.apache.myfaces.shared.util.ArrayUtils;
40 import org.apache.myfaces.shared.util.StringUtils;
41
42
43
44
45
46 public class HtmlTableRendererBase extends HtmlRenderer
47 {
48 protected static final String HEADER_FACET_NAME = "header";
49 protected static final String FOOTER_FACET_NAME = "footer";
50 protected static final String CAPTION_FACET_NAME = "caption";
51
52 private static final Logger log = Logger.getLogger(HtmlTableRendererBase.class.getName());
53
54 private static final Integer[] ZERO_INT_ARRAY = new Integer[]{0};
55
56
57
58
59
60 protected int getNewspaperColumns(UIComponent component)
61 {
62 return 1;
63 }
64
65
66
67
68
69 protected UIComponent getNewspaperTableSpacer(UIComponent component)
70 {
71 return null;
72 }
73
74
75
76
77
78 protected boolean hasNewspaperTableSpacer(UIComponent component)
79 {
80 return false;
81 }
82
83
84
85
86
87 protected boolean isNewspaperHorizontalOrientation(UIComponent component)
88 {
89 return false;
90 }
91
92 @Override
93 public boolean getRendersChildren()
94 {
95 return true;
96 }
97
98
99
100
101
102
103 @Override
104 public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
105 {
106 RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
107
108 Map<String, List<ClientBehavior>> behaviors = null;
109 if (uiComponent instanceof ClientBehaviorHolder)
110 {
111 behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
112 if (!behaviors.isEmpty())
113 {
114 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());
115 }
116 }
117
118 beforeTable(facesContext, (UIData) uiComponent);
119
120 startTable(facesContext, uiComponent);
121 }
122
123
124
125
126 protected void startTable(FacesContext facesContext, UIComponent uiComponent) throws IOException
127 {
128 ResponseWriter writer = facesContext.getResponseWriter();
129 writer.startElement(HTML.TABLE_ELEM, uiComponent);
130
131 Map<String, List<ClientBehavior>> behaviors = null;
132 if (uiComponent instanceof ClientBehaviorHolder)
133 {
134 behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
135 if (!behaviors.isEmpty())
136 {
137 HtmlRendererUtils.writeIdAndName(writer, uiComponent, facesContext);
138 }
139 else
140 {
141 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
142 }
143 if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
144 {
145 CommonPropertyUtils.renderEventProperties(writer,
146 CommonPropertyUtils.getCommonPropertiesMarked(uiComponent), uiComponent);
147 }
148 else
149 {
150 if (isCommonEventsOptimizationEnabled(facesContext))
151 {
152 CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer,
153 CommonPropertyUtils.getCommonPropertiesMarked(uiComponent),
154 CommonEventUtils.getCommonEventsMarked(uiComponent), uiComponent, behaviors);
155 }
156 else
157 {
158 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, uiComponent, behaviors);
159 }
160 }
161 if (isCommonPropertiesOptimizationEnabled(facesContext))
162 {
163 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.TABLE_ATTRIBUTES);
164 CommonPropertyUtils.renderCommonPassthroughPropertiesWithoutEvents(writer,
165 CommonPropertyUtils.getCommonPropertiesMarked(uiComponent), uiComponent);
166 }
167 else
168 {
169 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
170 HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
171 }
172 }
173 else
174 {
175 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
176 if (isCommonPropertiesOptimizationEnabled(facesContext))
177 {
178 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.TABLE_ATTRIBUTES);
179 CommonPropertyUtils.renderCommonPassthroughProperties(writer,
180 CommonPropertyUtils.getCommonPropertiesMarked(uiComponent), uiComponent);
181 }
182 else
183 {
184 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
185 HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
186 }
187 }
188 }
189
190
191
192
193
194
195 @Override
196 public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException
197 {
198 RendererUtils.checkParamValidity(facesContext, component, UIData.class);
199
200 beforeBody(facesContext, (UIData) component);
201
202 encodeInnerHtml(facesContext, component);
203
204 afterBody(facesContext, (UIData) component);
205 }
206
207
208
209
210
211
212
213
214 protected void renderCaptionFacet(FacesContext facesContext, ResponseWriter writer, UIComponent component)
215 throws IOException
216 {
217 HtmlRendererUtils.renderTableCaption(facesContext, writer, component);
218 }
219
220
221
222
223
224
225
226
227
228 protected void renderColgroupsFacet(FacesContext facesContext, ResponseWriter writer, UIComponent component)
229 throws IOException
230 {
231 UIComponent colgroupsFacet = component.getFacet("colgroups");
232 if (colgroupsFacet == null)
233 {
234
235 return;
236 }
237
238
239 colgroupsFacet.encodeAll(facesContext);
240 }
241
242
243
244
245 protected static Styles getStyles(UIData uiData)
246 {
247 String rowClasses;
248 String columnClasses;
249 if(uiData instanceof HtmlDataTable)
250 {
251 rowClasses = ((HtmlDataTable)uiData).getRowClasses();
252 columnClasses = ((HtmlDataTable)uiData).getColumnClasses();
253 }
254 else
255 {
256 rowClasses = (String)uiData.getAttributes().get(JSFAttr.ROW_CLASSES_ATTR);
257 columnClasses = (String)uiData.getAttributes().get(JSFAttr.COLUMN_CLASSES_ATTR);
258 }
259 return new Styles(rowClasses, columnClasses);
260 }
261
262
263
264
265 protected static class Styles
266 {
267
268 private String[] _columnStyle;
269 private String[] _rowStyle;
270
271 Styles(String rowStyles, String columnStyles)
272 {
273 _rowStyle = (rowStyles == null)
274 ? ArrayUtils.EMPTY_STRING_ARRAY
275 : StringUtils.trim(
276 StringUtils.splitShortString(rowStyles, ','));
277 _columnStyle = (columnStyles == null)
278 ? ArrayUtils.EMPTY_STRING_ARRAY
279 : StringUtils.trim(
280 StringUtils.splitShortString(columnStyles, ','));
281 }
282
283 public String getRowStyle(int idx)
284 {
285 if(!hasRowStyle())
286 {
287 return null;
288 }
289 return _rowStyle[idx % _rowStyle.length];
290 }
291
292 public String getColumnStyle(int idx)
293 {
294 if(!hasColumnStyle())
295 {
296 return null;
297 }
298
299 if (idx < _columnStyle.length)
300 {
301 return _columnStyle[idx];
302 }
303 return null;
304 }
305
306 public boolean hasRowStyle()
307 {
308 return _rowStyle.length > 0;
309 }
310
311 public boolean hasColumnStyle()
312 {
313 return _columnStyle.length > 0;
314 }
315 }
316
317 private Integer[] getBodyRows(FacesContext facesContext, UIComponent component)
318 {
319 Integer[] bodyrows = null;
320 String bodyrowsAttr = (String) component.getAttributes().get(JSFAttr.BODYROWS_ATTR);
321 if(bodyrowsAttr != null && !"".equals(bodyrowsAttr))
322 {
323 String[] bodyrowsString = StringUtils.trim(StringUtils.splitShortString(bodyrowsAttr, ','));
324
325
326 bodyrows = new Integer[bodyrowsString.length];
327 for(int i = 0; i < bodyrowsString.length; i++)
328 {
329 bodyrows[i] = Integer.valueOf(bodyrowsString[i]);
330 }
331
332 }
333 else
334 {
335 bodyrows = ZERO_INT_ARRAY;
336 }
337 return bodyrows;
338 }
339
340
341
342
343
344
345
346
347
348 public void encodeInnerHtml(FacesContext facesContext, UIComponent component)throws IOException
349 {
350 UIData uiData = (UIData) component;
351 ResponseWriter writer = facesContext.getResponseWriter();
352
353 int rowCount = uiData.getRowCount();
354
355 int newspaperColumns = getNewspaperColumns(component);
356
357 if (rowCount == -1 && newspaperColumns == 1)
358 {
359 encodeInnerHtmlUnknownRowCount(facesContext, component);
360 return;
361 }
362
363 if (rowCount == 0)
364 {
365
366 writer.startElement(HTML.TBODY_ELEM, null);
367 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element", null);
368 writer.startElement(HTML.TR_ELEM, null);
369 writer.startElement(HTML.TD_ELEM, null);
370 writer.endElement(HTML.TD_ELEM);
371 writer.endElement(HTML.TR_ELEM);
372 writer.endElement(HTML.TBODY_ELEM);
373 return;
374 }
375
376
377
378 Styles styles = getStyles(uiData);
379
380 int first = uiData.getFirst();
381 int rows = uiData.getRows();
382 int last;
383
384 if (rows <= 0)
385 {
386 last = rowCount;
387 }
388 else
389 {
390 last = first + rows;
391 if (last > rowCount)
392 {
393 last = rowCount;
394 }
395 }
396
397 int newspaperRows;
398 if((last - first) % newspaperColumns == 0)
399 {
400 newspaperRows = (last - first) / newspaperColumns;
401 }
402 else
403 {
404 newspaperRows = ((last - first) / newspaperColumns) + 1;
405 }
406 boolean newspaperHorizontalOrientation = isNewspaperHorizontalOrientation(component);
407
408
409 Integer[] bodyrows = getBodyRows(facesContext, component);
410 int bodyrowsCount = 0;
411
412
413 for(int nr = 0; nr < newspaperRows; nr++)
414 {
415 boolean rowStartRendered = false;
416
417 for(int nc = 0; nc < newspaperColumns; nc++)
418 {
419
420
421 int currentRow;
422 if (newspaperHorizontalOrientation)
423 {
424 currentRow = nr * newspaperColumns + nc + first;
425 }
426 else
427 {
428 currentRow = nc * newspaperRows + nr + first;
429 }
430
431
432 if(currentRow >= last)
433 {
434 continue;
435 }
436
437
438 uiData.setRowIndex(currentRow);
439 if(!uiData.isRowAvailable())
440 {
441 log.severe("Row is not available. Rowindex = " + currentRow);
442 break;
443 }
444
445 if (nc == 0)
446 {
447
448 beforeRow(facesContext, uiData);
449
450
451 if(ArrayUtils.contains(bodyrows, currentRow))
452 {
453
454 if(bodyrowsCount != 0)
455 {
456 writer.endElement(HTML.TBODY_ELEM);
457 }
458 writer.startElement(HTML.TBODY_ELEM, null);
459
460 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element" +
461 (bodyrowsCount == 0 ? "" : bodyrowsCount), null);
462 bodyrowsCount++;
463 }
464
465 renderRowStart(facesContext, writer, uiData, styles, nr);
466 rowStartRendered = true;
467 }
468
469 List children = null;
470 int columnStyleIndex = 0;
471 for (int j = 0, size = getChildCount(component); j < size; j++)
472 {
473 if (children == null)
474 {
475 children = getChildren(component);
476 }
477 UIComponent child = (UIComponent) children.get(j);
478 if (child.isRendered())
479 {
480 boolean columnRendering = child instanceof UIColumn;
481
482 if (columnRendering)
483 {
484 beforeColumn(facesContext, uiData, columnStyleIndex);
485 }
486
487 encodeColumnChild(facesContext, writer, uiData, child,
488 styles, nc * uiData.getChildCount() + columnStyleIndex);
489
490 if (columnRendering)
491 {
492 afterColumn(facesContext, uiData, columnStyleIndex);
493 }
494 columnStyleIndex = columnStyleIndex +
495 getColumnCountForComponent(facesContext, uiData, child);
496 }
497 }
498
499 if (hasNewspaperTableSpacer(uiData))
500 {
501
502 if(nc < newspaperColumns - 1)
503 {
504 renderSpacerCell(facesContext, writer, uiData);
505 }
506 }
507 }
508 if (rowStartRendered)
509 {
510 renderRowEnd(facesContext, writer, uiData);
511 afterRow(facesContext, uiData);
512 }
513 }
514
515 if(bodyrowsCount != 0)
516 {
517
518 writer.endElement(HTML.TBODY_ELEM);
519 }
520 }
521
522 private void encodeInnerHtmlUnknownRowCount(FacesContext facesContext, UIComponent component)throws IOException
523 {
524 UIData uiData = (UIData) component;
525 ResponseWriter writer = facesContext.getResponseWriter();
526
527 Styles styles = getStyles(uiData);
528
529 Integer[] bodyrows = getBodyRows(facesContext, component);
530 int bodyrowsCount = 0;
531
532 int first = uiData.getFirst();
533 int rows = uiData.getRows();
534 int currentRow = first;
535 boolean isRowRendered = false;
536
537 while(true)
538 {
539 uiData.setRowIndex(currentRow);
540 if (!uiData.isRowAvailable())
541 {
542 break;
543 }
544
545 isRowRendered = true;
546
547
548 beforeRow(facesContext, uiData);
549
550
551 if(ArrayUtils.contains(bodyrows, currentRow))
552 {
553
554 if(bodyrowsCount != 0)
555 {
556 writer.endElement(HTML.TBODY_ELEM);
557 }
558 writer.startElement(HTML.TBODY_ELEM, null);
559
560 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element" +
561 (bodyrowsCount == 0 ? "" : bodyrowsCount), null);
562 bodyrowsCount++;
563 }
564
565 renderRowStart(facesContext, writer, uiData, styles, currentRow);
566
567 List<UIComponent> children = null;
568 int columnStyleIndex = 0;
569 for (int j = 0, size = getChildCount(component); j < size; j++)
570 {
571 if (children == null)
572 {
573 children = getChildren(component);
574 }
575 UIComponent child = (UIComponent) children.get(j);
576 if (child.isRendered())
577 {
578 boolean columnRendering = child instanceof UIColumn;
579
580 if (columnRendering)
581 {
582 beforeColumn(facesContext, uiData, columnStyleIndex);
583 }
584
585 encodeColumnChild(facesContext, writer, uiData, child,
586 styles, columnStyleIndex);
587
588 if (columnRendering)
589 {
590 afterColumn(facesContext, uiData, columnStyleIndex);
591 }
592 columnStyleIndex = columnStyleIndex +
593 getColumnCountForComponent(facesContext, uiData, child);
594 }
595 }
596
597 renderRowEnd(facesContext, writer, uiData);
598 afterRow(facesContext, uiData);
599
600 currentRow++;
601
602 if (rows > 0 && currentRow-first > rows )
603 {
604 break;
605 }
606 }
607
608 if (!isRowRendered)
609 {
610
611 writer.startElement(HTML.TBODY_ELEM, null);
612 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element", null);
613 writer.startElement(HTML.TR_ELEM, null);
614 writer.startElement(HTML.TD_ELEM, null);
615 writer.endElement(HTML.TD_ELEM);
616 writer.endElement(HTML.TR_ELEM);
617 writer.endElement(HTML.TBODY_ELEM);
618 return;
619 }
620
621 if(bodyrowsCount != 0)
622 {
623
624 writer.endElement(HTML.TBODY_ELEM);
625 }
626 }
627
628 protected void encodeColumnChild(FacesContext facesContext, ResponseWriter writer,
629 UIData uiData, UIComponent component, Styles styles, int columnStyleIndex) throws IOException
630 {
631 if (component instanceof UIColumn)
632 {
633 renderColumnBody(facesContext, writer, uiData, component, styles, columnStyleIndex);
634 }
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649 protected void renderColumnBody(
650 FacesContext facesContext,
651 ResponseWriter writer,
652 UIData uiData,
653 UIComponent component,
654 Styles styles, int columnStyleIndex) throws IOException
655 {
656
657 Object rowHeaderAttr = component.getAttributes().get(JSFAttr.ROW_HEADER_ATTR);
658 boolean rowHeader = rowHeaderAttr != null && ((Boolean) rowHeaderAttr);
659
660 if(rowHeader)
661 {
662 writer.startElement(HTML.TH_ELEM, null);
663 writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_ROW_VALUE, null);
664 }
665 else
666 {
667 writer.startElement(HTML.TD_ELEM, null);
668 }
669 String styleClass = null;
670 if (component instanceof HtmlColumn)
671 {
672 styleClass = ((HtmlColumn) component).getStyleClass();
673 }
674 if (styles.hasColumnStyle())
675 {
676 if (styleClass == null)
677 {
678 styleClass = styles.getColumnStyle(columnStyleIndex);
679 }
680 else
681 {
682 styleClass = styleClass+" "+styles.getColumnStyle(columnStyleIndex);
683 }
684 }
685 if (styleClass != null)
686 {
687 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
688 }
689
690 component.encodeAll(facesContext);
691 if(rowHeader)
692 {
693 writer.endElement(HTML.TH_ELEM);
694 }
695 else
696 {
697 writer.endElement(HTML.TD_ELEM);
698 }
699 }
700
701
702
703
704
705
706
707
708 protected void renderRowStart(
709 FacesContext facesContext,
710 ResponseWriter writer,
711 UIData uiData,
712 Styles styles, int rowStyleIndex) throws IOException
713 {
714 writer.startElement(HTML.TR_ELEM, null);
715
716 renderRowStyle(facesContext, writer, uiData, styles, rowStyleIndex);
717
718 Object rowId = uiData.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.ROW_ID);
719
720 if (rowId != null)
721 {
722 writer.writeAttribute(HTML.ID_ATTR, rowId.toString(), null);
723 }
724 }
725
726 protected void renderRowStyle(FacesContext facesContext, ResponseWriter writer,
727 UIData uiData, Styles styles, int rowStyleIndex) throws IOException
728 {
729 String rowClass = null;
730 if (uiData instanceof HtmlDataTable)
731 {
732 rowClass = ((HtmlDataTable) uiData).getRowClass();
733 }
734 if (styles.hasRowStyle())
735 {
736 if (rowClass == null)
737 {
738 rowClass = styles.getRowStyle(rowStyleIndex);
739 }
740 else
741 {
742 rowClass = rowClass+" "+styles.getRowStyle(rowStyleIndex);
743 }
744 }
745 if (rowClass != null)
746 {
747 writer.writeAttribute(HTML.CLASS_ATTR, rowClass, null);
748 }
749 }
750
751
752
753
754
755
756
757
758 protected void renderRowEnd(
759 FacesContext facesContext,
760 ResponseWriter writer,
761 UIData uiData) throws IOException
762 {
763 writer.endElement(HTML.TR_ELEM);
764 }
765
766
767
768
769
770
771
772
773 protected void beforeTable(FacesContext facesContext, UIData uiData) throws IOException
774 {
775 }
776
777
778
779
780
781
782
783
784
785
786
787
788 protected void beforeBody(FacesContext facesContext, UIData uiData) throws IOException
789 {
790 ResponseWriter writer = facesContext.getResponseWriter();
791
792 renderCaptionFacet(facesContext, writer, uiData);
793 renderColgroupsFacet(facesContext, writer, uiData);
794 renderFacet(facesContext, writer, uiData, true);
795 renderFacet(facesContext, writer, uiData, false);
796 }
797
798
799
800
801
802
803
804
805 protected void beforeRow(FacesContext facesContext, UIData uiData) throws IOException
806 {
807 }
808
809
810
811
812
813
814
815
816 protected void afterRow(FacesContext facesContext, UIData uiData) throws IOException
817 {
818 }
819
820
821
822
823
824
825
826 protected void beforeColumn(FacesContext facesContext, UIData uiData, int columnIndex) throws IOException
827 {
828 }
829
830
831
832
833
834
835
836 protected void afterColumn(FacesContext facesContext, UIData uiData, int columnIndex) throws IOException
837 {
838 }
839
840
841
842
843
844
845
846
847 protected int getColumnCountForComponent(FacesContext facesContext, UIData uiData, UIComponent child)
848 {
849 if (child instanceof UIColumn)
850 {
851 return 1;
852 }
853 return 0;
854 }
855
856
857
858
859
860
861
862
863 protected void beforeColumnHeaderOrFooter(FacesContext facesContext, UIData uiData, boolean header,
864 int columnIndex) throws IOException
865 {
866 }
867
868
869
870
871
872
873
874
875 protected void afterColumnHeaderOrFooter(FacesContext facesContext, UIData uiData, boolean header,
876 int columnIndex) throws IOException
877 {
878 }
879
880
881
882
883
884
885
886 protected void inBodyStart(FacesContext facesContext, UIData uiData) throws IOException
887 {
888 }
889
890
891
892
893
894
895
896
897 protected void afterBody(FacesContext facesContext, UIData uiData) throws IOException
898 {
899 }
900
901
902
903
904
905
906
907
908 protected void afterTable(FacesContext facesContext, UIData uiData) throws IOException
909 {
910 }
911
912
913
914
915 public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException
916 {
917 RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
918
919 endTable(facesContext, uiComponent);
920
921 afterTable(facesContext, (UIData) uiComponent);
922 }
923
924
925
926
927 protected void endTable(FacesContext facesContext, UIComponent uiComponent) throws IOException
928 {
929 ResponseWriter writer = facesContext.getResponseWriter();
930 writer.endElement(HTML.TABLE_ELEM);
931 }
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952 protected void renderFacet(FacesContext facesContext, ResponseWriter writer,
953 UIComponent component, boolean header)
954 throws IOException
955 {
956 int colspan = 0;
957 boolean hasColumnFacet = false;
958 int childCount = component.getChildCount();
959 for (int i = 0; i < childCount; i++)
960 {
961 UIComponent uiComponent = component.getChildren().get(i);
962 if(uiComponent.isRendered())
963 {
964
965 colspan += determineChildColSpan(uiComponent);
966
967
968
969 if (!hasColumnFacet)
970 {
971 hasColumnFacet = hasFacet(header, uiComponent);
972 }
973 }
974 }
975
976
977 UIComponent facet = null;
978 if (component.getFacetCount() > 0)
979 {
980 facet = header ? (UIComponent) component.getFacets().get(HEADER_FACET_NAME)
981 : (UIComponent) component.getFacets().get(FOOTER_FACET_NAME);
982 }
983 if (facet != null || hasColumnFacet)
984 {
985
986
987 String elemName = determineHeaderFooterTag(facesContext, component, header);
988
989 if (elemName != null)
990 {
991 writer.startElement(elemName, null);
992 }
993 if (header)
994 {
995 String headerStyleClass = getHeaderClass(component);
996 if (facet != null)
997 {
998 renderTableHeaderRow(facesContext, writer, component, facet, headerStyleClass, colspan);
999 }
1000 if (hasColumnFacet)
1001 {
1002 renderColumnHeaderRow(facesContext, writer, component, headerStyleClass);
1003 }
1004 }
1005 else
1006 {
1007 String footerStyleClass = getFooterClass(component);
1008 if (hasColumnFacet)
1009 {
1010 renderColumnFooterRow(facesContext, writer, component, footerStyleClass);
1011 }
1012 if (facet != null)
1013 {
1014 renderTableFooterRow(facesContext, writer, component, facet, footerStyleClass, colspan);
1015 }
1016 }
1017 if (elemName != null)
1018 {
1019 writer.endElement(elemName);
1020 }
1021 }
1022 }
1023
1024 protected String determineHeaderFooterTag(FacesContext facesContext, UIComponent component, boolean header)
1025 {
1026 return header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM;
1027 }
1028
1029
1030
1031
1032
1033
1034 protected boolean hasFacet(boolean header, UIComponent uiComponent)
1035 {
1036 if (uiComponent instanceof UIColumn)
1037 {
1038 UIColumn uiColumn = (UIColumn) uiComponent;
1039 return header ? uiColumn.getHeader() != null : uiColumn.getFooter() != null;
1040 }
1041 return false;
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054 protected int determineChildColSpan(UIComponent uiComponent)
1055 {
1056 if (uiComponent instanceof UIColumn)
1057 {
1058 return 1;
1059 }
1060 return 0;
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074 protected void renderTableHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
1075 UIComponent headerFacet, String headerStyleClass, int colspan) throws IOException
1076 {
1077 renderTableHeaderOrFooterRow(facesContext, writer, component, headerFacet, headerStyleClass,
1078 determineHeaderCellTag(facesContext, component),
1079 colspan, true);
1080 }
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093 protected void renderTableFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
1094 UIComponent footerFacet, String footerStyleClass, int colspan) throws IOException
1095 {
1096 renderTableHeaderOrFooterRow(facesContext, writer, component, footerFacet, footerStyleClass, HTML.TD_ELEM,
1097 colspan, false);
1098 }
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
1111 String headerStyleClass) throws IOException
1112 {
1113 renderColumnHeaderOrFooterRow(facesContext, writer, component, headerStyleClass, true);
1114 }
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125 protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
1126 String footerStyleClass) throws IOException
1127 {
1128 renderColumnHeaderOrFooterRow(facesContext, writer, component, footerStyleClass, false);
1129 }
1130
1131 protected void renderTableHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer,
1132 UIComponent component,
1133 UIComponent facet, String styleClass, String colElementName, int colspan, boolean isHeader)
1134 throws IOException
1135 {
1136 writer.startElement(HTML.TR_ELEM, null);
1137 writer.startElement(colElementName, null);
1138 if (colElementName.equals(determineHeaderCellTag(facesContext, component)) && isHeader)
1139 {
1140 writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_COLGROUP_VALUE, null);
1141 }
1142
1143
1144 int newsPaperColumns = getNewspaperColumns(component);
1145 int totalColumns = colspan * newsPaperColumns;
1146 if(hasNewspaperTableSpacer(component))
1147 {
1148 totalColumns = totalColumns + newsPaperColumns - 1;
1149 }
1150
1151 if (totalColumns > 0)
1152 {
1153 writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.valueOf(totalColumns), null);
1154 }
1155 if (styleClass != null)
1156 {
1157 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
1158 }
1159 if (facet != null)
1160 {
1161
1162 facet.encodeAll(facesContext);
1163 }
1164 writer.endElement(colElementName);
1165 writer.endElement(HTML.TR_ELEM);
1166 }
1167
1168
1169
1170
1171 private void renderColumnHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer,
1172 UIComponent component, String styleClass, boolean header) throws IOException
1173 {
1174
1175 writer.startElement(HTML.TR_ELEM, null);
1176 int columnIndex = 0;
1177 int newspaperColumns = getNewspaperColumns(component);
1178 for(int nc = 0; nc < newspaperColumns; nc++)
1179 {
1180 for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
1181 {
1182 UIComponent uiComponent = component.getChildren().get(i);
1183 if (uiComponent.isRendered())
1184 {
1185 if (component instanceof UIData && uiComponent instanceof UIColumn)
1186 {
1187 beforeColumnHeaderOrFooter(facesContext, (UIData) component, header, columnIndex);
1188 }
1189
1190 renderColumnChildHeaderOrFooterRow(facesContext, writer, uiComponent, styleClass, header);
1191
1192 if (component instanceof UIData && uiComponent instanceof UIColumn)
1193 {
1194 afterColumnHeaderOrFooter(facesContext, (UIData) component, header, columnIndex);
1195 }
1196 }
1197 columnIndex += 1;
1198 }
1199
1200 if (hasNewspaperTableSpacer(component))
1201 {
1202
1203 if(nc < newspaperColumns - 1)
1204 {
1205 renderSpacerCell(facesContext, writer, component);
1206 }
1207 }
1208 }
1209 writer.endElement(HTML.TR_ELEM);
1210 }
1211
1212
1213
1214
1215 protected void renderSpacerCell(FacesContext facesContext, ResponseWriter writer, UIComponent component)
1216 throws IOException
1217 {
1218 UIComponent spacer = getNewspaperTableSpacer(component);
1219 if(spacer == null)
1220 {
1221 return;
1222 }
1223
1224 writer.startElement(HTML.TD_ELEM, null);
1225
1226 spacer.encodeAll(facesContext);
1227 writer.endElement(HTML.TD_ELEM);
1228 }
1229
1230 protected void renderColumnChildHeaderOrFooterRow(FacesContext facesContext,
1231 ResponseWriter writer, UIComponent uiComponent, String styleClass, boolean isHeader) throws IOException
1232 {
1233 if (uiComponent instanceof UIColumn)
1234 {
1235
1236 if (uiComponent instanceof HtmlColumn)
1237 {
1238 HtmlColumn column = (HtmlColumn)uiComponent;
1239 if (isHeader && column.getHeaderClass()!=null)
1240 {
1241 styleClass = column.getHeaderClass();
1242 }
1243 else if (!isHeader && column.getFooterClass()!=null)
1244 {
1245 styleClass = column.getFooterClass();
1246 }
1247 }
1248 else
1249 {
1250
1251
1252
1253
1254 UIColumn column = (UIColumn) uiComponent;
1255 if (isHeader)
1256 {
1257 String headerClass = (String) column.getAttributes().get("headerClass");
1258 if (headerClass != null)
1259 {
1260 styleClass = (String) headerClass;
1261 }
1262 }
1263 else
1264 {
1265 String footerClass = (String) column.getAttributes().get("footerClass");
1266 if (footerClass != null)
1267 {
1268 styleClass = (String) footerClass;
1269 }
1270 }
1271 }
1272
1273 if (isHeader)
1274 {
1275 renderColumnHeaderCell(facesContext, writer, uiComponent,
1276 ((UIColumn) uiComponent).getHeader(), styleClass, 0);
1277 }
1278 else
1279 {
1280 renderColumnFooterCell(facesContext, writer, uiComponent,
1281 ((UIColumn) uiComponent).getFooter(), styleClass, 0);
1282 }
1283 }
1284 }
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 protected void renderColumnHeaderCell(FacesContext facesContext, ResponseWriter writer, UIColumn uiColumn,
1297 String headerStyleClass, int colspan) throws IOException
1298 {
1299 renderColumnHeaderCell(facesContext, writer, uiColumn, uiColumn.getHeader(), headerStyleClass, colspan);
1300 }
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317 protected void renderColumnHeaderCell(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent,
1318 UIComponent facet, String headerStyleClass, int colspan) throws IOException
1319 {
1320 writer.startElement(determineHeaderCellTag(facesContext, uiComponent.getParent()), null);
1321 if (colspan > 1)
1322 {
1323 writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.valueOf(colspan), null);
1324 }
1325 if (headerStyleClass != null)
1326 {
1327 writer.writeAttribute(HTML.CLASS_ATTR, headerStyleClass, null);
1328 }
1329
1330 writer.writeAttribute(HTML.SCOPE_ATTR, "col", null);
1331
1332 if (facet != null)
1333 {
1334
1335 facet.encodeAll(facesContext);
1336 }
1337 writer.endElement(determineHeaderCellTag(facesContext, uiComponent.getParent()));
1338 }
1339
1340 protected String determineHeaderCellTag(FacesContext facesContext, UIComponent uiComponent)
1341 {
1342 return HTML.TH_ELEM;
1343 }
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355 protected void renderColumnFooterCell(FacesContext facesContext, ResponseWriter writer, UIColumn uiColumn,
1356 String footerStyleClass, int colspan) throws IOException
1357 {
1358 renderColumnFooterCell(facesContext, writer, uiColumn, uiColumn.getFooter(), footerStyleClass, colspan);
1359 }
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 protected void renderColumnFooterCell(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent,
1373 UIComponent facet, String footerStyleClass, int colspan) throws IOException
1374 {
1375 writer.startElement(HTML.TD_ELEM, null);
1376 if (colspan > 1)
1377 {
1378 writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.valueOf(colspan), null);
1379 }
1380 if (footerStyleClass != null)
1381 {
1382 writer.writeAttribute(HTML.CLASS_ATTR, footerStyleClass, null);
1383 }
1384 if (facet != null)
1385 {
1386
1387 facet.encodeAll(facesContext);
1388 }
1389 writer.endElement(HTML.TD_ELEM);
1390 }
1391
1392
1393
1394
1395
1396
1397 protected static String getHeaderClass(UIComponent component)
1398 {
1399 if (component instanceof HtmlDataTable)
1400 {
1401 return ((HtmlDataTable) component).getHeaderClass();
1402 }
1403 else
1404 {
1405 return (String) component.getAttributes().get(
1406 org.apache.myfaces.shared.renderkit.JSFAttr.HEADER_CLASS_ATTR);
1407 }
1408 }
1409
1410
1411
1412
1413
1414
1415 protected static String getFooterClass(UIComponent component)
1416 {
1417 if (component instanceof HtmlDataTable)
1418 {
1419 return ((HtmlDataTable) component).getFooterClass();
1420 }
1421 else
1422 {
1423 return (String) component.getAttributes().get(
1424 org.apache.myfaces.shared.renderkit.JSFAttr.FOOTER_CLASS_ATTR);
1425 }
1426 }
1427
1428 public void decode(FacesContext context, UIComponent component)
1429 {
1430 super.decode(context, component);
1431
1432 HtmlRendererUtils.decodeClientBehaviors(context, component);
1433 }
1434
1435 }