View Javadoc
1   /**
2    * This file Copyright (c) 2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.contentapp.browser;
35  
36  import info.magnolia.ui.api.app.AppContext;
37  import info.magnolia.ui.api.app.SubAppContext;
38  import info.magnolia.ui.contentapp.ContentBrowserSubApp;
39  import info.magnolia.ui.contentapp.browser.actionbar.ActionbarView;
40  import info.magnolia.ui.contentapp.browser.context.LocationContext;
41  import info.magnolia.ui.contentapp.browser.context.ValueContext;
42  import info.magnolia.ui.contentapp.configuration.BrowserDescriptor;
43  import info.magnolia.ui.contentapp.configuration.WorkbenchDefinition;
44  import info.magnolia.ui.framework.ContextProperty;
45  import info.magnolia.ui.framework.UiFrameworkView;
46  import info.magnolia.ui.framework.ViewDefinition;
47  import info.magnolia.ui.framework.ViewProvider;
48  import info.magnolia.ui.framework.datasource.DatasourceComponent;
49  import info.magnolia.ui.framework.datasource.components.ItemResolver;
50  import info.magnolia.ui.framework.datasource.components.SelectedItems;
51  
52  import java.util.Objects;
53  import java.util.Optional;
54  
55  import javax.inject.Inject;
56  
57  import com.vaadin.ui.CustomComponent;
58  import com.vaadin.ui.HorizontalLayout;
59  import com.vaadin.ui.VerticalLayout;
60  
61  /**
62   * View part of the new browser sub-app.
63   *
64   * @param <T> item type.
65   * @param <DS> data source definition type.
66   */
67  public class Browser<T, DS> extends CustomComponent implements UiFrameworkView {
68  
69      private final ContextProperty<ContentBrowserSubApp.BrowserLocation> location;
70      private final ValueContext<T> valueContext;
71      private final SubAppContext subAppContext;
72      private final AppContext appContext;
73      private final ItemResolver<T> itemResolver;
74  
75      @Inject
76      public Browser(
77              BrowserDescriptor<T, DS> descriptor,
78              SubAppContext subAppContext,
79              AppContext appContext,
80              @DatasourceComponent ItemResolver<T> itemResolver) {
81          this.subAppContext = subAppContext;
82          this.appContext = appContext;
83          this.itemResolver = itemResolver;
84  
85          valueContext = bindContext(ValueContext.class);
86          location = bindContext(LocationContext.class).location();
87  
88          valueContext.current().observe(valueOptional ->
89                  valueOptional.ifPresent(selectedItems ->
90                          location.mutate(location -> pushItemPathIntoLocation(selectedItems, location))));
91  
92          location.observe(locationOptional ->
93                  locationOptional.ifPresent(location -> {
94                      final ContextProperty<SelectedItems<T>> currentValue = valueContext.current();
95                      final Optional<String> currentPath = currentValue.value().flatMap(selectedItems ->  selectedItems.getFirst().map(itemResolver::getPath));
96  
97                      if (currentPath.map(path -> !Objects.equals(path, location.getNodePath())).orElse(false)) {
98                          itemResolver.getItemByPath(location.getNodePath()).ifPresent(t -> currentValue.set(SelectedItems.of(t)));
99                      }
100                 }));
101 
102         layout(descriptor);
103     }
104 
105     private void pushItemPathIntoLocation(SelectedItems<T> selectedItems, ContentBrowserSubApp.BrowserLocation location) {
106         selectedItems.getFirst().ifPresent(value -> {
107             location.updateNodePath(itemResolver.getPath(value));
108             this.updateLocation(location);
109         });
110     }
111 
112     private void updateLocation(ContentBrowserSubApp.BrowserLocation location) {
113         appContext.updateSubAppLocation(subAppContext, location);
114     }
115 
116     private void layout(BrowserDescriptor<T, DS> descriptor) {
117         final HorizontalLayout workbenchWrapper = new HorizontalLayout();
118         workbenchWrapper.setSizeFull();
119 
120         final ViewProvider viewProvider = getViewProvider();
121 
122         final WorkbenchDefinition<T> workbenchDefinition = descriptor.getWorkbench();
123         final Workbench<T> workbench = viewProvider.create("workbench", workbenchDefinition.getImplementationClass(), workbenchDefinition);
124         workbench.onContentViewTypeChange(viewId -> location.mutate(location -> location.updateViewType(viewId)));
125         workbench.setTitle(descriptor.getLabel());
126 
127         workbenchWrapper.addComponentsAndExpand(workbench);
128         workbenchWrapper.addComponents(viewProvider.create("actionbar", ActionbarView.class, descriptor.getActionbar()));
129 
130         @SuppressWarnings("unchecked")
131         final UiFrameworkView statusBar = getViewProvider().create(
132                 ViewDefinition.builder()
133                         .withName("statusbar")
134                         .withImplementationClass(StatusBar.class)
135                         .build());
136 
137         VerticalLayout browser = new VerticalLayout(workbenchWrapper, statusBar.asVaadinComponent());
138         browser.setSizeFull();
139         browser.setSpacing(false);
140         browser.setMargin(false);
141         browser.setExpandRatio(workbenchWrapper, 1f);
142         browser.setExpandRatio(statusBar.asVaadinComponent(), 0);
143         browser.addStyleName("browser");
144 
145         setCompositionRoot(browser);
146         setSizeFull();
147     }
148 
149     public void setLocation(ContentBrowserSubApp.BrowserLocation location) {
150         this.location.set(location);
151     }
152 }