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.admincentral.tree.view;
35
36 import info.magnolia.objectfactory.ComponentProvider;
37 import info.magnolia.ui.admincentral.content.view.ContentView;
38 import info.magnolia.ui.admincentral.event.ItemEditedEvent;
39 import info.magnolia.ui.admincentral.tree.container.HierarchicalJcrContainer;
40 import info.magnolia.ui.model.column.definition.ColumnDefinition;
41 import info.magnolia.ui.model.column.definition.ColumnFormatter;
42 import info.magnolia.ui.model.workbench.definition.WorkbenchDefinition;
43 import info.magnolia.ui.vaadin.grid.MagnoliaTreeTable;
44 import info.magnolia.ui.vaadin.integration.jcr.container.AbstractJcrContainer;
45
46 import java.util.ArrayList;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Set;
51
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 import com.vaadin.data.Container;
56 import com.vaadin.data.Property.ValueChangeEvent;
57 import com.vaadin.event.ItemClickEvent;
58 import com.vaadin.ui.Component;
59 import com.vaadin.ui.CssLayout;
60 import com.vaadin.ui.Layout;
61 import com.vaadin.ui.Table;
62 import com.vaadin.ui.TreeTable;
63
64
65
66
67 public class TreeViewImpl implements TreeView {
68
69 private static final Logger log = LoggerFactory.getLogger(TreeViewImpl.class);
70
71 private final Layout layout;
72
73 private final TreeTable treeTable;
74
75 private final HierarchicalJcrContainer container;
76
77 private ContentView.Listener listener;
78
79 private Set<?> defaultValue = null;
80
81
82
83
84
85
86
87
88 public TreeViewImpl(WorkbenchDefinition workbench, ComponentProvider componentProvider, HierarchicalJcrContainer container) {
89 this.container = container;
90
91 treeTable = buildTreeTable(container, workbench, componentProvider);
92 layout = buildLayout();
93 layout.addComponent(treeTable);
94
95 treeTable.addListener(new ItemClickEvent.ItemClickListener() {
96
97 private Object previousSelection;
98
99 @Override
100 public void itemClick(ItemClickEvent event) {
101 Object currentSelection = event.getItemId();
102 if (event.isDoubleClick()) {
103 presenterOnDoubleClick(String.valueOf(event.getItemId()));
104 } else {
105
106 if (previousSelection == currentSelection) {
107 treeTable.setValue(null);
108 }
109 }
110
111 previousSelection = currentSelection;
112 }
113 });
114
115 treeTable.addListener(new TreeTable.ValueChangeListener() {
116
117 @Override
118 public void valueChange(ValueChangeEvent event) {
119 if (defaultValue == null && event.getProperty().getValue() instanceof Set) {
120 defaultValue = (Set<?>) event.getProperty().getValue();
121 }
122 final Object value = event.getProperty().getValue();
123 if (value instanceof String) {
124 presenterOnItemSelection(String.valueOf(value));
125 } else if (value instanceof Set) {
126 final Set<?> set = new HashSet<Object>((Set<?>) value);
127 set.removeAll(defaultValue);
128 if (set.size() == 1) {
129 presenterOnItemSelection(String.valueOf(set.iterator().next()));
130 } else if (set.size() == 0) {
131 presenterOnItemSelection(null);
132 treeTable.setValue(null);
133 }
134 }
135 }
136 });
137
138 }
139
140
141
142 private TreeTable buildTreeTable(final Container container, WorkbenchDefinition workbench, ComponentProvider componentProvider) {
143
144 TreeTable treeTable = (workbench.isEditable()) ? new InplaceEditingTreeTable() : new MagnoliaTreeTable();
145
146
147 treeTable.setNullSelectionAllowed(true);
148 treeTable.setColumnCollapsingAllowed(false);
149 treeTable.setColumnReorderingAllowed(false);
150 treeTable.setCollapsed(treeTable.firstItemId(), false);
151 treeTable.setSizeFull();
152
153
154 treeTable.setContainerDataSource(container);
155 buildColumns(treeTable, container, workbench.getColumns(), componentProvider);
156
157
158 if (workbench.isEditable()) {
159 ((InplaceEditingTreeTable) treeTable).addListener(new ItemEditedEvent.Handler() {
160
161 @Override
162 public void onItemEdited(ItemEditedEvent event) {
163 presenterOnEditItem(event);
164 }
165 });
166 }
167
168 treeTable.setCellStyleGenerator(new Table.CellStyleGenerator() {
169
170 @Override
171 public String getStyle(Table source, Object itemId, Object propertyId) {
172 return presenterGetIcon(itemId, propertyId);
173 }
174 });
175
176 return treeTable;
177 }
178
179
180
181
182
183
184
185
186
187 protected void buildColumns(TreeTable treeTable, Container container, List<ColumnDefinition> columns, ComponentProvider componentProvider) {
188 final Iterator<ColumnDefinition> iterator = columns.iterator();
189 final List<String> visibleColumns = new ArrayList<String>();
190 final List<String> editableColumns = new ArrayList<String>();
191
192 while (iterator.hasNext()) {
193 final ColumnDefinition column = iterator.next();
194 final String columnProperty = column.getPropertyName() != null ? column.getPropertyName() : column.getName();
195
196
197 container.addContainerProperty(columnProperty, column.getType(), "");
198 visibleColumns.add(columnProperty);
199
200
201 treeTable.setColumnHeader(columnProperty, column.getLabel());
202 if (column.getWidth() > 0) {
203 treeTable.setColumnWidth(columnProperty, column.getWidth());
204 } else {
205 treeTable.setColumnExpandRatio(columnProperty, column.getExpandRatio());
206 }
207
208
209 Class<? extends ColumnFormatter> formatterClass = column.getFormatterClass();
210 if (formatterClass != null) {
211 ColumnFormatter formatter = componentProvider.newInstance(formatterClass, column);
212 treeTable.addGeneratedColumn(columnProperty, formatter);
213 }
214
215
216 if (column.isEditable()) {
217 editableColumns.add(columnProperty);
218 }
219 }
220
221 treeTable.setVisibleColumns(visibleColumns.toArray());
222 if (treeTable instanceof InplaceEditingTreeTable) {
223 ((InplaceEditingTreeTable) treeTable).setEditableColumns(editableColumns.toArray());
224 }
225 }
226
227
228
229 @Override
230 public void select(String path) {
231 treeTable.select(path);
232 }
233
234 @Override
235 public void refresh() {
236 container.refresh();
237 container.fireItemSetChange();
238 }
239
240 @Override
241 public AbstractJcrContainer getContainer() {
242 throw new UnsupportedOperationException(getClass().getName() + " does not support this operation");
243 }
244
245 @Override
246 public ViewType getViewType() {
247 return ViewType.TREE;
248 }
249
250 @Override
251 public void setListener(ContentView.Listener listener) {
252 this.listener = listener;
253 }
254
255 private void presenterOnItemSelection(String id) {
256 if (listener != null) {
257 listener.onItemSelection(treeTable.getItem(id));
258 }
259 }
260
261 private void presenterOnDoubleClick(String id) {
262 if (listener != null) {
263 listener.onDoubleClick(treeTable.getItem(id));
264 }
265 }
266
267 private void presenterOnEditItem(ItemEditedEvent event) {
268 if (listener != null) {
269 listener.onItemEdited(event.getItem());
270
271
272 TreeViewImpl.this.container.fireItemSetChange();
273 }
274 }
275
276
277
278 private Layout buildLayout() {
279 CssLayout layout = new CssLayout();
280 layout.setStyleName("mgnl-content-view");
281 layout.setSizeFull();
282 return layout;
283 }
284
285 @Override
286 public Component asVaadinComponent() {
287 return layout;
288 }
289
290 private String presenterGetIcon(Object itemId, Object propertyId) {
291 Container container = treeTable.getContainerDataSource();
292 if (listener != null && propertyId == null) {
293 return listener.getItemIcon(container.getItem(itemId));
294 }
295
296 return null;
297 }
298
299 }