1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.layout;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
20 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
21 import org.kuali.rice.krad.datadictionary.parse.BeanTags;
22 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
23 import org.kuali.rice.krad.uif.UifConstants;
24 import org.kuali.rice.krad.uif.component.Component;
25 import org.kuali.rice.krad.uif.component.DataBinding;
26 import org.kuali.rice.krad.uif.component.KeepExpression;
27 import org.kuali.rice.krad.uif.container.CollectionGroup;
28 import org.kuali.rice.krad.uif.container.Container;
29 import org.kuali.rice.krad.uif.container.Group;
30 import org.kuali.rice.krad.uif.element.Action;
31 import org.kuali.rice.krad.uif.element.Label;
32 import org.kuali.rice.krad.uif.field.DataField;
33 import org.kuali.rice.krad.uif.field.Field;
34 import org.kuali.rice.krad.uif.field.FieldGroup;
35 import org.kuali.rice.krad.uif.field.InputField;
36 import org.kuali.rice.krad.uif.field.MessageField;
37 import org.kuali.rice.krad.uif.util.ColumnCalculationInfo;
38 import org.kuali.rice.krad.uif.util.ComponentFactory;
39 import org.kuali.rice.krad.uif.util.ComponentUtils;
40 import org.kuali.rice.krad.uif.util.ExpressionUtils;
41 import org.kuali.rice.krad.uif.view.View;
42 import org.kuali.rice.krad.uif.widget.RichTable;
43 import org.kuali.rice.krad.web.form.UifFormBase;
44
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Set;
48 import java.util.TreeMap;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 @BeanTag(name = "tableCollectionLayout", parent = "Uif-TableCollectionLayout")
66 public class TableLayoutManager extends GridLayoutManager implements CollectionLayoutManager {
67 private static final long serialVersionUID = 3622267585541524208L;
68
69 private boolean useShortLabels;
70 private boolean repeatHeader;
71 private Label headerLabelPrototype;
72
73 private boolean renderSequenceField;
74 private boolean generateAutoSequence;
75 private Field sequenceFieldPrototype;
76
77 private FieldGroup actionFieldPrototype;
78 private FieldGroup subCollectionFieldGroupPrototype;
79 private Field selectFieldPrototype;
80
81 private boolean separateAddLine;
82 private Group addLineGroup;
83
84
85 private int numberOfDataColumns;
86
87 private List<Label> headerLabels;
88 private List<Component> dataFields;
89
90 private RichTable richTable;
91 private boolean headerAdded;
92
93 private int actionColumnIndex = -1;
94 private String actionColumnPlacement;
95
96
97 private Group rowDetailsGroup;
98 private String rowDetailsLinkName = "Details";
99 private boolean rowDetailsSwapActionImage;
100 private boolean rowDetailsOpen;
101 private boolean showToggleAllDetails;
102 private Action toggleAllDetailsAction;
103 private boolean ajaxDetailsRetrieval;
104 private Action expandDetailsActionPrototype;
105
106
107 @KeepExpression
108 private String groupingTitle;
109 private String groupingPrefix;
110 private int groupingColumnIndex;
111 private List<String> groupingPropertyNames;
112
113
114 private boolean renderOnlyLeftTotalLabels;
115 private boolean showTotal;
116 private boolean showPageTotal;
117 private boolean showGroupTotal;
118 private boolean generateGroupTotalRows;
119 private Label totalLabel;
120 private Label pageTotalLabel;
121 private Label groupTotalLabelPrototype;
122
123 private List<String> columnsToCalculate;
124 private List<ColumnCalculationInfo> columnCalculations;
125 private List<Component> footerCalculationComponents;
126
127 public TableLayoutManager() {
128 useShortLabels = false;
129 repeatHeader = false;
130 renderSequenceField = true;
131 generateAutoSequence = false;
132 separateAddLine = false;
133 rowDetailsOpen = false;
134
135 headerLabels = new ArrayList<Label>();
136 dataFields = new ArrayList<Component>();
137 columnsToCalculate = new ArrayList<String>();
138 columnCalculations = new ArrayList<ColumnCalculationInfo>();
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152 @Override
153 public void performInitialization(View view, Object model, Container container) {
154 CollectionGroup collectionGroup = (CollectionGroup) container;
155
156 this.setupDetails(collectionGroup, view);
157 this.setupGrouping(collectionGroup, view);
158
159 if (collectionGroup.isAddViaLightBox()) {
160 setSeparateAddLine(true);
161 }
162
163 super.performInitialization(view, model, container);
164
165 getRowCssClasses().clear();
166
167 if (generateAutoSequence && !(getSequenceFieldPrototype() instanceof MessageField)) {
168 sequenceFieldPrototype = ComponentFactory.getMessageField();
169 view.assignComponentIds(getSequenceFieldPrototype());
170 }
171 }
172
173
174
175
176
177
178
179
180
181
182 @Override
183 public void performApplyModel(View view, Object model, Container container) {
184 super.performApplyModel(view, model, container);
185
186 for (ColumnCalculationInfo cInfo : columnCalculations) {
187 ExpressionUtils.populatePropertyExpressionsFromGraph(cInfo, false);
188 }
189 }
190
191
192
193
194
195
196
197
198
199 @Override
200 public void performFinalize(View view, Object model, Container container) {
201 super.performFinalize(view, model, container);
202
203 UifFormBase formBase = (UifFormBase) model;
204
205 CollectionGroup collectionGroup = (CollectionGroup) container;
206
207 int totalColumns = getNumberOfDataColumns();
208 if (renderSequenceField) {
209 totalColumns++;
210 }
211
212 if (collectionGroup.isIncludeLineSelectionField()) {
213 totalColumns++;
214 }
215
216 if (collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly()) {
217 totalColumns++;
218 }
219
220 setNumberOfColumns(totalColumns);
221
222
223 if (UifConstants.ActionEvents.ADD_LINE.equals(formBase.getActionEvent())) {
224 String highlightScript = "jQuery(\"#" + container.getId() + " tr:first\").effect(\"highlight\",{}, 6000);";
225 String onReadyScript = collectionGroup.getOnDocumentReadyScript();
226 if (StringUtils.isNotBlank(onReadyScript)) {
227 highlightScript = onReadyScript + highlightScript;
228 }
229 collectionGroup.setOnDocumentReadyScript(highlightScript);
230 }
231
232
233 if (columnCalculations != null && richTable != null &&
234 this.getDataFields() != null && !this.getDataFields().isEmpty()) {
235 setupColumnCalculations(view, model, container, totalColumns);
236 }
237
238
239 if ((groupingPropertyNames != null || StringUtils.isNotBlank(this.getGroupingTitle())) && richTable != null) {
240 richTable.setGroupingOptionsJSString("{iGroupingColumnIndex: "
241 + groupingColumnIndex
242 + ", bGenerateGroupTotalRows:"
243 + this.generateGroupTotalRows
244 + ", bSetGroupingClassOnTR: true"
245 + ", sGroupingClass: 'uif-groupRow'"
246 + (this.getGroupingPrefix() != null ? ", sGroupLabelPrefix: '" + this.getGroupingPrefix() + "'" :
247 "")
248 + "}");
249 }
250 }
251
252
253
254
255
256
257
258
259 private void setupGrouping(CollectionGroup collectionGroup, View view) {
260
261 String groupingTitleExpression = "";
262 if (StringUtils.isNotBlank(this.getPropertyExpression("groupingTitle"))) {
263 groupingTitleExpression = this.getPropertyExpression("groupingTitle");
264 this.setGroupingTitle(this.getPropertyExpression("groupingTitle"));
265 } else if (this.getGroupingPropertyNames() != null) {
266
267 for (String propertyName : this.getGroupingPropertyNames()) {
268 groupingTitleExpression = groupingTitleExpression + ", " + propertyName;
269 }
270
271 groupingTitleExpression = groupingTitleExpression.replaceFirst(", ", "@{#lp.");
272 groupingTitleExpression = groupingTitleExpression.replace(", ", "}, @{#lp.");
273 groupingTitleExpression = groupingTitleExpression.trim() + "}";
274 }
275
276 if (StringUtils.isNotBlank(groupingTitleExpression)) {
277 MessageField groupingMessageField = ComponentFactory.getColGroupingField();
278 groupingMessageField.getMessage().getPropertyExpressions().put("messageText", groupingTitleExpression);
279 groupingMessageField.setLabel("Group");
280
281 view.assignComponentIds(groupingMessageField);
282
283 List<Component> theItems = new ArrayList<Component>();
284 theItems.add(groupingMessageField);
285 theItems.addAll(collectionGroup.getItems());
286 collectionGroup.setItems(theItems);
287 }
288 }
289
290
291
292
293
294
295
296
297
298 private void setupColumnCalculations(View view, Object model, Container container, int totalColumns) {
299 footerCalculationComponents = new ArrayList<Component>(totalColumns);
300
301
302 for (int i = 0; i < totalColumns; i++) {
303 footerCalculationComponents.add(null);
304 }
305
306 int leftLabelColumnIndex = 0;
307 if (groupingPropertyNames != null || StringUtils.isNotBlank(this.getGroupingTitle())) {
308 leftLabelColumnIndex = 1;
309 }
310
311
312 for (ColumnCalculationInfo cInfo : columnCalculations) {
313
314 if (StringUtils.isNotBlank(cInfo.getPropertyName())) {
315 for (int i = 0; i < this.getNumberOfColumns(); i++) {
316 Component component = this.getDataFields().get(i);
317 if (component != null && component instanceof DataField &&
318 ((DataField) component).getPropertyName().equals(cInfo.getPropertyName())) {
319 cInfo.setColumnNumber(i);
320 }
321 }
322 this.getColumnsToCalculate().add(cInfo.getColumnNumber().toString());
323 } else {
324 throw new RuntimeException("TableLayoutManager(" + container.getId() + "->" + this.getId() +
325 ") ColumnCalculationInfo MUST have a propertyName set");
326 }
327
328 FieldGroup calculationFieldGroup;
329 List<Component> groupItems;
330 Component columnComponent = footerCalculationComponents.get(cInfo.getColumnNumber());
331
332
333 calculationFieldGroup = ComponentFactory.getFieldGroup();
334 calculationFieldGroup.addDataAttribute("role", "totalsBlock");
335 groupItems = new ArrayList<Component>();
336
337
338 if (cInfo.isShowPageTotal()) {
339 Field pageTotalDataField = setupTotalField(cInfo.getPageTotalField(), cInfo, this.isShowPageTotal(),
340 this.getPageTotalLabel(), "pageTotal", leftLabelColumnIndex);
341 groupItems.add(pageTotalDataField);
342 }
343
344
345 if (cInfo.isShowTotal()) {
346 Field totalDataField = setupTotalField(cInfo.getTotalField(), cInfo, this.isShowTotal(),
347 this.getTotalLabel(), "total", leftLabelColumnIndex);
348
349
350
351
352 if (!cInfo.isRecalculateTotalClientside()) {
353 totalDataField.addDataAttribute("skipTotal", "true");
354 }
355
356 groupItems.add(totalDataField);
357 }
358
359
360
361 if (cInfo.isShowGroupTotal()) {
362 Field groupTotalDataField = setupTotalField(cInfo.getGroupTotalFieldPrototype(), cInfo,
363 this.isShowGroupTotal(), this.getGroupTotalLabelPrototype(), "groupTotal",
364 leftLabelColumnIndex);
365 groupTotalDataField.setId(container.getId() + "_gTotal" + cInfo.getColumnNumber());
366 groupTotalDataField.setStyle("display: none;");
367 groupItems.add(groupTotalDataField);
368
369 if (this.isRenderOnlyLeftTotalLabels() && !this.isShowGroupTotal()) {
370 generateGroupTotalRows = false;
371 } else {
372 generateGroupTotalRows = true;
373 }
374 }
375
376 calculationFieldGroup.setItems(groupItems);
377 view.assignComponentIds(calculationFieldGroup);
378
379
380
381
382 Component component = footerCalculationComponents.get(cInfo.getColumnNumber());
383 if (component != null && component instanceof FieldGroup) {
384 Group verticalComboCalcGroup = ComponentFactory.getVerticalBoxGroup();
385 view.assignComponentIds(verticalComboCalcGroup);
386 List<Component> comboGroupItems = new ArrayList<Component>();
387 comboGroupItems.add(component);
388 comboGroupItems.add(calculationFieldGroup);
389 verticalComboCalcGroup.setItems(comboGroupItems);
390 footerCalculationComponents.set(cInfo.getColumnNumber(), verticalComboCalcGroup);
391 } else if (component != null && component instanceof Group) {
392 List<Component> comboGroupItems = new ArrayList<Component>();
393 comboGroupItems.addAll(((Group) component).getItems());
394 comboGroupItems.add(calculationFieldGroup);
395 ((Group) component).setItems(comboGroupItems);
396 footerCalculationComponents.set(cInfo.getColumnNumber(), component);
397 } else {
398 footerCalculationComponents.set(cInfo.getColumnNumber(), calculationFieldGroup);
399 }
400 }
401
402
403
404 if (this.renderOnlyLeftTotalLabels && footerCalculationComponents.get(leftLabelColumnIndex) == null) {
405 Group labelGroup = ComponentFactory.getVerticalBoxGroup();
406 view.assignComponentIds(labelGroup);
407 List<Component> groupItems = new ArrayList<Component>();
408
409 if (this.isShowGroupTotal()) {
410
411 groupTotalLabelPrototype.setStyle("display: none;");
412 groupTotalLabelPrototype.addDataAttribute("role", "groupTotalLabel");
413 view.assignComponentIds(groupTotalLabelPrototype);
414 groupItems.add(groupTotalLabelPrototype);
415 }
416
417 if (this.isShowPageTotal()) {
418 view.assignComponentIds(pageTotalLabel);
419 groupItems.add(pageTotalLabel);
420 }
421
422 if (this.isShowTotal()) {
423 view.assignComponentIds(totalLabel);
424 groupItems.add(totalLabel);
425 }
426
427 labelGroup.setItems(groupItems);
428
429 footerCalculationComponents.set(leftLabelColumnIndex, labelGroup);
430 }
431
432
433
434 for (Component component : footerCalculationComponents) {
435 if (component != null) {
436 component.performInitialization(view, model);
437 component.performApplyModel(view, model, container);
438 component.performFinalize(view, model, container);
439 }
440 }
441
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455
456 private Field setupTotalField(Field totalField, ColumnCalculationInfo cInfo, boolean show, Label leftLabel,
457 String type, int leftLabelColumnIndex) {
458
459 Field totalDataField = totalField;
460 totalDataField.addDataAttribute("role", type);
461 totalDataField.addDataAttribute("function", cInfo.getCalculationFunctionName());
462 totalDataField.addDataAttribute("params", cInfo.getCalculationFunctionExtraData());
463
464 if (cInfo.getColumnNumber() != leftLabelColumnIndex) {
465
466
467 totalDataField.getFieldLabel().setRender(!this.isRenderOnlyLeftTotalLabels());
468 } else if (cInfo.getColumnNumber() == leftLabelColumnIndex && this.isRenderOnlyLeftTotalLabels()) {
469
470
471 totalDataField.setFieldLabel(leftLabel);
472 }
473
474 if (this.isRenderOnlyLeftTotalLabels()) {
475 totalDataField.setRender(show);
476 }
477
478 return totalDataField;
479 }
480
481
482
483
484
485
486
487
488
489
490
491
492
493 public void buildLine(View view, Object model, CollectionGroup collectionGroup, List<Field> lineFields,
494 List<FieldGroup> subCollectionFields, String bindingPath, List<Action> actions, String idSuffix,
495 Object currentLine, int lineIndex) {
496
497
498 if (dataFields.isEmpty()) {
499 if (isSuppressLineWrapping()) {
500 setNumberOfDataColumns(lineFields.size());
501 } else {
502 setNumberOfDataColumns(getNumberOfColumns());
503 }
504 }
505
506 boolean isAddLine = false;
507
508
509 if (lineIndex == -1 || (lineFields.size() != numberOfDataColumns
510 && ((lineIndex + 1) * numberOfDataColumns) < lineFields.size())) {
511 isAddLine = true;
512 }
513
514 boolean renderActions = collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly();
515 int extraColumns = 0;
516
517 if (collectionGroup.isHighlightNewItems() && ((UifFormBase) model).isAddedCollectionItem(currentLine)) {
518 getRowCssClasses().add(collectionGroup.getNewItemsCssClass());
519 } else if (isAddLine
520 && collectionGroup.isRenderAddLine()
521 && !collectionGroup.isReadOnly()
522 && !isSeparateAddLine()) {
523 getRowCssClasses().add(collectionGroup.getAddItemCssClass());
524 this.addStyleClass("uif-hasAddLine");
525 } else if (lineIndex != -1) {
526 getRowCssClasses().add("");
527 }
528
529
530 if (isAddLine && separateAddLine) {
531 if (StringUtils.isBlank(addLineGroup.getTitle()) && StringUtils.isBlank(
532 addLineGroup.getHeader().getHeaderText())) {
533 addLineGroup.getHeader().setHeaderText(collectionGroup.getAddLabel());
534 }
535 addLineGroup.setItems(lineFields);
536
537 List<Component> footerItems = new ArrayList<Component>(actions);
538 footerItems.addAll(addLineGroup.getFooter().getItems());
539 addLineGroup.getFooter().setItems(footerItems);
540
541 if (collectionGroup.isAddViaLightBox()) {
542 String actionScript = "showLightboxComponent('" + addLineGroup.getId() + "');";
543 if (StringUtils.isNotBlank(collectionGroup.getAddViaLightBoxAction().getActionScript())) {
544 actionScript = collectionGroup.getAddViaLightBoxAction().getActionScript() + actionScript;
545 }
546 collectionGroup.getAddViaLightBoxAction().setActionScript(actionScript);
547 addLineGroup.setStyle("display: none");
548 }
549
550 return;
551 }
552
553
554 if (!headerAdded) {
555 headerLabels = new ArrayList<Label>();
556 dataFields = new ArrayList<Component>();
557
558 buildTableHeaderRows(collectionGroup, lineFields);
559 ComponentUtils.pushObjectToContext(headerLabels, UifConstants.ContextVariableNames.LINE, currentLine);
560 ComponentUtils.pushObjectToContext(headerLabels, UifConstants.ContextVariableNames.INDEX, new Integer(
561 lineIndex));
562 headerAdded = true;
563 }
564
565
566 for (Field field : lineFields) {
567 field.setLabelRendered(true);
568 field.setFieldLabel(null);
569 }
570
571 int rowCount = calculateNumberOfRows(lineFields);
572 int rowSpan = rowCount + subCollectionFields.size();
573
574 if (actionColumnIndex == 1 && renderActions) {
575 addActionColumn(idSuffix, currentLine, lineIndex, rowSpan, actions);
576 }
577
578
579 if (renderSequenceField) {
580 Component sequenceField = null;
581 if (!isAddLine) {
582 sequenceField = ComponentUtils.copy(getSequenceFieldPrototype(), idSuffix);
583
584 sequenceField.addDataAttribute(UifConstants.DataAttributes.VIGNORE, "yes");
585 if (generateAutoSequence && (sequenceField instanceof MessageField)) {
586 ((MessageField) sequenceField).setMessageText(Integer.toString(lineIndex + 1));
587 }
588 } else {
589 sequenceField = ComponentUtils.copy(collectionGroup.getAddLineLabel(), idSuffix);
590 }
591 sequenceField.setRowSpan(rowSpan);
592
593 if (sequenceField instanceof DataBinding) {
594 ((DataBinding) sequenceField).getBindingInfo().setBindByNamePrefix(bindingPath);
595 }
596
597 ComponentUtils.updateContextForLine(sequenceField, currentLine, lineIndex, idSuffix);
598 dataFields.add(sequenceField);
599 extraColumns++;
600
601 if (actionColumnIndex == 2 && renderActions) {
602 addActionColumn(idSuffix, currentLine, lineIndex, rowSpan, actions);
603 }
604 }
605
606
607 if (collectionGroup.isIncludeLineSelectionField()) {
608 Field selectField = ComponentUtils.copy(getSelectFieldPrototype(), idSuffix);
609 CollectionLayoutUtils.prepareSelectFieldForLine(selectField, collectionGroup, bindingPath, currentLine);
610
611 ComponentUtils.updateContextForLine(selectField, currentLine, lineIndex, idSuffix);
612 dataFields.add(selectField);
613 extraColumns++;
614
615 if (renderActions) {
616 if ((actionColumnIndex == 3 && renderSequenceField) || (actionColumnIndex == 2
617 && !renderSequenceField)) {
618 addActionColumn(idSuffix, currentLine, lineIndex, rowSpan, actions);
619 }
620 }
621 }
622
623
624 int cellPosition = 0;
625 int columnNumber = 0;
626
627 boolean renderActionsLast = actionColumnIndex == -1 || actionColumnIndex > lineFields.size() + extraColumns;
628 boolean hasGrouping = (groupingPropertyNames != null || StringUtils.isNotBlank(this.getGroupingTitle()));
629 boolean insertActionField = false;
630
631 for (Field lineField : lineFields) {
632
633
634
635
636
637 insertActionField = (cellPosition != 0 && lineFields.size() != numberOfDataColumns) && renderActions && renderActionsLast && ((cellPosition % numberOfDataColumns) == 0);
638
639 cellPosition += lineField.getColSpan();
640 columnNumber++;
641
642
643 if (hasGrouping && lineField instanceof MessageField &&
644 lineField.getDataAttributes().get("role") != null && lineField.getDataAttributes().get("role")
645 .equals("grouping")) {
646 int groupFieldIndex = dataFields.size() - extraColumns;
647 dataFields.add(groupFieldIndex, lineField);
648 groupingColumnIndex = 0;
649 if (isAddLine) {
650 ((MessageField) lineField).getMessage().getPropertyExpressions().remove("messageText");
651 ((MessageField) lineField).getMessage().setMessageText("addLine");
652 }
653 } else {
654
655 if (insertActionField) {
656 addActionColumn(idSuffix, currentLine, lineIndex, rowSpan, actions);
657 }
658
659 dataFields.add(lineField);
660 }
661
662
663 if (!renderActionsLast && cellPosition == (actionColumnIndex - extraColumns - 1)) {
664 addActionColumn(idSuffix, currentLine, lineIndex, rowSpan, actions);
665 }
666
667
668 if (lineField instanceof FieldGroup && ((FieldGroup) lineField).getItems() != null) {
669 for (Component component : ((FieldGroup) lineField).getItems()) {
670 if (component != null && component instanceof Action && component.getDataAttributes().get("role")
671 != null && component.getDataAttributes().get("role").equals("detailsLink") &&
672 StringUtils.isBlank(((Action) component).getActionScript())) {
673 ((Action) component).setActionScript("rowDetailsActionHandler(this,'" + this.getId() + "');");
674 }
675 }
676 }
677
678
679
680 if (lineField instanceof InputField && columnCalculations != null) {
681 for (ColumnCalculationInfo cInfo : columnCalculations) {
682 if (cInfo.getPropertyName().equals(((InputField) lineField).getPropertyName())) {
683 if (cInfo.isCalculateOnKeyUp()) {
684 lineField.addDataAttribute("total", "keyup");
685 } else {
686 lineField.addDataAttribute("total", "change");
687 }
688 lineField.addStyleClass("uif-calculationField");
689 }
690 }
691 }
692
693 }
694
695 if (lineFields.size() == numberOfDataColumns && renderActions && renderActionsLast) {
696 addActionColumn(idSuffix, currentLine, lineIndex, rowSpan, actions);
697 }
698
699
700 for (FieldGroup subCollectionField : subCollectionFields) {
701 subCollectionField.setColSpan(numberOfDataColumns);
702 }
703
704
705 dataFields.addAll(subCollectionFields);
706 }
707
708
709
710
711
712
713
714
715
716
717 private void addActionColumn(String idSuffix, Object currentLine, int lineIndex, int rowSpan,
718 List<Action> actions) {
719 FieldGroup lineActionsField = ComponentUtils.copy(getActionFieldPrototype(), idSuffix);
720
721 ComponentUtils.updateContextForLine(lineActionsField, currentLine, lineIndex, idSuffix);
722 lineActionsField.setRowSpan(rowSpan);
723 lineActionsField.setItems(actions);
724
725 dataFields.add(lineActionsField);
726 }
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747 protected void buildTableHeaderRows(CollectionGroup collectionGroup, List<Field> lineFields) {
748
749
750 int rowCount = calculateNumberOfRows(lineFields);
751 boolean renderActions = collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly();
752 int extraColumns = 0;
753
754 if (actionColumnIndex == 1 && renderActions) {
755 addActionHeader(rowCount, 1);
756 }
757
758
759 if (renderSequenceField) {
760 getSequenceFieldPrototype().setLabelRendered(true);
761 getSequenceFieldPrototype().setRowSpan(rowCount);
762 addHeaderField(getSequenceFieldPrototype(), 1);
763 extraColumns++;
764
765 if (actionColumnIndex == 2 && renderActions) {
766 addActionHeader(rowCount, 2);
767 }
768 }
769
770
771 if (collectionGroup.isIncludeLineSelectionField()) {
772 getSelectFieldPrototype().setLabelRendered(true);
773 getSelectFieldPrototype().setRowSpan(rowCount);
774 addHeaderField(getSelectFieldPrototype(), 1);
775 extraColumns++;
776
777 if (actionColumnIndex == 3 && renderActions && renderSequenceField) {
778 addActionHeader(rowCount, 3);
779 } else if (actionColumnIndex == 2 && renderActions) {
780 addActionHeader(rowCount, 2);
781 }
782 }
783
784
785 int cellPosition = 0;
786 boolean renderActionsLast = actionColumnIndex == -1 || actionColumnIndex > lineFields.size() + extraColumns;
787 boolean insertActionHeader = false;
788 for (Field field : lineFields) {
789 if (!field.isRender() && StringUtils.isEmpty(field.getProgressiveRender())) {
790 continue;
791 }
792
793
794
795
796
797
798 insertActionHeader = (cellPosition != 0 && lineFields.size() != numberOfDataColumns && renderActions && renderActionsLast && ((cellPosition % numberOfDataColumns) == 0));
799
800 if ( insertActionHeader) {
801 addActionHeader(rowCount, cellPosition);
802 }
803
804 cellPosition += field.getColSpan();
805 addHeaderField(field, cellPosition);
806
807
808 if (renderActions && !renderActionsLast && cellPosition == actionColumnIndex - extraColumns - 1) {
809 cellPosition += 1;
810 addActionHeader(rowCount, cellPosition);
811 }
812 }
813
814 if (lineFields.size() == numberOfDataColumns && renderActions && renderActionsLast) {
815 cellPosition += 1;
816 addActionHeader(rowCount, cellPosition);
817 }
818 }
819
820
821
822
823
824
825
826 private void addActionHeader(int rowCount, int cellPosition) {
827 getActionFieldPrototype().setLabelRendered(true);
828 getActionFieldPrototype().setRowSpan(rowCount);
829 addHeaderField(getActionFieldPrototype(), cellPosition);
830 }
831
832
833
834
835
836
837
838
839
840
841 protected void addHeaderField(Field field, int column) {
842 Label headerLabel = ComponentUtils.copy(getHeaderLabelPrototype(), "_c" + column);
843 if (useShortLabels) {
844 headerLabel.setLabelText(field.getShortLabel());
845 } else {
846 headerLabel.setLabelText(field.getLabel());
847 }
848
849 headerLabel.setRowSpan(field.getRowSpan());
850 headerLabel.setColSpan(field.getColSpan());
851
852
853 headerLabel.setCellCssClasses(field.getCellCssClasses());
854
855 if ((field.getRequired() != null) && field.getRequired().booleanValue()) {
856 headerLabel.getRequiredMessage().setRender(!field.isReadOnly());
857 } else {
858 headerLabel.getRequiredMessage().setRender(false);
859 }
860
861 headerLabels.add(headerLabel);
862 }
863
864
865
866
867
868
869
870
871
872 protected int calculateNumberOfRows(List<? extends Field> items) {
873 int rowCount = 0;
874
875
876 if (isSuppressLineWrapping()) {
877 return 1;
878 }
879
880
881 if(items.size() % getNumberOfDataColumns() > 0){
882
883 Field field = items.get(items.size()-1);
884 field.setColSpan(1+(numberOfDataColumns-(items.size()%numberOfDataColumns)));
885 rowCount = ((items.size()/getNumberOfDataColumns())+1);
886 } else{
887 rowCount = items.size()/getNumberOfDataColumns();
888 }
889 return rowCount;
890 }
891
892
893
894
895 @Override
896 public Class<? extends Container> getSupportedContainer() {
897 return CollectionGroup.class;
898 }
899
900
901
902
903 @Override
904 public List<Component> getComponentsForLifecycle() {
905 List<Component> components = super.getComponentsForLifecycle();
906
907 components.add(richTable);
908 components.add(addLineGroup);
909 components.addAll(headerLabels);
910 components.addAll(dataFields);
911
912 for (ColumnCalculationInfo cInfo : columnCalculations) {
913 components.add(cInfo.getTotalField());
914 components.add(cInfo.getPageTotalField());
915 components.add(cInfo.getGroupTotalFieldPrototype());
916 }
917
918 if (isShowToggleAllDetails()) {
919 components.add(toggleAllDetailsAction);
920 }
921
922 return components;
923 }
924
925
926
927
928 @Override
929 public List<Component> getComponentPrototypes() {
930 List<Component> components = super.getComponentPrototypes();
931
932 components.add(getHeaderLabelPrototype());
933 components.add(getSequenceFieldPrototype());
934 components.add(getActionFieldPrototype());
935 components.add(getSubCollectionFieldGroupPrototype());
936 components.add(getSelectFieldPrototype());
937
938 return components;
939 }
940
941
942
943
944
945
946
947
948 @BeanTagAttribute(name = "useShortLabels")
949 public boolean isUseShortLabels() {
950 return this.useShortLabels;
951 }
952
953
954
955
956
957
958 public void setUseShortLabels(boolean useShortLabels) {
959 this.useShortLabels = useShortLabels;
960 }
961
962
963
964
965
966
967
968
969 @BeanTagAttribute(name = "repeatHeader")
970 public boolean isRepeatHeader() {
971 return this.repeatHeader;
972 }
973
974
975
976
977
978
979 public void setRepeatHeader(boolean repeatHeader) {
980 this.repeatHeader = repeatHeader;
981 }
982
983
984
985
986
987
988
989
990 @BeanTagAttribute(name = "headerLabelPrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
991 public Label getHeaderLabelPrototype() {
992 return this.headerLabelPrototype;
993 }
994
995
996
997
998
999
1000 public void setHeaderLabelPrototype(Label headerLabelPrototype) {
1001 this.headerLabelPrototype = headerLabelPrototype;
1002 }
1003
1004
1005
1006
1007
1008
1009
1010 public List<Label> getHeaderLabels() {
1011 return this.headerLabels;
1012 }
1013
1014
1015
1016
1017
1018
1019
1020 @BeanTagAttribute(name = "renderSequenceField")
1021 public boolean isRenderSequenceField() {
1022 return this.renderSequenceField;
1023 }
1024
1025
1026
1027
1028
1029
1030 public void setRenderSequenceField(boolean renderSequenceField) {
1031 this.renderSequenceField = renderSequenceField;
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041 @BeanTagAttribute(name = "sequencePropertyName")
1042 public String getSequencePropertyName() {
1043 if ((getSequenceFieldPrototype() != null) && (getSequenceFieldPrototype() instanceof DataField)) {
1044 return ((DataField) getSequenceFieldPrototype()).getPropertyName();
1045 }
1046
1047 return null;
1048 }
1049
1050
1051
1052
1053
1054
1055 public void setSequencePropertyName(String sequencePropertyName) {
1056 if ((getSequenceFieldPrototype() != null) && (getSequenceFieldPrototype() instanceof DataField)) {
1057 ((DataField) getSequenceFieldPrototype()).setPropertyName(sequencePropertyName);
1058 }
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074 @BeanTagAttribute(name = "generateAutoSequence")
1075 public boolean isGenerateAutoSequence() {
1076 return this.generateAutoSequence;
1077 }
1078
1079
1080
1081
1082
1083
1084 public void setGenerateAutoSequence(boolean generateAutoSequence) {
1085 this.generateAutoSequence = generateAutoSequence;
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095 @BeanTagAttribute(name = "sequenceFieldPrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1096 public Field getSequenceFieldPrototype() {
1097 return this.sequenceFieldPrototype;
1098 }
1099
1100
1101
1102
1103
1104
1105 public void setSequenceFieldPrototype(Field sequenceFieldPrototype) {
1106 this.sequenceFieldPrototype = sequenceFieldPrototype;
1107 }
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121 @BeanTagAttribute(name = "actionFieldPrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1122 public FieldGroup getActionFieldPrototype() {
1123 return this.actionFieldPrototype;
1124 }
1125
1126
1127
1128
1129
1130
1131 public void setActionFieldPrototype(FieldGroup actionFieldPrototype) {
1132 this.actionFieldPrototype = actionFieldPrototype;
1133 }
1134
1135
1136
1137
1138 @BeanTagAttribute(name = "subCollectionFieldGroupPrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1139 public FieldGroup getSubCollectionFieldGroupPrototype() {
1140 return this.subCollectionFieldGroupPrototype;
1141 }
1142
1143
1144
1145
1146
1147
1148 public void setSubCollectionFieldGroupPrototype(FieldGroup subCollectionFieldGroupPrototype) {
1149 this.subCollectionFieldGroupPrototype = subCollectionFieldGroupPrototype;
1150 }
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166 @BeanTagAttribute(name = "selectFieldPrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1167 public Field getSelectFieldPrototype() {
1168 return selectFieldPrototype;
1169 }
1170
1171
1172
1173
1174
1175
1176 public void setSelectFieldPrototype(Field selectFieldPrototype) {
1177 this.selectFieldPrototype = selectFieldPrototype;
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 @BeanTagAttribute(name = "separateAddLine")
1194 public boolean isSeparateAddLine() {
1195 return separateAddLine;
1196 }
1197
1198
1199
1200
1201
1202
1203 public void setSeparateAddLine(boolean separateAddLine) {
1204 this.separateAddLine = separateAddLine;
1205 }
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221 @BeanTagAttribute(name = "addLineGroup", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1222 public Group getAddLineGroup() {
1223 return addLineGroup;
1224 }
1225
1226
1227
1228
1229
1230
1231 public void setAddLineGroup(Group addLineGroup) {
1232 this.addLineGroup = addLineGroup;
1233 }
1234
1235
1236
1237
1238
1239
1240
1241 public List<Component> getDataFields() {
1242 return this.dataFields;
1243 }
1244
1245
1246
1247
1248
1249
1250
1251 @BeanTagAttribute(name = "richTable", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1252 public RichTable getRichTable() {
1253 return this.richTable;
1254 }
1255
1256
1257
1258
1259
1260
1261 public void setRichTable(RichTable richTable) {
1262 this.richTable = richTable;
1263 }
1264
1265
1266
1267
1268 @BeanTagAttribute(name = "numberOfDataColumns")
1269 public int getNumberOfDataColumns() {
1270 return this.numberOfDataColumns;
1271 }
1272
1273
1274
1275
1276 public void setNumberOfDataColumns(int numberOfDataColumns) {
1277 this.numberOfDataColumns = numberOfDataColumns;
1278 }
1279
1280
1281
1282
1283 @BeanTagAttribute(name = "hiddenColumns", type = BeanTagAttribute.AttributeType.SETVALUE)
1284 public Set<String> getHiddenColumns() {
1285 if (richTable != null) {
1286 return richTable.getHiddenColumns();
1287 }
1288
1289 return null;
1290 }
1291
1292
1293
1294
1295 public void setHiddenColumns(Set<String> hiddenColumns) {
1296 if (richTable != null) {
1297 richTable.setHiddenColumns(hiddenColumns);
1298 }
1299 }
1300
1301
1302
1303
1304 @BeanTagAttribute(name = "sortableColumns", type = BeanTagAttribute.AttributeType.SETVALUE)
1305 public Set<String> getSortableColumns() {
1306 if (richTable != null) {
1307 return richTable.getSortableColumns();
1308 }
1309
1310 return null;
1311 }
1312
1313
1314
1315
1316 public void setSortableColumns(Set<String> sortableColumns) {
1317 if (richTable != null) {
1318 richTable.setSortableColumns(sortableColumns);
1319 }
1320 }
1321
1322
1323
1324
1325
1326
1327 @BeanTagAttribute(name = "actionColumnIndex")
1328 public int getActionColumnIndex() {
1329 return actionColumnIndex;
1330 }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342 @BeanTagAttribute(name = "actionColumnPlacement")
1343 public String getActionColumnPlacement() {
1344 return actionColumnPlacement;
1345 }
1346
1347
1348
1349
1350
1351
1352 public void setActionColumnPlacement(String actionColumnPlacement) {
1353 this.actionColumnPlacement = actionColumnPlacement;
1354
1355 if ("LEFT".equals(actionColumnPlacement)) {
1356 actionColumnIndex = 1;
1357 } else if ("RIGHT".equals(actionColumnPlacement)) {
1358 actionColumnIndex = -1;
1359 } else if (StringUtils.isNumeric(actionColumnPlacement)) {
1360 actionColumnIndex = Integer.parseInt(actionColumnPlacement);
1361 }
1362 }
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375 @BeanTagAttribute(name = "rowDetailsGroup", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1376 public Group getRowDetailsGroup() {
1377 return rowDetailsGroup;
1378 }
1379
1380
1381
1382
1383
1384
1385 public void setRowDetailsGroup(Group rowDetailsGroup) {
1386 this.rowDetailsGroup = rowDetailsGroup;
1387 }
1388
1389
1390
1391
1392
1393
1394 @BeanTagAttribute(name = "rowDetailsLinkName")
1395 public String getRowDetailsLinkName() {
1396 return rowDetailsLinkName;
1397 }
1398
1399
1400
1401
1402
1403
1404 public void setRowDetailsLinkName(String rowDetailsLinkName) {
1405 this.rowDetailsLinkName = rowDetailsLinkName;
1406 }
1407
1408
1409
1410
1411
1412
1413
1414 @BeanTagAttribute(name = "rowDetailsSwapActionImage")
1415 public boolean isRowDetailsSwapActionImage() {
1416 return rowDetailsSwapActionImage;
1417 }
1418
1419
1420
1421
1422
1423
1424 public void setRowDetailsSwapActionImage(boolean rowDetailsSwapActionImage) {
1425 this.rowDetailsSwapActionImage = rowDetailsSwapActionImage;
1426 }
1427
1428
1429
1430
1431
1432
1433
1434
1435 public void setupDetails(CollectionGroup collectionGroup, View view) {
1436 if (getRowDetailsGroup() == null || this.getRichTable() == null || !this.getRichTable().isRender()) {
1437 return;
1438 }
1439
1440
1441 collectionGroup.addDataAttribute("detailsDefaultOpen", Boolean.toString(this.rowDetailsOpen));
1442
1443 toggleAllDetailsAction.addDataAttribute("open", Boolean.toString(this.rowDetailsOpen));
1444 toggleAllDetailsAction.addDataAttribute("tableid", this.getId());
1445
1446 this.getRowDetailsGroup().setHidden(true);
1447
1448 FieldGroup detailsFieldGroup = ComponentFactory.getFieldGroup();
1449
1450 TreeMap<String, String> dataAttributes = new TreeMap<String, String>();
1451 dataAttributes.put("role", "detailsFieldGroup");
1452 detailsFieldGroup.setDataAttributes(dataAttributes);
1453
1454 Action rowDetailsAction = this.getExpandDetailsActionPrototype();
1455 rowDetailsAction.addDataAttribute("role", "detailsLink");
1456 rowDetailsAction.addDataAttribute("swap", Boolean.toString(this.isRowDetailsSwapActionImage()));
1457 rowDetailsAction.setId(collectionGroup.getId() + "_detLink");
1458
1459 List<Component> detailsItems = new ArrayList<Component>();
1460 detailsItems.add(rowDetailsAction);
1461
1462 dataAttributes = new TreeMap<String, String>();
1463 dataAttributes.put("role", "details");
1464 this.getRowDetailsGroup().setDataAttributes(dataAttributes);
1465
1466 if (ajaxDetailsRetrieval) {
1467 this.getRowDetailsGroup().setRender(false);
1468 this.getRowDetailsGroup().setDisclosedByAction(true);
1469 }
1470
1471 detailsItems.add(getRowDetailsGroup());
1472 detailsFieldGroup.setItems(detailsItems);
1473 detailsFieldGroup.setId(collectionGroup.getId() + "_detGroup");
1474 view.assignComponentIds(detailsFieldGroup);
1475
1476
1477 List<Component> theItems = new ArrayList<Component>();
1478 theItems.add(detailsFieldGroup);
1479 theItems.addAll(collectionGroup.getItems());
1480 collectionGroup.setItems(theItems);
1481 }
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492 public List<String> getColumnsToCalculate() {
1493 return columnsToCalculate;
1494 }
1495
1496
1497
1498
1499
1500
1501
1502
1503 public void completeValidation(ValidationTrace tracer) {
1504 tracer.addBean("TableLayoutManager", getId());
1505
1506 if (getRowDetailsGroup() != null) {
1507 boolean validTable = false;
1508 if (getRichTable() != null) {
1509 if (getRichTable().isRender()) {
1510 validTable = true;
1511 }
1512 }
1513 if (!validTable) {
1514 String currentValues[] = {"rowDetailsGroup =" + getRowDetailsGroup(), "richTable =" + getRichTable()};
1515 tracer.createError("If rowDetailsGroup is set richTable must be set and its render true",
1516 currentValues);
1517 }
1518
1519 }
1520 }
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530 @BeanTagAttribute(name = "showTotal")
1531 public boolean isShowTotal() {
1532 return showTotal;
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 public void setShowTotal(boolean showTotal) {
1544 this.showTotal = showTotal;
1545 }
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555 @BeanTagAttribute(name = "showPageTotal")
1556 public boolean isShowPageTotal() {
1557 return showPageTotal;
1558 }
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569 public void setShowPageTotal(boolean showPageTotal) {
1570 this.showPageTotal = showPageTotal;
1571 }
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582 @BeanTagAttribute(name = "showGroupTotal")
1583 public boolean isShowGroupTotal() {
1584 return showGroupTotal;
1585 }
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596 public void setShowGroupTotal(boolean showGroupTotal) {
1597 this.showGroupTotal = showGroupTotal;
1598 }
1599
1600
1601
1602
1603
1604
1605
1606 @BeanTagAttribute(name = "totalLabel", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1607 public Label getTotalLabel() {
1608 return totalLabel;
1609 }
1610
1611
1612
1613
1614
1615
1616 public void setTotalLabel(Label totalLabel) {
1617 this.totalLabel = totalLabel;
1618 }
1619
1620
1621
1622
1623
1624
1625
1626 @BeanTagAttribute(name = "pageTotalLabel", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1627 public Label getPageTotalLabel() {
1628 return pageTotalLabel;
1629 }
1630
1631
1632
1633
1634
1635
1636 public void setPageTotalLabel(Label pageTotalLabel) {
1637 this.pageTotalLabel = pageTotalLabel;
1638 }
1639
1640
1641
1642
1643
1644
1645
1646 @BeanTagAttribute(name = "groupTotalLabelPrototype", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
1647 public Label getGroupTotalLabelPrototype() {
1648 return groupTotalLabelPrototype;
1649 }
1650
1651
1652
1653
1654
1655
1656 public void setGroupTotalLabelPrototype(Label groupTotalLabelPrototype) {
1657 this.groupTotalLabelPrototype = groupTotalLabelPrototype;
1658 }
1659
1660
1661
1662
1663
1664
1665
1666
1667 @BeanTagAttribute(name = "columnCalculations", type = BeanTagAttribute.AttributeType.LISTBEAN)
1668 public List<ColumnCalculationInfo> getColumnCalculations() {
1669 return columnCalculations;
1670 }
1671
1672
1673
1674
1675
1676
1677 public void setColumnCalculations(List<ColumnCalculationInfo> columnCalculations) {
1678 this.columnCalculations = columnCalculations;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687 @BeanTagAttribute(name = "renderOnlyLeftTotalLabels")
1688 public boolean isRenderOnlyLeftTotalLabels() {
1689 return renderOnlyLeftTotalLabels;
1690 }
1691
1692
1693
1694
1695
1696
1697 public void setRenderOnlyLeftTotalLabels(boolean renderOnlyLeftTotalLabels) {
1698 this.renderOnlyLeftTotalLabels = renderOnlyLeftTotalLabels;
1699 }
1700
1701
1702
1703
1704
1705
1706
1707 public List<Component> getFooterCalculationComponents() {
1708 return footerCalculationComponents;
1709 }
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726 @BeanTagAttribute(name = "groupingPropertyNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
1727 public List<String> getGroupingPropertyNames() {
1728 return groupingPropertyNames;
1729 }
1730
1731
1732
1733
1734
1735
1736 public void setGroupingPropertyNames(List<String> groupingPropertyNames) {
1737 this.groupingPropertyNames = groupingPropertyNames;
1738 }
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 @BeanTagAttribute(name = "groupingTitle")
1749 public String getGroupingTitle() {
1750 return groupingTitle;
1751 }
1752
1753
1754
1755
1756
1757
1758 public void setGroupingTitle(String groupingTitle) {
1759 if (groupingTitle != null && !groupingTitle.contains("@{")) {
1760 throw new RuntimeException("groupingTitle MUST contain a springEL expression to uniquely"
1761 + " identify a collection group (often related to some value of the line). "
1762 + "Value provided: "
1763 + this.getGroupingTitle());
1764 }
1765 this.groupingTitle = groupingTitle;
1766 }
1767
1768
1769
1770
1771
1772
1773
1774 @BeanTagAttribute(name = "groupingPrefix")
1775 public String getGroupingPrefix() {
1776 return groupingPrefix;
1777 }
1778
1779
1780
1781
1782
1783
1784 public void setGroupingPrefix(String groupingPrefix) {
1785 this.groupingPrefix = groupingPrefix;
1786 }
1787
1788
1789
1790
1791
1792
1793
1794 public boolean isRowDetailsOpen() {
1795 return rowDetailsOpen;
1796 }
1797
1798
1799
1800
1801
1802
1803 public void setRowDetailsOpen(boolean rowDetailsOpen) {
1804 this.rowDetailsOpen = rowDetailsOpen;
1805 }
1806
1807
1808
1809
1810
1811
1812
1813 public boolean isShowToggleAllDetails() {
1814 return showToggleAllDetails;
1815 }
1816
1817
1818
1819
1820
1821
1822 public void setShowToggleAllDetails(boolean showToggleAllDetails) {
1823 this.showToggleAllDetails = showToggleAllDetails;
1824 }
1825
1826
1827
1828
1829
1830
1831
1832 public Action getToggleAllDetailsAction() {
1833 return toggleAllDetailsAction;
1834 }
1835
1836
1837
1838
1839
1840
1841
1842
1843 public void setToggleAllDetailsAction(Action toggleAllDetailsAction) {
1844 this.toggleAllDetailsAction = toggleAllDetailsAction;
1845 }
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855 public boolean isAjaxDetailsRetrieval() {
1856 return ajaxDetailsRetrieval;
1857 }
1858
1859
1860
1861
1862
1863
1864 public void setAjaxDetailsRetrieval(boolean ajaxDetailsRetrieval) {
1865 this.ajaxDetailsRetrieval = ajaxDetailsRetrieval;
1866 }
1867
1868
1869
1870
1871
1872
1873
1874
1875 public Action getExpandDetailsActionPrototype() {
1876 return expandDetailsActionPrototype;
1877 }
1878
1879
1880
1881
1882
1883
1884 public void setExpandDetailsActionPrototype(Action expandDetailsActionPrototype) {
1885 this.expandDetailsActionPrototype = expandDetailsActionPrototype;
1886 }
1887 }