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.definition.ActionbarDefinition;
39 import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition;
40 import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition;
41 import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition;
42 import info.magnolia.ui.api.action.ActionDefinition;
43 import info.magnolia.ui.api.action.ActionExecutor;
44 import info.magnolia.ui.api.app.SubAppContext;
45 import info.magnolia.ui.api.app.SubAppEventBus;
46 import info.magnolia.ui.api.availability.AvailabilityChecker;
47 import info.magnolia.ui.api.availability.AvailabilityDefinition;
48 import info.magnolia.ui.api.event.AdmincentralEventBus;
49 import info.magnolia.ui.api.location.Location;
50 import info.magnolia.ui.api.location.LocationChangedEvent;
51 import info.magnolia.ui.contentapp.ContentSubAppView;
52 import info.magnolia.ui.framework.app.BaseSubApp;
53 import info.magnolia.ui.vaadin.actionbar.ActionPopup;
54 import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
55 import info.magnolia.ui.workbench.event.ItemRightClickedEvent;
56 import info.magnolia.ui.workbench.event.SearchEvent;
57 import info.magnolia.ui.workbench.event.SelectionChangedEvent;
58 import info.magnolia.ui.workbench.event.ViewTypeChangedEvent;
59 import info.magnolia.ui.workbench.search.SearchPresenterDefinition;
60
61 import java.util.Arrays;
62 import java.util.Iterator;
63 import java.util.List;
64 import java.util.Set;
65
66 import javax.inject.Inject;
67 import javax.inject.Named;
68
69 import org.apache.commons.lang3.StringUtils;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
72
73 import com.vaadin.ui.MenuBar.MenuItem;
74 import com.vaadin.server.ExternalResource;
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 @Deprecated
114 public class BrowserSubApp extends BaseSubApp<ContentSubAppView> {
115
116 private static final Logger log = LoggerFactory.getLogger(BrowserSubApp.class);
117
118 private final BrowserPresenter browser;
119 private final EventBus subAppEventBus;
120 private ActionExecutor actionExecutor;
121 protected ContentConnector contentConnector;
122 private AvailabilityChecker checker;
123
124 @Inject
125 public BrowserSubApp(ActionExecutor actionExecutor, final SubAppContext subAppContext, final ContentSubAppView view, final BrowserPresenter browser, final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, @Named(AdmincentralEventBus.NAME) EventBus adminCentralEventBus, ContentConnector contentConnector, AvailabilityChecker checker) {
126 super(subAppContext, view);
127 this.checker = checker;
128 if (subAppContext == null || view == null || browser == null || subAppEventBus == null) {
129 throw new IllegalArgumentException("Constructor does not allow for null args. Found SubAppContext = " + subAppContext + ", ContentSubAppView = " + view + ", BrowserPresenter = " + browser + ", EventBus = " + subAppEventBus);
130 }
131 this.browser = browser;
132 this.subAppEventBus = subAppEventBus;
133 this.actionExecutor = actionExecutor;
134 this.contentConnector = contentConnector;
135
136
137
138
139
140
141
142 adminCentralEventBus.addHandler(LocationChangedEvent.class, new LocationChangedEvent.Handler() {
143 @Override
144 public void onLocationChanged(LocationChangedEvent event) {
145
146
147
148
149
150 if (event.getNewLocation().equals(getCurrentLocation())) {
151 restoreBrowser(getCurrentLocation());
152 }
153 }
154 });
155 }
156
157
158
159
160
161
162
163
164
165
166
167 @Override
168 public ContentSubAppView start(final Location location) {
169 BrowserLocation l = BrowserLocation.wrap(location);
170 super.start(l);
171 getView().setContentView(browser.start());
172 restoreBrowser(l);
173 registerSubAppEventsHandlers(subAppEventBus);
174
175 return getView();
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 protected void restoreBrowser(final BrowserLocation location) {
199 String path = location.getNodePath();
200 String viewType = location.getViewType();
201
202 if (!getBrowser().hasViewType(viewType)) {
203 if (!StringUtils.isBlank(viewType)) {
204 log.warn("Unknown view type [{}], returning to default view type.", viewType);
205 }
206 viewType = getBrowser().getDefaultViewType();
207 location.updateViewType(viewType);
208 getAppContext().updateSubAppLocation(getSubAppContext(), location);
209 }
210 String query = location.getQuery();
211
212 Object itemId = contentConnector.getItemIdByUrlFragment(path);
213
214
215 if (!contentConnector.canHandleItem(itemId)) {
216 itemId = contentConnector.getDefaultItemId();
217 BrowserLocation newLocation = getCurrentLocation();
218 newLocation.updateNodePath("/");
219 getAppContext().updateSubAppLocation(getSubAppContext(), newLocation);
220 }
221
222 getBrowser().resync(Arrays.asList(itemId), viewType, query);
223 updateActionbar(getBrowser().getActionbarPresenter());
224 }
225
226
227
228
229
230 public void showActionPopup(Object itemId, int x, int y) {
231
232
233 BrowserSubAppDescriptora/ui/contentapp/browser/BrowserSubAppDescriptor.html#BrowserSubAppDescriptor">BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor();
234 ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar();
235 if (actionbarDefinition == null) {
236 return;
237 }
238
239 ActionPopup actionPopup = browser.getView().getActionPopup();
240
241 updateActionPopup(actionPopup);
242 actionPopup.open(x, y);
243 }
244
245
246
247
248
249 private void updateActionPopup(ActionPopup actionPopup) {
250
251 actionPopup.removeItems();
252
253 BrowserSubAppDescriptora/ui/contentapp/browser/BrowserSubAppDescriptor.html#BrowserSubAppDescriptor">BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor();
254 ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar();
255 if (actionbarDefinition == null) {
256 return;
257 }
258 List<ActionbarSectionDefinition> sections = actionbarDefinition.getSections();
259
260
261 ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections);
262
263
264 if (sectionDefinition == null) {
265 return;
266 }
267
268
269 for (final Iterator<ActionbarGroupDefinition> groupDefinitionIterator = sectionDefinition.getGroups().iterator(); groupDefinitionIterator.hasNext();) {
270 final ActionbarGroupDefinition groupDefinition = groupDefinitionIterator.next();
271 for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) {
272
273 final String actionName = itemDefinition.getName();
274 final MenuItem menuItem = addActionPopupItem(subAppDescriptor, itemDefinition);
275 ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName);
276 if (actionDefinition != null) {
277 AvailabilityDefinition availability = actionDefinition.getAvailability();
278 menuItem.setEnabled(checker.isAvailable(availability, browser.getSelectedItemIds()));
279 }
280 }
281
282
283 if (groupDefinitionIterator.hasNext()) {
284 getBrowser().getView().getActionPopup().addSeparator();
285 }
286 }
287 }
288
289
290
291
292 private MenuItem addActionPopupItem(BrowserSubAppDescriptor subAppDescriptor, ActionbarItemDefinition itemDefinition) {
293 String actionName = itemDefinition.getName();
294
295 ActionDefinition action = subAppDescriptor.getActions().get(actionName);
296 String label = action.getLabel();
297 String iconFontCode = ActionPopup.ICON_FONT_CODE + action.getIcon();
298 ExternalResource iconFontResource = new ExternalResource(iconFontCode);
299
300 return getBrowser().getView().getActionPopup().addItem(label, iconFontResource, item -> getBrowser().onActionbarItemClicked(actionName));
301 }
302
303
304
305
306
307
308
309
310
311 public void updateActionbar(ActionbarPresenter actionbar) {
312
313 BrowserSubAppDescriptora/ui/contentapp/browser/BrowserSubAppDescriptor.html#BrowserSubAppDescriptor">BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor();
314 ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar();
315 if (actionbarDefinition == null) {
316 return;
317 }
318 List<ActionbarSectionDefinition> sections = actionbarDefinition.getSections();
319
320 ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections);
321
322
323 for (ActionbarSectionDefinition section : sections) {
324 actionbar.hideSection(section.getName());
325 }
326
327 if (sectionDefinition != null) {
328
329 actionbar.showSection(sectionDefinition.getName());
330
331
332 for (ActionbarGroupDefinition groupDefinition : sectionDefinition.getGroups()) {
333 for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) {
334
335 String actionName = itemDefinition.getName();
336 ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName);
337 if (actionDefinition != null) {
338 AvailabilityDefinition availability = actionDefinition.getAvailability();
339 if (checker.isAvailable(availability, browser.getSelectedItemIds())) {
340 actionbar.enable(actionName);
341 } else {
342 actionbar.disable(actionName);
343 }
344 } else {
345 log.warn("Action bar expected an action named {}, but no such action is currently configured.", actionName);
346 }
347 }
348 }
349 }
350 }
351
352 private ActionbarSectionDefinition getVisibleSection(List<ActionbarSectionDefinition> sections) {
353 for (ActionbarSectionDefinition section : sections) {
354 if (isSectionVisible(section))
355 return section;
356 }
357 return null;
358 }
359
360 private boolean isSectionVisible(ActionbarSectionDefinition section) {
361 return checker.isAvailable(section.getAvailability(), browser.getSelectedItemIds());
362 }
363
364 protected final BrowserPresenter getBrowser() {
365 return browser;
366 }
367
368
369
370
371 @Override
372 public void locationChanged(final Location location) {
373 super.locationChanged(location);
374 restoreBrowser(BrowserLocation.wrap(location));
375 }
376
377
378
379
380 @Override
381 public BrowserLocation getCurrentLocation() {
382 return BrowserLocation.wrap(super.getCurrentLocation());
383 }
384
385
386
387
388
389
390
391
392
393 private void registerSubAppEventsHandlers(final EventBus subAppEventBus) {
394 final ActionbarPresenter actionbar = getBrowser().getActionbarPresenter();
395 subAppEventBus.addHandler(SelectionChangedEvent.class, new SelectionChangedEvent.Handler() {
396
397 @Override
398 public void onSelectionChanged(SelectionChangedEvent event) {
399 handleSelectionChange(event.getItemIds(), actionbar);
400 }
401 });
402
403 subAppEventBus.addHandler(ItemRightClickedEvent.class, new ItemRightClickedEvent.Handler() {
404
405 @Override
406 public void onItemRightClicked(ItemRightClickedEvent event) {
407 showActionPopup(event.getItemId(), event.getClickX(), event.getClickY());
408 }
409 });
410
411 subAppEventBus.addHandler(ViewTypeChangedEvent.class, new ViewTypeChangedEvent.Handler() {
412
413 @Override
414 public void onViewChanged(ViewTypeChangedEvent event) {
415 BrowserLocation location = getCurrentLocation();
416
417 if (location.getViewType().equals(SearchPresenterDefinition.VIEW_TYPE)
418 && !event.getViewType().equals(SearchPresenterDefinition.VIEW_TYPE)) {
419 location.updateQuery("");
420 }
421 location.updateViewType(event.getViewType());
422 getAppContext().updateSubAppLocation(getSubAppContext(), location);
423 updateActionbar(actionbar);
424 }
425 });
426
427 subAppEventBus.addHandler(SearchEvent.class, new SearchEvent.Handler() {
428
429 @Override
430 public void onSearch(SearchEvent event) {
431 BrowserLocation location = getCurrentLocation();
432 if (StringUtils.isNotBlank(event.getSearchExpression())) {
433 location.updateViewType(SearchPresenterDefinition.VIEW_TYPE);
434 }
435 location.updateQuery(event.getSearchExpression());
436 getAppContext().updateSubAppLocation(getSubAppContext(), location);
437 updateActionbar(actionbar);
438 }
439 });
440 }
441
442 private void handleSelectionChange(Set<Object> selectionIds, ActionbarPresenter actionbar) {
443 BrowserLocation location = getCurrentLocation();
444 applySelectionToLocation(location, selectionIds.isEmpty() ? contentConnector.getDefaultItemId() : selectionIds.iterator().next());
445 getAppContext().updateSubAppLocation(getSubAppContext(), location);
446 updateActionbar(actionbar);
447
448 }
449
450 protected void applySelectionToLocation(BrowserLocation location, Object selectedId) {
451 location.updateNodePath("");
452 if (!contentConnector.canHandleItem(selectedId)) {
453
454 } else {
455 location.updateNodePath(contentConnector.getItemUrlFragment(selectedId));
456 }
457 }
458 }