Introduce SimpleApp and SimpleErgonomics
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 8 May 2015 15:46:44 +0000 (15:46 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 8 May 2015 15:46:44 +0000 (15:46 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8102 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java
org.argeo.cms/src/org/argeo/cms/CmsApplication.java
org.argeo.cms/src/org/argeo/cms/CmsLogin.java [deleted file]
org.argeo.cms/src/org/argeo/cms/util/OpenUserMenu.java
org.argeo.cms/src/org/argeo/cms/util/SimpleApp.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/util/SimpleErgonomics.java [new file with mode: 0644]

index d3d4cbe90be035aa197e6e13e31a742d2c39f5c4..9a7f6412e862a5b219df558932fe5b6952606f92 100644 (file)
@@ -18,6 +18,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
 import org.argeo.cms.auth.ArgeoLoginContext;
+import org.argeo.cms.auth.LoginRequiredException;
 import org.argeo.cms.i18n.Msg;
 import org.argeo.jcr.JcrUtils;
 import org.eclipse.rap.rwt.RWT;
@@ -27,22 +28,24 @@ import org.eclipse.rap.rwt.client.service.BrowserNavigation;
 import org.eclipse.rap.rwt.client.service.BrowserNavigationEvent;
 import org.eclipse.rap.rwt.client.service.BrowserNavigationListener;
 import org.eclipse.rap.rwt.client.service.JavaScriptExecutor;
+import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
 
 /** Manages history and navigation */
-abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
-               CmsSession {
+public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint
+               implements CmsSession {
        private final Log log = LogFactory.getLog(AbstractCmsEntryPoint.class);
 
-       private Subject subject = new Subject();
+       private final Subject subject = new Subject();
 
-       private Repository repository;
-       private String workspace;
-       private Session session;
+       private final Repository repository;
+       private final String workspace;
+       private final String defaultPath;
        private final Map<String, String> factoryProperties;
 
-       // current state
+       // Current state
+       private Session session;
        private Node node;
        private String state;
        private String page;
@@ -53,9 +56,10 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
        private final BrowserNavigation browserNavigation;
 
        public AbstractCmsEntryPoint(Repository repository, String workspace,
-                       Map<String, String> factoryProperties) {
+                       String defaultPath, Map<String, String> factoryProperties) {
                this.repository = repository;
                this.workspace = workspace;
+               this.defaultPath = defaultPath;
                this.factoryProperties = new HashMap<String, String>(factoryProperties);
 
                // Initial login
@@ -80,8 +84,6 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                if (browserNavigation != null)
                        browserNavigation
                                        .addBrowserNavigationListener(new CmsNavigationListener());
-
-               // RWT.setLocale(Locale.FRANCE);
        }
 
        @Override
@@ -100,32 +102,36 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                return shell;
        }
 
-       /** Recreate header UI */
-       protected abstract void refreshHeader();
+       @Override
+       protected final void createContents(Composite parent) {
+               try {
+                       getShell().getDisplay().setData(CmsSession.KEY, this);
+
+                       createUi(parent);
+               } catch (Exception e) {
+                       throw new CmsException("Cannot create entrypoint contents", e);
+               }
+       }
+
+       /** Create UI */
+       protected abstract void createUi(Composite parent);
 
-       /** Recreate body UI */
-       protected abstract void refreshBody();
+       /** Recreate UI after navigation or auth change */
+       protected abstract void refresh();
 
        /**
         * The node to return when no node was found (for authenticated users and
         * anonymous)
         */
-       protected abstract Node getDefaultNode(Session session)
-                       throws RepositoryException;
-
-       /**
-        * Reasonable default since it is a nt:hierarchyNode and is thus compatible
-        * with the obvious default folder type, nt:folder, conceptual equivalent of
-        * an empty text file in an operating system. To be overridden.
-        */
-       // protected String getDefaultNewNodeType() {
-       // return CmsTypes.CMS_TEXT;
-       // }
-
-       /** Default new folder type (used in mkdirs) is nt:folder. To be overridden. */
-       // protected String getDefaultNewFolderType() {
-       // return NodeType.NT_FOLDER;
-       // }
+       protected Node getDefaultNode(Session session) throws RepositoryException {
+               if (!session.hasPermission(defaultPath, "read")) {
+                       if (session.getUserID().equals("anonymous"))
+                               throw new LoginRequiredException();
+                       else
+                               throw new CmsException("Unauthorized");
+               }
+               return session.getNode(defaultPath);
+       }
 
        protected String getBaseTitle() {
                return factoryProperties.get(WebClient.PAGE_TITLE);
@@ -134,7 +140,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
        public void navigateTo(String state) {
                exception = null;
                String title = setState(state);
-               refreshBody();
+               refresh();
                if (browserNavigation != null)
                        browserNavigation.pushState(state, title);
        }
@@ -157,8 +163,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                                node = session.getNode(currentPath);
 
                        // refresh UI
-                       refreshHeader();
-                       refreshBody();
+                       refresh();
                } catch (RepositoryException e) {
                        throw new CmsException("Cannot perform auth change", e);
                }
@@ -169,7 +174,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
        public void exception(Throwable e) {
                this.exception = e;
                log.error("Unexpected exception in CMS", e);
-               refreshBody();
+               refresh();
        }
 
        @Override
@@ -205,34 +210,10 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                        } else if (firstSlash > 0) {
                                String prefix = state.substring(0, firstSlash);
                                String path = state.substring(firstSlash);
-                               // if (session.getWorkspace().getNodeTypeManager()
-                               // .hasNodeType(prefix)) {
-                               // String nodeType = prefix;
-                               // if (!session.nodeExists(path))
-                               // node = addNode(session, path, nodeType);
-                               // else {
-                               // node = session.getNode(path);
-                               // if (!node.isNodeType(nodeType))
-                               // throw new CmsException("Node " + path
-                               // + " not of type " + nodeType);
-                               // }
-                               // } else if ("delete".equals(prefix)) {
-                               // if (session.itemExists(path)) {
-                               // Node nodeToDelete = session.getNode(path);
-                               // // TODO "Are you sure?"
-                               // nodeToDelete.remove();
-                               // session.save();
-                               // log.debug("Deleted " + path);
-                               // navigateTo(previousState);
-                               // } else
-                               // throw new CmsException("Data " + path
-                               // + " does not exist");
-                               // } else {
                                if (session.nodeExists(path))
                                        node = session.getNode(path);
                                else
                                        throw new CmsException("Data " + path + " does not exist");
-                               // }
                                page = prefix;
                        } else {
                                node = getDefaultNode(session);
@@ -255,6 +236,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
 
                        return title;
                } catch (Exception e) {
+                       log.error("Cannot set state '" + state + "'", e);
                        if (previousState.equals(""))
                                previousState = "~";
                        navigateTo(previousState);
@@ -263,13 +245,6 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                }
        }
 
-       // protected Node addNode(Session session, String path, String nodeType)
-       // throws RepositoryException {
-       // return JcrUtils.mkdirs(session, path, nodeType != null ? nodeType
-       // : getDefaultNewNodeType(), getDefaultNewFolderType(), false);
-       // // not saved, so that the UI can discard it later on
-       // }
-
        protected Node getNode() {
                return node;
        }
@@ -278,10 +253,6 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                return state;
        }
 
