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