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 info.magnolia.event.EventBus;
37 import info.magnolia.ui.actionbar.ActionbarPresenter;
38 import info.magnolia.ui.actionbar.ActionbarView;
39 import info.magnolia.ui.actionbar.definition.ActionbarDefinition;
40 import info.magnolia.ui.api.action.ActionExecutionException;
41 import info.magnolia.ui.api.action.ActionExecutor;
42 import info.magnolia.ui.api.app.AppContext;
43 import info.magnolia.ui.api.app.SubAppContext;
44 import info.magnolia.ui.api.app.SubAppEventBus;
45 import info.magnolia.ui.api.availability.AvailabilityChecker;
46 import info.magnolia.ui.api.availability.AvailabilityDefinition;
47 import info.magnolia.ui.api.event.AdmincentralEventBus;
48 import info.magnolia.ui.api.event.ContentChangedEvent;
49 import info.magnolia.ui.api.message.Message;
50 import info.magnolia.ui.api.message.MessageType;
51 import info.magnolia.ui.imageprovider.ImageProvider;
52 import info.magnolia.ui.vaadin.integration.NullItem;
53 import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
54 import info.magnolia.ui.workbench.WorkbenchPresenter;
55 import info.magnolia.ui.workbench.WorkbenchView;
56 import info.magnolia.ui.workbench.event.ActionEvent;
57 import info.magnolia.ui.workbench.event.ItemDoubleClickedEvent;
58 import info.magnolia.ui.workbench.event.ItemShortcutKeyEvent;
59 import info.magnolia.ui.workbench.event.SearchEvent;
60 import info.magnolia.ui.workbench.event.SelectionChangedEvent;
61
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.Collection;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Set;
68
69 import javax.inject.Inject;
70 import javax.inject.Named;
71
72 import org.apache.commons.collections4.ListUtils;
73 import org.apache.commons.collections4.Predicate;
74 import org.apache.commons.lang3.StringUtils;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78 import com.vaadin.event.ShortcutAction;
79 import com.vaadin.server.Resource;
80 import com.vaadin.v7.data.Item;
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public class BrowserPresenter implements ActionbarPresenter.Listener, BrowserView.Listener {
95
96 private static final Logger log = LoggerFactory.getLogger(BrowserPresenter.class);
97
98 private final Predicate<Object> itemExistsPredicate = this::verifyItemExists;
99
100 private final WorkbenchPresenter workbenchPresenter;
101
102 private final ActionExecutor actionExecutor;
103
104 private final BrowserSubAppDescriptor subAppDescriptor;
105
106 private final BrowserView view;
107
108 private final EventBus admincentralEventBus;
109
110 private final EventBus subAppEventBus;
111
112 private final ActionbarPresenter actionbarPresenter;
113
114 private final AvailabilityChecker availabilityChecker;
115
116 private final AppContext appContext;
117
118 private final ContentConnector contentConnector;
119
120 private final ImageProvider imageProvider;
121
122 @Inject
123 public BrowserPresenter(
124 BrowserView view,
125 SubAppContext subAppContext,
126 ActionExecutor actionExecutor,
127 @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus,
128 @Named(SubAppEventBus.NAME) EventBus subAppEventBus,
129 ContentConnector contentConnector,
130 ImageProvider imageProvider,
131 WorkbenchPresenter workbenchPresenter,
132 ActionbarPresenter actionbarPresenter,
133 AvailabilityChecker availabilityChecker) {
134 this.view = view;
135 this.appContext = subAppContext.getAppContext();
136 this.subAppDescriptor = (BrowserSubAppDescriptor) subAppContext.getSubAppDescriptor();
137 this.actionExecutor = actionExecutor;
138 this.admincentralEventBus = admincentralEventBus;
139 this.subAppEventBus = subAppEventBus;
140 this.contentConnector = contentConnector;
141 this.imageProvider = imageProvider;
142 this.workbenchPresenter = workbenchPresenter;
143 this.actionbarPresenter = actionbarPresenter;
144 this.availabilityChecker = availabilityChecker;
145 }
146
147 public BrowserView start() {
148 actionbarPresenter.setListener(this);
149
150 WorkbenchView workbenchView = workbenchPresenter.start(subAppDescriptor.getWorkbench(), subAppDescriptor.getImageProvider(), subAppEventBus);
151 ActionbarView actionbar = actionbarPresenter.start(subAppDescriptor.getActionbar(), subAppDescriptor.getActions());
152
153 workbenchView.setTitle(subAppDescriptor.getLabel());
154
155 view.setWorkbenchView(workbenchView);
156 view.setActionbarView(actionbar);
157 view.setListener(this);
158
159 bindHandlers();
160 return view;
161 }
162
163 protected void bindHandlers() {
164 admincentralEventBus.addHandler(ContentChangedEvent.class, event -> {
165 List<Object> itemIds = new ArrayList<>();
166 if (event.getItemId() instanceof Collection) {
167 itemIds.addAll((Collection<?>) event.getItemId());
168 } else {
169 itemIds.add(event.getItemId());
170 }
171 workbenchPresenter.refresh();
172
173
174
175 List<Object> existingSelectedItemIds = ListUtils.select(itemIds, itemExistsPredicate);
176 if (existingSelectedItemIds.isEmpty()) {
177 existingSelectedItemIds = ListUtils.select(getSelectedItemIds(), itemExistsPredicate);
178 }
179
180 workbenchPresenter.select(existingSelectedItemIds);
181
182 if (event.isItemContentChanged() && !existingSelectedItemIds.isEmpty()) {
183 workbenchPresenter.expand(existingSelectedItemIds.get(0));
184 }
185
186
187 if (!existingSelectedItemIds.isEmpty()) {
188 refreshActionbarPreviewImage(existingSelectedItemIds.get(0));
189 }
190 });
191
192 subAppEventBus.addHandler(SelectionChangedEvent.class, event -> {
193
194 refreshActionbarPreviewImage(event.getFirstItemId());
195 });
196
197 subAppEventBus.addHandler(ItemDoubleClickedEvent.class, event -> executeDefaultAction());
198
199 subAppEventBus.addHandler(SearchEvent.class, event -> workbenchPresenter.doSearch(event.getSearchExpression()));
200
201 subAppEventBus.addHandler(ActionEvent.class, event -> executeAction(event.getActionName(), event.getItemIds(), event.getParameters()));
202
203 subAppEventBus.addHandler(ItemShortcutKeyEvent.class, event -> {
204 int keyCode = event.getKeyCode();
205 switch (keyCode) {
206 case ShortcutAction.KeyCode.ENTER:
207 executeDefaultAction();
208 break;
209 case ShortcutAction.KeyCode.DELETE:
210 executeDeleteAction();
211 break;
212 }
213 });
214 }
215
216 private void refreshActionbarPreviewImage(Object itemId) {
217 Object previewResource = getPreviewImageForId(itemId);
218 if (previewResource instanceof Resource) {
219 getActionbarPresenter().setPreview((Resource) previewResource);
220 } else {
221 getActionbarPresenter().setPreview(null);
222 }
223 }
224
225 protected boolean verifyItemExists(Object itemId) {
226 return contentConnector.canHandleItem(itemId) && contentConnector.getItem(itemId) != null;
227 }
228
229 public List<Object> getSelectedItemIds() {
230 return workbenchPresenter.getSelectedIds();
231 }
232
233
234
235
236
237 public String getDefaultViewType() {
238 return workbenchPresenter.getDefaultViewType();
239 }
240
241 public boolean hasViewType(String viewType) {
242 return workbenchPresenter.hasViewType(viewType);
243 }
244
245 public BrowserView getView() {
246 return view;
247 }
248
249 public ActionbarPresenter getActionbarPresenter() {
250 return actionbarPresenter;
251 }
252
253
254
255
256
257 public void resync(final List<Object> itemIds, final String viewType, final String query) {
258 workbenchPresenter.resynch(itemIds, viewType, query);
259 }
260
261 protected Object getPreviewImageForId(Object itemId) {
262 if (imageProvider != null) {
263 return imageProvider.getThumbnailResource(itemId, ImageProvider.PORTRAIT_GENERATOR);
264 }
265 return null;
266 }
267
268 @Override
269 public void onActionbarItemClicked(String actionName) {
270 executeAction(actionName);
271 }
272
273 @Override
274 public void onActionBarSelection(String actionName) {
275 executeAction(actionName);
276 }
277
278
279
280
281 private void executeDefaultAction() {
282 ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar();
283 if (actionbarDefinition == null) {
284 return;
285 }
286 String defaultAction = actionbarDefinition.getDefaultAction();
287 if (StringUtils.isNotEmpty(defaultAction)) {
288 executeAction(defaultAction);
289 }
290 }
291
292
293
294
295 private void executeDeleteAction() {
296 ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar();
297 if (actionbarDefinition == null) {
298 return;
299 }
300 String deleteAction = actionbarDefinition.getDeleteAction();
301 if (StringUtils.isNotEmpty(deleteAction)) {
302 executeAction(deleteAction);
303 }
304 }
305
306 protected void executeAction(String actionName) {
307 try {
308 AvailabilityDefinition availability = actionExecutor.getActionDefinition(actionName).getAvailability();
309 if (availabilityChecker.isAvailable(availability, getSelectedItemIds())) {
310 Object[] args = prepareActionArgs();
311 actionExecutor.execute(actionName, args);
312 }
313 } catch (ActionExecutionException e) {
314 Message error = new Message(MessageType.ERROR, "An error occurred while executing an action.", e.getMessage());
315 log.error("An error occurred while executing action [{}]", actionName, e);
316 appContext.sendLocalMessage(error);
317 }
318 }
319
320 private void executeAction(String actionName, Set<Object> itemIds, Object... parameters) {
321 try {
322 AvailabilityDefinition availability = actionExecutor.getActionDefinition(actionName).getAvailability();
323 if (availabilityChecker.isAvailable(availability, getSelectedItemIds())) {
324 List<Object> args = new ArrayList<Object>();
325 args.add(itemIds);
326 args.addAll(Arrays.asList(parameters));
327 actionExecutor.execute(actionName, new Object[]{args.toArray(new Object[args.size()])});
328 }
329 } catch (ActionExecutionException e) {
330 Message error = new Message(MessageType.ERROR, "An error occurred while executing an action.", e.getMessage());
331 log.error("An error occurred while executing action [{}]", actionName, e);
332 appContext.sendLocalMessage(error);
333 }
334 }
335
336 protected Object[] prepareActionArgs() {
337 List<Object> argList = new ArrayList<Object>();
338 List<Item> selectedItems = new ArrayList<Item>();
339
340 List<Object> selectedIds = getSelectedItemIds();
341 if (selectedIds.isEmpty()) {
342 selectedIds.add(contentConnector.getDefaultItemId());
343 }
344 Iterator<Object> idIt = selectedIds.iterator();
345 while (idIt.hasNext()) {
346 selectedItems.add(contentConnector.getItem(idIt.next()));
347 }
348
349 if (selectedItems.size() <= 1) {
350
351 argList.add(selectedItems.isEmpty() ? new NullItem() : selectedItems.get(0));
352 argList.add(selectedItems);
353 } else {
354
355 argList.add(selectedItems);
356 }
357 return argList.toArray(new Object[argList.size()]);
358 }
359 }