001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.apps;
029
030import org.opencms.main.CmsLog;
031import org.opencms.ui.A_CmsUI;
032import org.opencms.ui.CmsVaadinUtils;
033import org.opencms.ui.I_CmsAppView;
034import org.opencms.ui.Messages;
035import org.opencms.ui.apps.CmsWorkplaceAppManager.NavigationState;
036import org.opencms.ui.components.CmsAppViewLayout;
037import org.opencms.ui.components.I_CmsWindowCloseListener;
038import org.opencms.ui.components.OpenCmsTheme;
039
040import java.util.HashMap;
041import java.util.HashSet;
042import java.util.Map;
043import java.util.Set;
044
045import org.apache.commons.logging.Log;
046
047import com.vaadin.event.Action;
048import com.vaadin.event.Action.Handler;
049import com.vaadin.event.ShortcutAction;
050import com.vaadin.navigator.ViewChangeListener;
051import com.vaadin.server.Page.BrowserWindowResizeEvent;
052import com.vaadin.server.Page.BrowserWindowResizeListener;
053import com.vaadin.ui.Label;
054import com.vaadin.ui.UI;
055import com.vaadin.ui.VerticalLayout;
056import com.vaadin.ui.themes.ValoTheme;
057
058/**
059 * Displays the selected app.<p>
060 */
061public class CmsAppView
062implements ViewChangeListener, I_CmsWindowCloseListener, I_CmsAppView, Handler, BrowserWindowResizeListener {
063
064    /**
065     * Enum representing caching status of a view.<p>
066     */
067    public static enum CacheStatus {
068        /** Cache view. */
069        cache,
070
071        /** Cache view one time only. */
072        cacheOnce,
073
074        /** Don't cache view. */
075        noCache
076    }
077
078    /**
079     * Used in case the requested app can not be displayed to the current user.<p>
080     */
081    protected class NotAvailableApp implements I_CmsWorkplaceApp {
082
083        /**
084         * @see org.opencms.ui.apps.I_CmsWorkplaceApp#initUI(org.opencms.ui.apps.I_CmsAppUIContext)
085         */
086        public void initUI(I_CmsAppUIContext context) {
087
088            Label label = new Label(CmsVaadinUtils.getMessageText(Messages.GUI_APP_NOT_AVAILABLE_0));
089            label.addStyleName(ValoTheme.LABEL_H2);
090            label.addStyleName(OpenCmsTheme.LABEL_ERROR);
091            VerticalLayout content = new VerticalLayout();
092            content.setMargin(true);
093            content.addComponent(label);
094            context.setAppContent(content);
095        }
096
097        /**
098         * @see org.opencms.ui.apps.I_CmsWorkplaceApp#onStateChange(java.lang.String)
099         */
100        public void onStateChange(String state) {
101
102            // nothing to do
103        }
104
105    }
106
107    /** The history back action. */
108    private static final Action ACTION_HISTORY_BACK = new ShortcutAction(
109        "Alt+ArrowLeft",
110        ShortcutAction.KeyCode.ARROW_LEFT,
111        new int[] {ShortcutAction.ModifierKey.ALT});
112
113    /** The history forward action. */
114    private static final Action ACTION_HISTORY_FORWARD = new ShortcutAction(
115        "Alt+ArrowRight",
116        ShortcutAction.KeyCode.ARROW_RIGHT,
117        new int[] {ShortcutAction.ModifierKey.ALT});
118
119    /** The serial version id. */
120    private static final long serialVersionUID = -8128528863875050216L;
121
122    /** Logger instance for this class. */
123    private static final Log LOG = CmsLog.getLog(CmsAppView.class);
124
125    /** The current app. */
126    private I_CmsWorkplaceApp m_app;
127
128    /** The app shortcut actions. */
129    private Map<Action, Runnable> m_appActions;
130
131    /** The app configuration. */
132    private I_CmsWorkplaceAppConfiguration m_appConfig;
133
134    /** The app layout component. */
135    private CmsAppViewLayout m_appLayout;
136
137    /** The cache status. */
138    private CacheStatus m_cacheStatus = CacheStatus.noCache;
139
140    /** The default shortcut actions. */
141    private Map<Action, Runnable> m_defaultActions;
142
143    /** The requires restore from cache flag. */
144    private boolean m_requiresRestore;
145
146    /**
147     * Constructor.<p>
148     *
149     * @param appConfig the app configuration
150     */
151    public CmsAppView(I_CmsWorkplaceAppConfiguration appConfig) {
152
153        m_appConfig = appConfig;
154        m_defaultActions = new HashMap<Action, Runnable>();
155        m_defaultActions.put(ACTION_HISTORY_BACK, new Runnable() {
156
157            public void run() {
158
159                ((CmsAppWorkplaceUi)UI.getCurrent()).historyBack();
160            }
161        });
162        m_defaultActions.put(ACTION_HISTORY_FORWARD, new Runnable() {
163
164            public void run() {
165
166                ((CmsAppWorkplaceUi)UI.getCurrent()).historyForward();
167            }
168        });
169    }
170
171    /**
172     * @see com.vaadin.navigator.ViewChangeListener#afterViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
173     */
174    public void afterViewChange(ViewChangeEvent event) {
175
176        if (m_app instanceof ViewChangeListener) {
177            ((ViewChangeListener)m_app).afterViewChange(event);
178        }
179    }
180
181    /**
182     * @see com.vaadin.navigator.ViewChangeListener#beforeViewChange(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
183     */
184    public boolean beforeViewChange(ViewChangeEvent event) {
185
186        disableGlobalShortcuts();
187        if (m_appLayout != null) {
188            m_appLayout.closePopupViews();
189        }
190        if (m_app instanceof ViewChangeListener) {
191            return ((ViewChangeListener)m_app).beforeViewChange(event);
192        }
193        return true;
194    }
195
196    /**
197     * @see com.vaadin.server.Page.BrowserWindowResizeListener#browserWindowResized(com.vaadin.server.Page.BrowserWindowResizeEvent)
198     */
199    public void browserWindowResized(BrowserWindowResizeEvent event) {
200
201        if (m_appLayout != null) {
202            m_appLayout.browserWindowResized(event);
203        }
204    }
205
206    /**
207     * @see org.opencms.ui.I_CmsAppView#disableGlobalShortcuts()
208     */
209    public void disableGlobalShortcuts() {
210
211        UI.getCurrent().removeActionHandler(this);
212    }
213
214    /**
215     * @see org.opencms.ui.I_CmsAppView#enableGlobalShortcuts()
216     */
217    public void enableGlobalShortcuts() {
218
219        // to avoid multiple action handler registration, remove this first
220        UI.getCurrent().removeActionHandler(this);
221        UI.getCurrent().addActionHandler(this);
222    }
223
224    /**
225     * @see org.opencms.ui.I_CmsAppView#enter(java.lang.String)
226     */
227    public void enter(String newState) {
228
229        if (newState.startsWith(NavigationState.PARAM_SEPARATOR)) {
230            newState = newState.substring(1);
231        }
232        if ((m_appLayout != null) && (m_appConfig != null)) {
233            m_appLayout.setAppTitle(m_appConfig.getName(UI.getCurrent().getLocale()));
234        }
235        m_app.onStateChange(newState);
236        if (m_app instanceof I_CmsHasShortcutActions) {
237            m_appActions = ((I_CmsHasShortcutActions)m_app).getShortcutActions();
238        }
239        UI.getCurrent().addActionHandler(this);
240    }
241
242    /**
243     * @see com.vaadin.navigator.View#enter(com.vaadin.navigator.ViewChangeListener.ViewChangeEvent)
244     */
245    public void enter(ViewChangeEvent event) {
246
247        String newState = event.getParameters();
248        enter(newState);
249    }
250
251    /**
252     * @see com.vaadin.event.Action.Handler#getActions(java.lang.Object, java.lang.Object)
253     */
254    public Action[] getActions(Object target, Object sender) {
255
256        if (m_appActions != null) {
257            Set<Action> actions = new HashSet<Action>(m_defaultActions.keySet());
258            actions.addAll(m_appActions.keySet());
259            return actions.toArray(new Action[actions.size()]);
260        }
261        return m_defaultActions.keySet().toArray(new Action[m_defaultActions.size()]);
262    }
263
264    /**
265     * Gets the cache status of the view.<p>
266     *
267     * @return the cache status of the view
268     */
269    public CacheStatus getCacheStatus() {
270
271        return m_cacheStatus;
272    }
273
274    /**
275     * @see org.opencms.ui.I_CmsAppView#getComponent()
276     */
277    public CmsAppViewLayout getComponent() {
278
279        if (m_app == null) {
280            return reinitComponent();
281        }
282        return m_appLayout;
283    }
284
285    /**
286     * @see org.opencms.ui.I_CmsAppView#getName()
287     */
288    public String getName() {
289
290        return m_appConfig.getId();
291    }
292
293    /**
294     * @see com.vaadin.event.Action.Handler#handleAction(com.vaadin.event.Action, java.lang.Object, java.lang.Object)
295     */
296    public void handleAction(Action action, Object sender, Object target) {
297
298        if ((m_appActions != null) && m_appActions.containsKey(action)) {
299            m_appActions.get(action).run();
300        } else if (m_defaultActions.containsKey(action)) {
301            m_defaultActions.get(action).run();
302        }
303    }
304
305    /**
306     * @see org.opencms.ui.I_CmsAppView#isCachable()
307     */
308    public boolean isCachable() {
309
310        return (m_app instanceof I_CmsCachableApp) && ((I_CmsCachableApp)m_app).isCachable();
311    }
312
313    /**
314     * @see org.opencms.ui.components.I_CmsWindowCloseListener#onWindowClose()
315     */
316    public void onWindowClose() {
317
318        if (m_app instanceof I_CmsWindowCloseListener) {
319            ((I_CmsWindowCloseListener)m_app).onWindowClose();
320        }
321        disableGlobalShortcuts();
322    }
323
324    /**
325     * @see org.opencms.ui.I_CmsAppView#reinitComponent()
326     */
327    public CmsAppViewLayout reinitComponent() {
328
329        if (m_app != null) {
330            beforeViewChange(
331                new ViewChangeEvent(CmsAppWorkplaceUi.get().getNavigator(), this, this, m_appConfig.getId(), ""));
332        }
333        if (!m_appConfig.getVisibility(A_CmsUI.getCmsObject()).isActive()) {
334            m_app = new NotAvailableApp();
335        } else {
336            m_app = m_appConfig.getAppInstance();
337        }
338        m_appLayout = new CmsAppViewLayout(m_appConfig.getId());
339        m_appLayout.setAppTitle(m_appConfig.getName(UI.getCurrent().getLocale()));
340        m_app.initUI(m_appLayout);
341        return m_appLayout;
342    }
343
344    /**
345     * @see org.opencms.ui.I_CmsAppView#requiresRestore()
346     */
347    public boolean requiresRestore() {
348
349        return m_requiresRestore;
350    }
351
352    /**
353     * Restores the view from cache.<p>
354     */
355    public void restoreFromCache() {
356
357        ((I_CmsCachableApp)m_app).onRestoreFromCache();
358        m_requiresRestore = false;
359    }
360
361    /**
362     * Sets the cache status.
363     *
364     * @param status the new cache status
365     */
366    public void setCacheStatus(CacheStatus status) {
367
368        m_cacheStatus = status;
369    }
370
371    /**
372     * @see org.opencms.ui.I_CmsAppView#setRequiresRestore(boolean)
373     */
374    public void setRequiresRestore(boolean restored) {
375
376        m_requiresRestore = restored;
377    }
378
379    /**
380     * @see java.lang.Object#toString()
381     */
382    @Override
383    public String toString() {
384
385        return "appView " + getName() + System.identityHashCode(this) + " (" + m_app + ")";
386    }
387
388}