-       // String getPage() {
-       // return page;
-       // }
-
        protected Throwable getException() {
                return exception;
        }
@@ -300,8 +271,7 @@ abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implements
                @Override
                public void navigated(BrowserNavigationEvent event) {
                        setState(event.getState());
-                       refreshBody();
+                       refresh();
                }
        }
-
-}
+}
\ No newline at end of file
index 2f2697d5a0e8a2d465f64f8a4643fb19f08f14b8..c428a0bf95e622056ffe4f97a978300f76b1871e 100644 (file)
 package org.argeo.cms;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.security.Privilege;
-import javax.jcr.version.VersionManager;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.auth.LoginRequiredException;
-import org.argeo.cms.internal.ImageManagerImpl;
-import org.argeo.cms.util.BundleResourceLoader;
-import org.argeo.cms.util.CmsUtils;
-import org.argeo.cms.util.SystemNotifications;
-import org.argeo.jcr.JcrUtils;
-import org.eclipse.gemini.blueprint.context.BundleContextAware;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.application.Application;
-import org.eclipse.rap.rwt.application.Application.OperationMode;
-import org.eclipse.rap.rwt.application.ApplicationConfiguration;
-import org.eclipse.rap.rwt.application.EntryPoint;
-import org.eclipse.rap.rwt.application.EntryPointFactory;
-import org.eclipse.rap.rwt.application.ExceptionHandler;
-import org.eclipse.rap.rwt.client.WebClient;
-import org.eclipse.rap.rwt.service.ResourceLoader;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.osgi.framework.BundleContext;
-
-/** Configures an Argeo CMS RWT application. */
-public class CmsApplication implements CmsConstants, ApplicationConfiguration,
-               BundleContextAware {
+import org.argeo.cms.util.SimpleApp;
+
+/**
+ * Configures an Argeo CMS RWT application.
+ * 
+ * @deprecated Use {@link SimpleApp} instead (same method signatures)
+ */
+@Deprecated
+public class CmsApplication extends SimpleApp {
        private final static Log log = LogFactory.getLog(CmsApplication.class);
 
-       private Map<String, Map<String, String>> branding = new HashMap<String, Map<String, String>>();
-       private Map<String, List<String>> styleSheets = new HashMap<String, List<String>>();
-
-       private List<String> resources = new ArrayList<String>();
-
-       private BundleContext bundleContext;
-
-       private Repository repository;
-       private String workspace = null;
-       private String basePath = "/";
-       private List<String> roPrincipals = Arrays.asList("anonymous", "everyone");
-       private List<String> rwPrincipals = Arrays.asList("everyone");
-
-       private CmsUiProvider header;
-       private Map<String, CmsUiProvider> pages = new LinkedHashMap<String, CmsUiProvider>();
-
-       private Integer headerHeight = 40;
-
-       // Managers
-       private CmsImageManager imageManager = new ImageManagerImpl();
-
-       public void configure(Application application) {
-               try {
-                       application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
-                       application.setExceptionHandler(new CmsExceptionHandler());
-
-                       // TODO load all pics under icons
-                       // loading animated gif
-                       application.addResource(LOADING_IMAGE,
-                                       createResourceLoader(LOADING_IMAGE));
-                       // empty image
-                       application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE));
-
-                       for (String resource : resources) {
-                               application.addResource(resource, new BundleResourceLoader(
-                                               bundleContext));
-                               if (log.isDebugEnabled())
-                                       log.debug("Registered resource " + resource);
-                       }
-
-                       Map<String, String> defaultBranding = null;
-                       if (branding.containsKey("*"))
-                               defaultBranding = branding.get("*");
-
-                       // entry points
-                       for (String page : pages.keySet()) {
-                               Map<String, String> properties = defaultBranding != null ? new HashMap<String, String>(
-                                               defaultBranding) : new HashMap<String, String>();
-                               if (branding.containsKey(page)) {
-                                       properties.putAll(branding.get(page));
-                               }
-                               // favicon
-                               if (properties.containsKey(WebClient.FAVICON)) {
-                                       String faviconRelPath = properties.get(WebClient.FAVICON);
-                                       application.addResource(faviconRelPath,
-                                                       new BundleResourceLoader(bundleContext));
-                                       if (log.isTraceEnabled())
-                                               log.trace("Registered favicon " + faviconRelPath);
-
-                               }
-
-                               // page title
-                               if (!properties.containsKey(WebClient.PAGE_TITLE))
-                                       properties.put(
-                                                       WebClient.PAGE_TITLE,
-                                                       Character.toUpperCase(page.charAt(0))
-                                                                       + page.substring(1));
-
-                               // default body HTML
-                               if (!properties.containsKey(WebClient.BODY_HTML))
-                                       properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY);
-
-                               //
-                               // ADD ENTRY POINT
-                               //
-                               application.addEntryPoint("/" + page, new CmsEntryPointFactory(
-                                               pages.get(page), repository, workspace, properties),
-                                               properties);
-                               log.info("Registered entry point /" + page);
-                       }
-
-                       // stylesheets
-                       for (String themeId : styleSheets.keySet()) {
-                               List<String> cssLst = styleSheets.get(themeId);
-                               for (String css : cssLst) {
-                                       application.addStyleSheet(themeId, css,
-                                                       new BundleResourceLoader(bundleContext));
-                               }
-
-                       }
-               } catch (RuntimeException e) {
-                       // Easier access to initialisation errors
-                       log.error("Unexpected exception when configuring RWT application.",
-                                       e);
-                       throw e;
-               }
-       }
-
-       public void init() throws RepositoryException {
-               Session session = null;
-               try {
-                       session = JcrUtils.loginOrCreateWorkspace(repository, workspace);
-                       VersionManager vm = session.getWorkspace().getVersionManager();
-                       if (!vm.isCheckedOut("/"))
-                               vm.checkout("/");
-                       JcrUtils.mkdirs(session, basePath);
-                       for (String principal : rwPrincipals)
-                               JcrUtils.addPrivilege(session, basePath, principal,
-                                               Privilege.JCR_WRITE);
-                       for (String principal : roPrincipals)
-                               JcrUtils.addPrivilege(session, basePath, principal,
-                                               Privilege.JCR_READ);
-
-                       for (String pageName : pages.keySet()) {
-                               try {
-                                       initPage(session, pages.get(pageName));
-                                       session.save();
-                               } catch (Exception e) {
-                                       throw new CmsException(
-                                                       "Cannot initialize page " + pageName, e);
-                               }
-                       }
-
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-       }
-
-       protected void initPage(Session adminSession, CmsUiProvider page)
-                       throws RepositoryException {
-               if (page instanceof LifeCycleUiProvider)
-                       ((LifeCycleUiProvider) page).init(adminSession);
-       }
-
-       public void destroy() {
-               for (String pageName : pages.keySet()) {
-                       try {
-                               CmsUiProvider page = pages.get(pageName);
-                               if (page instanceof LifeCycleUiProvider)
-                                       ((LifeCycleUiProvider) page).destroy();
-                       } catch (Exception e) {
-                               log.error("Cannot destroy page " + pageName, e);
-                       }
-               }
-       }
-
-       public void setRepository(Repository repository) {
-               this.repository = repository;
-       }
-
-       public void setWorkspace(String workspace) {
-               this.workspace = workspace;
-       }
-
-       public void setCmsLogin(@SuppressWarnings("deprecation") CmsLogin cmsLogin) {
-               // this.cmsLogin = cmsLogin;
-               log.warn("cmsLogin"
-                               + " is deprecated and will be removed soon. Adapt your configuration ASAP.");
-       }
-
-       public void setHeader(CmsUiProvider header) {
-               this.header = header;
-       }
-
-       public void setPages(Map<String, CmsUiProvider> pages) {
-               this.pages = pages;
-       }
-
-       public void setBasePath(String basePath) {
-               this.basePath = basePath;
-       }
-
-       public void setRoPrincipals(List<String> roPrincipals) {
-               this.roPrincipals = roPrincipals;
-       }
-
-       public void setRwPrincipals(List<String> rwPrincipals) {
-               this.rwPrincipals = rwPrincipals;
-       }
-
-       public void setHeaderHeight(Integer headerHeight) {
-               this.headerHeight = headerHeight;
-       }
-
-       public void setBranding(Map<String, Map<String, String>> branding) {
-               this.branding = branding;
-       }
-
-       public void setStyleSheets(Map<String, List<String>> styleSheets) {
-               this.styleSheets = styleSheets;
-       }
-
-       public void setBundleContext(BundleContext bundleContext) {
-               this.bundleContext = bundleContext;
-       }
-
-       public void setResources(List<String> resources) {
-               this.resources = resources;
-       }
-
-       class CmsExceptionHandler implements ExceptionHandler {
-
-               @Override
-               public void handleException(Throwable throwable) {
-                       CmsSession.current.get().exception(throwable);
-               }
-
-       }
-
-       private class CmsEntryPointFactory implements EntryPointFactory {
-               private final CmsUiProvider page;
-               private final Repository repository;
-               private final String workspace;
-               private final Map<String, String> properties;
-
-               public CmsEntryPointFactory(CmsUiProvider page, Repository repository,
-                               String workspace, Map<String, String> properties) {
-                       this.page = page;
-                       this.repository = repository;
-                       this.workspace = workspace;
-                       this.properties = properties;
-               }
-
-               @Override
-               public EntryPoint create() {
-                       CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace,
-                                       page, properties);
-                       entryPoint.setState("");
-                       CmsSession.current.set(entryPoint);
-                       return entryPoint;
-               }
-
-       }
-
-       private class CmsEntryPoint extends AbstractCmsEntryPoint {
-               private Composite headerArea;
-               private Composite bodyArea;
-               private final CmsUiProvider uiProvider;
-
-               public CmsEntryPoint(Repository repository, String workspace,
-                               CmsUiProvider uiProvider, Map<String, String> factoryProperties) {
-                       super(repository, workspace, factoryProperties);
-                       this.uiProvider = uiProvider;
-               }
-
-               @Override
-               protected void createContents(Composite parent) {
-                       try {
-                               getShell().getDisplay().setData(CmsSession.KEY, this);
-
-                               parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-                                               true));
-                               parent.setLayout(CmsUtils.noSpaceGridLayout());
-
-                               headerArea = new Composite(parent, SWT.NONE);
-                               headerArea.setLayout(new FillLayout());
-                               GridData headerData = new GridData(SWT.FILL, SWT.FILL, false,
-                                               false);
-                               headerData.heightHint = headerHeight;
-                               headerArea.setLayoutData(headerData);
-                               refreshHeader();
-
-                               bodyArea = new Composite(parent, SWT.NONE);
-                               bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY);
-                               bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-                                               true));
-                               // Should not be set here: it then prevent all children
-                               // composite to define a background color via CSS
-                               // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT);
-                               bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
-                               refreshBody();
-                       } catch (Exception e) {
-                               throw new CmsException("Cannot create entrypoint contents", e);
-                       }
-               }
-
-               @Override
-               protected void refreshHeader() {
-                       if (headerArea == null)
-                               return;
-                       for (Control child : headerArea.getChildren())
-                               child.dispose();
-                       try {
-                               header.createUi(headerArea, getNode());
-                       } catch (RepositoryException e) {
-                               throw new CmsException("Cannot refresh header", e);
-                       }
-                       headerArea.layout(true, true);
-               }
-
-               @Override
-               protected void refreshBody() {
-                       if (bodyArea == null)
-                               return;
-                       // Exception
-                       Throwable exception = getException();
-                       if (exception != null) {
-                               // new Label(bodyArea, SWT.NONE).setText("Unreachable state : "
-                               // + getState());
-                               // if (getNode() != null)
-                               // new Label(bodyArea, SWT.NONE).setText("Context : "
-                               // + getNode());
-                               //
-                               // Text errorText = new Text(bodyArea, SWT.MULTI | SWT.H_SCROLL
-                               // | SWT.V_SCROLL);
-                               // errorText.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
-                               // true,
-                               // true));
-                               // StringWriter sw = new StringWriter();
-                               // exception.printStackTrace(new PrintWriter(sw));
-                               // errorText.setText(sw.toString());
-                               // IOUtils.closeQuietly(sw);
-                               SystemNotifications systemNotifications = new SystemNotifications(
-                                               bodyArea);
-                               systemNotifications.notifyException(exception);
-                               resetException();
-                               return;
-                               // TODO report
-                       }
-
-                       // clear
-                       for (Control child : bodyArea.getChildren())
-                               child.dispose();
-                       bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
-
-                       String state = getState();
-                       try {
-                               if (state == null)
-                                       throw new CmsException("State cannot be null");
-                               uiProvider.createUi(bodyArea, getNode());
-                       } catch (RepositoryException e) {
-                               throw new CmsException("Cannot refresh body", e);
-                       }
-
-                       bodyArea.layout(true, true);
-               }
-
-               @Override
-               protected Node getDefaultNode(Session session)
-                               throws RepositoryException {
-                       if (!session.hasPermission(basePath, "read")) {
-                               if (session.getUserID().equals("anonymous"))
-                                       throw new LoginRequiredException();
-                               else
-                                       throw new CmsException("Unauthorized");
-                       }
-                       return session.getNode(basePath);
-               }
-
-               @Override
-               public CmsImageManager getImageManager() {
-                       return imageManager;
-               }
-
-       }
-
-       private static ResourceLoader createResourceLoader(final String resourceName) {
-               return new ResourceLoader() {
-                       public InputStream getResourceAsStream(String resourceName)
-                                       throws IOException {
-                               return getClass().getClassLoader().getResourceAsStream(
-                                               resourceName);
-                       }
-               };
+       public CmsApplication() {
+               super();
+               log.warn("org.argeo.cms.CmsApplication will be removed soon, use org.argeo.cms.util.SimpleApp");
        }
 
-       /*
-        * TEXTS
-        */
-       private static String DEFAULT_LOADING_BODY = "<div"
-                       + " style=\"position: absolute; left: 50%; top: 50%; margin: -32px -32px; width: 64px; height:64px\">"
-                       + "<img src=\"./rwt-resources/icons/loading.gif\" width=\"32\" height=\"32\" style=\"margin: 16px 16px\"/>"
-                       + "</div>";
+       //
+       // private Map<String, Map<String, String>> branding = new HashMap<String,
+       // Map<String, String>>();
+       // private Map<String, List<String>> styleSheets = new HashMap<String,
+       // List<String>>();
+       //
+       // private List<String> resources = new ArrayList<String>();
+       //
+       // private BundleContext bundleContext;
+       //
+       // private Repository repository;
+       // private String workspace = null;
+       // private String basePath = "/";
+       // private List<String> roPrincipals = Arrays.asList("anonymous",
+       // "everyone");
+       // private List<String> rwPrincipals = Arrays.asList("everyone");
+       //
+       // private CmsUiProvider header;
+       // private Map<String, CmsUiProvider> pages = new LinkedHashMap<String,
+       // CmsUiProvider>();
+       //
+       // private Integer headerHeight = 40;
+       //
+       // // Managers
+       // private CmsImageManager imageManager = new ImageManagerImpl();
+       //
+       // public void configure(Application application) {
+       // try {
+       // application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
+       // application.setExceptionHandler(new CmsExceptionHandler());
+       //
+       // // TODO load all pics under icons
+       // // loading animated gif
+       // application.addResource(LOADING_IMAGE,
+       // createResourceLoader(LOADING_IMAGE));
+       // // empty image
+       // application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE));
+       //
+       // for (String resource : resources) {
+       // application.addResource(resource, new BundleResourceLoader(
+       // bundleContext));
+       // if (log.isDebugEnabled())
+       // log.debug("Registered resource " + resource);
+       // }
+       //
+       // Map<String, String> defaultBranding = null;
+       // if (branding.containsKey("*"))
+       // defaultBranding = branding.get("*");
+       //
+       // // entry points
+       // for (String page : pages.keySet()) {
+       // Map<String, String> properties = defaultBranding != null ? new
+       // HashMap<String, String>(
+       // defaultBranding) : new HashMap<String, String>();
+       // if (branding.containsKey(page)) {
+       // properties.putAll(branding.get(page));
+       // }
+       // // favicon
+       // if (properties.containsKey(WebClient.FAVICON)) {
+       // String faviconRelPath = properties.get(WebClient.FAVICON);
+       // application.addResource(faviconRelPath,
+       // new BundleResourceLoader(bundleContext));
+       // if (log.isTraceEnabled())
+       // log.trace("Registered favicon " + faviconRelPath);
+       //
+       // }
+       //
+       // // page title
+       // if (!properties.containsKey(WebClient.PAGE_TITLE))
+       // properties.put(
+       // WebClient.PAGE_TITLE,
+       // Character.toUpperCase(page.charAt(0))
+       // + page.substring(1));
+       //
+       // // default body HTML
+       // if (!properties.containsKey(WebClient.BODY_HTML))
+       // properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY);
+       //
+       // //
+       // // ADD ENTRY POINT
+       // //
+       // application.addEntryPoint("/" + page, new CmsEntryPointFactory(
+       // pages.get(page), repository, workspace, properties),
+       // properties);
+       // log.info("Registered entry point /" + page);
+       // }
+       //
+       // // stylesheets
+       // for (String themeId : styleSheets.keySet()) {
+       // List<String> cssLst = styleSheets.get(themeId);
+       // for (String css : cssLst) {
+       // application.addStyleSheet(themeId, css,
+       // new BundleResourceLoader(bundleContext));
+       // }
+       //
+       // }
+       // } catch (RuntimeException e) {
+       // // Easier access to initialisation errors
+       // log.error("Unexpected exception when configuring RWT application.",
+       // e);
+       // throw e;
+       // }
+       // }
+       //
+       // public void init() throws RepositoryException {
+       // Session session = null;
+       // try {
+       // session = JcrUtils.loginOrCreateWorkspace(repository, workspace);
+       // VersionManager vm = session.getWorkspace().getVersionManager();
+       // if (!vm.isCheckedOut("/"))
+       // vm.checkout("/");
+       // JcrUtils.mkdirs(session, basePath);
+       // for (String principal : rwPrincipals)
+       // JcrUtils.addPrivilege(session, basePath, principal,
+       // Privilege.JCR_WRITE);
+       // for (String principal : roPrincipals)
+       // JcrUtils.addPrivilege(session, basePath, principal,
+       // Privilege.JCR_READ);
+       //
+       // for (String pageName : pages.keySet()) {
+       // try {
+       // initPage(session, pages.get(pageName));
+       // session.save();
+       // } catch (Exception e) {
+       // throw new CmsException(
+       // "Cannot initialize page " + pageName, e);
+       // }
+       // }
+       //
+       // } finally {
+       // JcrUtils.logoutQuietly(session);
+       // }
+       // }
+       //
+       // protected void initPage(Session adminSession, CmsUiProvider page)
+       // throws RepositoryException {
+       // if (page instanceof LifeCycleUiProvider)
+       // ((LifeCycleUiProvider) page).init(adminSession);
+       // }
+       //
+       // public void destroy() {
+       // for (String pageName : pages.keySet()) {
+       // try {
+       // CmsUiProvider page = pages.get(pageName);
+       // if (page instanceof LifeCycleUiProvider)
+       // ((LifeCycleUiProvider) page).destroy();
+       // } catch (Exception e) {
+       // log.error("Cannot destroy page " + pageName, e);
+       // }
+       // }
+       // }
+       //
+       // public void setRepository(Repository repository) {
+       // this.repository = repository;
+       // }
+       //
+       // public void setWorkspace(String workspace) {
+       // this.workspace = workspace;
+       // }
+       //
+       // public void setCmsLogin(@SuppressWarnings("deprecation") CmsLogin
+       // cmsLogin) {
+       // // this.cmsLogin = cmsLogin;
+       // log.warn("cmsLogin"
+       // +
+       // " is deprecated and will be removed soon. Adapt your configuration ASAP.");
+       // }
+       //
+       // public void setHeader(CmsUiProvider header) {
+       // this.header = header;
+       // }
+       //
+       // public void setPages(Map<String, CmsUiProvider> pages) {
+       // this.pages = pages;
+       // }
+       //
+       // public void setBasePath(String basePath) {
+       // this.basePath = basePath;
+       // }
+       //
+       // public void setRoPrincipals(List<String> roPrincipals) {
+       // this.roPrincipals = roPrincipals;
+       // }
+       //
+       // public void setRwPrincipals(List<String> rwPrincipals) {
+       // this.rwPrincipals = rwPrincipals;
+       // }
+       //
+       // public void setHeaderHeight(Integer headerHeight) {
+       // this.headerHeight = headerHeight;
+       // }
+       //
+       // public void setBranding(Map<String, Map<String, String>> branding) {
+       // this.branding = branding;
+       // }
+       //
+       // public void setStyleSheets(Map<String, List<String>> styleSheets) {
+       // this.styleSheets = styleSheets;
+       // }
+       //
+       // public void setBundleContext(BundleContext bundleContext) {
+       // this.bundleContext = bundleContext;
+       // }
+       //
+       // public void setResources(List<String> resources) {
+       // this.resources = resources;
+       // }
+       //
+       // class CmsExceptionHandler implements ExceptionHandler {
+       //
+       // @Override
+       // public void handleException(Throwable throwable) {
+       // CmsSession.current.get().exception(throwable);
+       // }
+       //
+       // }
+       //
+       // private class CmsEntryPointFactory implements EntryPointFactory {
+       // private final CmsUiProvider page;
+       // private final Repository repository;
+       // private final String workspace;
+       // private final Map<String, String> properties;
+       //
+       // public CmsEntryPointFactory(CmsUiProvider page, Repository repository,
+       // String workspace, Map<String, String> properties) {
+       // this.page = page;
+       // this.repository = repository;
+       // this.workspace = workspace;
+       // this.properties = properties;
+       // }
+       //
+       // @Override
+       // public EntryPoint create() {
+       // CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace,
+       // page, properties);
+       // entryPoint.setState("");
+       // CmsSession.current.set(entryPoint);
+       // return entryPoint;
+       // }
+       //
+       // }
+       //
+       // private class CmsEntryPoint extends AbstractCmsEntryPoint {
+       // private Composite headerArea;
+       // private Composite bodyArea;
+       // private final CmsUiProvider uiProvider;
+       //
+       // public CmsEntryPoint(Repository repository, String workspace,
+       // CmsUiProvider uiProvider, Map<String, String> factoryProperties) {
+       // super(repository, workspace, factoryProperties);
+       // this.uiProvider = uiProvider;
+       // }
+       //
+       // @Override
+       // protected void createContents(Composite parent) {
+       // try {
+       // getShell().getDisplay().setData(CmsSession.KEY, this);
+       //
+       // parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+       // true));
+       // parent.setLayout(CmsUtils.noSpaceGridLayout());
+       //
+       // headerArea = new Composite(parent, SWT.NONE);
+       // headerArea.setLayout(new FillLayout());
+       // GridData headerData = new GridData(SWT.FILL, SWT.FILL, false,
+       // false);
+       // headerData.heightHint = headerHeight;
+       // headerArea.setLayoutData(headerData);
+       // refreshHeader();
+       //
+       // bodyArea = new Composite(parent, SWT.NONE);
+       // bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY);
+       // bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+       // true));
+       // // Should not be set here: it then prevent all children
+       // // composite to define a background color via CSS
+       // // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT);
+       // bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
+       // refreshBody();
+       // } catch (Exception e) {
+       // throw new CmsException("Cannot create entrypoint contents", e);
+       // }
+       // }
+       //
+       // @Override
+       // protected void refreshHeader() {
+       // if (headerArea == null)
+       // return;
+       // for (Control child : headerArea.getChildren())
+       // child.dispose();
+       // try {
+       // header.createUi(headerArea, getNode());
+       // } catch (RepositoryException e) {
+       // throw new CmsException("Cannot refresh header", e);
+       // }
+       // headerArea.layout(true, true);
+       // }
+       //
+       // @Override
+       // protected void refreshBody() {
+       // if (bodyArea == null)
+       // return;
+       // // Exception
+       // Throwable exception = getException();
+       // if (exception != null) {
+       // // new Label(bodyArea, SWT.NONE).setText("Unreachable state : "
+       // // + getState());
+       // // if (getNode() != null)
+       // // new Label(bodyArea, SWT.NONE).setText("Context : "
+       // // + getNode());
+       // //
+       // // Text errorText = new Text(bodyArea, SWT.MULTI | SWT.H_SCROLL
+       // // | SWT.V_SCROLL);
+       // // errorText.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
+       // // true,
+       // // true));
+       // // StringWriter sw = new StringWriter();
+       // // exception.printStackTrace(new PrintWriter(sw));
+       // // errorText.setText(sw.toString());
+       // // IOUtils.closeQuietly(sw);
+       // SystemNotifications systemNotifications = new SystemNotifications(
+       // bodyArea);
+       // systemNotifications.notifyException(exception);
+       // resetException();
+       // return;
+       // // TODO report
+       // }
+       //
+       // // clear
+       // for (Control child : bodyArea.getChildren())
+       // child.dispose();
+       // bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
+       //
+       // String state = getState();
+       // try {
+       // if (state == null)
+       // throw new CmsException("State cannot be null");
+       // uiProvider.createUi(bodyArea, getNode());
+       // } catch (RepositoryException e) {
+       // throw new CmsException("Cannot refresh body", e);
+       // }
+       //
+       // bodyArea.layout(true, true);
+       // }
+       //
+       // @Override
+       // protected Node getDefaultNode(Session session)
+       // throws RepositoryException {
+       // if (!session.hasPermission(basePath, "read")) {
+       // if (session.getUserID().equals("anonymous"))
+       // throw new LoginRequiredException();
+       // else
+       // throw new CmsException("Unauthorized");
+       // }
+       // return session.getNode(basePath);
+       // }
+       //
+       // @Override
+       // public CmsImageManager getImageManager() {
+       // return imageManager;
+       // }
+       //
+       // }
+       //
+       // private static ResourceLoader createResourceLoader(final String
+       // resourceName) {
+       // return new ResourceLoader() {
+       // public InputStream getResourceAsStream(String resourceName)
+       // throws IOException {
+       // return getClass().getClassLoader().getResourceAsStream(
+       // resourceName);
+       // }
+       // };
+       // }
+       //
+       // /*
+       // * TEXTS
+       // */
+       // private static String DEFAULT_LOADING_BODY = "<div"
+       // +
+       // " style=\"position: absolute; left: 50%; top: 50%; margin: -32px -32px; width: 64px; height:64px\">"
+       // +
+       // "<img src=\"./rwt-resources/icons/loading.gif\" width=\"32\" height=\"32\" style=\"margin: 16px 16px\"/>"
+       // + "</div>";
 }
