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