1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.contentapp.browser;
35
36 import static java.util.stream.Collectors.toSet;
37
38 import info.magnolia.ui.contentapp.browser.actions.ContextAwareActionPopup;
39 import info.magnolia.ui.contentapp.browser.actions.ShortcutActionsExecutor;
40 import info.magnolia.ui.ValueContext;
41 import info.magnolia.ui.contentapp.browser.drop.RowDragger;
42 import info.magnolia.ui.contentapp.configuration.GridViewDefinition;
43
44 import java.util.HashSet;
45 import java.util.Objects;
46 import java.util.Optional;
47 import java.util.stream.Stream;
48
49 import org.vaadin.extension.gridscroll.GridScrollExtension;
50 import org.vaadin.extension.gridscroll.shared.ColumnResizeCompensationMode;
51
52 import com.vaadin.shared.ui.grid.DropMode;
53 import com.vaadin.ui.Composite;
54 import com.vaadin.ui.Grid;
55 import com.vaadin.ui.components.grid.Editor;
56
57
58
59
60
61
62
63 public abstract class GridView<T, P extends GridViewPresenter<T>> extends Composite implements ContentView {
64
65 protected final ValueContext<T> valueContext;
66 protected final GridViewDefinition<T> definition;
67 protected final Grid<T> grid;
68
69 protected final P presenter;
70 protected final Editor<T> editor;
71
72 protected GridView(ValueContext<T> valueContext, GridViewDefinition<T> definition) {
73 this.valueContext = valueContext;
74 this.definition = definition;
75 this.presenter = createPresenter();
76 this.grid = presenter.grid();
77 this.editor = grid.getEditor();
78
79 ContextAwareActionPopup actionPopup = null;
80 if (!definition.isReadOnly()) {
81 actionPopup = create(ContextAwareActionPopup.class, grid);
82 }
83 final ShortcutActionsExecutor actionsExecutor =
84 actionPopup != null ? actionPopup : ShortcutActionsExecutor.NOOP;
85
86 grid.setSizeFull();
87 grid.setSelectionMode(definition.isMultiSelect() ? Grid.SelectionMode.MULTI : Grid.SelectionMode.SINGLE);
88 grid.addSelectionListener(event -> valueContext.set(event.getAllSelectedItems()));
89
90 editor.setEnabled(false);
91 grid.getColumns().stream()
92 .map(Grid.Column::getEditorBinding)
93 .filter(Objects::nonNull)
94 .findFirst()
95 .ifPresent(any -> {
96 editor.setBuffered(false);
97 editor.setEnabled(true);
98 });
99
100 setLastColumnAsNotResizable(grid);
101
102 new GridScrollExtension<>(grid).setColumnResizeCompensationMode(ColumnResizeCompensationMode.RESIZE_COLUMN);
103
104
105
106
107
108
109
110
111 grid.addColumnResizeListener(event -> {
112 if (event.isUserOriginated()) {
113 Grid.Column<?, ?> column = event.getColumn();
114 double width = column.getWidth();
115 double minimumWidth = column.getMinimumWidth();
116 double maximumWidth = column.getMaximumWidth();
117
118 column.setMinimumWidth(minimumWidth > 0 && width <= minimumWidth ? width : minimumWidth);
119 column.setMaximumWidth(maximumWidth > 0 && width >= maximumWidth ? width : maximumWidth);
120 }
121 });
122
123 Optional.ofNullable(definition.getDropConstraint())
124 .ifPresent(dropConstraint -> create(RowDragger.class, grid, DropMode.BETWEEN, create(dropConstraint.getImplementationClass(), dropConstraint)));
125
126 valueContext.observe(items -> {
127 if (grid.getSelectedItems() != items) {
128 grid.deselectAll();
129 items.forEach(grid::select);
130 }
131 });
132
133 setCompositionRoot(create(GridWithShortcuts.class, grid, actionsExecutor));
134 grid.focus();
135 setSizeFull();
136 }
137
138 protected abstract P createPresenter();
139
140 protected void select(Stream<T> values) {
141 if (this.definition.isMultiSelect()) {
142 this.grid.asMultiSelect().updateSelection(values.collect(toSet()), new HashSet<>());
143 } else {
144 values.findFirst().ifPresent(this.grid.asSingleSelect()::setValue);
145 }
146 }
147
148
149
150
151 private void setLastColumnAsNotResizable(Grid<T> grid) {
152 if (grid.getColumns().size() > 0) {
153 grid.getColumns().get(grid.getColumns().size() - 1).setResizable(false);
154 }
155 }
156 }