X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=swt%2Frcp%2Forg.argeo.cms.swt.rcp%2Fsrc%2Forg%2Fargeo%2Fcms%2Fui%2Frcp%2FCmsRcpApp.java;fp=swt%2Frcp%2Forg.argeo.cms.swt.rcp%2Fsrc%2Forg%2Fargeo%2Fcms%2Fui%2Frcp%2FCmsRcpApp.java;h=e25a9f71149b66d0aaf2168e4f0fe31e936e8e92;hb=7b242851c0094d13cbaca5b68261ad92c873a59f;hp=0000000000000000000000000000000000000000;hpb=dbb84b4ec2d313ec0724d035c32f482ac57974c5;p=lgpl%2Fargeo-commons.git diff --git a/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java b/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java new file mode 100644 index 000000000..e25a9f711 --- /dev/null +++ b/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java @@ -0,0 +1,230 @@ +package org.argeo.cms.ui.rcp; + +import java.io.IOException; +import java.io.InputStream; +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.argeo.api.cms.CmsApp; +import org.argeo.api.cms.CmsAuth; +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsSession; +import org.argeo.api.cms.ux.CmsImageManager; +import org.argeo.api.cms.ux.CmsTheme; +import org.argeo.api.cms.ux.CmsUi; +import org.argeo.api.cms.ux.CmsView; +import org.argeo.api.cms.ux.UxContext; +import org.argeo.cms.swt.CmsSwtUtils; +import org.eclipse.e4.ui.css.core.engine.CSSEngine; +import org.eclipse.e4.ui.css.core.engine.CSSErrorHandler; +import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; + +/** Runs a {@link CmsApp} as an SWT desktop application. */ +@SuppressWarnings("restriction") +public class CmsRcpApp implements CmsView { + private final static CmsLog log = CmsLog.getLog(CmsRcpApp.class); + + // private BundleContext bundleContext = + // FrameworkUtil.getBundle(CmsRcpApp.class).getBundleContext(); + + private Shell shell; + private CmsApp cmsApp; + + // CMS View + private String uid; + private LoginContext loginContext; + + private EventAdmin eventAdmin; + + private CSSEngine cssEngine; + + private CmsUi ui; + // TODO make it configurable + private String uiName = "desktop"; + + public CmsRcpApp(String uiName) { + uid = UUID.randomUUID().toString(); + this.uiName = uiName; + } + + public void initRcpApp() { + Display display = Display.getCurrent(); + shell = new Shell(display); + shell.setText("Argeo CMS"); + Composite parent = shell; + parent.setLayout(CmsSwtUtils.noSpaceGridLayout()); + CmsSwtUtils.registerCmsView(shell, CmsRcpApp.this); + + try { + loginContext = new LoginContext(CmsAuth.SINGLE_USER.getLoginContextName()); + loginContext.login(); + } catch (LoginException e) { + throw new IllegalStateException("Could not log in.", e); + } + if (log.isDebugEnabled()) + log.debug("Logged in to desktop: " + loginContext.getSubject()); + + Subject.doAs(loginContext.getSubject(), (PrivilegedAction) () -> { + + // TODO factorise with web app + parent.setData(CmsApp.UI_NAME_PROPERTY, uiName); + ui = cmsApp.initUi(parent); + if (ui instanceof Composite) + ((Composite) ui).setLayoutData(CmsSwtUtils.fillAll()); + // we need ui to be set before refresh so that CmsView can store UI context data + // in it. + cmsApp.refreshUi(ui, null); + + // Styling + CmsTheme theme = CmsSwtUtils.getCmsTheme(parent); + if (theme != null) { + cssEngine = new CSSSWTEngineImpl(display); + for (String path : theme.getSwtCssPaths()) { + try (InputStream in = theme.loadPath(path)) { + cssEngine.parseStyleSheet(in); + } catch (IOException e) { + throw new IllegalStateException("Cannot load stylesheet " + path, e); + } + } + cssEngine.setErrorHandler(new CSSErrorHandler() { + public void error(Exception e) { + log.error("SWT styling error: ", e); + } + }); + applyStyles(shell); + } + shell.layout(true, true); + + shell.open(); + return null; + }); + } + + /* + * CMS VIEW + */ + + @Override + public String getUid() { + return uid; + } + + @Override + public UxContext getUxContext() { + throw new UnsupportedOperationException(); + } + + @Override + public void navigateTo(String state) { + throw new UnsupportedOperationException(); + } + + @Override + public void authChange(LoginContext loginContext) { + } + + @Override + public void logout() { + if (loginContext != null) + try { + loginContext.logout(); + } catch (LoginException e) { + log.error("Cannot log out", e); + } + } + + @Override + public void exception(Throwable e) { + log.error("Unexpected exception in CMS RCP", e); + } + + @Override + public CmsImageManager getImageManager() { + throw new UnsupportedOperationException(); + } + + @Override + public CmsSession getCmsSession() { + CmsSession cmsSession = cmsApp.getCmsContext().getCmsSession(getSubject()); + return cmsSession; + } + + @Override + public Object getData(String key) { + if (ui != null) { + return ui.getData(key); + } else { + throw new IllegalStateException("UI is not initialized"); + } + } + + @Override + public void setData(String key, Object value) { + if (ui != null) { + ui.setData(key, value); + } else { + throw new IllegalStateException("UI is not initialized"); + } + } + + @Override + public boolean isAnonymous() { + return false; + } + + @Override + public void applyStyles(Object node) { + if (cssEngine != null) + cssEngine.applyStyles(node, true); + } + + @Override + public void sendEvent(String topic, Map properties) { + if (properties == null) + properties = new HashMap<>(); + if (properties.containsKey(CMS_VIEW_UID_PROPERTY) && !properties.get(CMS_VIEW_UID_PROPERTY).equals(uid)) + throw new IllegalArgumentException("Property " + CMS_VIEW_UID_PROPERTY + " is set to another CMS view uid (" + + properties.get(CMS_VIEW_UID_PROPERTY) + ") then " + uid); + properties.put(CMS_VIEW_UID_PROPERTY, uid); + eventAdmin.sendEvent(new Event(topic, properties)); + } + + public T doAs(PrivilegedAction action) { + return Subject.doAs(getSubject(), action); + } + + protected Subject getSubject() { + return loginContext.getSubject(); + } + + public Shell getShell() { + return shell; + } + + /* + * DEPENDENCY INJECTION + */ + public void setCmsApp(CmsApp cmsApp, Map properties) { + this.cmsApp = cmsApp; + } + + public void unsetCmsApp(CmsApp cmsApp, Map properties) { + this.cmsApp = null; + } + + public void setEventAdmin(EventAdmin eventAdmin) { + this.eventAdmin = eventAdmin; + } + +}