View Javadoc
1   /**
2    * This file Copyright (c) 2013-2015 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.workbench;
35  
36  import info.magnolia.i18nsystem.SimpleTranslator;
37  import info.magnolia.ui.api.view.View;
38  import info.magnolia.ui.workbench.definition.ContentPresenterDefinition;
39  import info.magnolia.ui.workbench.list.ListPresenterDefinition;
40  import info.magnolia.ui.workbench.search.SearchPresenterDefinition;
41  import info.magnolia.ui.workbench.tree.TreePresenterDefinition;
42  import info.magnolia.ui.workbench.tree.TreeView;
43  
44  import java.io.Serializable;
45  import java.util.HashMap;
46  import java.util.Map;
47  
48  import javax.inject.Inject;
49  
50  import org.apache.commons.lang3.StringUtils;
51  
52  import com.vaadin.event.ShortcutAction;
53  import com.vaadin.event.ShortcutListener;
54  import com.vaadin.server.Sizeable;
55  import com.vaadin.shared.ui.MarginInfo;
56  import com.vaadin.ui.Button;
57  import com.vaadin.ui.Component;
58  import com.vaadin.ui.CssLayout;
59  import com.vaadin.ui.HorizontalLayout;
60  import com.vaadin.ui.NativeButton;
61  import com.vaadin.ui.Panel;
62  import com.vaadin.ui.VerticalLayout;
63  import com.vaadin.ui.themes.BaseTheme;
64  
65  /**
66   * Implementation of the workbench view.
67   */
68  public class WorkbenchViewImpl extends VerticalLayout implements WorkbenchView, Serializable {
69  
70      private final HorizontalLayout toolBar = new HorizontalLayout();
71  
72      private final CssLayout viewModes = new CssLayout();
73  
74      protected final Panel keyboardEventPanel;
75  
76      private StatusBarView statusBar;
77  
78      private Map<String, ContentView> contentViews = new HashMap<String, ContentView>();
79  
80      private Map<String, Button> contentViewsButton = new HashMap<String, Button>();
81  
82      private String currentViewType = TreePresenterDefinition.VIEW_TYPE;
83  
84      /**
85       * for going back from search view if search expression is empty.
86       */
87      private String previousViewType = currentViewType;
88  
89      private WorkbenchView.Listener listener;
90  
91      private final SimpleTranslator i18n;
92  
93      @Inject
94      public WorkbenchViewImpl(SimpleTranslator i18n) {
95          this.i18n = i18n;
96  
97          setSizeFull();
98          setMargin(new MarginInfo(true, false, false, true));
99          addStyleName("workbench");
100 
101         viewModes.setStyleName("view-modes");
102 
103         toolBar.addStyleName("toolbar");
104         toolBar.setWidth(100.0F, Sizeable.Unit.PERCENTAGE);
105         toolBar.addComponent(viewModes);
106         toolBar.setExpandRatio(viewModes, 1f);
107 
108         addComponent(toolBar);
109         setExpandRatio(toolBar, 0.0F);
110 
111         this.keyboardEventPanel = new Panel();
112         this.keyboardEventPanel.setSizeFull();
113         this.keyboardEventPanel.addStyleName("keyboard-panel");
114         addComponent(keyboardEventPanel, 1);
115         setExpandRatio(keyboardEventPanel, 1.0F);
116 
117         bindKeyboardHandlers();
118     }
119 
120     public void bindKeyboardHandlers() {
121 
122         final ShortcutListener enterShortcut = new ShortcutListener("Enter shortcut", ShortcutAction.KeyCode.ENTER, null) {
123             @Override
124             public void handleAction(Object sender, Object target) {
125                 getSelectedView().onShortcutKey(ShortcutAction.KeyCode.ENTER, null);
126             }
127         };
128         keyboardEventPanel.addShortcutListener(enterShortcut);
129 
130         final ShortcutListener deleteShortcut = new ShortcutListener("Delete shortcut", ShortcutAction.KeyCode.DELETE, null) {
131             @Override
132             public void handleAction(Object sender, Object target) {
133                 getSelectedView().onShortcutKey(ShortcutAction.KeyCode.DELETE, null);
134             }
135         };
136         // MGNLUI-2106 disable the delete shortcut until we apply it without disrupting inplace-editing
137         // keyboardEventPanel.addShortcutListener(deleteShortcut);
138     }
139 
140     @Override
141     public void setSearchQuery(String query) {
142         listener.onSearchQueryChange(query);
143     }
144 
145     @Override
146     public void addContentView(String viewType, ContentView view, ContentPresenterDefinition contentViewDefintion) {
147         contentViews.put(viewType, view);
148 
149         if (view instanceof TreeView) {
150             ((TreeView) view).setActionManager(keyboardEventPanel);
151         }
152 
153         // display search-box only if both list and search content presenters are configured
154         if (contentViews.containsKey(ListPresenterDefinition.VIEW_TYPE) && contentViews.containsKey(SearchPresenterDefinition.VIEW_TYPE)) {
155             if (toolBar.getComponentCount() > 1) { // components > 1 because first component in the toolbar is switcher between tree/list view
156                 toolBar.getComponent(1).setVisible(true);
157             }
158         }
159 
160         if (contentViewDefintion instanceof SearchPresenterDefinition) {
161             // do not add a view-type button for search
162             return;
163         }
164 
165         // set button
166         Button button = buildButton(viewType, contentViewDefintion.getIcon(), contentViewDefintion.isActive());
167         contentViewsButton.put(viewType, button);
168         viewModes.addComponent(button);
169         // set active
170         if (contentViewDefintion.isActive()) {
171             currentViewType = previousViewType = viewType;
172         }
173     }
174 
175     @Override
176     public void setViewType(String type) {
177         final Component c = contentViews.get(type).asVaadinComponent();
178 
179         keyboardEventPanel.setContent(c);
180 
181         if (!StringUtils.equals(type, SearchPresenterDefinition.VIEW_TYPE)) {
182             previousViewType = type;
183             setSearchQuery(null);
184         }
185         setViewTypeStyling(type);
186 
187         currentViewType = type;
188     }
189 
190     private void fireViewTypeChangedEvent(String viewType) {
191         this.listener.onViewTypeChanged(viewType);
192     }
193 
194     @Override
195     public void setStatusBarView(StatusBarView statusBar) {
196         Component c = statusBar.asVaadinComponent();
197         if (this.statusBar == null) {
198             addComponent(c, getComponentCount()); // add last
199         } else {
200             replaceComponent(this.statusBar.asVaadinComponent(), c);
201         }
202         setExpandRatio(c, 0);
203         this.statusBar = statusBar;
204     }
205 
206     @Override
207     public ContentView getSelectedView() {
208         return contentViews.get(currentViewType);
209     }
210 
211     @Override
212     public Component asVaadinComponent() {
213         return this;
214     }
215 
216     @Override
217     public void setListener(WorkbenchView.Listener listener) {
218         this.listener = listener;
219     }
220 
221     private Button buildButton(final String viewType, final String icon, final boolean active) {
222         NativeButton button = new NativeButton(null, new Button.ClickListener() {
223             @Override
224             public void buttonClick(Button.ClickEvent event) {
225                 fireViewTypeChangedEvent(viewType);
226             }
227         });
228         button.setStyleName(BaseTheme.BUTTON_LINK);
229 
230         button.setHtmlContentAllowed(true);
231         button.setCaption("<span class=\"" + icon + "\"></span><span class=\"view-type-arrow view-type-arrow-" + viewType + " icon-arrow2_n\"></span>");
232 
233         if (active) {
234             button.addStyleName("active");
235         }
236         return button;
237     }
238 
239     private void setViewTypeStyling(final String viewType) {
240         for (Map.Entry<String, Button> entry : contentViewsButton.entrySet()) {
241             entry.getValue().removeStyleName("active");
242             if (entry.getKey().equals(viewType)) {
243                 entry.getValue().addStyleName("active");
244             }
245         }
246         // search is a list view
247         if (viewType.equals(SearchPresenterDefinition.VIEW_TYPE) && contentViews.containsKey(ListPresenterDefinition.VIEW_TYPE)) {
248             contentViewsButton.get(ListPresenterDefinition.VIEW_TYPE).addStyleName("active");
249         }
250     }
251 
252     @Override
253     public void setMultiselect(boolean multiselect) {
254         for (String type : contentViews.keySet()) {
255             contentViews.get(type).setMultiselect(multiselect);
256         }
257     }
258 
259     @Override
260     public void addContentTool(View view) {
261         toolBar.addComponent(view.asVaadinComponent(), toolBar.getComponentCount());
262     }
263 }