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