diff --git a/org.argeo.cms/src/org/argeo/cms/CmsLogin.java b/org.argeo.cms/src/org/argeo/cms/CmsLogin.java
deleted file mode 100644 (file)
index a9dd825..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.argeo.cms;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.auth.ArgeoLoginContext;
-import org.springframework.security.authentication.AuthenticationManager;
-
-/**
- * Gateway for user login, can also generate the related UI.
- * 
- * @deprecated Use {@link ArgeoLoginContext} instead
- */
-@Deprecated
-public class CmsLogin {
-       private final static Log log = LogFactory.getLog(CmsLogin.class);
-
-       public CmsLogin() {
-               log.warn("org.argeo.cms.CmsLogin is deprecated and will be removed soon.");
-       }
-
-       // private AuthenticationManager authenticationManager;
-       //
-       // public void logInAsAnonymous() {
-       // Subject subject = new Subject();
-       // final LoginContext loginContext;
-       // try {
-       // loginContext = new ArgeoLoginContext(
-       // KernelHeader.LOGIN_CONTEXT_ANONYMOUS, subject);
-       // loginContext.login();
-       // } catch (LoginException e1) {
-       // throw new ArgeoException("Cannot authenticate anonymous", e1);
-       // }
-       // }
-       //
-       // public void logInWithPassword(String username, char[] password) {
-       // NodeAuthenticationToken token = new NodeAuthenticationToken(username,
-       // password);
-       // Authentication authentication = authenticationManager
-       // .authenticate(token);
-       // SecurityContextHolder.getContext().setAuthentication(authentication);
-       // if (log.isDebugEnabled())
-       // log.debug("Authenticated as " + authentication);
-       // }
-       //
-       public void setAuthenticationManager(
-                       AuthenticationManager authenticationManager) {
-               // this.authenticationManager = authenticationManager;
-       }
-}
index 8ad15bf9c0d655355f8f76179f5fa31331f0f380..bb2bb3990f6937f946514505058d0edf686e53e2 100644 (file)
@@ -1,30 +1,17 @@
 package org.argeo.cms.util;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.CmsLogin;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.widgets.Control;
 
 /** Open the user menu when clicked */
