javax.jcr.security,\
com.fasterxml.jackson.core,\
org.apache.jackrabbit.*;version="[1,4)",\
+org.argeo.cms.acr,\
*
Require-Capability:\
--- /dev/null
+package org.argeo.app.swt.ux;
+
+import java.util.Map;
+
+import org.argeo.api.acr.Content;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.SwtUiProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.osgi.framework.BundleContext;
+
+/** Footer of a standard Argeo Suite application. */
+public class DefaultFooter implements SwtUiProvider {
+ @Override
+ public Control createUiPart(Composite parent, Content context) {
+ parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
+ Composite content = new Composite(parent, SWT.NONE);
+ content.setLayoutData(new GridData(0, 0));
+ Control contentControl = createContent(content, context);
+
+ // TODO support and guarantee
+
+ return contentControl;
+ }
+
+ protected Control createContent(Composite parent, Content context) {
+ return parent;
+ }
+
+ public void init(BundleContext bundleContext, Map<String, String> properties) {
+ }
+
+ public void destroy(BundleContext bundleContext, Map<String, String> properties) {
+
+ }
+}
--- /dev/null
+package org.argeo.app.swt.ux;
+
+import java.util.Map;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.app.ux.SuiteIcon;
+import org.argeo.app.ux.SuiteStyle;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.Localized;
+import org.argeo.cms.swt.CmsSwtTheme;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.SwtUiProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleWiring;
+
+/** Header of a standard Argeo Suite application. */
+public class DefaultHeader implements SwtUiProvider {
+ public final static String TITLE_PROPERTY = "argeo.suite.ui.header.title";
+ private Localized title = null;
+
+ @Override
+ public Control createUiPart(Composite parent, Content context) {
+ CmsView cmsView = CmsSwtUtils.getCmsView(parent);
+ CmsSwtTheme theme = CmsSwtUtils.getCmsTheme(parent);
+
+ parent.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(3, true)));
+
+ // TODO right to left
+ Composite lead = new Composite(parent, SWT.NONE);
+ CmsSwtUtils.style(lead, SuiteStyle.header);
+ lead.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, false));
+ lead.setLayout(new GridLayout());
+ Label lbl = new Label(lead, SWT.NONE);
+// String title = properties.get(TITLE_PROPERTY);
+// // TODO expose the localized
+// lbl.setText(LocaleUtils.isLocaleKey(title) ? LocaleUtils.local(title, getClass().getClassLoader()).toString()
+// : title);
+ lbl.setText(title.lead());
+ CmsSwtUtils.style(lbl, SuiteStyle.headerTitle);
+ lbl.setLayoutData(CmsSwtUtils.fillWidth());
+
+ Composite middle = new Composite(parent, SWT.NONE);
+ CmsSwtUtils.style(middle, SuiteStyle.header);
+ middle.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false));
+ middle.setLayout(new GridLayout());
+
+ Composite end = new Composite(parent, SWT.NONE);
+ CmsSwtUtils.style(end, SuiteStyle.header);
+ end.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false));
+
+ if (!cmsView.isAnonymous()) {
+ end.setLayout(new GridLayout(2, false));
+ Label userL = new Label(end, SWT.NONE);
+ CmsSwtUtils.style(userL, SuiteStyle.header);
+ userL.setText(CurrentUser.getDisplayName());
+// Button logoutB = new Button(end, SWT.FLAT);
+// logoutB.setImage(theme.getSmallIcon(SuiteIcon.logout));
+// logoutB.addSelectionListener(new SelectionAdapter() {
+// private static final long serialVersionUID = 7116760083964201233L;
+//
+// @Override
+// public void widgetSelected(SelectionEvent e) {
+// cmsView.logout();
+// }
+//
+// });
+ Label logOutL = new Label(end, 0);
+ logOutL.setImage(theme.getSmallIcon(SuiteIcon.openUserMenu));
+ logOutL.addMouseListener(new MouseAdapter() {
+ private static final long serialVersionUID = 6908266850511460799L;
+
+ @Override
+ public void mouseDown(MouseEvent e) {
+ cmsView.logout();
+ }
+
+ });
+ } else {
+ end.setLayout(new GridLayout(1, false));
+ // required in order to avoid wrong height after logout
+ new Label(end, SWT.NONE).setText("");
+
+ }
+ return lbl;
+ }
+
+ public void init(BundleContext bundleContext, Map<String, String> properties) {
+ String titleStr = (String) properties.get(TITLE_PROPERTY);
+ if (titleStr != null) {
+ if (titleStr.startsWith("%")) {
+ title = new Localized() {
+
+ @Override
+ public String name() {
+ return titleStr;
+ }
+
+ @Override
+ public ClassLoader getL10nClassLoader() {
+ return bundleContext != null
+ ? bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader()
+ : getClass().getClassLoader();
+ }
+ };
+ } else {
+ title = new Localized.Untranslated(titleStr);
+ }
+ }
+ }
+
+ public void destroy(BundleContext bundleContext, Map<String, String> properties) {
+
+ }
+
+ public Localized getTitle() {
+ return title;
+ }
+
+}
--- /dev/null
+package org.argeo.app.swt.ux;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.ux.CmsIcon;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.app.api.RankedObject;
+import org.argeo.app.core.SuiteUtils;
+import org.argeo.app.ux.SuiteIcon;
+import org.argeo.app.ux.SuiteStyle;
+import org.argeo.app.ux.SuiteUxEvent;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.LocaleUtils;
+import org.argeo.cms.Localized;
+import org.argeo.cms.swt.CmsSwtTheme;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.SwtUiProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleWiring;
+
+/** Side pane listing various perspectives. */
+public class DefaultLeadPane implements SwtUiProvider {
+ private final static CmsLog log = CmsLog.getLog(DefaultLeadPane.class);
+
+ public static enum Property {
+ defaultLayers, adminLayers;
+ }
+
+ private Map<String, RankedObject<SwtAppLayer>> layers = Collections.synchronizedSortedMap(new TreeMap<>());
+ private List<String> defaultLayers;
+ private List<String> adminLayers = new ArrayList<>();
+
+ private ClassLoader l10nClassLoader;
+
+ @Override
+ public Control createUiPart(Composite parent, Content node) {
+ CmsView cmsView = CmsSwtUtils.getCmsView(parent);
+ parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
+ Composite appLayersC = new Composite(parent, SWT.NONE);
+ CmsSwtUtils.style(appLayersC, SuiteStyle.leadPane);
+ GridLayout layout = new GridLayout();
+ layout.verticalSpacing = 10;
+ layout.marginTop = 10;
+ layout.marginLeft = 10;
+ layout.marginRight = 10;
+ appLayersC.setLayout(layout);
+ appLayersC.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+
+ Composite adminLayersC;
+ if (!adminLayers.isEmpty()) {
+ adminLayersC = new Composite(parent, SWT.NONE);
+ CmsSwtUtils.style(adminLayersC, SuiteStyle.leadPane);
+ GridLayout adminLayout = new GridLayout();
+ adminLayout.verticalSpacing = 10;
+ adminLayout.marginBottom = 10;
+ adminLayout.marginLeft = 10;
+ adminLayout.marginRight = 10;
+ adminLayersC.setLayout(adminLayout);
+ adminLayersC.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, false, true));
+ } else {
+ adminLayersC = null;
+ }
+
+// boolean isAdmin = cmsView.doAs(() -> CurrentUser.isInRole(NodeConstants.ROLE_USER_ADMIN));
+ // Set<String> userRoles = cmsView.doAs(() -> CurrentUser.roles());
+ Button first = null;
+ layers: for (String layerDef : defaultLayers) {
+ layerDef = layerDef.trim();
+ if ("".equals(layerDef))
+ continue layers;// skip empty lines
+ String[] semiColArr = layerDef.split(";");
+ String layerId = semiColArr[0];
+ Set<String> layerRoles = SuiteUtils.extractRoles(semiColArr);
+ if (layers.containsKey(layerId)) {
+ if (!layerRoles.isEmpty()) {
+ boolean authorized = false;
+ authorized = cmsView.doAs(() -> {
+ for (String layerRole : layerRoles) {
+ if (CurrentUser.implies(layerRole, null)) {
+ return true;
+ }
+ }
+ return false;
+ });
+ if (!authorized)
+ continue layers;// skip unauthorized layer
+// Set<String> intersection = new HashSet<String>(layerRoles);
+// intersection.retainAll(userRoles);
+// if (intersection.isEmpty())
+// continue layers;// skip unauthorized layer
+ }
+ RankedObject<SwtAppLayer> layerObj = layers.get(layerId);
+
+ Localized title = null;
+ if (!adminLayers.contains(layerId)) {
+ String titleStr = (String) layerObj.getProperties().get(SwtAppLayer.Property.title.name());
+ if (titleStr != null) {
+ if (titleStr.startsWith("%")) {
+ // LocaleUtils.local(titleStr, getClass().getClassLoader());
+ title = () -> titleStr;
+ } else {
+ title = new Localized.Untranslated(titleStr);
+ }
+ }
+ }
+
+ String iconName = (String) layerObj.getProperties().get(SwtAppLayer.Property.icon.name());
+ SuiteIcon icon = null;
+ if (iconName != null)
+ icon = SuiteIcon.valueOf(iconName);
+
+ Composite buttonParent;
+ if (adminLayers.contains(layerId))
+ buttonParent = adminLayersC;
+ else
+ buttonParent = appLayersC;
+ Button b = createLayerButton(buttonParent, layerId, title, icon, l10nClassLoader);
+ if (first == null)
+ first = b;
+ }
+ }
+ return first;
+ }
+
+ protected Button createLayerButton(Composite parent, String layer, Localized msg, CmsIcon icon,
+ ClassLoader l10nClassLoader) {
+ CmsSwtTheme theme = CmsSwtUtils.getCmsTheme(parent);
+ Button button = new Button(parent, SWT.PUSH);
+ CmsSwtUtils.style(button, SuiteStyle.leadPane);
+ if (icon != null)
+ button.setImage(theme.getBigIcon(icon));
+ button.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, false));
+ // button.setToolTipText(msg.lead());
+ if (msg != null) {
+ Label lbl = new Label(parent, SWT.CENTER);
+ CmsSwtUtils.style(lbl, SuiteStyle.leadPane);
+ String txt = LocaleUtils.lead(msg, l10nClassLoader);
+// String txt = msg.lead();
+ lbl.setText(txt);
+ lbl.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
+ }
+ CmsSwtUtils.sendEventOnSelect(button, SuiteUxEvent.switchLayer.topic(), SuiteUxEvent.LAYER, layer);
+ return button;
+ }
+
+ public void init(BundleContext bundleContext, Map<String, Object> properties) {
+ l10nClassLoader = bundleContext != null ? bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader()
+ : getClass().getClassLoader();
+
+ String[] defaultLayers = (String[]) properties.get(Property.defaultLayers.toString());
+ if (defaultLayers == null)
+ throw new IllegalArgumentException("Default layers must be set.");
+ this.defaultLayers = Arrays.asList(defaultLayers);
+ if (log.isDebugEnabled())
+ log.debug("Default layers: " + Arrays.asList(defaultLayers));
+ String[] adminLayers = (String[]) properties.get(Property.adminLayers.toString());
+ if (adminLayers != null) {
+ this.adminLayers = Arrays.asList(adminLayers);
+ if (log.isDebugEnabled())
+ log.debug("Admin layers: " + Arrays.asList(adminLayers));
+ }
+ }
+
+ public void destroy(BundleContext bundleContext, Map<String, String> properties) {
+
+ }
+
+ public void addLayer(SwtAppLayer layer, Map<String, Object> properties) {
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String pid = (String) properties.get(Constants.SERVICE_PID);
+ RankedObject.putIfHigherRank(layers, pid, layer, properties);
+ }
+ }
+
+ public void removeLayer(SwtAppLayer layer, Map<String, Object> properties) {
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String pid = (String) properties.get(Constants.SERVICE_PID);
+ if (layers.containsKey(pid)) {
+ if (layers.get(pid).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
+ layers.remove(pid);
+ }
+ }
+ }
+ }
+
+// protected Button createLayerButton(Composite parent, String layer, Localized msg, CmsIcon icon) {
+// CmsTheme theme = CmsTheme.getCmsTheme(parent);
+// Button button = new Button(parent, SWT.PUSH);
+// CmsUiUtils.style(button, SuiteStyle.leadPane);
+// if (icon != null)
+// button.setImage(icon.getBigIcon(theme));
+// button.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, false));
+// // button.setToolTipText(msg.lead());
+// if (msg != null) {
+// Label lbl = new Label(parent, SWT.CENTER);
+// CmsUiUtils.style(lbl, SuiteStyle.leadPane);
+// // CmsUiUtils.markup(lbl);
+// ClassLoader l10nClassLoader = getClass().getClassLoader();
+// String txt = LocaleUtils.lead(msg, l10nClassLoader);
+//// String txt = msg.lead();
+// lbl.setText(txt);
+// lbl.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
+// }
+// CmsUiUtils.sendEventOnSelect(button, SuiteEvent.switchLayer.topic(), SuiteEvent.LAYER, layer);
+// return button;
+// }
+}
--- /dev/null
+package org.argeo.app.swt.ux;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.cms.CmsContext;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.SwtUiProvider;
+import org.argeo.cms.swt.auth.CmsLogin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/** Provides a login screen. */
+public class DefaultLoginScreen implements SwtUiProvider {
+ private CmsContext cmsContext;
+
+ @Override
+ public Control createUiPart(Composite parent, Content context) {
+ CmsView cmsView = CmsSwtUtils.getCmsView(parent);
+ if (!cmsView.isAnonymous())
+ throw new IllegalStateException(CurrentUser.getUsername() + " is already logged in");
+
+ parent.setLayout(new GridLayout());
+ Composite loginArea = new Composite(parent, SWT.NONE);
+ loginArea.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
+
+ CmsLogin cmsLogin = new CmsLogin(cmsView, cmsContext);
+ cmsLogin.createUi(loginArea);
+ return cmsLogin.getCredentialsBlock();
+ }
+
+ public void setCmsContext(CmsContext cmsContext) {
+ this.cmsContext = cmsContext;
+ }
+
+}
--- /dev/null
+package org.argeo.app.swt.ux;
+
+import static org.argeo.api.cms.ux.CmsView.CMS_VIEW_UID_PROPERTY;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.ContentRepository;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.api.cms.CmsConstants;
+import org.argeo.api.cms.CmsEvent;
+import org.argeo.api.cms.CmsEventSubscriber;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.ux.CmsTheme;
+import org.argeo.api.cms.ux.CmsUi;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.app.api.AppUserState;
+import org.argeo.app.api.EntityConstants;
+import org.argeo.app.api.EntityName;
+import org.argeo.app.api.EntityType;
+import org.argeo.app.api.RankedObject;
+import org.argeo.app.ux.AbstractArgeoApp;
+import org.argeo.app.ux.AppUi;
+import org.argeo.app.ux.SuiteUxEvent;
+import org.argeo.cms.LocaleUtils;
+import org.argeo.cms.Localized;
+import org.argeo.cms.acr.ContentUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.SwtUiProvider;
+import org.argeo.cms.swt.dialogs.CmsFeedback;
+import org.argeo.cms.util.LangUtils;
+import org.argeo.cms.ux.CmsUxUtils;
+import org.argeo.eclipse.ui.specific.UiContext;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.osgi.framework.Constants;
+
+/** The Argeo Suite App. */
+public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber {
+ private final static CmsLog log = CmsLog.getLog(SwtArgeoApp.class);
+
+ public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath";
+ public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName";
+ public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId";
+ public final static String DEFAULT_LAYER_PROPERTY = "defaultLayer";
+ private final static String LOGIN = "login";
+ private final static String HOME_STATE = "~";
+
+ private String publicBasePath = null;
+
+ private String pidPrefix;
+ private String headerPid;
+ private String footerPid;
+ private String leadPanePid;
+ private String adminLeadPanePid;
+ private String loginScreenPid;
+
+ private String defaultUiName = "app";
+ private String adminUiName = "admin";
+
+ // FIXME such default names make refactoring more dangerous
+ @Deprecated
+ private String defaultLayerPid = "argeo.suite.ui.dashboardLayer";
+ @Deprecated
+ private String defaultThemeId = "org.argeo.app.theme.default";
+
+ // TODO use QName as key for byType
+ private Map<String, RankedObject<SwtUiProvider>> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>());
+ private Map<String, RankedObject<SwtUiProvider>> uiProvidersByType = Collections.synchronizedMap(new HashMap<>());
+ private Map<String, RankedObject<SwtAppLayer>> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>());
+ private Map<String, RankedObject<SwtAppLayer>> layersByType = Collections.synchronizedSortedMap(new TreeMap<>());
+
+// private CmsUserManager cmsUserManager;
+
+ // TODO make more optimal or via CmsSession/CmsView
+ private Map<String, SwtAppUi> managedUis = new HashMap<>();
+
+ // ACR
+ private ContentRepository contentRepository;
+ private AppUserState appUserState;
+ // JCR
+// private Repository repository;
+
+ public void init(Map<String, Object> properties) {
+ for (SuiteUxEvent event : SuiteUxEvent.values()) {
+ getCmsContext().getCmsEventBus().addEventSubscriber(event.topic(), this);
+ }
+
+ if (log.isDebugEnabled())
+ log.info("Argeo Suite App started");
+
+ if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY))
+ defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY);
+ if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY))
+ defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY);
+ if (properties.containsKey(DEFAULT_LAYER_PROPERTY))
+ defaultLayerPid = LangUtils.get(properties, DEFAULT_LAYER_PROPERTY);
+ publicBasePath = LangUtils.get(properties, PUBLIC_BASE_PATH_PROPERTY);
+
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String servicePid = properties.get(Constants.SERVICE_PID).toString();
+ if (servicePid.endsWith(".app")) {
+ pidPrefix = servicePid.substring(0, servicePid.length() - "app".length());
+ }
+ }
+
+ if (pidPrefix == null)
+ throw new IllegalArgumentException("PID prefix must be set.");
+
+ headerPid = pidPrefix + "header";
+ footerPid = pidPrefix + "footer";
+ leadPanePid = pidPrefix + "leadPane";
+ adminLeadPanePid = pidPrefix + "adminLeadPane";
+ loginScreenPid = pidPrefix + "loginScreen";
+ }
+
+ public void destroy(Map<String, Object> properties) {
+ for (SwtAppUi ui : managedUis.values())
+ if (!ui.isDisposed()) {
+ ui.getDisplay().syncExec(() -> ui.dispose());
+ }
+ if (log.isDebugEnabled())
+ log.info("Argeo Suite App stopped");
+
+ }
+
+ @Override
+ public Set<String> getUiNames() {
+ HashSet<String> uiNames = new HashSet<>();
+ uiNames.add(defaultUiName);
+ uiNames.add(adminUiName);
+ return uiNames;
+ }
+
+ @Override
+ public CmsUi initUi(Object parent) {
+ Composite uiParent = (Composite) parent;
+ String uiName = uiParent.getData(UI_NAME_PROPERTY) != null ? uiParent.getData(UI_NAME_PROPERTY).toString()
+ : null;
+ CmsView cmsView = CmsSwtUtils.getCmsView(uiParent);
+ if (cmsView == null)
+ throw new IllegalStateException("No CMS view is registered.");
+ CmsTheme theme = getTheme(uiName);
+ if (theme != null)
+ CmsSwtUtils.registerCmsTheme(uiParent.getShell(), theme);
+ SwtAppUi argeoSuiteUi = new SwtAppUi(uiParent, SWT.INHERIT_DEFAULT);
+ String uid = cmsView.getUid();
+ managedUis.put(uid, argeoSuiteUi);
+ argeoSuiteUi.addDisposeListener((e) -> {
+ managedUis.remove(uid);
+ if (log.isDebugEnabled())
+ log.debug("Suite UI " + uid + " has been disposed.");
+ });
+ return argeoSuiteUi;
+ }
+
+ @Override
+ public String getThemeId(String uiName) {
+ String themeId = System.getProperty("org.argeo.app.theme.default");
+ if (themeId != null)
+ return themeId;
+ return defaultThemeId;
+ }
+
+ @Override
+ public void refreshUi(CmsUi cmsUi, String state) {
+ try {
+ Content context = null;
+ SwtAppUi ui = (SwtAppUi) cmsUi;
+
+ String uiName = Objects.toString(ui.getParent().getData(UI_NAME_PROPERTY), null);
+ if (uiName == null)
+ throw new IllegalStateException("UI name should not be null");
+ CmsView cmsView = CmsSwtUtils.getCmsView(ui);
+
+ ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository, cmsView);
+
+ SwtUiProvider headerUiProvider = findUiProvider(headerPid);
+ SwtUiProvider footerUiProvider = findUiProvider(footerPid);
+ SwtUiProvider leadPaneUiProvider;
+ if (adminUiName.equals(uiName)) {
+ leadPaneUiProvider = findUiProvider(adminLeadPanePid);
+ } else {
+ leadPaneUiProvider = findUiProvider(leadPanePid);
+ }
+
+ Localized appTitle = null;
+ if (headerUiProvider instanceof DefaultHeader) {
+ appTitle = ((DefaultHeader) headerUiProvider).getTitle();
+ }
+ ui.setTitle(appTitle);
+
+ if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login
+ ui.logout();
+ ui.setLoginScreen(true);
+ if (headerUiProvider != null)
+ refreshPart(headerUiProvider, ui.getHeader(), context);
+ ui.refreshBelowHeader(false);
+ refreshPart(findUiProvider(loginScreenPid), ui.getBelowHeader(), context);
+ if (footerUiProvider != null)
+ refreshPart(footerUiProvider, ui.getFooter(), context);
+ ui.layout(true, true);
+ setState(ui, LOGIN);
+ } else {
+ if (LOGIN.equals(state))
+ state = null;
+ if (ui.isLoginScreen()) {
+ ui.setLoginScreen(false);
+ }
+ CmsSession cmsSession = cmsView.getCmsSession();
+ if (ui.getUserDir() == null) {
+ // FIXME NPE on CMSSession when logging in from anonymous
+ if (cmsSession == null || cmsView.isAnonymous()) {
+ assert publicBasePath != null;
+ Content userDir = contentSession
+ .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + publicBasePath);
+ ui.setUserDir(userDir);
+ } else {
+ Content userDir = appUserState.getOrCreateSessionDir(contentSession, cmsSession);
+ ui.setUserDir(userDir);
+// Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> {
+// Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
+// return node;
+// });
+// Content userDir = contentSession
+// .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + userDirNode.getPath());
+// ui.setUserDir(userDir);
+ }
+ }
+ initLocale(cmsSession);
+ context = stateToNode(ui, state);
+ if (context == null)
+ context = ui.getUserDir();
+
+ if (headerUiProvider != null)
+ refreshPart(headerUiProvider, ui.getHeader(), context);
+ ui.refreshBelowHeader(true);
+ for (String key : layersByPid.keySet()) {
+ SwtAppLayer layer = layersByPid.get(key).get();
+ ui.addLayer(key, layer);
+ }
+
+ if (leadPaneUiProvider != null)
+ refreshPart(leadPaneUiProvider, ui.getLeadPane(), context);
+ if (footerUiProvider != null)
+ refreshPart(footerUiProvider, ui.getFooter(), context);
+ ui.layout(true, true);
+ setState(ui, state != null ? state : defaultLayerPid);
+ }
+ } catch (Exception e) {
+ CmsFeedback.error("Unexpected exception", e);
+ }
+ }
+
+ private void initLocale(CmsSession cmsSession) {
+ if (cmsSession == null)
+ return;
+ Locale locale = cmsSession.getLocale();
+ UiContext.setLocale(locale);
+ LocaleUtils.setThreadLocale(locale);
+
+ }
+
+ private void refreshPart(SwtUiProvider uiProvider, Composite part, Content context) {
+ CmsSwtUtils.clear(part);
+ uiProvider.createUiPart(part, context);
+ }
+
+ private SwtUiProvider findUiProvider(String pid) {
+ if (!uiProvidersByPid.containsKey(pid))
+ return null;
+ return uiProvidersByPid.get(pid).get();
+ }
+
+ private SwtAppLayer findLayer(String pid) {
+ if (!layersByPid.containsKey(pid))
+ return null;
+ return layersByPid.get(pid).get();
+ }
+
+ private <T> T findByType(Map<String, RankedObject<T>> byType, Content content) {
+ if (content == null)
+ throw new IllegalArgumentException("A node should be provided");
+
+// boolean checkJcr = false;
+// if (checkJcr && content instanceof JcrContent) {
+// Node context = ((JcrContent) content).getJcrNode();
+// try {
+// // mixins
+// Set<String> types = new TreeSet<>();
+// for (NodeType mixinType : context.getMixinNodeTypes()) {
+// String mixinTypeName = mixinType.getName();
+// if (byType.containsKey(mixinTypeName)) {
+// types.add(mixinTypeName);
+// }
+// for (NodeType superType : mixinType.getDeclaredSupertypes()) {
+// if (byType.containsKey(superType.getName())) {
+// types.add(superType.getName());
+// }
+// }
+// }
+// // primary node type
+// NodeType primaryType = context.getPrimaryNodeType();
+// String primaryTypeName = primaryType.getName();
+// if (byType.containsKey(primaryTypeName)) {
+// types.add(primaryTypeName);
+// }
+// for (NodeType superType : primaryType.getDeclaredSupertypes()) {
+// if (byType.containsKey(superType.getName())) {
+// types.add(superType.getName());
+// }
+// }
+// // entity type
+// if (context.isNodeType(EntityType.entity.get())) {
+// if (context.hasProperty(EntityNames.ENTITY_TYPE)) {
+// String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString();
+// if (byType.containsKey(entityTypeName)) {
+// types.add(entityTypeName);
+// }
+// }
+// }
+//
+// if (CmsJcrUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node
+// types.add("nt:folder");
+// }
+//
+// if (types.size() == 0)
+// throw new IllegalArgumentException(
+// "No type found for " + context + " (" + listTypes(context) + ")");
+// String type = types.iterator().next();
+// if (!byType.containsKey(type))
+// throw new IllegalArgumentException("No component found for " + context + " with type " + type);
+// return byType.get(type).get();
+// } catch (RepositoryException e) {
+// throw new IllegalStateException(e);
+// }
+//
+// } else {
+ Set<String> types = new TreeSet<>();
+ if (content.hasContentClass(EntityType.entity.qName())) {
+ String type = content.attr(EntityName.type.qName());
+ if (type != null && byType.containsKey(type))
+ types.add(type);
+ }
+
+ List<QName> objectClasses = content.getContentClasses();
+ for (QName cc : objectClasses) {
+ String type = cc.getPrefix() + ":" + cc.getLocalPart();
+ if (byType.containsKey(type))
+ types.add(type);
+ }
+ if (types.size() == 0) {
+ throw new IllegalArgumentException("No type found for " + content + " (" + objectClasses + ")");
+ }
+ String type = types.iterator().next();
+ if (!byType.containsKey(type))
+ throw new IllegalArgumentException("No component found for " + content + " with type " + type);
+ return byType.get(type).get();
+// }
+ }
+
+// private static String listTypes(Node context) {
+// try {
+// StringBuilder sb = new StringBuilder();
+// sb.append(context.getPrimaryNodeType().getName());
+// for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
+// sb.append(' ');
+// sb.append(superType.getName());
+// }
+//
+// for (NodeType nodeType : context.getMixinNodeTypes()) {
+// sb.append(' ');
+// sb.append(nodeType.getName());
+// if (nodeType.getName().equals(EntityType.local.get()))
+// sb.append('/').append(context.getProperty(EntityNames.ENTITY_TYPE).getString());
+// for (NodeType superType : nodeType.getDeclaredSupertypes()) {
+// sb.append(' ');
+// sb.append(superType.getName());
+// }
+// }
+// return sb.toString();
+// } catch (RepositoryException e) {
+// throw new JcrException(e);
+// }
+// }
+
+ @Override
+ public void setState(CmsUi cmsUi, String state) {
+ AppUi ui = (AppUi) cmsUi;
+ if (state == null)
+ return;
+ if (!state.startsWith("/")) {
+// if (cmsUi instanceof SwtAppUi) {
+// SwtAppUi ui = (SwtAppUi) cmsUi;
+ if (LOGIN.equals(state)) {
+ String appTitle = "";
+ if (ui.getTitle() != null)
+ appTitle = ui.getTitle().lead();
+ ui.getCmsView().stateChanged(state, appTitle);
+ return;
+ }
+ Map<String, Object> properties = new HashMap<>();
+ String layerId = HOME_STATE.equals(state) ? defaultLayerPid : state;
+ properties.put(SuiteUxEvent.LAYER, layerId);
+ properties.put(SuiteUxEvent.CONTENT_PATH, HOME_STATE);
+ ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), properties);
+// }
+ return;
+ }
+// SwtAppUi suiteUi = (SwtAppUi) cmsUi;
+ if (ui.isLoginScreen()) {
+ return;
+ }
+
+ Content node = stateToNode(ui, state);
+ if (node == null) {
+ ui.getCmsView().navigateTo(HOME_STATE);
+ } else {
+ ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), SuiteUxEvent.eventProperties(node));
+ ui.getCmsView().sendEvent(SuiteUxEvent.refreshPart.topic(), SuiteUxEvent.eventProperties(node));
+ }
+ }
+
+ // TODO move it to an internal package?
+ public static String nodeToState(Content node) {
+ return node.getPath();
+ }
+
+ private Content stateToNode(CmsUi suiteUi, String state) {
+ if (suiteUi == null)
+ return null;
+ if (state == null || !state.startsWith("/"))
+ return null;
+
+ String path = state;
+
+ ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
+ suiteUi.getCmsView());
+ return contentSession.get(path);
+ }
+
+ /*
+ * Events management
+ */
+
+ @Override
+ public void onEvent(String topic, Map<String, Object> event) {
+
+ // Specific UI related events
+ SwtAppUi ui = getRelatedUi(event);
+ if (ui == null)
+ return;
+ ui.getCmsView().runAs(() -> {
+ try {
+ String appTitle = "";
+ if (ui.getTitle() != null)
+ appTitle = ui.getTitle().lead() + " - ";
+
+ if (isTopic(topic, SuiteUxEvent.refreshPart)) {
+ Content node = getContentFromEvent(ui, event);
+ if (node == null)
+ return;
+ SwtUiProvider uiProvider = findByType(uiProvidersByType, node);
+ SwtAppLayer layer = findByType(layersByType, node);
+ ui.switchToLayer(layer, node);
+ layer.view(uiProvider, ui.getCurrentWorkArea(), node);
+ ui.getCmsView().stateChanged(nodeToState(node), appTitle + CmsUxUtils.getTitle(node));
+ } else if (isTopic(topic, SuiteUxEvent.openNewPart)) {
+ Content node = getContentFromEvent(ui, event);
+ if (node == null)
+ return;
+ SwtUiProvider uiProvider = findByType(uiProvidersByType, node);
+ SwtAppLayer layer = findByType(layersByType, node);
+ ui.switchToLayer(layer, node);
+ layer.open(uiProvider, ui.getCurrentWorkArea(), node);
+ ui.getCmsView().stateChanged(nodeToState(node), appTitle + CmsUxUtils.getTitle(node));
+ } else if (isTopic(topic, SuiteUxEvent.switchLayer)) {
+ String layerId = get(event, SuiteUxEvent.LAYER);
+ if (layerId != null) {
+ SwtAppLayer suiteLayer = findLayer(layerId);
+ if (suiteLayer == null)
+ throw new IllegalArgumentException("No layer '" + layerId + "' available.");
+ Localized layerTitle = suiteLayer.getTitle();
+ // FIXME make sure we don't rebuild the work area twice
+ Composite workArea = ui.switchToLayer(layerId, ui.getUserDir());
+ String title = null;
+ if (layerTitle != null)
+ title = layerTitle.lead();
+ Content nodeFromState = getContentFromEvent(ui, event);
+ if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDir().getPath())) {
+ // default layer view is forced
+ String state = defaultLayerPid.equals(layerId) ? "~" : layerId;
+ ui.getCmsView().stateChanged(state, appTitle + title);
+ suiteLayer.view(null, workArea, nodeFromState);
+ } else {
+ Content layerCurrentContext = suiteLayer.getCurrentContext(workArea);
+ if (layerCurrentContext != null && !layerCurrentContext.equals(ui.getUserDir())) {
+ // layer was already showing a context so we set the state to it
+ ui.getCmsView().stateChanged(nodeToState(layerCurrentContext),
+ appTitle + CmsUxUtils.getTitle(layerCurrentContext));
+ } else {
+ // no context was shown
+ ui.getCmsView().stateChanged(layerId, appTitle + title);
+ }
+ }
+ } else {
+ Content node = getContentFromEvent(ui, event);
+ if (node != null) {
+ SwtAppLayer layer = findByType(layersByType, node);
+ ui.switchToLayer(layer, node);
+ }
+ }
+ }
+ } catch (Exception e) {
+ CmsFeedback.error("Cannot handle event " + topic + " " + event, e);
+// log.error("Cannot handle event " + event, e);
+ }
+ });
+ }
+
+ private boolean isTopic(String topic, CmsEvent cmsEvent) {
+ Objects.requireNonNull(topic);
+ return topic.equals(cmsEvent.topic());
+ }
+
+ protected Content getContentFromEvent(SwtAppUi ui, Map<String, Object> event) {
+ ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
+ ui.getCmsView());
+
+ String path = get(event, SuiteUxEvent.CONTENT_PATH);
+
+ if (path != null && (path.equals(HOME_STATE) || path.equals("")))
+ return ui.getUserDir();
+ Content node;
+ if (path == null) {
+ return null;
+// // look for a user
+// String username = get(event, SuiteUxEvent.USERNAME);
+// if (username == null)
+// return null;
+// User user = cmsUserManager.getUser(username);
+// if (user == null)
+// return null;
+// node = ContentUtils.roleToContent(cmsUserManager, contentSession, user);
+ } else {
+ node = contentSession.get(path);
+ }
+ return node;
+ }
+
+ private SwtAppUi getRelatedUi(Map<String, Object> eventProperties) {
+ return managedUis.get(get(eventProperties, CMS_VIEW_UID_PROPERTY));
+ }
+
+ public static String get(Map<String, Object> eventProperties, String key) {
+ Object value = eventProperties.get(key);
+ if (value == null)
+ return null;
+ return value.toString();
+
+ }
+
+ /*
+ * Dependency injection.
+ */
+
+ public void addUiProvider(SwtUiProvider uiProvider, Map<String, Object> properties) {
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String pid = (String) properties.get(Constants.SERVICE_PID);
+ RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties);
+ }
+ if (properties.containsKey(EntityConstants.TYPE)) {
+ List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
+ for (String type : types) {
+ RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties);
+ }
+ }
+ }
+
+ public void removeUiProvider(SwtUiProvider uiProvider, Map<String, Object> properties) {
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String pid = (String) properties.get(Constants.SERVICE_PID);
+ if (uiProvidersByPid.containsKey(pid)) {
+ if (uiProvidersByPid.get(pid).equals(new RankedObject<SwtUiProvider>(uiProvider, properties))) {
+ uiProvidersByPid.remove(pid);
+ }
+ }
+ }
+ if (properties.containsKey(EntityConstants.TYPE)) {
+ List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
+ for (String type : types) {
+ if (uiProvidersByType.containsKey(type)) {
+ if (uiProvidersByType.get(type).equals(new RankedObject<SwtUiProvider>(uiProvider, properties))) {
+ uiProvidersByType.remove(type);
+ }
+ }
+ }
+ }
+ }
+
+ public void addLayer(SwtAppLayer layer, Map<String, Object> properties) {
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String pid = (String) properties.get(Constants.SERVICE_PID);
+ RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
+ }
+ if (properties.containsKey(EntityConstants.TYPE)) {
+ List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
+ for (String type : types)
+ RankedObject.putIfHigherRank(layersByType, type, layer, properties);
+ }
+ }
+
+ public void removeLayer(SwtAppLayer layer, Map<String, Object> properties) {
+ if (properties.containsKey(Constants.SERVICE_PID)) {
+ String pid = (String) properties.get(Constants.SERVICE_PID);
+ if (layersByPid.containsKey(pid)) {
+ if (layersByPid.get(pid).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
+ layersByPid.remove(pid);
+ }
+ }
+ }
+ if (properties.containsKey(EntityConstants.TYPE)) {
+ List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
+ for (String type : types) {
+ if (layersByType.containsKey(type)) {
+ if (layersByType.get(type).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
+ layersByType.remove(type);
+ }
+ }
+ }
+ }
+ }
+
+// public void setCmsUserManager(CmsUserManager cmsUserManager) {
+// this.cmsUserManager = cmsUserManager;
+// }
+
+// protected ContentRepository getContentRepository() {
+// return contentRepository;
+// }
+
+ public void setContentRepository(ContentRepository contentRepository) {
+ this.contentRepository = contentRepository;
+ }
+
+ public void setAppUserState(AppUserState appUserState) {
+ this.appUserState = appUserState;
+ }
+
+}
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" immediate="false" name="Admin Lead Pane">
- <implementation class="org.argeo.app.ui.DefaultLeadPane"/>
+ <implementation class="org.argeo.app.swt.ux.DefaultLeadPane"/>
<service>
<provide interface="org.argeo.cms.swt.acr.SwtUiProvider"/>
</service>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="Argeo Suite App">
- <implementation class="org.argeo.app.ui.SuiteApp"/>
+ <implementation class="org.argeo.app.swt.ux.SwtArgeoApp"/>
<service>
<provide interface="org.argeo.api.cms.CmsApp"/>
</service>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" immediate="false" name="Default Suite Footer">
- <implementation class="org.argeo.app.ui.DefaultFooter"/>
+ <implementation class="org.argeo.app.swt.ux.DefaultFooter"/>
<service>
<provide interface="org.argeo.cms.swt.acr.SwtUiProvider"/>
</service>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" immediate="false" name="Default Suite Header">
- <implementation class="org.argeo.app.ui.DefaultHeader"/>
+ <implementation class="org.argeo.app.swt.ux.DefaultHeader"/>
<service>
<provide interface="org.argeo.cms.swt.acr.SwtUiProvider"/>
</service>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" immediate="false" name="Default Lead Pane">
- <implementation class="org.argeo.app.ui.DefaultLeadPane"/>
+ <implementation class="org.argeo.app.swt.ux.DefaultLeadPane"/>
<service>
<provide interface="org.argeo.cms.swt.acr.SwtUiProvider"/>
</service>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Default Login Screen">
- <implementation class="org.argeo.app.ui.DefaultLoginScreen"/>
+ <implementation class="org.argeo.app.swt.ux.DefaultLoginScreen"/>
<properties entry="config/loginScreen.properties"/>
<service>
<provide interface="org.argeo.cms.swt.acr.SwtUiProvider"/>
org.eclipse.jface.dialogs,\
org.eclipse.rap.rwt,\
javax.servlet.*;version="[3,5)",\
+javax.jcr.nodetype,\
*
+++ /dev/null
-package org.argeo.app.ui;
-
-import java.util.Map;
-
-import org.argeo.api.acr.Content;
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.CmsUiProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.osgi.framework.BundleContext;
-
-/** Footer of a standard Argeo Suite application. */
-public class DefaultFooter implements CmsUiProvider {
- @Override
- public Control createUiPart(Composite parent, Content context) {
- parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
- Composite content = new Composite(parent, SWT.NONE);
- content.setLayoutData(new GridData(0, 0));
- Control contentControl = createContent(content, context);
-
- // TODO support and guarantee
-
- return contentControl;
- }
-
- protected Control createContent(Composite parent, Content context) {
- return parent;
- }
-
- public void init(BundleContext bundleContext, Map<String, String> properties) {
- }
-
- public void destroy(BundleContext bundleContext, Map<String, String> properties) {
-
- }
-}
+++ /dev/null
-package org.argeo.app.ui;
-
-import java.util.Map;
-
-import org.argeo.api.acr.Content;
-import org.argeo.api.cms.ux.CmsView;
-import org.argeo.app.ux.SuiteIcon;
-import org.argeo.app.ux.SuiteStyle;
-import org.argeo.cms.CurrentUser;
-import org.argeo.cms.Localized;
-import org.argeo.cms.swt.CmsSwtTheme;
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.CmsUiProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleWiring;
-
-/** Header of a standard Argeo Suite application. */
-public class DefaultHeader implements CmsUiProvider {
- public final static String TITLE_PROPERTY = "argeo.suite.ui.header.title";
- private Localized title = null;
-
- @Override
- public Control createUiPart(Composite parent, Content context) {
- CmsView cmsView = CmsSwtUtils.getCmsView(parent);
- CmsSwtTheme theme = CmsSwtUtils.getCmsTheme(parent);
-
- parent.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(3, true)));
-
- // TODO right to left
- Composite lead = new Composite(parent, SWT.NONE);
- CmsSwtUtils.style(lead, SuiteStyle.header);
- lead.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, false));
- lead.setLayout(new GridLayout());
- Label lbl = new Label(lead, SWT.NONE);
-// String title = properties.get(TITLE_PROPERTY);
-// // TODO expose the localized
-// lbl.setText(LocaleUtils.isLocaleKey(title) ? LocaleUtils.local(title, getClass().getClassLoader()).toString()
-// : title);
- lbl.setText(title.lead());
- CmsSwtUtils.style(lbl, SuiteStyle.headerTitle);
- lbl.setLayoutData(CmsSwtUtils.fillWidth());
-
- Composite middle = new Composite(parent, SWT.NONE);
- CmsSwtUtils.style(middle, SuiteStyle.header);
- middle.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false));
- middle.setLayout(new GridLayout());
-
- Composite end = new Composite(parent, SWT.NONE);
- CmsSwtUtils.style(end, SuiteStyle.header);
- end.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false));
-
- if (!cmsView.isAnonymous()) {
- end.setLayout(new GridLayout(2, false));
- Label userL = new Label(end, SWT.NONE);
- CmsSwtUtils.style(userL, SuiteStyle.header);
- userL.setText(CurrentUser.getDisplayName());
-// Button logoutB = new Button(end, SWT.FLAT);
-// logoutB.setImage(theme.getSmallIcon(SuiteIcon.logout));
-// logoutB.addSelectionListener(new SelectionAdapter() {
-// private static final long serialVersionUID = 7116760083964201233L;
-//
-// @Override
-// public void widgetSelected(SelectionEvent e) {
-// cmsView.logout();
-// }
-//
-// });
- Label logOutL = new Label(end, 0);
- logOutL.setImage(theme.getSmallIcon(SuiteIcon.openUserMenu));
- logOutL.addMouseListener(new MouseAdapter() {
- private static final long serialVersionUID = 6908266850511460799L;
-
- @Override
- public void mouseDown(MouseEvent e) {
- cmsView.logout();
- }
-
- });
- } else {
- end.setLayout(new GridLayout(1, false));
- // required in order to avoid wrong height after logout
- new Label(end, SWT.NONE).setText("");
-
- }
- return lbl;
- }
-
- public void init(BundleContext bundleContext, Map<String, String> properties) {
- String titleStr = (String) properties.get(TITLE_PROPERTY);
- if (titleStr != null) {
- if (titleStr.startsWith("%")) {
- title = new Localized() {
-
- @Override
- public String name() {
- return titleStr;
- }
-
- @Override
- public ClassLoader getL10nClassLoader() {
- return bundleContext != null
- ? bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader()
- : getClass().getClassLoader();
- }
- };
- } else {
- title = new Localized.Untranslated(titleStr);
- }
- }
- }
-
- public void destroy(BundleContext bundleContext, Map<String, String> properties) {
-
- }
-
- public Localized getTitle() {
- return title;
- }
-
-}
+++ /dev/null
-package org.argeo.app.ui;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.argeo.api.acr.Content;
-import org.argeo.api.cms.CmsLog;
-import org.argeo.api.cms.ux.CmsView;
-import org.argeo.app.api.RankedObject;
-import org.argeo.app.core.SuiteUtils;
-import org.argeo.app.swt.ux.SwtAppLayer;
-import org.argeo.app.ux.SuiteIcon;
-import org.argeo.app.ux.SuiteStyle;
-import org.argeo.cms.CurrentUser;
-import org.argeo.cms.Localized;
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.CmsUiProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.wiring.BundleWiring;
-
-/** Side pane listing various perspectives. */
-public class DefaultLeadPane implements CmsUiProvider {
- private final static CmsLog log = CmsLog.getLog(DefaultLeadPane.class);
-
- public static enum Property {
- defaultLayers, adminLayers;
- }
-
- private Map<String, RankedObject<SwtAppLayer>> layers = Collections.synchronizedSortedMap(new TreeMap<>());
- private List<String> defaultLayers;
- private List<String> adminLayers = new ArrayList<>();
-
- private ClassLoader l10nClassLoader;
-
- @Override
- public Control createUiPart(Composite parent, Content node) {
- CmsView cmsView = CmsSwtUtils.getCmsView(parent);
- parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
- Composite appLayersC = new Composite(parent, SWT.NONE);
- CmsSwtUtils.style(appLayersC, SuiteStyle.leadPane);
- GridLayout layout = new GridLayout();
- layout.verticalSpacing = 10;
- layout.marginTop = 10;
- layout.marginLeft = 10;
- layout.marginRight = 10;
- appLayersC.setLayout(layout);
- appLayersC.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
-
- Composite adminLayersC;
- if (!adminLayers.isEmpty()) {
- adminLayersC = new Composite(parent, SWT.NONE);
- CmsSwtUtils.style(adminLayersC, SuiteStyle.leadPane);
- GridLayout adminLayout = new GridLayout();
- adminLayout.verticalSpacing = 10;
- adminLayout.marginBottom = 10;
- adminLayout.marginLeft = 10;
- adminLayout.marginRight = 10;
- adminLayersC.setLayout(adminLayout);
- adminLayersC.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, false, true));
- } else {
- adminLayersC = null;
- }
-
-// boolean isAdmin = cmsView.doAs(() -> CurrentUser.isInRole(NodeConstants.ROLE_USER_ADMIN));
- // Set<String> userRoles = cmsView.doAs(() -> CurrentUser.roles());
- Button first = null;
- layers: for (String layerDef : defaultLayers) {
- layerDef = layerDef.trim();
- if ("".equals(layerDef))
- continue layers;// skip empty lines
- String[] semiColArr = layerDef.split(";");
- String layerId = semiColArr[0];
- Set<String> layerRoles = SuiteUtils.extractRoles(semiColArr);
- if (layers.containsKey(layerId)) {
- if (!layerRoles.isEmpty()) {
- boolean authorized = false;
- authorized = cmsView.doAs(() -> {
- for (String layerRole : layerRoles) {
- if (CurrentUser.implies(layerRole, null)) {
- return true;
- }
- }
- return false;
- });
- if (!authorized)
- continue layers;// skip unauthorized layer
-// Set<String> intersection = new HashSet<String>(layerRoles);
-// intersection.retainAll(userRoles);
-// if (intersection.isEmpty())
-// continue layers;// skip unauthorized layer
- }
- RankedObject<SwtAppLayer> layerObj = layers.get(layerId);
-
- Localized title = null;
- if (!adminLayers.contains(layerId)) {
- String titleStr = (String) layerObj.getProperties().get(SwtAppLayer.Property.title.name());
- if (titleStr != null) {
- if (titleStr.startsWith("%")) {
- // LocaleUtils.local(titleStr, getClass().getClassLoader());
- title = () -> titleStr;
- } else {
- title = new Localized.Untranslated(titleStr);
- }
- }
- }
-
- String iconName = (String) layerObj.getProperties().get(SwtAppLayer.Property.icon.name());
- SuiteIcon icon = null;
- if (iconName != null)
- icon = SuiteIcon.valueOf(iconName);
-
- Composite buttonParent;
- if (adminLayers.contains(layerId))
- buttonParent = adminLayersC;
- else
- buttonParent = appLayersC;
- Button b = SuiteUiUtils.createLayerButton(buttonParent, layerId, title, icon, l10nClassLoader);
- if (first == null)
- first = b;
- }
- }
- return first;
- }
-
- public void init(BundleContext bundleContext, Map<String, Object> properties) {
- l10nClassLoader = bundleContext != null ? bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader()
- : getClass().getClassLoader();
-
- String[] defaultLayers = (String[]) properties.get(Property.defaultLayers.toString());
- if (defaultLayers == null)
- throw new IllegalArgumentException("Default layers must be set.");
- this.defaultLayers = Arrays.asList(defaultLayers);
- if (log.isDebugEnabled())
- log.debug("Default layers: " + Arrays.asList(defaultLayers));
- String[] adminLayers = (String[]) properties.get(Property.adminLayers.toString());
- if (adminLayers != null) {
- this.adminLayers = Arrays.asList(adminLayers);
- if (log.isDebugEnabled())
- log.debug("Admin layers: " + Arrays.asList(adminLayers));
- }
- }
-
- public void destroy(BundleContext bundleContext, Map<String, String> properties) {
-
- }
-
- public void addLayer(SwtAppLayer layer, Map<String, Object> properties) {
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- RankedObject.putIfHigherRank(layers, pid, layer, properties);
- }
- }
-
- public void removeLayer(SwtAppLayer layer, Map<String, Object> properties) {
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- if (layers.containsKey(pid)) {
- if (layers.get(pid).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
- layers.remove(pid);
- }
- }
- }
- }
-
-// protected Button createLayerButton(Composite parent, String layer, Localized msg, CmsIcon icon) {
-// CmsTheme theme = CmsTheme.getCmsTheme(parent);
-// Button button = new Button(parent, SWT.PUSH);
-// CmsUiUtils.style(button, SuiteStyle.leadPane);
-// if (icon != null)
-// button.setImage(icon.getBigIcon(theme));
-// button.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, false));
-// // button.setToolTipText(msg.lead());
-// if (msg != null) {
-// Label lbl = new Label(parent, SWT.CENTER);
-// CmsUiUtils.style(lbl, SuiteStyle.leadPane);
-// // CmsUiUtils.markup(lbl);
-// ClassLoader l10nClassLoader = getClass().getClassLoader();
-// String txt = LocaleUtils.lead(msg, l10nClassLoader);
-//// String txt = msg.lead();
-// lbl.setText(txt);
-// lbl.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
-// }
-// CmsUiUtils.sendEventOnSelect(button, SuiteEvent.switchLayer.topic(), SuiteEvent.LAYER, layer);
-// return button;
-// }
-}
+++ /dev/null
-package org.argeo.app.ui;
-
-import org.argeo.api.acr.Content;
-import org.argeo.api.cms.CmsContext;
-import org.argeo.api.cms.ux.CmsView;
-import org.argeo.cms.CurrentUser;
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.swt.auth.CmsLogin;
-import org.argeo.cms.ui.CmsUiProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-
-/** Provides a login screen. */
-public class DefaultLoginScreen implements CmsUiProvider {
- private CmsContext cmsContext;
-
- @Override
- public Control createUiPart(Composite parent, Content context) {
- CmsView cmsView = CmsSwtUtils.getCmsView(parent);
- if (!cmsView.isAnonymous())
- throw new IllegalStateException(CurrentUser.getUsername() + " is already logged in");
-
- parent.setLayout(new GridLayout());
- Composite loginArea = new Composite(parent, SWT.NONE);
- loginArea.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
-
- CmsLogin cmsLogin = new CmsLogin(cmsView, cmsContext);
- cmsLogin.createUi(loginArea);
- return cmsLogin.getCredentialsBlock();
- }
-
- public void setCmsContext(CmsContext cmsContext) {
- this.cmsContext = cmsContext;
- }
-
-}
+++ /dev/null
-package org.argeo.app.ui;
-
-import static org.argeo.api.cms.ux.CmsView.CMS_VIEW_UID_PROPERTY;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import javax.xml.namespace.QName;
-
-import org.argeo.api.acr.Content;
-import org.argeo.api.acr.ContentRepository;
-import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.api.cms.CmsEventSubscriber;
-import org.argeo.api.cms.CmsLog;
-import org.argeo.api.cms.CmsSession;
-import org.argeo.api.cms.ux.CmsTheme;
-import org.argeo.api.cms.ux.CmsUi;
-import org.argeo.api.cms.ux.CmsView;
-import org.argeo.app.api.AppUserState;
-import org.argeo.app.api.EntityConstants;
-import org.argeo.app.api.EntityName;
-import org.argeo.app.api.EntityType;
-import org.argeo.app.api.RankedObject;
-import org.argeo.app.swt.ux.SwtAppLayer;
-import org.argeo.app.swt.ux.SwtAppUi;
-import org.argeo.app.ux.AbstractArgeoApp;
-import org.argeo.app.ux.AppUi;
-import org.argeo.app.ux.SuiteUxEvent;
-import org.argeo.cms.LocaleUtils;
-import org.argeo.cms.Localized;
-import org.argeo.cms.acr.ContentUtils;
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.swt.acr.SwtUiProvider;
-import org.argeo.cms.swt.dialogs.CmsFeedback;
-import org.argeo.cms.util.LangUtils;
-import org.argeo.cms.ux.CmsUxUtils;
-import org.argeo.eclipse.ui.specific.UiContext;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.osgi.framework.Constants;
-
-/** The Argeo Suite App. */
-public class SuiteApp extends AbstractArgeoApp implements CmsEventSubscriber {
- private final static CmsLog log = CmsLog.getLog(SuiteApp.class);
-
- public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath";
- public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName";
- public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId";
- public final static String DEFAULT_LAYER_PROPERTY = "defaultLayer";
- private final static String LOGIN = "login";
- private final static String HOME_STATE = "~";
-
- private String publicBasePath = null;
-
- private String pidPrefix;
- private String headerPid;
- private String footerPid;
- private String leadPanePid;
- private String adminLeadPanePid;
- private String loginScreenPid;
-
- private String defaultUiName = "app";
- private String adminUiName = "admin";
-
- // FIXME such default names make refactoring more dangerous
- @Deprecated
- private String defaultLayerPid = "argeo.suite.ui.dashboardLayer";
- @Deprecated
- private String defaultThemeId = "org.argeo.app.theme.default";
-
- // TODO use QName as key for byType
- private Map<String, RankedObject<SwtUiProvider>> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>());
- private Map<String, RankedObject<SwtUiProvider>> uiProvidersByType = Collections.synchronizedMap(new HashMap<>());
- private Map<String, RankedObject<SwtAppLayer>> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>());
- private Map<String, RankedObject<SwtAppLayer>> layersByType = Collections.synchronizedSortedMap(new TreeMap<>());
-
-// private CmsUserManager cmsUserManager;
-
- // TODO make more optimal or via CmsSession/CmsView
- private Map<String, SwtAppUi> managedUis = new HashMap<>();
-
- // ACR
- private ContentRepository contentRepository;
- private AppUserState appUserState;
- // JCR
-// private Repository repository;
-
- public void init(Map<String, Object> properties) {
- for (SuiteUxEvent event : SuiteUxEvent.values()) {
- getCmsContext().getCmsEventBus().addEventSubscriber(event.topic(), this);
- }
-
- if (log.isDebugEnabled())
- log.info("Argeo Suite App started");
-
- if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY))
- defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY);
- if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY))
- defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY);
- if (properties.containsKey(DEFAULT_LAYER_PROPERTY))
- defaultLayerPid = LangUtils.get(properties, DEFAULT_LAYER_PROPERTY);
- publicBasePath = LangUtils.get(properties, PUBLIC_BASE_PATH_PROPERTY);
-
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String servicePid = properties.get(Constants.SERVICE_PID).toString();
- if (servicePid.endsWith(".app")) {
- pidPrefix = servicePid.substring(0, servicePid.length() - "app".length());
- }
- }
-
- if (pidPrefix == null)
- throw new IllegalArgumentException("PID prefix must be set.");
-
- headerPid = pidPrefix + "header";
- footerPid = pidPrefix + "footer";
- leadPanePid = pidPrefix + "leadPane";
- adminLeadPanePid = pidPrefix + "adminLeadPane";
- loginScreenPid = pidPrefix + "loginScreen";
- }
-
- public void destroy(Map<String, Object> properties) {
- for (SwtAppUi ui : managedUis.values())
- if (!ui.isDisposed()) {
- ui.getDisplay().syncExec(() -> ui.dispose());
- }
- if (log.isDebugEnabled())
- log.info("Argeo Suite App stopped");
-
- }
-
- @Override
- public Set<String> getUiNames() {
- HashSet<String> uiNames = new HashSet<>();
- uiNames.add(defaultUiName);
- uiNames.add(adminUiName);
- return uiNames;
- }
-
- @Override
- public CmsUi initUi(Object parent) {
- Composite uiParent = (Composite) parent;
- String uiName = uiParent.getData(UI_NAME_PROPERTY) != null ? uiParent.getData(UI_NAME_PROPERTY).toString()
- : null;
- CmsView cmsView = CmsSwtUtils.getCmsView(uiParent);
- if (cmsView == null)
- throw new IllegalStateException("No CMS view is registered.");
- CmsTheme theme = getTheme(uiName);
- if (theme != null)
- CmsSwtUtils.registerCmsTheme(uiParent.getShell(), theme);
- SwtAppUi argeoSuiteUi = new SwtAppUi(uiParent, SWT.INHERIT_DEFAULT);
- String uid = cmsView.getUid();
- managedUis.put(uid, argeoSuiteUi);
- argeoSuiteUi.addDisposeListener((e) -> {
- managedUis.remove(uid);
- if (log.isDebugEnabled())
- log.debug("Suite UI " + uid + " has been disposed.");
- });
- return argeoSuiteUi;
- }
-
- @Override
- public String getThemeId(String uiName) {
- String themeId = System.getProperty("org.argeo.app.theme.default");
- if (themeId != null)
- return themeId;
- return defaultThemeId;
- }
-
- @Override
- public void refreshUi(CmsUi cmsUi, String state) {
- try {
- Content context = null;
- SwtAppUi ui = (SwtAppUi) cmsUi;
-
- String uiName = Objects.toString(ui.getParent().getData(UI_NAME_PROPERTY), null);
- if (uiName == null)
- throw new IllegalStateException("UI name should not be null");
- CmsView cmsView = CmsSwtUtils.getCmsView(ui);
-
- ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository, cmsView);
-
- SwtUiProvider headerUiProvider = findUiProvider(headerPid);
- SwtUiProvider footerUiProvider = findUiProvider(footerPid);
- SwtUiProvider leadPaneUiProvider;
- if (adminUiName.equals(uiName)) {
- leadPaneUiProvider = findUiProvider(adminLeadPanePid);
- } else {
- leadPaneUiProvider = findUiProvider(leadPanePid);
- }
-
- Localized appTitle = null;
- if (headerUiProvider instanceof DefaultHeader) {
- appTitle = ((DefaultHeader) headerUiProvider).getTitle();
- }
- ui.setTitle(appTitle);
-
- if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login
- ui.logout();
- ui.setLoginScreen(true);
- if (headerUiProvider != null)
- refreshPart(headerUiProvider, ui.getHeader(), context);
- ui.refreshBelowHeader(false);
- refreshPart(findUiProvider(loginScreenPid), ui.getBelowHeader(), context);
- if (footerUiProvider != null)
- refreshPart(footerUiProvider, ui.getFooter(), context);
- ui.layout(true, true);
- setState(ui, LOGIN);
- } else {
- if (LOGIN.equals(state))
- state = null;
- if (ui.isLoginScreen()) {
- ui.setLoginScreen(false);
- }
- CmsSession cmsSession = cmsView.getCmsSession();
- if (ui.getUserDir() == null) {
- // FIXME NPE on CMSSession when logging in from anonymous
- if (cmsSession == null || cmsView.isAnonymous()) {
- assert publicBasePath != null;
- Content userDir = contentSession
- .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + publicBasePath);
- ui.setUserDir(userDir);
- } else {
- Content userDir = appUserState.getOrCreateSessionDir(contentSession, cmsSession);
- ui.setUserDir(userDir);
-// Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> {
-// Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
-// return node;
-// });
-// Content userDir = contentSession
-// .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + userDirNode.getPath());
-// ui.setUserDir(userDir);
- }
- }
- initLocale(cmsSession);
- context = stateToNode(ui, state);
- if (context == null)
- context = ui.getUserDir();
-
- if (headerUiProvider != null)
- refreshPart(headerUiProvider, ui.getHeader(), context);
- ui.refreshBelowHeader(true);
- for (String key : layersByPid.keySet()) {
- SwtAppLayer layer = layersByPid.get(key).get();
- ui.addLayer(key, layer);
- }
-
- if (leadPaneUiProvider != null)
- refreshPart(leadPaneUiProvider, ui.getLeadPane(), context);
- if (footerUiProvider != null)
- refreshPart(footerUiProvider, ui.getFooter(), context);
- ui.layout(true, true);
- setState(ui, state != null ? state : defaultLayerPid);
- }
- } catch (Exception e) {
- CmsFeedback.error("Unexpected exception", e);
- }
- }
-
- private void initLocale(CmsSession cmsSession) {
- if (cmsSession == null)
- return;
- Locale locale = cmsSession.getLocale();
- UiContext.setLocale(locale);
- LocaleUtils.setThreadLocale(locale);
-
- }
-
- private void refreshPart(SwtUiProvider uiProvider, Composite part, Content context) {
- CmsSwtUtils.clear(part);
- uiProvider.createUiPart(part, context);
- }
-
- private SwtUiProvider findUiProvider(String pid) {
- if (!uiProvidersByPid.containsKey(pid))
- return null;
- return uiProvidersByPid.get(pid).get();
- }
-
- private SwtAppLayer findLayer(String pid) {
- if (!layersByPid.containsKey(pid))
- return null;
- return layersByPid.get(pid).get();
- }
-
- private <T> T findByType(Map<String, RankedObject<T>> byType, Content content) {
- if (content == null)
- throw new IllegalArgumentException("A node should be provided");
-
-// boolean checkJcr = false;
-// if (checkJcr && content instanceof JcrContent) {
-// Node context = ((JcrContent) content).getJcrNode();
-// try {
-// // mixins
-// Set<String> types = new TreeSet<>();
-// for (NodeType mixinType : context.getMixinNodeTypes()) {
-// String mixinTypeName = mixinType.getName();
-// if (byType.containsKey(mixinTypeName)) {
-// types.add(mixinTypeName);
-// }
-// for (NodeType superType : mixinType.getDeclaredSupertypes()) {
-// if (byType.containsKey(superType.getName())) {
-// types.add(superType.getName());
-// }
-// }
-// }
-// // primary node type
-// NodeType primaryType = context.getPrimaryNodeType();
-// String primaryTypeName = primaryType.getName();
-// if (byType.containsKey(primaryTypeName)) {
-// types.add(primaryTypeName);
-// }
-// for (NodeType superType : primaryType.getDeclaredSupertypes()) {
-// if (byType.containsKey(superType.getName())) {
-// types.add(superType.getName());
-// }
-// }
-// // entity type
-// if (context.isNodeType(EntityType.entity.get())) {
-// if (context.hasProperty(EntityNames.ENTITY_TYPE)) {
-// String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString();
-// if (byType.containsKey(entityTypeName)) {
-// types.add(entityTypeName);
-// }
-// }
-// }
-//
-// if (CmsJcrUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node
-// types.add("nt:folder");
-// }
-//
-// if (types.size() == 0)
-// throw new IllegalArgumentException(
-// "No type found for " + context + " (" + listTypes(context) + ")");
-// String type = types.iterator().next();
-// if (!byType.containsKey(type))
-// throw new IllegalArgumentException("No component found for " + context + " with type " + type);
-// return byType.get(type).get();
-// } catch (RepositoryException e) {
-// throw new IllegalStateException(e);
-// }
-//
-// } else {
- Set<String> types = new TreeSet<>();
- if (content.hasContentClass(EntityType.entity.qName())) {
- String type = content.attr(EntityName.type.qName());
- if (type != null && byType.containsKey(type))
- types.add(type);
- }
-
- List<QName> objectClasses = content.getContentClasses();
- for (QName cc : objectClasses) {
- String type = cc.getPrefix() + ":" + cc.getLocalPart();
- if (byType.containsKey(type))
- types.add(type);
- }
- if (types.size() == 0) {
- throw new IllegalArgumentException("No type found for " + content + " (" + objectClasses + ")");
- }
- String type = types.iterator().next();
- if (!byType.containsKey(type))
- throw new IllegalArgumentException("No component found for " + content + " with type " + type);
- return byType.get(type).get();
-// }
- }
-
-// private static String listTypes(Node context) {
-// try {
-// StringBuilder sb = new StringBuilder();
-// sb.append(context.getPrimaryNodeType().getName());
-// for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
-// sb.append(' ');
-// sb.append(superType.getName());
-// }
-//
-// for (NodeType nodeType : context.getMixinNodeTypes()) {
-// sb.append(' ');
-// sb.append(nodeType.getName());
-// if (nodeType.getName().equals(EntityType.local.get()))
-// sb.append('/').append(context.getProperty(EntityNames.ENTITY_TYPE).getString());
-// for (NodeType superType : nodeType.getDeclaredSupertypes()) {
-// sb.append(' ');
-// sb.append(superType.getName());
-// }
-// }
-// return sb.toString();
-// } catch (RepositoryException e) {
-// throw new JcrException(e);
-// }
-// }
-
- @Override
- public void setState(CmsUi cmsUi, String state) {
- AppUi ui = (AppUi) cmsUi;
- if (state == null)
- return;
- if (!state.startsWith("/")) {
-// if (cmsUi instanceof SwtAppUi) {
-// SwtAppUi ui = (SwtAppUi) cmsUi;
- if (LOGIN.equals(state)) {
- String appTitle = "";
- if (ui.getTitle() != null)
- appTitle = ui.getTitle().lead();
- ui.getCmsView().stateChanged(state, appTitle);
- return;
- }
- Map<String, Object> properties = new HashMap<>();
- String layerId = HOME_STATE.equals(state) ? defaultLayerPid : state;
- properties.put(SuiteUxEvent.LAYER, layerId);
- properties.put(SuiteUxEvent.CONTENT_PATH, HOME_STATE);
- ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), properties);
-// }
- return;
- }
-// SwtAppUi suiteUi = (SwtAppUi) cmsUi;
- if (ui.isLoginScreen()) {
- return;
- }
-
- Content node = stateToNode(ui, state);
- if (node == null) {
- ui.getCmsView().navigateTo(HOME_STATE);
- } else {
- ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), SuiteUxEvent.eventProperties(node));
- ui.getCmsView().sendEvent(SuiteUxEvent.refreshPart.topic(), SuiteUxEvent.eventProperties(node));
- }
- }
-
- // TODO move it to an internal package?
- public static String nodeToState(Content node) {
- return node.getPath();
- }
-
- private Content stateToNode(CmsUi suiteUi, String state) {
- if (suiteUi == null)
- return null;
- if (state == null || !state.startsWith("/"))
- return null;
-
- String path = state;
-
- ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
- suiteUi.getCmsView());
- return contentSession.get(path);
- }
-
- /*
- * Events management
- */
-
- @Override
- public void onEvent(String topic, Map<String, Object> event) {
-
- // Specific UI related events
- SwtAppUi ui = getRelatedUi(event);
- if (ui == null)
- return;
- ui.getCmsView().runAs(() -> {
- try {
- String appTitle = "";
- if (ui.getTitle() != null)
- appTitle = ui.getTitle().lead() + " - ";
-
- if (SuiteUiUtils.isTopic(topic, SuiteUxEvent.refreshPart)) {
- Content node = getContentFromEvent(ui, event);
- if (node == null)
- return;
- SwtUiProvider uiProvider = findByType(uiProvidersByType, node);
- SwtAppLayer layer = findByType(layersByType, node);
- ui.switchToLayer(layer, node);
- layer.view(uiProvider, ui.getCurrentWorkArea(), node);
- ui.getCmsView().stateChanged(nodeToState(node), appTitle + CmsUxUtils.getTitle(node));
- } else if (SuiteUiUtils.isTopic(topic, SuiteUxEvent.openNewPart)) {
- Content node = getContentFromEvent(ui, event);
- if (node == null)
- return;
- SwtUiProvider uiProvider = findByType(uiProvidersByType, node);
- SwtAppLayer layer = findByType(layersByType, node);
- ui.switchToLayer(layer, node);
- layer.open(uiProvider, ui.getCurrentWorkArea(), node);
- ui.getCmsView().stateChanged(nodeToState(node), appTitle + CmsUxUtils.getTitle(node));
- } else if (SuiteUiUtils.isTopic(topic, SuiteUxEvent.switchLayer)) {
- String layerId = get(event, SuiteUxEvent.LAYER);
- if (layerId != null) {
- SwtAppLayer suiteLayer = findLayer(layerId);
- if (suiteLayer == null)
- throw new IllegalArgumentException("No layer '" + layerId + "' available.");
- Localized layerTitle = suiteLayer.getTitle();
- // FIXME make sure we don't rebuild the work area twice
- Composite workArea = ui.switchToLayer(layerId, ui.getUserDir());
- String title = null;
- if (layerTitle != null)
- title = layerTitle.lead();
- Content nodeFromState = getContentFromEvent(ui, event);
- if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDir().getPath())) {
- // default layer view is forced
- String state = defaultLayerPid.equals(layerId) ? "~" : layerId;
- ui.getCmsView().stateChanged(state, appTitle + title);
- suiteLayer.view(null, workArea, nodeFromState);
- } else {
- Content layerCurrentContext = suiteLayer.getCurrentContext(workArea);
- if (layerCurrentContext != null && !layerCurrentContext.equals(ui.getUserDir())) {
- // layer was already showing a context so we set the state to it
- ui.getCmsView().stateChanged(nodeToState(layerCurrentContext),
- appTitle + CmsUxUtils.getTitle(layerCurrentContext));
- } else {
- // no context was shown
- ui.getCmsView().stateChanged(layerId, appTitle + title);
- }
- }
- } else {
- Content node = getContentFromEvent(ui, event);
- if (node != null) {
- SwtAppLayer layer = findByType(layersByType, node);
- ui.switchToLayer(layer, node);
- }
- }
- }
- } catch (Exception e) {
- CmsFeedback.error("Cannot handle event " + topic + " " + event, e);
-// log.error("Cannot handle event " + event, e);
- }
- });
- }
-
- protected Content getContentFromEvent(SwtAppUi ui, Map<String, Object> event) {
- ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
- ui.getCmsView());
-
- String path = get(event, SuiteUxEvent.CONTENT_PATH);
-
- if (path != null && (path.equals(HOME_STATE) || path.equals("")))
- return ui.getUserDir();
- Content node;
- if (path == null) {
- return null;
-// // look for a user
-// String username = get(event, SuiteUxEvent.USERNAME);
-// if (username == null)
-// return null;
-// User user = cmsUserManager.getUser(username);
-// if (user == null)
-// return null;
-// node = ContentUtils.roleToContent(cmsUserManager, contentSession, user);
- } else {
- node = contentSession.get(path);
- }
- return node;
- }
-
- private SwtAppUi getRelatedUi(Map<String, Object> eventProperties) {
- return managedUis.get(get(eventProperties, CMS_VIEW_UID_PROPERTY));
- }
-
- public static String get(Map<String, Object> eventProperties, String key) {
- Object value = eventProperties.get(key);
- if (value == null)
- return null;
- return value.toString();
-
- }
-
- /*
- * Dependency injection.
- */
-
- public void addUiProvider(SwtUiProvider uiProvider, Map<String, Object> properties) {
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties);
- }
- if (properties.containsKey(EntityConstants.TYPE)) {
- List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
- for (String type : types) {
- RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties);
- }
- }
- }
-
- public void removeUiProvider(SwtUiProvider uiProvider, Map<String, Object> properties) {
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- if (uiProvidersByPid.containsKey(pid)) {
- if (uiProvidersByPid.get(pid).equals(new RankedObject<SwtUiProvider>(uiProvider, properties))) {
- uiProvidersByPid.remove(pid);
- }
- }
- }
- if (properties.containsKey(EntityConstants.TYPE)) {
- List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
- for (String type : types) {
- if (uiProvidersByType.containsKey(type)) {
- if (uiProvidersByType.get(type).equals(new RankedObject<SwtUiProvider>(uiProvider, properties))) {
- uiProvidersByType.remove(type);
- }
- }
- }
- }
- }
-
- public void addLayer(SwtAppLayer layer, Map<String, Object> properties) {
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
- }
- if (properties.containsKey(EntityConstants.TYPE)) {
- List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
- for (String type : types)
- RankedObject.putIfHigherRank(layersByType, type, layer, properties);
- }
- }
-
- public void removeLayer(SwtAppLayer layer, Map<String, Object> properties) {
- if (properties.containsKey(Constants.SERVICE_PID)) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- if (layersByPid.containsKey(pid)) {
- if (layersByPid.get(pid).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
- layersByPid.remove(pid);
- }
- }
- }
- if (properties.containsKey(EntityConstants.TYPE)) {
- List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
- for (String type : types) {
- if (layersByType.containsKey(type)) {
- if (layersByType.get(type).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
- layersByType.remove(type);
- }
- }
- }
- }
- }
-
-// public void setCmsUserManager(CmsUserManager cmsUserManager) {
-// this.cmsUserManager = cmsUserManager;
-// }
-
-// protected ContentRepository getContentRepository() {
-// return contentRepository;
-// }
-
- public void setContentRepository(ContentRepository contentRepository) {
- this.contentRepository = contentRepository;
- }
-
- public void setAppUserState(AppUserState appUserState) {
- this.appUserState = appUserState;
- }
-
-}
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
-import java.util.Objects;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.apache.commons.io.IOUtils;
import org.argeo.api.acr.Content;
-import org.argeo.api.cms.CmsEvent;
import org.argeo.api.cms.ux.CmsEditable;
-import org.argeo.api.cms.ux.CmsIcon;
import org.argeo.api.cms.ux.CmsStyle;
import org.argeo.app.api.EntityNames;
import org.argeo.app.api.EntityType;
+import org.argeo.app.swt.ux.SwtArgeoApp;
import org.argeo.app.ux.SuiteStyle;
import org.argeo.app.ux.SuiteUxEvent;
-import org.argeo.cms.LocaleUtils;
import org.argeo.cms.Localized;
import org.argeo.cms.jcr.acr.JcrContent;
-import org.argeo.cms.swt.CmsSwtTheme;
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.dialogs.LightweightDialog;
import org.argeo.cms.ui.util.CmsLink;
}
public static String toLink(Content node) {
- return node != null ? "#" + CmsSwtUtils.cleanPathForUrl(SuiteApp.nodeToState(node)) : null;
+ return node != null ? "#" + CmsSwtUtils.cleanPathForUrl(SwtArgeoApp.nodeToState(node)) : null;
}
public static String toLink(Node node) {
- return node != null ? "#" + CmsSwtUtils.cleanPathForUrl(SuiteApp.nodeToState(JcrContent.nodeToContent(node)))
+ return node != null ? "#" + CmsSwtUtils.cleanPathForUrl(SwtArgeoApp.nodeToState(JcrContent.nodeToContent(node)))
: null;
}
return lbl;
}
-// public static boolean isCoworker(CmsView cmsView) {
-// boolean coworker = cmsView.doAs(() -> CurrentUser.isInRole(SuiteRole.coworker.dn()));
-// return coworker;
-// }
-
- public static boolean isTopic(String topic, CmsEvent cmsEvent) {
- Objects.requireNonNull(topic);
- return topic.equals(cmsEvent.topic());
- }
-
- public static Button createLayerButton(Composite parent, String layer, Localized msg, CmsIcon icon,
- ClassLoader l10nClassLoader) {
- CmsSwtTheme theme = CmsSwtUtils.getCmsTheme(parent);
- Button button = new Button(parent, SWT.PUSH);
- CmsSwtUtils.style(button, SuiteStyle.leadPane);
- if (icon != null)
- button.setImage(theme.getBigIcon(icon));
- button.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, false));
- // button.setToolTipText(msg.lead());
- if (msg != null) {
- Label lbl = new Label(parent, SWT.CENTER);
- CmsSwtUtils.style(lbl, SuiteStyle.leadPane);
- String txt = LocaleUtils.lead(msg, l10nClassLoader);
-// String txt = msg.lead();
- lbl.setText(txt);
- lbl.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
- }
- CmsSwtUtils.sendEventOnSelect(button, SuiteUxEvent.switchLayer.topic(), SuiteUxEvent.LAYER, layer);
- return button;
- }
-
@Deprecated
public static Map<String, Object> eventProperties(Node node) {
Map<String, Object> properties = new HashMap<>();
package org.argeo.app.ui.publish;
-import static org.argeo.app.ui.SuiteApp.DEFAULT_THEME_ID_PROPERTY;
-import static org.argeo.app.ui.SuiteApp.DEFAULT_UI_NAME_PROPERTY;
+import static org.argeo.app.swt.ux.SwtArgeoApp.DEFAULT_THEME_ID_PROPERTY;
+import static org.argeo.app.swt.ux.SwtArgeoApp.DEFAULT_UI_NAME_PROPERTY;
import java.util.HashSet;
import java.util.Map;
import org.argeo.api.cms.CmsApp;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.ux.CmsUi;
-import org.argeo.app.ui.SuiteApp;
+import org.argeo.app.swt.ux.SwtArgeoApp;
import org.argeo.cms.AbstractCmsApp;
import org.argeo.cms.ui.CmsUiProvider;
import org.argeo.cms.util.LangUtils;
defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY);
if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY))
defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY);
- publicBasePath = LangUtils.get(properties, SuiteApp.PUBLIC_BASE_PATH_PROPERTY);
+ publicBasePath = LangUtils.get(properties, SwtArgeoApp.PUBLIC_BASE_PATH_PROPERTY);
pid = properties.get(Constants.SERVICE_PID);
if (log.isDebugEnabled())