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