-@SuppressWarnings("deprecation")
 public class OpenUserMenu extends MouseAdapter {
        private static final long serialVersionUID = 3634864186295639792L;
 
-       private final static Log log = LogFactory.getLog(OpenUserMenu.class);
-
-       // private CmsLogin cmsLogin;
-
        @Override
        public void mouseDown(MouseEvent e) {
                if (e.button == 1) {
                        new UserMenu((Control) e.getSource());
                }
        }
-
-       public void setCmsLogin(CmsLogin cmsLogin) {
-               log.warn("org.argeo.cms.CmsLogin is deprecated and will be removed soon");
-       }
-
 }
\ No newline at end of file
diff --git a/org.argeo.cms/src/org/argeo/cms/util/SimpleApp.java b/org.argeo.cms/src/org/argeo/cms/util/SimpleApp.java
new file mode 100644 (file)
index 0000000..be764e9
--- /dev/null
@@ -0,0 +1,295 @@
+package org.argeo.cms.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.Privilege;
+import javax.jcr.version.VersionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsConstants;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.CmsSession;
+import org.argeo.cms.CmsUiProvider;
+import org.argeo.cms.LifeCycleUiProvider;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.gemini.blueprint.context.BundleContextAware;
+import org.eclipse.rap.rwt.application.Application;
+import org.eclipse.rap.rwt.application.Application.OperationMode;
+import org.eclipse.rap.rwt.application.ApplicationConfiguration;
+import org.eclipse.rap.rwt.application.EntryPoint;
+import org.eclipse.rap.rwt.application.EntryPointFactory;
+import org.eclipse.rap.rwt.application.ExceptionHandler;
+import org.eclipse.rap.rwt.client.WebClient;
+import org.eclipse.rap.rwt.service.ResourceLoader;
+import org.osgi.framework.BundleContext;
+
+/** A basic generic app based on {@link SimpleErgonomics}. */
+public class SimpleApp implements CmsConstants, ApplicationConfiguration,
+               BundleContextAware {
+       private final static Log log = LogFactory.getLog(SimpleApp.class);
+
+       private Map<String, Map<String, String>> branding = new HashMap<String, Map<String, String>>();
+       private Map<String, List<String>> styleSheets = new HashMap<String, List<String>>();
+
+       private List<String> resources = new ArrayList<String>();
+
+       private BundleContext bundleContext;
+
+       private Repository repository;
+       private String workspace = null;
+       private String basePath = "/";
+       private List<String> roPrincipals = Arrays.asList("anonymous", "everyone");
+       private List<String> rwPrincipals = Arrays.asList("everyone");
+
+       private CmsUiProvider header;
+       private Map<String, CmsUiProvider> pages = new LinkedHashMap<String, CmsUiProvider>();
+
+       private Integer headerHeight = 40;
+
+       public void configure(Application application) {
+               try {
+                       application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
+                       application.setExceptionHandler(new CmsExceptionHandler());
+
+                       // loading animated gif
+                       application.addResource(LOADING_IMAGE,
+                                       createResourceLoader(LOADING_IMAGE));
+                       // empty image
+                       application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE));
+
+                       for (String resource : resources) {
+                               application.addResource(resource, new BundleResourceLoader(
+                                               bundleContext));
+                               if (log.isDebugEnabled())
+                                       log.debug("Registered resource " + resource);
+                       }
+
+                       Map<String, String> defaultBranding = null;
+                       if (branding.containsKey("*"))
+                               defaultBranding = branding.get("*");
+
+                       // entry points
+                       for (String page : pages.keySet()) {
+                               Map<String, String> properties = defaultBranding != null ? new HashMap<String, String>(
+                                               defaultBranding) : new HashMap<String, String>();
+                               if (branding.containsKey(page)) {
+                                       properties.putAll(branding.get(page));
+                               }
+                               // favicon
+                               if (properties.containsKey(WebClient.FAVICON)) {
+                                       String faviconRelPath = properties.get(WebClient.FAVICON);
+                                       application.addResource(faviconRelPath,
+                                                       new BundleResourceLoader(bundleContext));
+                                       if (log.isTraceEnabled())
+                                               log.trace("Registered favicon " + faviconRelPath);
+
+                               }
+
+                               // page title
+                               if (!properties.containsKey(WebClient.PAGE_TITLE))
+                                       properties.put(
+                                                       WebClient.PAGE_TITLE,
+                                                       Character.toUpperCase(page.charAt(0))
+                                                                       + page.substring(1));
+
+                               // default body HTML
+                               if (!properties.containsKey(WebClient.BODY_HTML))
+                                       properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY);
+
+                               //
+                               // ADD ENTRY POINT
+                               //
+                               application.addEntryPoint("/" + page, new CmsEntryPointFactory(
+                                               pages.get(page), repository, workspace, properties),
+                                               properties);
+                               log.info("Registered entry point /" + page);
+                       }
+
+                       // stylesheets
+                       for (String themeId : styleSheets.keySet()) {
+                               List<String> cssLst = styleSheets.get(themeId);
+                               for (String css : cssLst) {
+                                       application.addStyleSheet(themeId, css,
+                                                       new BundleResourceLoader(bundleContext));
+                               }
+
+                       }
+               } catch (RuntimeException e) {
+                       // Easier access to initialisation errors
+                       log.error("Unexpected exception when configuring RWT application.",
+                                       e);
+                       throw e;
+               }
+       }
+
+       public void init() throws RepositoryException {
+               Session session = null;
+               try {
+                       session = JcrUtils.loginOrCreateWorkspace(repository, workspace);
+                       VersionManager vm = session.getWorkspace().getVersionManager();
+                       if (!vm.isCheckedOut("/"))
+                               vm.checkout("/");
+                       JcrUtils.mkdirs(session, basePath);
+                       for (String principal : rwPrincipals)
+                               JcrUtils.addPrivilege(session, basePath, principal,
+                                               Privilege.JCR_WRITE);
+                       for (String principal : roPrincipals)
+                               JcrUtils.addPrivilege(session, basePath, principal,
+                                               Privilege.JCR_READ);
+
+                       for (String pageName : pages.keySet()) {
+                               try {
+                                       initPage(session, pages.get(pageName));
+                                       session.save();
+                               } catch (Exception e) {
+                                       throw new CmsException(
+                                                       "Cannot initialize page " + pageName, e);
+                               }
+                       }
+
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+       }
+
+       protected void initPage(Session adminSession, CmsUiProvider page)
+                       throws RepositoryException {
+               if (page instanceof LifeCycleUiProvider)
+                       ((LifeCycleUiProvider) page).init(adminSession);
+       }
+
+       public void destroy() {
+               for (String pageName : pages.keySet()) {
+                       try {
+                               CmsUiProvider page = pages.get(pageName);
+                               if (page instanceof LifeCycleUiProvider)
+                                       ((LifeCycleUiProvider) page).destroy();
+                       } catch (Exception e) {
+                               log.error("Cannot destroy page " + pageName, e);
+                       }
+               }
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+       public void setWorkspace(String workspace) {
+               this.workspace = workspace;
+       }
+
+       public void setHeader(CmsUiProvider header) {
+               this.header = header;
+       }
+
+       public void setPages(Map<String, CmsUiProvider> pages) {
+               this.pages = pages;
+       }
+
+       public void setBasePath(String basePath) {
+               this.basePath = basePath;
+       }
+
+       public void setRoPrincipals(List<String> roPrincipals) {
+               this.roPrincipals = roPrincipals;
+       }
+
+       public void setRwPrincipals(List<String> rwPrincipals) {
+               this.rwPrincipals = rwPrincipals;
+       }
+
+       public void setHeaderHeight(Integer headerHeight) {
+               this.headerHeight = headerHeight;
+       }
+
+       public void setBranding(Map<String, Map<String, String>> branding) {
+               this.branding = branding;
+       }
+
+       public void setStyleSheets(Map<String, List<String>> styleSheets) {
+               this.styleSheets = styleSheets;
+       }
+
+       public void setBundleContext(BundleContext bundleContext) {
+               this.bundleContext = bundleContext;
+       }
+
+       public void setResources(List<String> resources) {
+               this.resources = resources;
+       }
+
+       class CmsExceptionHandler implements ExceptionHandler {
+
+               @Override
+               public void handleException(Throwable throwable) {
+                       CmsSession.current.get().exception(throwable);
+               }
+
+       }
+
+       private class CmsEntryPointFactory implements EntryPointFactory {
+               private final CmsUiProvider page;
+               private final Repository repository;
+               private final String workspace;
+               private final Map<String, String> properties;
+
+               public CmsEntryPointFactory(CmsUiProvider page, Repository repository,
+                               String workspace, Map<String, String> properties) {
+                       this.page = page;
+                       this.repository = repository;
+                       this.workspace = workspace;
+                       this.properties = properties;
+               }
+
+               @Override
+               public EntryPoint create() {
+                       SimpleErgonomics entryPoint = new SimpleErgonomics(repository,
+                                       workspace, basePath, page, properties);
+                       // entryPoint.setState("");
+                       entryPoint.setHeader(header);
+                       entryPoint.setHeaderHeight(headerHeight);
+                       CmsSession.current.set(entryPoint);
+                       return entryPoint;
+               }
+
+       }
+
+       private static ResourceLoader createResourceLoader(final String resourceName) {
+               return new ResourceLoader() {
+                       public InputStream getResourceAsStream(String resourceName)
+                                       throws IOException {
+                               return getClass().getClassLoader().getResourceAsStream(
+                                               resourceName);
+                       }
+               };
+       }
+
+       // private static ResourceLoader createUrlResourceLoader(final URL url) {
+       // return new ResourceLoader() {
+       // public InputStream getResourceAsStream(String resourceName)
+       // throws IOException {
+       // return url.openStream();
+       // }
+       // };
+       // }
+
+       /*
+        * TEXTS
+        */
+       private static String DEFAULT_LOADING_BODY = "<div"
+                       + " style=\"position: absolute; left: 50%; top: 50%; margin: -32px -32px; width: 64px; height:64px\">"
+                       + "<img src=\"./rwt-resources/" + LOADING_IMAGE
+                       + "\" width=\"32\" height=\"32\" style=\"margin: 16px 16px\"/>"
+                       + "</div>";
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/util/SimpleErgonomics.java b/org.argeo.cms/src/org/argeo/cms/util/SimpleErgonomics.java
new file mode 100644 (file)
index 0000000..4b871cb
--- /dev/null
@@ -0,0 +1,125 @@
+package org.argeo.cms.util;
+
+import java.util.Map;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.AbstractCmsEntryPoint;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.CmsImageManager;
+import org.argeo.cms.CmsStyles;
+import org.argeo.cms.CmsUiProvider;
+import org.argeo.cms.internal.ImageManagerImpl;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/** Simple header/body ergonomics. */
+public class SimpleErgonomics extends AbstractCmsEntryPoint {
+       private Composite headerArea;
+       private Composite bodyArea;
+       private final CmsUiProvider uiProvider;
+
+       private CmsUiProvider header;
+       private Integer headerHeight = 40;
+
+       private CmsImageManager imageManager = new ImageManagerImpl();
+
+       public SimpleErgonomics(Repository repository, String workspace,
+                       String defaultPath, CmsUiProvider uiProvider,
+                       Map<String, String> factoryProperties) {
+               super(repository, workspace, defaultPath, factoryProperties);
+               this.uiProvider = uiProvider;
+       }
+
+       @Override
+       protected void createUi(Composite parent) {
+               parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               parent.setLayout(CmsUtils.noSpaceGridLayout());
+
+               headerArea = new Composite(parent, SWT.NONE);
+               headerArea.setLayout(new FillLayout());
+               GridData headerData = new GridData(SWT.FILL, SWT.FILL, false, false);
+               headerData.heightHint = headerHeight;
+               headerArea.setLayoutData(headerData);
+
+               bodyArea = new Composite(parent, SWT.NONE);
+               bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY);
+               bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
+
+               refresh();
+       }
+
+       @Override
+       protected void refresh() {
+               refreshHeader();
+               refreshBody();
+       }
+
+       protected void refreshHeader() {
+               if (headerArea == null)
+                       return;
+               for (Control child : headerArea.getChildren())
+                       child.dispose();
+               try {
+                       header.createUi(headerArea, getNode());
+               } catch (RepositoryException e) {
+                       throw new CmsException("Cannot refresh header", e);
+               }
+               headerArea.layout(true, true);
+       }
+
+       protected void refreshBody() {
+               if (bodyArea == null)
+                       return;
+               // Exception
+               Throwable exception = getException();
+               if (exception != null) {
+                       SystemNotifications systemNotifications = new SystemNotifications(
+                                       bodyArea);
+                       systemNotifications.notifyException(exception);
+                       resetException();
+                       return;
+                       // TODO report
+               }
+
+               // clear
+               for (Control child : bodyArea.getChildren())
+                       child.dispose();
+               bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
+
+               String state = getState();
+               try {
+                       if (state == null)
+                               setState("");
+                       // throw new CmsException("State cannot be null");
+                       uiProvider.createUi(bodyArea, getNode());
+               } catch (RepositoryException e) {
+                       throw new CmsException("Cannot refresh body", e);
+               }
+
+               bodyArea.layout(true, true);
+       }
+
+       @Override
+       public CmsImageManager getImageManager() {
+               return imageManager;
+       }
+
+       public void setHeader(CmsUiProvider header) {
+               this.header = header;
+       }
+
+       public void setHeaderHeight(Integer headerHeight) {
+               this.headerHeight = headerHeight;
+       }
+
+       public void setImageManager(CmsImageManager imageManager) {
+               this.imageManager = imageManager;
+       }
+}