/** * Sencha GXT 3.1.1 - Sencha for GWT * Copyright(c) 2007-2014, Sencha, Inc. * licensing@sencha.com * * http://www.sencha.com/products/gxt/license/ */ package com.dldinternet.aws.cfn.stacker.desktopapp.client; import com.dldinternet.aws.cfn.stacker.desktopapp.client.persistence.StorageProvider; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.UIObject; import com.dldinternet.aws.cfn.stacker.desktop.client.layout.DesktopLayoutType; import com.dldinternet.aws.cfn.stacker.desktop.client.widget.ShortcutCell.ShortcutCellAppearance; import com.dldinternet.aws.cfn.stacker.desktopapp.client.event.LoginEvent; import com.dldinternet.aws.cfn.stacker.desktopapp.client.event.LoginEvent.LoginHandler; import com.dldinternet.aws.cfn.stacker.desktopapp.client.event.LogoutEvent; import com.dldinternet.aws.cfn.stacker.desktopapp.client.event.LogoutEvent.LogoutHandler; import com.dldinternet.aws.cfn.stacker.desktopapp.client.service.LoginServiceProvider; import com.dldinternet.aws.cfn.stacker.desktopapp.client.service.ProfileServiceProvider; import com.dldinternet.aws.cfn.stacker.desktopapp.client.utility.Prompt; import com.sencha.gxt.widget.core.client.box.AlertMessageBox; import java.util.logging.Level; import java.util.logging.Logger; /** * A sample application that provides a basic desktop capability in a browser * window. This includes a start menu, shortcuts and a task bar with buttons for * each active application, as well as support for multiple users, each with * their own profile settings. Desktop applications include: *
*
File Manager
*
Uses a {@link com.sencha.gxt.widget.core.client.treegrid.TreeGrid} to provides access to a hierarchical, * browser-based file system, which is persistent on browsers that support HTML5 * Local Storage. Users may create folders, documents, browser shortcuts, and * other files, rename files and drag and drop to move files in the file system. * As file operations occur, open applications respond appropriately (e.g. to * indicate renamed or moved files).
*
Word Processor
*
Uses a {@link com.sencha.gxt.widget.core.client.form.HtmlEditor} to provides a simple rich editing capability * with documents that can be stored locally in the browser based file system. * Automatically propagates saved changes to other Word Processor windows, * closes if the document is deleted in File Manager, as well as handling * documents that are renamed or moved using File Manager.
*
Browser
*
Uses a {@link com.google.gwt.user.client.ui.Frame} to provide a browser-within-a-browser that displays * a browser web page within the desktop. Although this may sound like a * gimmick, it's amazing how useful it can be to display multiple web pages * simultaneously in conjunction with the {@link DesktopLayoutType#TILE} * feature.
*
Spreadsheet
*
Uses a {@link com.sencha.gxt.widget.core.client.grid.Grid} to provide a simple spreadsheet capability, including * sorting, column and row move, insert and delete as well as formulas and * charts.
*
Program
*
Uses JSNI to provide a simple JavaScript snippet * interpreter, including use of references to the page's window object and * call-backs to a Java method.
*
* In addition to highlighting the capability of the GXT components and * providing useful, reusable function, the desktop application illustrates a * number of best practices for creating complex, interactive real-world * applications. *

*

*

* In addition, this application illustrates the use of a number of GWT and * Sencha technologies, including: *

*

* If the browser does not support HTML5 Local Storage, or it is not configured * for use with the application, this application will prompt the user whether * to degrade gracefully to temporary (in-memory) storage that will be freed * when the browser terminates or the the browser window is refreshed. *

* To request that the desktop application prompt the user to clear all local * storage for all users of this application, add #clear to the * application URL. *

* This sample application is under continuing development. The API is subject * to change without notice. */ public class DesktopApp implements EntryPoint { private DesktopBus desktopBus; private DesktopAppPresenter desktopAppPresenter; private LoginHandler loginHandler; private LoginServiceProvider loginServiceProvider; private ProfileServiceProvider profileServiceProvider; private LogoutHandler logoutHandler; private LoginPresenter loginPresenter; private ProfilePresenter profilePresenter; public void loadModule(HasWidgets hasWidgets) { setBackground(hasWidgets); initializeDesktopBus(hasWidgets); if (!getDesktopAppPresenter().isLocalStorageSupported()) { loadApplicationAfterAlertingUser(hasWidgets); } else { loadApplication(hasWidgets); } } @Override public void onModuleLoad() { // Set the FINEST logging to inspect storage ... Logger logger = Logger.getLogger(StorageProvider.class.getName()); logger.setLevel(Level.FINEST); setUncaughtExceptionHandler(); loadModule(RootPanel.get()); Element body = RootPanel.getBodyElement(); @SuppressWarnings("GwtToHtmlReferences") Element loading = RootPanel.get("loading").getElement(); body.removeChild(loading); // DOM.removeChild(RootPanel.getBodyElement(), DOM.getElementById("loading")); } private void checkForLogin(HasWidgets hasWidgets) { if (getDesktopAppPresenter().isLoggedIn()) { displayView(hasWidgets); } else { getDesktopBus().invokeLoginService(); } } private void displayView(HasWidgets hasWidgets) { getDesktopAppPresenter().go(hasWidgets); } private DesktopAppPresenter getDesktopAppPresenter() { if (desktopAppPresenter == null) { desktopAppPresenter = new DesktopAppPresenterImpl(getDesktopBus()); } return desktopAppPresenter; } private DesktopBus getDesktopBus() { if (desktopBus == null) { desktopBus = new DesktopBus(); } return desktopBus; } private LoginHandler getLoginHandler(final HasWidgets hasWidgets) { if (loginHandler == null) { loginHandler = new LoginHandler() { @Override public void onLogin(LoginEvent loginEvent) { displayView(hasWidgets); if (loginEvent.isNewUser()) { getDesktopBus().invokeProfileService(); } } }; } return loginHandler; } private LoginPresenter getLoginPresenter() { if (loginPresenter == null) { loginPresenter = new LoginPresenterImpl(getDesktopAppPresenter()); } return loginPresenter; } private LoginServiceProvider getLoginServiceProvider(HasWidgets rootPanel) { if (loginServiceProvider == null) { loginServiceProvider = new LoginServiceProvider(getLoginPresenter(), rootPanel); } return loginServiceProvider; } private LogoutHandler getLogoutHandler() { if (logoutHandler == null) { logoutHandler = new LogoutHandler() { @Override public void onLogout(LogoutEvent logoutEvent) { com.google.gwt.user.client.Window.Location.reload(); } }; } return logoutHandler; } private ProfilePresenter getProfilePresenter() { if (profilePresenter == null) { profilePresenter = new ProfilePresenterImpl(getDesktopAppPresenter()); } return profilePresenter; } private ProfileServiceProvider getProfileServiceProvider(HasWidgets hasWidgets) { if (profileServiceProvider == null) { profileServiceProvider = new ProfileServiceProvider(getProfilePresenter(), hasWidgets); } return profileServiceProvider; } private void initializeDesktopBus(HasWidgets hasWidgets) { getDesktopBus().registerLoginService(getLoginServiceProvider(hasWidgets)); getDesktopBus().registerProfileService(getProfileServiceProvider(hasWidgets)); getDesktopBus().addLoginHandler(getLoginHandler(hasWidgets)); getDesktopBus().addLogoutHandler(getLogoutHandler()); } private void loadApplication(HasWidgets hasWidgets) { if ("clear".equals(History.getToken())) { promptToClearStorage(hasWidgets); } else { checkForLogin(hasWidgets); } } private void loadApplicationAfterAlertingUser(final HasWidgets hasWidgets) { Prompt.get().alert( "Local Storage is Not Supported", "Either your browser does not support HTML5 Local Storage or it is not configured for use by this application.

This application will continue to run, but anything you create will be discarded when the browser terminates or the browser window is refreshed.", new Runnable() { @Override public void run() { loadApplication(hasWidgets); } }); } private void promptToClearStorage(final HasWidgets hasWidgets) { Prompt.get().confirm("Desktop", "Would you like to clear this domain's local storage before continuing?", new Runnable() { @Override public void run() { getDesktopAppPresenter().clearLocalStorage(); checkForLogin(hasWidgets); } }, new Runnable() { @Override public void run() { checkForLogin(hasWidgets); } }); } private void setBackground(HasWidgets hasWidgets) { if (hasWidgets instanceof UIObject) { ((UIObject) hasWidgets).addStyleName("x-desktop"); } } private void setUncaughtExceptionHandler() { GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void onUncaughtException(Throwable e) { e.printStackTrace(); Throwable rootCause = getRootCause(e); new AlertMessageBox("Exception", rootCause.toString()).show(); } }); } private Throwable getRootCause(Throwable e) { Throwable lastCause; do { lastCause = e; } while ((e = e.getCause()) != null); return lastCause; } }