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.ValueContext;
39 import info.magnolia.ui.contentapp.browser.actions.ContextAwareActionPopup;
40 import info.magnolia.ui.contentapp.browser.actions.ShortcutActionsExecutor;
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.Iterator;
46 import java.util.Objects;
47 import java.util.Optional;
48 import java.util.stream.Stream;
49
50 import com.vaadin.data.provider.DataProvider;
51 import com.vaadin.shared.ui.grid.DropMode;
52 import com.vaadin.shared.ui.grid.ScrollDestination;
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<T> 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 Optional.ofNullable(definition.getDropConstraint())
103 .ifPresent(dropConstraint -> create(RowDragger.class, grid, DropMode.BETWEEN, create(dropConstraint.getImplementationClass(), dropConstraint)));
104
105 valueContext.observe(items -> {
106 if (grid.getSelectedItems() != items) {
107 grid.deselectAll();
108 items.forEach(grid::select);
109 }
110 });
111
112 setCompositionRoot(create(GridWithShortcuts.class, grid, actionsExecutor));
113 grid.focus();
114 setSizeFull();
115 addAttachListener(event -> scrollToSelectedItem());
116 }
117
118 @Override
119 public void setVisible(boolean visible) {
120 if (visible) {
121
122
123 scrollToSelectedItem();
124 }
125 super.setVisible(visible);
126 }
127
128 protected void scrollToSelectedItem() {
129 if (definition.isScrollToSelectedItem()) {
130 grid.getSelectedItems().stream().findFirst()
131 .ifPresent(selectedItem -> {
132 int index = 0;
133 final DataProvider<T, ?> dataProvider = grid.getDataProvider();
134 final Object selectedItemId = dataProvider.getId(selectedItem);
135 for (Iterator<T> it = fetchItems().iterator(); it.hasNext(); ) {
136 T t = it.next();
137 if (dataProvider.getId(t).equals(selectedItemId)) {
138 break;
139 } else {
140 index++;
141 }
142 }
143 grid.scrollTo(index, ScrollDestination.MIDDLE);
144 });
145 }
146 }
147
148 Stream<T> fetchItems() {
149 return grid.getDataCommunicator().fetchItemsWithRange(0, Integer.MAX_VALUE).stream();
150 }
151
152 protected abstract P createPresenter();
153
154 protected void select(Stream<T> values) {
155 if (this.definition.isMultiSelect()) {
156 this.grid.asMultiSelect().updateSelection(values.collect(toSet()), new HashSet<>());
157 } else {
158 values.findFirst().ifPresent(this.grid.asSingleSelect()::setValue);
159 }
160 }
161
162
163
164
165 private void setLastColumnAsNotResizable(Grid<T> grid) {
166 if (grid.getColumns().size() > 0) {
167 grid.getColumns().get(grid.getColumns().size() - 1).setResizable(false);
168 }
169 }
170 }