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.actionbar;
35  
36  import info.magnolia.i18nsystem.SimpleTranslator;
37  import info.magnolia.ui.actionbar.definition.ActionbarDefinition;
38  import info.magnolia.ui.contentapp.browser.context.ValueContext;
39  import info.magnolia.ui.contentapp.browser.preview.PreviewProvider;
40  import info.magnolia.ui.framework.UiFrameworkView;
41  import info.magnolia.ui.framework.datasource.DatasourceComponent;
42  import info.magnolia.ui.framework.datasource.components.SelectedItems;
43  import info.magnolia.ui.vaadin.actionbar.Actionbar;
44  import info.magnolia.util.OptionalConsumer;
45  
46  import java.util.ArrayList;
47  import java.util.List;
48  
49  import javax.inject.Inject;
50  
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  
54  import com.vaadin.server.Resource;
55  import com.vaadin.ui.CssLayout;
56  
57  /**
58   * Actionbar view, lays out the sub-app actions according the {@link ActionbarDefinition},
59   * triggers their execution against the current value of the {@link ValueContext}.
60   *
61   * @param <T>
62   *     data type actionbar executes actions against
63   */
64  public class ActionbarView<T> extends CssLayout implements UiFrameworkView {
65  
66      private static final String PREVIEW_SECTION_NAME = "preview";
67  
68      private static final Logger log = LoggerFactory.getLogger(ActionbarView.class);
69  
70      private final Actionbar actionbar = new Actionbar();
71      private final ActionbarPresenter<T> presenter;
72      private final ActionbarDefinition definition;
73      private final SimpleTranslator simpleTranslator;
74  
75      @Inject
76      @SuppressWarnings("unchecked")
77      public ActionbarView(ValueContext<T> valueContext, ActionbarDefinition definition, SimpleTranslator simpleTranslator, @DatasourceComponent PreviewProvider<T> previewProvider) {
78          this.definition = definition;
79          this.simpleTranslator = simpleTranslator;
80          this.presenter = create(ActionbarPresenter.class);
81  
82          setHeight(100, Unit.PERCENTAGE);
83          addStyleName("actionbar");
84  
85          initialiseActionbar(definition);
86  
87          valueContext.current().observe(items -> {
88              this.update();
89              OptionalConsumer.of(items.flatMap(SelectedItems::getFirst).flatMap(previewProvider::getResource))
90                      .ifPresent(this::setPreview)
91                      .ifNotPresent(() -> setPreview(null));
92          });
93          addComponent(actionbar);
94      }
95  
96      private void setPreview(Resource previewResource) {
97          if (previewResource != null) {
98              if (!actionbar.getSections().containsKey(PREVIEW_SECTION_NAME)) {
99                  actionbar.addSection(PREVIEW_SECTION_NAME, simpleTranslator.translate("actionbar.preview"));
100             }
101             actionbar.setSectionPreview(previewResource, PREVIEW_SECTION_NAME);
102         } else {
103             if (actionbar.getSections().containsKey(PREVIEW_SECTION_NAME)) {
104                 actionbar.removeSection(PREVIEW_SECTION_NAME);
105             }
106         }
107     }
108 
109     private void initialiseActionbar(ActionbarDefinition definition) {
110         // build action bar structure from definition
111         definition.getSections().forEach(section -> {
112             actionbar.addSection(section.getName(), section.getLabel());
113             final List<String> usedActions = new ArrayList<>();
114             section.getGroups().forEach(group -> {
115                 // standalone groups make no sense
116                 log.debug("Group actions: {}", group.getItems());
117 
118                 group.getItems().forEach(action -> {
119                     if (usedActions.contains(action.getName())) {
120                         log.warn("Action was not added: an action with name '{}' was already added to the section '{}'.", action.getName(), section.getName());
121                         return;
122                     }
123 
124                     usedActions.add(action.getName());
125                     this.presenter
126                             .createActionItem(action.getName(), group.getName())
127                             .ifPresent(item -> {
128                                 actionbar.addAction(item, section.getName());
129                                 actionbar.setActionEnabled(action.getName(), this.presenter.isEnableAction(action.getName()));
130                             });
131                 });
132             });
133         });
134 
135         this.actionbar.addActionTriggerListener(presenter::fireAction);
136     }
137 
138     private void update() {
139         this.definition.getSections().forEach(section -> actionbar.setSectionVisible(section.getName(), false));
140         this.presenter
141                 .getAvailableSection(definition.getSections())
142                 .ifPresent(section -> {
143                     actionbar.setSectionVisible(section.getName(), true);
144                     section.getGroups().forEach(group -> group.getItems().forEach(action -> {
145                         actionbar.setActionEnabled(action.getName(), this.presenter.isEnableAction(action.getName()));
146                     }));
147                 });
148     }
149 }