Major refactoring of Argeo CMS UI
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 10 Dec 2021 10:43:43 +0000 (11:43 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 10 Dec 2021 10:43:43 +0000 (11:43 +0100)
168 files changed:
org.argeo.api/bnd.bnd
org.argeo.api/src/org/argeo/api/DataModelNamespace.java [deleted file]
org.argeo.api/src/org/argeo/api/PublishNamespace.java [deleted file]
org.argeo.api/src/org/argeo/api/cms/Cms2DSize.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsApp.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsAppListener.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsEditable.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsEvent.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsImageManager.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsSession.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsSessionId.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsStyle.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsTheme.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsUi.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/CmsView.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/MvcProvider.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/cms/UxContext.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/gcr/ContentRepository.java [new file with mode: 0644]
org.argeo.api/src/org/argeo/api/gcr/ContentSession.java [new file with mode: 0644]
org.argeo.cms.e4.rap/src/org/argeo/cms/e4/rap/AbstractRapE4App.java
org.argeo.cms.e4.rap/src/org/argeo/cms/e4/rap/CmsLoginLifecycle.java
org.argeo.cms.e4/OSGI-INF/defaultCallbackHandler.xml
org.argeo.cms.e4/bnd.bnd
org.argeo.cms.e4/e4xmi/cms-devops.e4xmi
org.argeo.cms.e4/src/org/argeo/cms/e4/handlers/ChangePassword.java
org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/AbstractOsgiComposite.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/Browse.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/ConnectivityDeploymentUi.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DataDeploymentUi.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/LogDeploymentUi.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/NonAdminPage.java
org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/SecurityDeploymentUi.java
org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/CmsSessionsView.java
org.argeo.cms.e4/src/org/argeo/cms/e4/parts/EgoDashboard.java
org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupEditor.java
org.argeo.cms.e4/src/org/argeo/cms/e4/users/UserEditor.java
org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/DataModels.java
org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/JcrDeployment.java
org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/KernelUtils.java
org.argeo.cms.jcr/src/org/argeo/cms/jcr/internal/servlet/CmsSessionProvider.java
org.argeo.cms.jcr/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
org.argeo.cms.swt/bnd.bnd
org.argeo.cms.swt/pom.xml
org.argeo.cms.swt/src/org/argeo/cms/swt/CmsIcon.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/CmsStyles.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/CmsSwtTheme.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/CmsSwtUtils.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/MouseDoubleClick.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/MouseDown.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/Selected.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/SimpleSwtUxContext.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLoginShell.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CompositeCallbackHandler.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/DynamicCallbackHandler.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/auth/package-info.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/ChangePasswordDialog.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsFeedback.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsMessageDialog.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsWizardDialog.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/LightweightDialog.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/SingleValueDialog.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/package-info.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/osgi/BundleCmsSwtTheme.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/PickUpUserDialog.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/UserLP.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/UsersImages.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/package-info.java [new file with mode: 0644]
org.argeo.cms.swt/src/org/argeo/eclipse/ui/MouseDoubleClick.java [deleted file]
org.argeo.cms.swt/src/org/argeo/eclipse/ui/MouseDown.java [deleted file]
org.argeo.cms.swt/src/org/argeo/eclipse/ui/Selected.java [deleted file]
org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/AppUi.java
org.argeo.cms.ui.rap/src/org/argeo/cms/ui/script/CmsScriptApp.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/AbstractCmsEntryPoint.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsThemeResourceLoader.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebApp.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/CmsWebEntryPoint.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/MinimalWebApp.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/SimpleErgonomics.java
org.argeo.cms.ui.rap/src/org/argeo/cms/web/WebThemeUtils.java
org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsApp.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsApp.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsAppListener.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsConstants.java
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsEditable.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsImageManager.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsStyles.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsTheme.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsUiProvider.java
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/MvcProvider.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/UxContext.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/ChangePasswordDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsMessageDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsWizardDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/LightweightDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/SingleValueDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/package-info.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormEditorHeader.java
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormStyle.java
org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormUtils.java
org.argeo.cms.ui/src/org/argeo/cms/ui/fs/CmsFsBrowser.java
org.argeo.cms.ui/src/org/argeo/cms/ui/fs/FsContextMenu.java
org.argeo.cms.ui/src/org/argeo/cms/ui/internal/JcrFileUploadReceiver.java
org.argeo.cms.ui/src/org/argeo/cms/ui/internal/SimpleEditableImage.java
org.argeo.cms.ui/src/org/argeo/cms/ui/internal/rwt/UserUi.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/PickUpUserDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/UserLP.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/UsersImages.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/package-info.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/AbstractCmsTheme.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/BundleCmsTheme.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsEvent.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsIcon.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsLink.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsPane.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsStyle.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/DefaultImageManager.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/LoginEntryPoint.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/MenuLink.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleCmsHeader.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleStaticPage.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleStyle.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleUxContext.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/util/SystemNotifications.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/UserMenu.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/UserMenuLink.java
org.argeo.cms.ui/src/org/argeo/cms/ui/util/VerticalMenu.java
org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java
org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/JcrVersionCmsEditable.java
org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/Section.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/ContextOverlay.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/EditableImage.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/EditableText.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/Img.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/JcrComposite.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/StyledControl.java
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/AbstractLoginDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CmsLogin.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CmsLoginShell.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CompositeCallbackHandler.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/DefaultLoginDialog.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/DynamicCallbackHandler.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/LocaleChoice.java [deleted file]
org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/package-info.java [deleted file]
org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java
org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java [deleted file]
org.argeo.cms/src/org/argeo/cms/auth/CmsSessionId.java [deleted file]
org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java
org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java
org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java
org.argeo.cms/src/org/argeo/cms/internal/http/PkgServlet.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java
org.argeo.cms/src/org/argeo/cms/osgi/BundleCmsTheme.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/CmsOsgiUtils.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/DataModelNamespace.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/osgi/PublishNamespace.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/servlet/ServletAuthUtils.java

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6f9826d27c949d9fe77a1d643f6c500355844728 100644 (file)
@@ -0,0 +1,2 @@
+Import-Package: javax.naming.*,\
+javax.security.*
\ No newline at end of file
diff --git a/org.argeo.api/src/org/argeo/api/DataModelNamespace.java b/org.argeo.api/src/org/argeo/api/DataModelNamespace.java
deleted file mode 100644 (file)
index 421b11a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.argeo.api;
-
-import org.osgi.resource.Namespace;
-
-/** CMS Data Model capability namespace. */
-public class DataModelNamespace extends Namespace {
-
-       public static final String CMS_DATA_MODEL_NAMESPACE = "cms.datamodel";
-       public static final String NAME = "name";
-       public static final String CND = "cnd";
-       /** If 'true', indicates that no repository should be published */
-       public static final String ABSTRACT = "abstract";
-
-       private DataModelNamespace() {
-               // empty
-       }
-
-}
diff --git a/org.argeo.api/src/org/argeo/api/PublishNamespace.java b/org.argeo.api/src/org/argeo/api/PublishNamespace.java
deleted file mode 100644 (file)
index ff95754..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.argeo.api;
-
-import org.osgi.resource.Namespace;
-
-/** Namespace defining which resources can be published. Typically use to expose icon of scripts to the web. */
-public class PublishNamespace extends Namespace {
-
-       public static final String CMS_PUBLISH_NAMESPACE = "cms.publish";
-       public static final String PKG = "pkg";
-       public static final String FILE = "file";
-
-       private PublishNamespace() {
-               // empty
-       }
-
-}
diff --git a/org.argeo.api/src/org/argeo/api/cms/Cms2DSize.java b/org.argeo.api/src/org/argeo/api/cms/Cms2DSize.java
new file mode 100644 (file)
index 0000000..30b3d81
--- /dev/null
@@ -0,0 +1,34 @@
+package org.argeo.api.cms;
+
+/** A 2D size. */
+public class Cms2DSize {
+       private Integer width;
+       private Integer height;
+
+       public Cms2DSize() {
+
+       }
+
+       public Cms2DSize(Integer width, Integer height) {
+               super();
+               this.width = width;
+               this.height = height;
+       }
+
+       public Integer getWidth() {
+               return width;
+       }
+
+       public void setWidth(Integer width) {
+               this.width = width;
+       }
+
+       public Integer getHeight() {
+               return height;
+       }
+
+       public void setHeight(Integer height) {
+               this.height = height;
+       }
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsApp.java b/org.argeo.api/src/org/argeo/api/cms/CmsApp.java
new file mode 100644 (file)
index 0000000..761191e
--- /dev/null
@@ -0,0 +1,31 @@
+package org.argeo.api.cms;
+
+import java.util.Set;
+
+/** An extensible user interface base on the CMS backend. */
+public interface CmsApp {
+       /**
+        * If {@link CmsUi#setData(String, Object)} is set with this property, it
+        * indicates a different UI (typically with another theming. The {@link CmsApp}
+        * can use this information, but it doesn't have to be set, in which case a
+        * default UI must be provided. The provided value must belong to the values
+        * returned by {@link CmsApp#getUiNames()}.
+        */
+       final static String UI_NAME_PROPERTY = CmsApp.class.getName() + ".ui.name";
+
+       Set<String> getUiNames();
+
+       CmsUi initUi(Object uiParent);
+
+       void refreshUi(CmsUi cmsUi, String state);
+
+       void setState(CmsUi cmsUi, String state);
+
+       CmsTheme getTheme(String uiName);
+
+       boolean allThemesAvailable();
+
+       void addCmsAppListener(CmsAppListener listener);
+
+       void removeCmsAppListener(CmsAppListener listener);
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsAppListener.java b/org.argeo.api/src/org/argeo/api/cms/CmsAppListener.java
new file mode 100644 (file)
index 0000000..55fcec5
--- /dev/null
@@ -0,0 +1,7 @@
+package org.argeo.api.cms;
+
+/** Notifies important events in a CMS App life cycle. */
+public interface CmsAppListener {
+       /** Theming has been updated and should be reloaded. */
+       void themingUpdated();
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsEditable.java b/org.argeo.api/src/org/argeo/api/cms/CmsEditable.java
new file mode 100644 (file)
index 0000000..2deca01
--- /dev/null
@@ -0,0 +1,57 @@
+package org.argeo.api.cms;
+
+/** Abstraction of a simple edition life cycle. */
+public interface CmsEditable {
+
+       /** Whether the calling thread can edit, the value is immutable */
+       public Boolean canEdit();
+
+       public Boolean isEditing();
+
+       public void startEditing();
+
+       public void stopEditing();
+
+       public static CmsEditable NON_EDITABLE = new CmsEditable() {
+
+               @Override
+               public void stopEditing() {
+               }
+
+               @Override
+               public void startEditing() {
+               }
+
+               @Override
+               public Boolean isEditing() {
+                       return false;
+               }
+
+               @Override
+               public Boolean canEdit() {
+                       return false;
+               }
+       };
+
+       public static CmsEditable ALWAYS_EDITING = new CmsEditable() {
+
+               @Override
+               public void stopEditing() {
+               }
+
+               @Override
+               public void startEditing() {
+               }
+
+               @Override
+               public Boolean isEditing() {
+                       return true;
+               }
+
+               @Override
+               public Boolean canEdit() {
+                       return true;
+               }
+       };
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsEvent.java b/org.argeo.api/src/org/argeo/api/cms/CmsEvent.java
new file mode 100644 (file)
index 0000000..b5dccbe
--- /dev/null
@@ -0,0 +1,19 @@
+package org.argeo.api.cms;
+
+/**
+ * Can be applied to {@link Enum}s in order to define events used by
+ * {@link CmsView#sendEvent(String, java.util.Map)}.
+ */
+public interface CmsEvent {
+       String name();
+
+       default String topic() {
+               return getTopicBase() + "/" + name();
+       }
+
+       default         String getTopicBase() {
+               return "argeo/cms";
+       }
+
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsImageManager.java b/org.argeo.api/src/org/argeo/api/cms/CmsImageManager.java
new file mode 100644 (file)
index 0000000..8c637b8
--- /dev/null
@@ -0,0 +1,46 @@
+package org.argeo.api.cms;
+
+import java.io.InputStream;
+
+/** Read and write access to images. */
+public interface CmsImageManager<V, M> {
+       /** Load image in control */
+       public Boolean load(M node, V control, Cms2DSize size);
+
+       /** @return (0,0) if not available */
+       public Cms2DSize getImageSize(M node);
+
+       /**
+        * The related &lt;img&gt; tag, with src, width and height set.
+        * 
+        * @return null if not available
+        */
+       public String getImageTag(M node);
+
+       /**
+        * The related &lt;img&gt; tag, with url, width and height set. Caller must
+        * close the tag (or add additional attributes).
+        * 
+        * @return null if not available
+        */
+       public StringBuilder getImageTagBuilder(M node, Cms2DSize size);
+
+       /**
+        * Returns the remotely accessible URL of the image (registering it if
+        * needed) @return null if not available
+        */
+       public String getImageUrl(M node);
+
+//     public Binary getImageBinary(Node node) throws RepositoryException;
+
+//     public Image getSwtImage(Node node) throws RepositoryException;
+
+       /** @return URL */
+       public String uploadImage(M context, M uploadFolder, String fileName, InputStream in, String contentType);
+
+       @Deprecated
+       default String uploadImage(M uploadFolder, String fileName, InputStream in) {
+               System.err.println("Context must be provided to " + CmsImageManager.class.getName());
+               return uploadImage(null, uploadFolder, fileName, in, null);
+       }
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsSession.java b/org.argeo.api/src/org/argeo/api/cms/CmsSession.java
new file mode 100644 (file)
index 0000000..18d53ce
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.api.cms;
+
+import java.time.ZonedDateTime;
+import java.util.Locale;
+import java.util.UUID;
+
+import javax.naming.ldap.LdapName;
+import javax.security.auth.Subject;
+
+/** An authenticated user session. */
+public interface CmsSession {
+       final static String USER_DN = "DN";
+       final static String SESSION_UUID = "entryUUID";
+       final static String SESSION_LOCAL_ID = "uniqueIdentifier";
+
+       UUID getUuid();
+
+       String getUserRole();
+       
+       LdapName getUserDn();
+
+       String getLocalId();
+
+       String getDisplayName();
+//     Authorization getAuthorization();
+       
+       Subject getSubject();
+
+       boolean isAnonymous();
+
+       ZonedDateTime getCreationTime();
+
+       ZonedDateTime getEnd();
+
+       Locale getLocale();
+
+       boolean isValid();
+
+       void registerView(String uid, Object view);
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsSessionId.java b/org.argeo.api/src/org/argeo/api/cms/CmsSessionId.java
new file mode 100644 (file)
index 0000000..0e47789
--- /dev/null
@@ -0,0 +1,39 @@
+package org.argeo.api.cms;
+
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+
+/**
+ * The ID of a {@link CmsSession}, which must be available in the private
+ * credentials of an authenticated {@link Subject}.
+ */
+public class CmsSessionId {
+       private final UUID uuid;
+
+       public CmsSessionId(UUID value) {
+               if (value == null)
+                       throw new IllegalArgumentException("Value cannot be null");
+               this.uuid = value;
+       }
+
+       public UUID getUuid() {
+               return uuid;
+       }
+
+       @Override
+       public int hashCode() {
+               return uuid.hashCode();
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               return obj instanceof CmsSessionId && ((CmsSessionId) obj).getUuid().equals(uuid);
+       }
+
+       @Override
+       public String toString() {
+               return "Node Session " + uuid;
+       }
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsStyle.java b/org.argeo.api/src/org/argeo/api/cms/CmsStyle.java
new file mode 100644 (file)
index 0000000..8444e2f
--- /dev/null
@@ -0,0 +1,22 @@
+package org.argeo.api.cms;
+
+/** Can be applied to {@link Enum}s in order to generate (CSS) class names. */
+public interface CmsStyle {
+       String name();
+
+       /** @deprecated use {@link #style()} instead. */
+       @Deprecated
+       default String toStyleClass() {
+               return style();
+       }
+
+       default String style() {
+               String classPrefix = getClassPrefix();
+               return "".equals(classPrefix) ? name() : classPrefix + "-" + name();
+       }
+
+       default String getClassPrefix() {
+               return "";
+       }
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsTheme.java b/org.argeo.api/src/org/argeo/api/cms/CmsTheme.java
new file mode 100644 (file)
index 0000000..50c3b1f
--- /dev/null
@@ -0,0 +1,45 @@
+package org.argeo.api.cms;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+
+/** A CMS theme which can be applied to web apps as well as desktop apps. */
+public interface CmsTheme {
+       /** Unique ID of this theme. */
+       String getThemeId();
+
+       /**
+        * Load a resource as an input stream, base don its relative path, or
+        * <code>null</code> if not found
+        */
+       InputStream getResourceAsStream(String resourceName) throws IOException;
+
+       /** Relative paths to standard web CSS. */
+       Set<String> getWebCssPaths();
+
+       /** Relative paths to RAP specific CSS. */
+       Set<String> getRapCssPaths();
+
+       /** Relative paths to SWT specific CSS. */
+       Set<String> getSwtCssPaths();
+
+       /** Relative paths to images such as icons. */
+       Set<String> getImagesPaths();
+
+       /** Relative paths to fonts. */
+       Set<String> getFontsPaths();
+
+       /** Tags to be added to the header section of the HTML page. */
+       String getHtmlHeaders();
+
+       /** The HTML body to use. */
+       String getBodyHtml();
+
+       /** The default icon size (typically the smallest). */
+       Integer getDefaultIconSize();
+
+       /** Loads one of the relative path provided by the other methods. */
+       InputStream loadPath(String path) throws IOException;
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsUi.java b/org.argeo.api/src/org/argeo/api/cms/CmsUi.java
new file mode 100644 (file)
index 0000000..fd91c6e
--- /dev/null
@@ -0,0 +1,7 @@
+package org.argeo.api.cms;
+
+public interface CmsUi {
+       Object getData(String key);
+       void setData(String key, Object value);
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsView.java b/org.argeo.api/src/org/argeo/api/cms/CmsView.java
new file mode 100644 (file)
index 0000000..c7ca1e9
--- /dev/null
@@ -0,0 +1,97 @@
+package org.argeo.api.cms;
+
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.login.LoginContext;
+
+/** Provides interaction with the CMS system. */
+public interface CmsView {
+       final static String CMS_VIEW_UID_PROPERTY = "argeo.cms.view.uid";
+       // String KEY = "org.argeo.cms.ui.view";
+
+       String getUid();
+
+       UxContext getUxContext();
+
+       // NAVIGATION
+       void navigateTo(String state);
+
+       // SECURITY
+       void authChange(LoginContext loginContext);
+
+       void logout();
+
+       // void registerCallbackHandler(CallbackHandler callbackHandler);
+
+       // SERVICES
+       void exception(Throwable e);
+
+       CmsImageManager<?, ?> getImageManager();
+
+       boolean isAnonymous();
+
+       /**
+        * Send an event to this topic. Does nothing by default., but if implemented it
+        * MUST set the {@link #CMS_VIEW_UID_PROPERTY} in the properties.
+        */
+       default void sendEvent(String topic, Map<String, Object> properties) {
+
+       }
+
+       /**
+        * Convenience methods for when {@link #sendEvent(String, Map)} only requires
+        * one single parameter.
+        */
+       default void sendEvent(String topic, String param, Object value) {
+               Map<String, Object> properties = new HashMap<>();
+               properties.put(param, value);
+               sendEvent(topic, properties);
+       }
+
+       default void applyStyles(Object widget) {
+
+       }
+
+       default <T> T doAs(PrivilegedAction<T> action) {
+               throw new UnsupportedOperationException();
+       }
+
+       default Void runAs(Runnable runnable) {
+               return doAs(new PrivilegedAction<Void>() {
+
+                       @Override
+                       public Void run() {
+                               if (runnable != null)
+                                       runnable.run();
+                               return null;
+                       }
+               });
+       }
+
+       default void stateChanged(String state, String title) {
+       }
+
+       default CmsSession getCmsSession() {
+               throw new UnsupportedOperationException();
+       }
+
+       default Object getData(String key) {
+               throw new UnsupportedOperationException();
+       }
+
+       @SuppressWarnings("unchecked")
+       default <T> T getUiContext(Class<T> clss) {
+               return (T) getData(clss.getName());
+       }
+
+       default <T> void setUiContext(Class<T> clss, T instance) {
+               setData(clss.getName(), instance);
+       }
+
+       default void setData(String key, Object value) {
+               throw new UnsupportedOperationException();
+       }
+
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/MvcProvider.java b/org.argeo.api/src/org/argeo/api/cms/MvcProvider.java
new file mode 100644 (file)
index 0000000..c1aa600
--- /dev/null
@@ -0,0 +1,44 @@
+package org.argeo.api.cms;
+
+import java.util.function.BiFunction;
+
+/**
+ * Stateless UI part creator. Takes a parent view (V) and a model context (M) in
+ * order to create a view part (W) which can then be further configured. Such
+ * object can be used as services and reference other part of the model which
+ * are relevant for all created UI part.
+ */
+@FunctionalInterface
+public interface MvcProvider<V, M, W> extends BiFunction<V, M, W> {
+       W createUiPart(V parent, M context);
+       
+       /**
+        * Whether this parent view is supported.
+        * 
+        * @return true by default.
+        */
+       default boolean isViewSupported(V parent) {
+               return true;
+       }
+
+       /**
+        * Whether this context is supported.
+        * 
+        * @return true by default.
+        */
+       default boolean isModelSupported(M context) {
+               return true;
+       }
+
+       default W apply(V parent, M context) {
+               if (!isViewSupported(parent))
+                       throw new IllegalArgumentException("Parent view " + parent + "is not supported.");
+               if (!isModelSupported(context))
+                       throw new IllegalArgumentException("Model context " + context + "is not supported.");
+               return createUiPart(parent, context);
+       }
+
+       default W createUiPart(V parent) {
+               return createUiPart(parent, null);
+       }
+}
diff --git a/org.argeo.api/src/org/argeo/api/cms/UxContext.java b/org.argeo.api/src/org/argeo/api/cms/UxContext.java
new file mode 100644 (file)
index 0000000..fb99178
--- /dev/null
@@ -0,0 +1,18 @@
+package org.argeo.api.cms;
+
+public interface UxContext {
+       boolean isPortrait();
+
+       boolean isLandscape();
+
+       boolean isSquare();
+
+       boolean isSmall();
+
+       /**
+        * Is a production environment (must be false by default, and be explicitly
+        * set during the CMS deployment). When false, it can activate additional UI
+        * capabilities in order to facilitate QA.
+        */
+       boolean isMasterData();
+}
diff --git a/org.argeo.api/src/org/argeo/api/gcr/ContentRepository.java b/org.argeo.api/src/org/argeo/api/gcr/ContentRepository.java
new file mode 100644 (file)
index 0000000..3349b30
--- /dev/null
@@ -0,0 +1,6 @@
+package org.argeo.api.gcr;
+
+import java.util.function.Supplier;
+
+public interface ContentRepository extends Supplier<ContentSession> {
+}
diff --git a/org.argeo.api/src/org/argeo/api/gcr/ContentSession.java b/org.argeo.api/src/org/argeo/api/gcr/ContentSession.java
new file mode 100644 (file)
index 0000000..cd2543f
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.api.gcr;
+
+public interface ContentSession {
+
+}
index 8c43a8089fcbabcb7a136ddab53e68ee3ff32742..5fe22ae33b0aa42da989676390e714f288a8ac08 100644 (file)
@@ -3,7 +3,7 @@ package org.argeo.cms.e4.rap;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.argeo.cms.ui.dialogs.CmsFeedback;
+import org.argeo.cms.swt.dialogs.CmsFeedback;
 import org.eclipse.rap.e4.E4ApplicationConfig;
 import org.eclipse.rap.rwt.application.Application;
 import org.eclipse.rap.rwt.application.Application.OperationMode;
index 12ee3c55e9150fe17ea22a87bd85eb13e3dd9156..3ee8df1ef76c27a9b44a672c16354d4b3fe0cf8a 100644 (file)
@@ -10,14 +10,15 @@ import javax.security.auth.login.LoginException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.api.cms.CmsView;
+import org.argeo.api.cms.UxContext;
 import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.ui.CmsImageManager;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.UxContext;
-import org.argeo.cms.ui.dialogs.CmsFeedback;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.SimpleSwtUxContext;
+import org.argeo.cms.swt.auth.CmsLoginShell;
+import org.argeo.cms.swt.dialogs.CmsFeedback;
 import org.argeo.cms.ui.util.SimpleImageManager;
-import org.argeo.cms.ui.util.SimpleUxContext;
-import org.argeo.cms.ui.widgets.auth.CmsLoginShell;
 import org.eclipse.e4.core.services.events.IEventBroker;
 import org.eclipse.e4.ui.workbench.UIEvents;
 import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate;
@@ -63,7 +64,7 @@ public class CmsLoginLifecycle implements CmsView {
                Display display = Display.getCurrent();
 //             UiContext.setData(CmsView.KEY, this);
                CmsLoginShell loginShell = new CmsLoginShell(this);
-               CmsView.registerCmsView(loginShell.getShell(), this);
+               CmsSwtUtils.registerCmsView(loginShell.getShell(), this);
                loginShell.setSubject(subject);
                try {
                        // try pre-auth
@@ -80,7 +81,7 @@ public class CmsLoginLifecycle implements CmsView {
                }
                if (CurrentUser.getUsername(getSubject()) == null)
                        return false;
-               uxContext = new SimpleUxContext();
+               uxContext = new SimpleSwtUxContext();
                imageManager = new SimpleImageManager();
 
                eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new EventHandler() {
index 3fd7fdafb16fa4e1356d1de50dc058eb3bc00c1b..fcd3ae5cbe03306aa32b43c5f877b4c0ad085bb5 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Default CallbackHandler">
-   <implementation class="org.argeo.cms.ui.widgets.auth.DynamicCallbackHandler"/>
+   <implementation class="org.argeo.cms.swt.auth.DynamicCallbackHandler"/>
    <service>
       <provide interface="javax.security.auth.callback.CallbackHandler"/>
    </service>
index 8714dab794e92e1e0a5fd39a2b481005ba601bd7..e4a4519f0537549b77d4901f7efbf2d62340e4e3 100644 (file)
@@ -11,5 +11,5 @@ javax.jcr.nodetype,\
 org.argeo.cms,\
 org.eclipse.core.commands.common,\
 org.eclipse.jface.window,\
-org.argeo.cms.ui.widgets.auth,\
+org.argeo.cms.swt.auth,\
 *
index dc80445874650952dd7cb0227f174e8eeddfa600..89bcc376d35259c76989139b08ee646ffe99f0ec 100644 (file)
@@ -5,16 +5,16 @@
     <tags>shellMaximized</tags>
     <tags>auth.cn=admin,ou=roles,ou=node</tags>
     <children xsi:type="advanced:PerspectiveStack" xmi:id="_jXVqsCk4Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.perspectivestack.0" selectedElement="_xOVlsDvOEeiF1foPJZSZkw">
-      <children xsi:type="advanced:Perspective" xmi:id="_xOVlsDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.perspective.users" label="Users" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/group.png">
+      <children xsi:type="advanced:Perspective" xmi:id="_xOVlsDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.perspective.users" label="Users" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png">
         <tags>auth.cn=admin,ou=roles,ou=node</tags>
         <children xsi:type="basic:PartSashContainer" xmi:id="_1tQoEDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partsashcontainer.2" horizontal="true">
           <children xsi:type="basic:PartStack" xmi:id="_vtbKkDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partstack.4" containerData="4000" selectedElement="_9gukYDvOEeiF1foPJZSZkw">
-            <children xsi:type="basic:Part" xmi:id="_9gukYDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.part.users" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.UsersView" label="Users" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/person.png">
+            <children xsi:type="basic:Part" xmi:id="_9gukYDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.part.users" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.UsersView" label="Users" iconURI="platform:/plugin/org.argeo.cms.swt/icons/person.png">
               <handlers xmi:id="_0mN68DvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.4" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.handlers.NewUser" command="_uL5i4DvjEeiF1foPJZSZkw"/>
               <handlers xmi:id="_ODLdgDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.5" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.handlers.DeleteUsers" command="_xkcMADvjEeiF1foPJZSZkw"/>
               <toolbar xmi:id="_jLWmkDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.toolbar.1">
-                <children xsi:type="menu:HandledToolItem" xmi:id="_jy_OUDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.new" label="New" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/add.png" command="_uL5i4DvjEeiF1foPJZSZkw"/>
-                <children xsi:type="menu:HandledToolItem" xmi:id="_9qszMDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/delete.png" command="_xkcMADvjEeiF1foPJZSZkw"/>
+                <children xsi:type="menu:HandledToolItem" xmi:id="_jy_OUDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.new" label="New" iconURI="platform:/plugin/org.argeo.cms.swt/icons/add.png" command="_uL5i4DvjEeiF1foPJZSZkw"/>
+                <children xsi:type="menu:HandledToolItem" xmi:id="_9qszMDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.swt/icons/delete.png" command="_xkcMADvjEeiF1foPJZSZkw"/>
               </toolbar>
             </children>
           </children>
             <tags>usersEditorArea</tags>
           </children>
           <children xsi:type="basic:PartStack" xmi:id="_-mFn8DvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partstack.5" containerData="2000">
-            <children xsi:type="basic:Part" xmi:id="_6etk4DvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.part.groups" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.GroupsView" label="Groups" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/group.png">
+            <children xsi:type="basic:Part" xmi:id="_6etk4DvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.part.groups" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.GroupsView" label="Groups" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png">
               <handlers xmi:id="_cmShoDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.6" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.handlers.NewGroup" command="_uL5i4DvjEeiF1foPJZSZkw"/>
               <handlers xmi:id="_fbYfcDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.7" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.handlers.DeleteGroups" command="_xkcMADvjEeiF1foPJZSZkw"/>
               <toolbar xmi:id="_Us0rADvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.toolbar.2">
-                <children xsi:type="menu:HandledToolItem" xmi:id="_VQTLgDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.new" label="New" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/add.png" command="_uL5i4DvjEeiF1foPJZSZkw"/>
-                <children xsi:type="menu:HandledToolItem" xmi:id="_XfME8DvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/delete.png" command="_xkcMADvjEeiF1foPJZSZkw"/>
+                <children xsi:type="menu:HandledToolItem" xmi:id="_VQTLgDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.new" label="New" iconURI="platform:/plugin/org.argeo.cms.swt/icons/add.png" command="_uL5i4DvjEeiF1foPJZSZkw"/>
+                <children xsi:type="menu:HandledToolItem" xmi:id="_XfME8DvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.swt/icons/delete.png" command="_xkcMADvjEeiF1foPJZSZkw"/>
               </toolbar>
             </children>
           </children>
         </children>
       </children>
-      <children xsi:type="advanced:Perspective" xmi:id="_jvjWYCk4Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.perspective.data" label="Data" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/nodes.gif">
+      <children xsi:type="advanced:Perspective" xmi:id="_jvjWYCk4Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.perspective.data" label="Data" iconURI="platform:/plugin/org.argeo.cms.swt/icons/nodes.gif">
         <children xsi:type="basic:PartSashContainer" xmi:id="_h3tvMCkxEein5vuhpK-Dew" elementId="org.argeo.cms.e4.partsashcontainer.0" selectedElement="_0B9SECkxEein5vuhpK-Dew" horizontal="true">
           <children xsi:type="basic:PartStack" xmi:id="_0B9SECkxEein5vuhpK-Dew" elementId="org.argeo.cms.e4.partstack.0" containerData="4000" selectedElement="_WAjPkCkTEein5vuhpK-Dew">
-            <children xsi:type="basic:Part" xmi:id="_WAjPkCkTEein5vuhpK-Dew" elementId="org.argeo.cms.e4.jcrbrowser" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.JcrBrowserView" label="JCR" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/browser.gif">
+            <children xsi:type="basic:Part" xmi:id="_WAjPkCkTEein5vuhpK-Dew" elementId="org.argeo.cms.e4.jcrbrowser" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.JcrBrowserView" label="JCR" iconURI="platform:/plugin/org.argeo.cms.swt/icons/browser.gif">
               <menus xsi:type="menu:PopupMenu" xmi:id="_eXiUECqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.popupmenu.nodeViewer">
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_GVeO8CqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.refresh" label="Refresh" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/refresh.png" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_fU238CqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.addfoldernode" label="Add folder" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/addFolder.gif" command="_RgE5cCqREeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_U4o9cCqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.rename" label="Rename" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/rename.gif" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_Ncxo0CqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.remove" label="Remove" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/remove.gif" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_GVeO8CqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.refresh" label="Refresh" iconURI="platform:/plugin/org.argeo.cms.swt/icons/refresh.png" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_fU238CqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.addfoldernode" label="Add folder" iconURI="platform:/plugin/org.argeo.cms.swt/icons/addFolder.gif" command="_RgE5cCqREeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_U4o9cCqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.rename" label="Rename" iconURI="platform:/plugin/org.argeo.cms.swt/icons/rename.gif" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_Ncxo0CqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.remove" label="Remove" iconURI="platform:/plugin/org.argeo.cms.swt/icons/remove.gif" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
               </menus>
               <menus xmi:id="_oRg_ACqTEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.menu.0">
                 <tags>ViewMenu</tags>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_yJR8ECqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.refresh" label="Refresh" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/refresh.png" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_o6HQECqTEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.addfoldernode" label="Add folder" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/addFolder.gif" command="_RgE5cCqREeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_5D7aACqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.rename" label="Rename" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/rename.gif" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_7rR2wCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/remove.gif" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
-                <children xsi:type="menu:HandledMenuItem" xmi:id="_XsHLgFgQEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledmenuitem.0" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/addRepo.gif" command="_ZWpasFgQEeiknZQLx-vtnA"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_yJR8ECqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.refresh" label="Refresh" iconURI="platform:/plugin/org.argeo.cms.swt/icons/refresh.png" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_o6HQECqTEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.addfoldernode" label="Add folder" iconURI="platform:/plugin/org.argeo.cms.swt/icons/addFolder.gif" command="_RgE5cCqREeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_5D7aACqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.rename" label="Rename" iconURI="platform:/plugin/org.argeo.cms.swt/icons/rename.gif" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_7rR2wCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.swt/icons/remove.gif" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
+                <children xsi:type="menu:HandledMenuItem" xmi:id="_XsHLgFgQEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledmenuitem.0" iconURI="platform:/plugin/org.argeo.cms.swt/icons/addRepo.gif" command="_ZWpasFgQEeiknZQLx-vtnA"/>
               </menus>
             </children>
           </children>
           </children>
         </children>
       </children>
-      <children xsi:type="advanced:Perspective" xmi:id="_u5ZakFhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.perspective.monitoring" label="Monitoring" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/bundles.gif">
+      <children xsi:type="advanced:Perspective" xmi:id="_u5ZakFhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.perspective.monitoring" label="Monitoring" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif">
         <children xsi:type="basic:PartStack" xmi:id="_7i7t8FhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.partstack.6">
-          <children xsi:type="basic:Part" xmi:id="_Z-3cMFhbEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.osgiConfigurations" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.OsgiConfigurationsView" label="OSGi Configurations" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/node.gif"/>
-          <children xsi:type="basic:Part" xmi:id="_8dM90FhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.cmsSessions" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.CmsSessionsView" label="CMS Sessions" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/person-logged-in.png"/>
-          <children xsi:type="basic:Part" xmi:id="_KqRZIFhNEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.modules" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.ModulesView" label="Modules" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/bundles.gif"/>
-          <children xsi:type="basic:Part" xmi:id="_dXtIoFhNEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.bundles" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.BundlesView" label="Bundles" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/bundles.gif"/>
+          <children xsi:type="basic:Part" xmi:id="_Z-3cMFhbEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.osgiConfigurations" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.OsgiConfigurationsView" label="OSGi Configurations" iconURI="platform:/plugin/org.argeo.cms.swt/icons/node.gif"/>
+          <children xsi:type="basic:Part" xmi:id="_8dM90FhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.cmsSessions" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.CmsSessionsView" label="CMS Sessions" iconURI="platform:/plugin/org.argeo.cms.swt/icons/person-logged-in.png"/>
+          <children xsi:type="basic:Part" xmi:id="_KqRZIFhNEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.modules" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.ModulesView" label="Modules" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif"/>
+          <children xsi:type="basic:Part" xmi:id="_dXtIoFhNEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.bundles" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.BundlesView" label="Bundles" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif"/>
         </children>
       </children>
-      <children xsi:type="advanced:Perspective" xmi:id="_ABK2ADsNEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.perspective.files" label="Files" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/file.gif">
+      <children xsi:type="advanced:Perspective" xmi:id="_ABK2ADsNEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.perspective.files" label="Files" iconURI="platform:/plugin/org.argeo.cms.swt/icons/file.gif">
         <children xsi:type="basic:PartSashContainer" xmi:id="_FPimEDsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.partsashcontainer.1" horizontal="true">
           <children xsi:type="basic:PartStack" xmi:id="_H93NgDsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.partstack.2" containerData="4000">
-            <children xsi:type="basic:Part" xmi:id="_Izxh0DsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.part.files" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.files.NodeFsBrowserView" label="Files" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/file.gif"/>
+            <children xsi:type="basic:Part" xmi:id="_Izxh0DsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.part.files" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.files.NodeFsBrowserView" label="Files" iconURI="platform:/plugin/org.argeo.cms.swt/icons/file.gif"/>
           </children>
           <children xsi:type="basic:Part" xmi:id="_TMqBMDsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.part.0" containerData="6000"/>
         </children>
     <handlers xmi:id="_Vwax0DvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.8" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.handlers.OpenPerspective" command="_AF1UsDvrEeiF1foPJZSZkw"/>
     <trimBars xmi:id="_euVxMCk2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.trimbar.0" side="Left">
       <children xsi:type="menu:ToolBar" xmi:id="_fotHsCk2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.toolbar.0">
-        <children xsi:type="menu:HandledToolItem" xmi:id="_jCSQgDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.users" label="Users" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/group.png" command="_AF1UsDvrEeiF1foPJZSZkw">
+        <children xsi:type="menu:HandledToolItem" xmi:id="_jCSQgDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.users" label="Users" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png" command="_AF1UsDvrEeiF1foPJZSZkw">
           <tags>auth.cn=admin,ou=roles,ou=node</tags>
           <parameters xmi:id="_lu_uYDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.parameter.2" name="perspectiveId" value="org.argeo.cms.e4.perspective.users"/>
         </children>
-        <children xsi:type="menu:HandledToolItem" xmi:id="_jfUM4Ck2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.handledtoolitem.test" label="Data" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/nodes.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
+        <children xsi:type="menu:HandledToolItem" xmi:id="_jfUM4Ck2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.handledtoolitem.test" label="Data" iconURI="platform:/plugin/org.argeo.cms.swt/icons/nodes.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
           <parameters xmi:id="_KDlXQDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.parameter.0" name="perspectiveId" value="org.argeo.cms.e4.perspective.data"/>
         </children>
-        <children xsi:type="menu:HandledToolItem" xmi:id="_dhv80FhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledtoolitem.monitoring" label="Monitoring" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/bundles.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
+        <children xsi:type="menu:HandledToolItem" xmi:id="_dhv80FhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledtoolitem.monitoring" label="Monitoring" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
           <parameters xmi:id="_kjN0cFhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.parameter.3" name="perspectiveId" value="org.argeo.cms.e4.perspective.monitoring"/>
         </children>
-        <children xsi:type="menu:HandledToolItem" xmi:id="_b0OHUDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.files" label="Files" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/file.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
+        <children xsi:type="menu:HandledToolItem" xmi:id="_b0OHUDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.files" label="Files" iconURI="platform:/plugin/org.argeo.cms.swt/icons/file.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
           <parameters xmi:id="_fXvRYDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.parameter.1" name="perspectiveId" value="org.argeo.cms.e4.perspective.files"/>
         </children>
         <children xsi:type="menu:ToolBarSeparator" xmi:id="_wuoL8FhLEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.toolbarseparator.0"/>
-        <children xsi:type="menu:HandledToolItem" xmi:id="_2v8DkFhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledtoolitem.logout" label="Log out" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/logout.png" command="_PsWd0FhLEeiknZQLx-vtnA"/>
+        <children xsi:type="menu:HandledToolItem" xmi:id="_2v8DkFhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledtoolitem.logout" label="Log out" iconURI="platform:/plugin/org.argeo.cms.swt/icons/logout.png" command="_PsWd0FhLEeiknZQLx-vtnA"/>
       </children>
     </trimBars>
   </children>
   <handlers xmi:id="_omPfkCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handler.3" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.handlers.RenameNode" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
   <handlers xmi:id="_dUg-cFgQEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handler.9" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.handlers.AddRemoteRepository" command="_ZWpasFgQEeiknZQLx-vtnA"/>
   <handlers xmi:id="_RQyFAFhLEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handler.10" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.handlers.CloseWorkbench" command="_PsWd0FhLEeiknZQLx-vtnA"/>
-  <descriptors xmi:id="_XzfoMCqlEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.partdescriptor.nodeEditor" label="Node Editor" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/node.gif" allowMultiple="true" category="dataExplorer" closeable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.JcrNodeEditor"/>
-  <descriptors xmi:id="_sAdNwDvdEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partdescriptor.userEditor" label="User Editor" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/person.png" allowMultiple="true" category="usersEditorArea" closeable="true" dirtyable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.UserEditor"/>
-  <descriptors xmi:id="_5nK7EDvdEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partdescriptor.groupEditor" label="Group Editor" iconURI="platform:/plugin/org.argeo.cms.ui.theme/icons/group.png" allowMultiple="true" category="usersEditorArea" closeable="true" dirtyable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.GroupEditor"/>
+  <descriptors xmi:id="_XzfoMCqlEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.partdescriptor.nodeEditor" label="Node Editor" iconURI="platform:/plugin/org.argeo.cms.swt/icons/node.gif" allowMultiple="true" category="dataExplorer" closeable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.JcrNodeEditor"/>
+  <descriptors xmi:id="_sAdNwDvdEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partdescriptor.userEditor" label="User Editor" iconURI="platform:/plugin/org.argeo.cms.swt/icons/person.png" allowMultiple="true" category="usersEditorArea" closeable="true" dirtyable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.UserEditor"/>
+  <descriptors xmi:id="_5nK7EDvdEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partdescriptor.groupEditor" label="Group Editor" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png" allowMultiple="true" category="usersEditorArea" closeable="true" dirtyable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.users.GroupEditor"/>
   <commands xmi:id="_RgE5cCqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.addFolderNode" commandName="Add folder node" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
   <commands xmi:id="_ChJ-4CqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.deleteNodes" commandName="Delete nodes" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
   <commands xmi:id="_TOKHsCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.refreshNodes" commandName="Refresh nodes" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
index fe05253c11045778fa369a702d043a0f7637b227..1d3bab9f81e7a2dfb8112171512c64f919abdc8d 100644 (file)
@@ -15,7 +15,7 @@ import javax.naming.ldap.LdapName;
 import org.argeo.api.security.CryptoKeyring;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.ui.dialogs.CmsMessageDialog;
+import org.argeo.cms.swt.dialogs.CmsMessageDialog;
 import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
 import org.argeo.osgi.transaction.WorkTransaction;
 import org.eclipse.e4.core.di.annotations.Execute;
index 4fc1d983c1f15a7232d66bbd64230b1c0ed0e7df..f352f91aaac9028ab59a8939b916df707ccfa1ca 100644 (file)
@@ -20,13 +20,13 @@ import org.argeo.api.NodeConstants;
 import org.argeo.api.security.CryptoKeyring;
 import org.argeo.api.security.Keyring;
 import org.argeo.cms.CmsException;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.jcr.JcrBrowserUtils;
 import org.argeo.cms.ui.jcr.NodeContentProvider;
 import org.argeo.cms.ui.jcr.NodeLabelProvider;
 import org.argeo.cms.ui.jcr.OsgiRepositoryRegister;
 import org.argeo.cms.ui.jcr.PropertiesContentProvider;
 import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.eclipse.ui.EclipseUiException;
 import org.argeo.eclipse.ui.TreeParent;
 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
@@ -97,7 +97,7 @@ public class JcrBrowserView {
                // Create the tree on top of the view
                Composite top = new Composite(sashForm, SWT.NONE);
                // GridLayout gl = new GridLayout(1, false);
-               top.setLayout(CmsUiUtils.noSpaceGridLayout());
+               top.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                try {
                        this.userSession = this.nodeRepository.login(NodeConstants.HOME_WORKSPACE);
@@ -121,7 +121,7 @@ public class JcrBrowserView {
 
                // Create the property viewer on the bottom
                Composite bottom = new Composite(sashForm, SWT.NONE);
-               bottom.setLayout(CmsUiUtils.noSpaceGridLayout());
+               bottom.setLayout(CmsSwtUtils.noSpaceGridLayout());
                propertiesViewer = createPropertiesViewer(bottom);
 
                sashForm.setWeights(getWeights());
index c83183130f5bb22adb8bd6ce90ddaa76dc6c39f2..c9c18e9df7af9cdd4305691257599d8483c29bf4 100644 (file)
@@ -4,7 +4,7 @@ import java.util.Collection;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
@@ -20,8 +20,8 @@ abstract class AbstractOsgiComposite extends Composite {
 
        public AbstractOsgiComposite(Composite parent, int style) {
                super(parent, style);
-               parent.setLayout(CmsUiUtils.noSpaceGridLayout());
-               setLayout(CmsUiUtils.noSpaceGridLayout());
+               parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
+               setLayout(CmsSwtUtils.noSpaceGridLayout());
                setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
                initUi(style);
        }
index 2212b7b058e16492954f2e6dde6e26ebb036363f..260a114cd990f066c2db26852f55d8073562acc1 100644 (file)
@@ -15,10 +15,11 @@ import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 
+import org.argeo.api.cms.Cms2DSize;
 import org.argeo.cms.CmsException;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.argeo.cms.ui.util.CmsLink;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.cms.ui.widgets.EditableImage;
 import org.argeo.cms.ui.widgets.Img;
 import org.argeo.jcr.JcrUtils;
@@ -75,13 +76,13 @@ public class Browse implements CmsUiProvider {
                if (context == null)
                        // return null;
                        throw new CmsException("Context cannot be null");
-               GridLayout layout = CmsUiUtils.noSpaceGridLayout();
+               GridLayout layout = CmsSwtUtils.noSpaceGridLayout();
                layout.numColumns = 2;
                parent.setLayout(layout);
 
                // Left
                Composite leftCmp = new Composite(parent, SWT.NO_FOCUS);
-               leftCmp.setLayoutData(CmsUiUtils.fillAll());
+               leftCmp.setLayoutData(CmsSwtUtils.fillAll());
                createBrowserPart(leftCmp, context);
 
                // Right
@@ -102,17 +103,17 @@ public class Browse implements CmsUiProvider {
        }
 
        private void createBrowserPart(Composite parent, Node context) throws RepositoryException {
-               GridLayout layout = CmsUiUtils.noSpaceGridLayout();
+               GridLayout layout = CmsSwtUtils.noSpaceGridLayout();
                parent.setLayout(layout);
                Composite filterCmp = new Composite(parent, SWT.NO_FOCUS);
-               filterCmp.setLayoutData(CmsUiUtils.fillWidth());
+               filterCmp.setLayoutData(CmsSwtUtils.fillWidth());
 
                // top filter
                addFilterPanel(filterCmp);
 
                // scrolled composite
                scrolledCmp = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.BORDER | SWT.NO_FOCUS);
-               scrolledCmp.setLayoutData(CmsUiUtils.fillAll());
+               scrolledCmp.setLayoutData(CmsSwtUtils.fillAll());
                scrolledCmp.setExpandVertical(true);
                scrolledCmp.setExpandHorizontal(true);
                scrolledCmp.setShowFocusedControl(true);
@@ -132,7 +133,7 @@ public class Browse implements CmsUiProvider {
        }
 
        private Control initExplorer(Composite parent, Node context) throws RepositoryException {
-               parent.setLayout(CmsUiUtils.noSpaceGridLayout());
+               parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
                createBrowserColumn(parent, context);
                return null;
        }
@@ -149,14 +150,14 @@ public class Browse implements CmsUiProvider {
 
        public void addFilterPanel(Composite parent) {
 
-               parent.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(2, false)));
+               parent.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(2, false)));
 
                // Text Area for the filter
                parentPathTxt = new Text(parent, SWT.NO_FOCUS);
                parentPathTxt.setEditable(false);
                filterTxt = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL);
                filterTxt.setMessage("Filter current list");
-               filterTxt.setLayoutData(CmsUiUtils.fillWidth());
+               filterTxt.setLayoutData(CmsSwtUtils.fillWidth());
                filterTxt.addModifyListener(new ModifyListener() {
                        private static final long serialVersionUID = 7709303319740056286L;
 
@@ -212,7 +213,7 @@ public class Browse implements CmsUiProvider {
        private void setEdited(Node node) {
                try {
                        currEdited = node;
-                       CmsUiUtils.clear(nodeDisplayParent);
+                       CmsSwtUtils.clear(nodeDisplayParent);
                        createNodeView(nodeDisplayParent, currEdited);
                        nodeDisplayParent.layout();
                        refreshFilters(node);
@@ -282,7 +283,7 @@ public class Browse implements CmsUiProvider {
                if (!browserCols.containsKey(currNodePath))
                        createBrowserColumn(colViewer, node);
 
-               colViewer.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(browserCols.size(), false)));
+               colViewer.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(browserCols.size(), false)));
                // colViewer.pack();
                colViewer.layout();
                // also resize the scrolled composite
@@ -313,7 +314,7 @@ public class Browse implements CmsUiProvider {
                }
        }
 
-       private Point imageWidth = new Point(250, 0);
+       private Cms2DSize imageWidth = new Cms2DSize(250, 0);
 
        /**
         * Recreates the content of the box that displays information about the current
@@ -330,7 +331,7 @@ public class Browse implements CmsUiProvider {
 
                // Name and primary type
                Label contextL = new Label(parent, SWT.NONE);
-               CmsUiUtils.markup(contextL);
+               CmsSwtUtils.markup(contextL);
                contextL.setText("<b>" + context.getName() + "</b>");
                new Label(parent, SWT.NONE).setText(context.getPrimaryNodeType().getName());
 
@@ -437,7 +438,7 @@ public class Browse implements CmsUiProvider {
 
                protected void populate() {
                        Composite parent = this;
-                       GridLayout layout = CmsUiUtils.noSpaceGridLayout();
+                       GridLayout layout = CmsSwtUtils.noSpaceGridLayout();
 
                        this.setLayout(layout);
                        createTableViewer(parent);
@@ -452,17 +453,17 @@ public class Browse implements CmsUiProvider {
                        GridData gd = new GridData(SWT.LEFT, SWT.FILL, false, true);
                        gd.widthHint = COLUMN_WIDTH;
                        listCmp.setLayoutData(gd);
-                       listCmp.setLayout(CmsUiUtils.noSpaceGridLayout());
+                       listCmp.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                        entityViewer = new TableViewer(listCmp, SWT.VIRTUAL | SWT.SINGLE);
                        Table table = entityViewer.getTable();
 
-                       table.setLayoutData(CmsUiUtils.fillAll());
+                       table.setLayoutData(CmsSwtUtils.fillAll());
                        table.setLinesVisible(true);
                        table.setHeaderVisible(false);
-                       CmsUiUtils.markup(table);
+                       CmsSwtUtils.markup(table);
 
-                       CmsUiUtils.style(table, MaintenanceStyles.BROWSER_COLUMN);
+                       CmsSwtUtils.style(table, MaintenanceStyles.BROWSER_COLUMN);
 
                        // first column
                        TableViewerColumn column = new TableViewerColumn(entityViewer, SWT.NONE);
index 7e8a99196de86420a7f62e491c1bfbe02c3bd168..97f3e671371370653384d05be08c2342b5cfa2fd 100644 (file)
@@ -1,6 +1,6 @@
 package org.argeo.cms.e4.maintenance;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
@@ -38,7 +38,7 @@ class ConnectivityDeploymentUi extends AbstractOsgiComposite {
 
                Label label = new Label(this, SWT.NONE);
                label.setData(new GridData(SWT.FILL, SWT.FILL, false, false));
-               CmsUiUtils.markup(label);
+               CmsSwtUtils.markup(label);
                label.setText(text.toString());
        }
 
index a750e9541abf2b82179a5216df4947ad5f5da4be..22e80069d61e2218b3bca163fd71582ce93e6d3d 100644 (file)
@@ -10,7 +10,7 @@ import java.util.Collection;
 import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.argeo.api.NodeConstants;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
@@ -106,7 +106,7 @@ class DataDeploymentUi extends AbstractOsgiComposite {
                }
                Label label = new Label(parent, SWT.NONE);
                label.setData(new GridData(SWT.FILL, SWT.FILL, false, false));
-               CmsUiUtils.markup(label);
+               CmsSwtUtils.markup(label);
                label.setText("<span style=''>" + text.toString() + "</span>");
        }
 
index a746b3c46c938ff671a81c7fdb332f5619fd8e80..505f67d8157b8f787364301ba96ca9abff56c5e9 100644 (file)
@@ -6,7 +6,7 @@ import java.util.TimeZone;
 import org.argeo.api.NodeConstants;
 import org.argeo.api.NodeDeployment;
 import org.argeo.api.NodeState;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
@@ -68,7 +68,7 @@ class DeploymentEntryPoint {
                NodeState nodeState = bc.getService(nodeStateRef);
                ServiceReference<NodeDeployment> nodeDeploymentRef = bc.getServiceReference(NodeDeployment.class);
                Label label = new Label(composite, SWT.WRAP);
-               CmsUiUtils.markup(label);
+               CmsSwtUtils.markup(label);
                if (nodeDeploymentRef == null) {
                        label.setText("Not yet deployed on <br>" + nodeState.getHostname() + "</br>, please configure below.");
                } else {
@@ -85,7 +85,7 @@ class DeploymentEntryPoint {
        private static Group createHighLevelGroup(Composite parent, String text) {
                Group group = new Group(parent, SWT.NONE);
                group.setText(text);
-               CmsUiUtils.markup(group);
+               CmsSwtUtils.markup(group);
                return group;
        }
 
index 05923fb4741010f88da91f9f0b3ad0ae868ccecc..fa5d3dae3aff34323ce8c54b110de3eeaec05bdd 100644 (file)
@@ -6,7 +6,7 @@ import java.util.Enumeration;
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
@@ -37,7 +37,7 @@ class LogDeploymentUi extends AbstractOsgiComposite implements LogListener {
                this.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                logDisplay = new Text(this, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY);
                logDisplay.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               CmsUiUtils.markup(logDisplay);
+               CmsSwtUtils.markup(logDisplay);
                Enumeration<LogEntry> logEntries = (Enumeration<LogEntry>) logReader.getLog();
                while (logEntries.hasMoreElements())
                        logDisplay.append(printEntry(logEntries.nextElement()));
index 122f5cfaa590adb7602376991067b83d8bd7c594..cb38ce89925044f142ae8b2b2ce52f208826913c 100644 (file)
@@ -3,8 +3,8 @@ package org.argeo.cms.e4.maintenance;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsUiProvider;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
@@ -18,7 +18,7 @@ public class NonAdminPage implements CmsUiProvider{
        public Control createUi(Composite parent, Node context)
                        throws RepositoryException {
                Composite body = new Composite(parent, SWT.NO_FOCUS);
-               body.setLayoutData(CmsUiUtils.fillAll());
+               body.setLayoutData(CmsSwtUtils.fillAll());
                body.setLayout(new GridLayout());
                Label label = new Label(body, SWT.NONE);
                label.setText("You should be an admin to perform maintenance operations. "
index 4edbf565adf56faf3ac521dda7205591a4e40c1f..3492c5499d7cc629ced31de372419e332e76d7ca 100644 (file)
@@ -2,7 +2,7 @@ package org.argeo.cms.e4.maintenance;
 
 import java.net.URI;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
@@ -75,7 +75,7 @@ class SecurityDeploymentUi extends AbstractOsgiComposite {
                }
                Label label = new Label(parent, SWT.NONE);
                label.setData(new GridData(SWT.FILL, SWT.FILL, false, false));
-               CmsUiUtils.markup(label);
+               CmsSwtUtils.markup(label);
                label.setText(text.toString());
        }
 
index 0c73fd7ce2c755c7ccaf5aa05efcfa4a47f6a325..8a360509527e41ac4eb3a562498d3fe4784e757b 100644 (file)
@@ -10,8 +10,7 @@ import java.util.List;
 import javax.annotation.PostConstruct;
 import javax.naming.ldap.LdapName;
 
-import org.argeo.cms.CmsException;
-import org.argeo.cms.auth.CmsSession;
+import org.argeo.api.cms.CmsSession;
 import org.argeo.eclipse.ui.ColumnViewerComparator;
 import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
 import org.argeo.util.LangUtils;
@@ -55,7 +54,7 @@ public class CmsSessionsView {
                        private static final long serialVersionUID = -5234573509093747505L;
 
                        public String getText(Object element) {
-                               return ((CmsSession) element).getAuthorization().toString();
+                               return ((CmsSession) element).getDisplayName();
                        }
 
                        public String getToolTipText(Object element) {
@@ -154,7 +153,7 @@ public class CmsSessionsView {
                                try {
                                        srs = bc.getServiceReferences(CmsSession.class, null);
                                } catch (InvalidSyntaxException e) {
-                                       throw new CmsException("Cannot retrieve CMS sessions", e);
+                                       throw new IllegalArgumentException("Cannot retrieve CMS sessions", e);
                                }
                                List<CmsSession> res = new ArrayList<>();
                                for (ServiceReference<CmsSession> sr : srs) {
index 8499356dca3b0c77d804273056029fff773e0f09..5a805d1e953646da314646793cb16bd87b3b58d2 100644 (file)
@@ -1,16 +1,15 @@
 package org.argeo.cms.e4.parts;
 
-import static org.argeo.cms.ui.util.CmsUiUtils.lbl;
-import static org.argeo.cms.ui.util.CmsUiUtils.txt;
-
 import java.security.AccessController;
 import java.time.ZonedDateTime;
 
 import javax.annotation.PostConstruct;
 import javax.security.auth.Subject;
 
-import org.argeo.cms.auth.CmsSession;
+import org.argeo.api.cms.CmsSession;
 import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.osgi.CmsOsgiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.osgi.framework.BundleContext;
@@ -25,23 +24,23 @@ public class EgoDashboard {
                p.setLayout(new GridLayout());
                String username = CurrentUser.getUsername();
 
-               lbl(p, "<strong>" + CurrentUser.getDisplayName() + "</strong>");
-               txt(p, username);
-               lbl(p, "Roles:");
+               CmsSwtUtils.lbl(p, "<strong>" + CurrentUser.getDisplayName() + "</strong>");
+               CmsSwtUtils.txt(p, username);
+               CmsSwtUtils.lbl(p, "Roles:");
                roles: for (String role : CurrentUser.roles()) {
                        if (username.equals(role))
                                continue roles;
-                       txt(p, role);
+                       CmsSwtUtils.txt(p, role);
                }
 
                Subject subject = Subject.getSubject(AccessController.getContext());
                if (subject != null) {
-                       CmsSession cmsSession = CmsSession.getCmsSession(bc, subject);
+                       CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bc, subject);
                        ZonedDateTime loggedIndSince = cmsSession.getCreationTime();
-                       lbl(p, "Session:");
-                       txt(p, cmsSession.getUuid().toString());
-                       lbl(p, "Logged in since:");
-                       txt(p, loggedIndSince.toString());
+                       CmsSwtUtils.lbl(p, "Session:");
+                       CmsSwtUtils.txt(p, cmsSession.getUuid().toString());
+                       CmsSwtUtils.lbl(p, "Logged in since:");
+                       CmsSwtUtils.txt(p, loggedIndSince.toString());
                }
        }
 }
index 708a653159f7befb3639a3fabb582478d64b4873..2521612c765dcf16b7f1a6f434269b0fafccb5d0 100644 (file)
@@ -27,9 +27,9 @@ import org.argeo.cms.e4.users.providers.MailLP;
 import org.argeo.cms.e4.users.providers.RoleIconLP;
 import org.argeo.cms.e4.users.providers.UserFilter;
 import org.argeo.cms.jcr.CmsJcrUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
 import org.argeo.cms.ui.eclipse.forms.IManagedForm;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.eclipse.ui.ColumnDefinition;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.eclipse.ui.parts.LdifUsersTable;
@@ -146,7 +146,7 @@ public class GroupEditor extends AbstractRoleEditor {
                // GridLayout layout = new GridLayout(5, false);
                GridLayout layout = new GridLayout(2, false);
                body.setLayout(layout);
-               body.setLayoutData(CmsUiUtils.fillWidth());
+               body.setLayoutData(CmsSwtUtils.fillWidth());
 
                String cn = UserAdminUtils.getProperty(group, LdapAttrs.cn.name());
                createReadOnlyLT(body, "Name", cn);
@@ -287,7 +287,7 @@ public class GroupEditor extends AbstractRoleEditor {
 
                ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
                ToolBar toolBar = toolBarManager.createControl(body);
-               toolBar.setLayoutData(CmsUiUtils.fillWidth());
+               toolBar.setLayoutData(CmsSwtUtils.fillWidth());
 
                toolBarManager.add(action);
                toolBarManager.update(true);
index 18753f7ba9eb0b1e362475a0ddd87a68ef5fd65c..a931001204b1399cbe3d0730f995ddf0e1b09dde 100644 (file)
@@ -20,10 +20,10 @@ import org.argeo.cms.e4.users.providers.CommonNameLP;
 import org.argeo.cms.e4.users.providers.DomainNameLP;
 import org.argeo.cms.e4.users.providers.RoleIconLP;
 import org.argeo.cms.e4.users.providers.UserFilter;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
 //import org.argeo.cms.ui.eclipse.forms.FormToolkit;
 import org.argeo.cms.ui.eclipse.forms.IManagedForm;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.eclipse.ui.ColumnDefinition;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.eclipse.ui.parts.LdifUsersTable;
@@ -278,7 +278,7 @@ public class UserEditor extends AbstractRoleEditor {
                // Composite body= parent;
                Composite body = new Composite(parent, SWT.BORDER);
                body.setLayout(new GridLayout());
-               body.setLayoutData(CmsUiUtils.fillAll());
+               body.setLayoutData(CmsSwtUtils.fillAll());
 
                // boolean isAdmin = CurrentUser.isInRole(NodeConstants.ROLE_ADMIN);
 
@@ -346,7 +346,7 @@ public class UserEditor extends AbstractRoleEditor {
                Action action = new RemoveMembershipAction(userViewer, user, tooltip, SecurityAdminImages.ICON_REMOVE_DESC);
                ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
                ToolBar toolBar = toolBarManager.createControl(body);
-               toolBar.setLayoutData(CmsUiUtils.fillWidth());
+               toolBar.setLayoutData(CmsSwtUtils.fillWidth());
                toolBarManager.add(action);
                toolBarManager.update(true);
                return userViewerCmp;
index a1b5008161dfe41f221d6735b2ef26fcebb52d63..3d0f3a1670bfec4542b6586c9fa27d1216e70bc5 100644 (file)
@@ -1,6 +1,6 @@
 package org.argeo.cms.jcr.internal;
 
-import static org.argeo.api.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
+import static org.argeo.cms.osgi.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -10,8 +10,8 @@ import java.util.TreeMap;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.api.DataModelNamespace;
 import org.argeo.cms.CmsException;
+import org.argeo.cms.osgi.DataModelNamespace;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
index 0daaad47c95f830503c6434a75f8a6acea26e4a0..9915fb037012f00fa714ef038d27043f45b9c231 100644 (file)
@@ -1,6 +1,6 @@
 package org.argeo.cms.jcr.internal;
 
-import static org.argeo.api.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
+import static org.argeo.cms.osgi.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
 import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX;
 
 import java.io.File;
@@ -31,7 +31,6 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.jackrabbit.commons.cnd.CndImporter;
 import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.RepositoryImpl;
-import org.argeo.api.DataModelNamespace;
 import org.argeo.api.NodeConstants;
 import org.argeo.api.NodeDeployment;
 import org.argeo.api.security.CryptoKeyring;
@@ -42,6 +41,7 @@ import org.argeo.cms.jcr.CmsJcrUtils;
 import org.argeo.cms.jcr.internal.servlet.CmsRemotingServlet;
 import org.argeo.cms.jcr.internal.servlet.CmsWebDavServlet;
 import org.argeo.cms.jcr.internal.servlet.JcrHttpUtils;
+import org.argeo.cms.osgi.DataModelNamespace;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
index 98749cf439c35608a8cd496b5c54c85d10d7bd3e..ed04518c004fb312a9d67d1bb0435378d48fbdea 100644 (file)
@@ -24,9 +24,9 @@ import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 
 import org.apache.commons.logging.Log;
-import org.argeo.api.DataModelNamespace;
 import org.argeo.api.NodeConstants;
 import org.argeo.cms.jcr.internal.osgi.CmsJcrActivator;
+import org.argeo.cms.osgi.DataModelNamespace;
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
 
index 8ec2f45b3156043e0e098462e33bd0047b532cb2..45ca33855aea86772d918b3748c17a83d593557f 100644 (file)
@@ -20,7 +20,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.jackrabbit.server.SessionProvider;
 import org.argeo.api.NodeConstants;
-import org.argeo.cms.auth.CmsSession;
+import org.argeo.api.cms.CmsSession;
 import org.argeo.jcr.JcrUtils;
 
 /**
index 5767ecd5e648d7bb8ae476978a379a0865e5bb76..4b59453777de418830a22e3e4dd923de9f629c14 100644 (file)
@@ -27,9 +27,10 @@ import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
 import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsSession;
 import org.argeo.api.security.AnonymousPrincipal;
 import org.argeo.api.security.DataAdminPrincipal;
-import org.argeo.cms.auth.CmsSession;
+import org.argeo.cms.osgi.CmsOsgiUtils;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 
@@ -84,7 +85,7 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
                boolean isRegularUser = !userPrincipal.isEmpty();
                CmsSession cmsSession = null;
                if (cmsBundleContext != null) {
-                       cmsSession = CmsSession.getCmsSession(cmsBundleContext, subject);
+                       cmsSession = CmsOsgiUtils.getCmsSession(cmsBundleContext, subject);
                        if (log.isTraceEnabled())
                                log.trace("Opening JCR session for CMS session " + cmsSession);
                }
index ad8e581781fd6d55c6c9ba56435e29046b8e1848..9d4eae6c3dfd3035711c38b7de0cdc476dee3020 100644 (file)
@@ -2,3 +2,6 @@ Import-Package: org.eclipse.swt,\
                                org.eclipse.jface.window,\
                                org.eclipse.core.commands.common,\
                                *
+
+Bundle-ActivationPolicy: lazy
+                               
\ No newline at end of file
index 2e3942000b63d41b3cd671385244e8dc7cc63709..c6e772c89fe052505ff85f3d089a53090ee56b5d 100644 (file)
                        <version>2.3-SNAPSHOT</version>
                </dependency>
 
+               <!-- Specific -->
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.swt.specific.rap</artifactId>
+                       <version>2.3-SNAPSHOT</version>
+                       <scope>provided</scope>
+               </dependency>
                <!-- UI -->
                <dependency>
                        <groupId>org.argeo.tp.rap.e4</groupId>
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsIcon.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsIcon.java
new file mode 100644 (file)
index 0000000..4ff89f2
--- /dev/null
@@ -0,0 +1,25 @@
+package org.argeo.cms.swt;
+
+import org.argeo.api.cms.CmsTheme;
+import org.eclipse.swt.graphics.Image;
+
+/** Can be applied to {@link Enum}s in order to generated {@link Image}s. */
+public interface CmsIcon {
+       String name();
+
+       default Image getSmallIcon(CmsTheme theme) {
+               return ((CmsSwtTheme) theme).getIcon(name(), getSmallIconSize());
+       }
+
+       default Image getBigIcon(CmsTheme theme) {
+               return ((CmsSwtTheme) theme).getIcon(name(), getBigIconSize());
+       }
+
+       default Integer getSmallIconSize() {
+               return 16;
+       }
+
+       default Integer getBigIconSize() {
+               return 32;
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsStyles.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsStyles.java
new file mode 100644 (file)
index 0000000..9eba6f6
--- /dev/null
@@ -0,0 +1,32 @@
+package org.argeo.cms.swt;
+
+/** Styles references in the CSS. */
+@Deprecated
+public interface CmsStyles {
+       // General
+       public final static String CMS_SHELL = "cms_shell";
+       public final static String CMS_MENU_LINK = "cms_menu_link";
+
+       // Header
+       public final static String CMS_HEADER = "cms_header";
+       public final static String CMS_HEADER_LEAD = "cms_header-lead";
+       public final static String CMS_HEADER_CENTER = "cms_header-center";
+       public final static String CMS_HEADER_END = "cms_header-end";
+
+       public final static String CMS_LEAD = "cms_lead";
+       public final static String CMS_END = "cms_end";
+       public final static String CMS_FOOTER = "cms_footer";
+
+       public final static String CMS_USER_MENU = "cms_user_menu";
+       public final static String CMS_USER_MENU_LINK = "cms_user_menu-link";
+       public final static String CMS_USER_MENU_ITEM = "cms_user_menu-item";
+       public final static String CMS_LOGIN_DIALOG = "cms_login_dialog";
+       public final static String CMS_LOGIN_DIALOG_USERNAME = "cms_login_dialog-username";
+       public final static String CMS_LOGIN_DIALOG_PASSWORD = "cms_login_dialog-password";
+
+       // Body
+       public final static String CMS_SCROLLED_AREA = "cms_scrolled_area";
+       public final static String CMS_BODY = "cms_body";
+       public final static String CMS_STATIC_TEXT = "cms_static-text";
+       public final static String CMS_LINK = "cms_link";
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsSwtTheme.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsSwtTheme.java
new file mode 100644 (file)
index 0000000..b5f7c0e
--- /dev/null
@@ -0,0 +1,21 @@
+package org.argeo.cms.swt;
+
+import org.argeo.api.cms.CmsTheme;
+import org.eclipse.swt.graphics.Image;
+
+/** SWT specific {@link CmsTheme}. */
+public interface CmsSwtTheme extends CmsTheme {
+       /** The image registered at this path, or <code>null</code> if not found. */
+       Image getImage(String path);
+
+       /**
+        * And icon with this file name (without the extension), with a best effort to
+        * find the appropriate size, or <code>null</code> if not found.
+        * 
+        * @param name          An icon file name without path and extension.
+        * @param preferredSize the preferred size, if <code>null</code>,
+        *                      {@link #getDefaultIconSize()} will be tried.
+        */
+       Image getIcon(String name, Integer preferredSize);
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsSwtUtils.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/CmsSwtUtils.java
new file mode 100644 (file)
index 0000000..a94d707
--- /dev/null
@@ -0,0 +1,251 @@
+package org.argeo.cms.swt;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.argeo.api.cms.CmsStyle;
+import org.argeo.api.cms.CmsTheme;
+import org.argeo.api.cms.CmsView;
+import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+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.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+
+/** SWT utilities. */
+public class CmsSwtUtils {
+
+       /** Singleton. */
+       private CmsSwtUtils() {
+       }
+
+       public static CmsTheme getCmsTheme(Composite parent) {
+               CmsTheme theme = (CmsTheme) parent.getData(CmsTheme.class.getName());
+               if (theme == null) {
+                       // find parent shell
+                       Shell topShell = parent.getShell();
+                       while (topShell.getParent() != null)
+                               topShell = (Shell) topShell.getParent();
+                       theme = (CmsTheme) topShell.getData(CmsTheme.class.getName());
+                       parent.setData(CmsTheme.class.getName(), theme);
+               }
+               return theme;
+       }
+
+       public static void registerCmsTheme(Shell shell, CmsTheme theme) {
+               // find parent shell
+               Shell topShell = shell;
+               while (topShell.getParent() != null)
+                       topShell = (Shell) topShell.getParent();
+               // check if already set
+               if (topShell.getData(CmsTheme.class.getName()) != null) {
+                       CmsTheme registeredTheme = (CmsTheme) topShell.getData(CmsTheme.class.getName());
+                       throw new IllegalArgumentException(
+                                       "Theme " + registeredTheme.getThemeId() + " already registered in this shell");
+               }
+               topShell.setData(CmsTheme.class.getName(), theme);
+       }
+
+       public static CmsView getCmsView(Control parent) {
+               // find parent shell
+               Shell topShell = parent.getShell();
+               while (topShell.getParent() != null)
+                       topShell = (Shell) topShell.getParent();
+               return (CmsView) topShell.getData(CmsView.class.getName());
+       }
+
+       public static void registerCmsView(Shell shell, CmsView view) {
+               // find parent shell
+               Shell topShell = shell;
+               while (topShell.getParent() != null)
+                       topShell = (Shell) topShell.getParent();
+               // check if already set
+               if (topShell.getData(CmsView.class.getName()) != null) {
+                       CmsView registeredView = (CmsView) topShell.getData(CmsView.class.getName());
+                       throw new IllegalArgumentException("Cms view " + registeredView + " already registered in this shell");
+               }
+               shell.setData(CmsView.class.getName(), view);
+       }
+
+       /** Sends an event via {@link CmsView#sendEvent(String, Map)}. */
+       public static void sendEventOnSelect(Control control, String topic, Map<String, Object> properties) {
+               SelectionListener listener = (Selected) (e) -> {
+                       getCmsView(control.getParent()).sendEvent(topic, properties);
+               };
+               if (control instanceof Button) {
+                       ((Button) control).addSelectionListener(listener);
+               } else
+                       throw new UnsupportedOperationException("Control type " + control.getClass() + " is not supported.");
+       }
+
+       /**
+        * Convenience method to sends an event via
+        * {@link CmsView#sendEvent(String, Map)}.
+        */
+       public static void sendEventOnSelect(Control control, String topic, String key, Object value) {
+               Map<String, Object> properties = new HashMap<>();
+               properties.put(key, value);
+               sendEventOnSelect(control, topic, properties);
+       }
+
+       /*
+        * GRID LAYOUT
+        */
+       public static GridLayout noSpaceGridLayout() {
+               return noSpaceGridLayout(new GridLayout());
+       }
+
+       public static GridLayout noSpaceGridLayout(int columns) {
+               return noSpaceGridLayout(new GridLayout(columns, false));
+       }
+
+       /** @return the same layout, with spaces removed. */
+       public static GridLayout noSpaceGridLayout(GridLayout layout) {
+               layout.horizontalSpacing = 0;
+               layout.verticalSpacing = 0;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+               return layout;
+       }
+
+       public static GridData fillAll() {
+               return new GridData(SWT.FILL, SWT.FILL, true, true);
+       }
+
+       public static GridData fillWidth() {
+               return grabWidth(SWT.FILL, SWT.FILL);
+       }
+
+       public static GridData grabWidth(int horizontalAlignment, int verticalAlignment) {
+               return new GridData(horizontalAlignment, horizontalAlignment, true, false);
+       }
+
+       public static GridData fillHeight() {
+               return grabHeight(SWT.FILL, SWT.FILL);
+       }
+
+       public static GridData grabHeight(int horizontalAlignment, int verticalAlignment) {
+               return new GridData(horizontalAlignment, horizontalAlignment, false, true);
+       }
+
+       /*
+        * ROW LAYOUT
+        */
+       /** @return the same layout, with margins removed. */
+       public static RowLayout noMarginsRowLayout(RowLayout rowLayout) {
+               rowLayout.marginTop = 0;
+               rowLayout.marginBottom = 0;
+               rowLayout.marginLeft = 0;
+               rowLayout.marginRight = 0;
+               return rowLayout;
+       }
+
+       public static RowLayout noMarginsRowLayout(int type) {
+               return noMarginsRowLayout(new RowLayout(type));
+       }
+
+       public static RowData rowData16px() {
+               return new RowData(16, 16);
+       }
+
+       /*
+        * FORM LAYOUT
+        */
+       public static FormData coverAll() {
+               FormData fdLabel = new FormData();
+               fdLabel.top = new FormAttachment(0, 0);
+               fdLabel.left = new FormAttachment(0, 0);
+               fdLabel.right = new FormAttachment(100, 0);
+               fdLabel.bottom = new FormAttachment(100, 0);
+               return fdLabel;
+       }
+
+       /*
+        * STYLING
+        */
+
+       /** Style widget */
+       public static <T extends Widget> T style(T widget, String style) {
+               if (style == null)
+                       return widget;// does nothing
+               EclipseUiSpecificUtils.setStyleData(widget, style);
+               if (widget instanceof Control) {
+                       CmsView cmsView = getCmsView((Control) widget);
+                       if (cmsView != null)
+                               cmsView.applyStyles(widget);
+               }
+               return widget;
+       }
+
+       /** Style widget */
+       public static <T extends Widget> T style(T widget, CmsStyle style) {
+               return style(widget, style.style());
+       }
+
+       /** Enable markups on widget */
+       public static <T extends Widget> T markup(T widget) {
+               EclipseUiSpecificUtils.setMarkupData(widget);
+               return widget;
+       }
+
+       /** Disable markup validation. */
+       public static <T extends Widget> T disableMarkupValidation(T widget) {
+               EclipseUiSpecificUtils.setMarkupValidationDisabledData(widget);
+               return widget;
+       }
+
+       /**
+        * Apply markup and set text on {@link Label}, {@link Button}, {@link Text}.
+        * 
+        * @param widget the widget to style and to use in order to display text
+        * @param txt    the object to display via its <code>toString()</code> method.
+        *               This argument should not be null, but if it is null and
+        *               assertions are disabled "<null>" is displayed instead; if
+        *               assertions are enabled the call will fail.
+        * 
+        * @see markup
+        */
+       public static <T extends Widget> T text(T widget, Object txt) {
+               assert txt != null;
+               String str = txt != null ? txt.toString() : "<null>";
+               markup(widget);
+               if (widget instanceof Label)
+                       ((Label) widget).setText(str);
+               else if (widget instanceof Button)
+                       ((Button) widget).setText(str);
+               else if (widget instanceof Text)
+                       ((Text) widget).setText(str);
+               else
+                       throw new IllegalArgumentException("Unsupported widget type " + widget.getClass());
+               return widget;
+       }
+
+       /** A {@link Label} with markup activated. */
+       public static Label lbl(Composite parent, Object txt) {
+               return text(new Label(parent, SWT.NONE), txt);
+       }
+
+       /** A read-only {@link Text} whose content can be copy/pasted. */
+       public static Text txt(Composite parent, Object txt) {
+               return text(new Text(parent, SWT.NONE), txt);
+       }
+
+       /** Dispose all children of a Composite */
+       public static void clear(Composite composite) {
+               if (composite.isDisposed())
+                       return;
+               for (Control child : composite.getChildren())
+                       child.dispose();
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/MouseDoubleClick.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/MouseDoubleClick.java
new file mode 100644 (file)
index 0000000..b818b06
--- /dev/null
@@ -0,0 +1,26 @@
+package org.argeo.cms.swt;
+
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+
+/**
+ * {@link MouseListener#mouseDoubleClick(MouseEvent)} as a functional interface
+ * in order to use as a short lambda expression in UI code.
+ * {@link MouseListener#mouseDownouseEvent)} and
+ * {@link MouseListener#mouseUp(MouseEvent)} do nothing by default.
+ */
+@FunctionalInterface
+public interface MouseDoubleClick extends MouseListener {
+       @Override
+       void mouseDoubleClick(MouseEvent e);
+
+       @Override
+       default void mouseDown(MouseEvent e) {
+               // does nothing
+       }
+
+       @Override
+       default void mouseUp(MouseEvent e) {
+               // does nothing
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/MouseDown.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/MouseDown.java
new file mode 100644 (file)
index 0000000..baecb00
--- /dev/null
@@ -0,0 +1,26 @@
+package org.argeo.cms.swt;
+
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+
+/**
+ * {@link MouseListener#mouseDown(MouseEvent)} as a functional interface in
+ * order to use as a short lambda expression in UI code.
+ * {@link MouseListener#mouseDoubleClick(MouseEvent)} and
+ * {@link MouseListener#mouseUp(MouseEvent)} do nothing by default.
+ */
+@FunctionalInterface
+public interface MouseDown extends MouseListener {
+       @Override
+       void mouseDown(MouseEvent e);
+
+       @Override
+       default void mouseDoubleClick(MouseEvent e) {
+               // does nothing
+       }
+
+       @Override
+       default void mouseUp(MouseEvent e) {
+               // does nothing
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/Selected.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/Selected.java
new file mode 100644 (file)
index 0000000..03fbad0
--- /dev/null
@@ -0,0 +1,21 @@
+package org.argeo.cms.swt;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+/**
+ * {@link SelectionListener} as a functional interface in order to use as a
+ * short lambda expression in UI code.
+ * {@link SelectionListener#widgetDefaultSelected(SelectionEvent)} does nothing
+ * by default.
+ */
+@FunctionalInterface
+public interface Selected extends SelectionListener {
+       @Override
+       public void widgetSelected(SelectionEvent e);
+
+       default public void widgetDefaultSelected(SelectionEvent e) {
+               // does nothing
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/SimpleSwtUxContext.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/SimpleSwtUxContext.java
new file mode 100644 (file)
index 0000000..9c55e8b
--- /dev/null
@@ -0,0 +1,50 @@
+package org.argeo.cms.swt;
+
+import org.argeo.api.cms.UxContext;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+
+public class SimpleSwtUxContext implements UxContext {
+       private Point size;
+       private Point small = new Point(400, 400);
+
+       public SimpleSwtUxContext() {
+               this(Display.getCurrent().getBounds());
+       }
+
+       public SimpleSwtUxContext(Rectangle rect) {
+               this.size = new Point(rect.width, rect.height);
+       }
+
+       public SimpleSwtUxContext(Point size) {
+               this.size = size;
+       }
+
+       @Override
+       public boolean isPortrait() {
+               return size.x >= size.y;
+       }
+
+       @Override
+       public boolean isLandscape() {
+               return size.x < size.y;
+       }
+
+       @Override
+       public boolean isSquare() {
+               return size.x == size.y;
+       }
+
+       @Override
+       public boolean isSmall() {
+               return size.x <= small.x || size.y <= small.y;
+       }
+
+       @Override
+       public boolean isMasterData() {
+               // TODO make it configurable
+               return true;
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java
new file mode 100644 (file)
index 0000000..8e12a89
--- /dev/null
@@ -0,0 +1,334 @@
+package org.argeo.cms.swt.auth;
+
+import static org.argeo.cms.CmsMsg.password;
+import static org.argeo.cms.CmsMsg.username;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.api.NodeConstants;
+import org.argeo.api.NodeState;
+import org.argeo.api.cms.CmsView;
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.LocaleUtils;
+import org.argeo.cms.auth.HttpRequestCallback;
+import org.argeo.cms.swt.CmsStyles;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.eclipse.ui.specific.UiContext;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+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.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class CmsLogin implements CmsStyles, CallbackHandler {
+       private final static Log log = LogFactory.getLog(CmsLogin.class);
+
+       private Composite parent;
+       private Text usernameT, passwordT;
+       private Composite credentialsBlock;
+       private final SelectionListener loginSelectionListener;
+
+       private final Locale defaultLocale;
+       private LocaleChoice localeChoice = null;
+
+       private final CmsView cmsView;
+
+       // optional subject to be set explicitly
+       private Subject subject = null;
+
+       public CmsLogin(CmsView cmsView) {
+               this.cmsView = cmsView;
+               NodeState nodeState = null;// = Activator.getNodeState();
+               if (nodeState != null) {
+                       defaultLocale = nodeState.getDefaultLocale();
+                       List<Locale> locales = nodeState.getLocales();
+                       if (locales != null)
+                               localeChoice = new LocaleChoice(locales, defaultLocale);
+               } else {
+                       defaultLocale = Locale.getDefault();
+               }
+               loginSelectionListener = new SelectionListener() {
+                       private static final long serialVersionUID = -8832133363830973578L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               login();
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                       }
+               };
+       }
+
+       protected boolean isAnonymous() {
+               return cmsView.isAnonymous();
+       }
+
+       public final void createUi(Composite parent) {
+               this.parent = parent;
+               createContents(parent);
+       }
+
+       protected void createContents(Composite parent) {
+               defaultCreateContents(parent);
+       }
+
+       public final void defaultCreateContents(Composite parent) {
+               parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
+               Composite credentialsBlock = createCredentialsBlock(parent);
+               if (parent instanceof Shell) {
+                       credentialsBlock.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
+               }
+       }
+
+       public final Composite createCredentialsBlock(Composite parent) {
+               if (isAnonymous()) {
+                       return anonymousUi(parent);
+               } else {
+                       return userUi(parent);
+               }
+       }
+
+       public Composite getCredentialsBlock() {
+               return credentialsBlock;
+       }
+
+       protected Composite userUi(Composite parent) {
+               Locale locale = localeChoice == null ? this.defaultLocale : localeChoice.getSelectedLocale();
+               credentialsBlock = new Composite(parent, SWT.NONE);
+               credentialsBlock.setLayout(new GridLayout());
+               // credentialsBlock.setLayoutData(CmsUiUtils.fillAll());
+
+               specificUserUi(credentialsBlock);
+
+               Label l = new Label(credentialsBlock, SWT.NONE);
+               CmsSwtUtils.style(l, CMS_USER_MENU_ITEM);
+               l.setText(CmsMsg.logout.lead(locale));
+               GridData lData = CmsSwtUtils.fillWidth();
+               lData.widthHint = 120;
+               l.setLayoutData(lData);
+
+               l.addMouseListener(new MouseAdapter() {
+                       private static final long serialVersionUID = 6444395812777413116L;
+
+                       public void mouseDown(MouseEvent e) {
+                               logout();
+                       }
+               });
+               return credentialsBlock;
+       }
+
+       /** To be overridden */
+       protected void specificUserUi(Composite parent) {
+
+       }
+
+       protected Composite anonymousUi(Composite parent) {
+               Locale locale = localeChoice == null ? this.defaultLocale : localeChoice.getSelectedLocale();
+               // We need a composite for the traversal
+               credentialsBlock = new Composite(parent, SWT.NONE);
+               credentialsBlock.setLayout(new GridLayout());
+               // credentialsBlock.setLayoutData(CmsUiUtils.fillAll());
+               CmsSwtUtils.style(credentialsBlock, CMS_LOGIN_DIALOG);
+
+               Integer textWidth = 120;
+               if (parent instanceof Shell)
+                       CmsSwtUtils.style(parent, CMS_USER_MENU);
+               // new Label(this, SWT.NONE).setText(CmsMsg.username.lead());
+               usernameT = new Text(credentialsBlock, SWT.BORDER);
+               usernameT.setMessage(username.lead(locale));
+               CmsSwtUtils.style(usernameT, CMS_LOGIN_DIALOG_USERNAME);
+               GridData gd = CmsSwtUtils.fillWidth();
+               gd.widthHint = textWidth;
+               usernameT.setLayoutData(gd);
+
+               // new Label(this, SWT.NONE).setText(CmsMsg.password.lead());
+               passwordT = new Text(credentialsBlock, SWT.BORDER | SWT.PASSWORD);
+               passwordT.setMessage(password.lead(locale));
+               CmsSwtUtils.style(passwordT, CMS_LOGIN_DIALOG_PASSWORD);
+               gd = CmsSwtUtils.fillWidth();
+               gd.widthHint = textWidth;
+               passwordT.setLayoutData(gd);
+
+               TraverseListener tl = new TraverseListener() {
+                       private static final long serialVersionUID = -1158892811534971856L;
+
+                       public void keyTraversed(TraverseEvent e) {
+                               if (e.detail == SWT.TRAVERSE_RETURN)
+                                       login();
+                       }
+               };
+               credentialsBlock.addTraverseListener(tl);
+               usernameT.addTraverseListener(tl);
+               passwordT.addTraverseListener(tl);
+               parent.setTabList(new Control[] { credentialsBlock });
+               credentialsBlock.setTabList(new Control[] { usernameT, passwordT });
+
+               // Button
+               Button loginButton = new Button(credentialsBlock, SWT.PUSH);
+               loginButton.setText(CmsMsg.login.lead(locale));
+               loginButton.setLayoutData(CmsSwtUtils.fillWidth());
+               loginButton.addSelectionListener(loginSelectionListener);
+
+               extendsCredentialsBlock(credentialsBlock, locale, loginSelectionListener);
+               if (localeChoice != null)
+                       createLocalesBlock(credentialsBlock);
+               return credentialsBlock;
+       }
+
+       /**
+        * To be overridden in order to provide custom login button and other links.
+        */
+       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
+                       SelectionListener loginSelectionListener) {
+
+       }
+
+       protected void updateLocale(Locale selectedLocale) {
+               // save already entered values
+               String usernameStr = usernameT.getText();
+               char[] pwd = passwordT.getTextChars();
+
+               for (Control child : parent.getChildren())
+                       child.dispose();
+               createContents(parent);
+               if (parent.getParent() != null)
+                       parent.getParent().layout(true, true);
+               else
+                       parent.layout();
+               usernameT.setText(usernameStr);
+               passwordT.setTextChars(pwd);
+       }
+
+       protected Composite createLocalesBlock(final Composite parent) {
+               Composite c = new Composite(parent, SWT.NONE);
+               CmsSwtUtils.style(c, CMS_USER_MENU_ITEM);
+               c.setLayout(CmsSwtUtils.noSpaceGridLayout());
+               c.setLayoutData(CmsSwtUtils.fillAll());
+
+               SelectionListener selectionListener = new SelectionAdapter() {
+                       private static final long serialVersionUID = 4891637813567806762L;
+
+                       public void widgetSelected(SelectionEvent event) {
+                               Button button = (Button) event.widget;
+                               if (button.getSelection()) {
+                                       localeChoice.setSelectedIndex((Integer) event.widget.getData());
+                                       updateLocale(localeChoice.getSelectedLocale());
+                               }
+                       };
+               };
+
+               List<Locale> locales = localeChoice.getLocales();
+               for (Integer i = 0; i < locales.size(); i++) {
+                       Locale locale = locales.get(i);
+                       Button button = new Button(c, SWT.RADIO);
+                       CmsSwtUtils.style(button, CMS_USER_MENU_ITEM);
+                       button.setData(i);
+                       button.setText(LocaleUtils.toLead(locale.getDisplayName(locale), locale) + " (" + locale + ")");
+                       // button.addListener(SWT.Selection, listener);
+                       button.addSelectionListener(selectionListener);
+                       if (i == localeChoice.getSelectedIndex())
+                               button.setSelection(true);
+               }
+               return c;
+       }
+
+       protected boolean login() {
+               // TODO use CmsVie in order to retrieve subject?
+               // Subject subject = cmsView.getLoginContext().getSubject();
+               // LoginContext loginContext = cmsView.getLoginContext();
+               try {
+                       //
+                       // LOGIN
+                       //
+                       // loginContext.logout();
+                       LoginContext loginContext;
+                       if (subject == null)
+                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, this);
+                       else
+                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, this);
+                       loginContext.login();
+                       cmsView.authChange(loginContext);
+                       return true;
+               } catch (LoginException e) {
+                       if (log.isTraceEnabled())
+                               log.warn("Login failed: " + e.getMessage(), e);
+                       else
+                               log.warn("Login failed: " + e.getMessage());
+
+                       try {
+                               Thread.sleep(3000);
+                       } catch (InterruptedException e2) {
+                               // silent
+                       }
+                       // ErrorFeedback.show("Login failed", e);
+                       return false;
+               }
+               // catch (LoginException e) {
+               // log.error("Cannot login", e);
+               // return false;
+               // }
+       }
+
+       protected void logout() {
+               cmsView.logout();
+               cmsView.navigateTo("~");
+       }
+
+       @Override
+       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+               for (Callback callback : callbacks) {
+                       if (callback instanceof NameCallback && usernameT != null)
+                               ((NameCallback) callback).setName(usernameT.getText());
+                       else if (callback instanceof PasswordCallback && passwordT != null)
+                               ((PasswordCallback) callback).setPassword(passwordT.getTextChars());
+                       else if (callback instanceof HttpRequestCallback) {
+                               ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
+                               ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse());
+                       } else if (callback instanceof LanguageCallback) {
+                               Locale toUse = null;
+                               if (localeChoice != null)
+                                       toUse = localeChoice.getSelectedLocale();
+                               else if (defaultLocale != null)
+                                       toUse = defaultLocale;
+
+                               if (toUse != null) {
+                                       ((LanguageCallback) callback).setLocale(toUse);
+                                       UiContext.setLocale(toUse);
+                               }
+
+                       }
+               }
+       }
+
+       public void setSubject(Subject subject) {
+               this.subject = subject;
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLoginShell.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLoginShell.java
new file mode 100644 (file)
index 0000000..f6a35f1
--- /dev/null
@@ -0,0 +1,72 @@
+package org.argeo.cms.swt.auth;
+
+import org.argeo.api.cms.CmsView;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/** The site-related user menu */
+public class CmsLoginShell extends CmsLogin {
+       private final Shell shell;
+
+       public CmsLoginShell(CmsView cmsView) {
+               super(cmsView);
+               shell = createShell();
+//             createUi(shell);
+       }
+
+       /** To be overridden. */
+       protected Shell createShell() {
+               Shell shell = new Shell(Display.getCurrent(), SWT.NO_TRIM);
+               shell.setMaximized(true);
+               return shell;
+       }
+
+       /** To be overridden. */
+       public void open() {
+               CmsSwtUtils.style(shell, CMS_USER_MENU);
+               shell.open();
+       }
+
+       @Override
+       protected boolean login() {
+               boolean success = false;
+               try {
+                       success = super.login();
+                       return success;
+               } finally {
+                       if (success)
+                               closeShell();
+                       else {
+                               for (Control child : shell.getChildren())
+                                       child.dispose();
+                               createUi(shell);
+                               shell.layout();
+                               // TODO error message
+                       }
+               }
+       }
+
+       @Override
+       protected void logout() {
+               closeShell();
+               super.logout();
+       }
+
+       protected void closeShell() {
+               if (!shell.isDisposed()) {
+                       shell.close();
+                       shell.dispose();
+               }
+       }
+
+       public Shell getShell() {
+               return shell;
+       }
+       
+       public void createUi(){
+               createUi(shell);
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CompositeCallbackHandler.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CompositeCallbackHandler.java
new file mode 100644 (file)
index 0000000..495007c
--- /dev/null
@@ -0,0 +1,273 @@
+package org.argeo.cms.swt.auth;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * A composite that can populate itself based on {@link Callback}s. It can be
+ * used directly as a {@link CallbackHandler} or be used by one by calling the
+ * {@link #createCallbackHandlers(Callback[])}. Supported standard
+ * {@link Callback}s are:<br>
+ * <ul>
+ * <li>{@link PasswordCallback}</li>
+ * <li>{@link NameCallback}</li>
+ * <li>{@link TextOutputCallback}</li>
+ * </ul>
+ * Supported Argeo {@link Callback}s are:<br>
+ * <ul>
+ * <li>{@link LocaleChoice}</li>
+ * </ul>
+ */
+public class CompositeCallbackHandler extends Composite implements CallbackHandler {
+       private static final long serialVersionUID = -928223893722723777L;
+
+       private boolean wasUsedAlready = false;
+       private boolean isSubmitted = false;
+       private boolean isCanceled = false;
+
+       public CompositeCallbackHandler(Composite parent, int style) {
+               super(parent, style);
+       }
+
+       @Override
+       public synchronized void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+               // reset
+               if (wasUsedAlready && !isSubmitted() && !isCanceled()) {
+                       cancel();
+                       for (Control control : getChildren())
+                               control.dispose();
+                       isSubmitted = false;
+                       isCanceled = false;
+               }
+
+               for (Callback callback : callbacks)
+                       checkCallbackSupported(callback);
+               // create controls synchronously in the UI thread
+               getDisplay().syncExec(new Runnable() {
+
+                       @Override
+                       public void run() {
+                               createCallbackHandlers(callbacks);
+                       }
+               });
+
+               if (!wasUsedAlready)
+                       wasUsedAlready = true;
+
+               // while (!isSubmitted() && !isCanceled()) {
+               // try {
+               // wait(1000l);
+               // } catch (InterruptedException e) {
+               // // silent
+               // }
+               // }
+
+               // cleanCallbacksAfterCancel(callbacks);
+       }
+
+       public void checkCallbackSupported(Callback callback) throws UnsupportedCallbackException {
+               if (callback instanceof TextOutputCallback || callback instanceof NameCallback
+                               || callback instanceof PasswordCallback || callback instanceof LocaleChoice) {
+                       return;
+               } else {
+                       throw new UnsupportedCallbackException(callback);
+               }
+       }
+
+       /**
+        * Set writable callbacks to null if the handle is canceled (check is done
+        * by the method)
+        */
+       public void cleanCallbacksAfterCancel(Callback[] callbacks) {
+               if (isCanceled()) {
+                       for (Callback callback : callbacks) {
+                               if (callback instanceof NameCallback) {
+                                       ((NameCallback) callback).setName(null);
+                               } else if (callback instanceof PasswordCallback) {
+                                       PasswordCallback pCallback = (PasswordCallback) callback;
+                                       char[] arr = pCallback.getPassword();
+                                       if (arr != null) {
+                                               Arrays.fill(arr, '*');
+                                               pCallback.setPassword(null);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       public void createCallbackHandlers(Callback[] callbacks) {
+               Composite composite = this;
+               for (int i = 0; i < callbacks.length; i++) {
+                       Callback callback = callbacks[i];
+                       if (callback instanceof TextOutputCallback) {
+                               createLabelTextoutputHandler(composite, (TextOutputCallback) callback);
+                       } else if (callback instanceof NameCallback) {
+                               createNameHandler(composite, (NameCallback) callback);
+                       } else if (callback instanceof PasswordCallback) {
+                               createPasswordHandler(composite, (PasswordCallback) callback);
+                       } else if (callback instanceof LocaleChoice) {
+                               createLocaleHandler(composite, (LocaleChoice) callback);
+                       }
+               }
+       }
+
+       protected Text createNameHandler(Composite composite, final NameCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+               final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+               if (callback.getDefaultName() != null) {
+                       // set default value, if provided
+                       text.setText(callback.getDefaultName());
+                       callback.setName(callback.getDefaultName());
+               }
+               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               text.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = 7300032545287292973L;
+
+                       public void modifyText(ModifyEvent event) {
+                               callback.setName(text.getText());
+                       }
+               });
+               text.addSelectionListener(new SelectionListener() {
+                       private static final long serialVersionUID = 1820530045857665111L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                               submit();
+                       }
+               });
+
+               text.addKeyListener(new KeyListener() {
+                       private static final long serialVersionUID = -8698107785092095713L;
+
+                       @Override
+                       public void keyReleased(KeyEvent e) {
+                       }
+
+                       @Override
+                       public void keyPressed(KeyEvent e) {
+                       }
+               });
+               return text;
+       }
+
+       protected Text createPasswordHandler(Composite composite, final PasswordCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+               final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD | SWT.BORDER);
+               passwordText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               passwordText.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = -7099363995047686732L;
+
+                       public void modifyText(ModifyEvent event) {
+                               callback.setPassword(passwordText.getTextChars());
+                       }
+               });
+               passwordText.addSelectionListener(new SelectionListener() {
+                       private static final long serialVersionUID = 1820530045857665111L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                               submit();
+                       }
+               });
+               return passwordText;
+       }
+
+       protected Combo createLocaleHandler(Composite composite, final LocaleChoice callback) {
+               String[] labels = callback.getSupportedLocalesLabels();
+               if (labels.length == 0)
+                       return null;
+               Label label = new Label(composite, SWT.NONE);
+               label.setText("Language");
+
+               final Combo combo = new Combo(composite, SWT.READ_ONLY);
+               combo.setItems(labels);
+               combo.select(callback.getDefaultIndex());
+               combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               combo.addSelectionListener(new SelectionListener() {
+                       private static final long serialVersionUID = 38678989091946277L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               callback.setSelectedIndex(combo.getSelectionIndex());
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                       }
+               });
+               return combo;
+       }
+
+       protected Label createLabelTextoutputHandler(Composite composite, final TextOutputCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getMessage());
+               GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+               data.horizontalSpan = 2;
+               label.setLayoutData(data);
+               return label;
+               // TODO: find a way to pass this information
+               // int messageType = callback.getMessageType();
+               // int dialogMessageType = IMessageProvider.NONE;
+               // switch (messageType) {
+               // case TextOutputCallback.INFORMATION:
+               // dialogMessageType = IMessageProvider.INFORMATION;
+               // break;
+               // case TextOutputCallback.WARNING:
+               // dialogMessageType = IMessageProvider.WARNING;
+               // break;
+               // case TextOutputCallback.ERROR:
+               // dialogMessageType = IMessageProvider.ERROR;
+               // break;
+               // }
+               // setMessage(callback.getMessage(), dialogMessageType);
+       }
+
+       synchronized boolean isSubmitted() {
+               return isSubmitted;
+       }
+
+       synchronized boolean isCanceled() {
+               return isCanceled;
+       }
+
+       protected synchronized void submit() {
+               isSubmitted = true;
+               notifyAll();
+       }
+
+       protected synchronized void cancel() {
+               isCanceled = true;
+               notifyAll();
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/DynamicCallbackHandler.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/DynamicCallbackHandler.java
new file mode 100644 (file)
index 0000000..b0c36c6
--- /dev/null
@@ -0,0 +1,34 @@
+package org.argeo.cms.swt.auth;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.argeo.eclipse.ui.dialogs.LightweightDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class DynamicCallbackHandler implements CallbackHandler {
+
+       @Override
+       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+               Shell activeShell = Display.getCurrent().getActiveShell();
+               LightweightDialog dialog = new LightweightDialog(activeShell) {
+
+                       @Override
+                       protected Control createDialogArea(Composite parent) {
+                               CompositeCallbackHandler cch = new CompositeCallbackHandler(parent, SWT.NONE);
+                               cch.createCallbackHandlers(callbacks);
+                               return cch;
+                       }
+               };
+               dialog.setBlockOnOpen(true);
+               dialog.open();
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/LocaleChoice.java
new file mode 100644 (file)
index 0000000..e98e390
--- /dev/null
@@ -0,0 +1,86 @@
+package org.argeo.cms.swt.auth;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+import javax.security.auth.callback.LanguageCallback;
+
+import org.argeo.cms.CmsException;
+import org.argeo.cms.LocaleUtils;
+
+/** Choose in a list of locales. TODO: replace with {@link LanguageCallback} */
+public class LocaleChoice {
+       private final List<Locale> locales;
+
+       private Integer selectedIndex = null;
+       private final Integer defaultIndex;
+
+       public LocaleChoice(List<Locale> locales, Locale defaultLocale) {
+               Integer defaultIndex = null;
+               this.locales = Collections.unmodifiableList(locales);
+               for (int i = 0; i < locales.size(); i++)
+                       if (locales.get(i).equals(defaultLocale))
+                               defaultIndex = i;
+
+               // based on language only
+               if (defaultIndex == null)
+                       for (int i = 0; i < locales.size(); i++)
+                               if (locales.get(i).getLanguage().equals(defaultLocale.getLanguage()))
+                                       defaultIndex = i;
+
+               if (defaultIndex == null)
+                       throw new CmsException("Default locale " + defaultLocale + " is not in available locales " + locales);
+               this.defaultIndex = defaultIndex;
+
+               this.selectedIndex = defaultIndex;
+       }
+
+       /**
+        * Convenience constructor based on a comma separated list of iso codes (en,
+        * en_US, fr_CA, etc.). Default selection is default locale.
+        */
+       public LocaleChoice(String locales, Locale defaultLocale) {
+               this(LocaleUtils.asLocaleList(locales), defaultLocale);
+       }
+
+       public String[] getSupportedLocalesLabels() {
+               String[] labels = new String[locales.size()];
+               for (int i = 0; i < locales.size(); i++) {
+                       Locale locale = locales.get(i);
+                       if (locale.getCountry().equals(""))
+                               labels[i] = locale.getDisplayLanguage(locale) + " [" + locale.getLanguage() + "]";
+                       else
+                               labels[i] = locale.getDisplayLanguage(locale) + " (" + locale.getDisplayCountry(locale) + ") ["
+                                               + locale.getLanguage() + "_" + locale.getCountry() + "]";
+
+               }
+               return labels;
+       }
+
+       public Locale getSelectedLocale() {
+               if (selectedIndex == null)
+                       return null;
+               return locales.get(selectedIndex);
+       }
+
+       public void setSelectedIndex(Integer selectedIndex) {
+               this.selectedIndex = selectedIndex;
+       }
+
+       public Integer getSelectedIndex() {
+               return selectedIndex;
+       }
+
+       public Integer getDefaultIndex() {
+               return defaultIndex;
+       }
+
+       public List<Locale> getLocales() {
+               return locales;
+       }
+
+       public Locale getDefaultLocale() {
+               return locales.get(getDefaultIndex());
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/package-info.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/package-info.java
new file mode 100644 (file)
index 0000000..b431423
--- /dev/null
@@ -0,0 +1,2 @@
+/** Argeo CMS authentication widgets, based on SWT. */
+package org.argeo.cms.swt.auth;
\ No newline at end of file
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/ChangePasswordDialog.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/ChangePasswordDialog.java
new file mode 100644 (file)
index 0000000..2cf0c8c
--- /dev/null
@@ -0,0 +1,84 @@
+package org.argeo.cms.swt.dialogs;
+
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.api.cms.CmsView;
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.CmsUserManager;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** Dialog to change a password. */
+public class ChangePasswordDialog extends CmsMessageDialog {
+       private final static Log log = LogFactory.getLog(ChangePasswordDialog.class);
+
+       private CmsUserManager cmsUserManager;
+       private CmsView cmsView;
+
+       private PrivilegedAction<Integer> doIt;
+
+       public ChangePasswordDialog(Shell parentShell, String message, int kind, CmsUserManager cmsUserManager) {
+               super(parentShell, message, kind);
+               this.cmsUserManager = cmsUserManager;
+               cmsView = CmsSwtUtils.getCmsView(parentShell);
+       }
+
+       @Override
+       protected Control createInputArea(Composite userSection) {
+               addFormLabel(userSection, CmsMsg.currentPassword.lead());
+               Text previousPassword = new Text(userSection, SWT.BORDER | SWT.PASSWORD);
+               previousPassword.setLayoutData(CmsSwtUtils.fillWidth());
+               addFormLabel(userSection, CmsMsg.newPassword.lead());
+               Text newPassword = new Text(userSection, SWT.BORDER | SWT.PASSWORD);
+               newPassword.setLayoutData(CmsSwtUtils.fillWidth());
+               addFormLabel(userSection, CmsMsg.repeatNewPassword.lead());
+               Text confirmPassword = new Text(userSection, SWT.BORDER | SWT.PASSWORD);
+               confirmPassword.setLayoutData(CmsSwtUtils.fillWidth());
+
+               doIt = () -> {
+                       if (Arrays.equals(newPassword.getTextChars(), confirmPassword.getTextChars())) {
+                               try {
+                                       cmsUserManager.changeOwnPassword(previousPassword.getTextChars(), newPassword.getTextChars());
+                                       return OK;
+                               } catch (Exception e1) {
+                                       log.error("Could not change password", e1);
+                                       cancel();
+                                       CmsMessageDialog.openError(CmsMsg.invalidPassword.lead());
+                                       return CANCEL;
+                               }
+                       } else {
+                               cancel();
+                               CmsMessageDialog.openError(CmsMsg.repeatNewPassword.lead());
+                               return CANCEL;
+                       }
+               };
+
+               pack();
+               return previousPassword;
+       }
+
+       @Override
+       protected void okPressed() {
+               Integer returnCode = cmsView.doAs(doIt);
+               if (returnCode.equals(OK)) {
+                       super.okPressed();
+                       CmsMessageDialog.openInformation(CmsMsg.passwordChanged.lead());
+               }
+       }
+
+       private static Label addFormLabel(Composite parent, String label) {
+               Label lbl = new Label(parent, SWT.WRAP);
+               lbl.setText(label);
+//             CmsUiUtils.style(lbl, SuiteStyle.simpleLabel);
+               return lbl;
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsFeedback.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsFeedback.java
new file mode 100644 (file)
index 0000000..5128298
--- /dev/null
@@ -0,0 +1,101 @@
+package org.argeo.cms.swt.dialogs;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.swt.Selected;
+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.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** A dialog feedback based on a {@link LightweightDialog}. */
+public class CmsFeedback extends LightweightDialog {
+       private final static Log log = LogFactory.getLog(CmsFeedback.class);
+
+       private String message;
+       private Throwable exception;
+
+       public CmsFeedback(Shell parentShell, String message, Throwable e) {
+               super(parentShell);
+               this.message = message;
+               this.exception = e;
+               log.error(message, e);
+       }
+
+       public static CmsFeedback show(String message, Throwable e) {
+               // rethrow ThreaDeath in order to make sure that RAP will properly clean
+               // up the UI thread
+               if (e instanceof ThreadDeath)
+                       throw (ThreadDeath) e;
+
+               try {
+                       CmsFeedback cmsFeedback = new CmsFeedback(null, message, e);
+                       cmsFeedback.setBlockOnOpen(false);
+                       cmsFeedback.open();
+                       return cmsFeedback;
+               } catch (Throwable e1) {
+                       log.error("Cannot open error feedback (" + e.getMessage() + "), original error below", e);
+                       return null;
+               }
+       }
+
+       public static CmsFeedback show(String message) {
+               CmsFeedback cmsFeedback = new CmsFeedback(null, message, null);
+               cmsFeedback.open();
+               return cmsFeedback;
+       }
+
+       /** Tries to find a display */
+       // private static Display getDisplay() {
+       // try {
+       // Display display = Display.getCurrent();
+       // if (display != null)
+       // return display;
+       // else
+       // return Display.getDefault();
+       // } catch (Exception e) {
+       // return Display.getCurrent();
+       // }
+       // }
+
+       protected Control createDialogArea(Composite parent) {
+               parent.setLayout(new GridLayout(2, false));
+
+               Label messageLbl = new Label(parent, SWT.WRAP);
+               if (message != null)
+                       messageLbl.setText(message);
+               else if (exception != null)
+                       messageLbl.setText(exception.getLocalizedMessage());
+
+               Button close = new Button(parent, SWT.FLAT);
+               close.setText(CmsMsg.close.lead());
+               close.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false));
+               close.addSelectionListener((Selected) (e) -> closeShell(OK));
+
+               // Composite composite = new Composite(dialogarea, SWT.NONE);
+               // composite.setLayout(new GridLayout(2, false));
+               // composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               if (exception != null) {
+                       Text stack = new Text(parent, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+                       stack.setEditable(false);
+                       stack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+                       StringWriter sw = new StringWriter();
+                       exception.printStackTrace(new PrintWriter(sw));
+                       stack.setText(sw.toString());
+               }
+
+               // parent.pack();
+               return messageLbl;
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsMessageDialog.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsMessageDialog.java
new file mode 100644 (file)
index 0000000..66e6405
--- /dev/null
@@ -0,0 +1,167 @@
+package org.argeo.cms.swt.dialogs;
+
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.Selected;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Point;
+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.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/** Base class for dialogs displaying messages or small forms. */
+public class CmsMessageDialog extends LightweightDialog {
+       public final static int NONE = 0;
+       public final static int ERROR = 1;
+       public final static int INFORMATION = 2;
+       public final static int QUESTION = 3;
+       public final static int WARNING = 4;
+       public final static int CONFIRM = 5;
+       public final static int QUESTION_WITH_CANCEL = 6;
+
+       private int kind;
+       private String message;
+
+       public CmsMessageDialog(Shell parentShell, String message, int kind) {
+               super(parentShell);
+               this.kind = kind;
+               this.message = message;
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               parent.setLayout(new GridLayout());
+
+               TraverseListener traverseListener = new TraverseListener() {
+                       private static final long serialVersionUID = -1158892811534971856L;
+
+                       public void keyTraversed(TraverseEvent e) {
+                               if (e.detail == SWT.TRAVERSE_RETURN)
+                                       okPressed();
+                               else if (e.detail == SWT.TRAVERSE_ESCAPE)
+                                       cancelPressed();
+                       }
+               };
+
+               // message
+               Composite body = new Composite(parent, SWT.NONE);
+               body.addTraverseListener(traverseListener);
+               GridLayout bodyGridLayout = new GridLayout();
+               bodyGridLayout.marginHeight = 20;
+               bodyGridLayout.marginWidth = 20;
+               body.setLayout(bodyGridLayout);
+               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               if (message != null) {
+                       Label messageLbl = new Label(body, SWT.WRAP);
+                       CmsSwtUtils.markup(messageLbl);
+                       messageLbl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+                       messageLbl.setFont(EclipseUiUtils.getBoldFont(parent));
+                       messageLbl.setText(message);
+               }
+
+               // buttons
+               Composite buttons = new Composite(parent, SWT.NONE);
+               buttons.addTraverseListener(traverseListener);
+               buttons.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
+               if (kind == INFORMATION || kind == WARNING || kind == ERROR || kind == ERROR) {
+                       GridLayout layout = new GridLayout(1, true);
+                       layout.marginWidth = 0;
+                       layout.marginHeight = 0;
+                       buttons.setLayout(layout);
+
+                       Button close = new Button(buttons, SWT.FLAT);
+                       close.setText(CmsMsg.close.lead());
+                       close.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+                       close.addSelectionListener((Selected) (e) -> closeShell(OK));
+                       close.setFocus();
+                       close.addTraverseListener(traverseListener);
+
+                       buttons.setTabList(new Control[] { close });
+               } else if (kind == CONFIRM || kind == QUESTION || kind == QUESTION_WITH_CANCEL) {
+                       Control input = createInputArea(body);
+                       if (input != null) {
+                               input.addTraverseListener(traverseListener);
+                               body.setTabList(new Control[] { input });
+                       }
+                       GridLayout layout = new GridLayout(2, true);
+                       layout.marginWidth = 0;
+                       layout.marginHeight = 0;
+                       buttons.setLayout(layout);
+
+                       Button cancel = new Button(buttons, SWT.FLAT);
+                       cancel.setText(CmsMsg.cancel.lead());
+                       cancel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+                       cancel.addSelectionListener((Selected) (e) -> cancelPressed());
+                       cancel.addTraverseListener(traverseListener);
+
+                       Button ok = new Button(buttons, SWT.FLAT);
+                       ok.setText(CmsMsg.ok.lead());
+                       ok.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+                       ok.addSelectionListener((Selected) (e) -> okPressed());
+                       ok.addTraverseListener(traverseListener);
+                       if (input == null)
+                               ok.setFocus();
+                       else
+                               input.setFocus();
+
+                       buttons.setTabList(new Control[] { ok, cancel });
+               }
+               // pack();
+               parent.setTabList(new Control[] { body, buttons });
+               return body;
+       }
+
+       protected Control createInputArea(Composite parent) {
+               return null;
+       }
+
+       protected void okPressed() {
+               closeShell(OK);
+       }
+
+       protected void cancelPressed() {
+               closeShell(CANCEL);
+       }
+
+       protected void cancel() {
+               closeShell(CANCEL);
+       }
+
+       protected Point getInitialSize() {
+               return new Point(400, 200);
+       }
+
+       public static boolean open(int kind, Shell parent, String message) {
+               CmsMessageDialog dialog = new CmsMessageDialog(parent, message, kind);
+               return dialog.open() == 0;
+       }
+
+       public static boolean openConfirm(String message) {
+               return open(CONFIRM, Display.getCurrent().getActiveShell(), message);
+       }
+
+       public static void openInformation(String message) {
+               open(INFORMATION, Display.getCurrent().getActiveShell(), message);
+       }
+
+       public static boolean openQuestion(String message) {
+               return open(QUESTION, Display.getCurrent().getActiveShell(), message);
+       }
+
+       public static void openWarning(String message) {
+               open(WARNING, Display.getCurrent().getActiveShell(), message);
+       }
+
+       public static void openError(String message) {
+               open(ERROR, Display.getCurrent().getActiveShell(), message);
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsWizardDialog.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsWizardDialog.java
new file mode 100644 (file)
index 0000000..59d9ab7
--- /dev/null
@@ -0,0 +1,220 @@
+package org.argeo.cms.swt.dialogs;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.argeo.cms.CmsMsg;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.Selected;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.IWizardContainer2;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+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.eclipse.swt.widgets.Shell;
+
+/** A wizard dialog based on {@link LightweightDialog}. */
+public class CmsWizardDialog extends LightweightDialog implements IWizardContainer2 {
+       private static final long serialVersionUID = -2123153353654812154L;
+
+       private IWizard wizard;
+       private IWizardPage currentPage;
+       private int currentPageIndex;
+
+       private Label titleBar;
+       private Label message;
+       private Composite[] pageBodies;
+       private Composite buttons;
+       private Button back;
+       private Button next;
+       private Button finish;
+
+       public CmsWizardDialog(Shell parentShell, IWizard wizard) {
+               super(parentShell);
+               this.wizard = wizard;
+               wizard.setContainer(this);
+               // create the pages
+               wizard.addPages();
+               currentPage = wizard.getStartingPage();
+               if (currentPage == null)
+                       throw new IllegalArgumentException("At least one wizard page is required");
+       }
+
+       @Override
+       protected Control createDialogArea(Composite parent) {
+               updateWindowTitle();
+
+               Composite messageArea = new Composite(parent, SWT.NONE);
+               messageArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               {
+                       messageArea.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(2, false)));
+                       titleBar = new Label(messageArea, SWT.WRAP);
+                       titleBar.setFont(EclipseUiUtils.getBoldFont(parent));
+                       titleBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
+                       updateTitleBar();
+                       Button cancelButton = new Button(messageArea, SWT.FLAT);
+                       cancelButton.setText(CmsMsg.cancel.lead());
+                       cancelButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false, 1, 3));
+                       cancelButton.addSelectionListener((Selected) (e) -> closeShell(CANCEL));
+                       message = new Label(messageArea, SWT.WRAP);
+                       message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 2));
+                       updateMessage();
+               }
+
+               Composite body = new Composite(parent, SWT.BORDER);
+               body.setLayout(new FormLayout());
+               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               pageBodies = new Composite[wizard.getPageCount()];
+               IWizardPage[] pages = wizard.getPages();
+               for (int i = 0; i < pages.length; i++) {
+                       pageBodies[i] = new Composite(body, SWT.NONE);
+                       pageBodies[i].setLayout(CmsSwtUtils.noSpaceGridLayout());
+                       setSwitchingFormData(pageBodies[i]);
+                       pages[i].createControl(pageBodies[i]);
+               }
+               showPage(currentPage);
+
+               buttons = new Composite(parent, SWT.NONE);
+               buttons.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
+               {
+                       boolean singlePage = wizard.getPageCount() == 1;
+                       // singlePage = false;// dev
+                       GridLayout layout = new GridLayout(singlePage ? 1 : 3, true);
+                       layout.marginWidth = 0;
+                       layout.marginHeight = 0;
+                       buttons.setLayout(layout);
+                       // TODO revert order for right-to-left languages
+
+                       if (!singlePage) {
+                               back = new Button(buttons, SWT.PUSH);
+                               back.setText(CmsMsg.wizardBack.lead());
+                               back.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+                               back.addSelectionListener((Selected) (e) -> backPressed());
+
+                               next = new Button(buttons, SWT.PUSH);
+                               next.setText(CmsMsg.wizardNext.lead());
+                               next.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+                               next.addSelectionListener((Selected) (e) -> nextPressed());
+                       }
+                       finish = new Button(buttons, SWT.PUSH);
+                       finish.setText(CmsMsg.wizardFinish.lead());
+                       finish.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+                       finish.addSelectionListener((Selected) (e) -> finishPressed());
+
+                       updateButtons();
+               }
+               return body;
+       }
+
+       @Override
+       public IWizardPage getCurrentPage() {
+               return currentPage;
+       }
+
+       @Override
+       public Shell getShell() {
+               return getForegoundShell();
+       }
+
+       @Override
+       public void showPage(IWizardPage page) {
+               IWizardPage[] pages = wizard.getPages();
+               int index = -1;
+               for (int i = 0; i < pages.length; i++) {
+                       if (page == pages[i]) {
+                               index = i;
+                               break;
+                       }
+               }
+               if (index < 0)
+                       throw new IllegalArgumentException("Cannot find index of wizard page " + page);
+               pageBodies[index].moveAbove(pageBodies[currentPageIndex]);
+
+               // // clear
+               // for (Control c : body.getChildren())
+               // c.dispose();
+               // page.createControl(body);
+               // body.layout(true, true);
+               currentPageIndex = index;
+               currentPage = page;
+       }
+
+       @Override
+       public void updateButtons() {
+               if (back != null)
+                       back.setEnabled(wizard.getPreviousPage(currentPage) != null);
+               if (next != null)
+                       next.setEnabled(wizard.getNextPage(currentPage) != null && currentPage.canFlipToNextPage());
+               if (finish != null) {
+                       finish.setEnabled(wizard.canFinish());
+               }
+       }
+
+       @Override
+       public void updateMessage() {
+               if (currentPage.getMessage() != null)
+                       message.setText(currentPage.getMessage());
+       }
+
+       @Override
+       public void updateTitleBar() {
+               if (currentPage.getTitle() != null)
+                       titleBar.setText(currentPage.getTitle());
+       }
+
+       @Override
+       public void updateWindowTitle() {
+               setTitle(wizard.getWindowTitle());
+       }
+
+       @Override
+       public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
+                       throws InvocationTargetException, InterruptedException {
+               runnable.run(null);
+       }
+
+       @Override
+       public void updateSize() {
+               // TODO pack?
+       }
+
+       protected boolean onCancel() {
+               return wizard.performCancel();
+       }
+
+       protected void nextPressed() {
+               IWizardPage page = wizard.getNextPage(currentPage);
+               showPage(page);
+               updateButtons();
+       }
+
+       protected void backPressed() {
+               IWizardPage page = wizard.getPreviousPage(currentPage);
+               showPage(page);
+               updateButtons();
+       }
+
+       protected void finishPressed() {
+               if (wizard.performFinish())
+                       closeShell(OK);
+       }
+
+       private static void setSwitchingFormData(Composite composite) {
+               FormData fdLabel = new FormData();
+               fdLabel.top = new FormAttachment(0, 0);
+               fdLabel.left = new FormAttachment(0, 0);
+               fdLabel.right = new FormAttachment(100, 0);
+               fdLabel.bottom = new FormAttachment(100, 0);
+               composite.setLayoutData(fdLabel);
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/LightweightDialog.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/LightweightDialog.java
new file mode 100644 (file)
index 0000000..2f00a37
--- /dev/null
@@ -0,0 +1,256 @@
+package org.argeo.cms.swt.dialogs;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/** Generic lightweight dialog, not based on JFace. */
+public class LightweightDialog {
+       private final static Log log = LogFactory.getLog(LightweightDialog.class);
+
+       // must be the same value as org.eclipse.jface.window.Window#OK
+       public final static int OK = 0;
+       // must be the same value as org.eclipse.jface.window.Window#CANCEL
+       public final static int CANCEL = 1;
+
+       private Shell parentShell;
+       private Shell backgroundShell;
+       private Shell foregoundShell;
+
+       private Integer returnCode = null;
+       private boolean block = true;
+
+       private String title;
+
+       /** Tries to find a display */
+       private static Display getDisplay() {
+               try {
+                       Display display = Display.getCurrent();
+                       if (display != null)
+                               return display;
+                       else
+                               return Display.getDefault();
+               } catch (Exception e) {
+                       return Display.getCurrent();
+               }
+       }
+
+       public LightweightDialog(Shell parentShell) {
+               this.parentShell = parentShell;
+       }
+
+       public int open() {
+               if (foregoundShell != null)
+                       throw new EclipseUiException("There is already a shell");
+               backgroundShell = new Shell(parentShell, SWT.ON_TOP);
+               backgroundShell.setFullScreen(true);
+               // if (parentShell != null) {
+               // backgroundShell.setBounds(parentShell.getBounds());
+               // } else
+               // backgroundShell.setMaximized(true);
+               backgroundShell.setAlpha(128);
+               backgroundShell.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
+               foregoundShell = new Shell(backgroundShell, SWT.NO_TRIM | SWT.ON_TOP);
+               if (title != null)
+                       setTitle(title);
+               foregoundShell.setLayout(new GridLayout());
+               foregoundShell.setSize(getInitialSize());
+               createDialogArea(foregoundShell);
+               // shell.pack();
+               // shell.layout();
+
+               Rectangle shellBounds = parentShell != null ? parentShell.getBounds() : Display.getCurrent().getBounds();// RAP
+               Point dialogSize = foregoundShell.getSize();
+               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
+               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
+               foregoundShell.setLocation(x, y);
+
+               foregoundShell.addShellListener(new ShellAdapter() {
+                       private static final long serialVersionUID = -2701270481953688763L;
+
+                       @Override
+                       public void shellDeactivated(ShellEvent e) {
+                               if (hasChildShells())
+                                       return;
+                               if (returnCode == null)// not yet closed
+                                       closeShell(CANCEL);
+                       }
+
+                       @Override
+                       public void shellClosed(ShellEvent e) {
+                               notifyClose();
+                       }
+
+               });
+
+               backgroundShell.open();
+               foregoundShell.open();
+               // after the foreground shell has been opened
+               backgroundShell.addFocusListener(new FocusListener() {
+                       private static final long serialVersionUID = 3137408447474661070L;
+
+                       @Override
+                       public void focusLost(FocusEvent event) {
+                       }
+
+                       @Override
+                       public void focusGained(FocusEvent event) {
+                               if (hasChildShells())
+                                       return;
+                               if (returnCode == null)// not yet closed
+                                       closeShell(CANCEL);
+                       }
+               });
+
+               if (block) {
+                       block();
+               }
+               if (returnCode == null)
+                       returnCode = OK;
+               return returnCode;
+       }
+
+       public void block() {
+               try {
+                       runEventLoop(foregoundShell);
+               } catch (ThreadDeath t) {
+                       returnCode = CANCEL;
+                       if (log.isTraceEnabled())
+                               log.error("Thread death, canceling dialog", t);
+               } catch (Throwable t) {
+                       returnCode = CANCEL;
+                       log.error("Cannot open blocking lightweight dialog", t);
+               }
+       }
+
+       private boolean hasChildShells() {
+               if (foregoundShell == null)
+                       return false;
+               return foregoundShell.getShells().length != 0;
+       }
+
+       // public synchronized int openAndWait() {
+       // open();
+       // while (returnCode == null)
+       // try {
+       // wait(100);
+       // } catch (InterruptedException e) {
+       // // silent
+       // }
+       // return returnCode;
+       // }
+
+       private synchronized void notifyClose() {
+               if (returnCode == null)
+                       returnCode = CANCEL;
+               notifyAll();
+       }
+
+       protected void closeShell(int returnCode) {
+               this.returnCode = returnCode;
+               if (CANCEL == returnCode)
+                       onCancel();
+               if (foregoundShell != null && !foregoundShell.isDisposed()) {
+                       foregoundShell.close();
+                       foregoundShell.dispose();
+                       foregoundShell = null;
+               }
+
+               if (backgroundShell != null && !backgroundShell.isDisposed()) {
+                       backgroundShell.close();
+                       backgroundShell.dispose();
+               }
+       }
+
+       protected Point getInitialSize() {
+               // if (exception != null)
+               // return new Point(800, 600);
+               // else
+               return new Point(600, 400);
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite dialogarea = new Composite(parent, SWT.NONE);
+               dialogarea.setLayout(new GridLayout());
+               dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               return dialogarea;
+       }
+
+       protected Shell getBackgroundShell() {
+               return backgroundShell;
+       }
+
+       protected Shell getForegoundShell() {
+               return foregoundShell;
+       }
+
+       public void setBlockOnOpen(boolean shouldBlock) {
+               block = shouldBlock;
+       }
+
+       public void pack() {
+               foregoundShell.pack();
+       }
+
+       private void runEventLoop(Shell loopShell) {
+               Display display;
+               if (foregoundShell == null) {
+                       display = Display.getCurrent();
+               } else {
+                       display = loopShell.getDisplay();
+               }
+
+               while (loopShell != null && !loopShell.isDisposed()) {
+                       try {
+                               if (!display.readAndDispatch()) {
+                                       display.sleep();
+                               }
+                       } catch (UnsupportedOperationException e) {
+                               throw e;
+                       } catch (Throwable e) {
+                               handleException(e);
+                       }
+               }
+               if (!display.isDisposed())
+                       display.update();
+       }
+
+       protected void handleException(Throwable t) {
+               if (t instanceof ThreadDeath) {
+                       // Don't catch ThreadDeath as this is a normal occurrence when
+                       // the thread dies
+                       throw (ThreadDeath) t;
+               }
+               // Try to keep running.
+               t.printStackTrace();
+       }
+
+       /** @return false, if the dialog should not be closed. */
+       protected boolean onCancel() {
+               return true;
+       }
+
+       public void setTitle(String title) {
+               this.title = title;
+               if (title != null && getForegoundShell() != null)
+                       getForegoundShell().setText(title);
+       }
+
+       public Integer getReturnCode() {
+               return returnCode;
+       }
+
+}
\ No newline at end of file
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/SingleValueDialog.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/SingleValueDialog.java
new file mode 100644 (file)
index 0000000..9404b81
--- /dev/null
@@ -0,0 +1,82 @@
+package org.argeo.cms.swt.dialogs;
+
+import org.eclipse.jface.window.Window;
+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.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** A dialog asking a for a single value. */
+public class SingleValueDialog extends CmsMessageDialog {
+       private Text valueT;
+       private String value;
+       private String defaultValue;
+
+       public SingleValueDialog(Shell parentShell, String message) {
+               super(parentShell, message, QUESTION);
+       }
+
+       public SingleValueDialog(Shell parentShell, String message, String defaultValue) {
+               super(parentShell, message, QUESTION);
+               this.defaultValue = defaultValue;
+       }
+
+       @Override
+       protected Control createInputArea(Composite parent) {
+               valueT = new Text(parent, SWT.LEAD | SWT.BORDER | SWT.SINGLE);
+               valueT.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
+               if (defaultValue != null)
+                       valueT.setText(defaultValue);
+               return valueT;
+       }
+
+       @Override
+       protected void okPressed() {
+               value = valueT.getText();
+               super.okPressed();
+       }
+
+       public String getString() {
+               return value;
+       }
+
+       public Long getLong() {
+               return Long.valueOf(getString());
+       }
+
+       public Double getDouble() {
+               return Double.valueOf(getString());
+       }
+
+       public static String ask(String message) {
+               return ask(message, null);
+       }
+
+       public static String ask(String message, String defaultValue) {
+               SingleValueDialog svd = new SingleValueDialog(Display.getCurrent().getActiveShell(), message, defaultValue);
+               if (svd.open() == Window.OK)
+                       return svd.getString();
+               else
+                       return null;
+       }
+
+       public static Long askLong(String message) {
+               SingleValueDialog svd = new SingleValueDialog(Display.getCurrent().getActiveShell(), message);
+               if (svd.open() == Window.OK)
+                       return svd.getLong();
+               else
+                       return null;
+       }
+
+       public static Double askDouble(String message) {
+               SingleValueDialog svd = new SingleValueDialog(Display.getCurrent().getActiveShell(), message);
+               if (svd.open() == Window.OK)
+                       return svd.getDouble();
+               else
+                       return null;
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/package-info.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/package-info.java
new file mode 100644 (file)
index 0000000..ac76dba
--- /dev/null
@@ -0,0 +1,2 @@
+/** SWT/JFace dialogs. */
+package org.argeo.cms.swt.dialogs;
\ No newline at end of file
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/osgi/BundleCmsSwtTheme.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/osgi/BundleCmsSwtTheme.java
new file mode 100644 (file)
index 0000000..b9b2751
--- /dev/null
@@ -0,0 +1,93 @@
+package org.argeo.cms.swt.osgi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.argeo.cms.osgi.BundleCmsTheme;
+import org.argeo.cms.swt.CmsSwtTheme;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.widgets.Display;
+
+/** Centralises some generic {@link CmsSwtTheme} patterns. */
+public class BundleCmsSwtTheme extends BundleCmsTheme implements CmsSwtTheme {
+       private Map<String, ImageData> imageCache = new HashMap<>();
+
+       private Map<String, Map<Integer, String>> iconPaths = new HashMap<>();
+
+       public Image getImage(String path) {
+               if (!imageCache.containsKey(path)) {
+                       try (InputStream in = getResourceAsStream(path)) {
+                               if (in == null)
+                                       return null;
+                               ImageData imageData = new ImageData(in);
+                               imageCache.put(path, imageData);
+                       } catch (IOException e) {
+                               throw new IllegalStateException(e);
+                       }
+               }
+               ImageData imageData = imageCache.get(path);
+               Image image = new Image(Display.getCurrent(), imageData);
+               return image;
+       }
+
+       /**
+        * And icon with this file name (without the extension), with a best effort to
+        * find the appropriate size, or <code>null</code> if not found.
+        * 
+        * @param name          An icon file name without path and extension.
+        * @param preferredSize the preferred size, if <code>null</code>,
+        *                      {@link #getDefaultIconSize()} will be tried.
+        */
+       public Image getIcon(String name, Integer preferredSize) {
+               if (preferredSize == null)
+                       preferredSize = getDefaultIconSize();
+               Map<Integer, String> subCache;
+               if (!iconPaths.containsKey(name))
+                       subCache = new HashMap<>();
+               else
+                       subCache = iconPaths.get(name);
+               Image image = null;
+               if (!subCache.containsKey(preferredSize)) {
+                       Image bestMatchSoFar = null;
+                       paths: for (String p : getImagesPaths()) {
+                               int lastSlash = p.lastIndexOf('/');
+                               String fileName = p;
+                               if (lastSlash >= 0)
+                                       fileName = p.substring(lastSlash + 1);
+                               int lastDot = fileName.lastIndexOf('.');
+                               if (lastDot >= 0)
+                                       fileName = fileName.substring(0, lastDot);
+                               if (fileName.equals(name)) {// matched
+                                       Image img = getImage(p);
+                                       int width = img.getBounds().width;
+                                       if (width == preferredSize) {// perfect match
+                                               subCache.put(preferredSize, p);
+                                               image = img;
+                                               break paths;
+                                       }
+                                       if (bestMatchSoFar == null) {
+                                               bestMatchSoFar = img;
+                                       } else {
+                                               if (Math.abs(width - preferredSize) < Math
+                                                               .abs(bestMatchSoFar.getBounds().width - preferredSize))
+                                                       bestMatchSoFar = img;
+                                       }
+                               }
+                       }
+
+                       if (image == null)
+                               image = bestMatchSoFar;
+               } else {
+                       image = getImage(subCache.get(preferredSize));
+               }
+
+               if (image != null && !iconPaths.containsKey(name))
+                       iconPaths.put(name, subCache);
+
+               return image;
+       }
+
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/PickUpUserDialog.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/PickUpUserDialog.java
new file mode 100644 (file)
index 0000000..6f5aa9d
--- /dev/null
@@ -0,0 +1,246 @@
+package org.argeo.cms.swt.useradmin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.argeo.api.NodeConstants;
+import org.argeo.eclipse.ui.ColumnDefinition;
+import org.argeo.eclipse.ui.EclipseUiException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.parts.LdifUsersTable;
+import org.argeo.naming.LdapAttrs;
+import org.argeo.naming.LdapObjs;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.FillLayout;
+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.Shell;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/** Dialog with a user (or group) list to pick up one */
+public class PickUpUserDialog extends TrayDialog {
+       private static final long serialVersionUID = -1420106871173920369L;
+
+       // Business objects
+       private final UserAdmin userAdmin;
+       private User selectedUser;
+
+       // this page widgets and UI objects
+       private String title;
+       private LdifUsersTable userTableViewerCmp;
+       private TableViewer userViewer;
+       private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+
+       /**
+        * A dialog to pick up a group or a user, showing a table with default
+        * columns
+        */
+       public PickUpUserDialog(Shell parentShell, String title, UserAdmin userAdmin) {
+               super(parentShell);
+               this.title = title;
+               this.userAdmin = userAdmin;
+
+               columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_ICON), "",
+                               24, 24));
+               columnDefs.add(new ColumnDefinition(
+                               new UserLP(UserLP.COL_DISPLAY_NAME), "Common Name", 150, 100));
+               columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_DOMAIN),
+                               "Domain", 100, 120));
+               columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_DN),
+                               "Distinguished Name", 300, 100));
+       }
+
+       /** A dialog to pick up a group or a user */
+       public PickUpUserDialog(Shell parentShell, String title,
+                       UserAdmin userAdmin, List<ColumnDefinition> columnDefs) {
+               super(parentShell);
+               this.title = title;
+               this.userAdmin = userAdmin;
+               this.columnDefs = columnDefs;
+       }
+
+       @Override
+       protected void okPressed() {
+               if (getSelected() == null)
+                       MessageDialog.openError(getShell(), "No user chosen",
+                                       "Please, choose a user or press Cancel.");
+               else
+                       super.okPressed();
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite dialogArea = (Composite) super.createDialogArea(parent);
+               dialogArea.setLayout(new FillLayout());
+
+               Composite bodyCmp = new Composite(dialogArea, SWT.NO_FOCUS);
+               bodyCmp.setLayout(new GridLayout());
+
+               // Create and configure the table
+               userTableViewerCmp = new MyUserTableViewer(bodyCmp, SWT.MULTI
+                               | SWT.H_SCROLL | SWT.V_SCROLL);
+
+               userTableViewerCmp.setColumnDefinitions(columnDefs);
+               userTableViewerCmp.populateWithStaticFilters(false, false);
+               GridData gd = EclipseUiUtils.fillAll();
+               gd.minimumHeight = 300;
+               userTableViewerCmp.setLayoutData(gd);
+               userTableViewerCmp.refresh();
+
+               // Controllers
+               userViewer = userTableViewerCmp.getTableViewer();
+               userViewer.addDoubleClickListener(new MyDoubleClickListener());
+               userViewer
+                               .addSelectionChangedListener(new MySelectionChangedListener());
+
+               parent.pack();
+               return dialogArea;
+       }
+
+       public User getSelected() {
+               if (selectedUser == null)
+                       return null;
+               else
+                       return selectedUser;
+       }
+
+       protected void configureShell(Shell shell) {
+               super.configureShell(shell);
+               shell.setText(title);
+       }
+
+       class MyDoubleClickListener implements IDoubleClickListener {
+               public void doubleClick(DoubleClickEvent evt) {
+                       if (evt.getSelection().isEmpty())
+                               return;
+
+                       Object obj = ((IStructuredSelection) evt.getSelection())
+                                       .getFirstElement();
+                       if (obj instanceof User) {
+                               selectedUser = (User) obj;
+                               okPressed();
+                       }
+               }
+       }
+
+       class MySelectionChangedListener implements ISelectionChangedListener {
+               @Override
+               public void selectionChanged(SelectionChangedEvent event) {
+                       if (event.getSelection().isEmpty()) {
+                               selectedUser = null;
+                               return;
+                       }
+                       Object obj = ((IStructuredSelection) event.getSelection())
+                                       .getFirstElement();
+                       if (obj instanceof Group) {
+                               selectedUser = (Group) obj;
+                       }
+               }
+       }
+
+       private class MyUserTableViewer extends LdifUsersTable {
+               private static final long serialVersionUID = 8467999509931900367L;
+
+               private final String[] knownProps = { LdapAttrs.uid.name(),
+                               LdapAttrs.cn.name(), LdapAttrs.DN };
+
+               private Button showSystemRoleBtn;
+               private Button showUserBtn;
+
+               public MyUserTableViewer(Composite parent, int style) {
+                       super(parent, style);
+               }
+
+               protected void populateStaticFilters(Composite staticFilterCmp) {
+                       staticFilterCmp.setLayout(new GridLayout());
+                       showSystemRoleBtn = new Button(staticFilterCmp, SWT.CHECK);
+                       showSystemRoleBtn.setText("Show system roles  ");
+
+                       showUserBtn = new Button(staticFilterCmp, SWT.CHECK);
+                       showUserBtn.setText("Show users  ");
+
+                       SelectionListener sl = new SelectionAdapter() {
+                               private static final long serialVersionUID = -7033424592697691676L;
+
+                               @Override
+                               public void widgetSelected(SelectionEvent e) {
+                                       refresh();
+                               }
+                       };
+
+                       showSystemRoleBtn.addSelectionListener(sl);
+                       showUserBtn.addSelectionListener(sl);
+               }
+
+               @Override
+               protected List<User> listFilteredElements(String filter) {
+                       Role[] roles;
+                       try {
+                               StringBuilder builder = new StringBuilder();
+
+                               StringBuilder filterBuilder = new StringBuilder();
+                               if (notNull(filter))
+                                       for (String prop : knownProps) {
+                                               filterBuilder.append("(");
+                                               filterBuilder.append(prop);
+                                               filterBuilder.append("=*");
+                                               filterBuilder.append(filter);
+                                               filterBuilder.append("*)");
+                                       }
+
+                               String typeStr = "(" + LdapAttrs.objectClass.name() + "="
+                                               + LdapObjs.groupOfNames.name() + ")";
+                               if ((showUserBtn.getSelection()))
+                                       typeStr = "(|(" + LdapAttrs.objectClass.name() + "="
+                                                       + LdapObjs.inetOrgPerson.name() + ")" + typeStr
+                                                       + ")";
+
+                               if (!showSystemRoleBtn.getSelection())
+                                       typeStr = "(& " + typeStr + "(!(" + LdapAttrs.DN + "=*"
+                                                       + NodeConstants.ROLES_BASEDN + ")))";
+
+                               if (filterBuilder.length() > 1) {
+                                       builder.append("(&" + typeStr);
+                                       builder.append("(|");
+                                       builder.append(filterBuilder.toString());
+                                       builder.append("))");
+                               } else {
+                                       builder.append(typeStr);
+                               }
+                               roles = userAdmin.getRoles(builder.toString());
+                       } catch (InvalidSyntaxException e) {
+                               throw new EclipseUiException(
+                                               "Unable to get roles with filter: " + filter, e);
+                       }
+                       List<User> users = new ArrayList<User>();
+                       for (Role role : roles)
+                               if (!users.contains(role))
+                                       users.add((User) role);
+                       return users;
+               }
+       }
+
+       private boolean notNull(String string) {
+               if (string == null)
+                       return false;
+               else
+                       return !"".equals(string.trim());
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/UserLP.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/UserLP.java
new file mode 100644 (file)
index 0000000..88573cd
--- /dev/null
@@ -0,0 +1,76 @@
+package org.argeo.cms.swt.useradmin;
+
+import org.argeo.api.NodeConstants;
+import org.argeo.cms.auth.UserAdminUtils;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+
+/** Centralize label providers for the group table */
+class UserLP extends ColumnLabelProvider {
+       private static final long serialVersionUID = -4645930210988368571L;
+
+       final static String COL_ICON = "colID.icon";
+       final static String COL_DN = "colID.dn";
+       final static String COL_DISPLAY_NAME = "colID.displayName";
+       final static String COL_DOMAIN = "colID.domain";
+
+       final String currType;
+
+       // private Font italic;
+       private Font bold;
+
+       UserLP(String colId) {
+               this.currType = colId;
+       }
+
+       @Override
+       public Font getFont(Object element) {
+               // Current user as bold
+               if (UserAdminUtils.isCurrentUser(((User) element))) {
+                       if (bold == null)
+                               bold = JFaceResources.getFontRegistry().defaultFontDescriptor().setStyle(SWT.BOLD)
+                                               .createFont(Display.getCurrent());
+                       return bold;
+               }
+               return null;
+       }
+
+       @Override
+       public Image getImage(Object element) {
+               if (COL_ICON.equals(currType)) {
+                       User user = (User) element;
+                       String dn = user.getName();
+                       if (dn.endsWith(NodeConstants.ROLES_BASEDN))
+                               return UsersImages.ICON_ROLE;
+                       else if (user.getType() == Role.GROUP)
+                               return UsersImages.ICON_GROUP;
+                       else
+                               return UsersImages.ICON_USER;
+               } else
+                       return null;
+       }
+
+       @Override
+       public String getText(Object element) {
+               User user = (User) element;
+               return getText(user);
+
+       }
+
+       public String getText(User user) {
+               if (COL_DN.equals(currType))
+                       return user.getName();
+               else if (COL_DISPLAY_NAME.equals(currType))
+                       return UserAdminUtils.getCommonName(user);
+               else if (COL_DOMAIN.equals(currType))
+                       return UserAdminUtils.getDomainName(user);
+               else
+                       return "";
+       }
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/UsersImages.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/UsersImages.java
new file mode 100644 (file)
index 0000000..21fc5af
--- /dev/null
@@ -0,0 +1,14 @@
+package org.argeo.cms.swt.useradmin;
+
+import org.argeo.cms.ui.theme.CmsImages;
+import org.eclipse.swt.graphics.Image;
+
+/** Specific users icons. */
+public class UsersImages {
+       private final static String PREFIX = "icons/";
+
+       public final static Image ICON_USER = CmsImages.createImg(PREFIX + "person.png");
+       public final static Image ICON_GROUP = CmsImages.createImg(PREFIX + "group.png");
+       public final static Image ICON_ROLE = CmsImages.createImg(PREFIX + "role.gif");
+       public final static Image ICON_CHANGE_PASSWORD = CmsImages.createImg(PREFIX + "security.gif");
+}
diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/package-info.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/useradmin/package-info.java
new file mode 100644 (file)
index 0000000..3597bfc
--- /dev/null
@@ -0,0 +1,2 @@
+/** SWT/JFace users management components. */
+package org.argeo.cms.swt.useradmin;
\ No newline at end of file
diff --git a/org.argeo.cms.swt/src/org/argeo/eclipse/ui/MouseDoubleClick.java b/org.argeo.cms.swt/src/org/argeo/eclipse/ui/MouseDoubleClick.java
deleted file mode 100644 (file)
index 49d11e5..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.argeo.eclipse.ui;
-
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-
-/**
- * {@link MouseListener#mouseDoubleClick(MouseEvent)} as a functional interface
- * in order to use as a short lambda expression in UI code.
- * {@link MouseListener#mouseDownouseEvent)} and
- * {@link MouseListener#mouseUp(MouseEvent)} do nothing by default.
- */
-@FunctionalInterface
-public interface MouseDoubleClick extends MouseListener {
-       @Override
-       void mouseDoubleClick(MouseEvent e);
-
-       @Override
-       default void mouseDown(MouseEvent e) {
-               // does nothing
-       }
-
-       @Override
-       default void mouseUp(MouseEvent e) {
-               // does nothing
-       }
-}
diff --git a/org.argeo.cms.swt/src/org/argeo/eclipse/ui/MouseDown.java b/org.argeo.cms.swt/src/org/argeo/eclipse/ui/MouseDown.java
deleted file mode 100644 (file)
index 7abed80..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.argeo.eclipse.ui;
-
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-
-/**
- * {@link MouseListener#mouseDown(MouseEvent)} as a functional interface in
- * order to use as a short lambda expression in UI code.
- * {@link MouseListener#mouseDoubleClick(MouseEvent)} and
- * {@link MouseListener#mouseUp(MouseEvent)} do nothing by default.
- */
-@FunctionalInterface
-public interface MouseDown extends MouseListener {
-       @Override
-       void mouseDown(MouseEvent e);
-
-       @Override
-       default void mouseDoubleClick(MouseEvent e) {
-               // does nothing
-       }
-
-       @Override
-       default void mouseUp(MouseEvent e) {
-               // does nothing
-       }
-}
diff --git a/org.argeo.cms.swt/src/org/argeo/eclipse/ui/Selected.java b/org.argeo.cms.swt/src/org/argeo/eclipse/ui/Selected.java
deleted file mode 100644 (file)
index 77bdd79..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.argeo.eclipse.ui;
-
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-
-/**
- * {@link SelectionListener} as a functional interface in order to use as a
- * short lambda expression in UI code.
- * {@link SelectionListener#widgetDefaultSelected(SelectionEvent)} does nothing
- * by default.
- */
-@FunctionalInterface
-public interface Selected extends SelectionListener {
-       @Override
-       public void widgetSelected(SelectionEvent e);
-
-       default public void widgetDefaultSelected(SelectionEvent e) {
-               // does nothing
-       }
-
-}
index 15b181780240f943caef71e1cf9bad18deecabc3..30cff8f8163c6396be6bf33c879d7f295c0df751 100644 (file)
@@ -10,11 +10,11 @@ import javax.script.Invocable;
 import javax.script.ScriptException;
 
 import org.argeo.api.NodeConstants;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.Selected;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.argeo.cms.ui.util.CmsPane;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.cms.web.SimpleErgonomics;
-import org.argeo.eclipse.ui.Selected;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.Application;
 import org.eclipse.rap.rwt.application.EntryPoint;
@@ -124,9 +124,9 @@ public class AppUi implements CmsUiProvider, Branding {
 
                if (false) {
                        // QA
-                       CmsUiUtils.style(cmsPane.getQaArea(), "qa");
+                       CmsSwtUtils.style(cmsPane.getQaArea(), "qa");
                        Button reload = new Button(cmsPane.getQaArea(), SWT.FLAT);
-                       CmsUiUtils.style(reload, "qa");
+                       CmsSwtUtils.style(reload, "qa");
                        reload.setText("Reload");
                        reload.addSelectionListener(new Selected() {
                                private static final long serialVersionUID = 1L;
@@ -145,9 +145,9 @@ public class AppUi implements CmsUiProvider, Branding {
                        });
 
                        // Support
-                       CmsUiUtils.style(cmsPane.getSupportArea(), "support");
+                       CmsSwtUtils.style(cmsPane.getSupportArea(), "support");
                        Label msg = new Label(cmsPane.getSupportArea(), SWT.NONE);
-                       CmsUiUtils.style(msg, "support");
+                       CmsSwtUtils.style(msg, "support");
                        msg.setText("UNSUPPORTED DEVELOPMENT VERSION");
                }
 
index 3f0987199077a0550fcad4f5c74f18b6614f3473..9dd1509be96c465d59f6092276b0cfaa82140120 100644 (file)
@@ -22,9 +22,9 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.cms.CmsTheme;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.ui.CmsConstants;
-import org.argeo.cms.ui.CmsTheme;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.cms.web.BundleResourceLoader;
index 887490c41d3cc3d7706d69928db494635a30b712..504ed49786a21981c7b4b19c7d7f6dd8b6f28b37 100644 (file)
@@ -24,12 +24,13 @@ import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsView;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.HttpRequestCallback;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.cms.ui.CmsStyles;
-import org.argeo.cms.ui.CmsView;
+import org.argeo.cms.swt.CmsStyles;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.naming.AuthPassword;
@@ -120,7 +121,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        @Override
        protected final void createContents(final Composite parent) {
                // UiContext.setData(CmsView.KEY, this);
-               CmsView.registerCmsView(parent.getShell(), this);
+               CmsSwtUtils.registerCmsView(parent.getShell(), this);
                Subject.doAs(getSubject(), new PrivilegedAction<Void>() {
                        @Override
                        public Void run() {
index 0cf9a726970c448e5acff176153eb656757dd235..5de0f91034b551d5caa8481ac2c6a71b27b0d3e8 100644 (file)
@@ -3,7 +3,7 @@ package org.argeo.cms.web;
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.argeo.cms.ui.CmsTheme;
+import org.argeo.api.cms.CmsTheme;
 import org.eclipse.rap.rwt.service.ResourceLoader;
 
 /** A RAP {@link ResourceLoader} based on a {@link CmsTheme}. */
index c1bd3ad9893c279b0cb9c4f6b715fc6c95916bb5..e5b6c7efca1e37b6d76b1ffb5086a5505047e84f 100644 (file)
@@ -7,10 +7,11 @@ import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.ui.CmsApp;
-import org.argeo.cms.ui.CmsAppListener;
-import org.argeo.cms.ui.CmsTheme;
-import org.argeo.cms.ui.CmsView;
+import org.argeo.api.cms.CmsApp;
+import org.argeo.api.cms.CmsAppListener;
+import org.argeo.api.cms.CmsTheme;
+import org.argeo.api.cms.CmsView;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.util.LangUtils;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.Application;
@@ -78,7 +79,7 @@ public class CmsWebApp implements ApplicationConfiguration, ExceptionHandler, Cm
        public void handleException(Throwable throwable) {
                Display display = Display.getCurrent();
                if (display != null && !display.isDisposed()) {
-                       CmsView cmsView = CmsView.getCmsView(display.getActiveShell());
+                       CmsView cmsView = CmsSwtUtils.getCmsView(display.getActiveShell());
                        cmsView.exception(throwable);
                } else {
                        log.error("Unexpected exception outside an UI thread", throwable);
index b1691cb0536f0d725e5d8217bcb1c60c831b142f..4bdc5a0aa4fd554c2581767ba64d6658c9925c06 100644 (file)
@@ -15,18 +15,20 @@ import javax.security.auth.login.LoginException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsApp;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.CmsUi;
+import org.argeo.api.cms.CmsView;
+import org.argeo.api.cms.UxContext;
 import org.argeo.cms.LocaleUtils;
-import org.argeo.cms.auth.CmsSession;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.cms.ui.CmsApp;
-import org.argeo.cms.ui.CmsImageManager;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.UxContext;
-import org.argeo.cms.ui.dialogs.CmsFeedback;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.osgi.CmsOsgiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.SimpleSwtUxContext;
+import org.argeo.cms.swt.dialogs.CmsFeedback;
 import org.argeo.cms.ui.util.DefaultImageManager;
-import org.argeo.cms.ui.util.SimpleUxContext;
 import org.argeo.eclipse.ui.specific.UiContext;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.EntryPoint;
@@ -59,7 +61,8 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
        private UxContext uxContext;
        private CmsImageManager imageManager;
 
-       private Composite ui;
+       private Display display;
+       private CmsUi ui;
 
        private String uid;
 
@@ -104,7 +107,7 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
                        @Override
                        public Void run() {
                                try {
-                                       uxContext = new SimpleUxContext();
+                                       uxContext = new SimpleSwtUxContext();
                                        imageManager = new DefaultImageManager();
                                        CmsSession cmsSession = getCmsSession();
                                        if (cmsSession != null) {
@@ -115,8 +118,10 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
                                                LocaleUtils.setThreadLocale(rwtLocale);
                                        }
                                        parent.setData(CmsApp.UI_NAME_PROPERTY, uiName);
+                                       display = parent.getDisplay();
                                        ui = cmsWebApp.getCmsApp().initUi(parent);
-                                       ui.setLayoutData(CmsUiUtils.fillAll());
+                                       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.
                                        cmsWebApp.getCmsApp().refreshUi(ui, null);
@@ -178,7 +183,7 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
                        if (swtError.code == SWT.ERROR_FUNCTION_DISPOSED)
                                return;
                }
-               ui.getDisplay().syncExec(() -> {
+               display.syncExec(() -> {
 //                     CmsFeedback.show("Unexpected exception in CMS", e);
                        exception = e;
 //             log.error("Unexpected exception in CMS", e);
@@ -230,7 +235,6 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
                        browserNavigation.pushState(state, title);
        }
 
-       @Override
        public CmsImageManager getImageManager() {
                return imageManager;
        }
@@ -259,7 +263,7 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
 
        @Override
        public CmsSession getCmsSession() {
-               CmsSession cmsSession = CmsSession.getCmsSession(cmsWebApp.getBundleContext(), getSubject());
+               CmsSession cmsSession = CmsOsgiUtils.getCmsSession(cmsWebApp.getBundleContext(), getSubject());
                return cmsSession;
        }
 
@@ -289,8 +293,8 @@ public class CmsWebEntryPoint implements EntryPoint, CmsView, BrowserNavigationL
        public int createUI() {
                Display display = new Display();
                Shell shell = createShell(display);
-               shell.setLayout(CmsUiUtils.noSpaceGridLayout());
-               CmsView.registerCmsView(shell, this);
+               shell.setLayout(CmsSwtUtils.noSpaceGridLayout());
+               CmsSwtUtils.registerCmsView(shell, this);
                createContents(shell);
                shell.layout();
 //             if (shell.getMaximized()) {
index 188391c42e68d4b736d444fc88e374a06d142946..2eff71ee8bf5bf6aa5164afde18a1e948924acaf 100644 (file)
@@ -1,11 +1,11 @@
 package org.argeo.cms.web;
 
-import static org.argeo.cms.ui.util.BundleCmsTheme.CMS_THEME_BUNDLE_PROPERTY;
+import static org.argeo.cms.osgi.BundleCmsTheme.CMS_THEME_BUNDLE_PROPERTY;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import org.argeo.cms.ui.util.BundleCmsTheme;
+import org.argeo.cms.osgi.BundleCmsTheme;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.Application;
 import org.eclipse.rap.rwt.application.ApplicationConfiguration;
index 9760f9dadcdf0eb2eefc821b3a9a090cce456590..6e1165cf32777b3083f6f854c9f900ce80616a0d 100644 (file)
@@ -9,14 +9,14 @@ import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.api.cms.UxContext;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.CmsImageManager;
-import org.argeo.cms.ui.CmsStyles;
+import org.argeo.cms.swt.CmsStyles;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.SimpleSwtUxContext;
 import org.argeo.cms.ui.CmsUiProvider;
-import org.argeo.cms.ui.UxContext;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.cms.ui.util.DefaultImageManager;
-import org.argeo.cms.ui.util.SimpleUxContext;
 import org.argeo.cms.ui.util.SystemNotifications;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
@@ -62,9 +62,9 @@ public class SimpleErgonomics extends AbstractCmsEntryPoint {
        protected void initUi(Composite parent) {
                uid = UUID.randomUUID().toString();
                parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               parent.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(3, false)));
+               parent.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(3, false)));
 
-               uxContext = new SimpleUxContext();
+               uxContext = new SimpleSwtUxContext();
                if (!getUxContext().isMasterData())
                        createAdminArea(parent);
                headerArea = new Composite(parent, SWT.NONE);
@@ -76,17 +76,17 @@ public class SimpleErgonomics extends AbstractCmsEntryPoint {
                // TODO: bi-directional
                leftArea = new Composite(parent, SWT.NONE);
                leftArea.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false));
-               leftArea.setLayout(CmsUiUtils.noSpaceGridLayout());
+               leftArea.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                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(CmsUiUtils.noSpaceGridLayout());
+               bodyArea.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                // TODO: bi-directional
                rightArea = new Composite(parent, SWT.NONE);
                rightArea.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false));
-               rightArea.setLayout(CmsUiUtils.noSpaceGridLayout());
+               rightArea.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                footerArea = new Composite(parent, SWT.NONE);
                // footerArea.setLayout(new FillLayout());
@@ -141,7 +141,7 @@ public class SimpleErgonomics extends AbstractCmsEntryPoint {
 
                for (Control child : area.getChildren())
                        child.dispose();
-               CmsUiUtils.style(area, style);
+               CmsSwtUtils.style(area, style);
                try {
                        uiProvider.createUi(area, getNode());
                } catch (RepositoryException e) {
@@ -164,7 +164,7 @@ public class SimpleErgonomics extends AbstractCmsEntryPoint {
                // clear
                for (Control child : bodyArea.getChildren())
                        child.dispose();
-               bodyArea.setLayout(CmsUiUtils.noSpaceGridLayout());
+               bodyArea.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                try {
                        Node node = getNode();
@@ -188,7 +188,6 @@ public class SimpleErgonomics extends AbstractCmsEntryPoint {
                return uid;
        }
 
-       @Override
        public CmsImageManager getImageManager() {
                return imageManager;
        }
index a71ff97d3e569da2189f35b5671fd5c1d3c242c6..a28b13fc6ce322cfd97936fe3cf2bde8ef9f7be1 100644 (file)
@@ -2,7 +2,7 @@ package org.argeo.cms.web;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.ui.CmsTheme;
+import org.argeo.api.cms.CmsTheme;
 import org.eclipse.rap.rwt.application.Application;
 import org.eclipse.rap.rwt.service.ResourceLoader;
 
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsApp.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsApp.java
deleted file mode 100644 (file)
index 77cd983..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.argeo.cms.ui;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Repository;
-
-import org.eclipse.rap.rwt.RWT;
-
-/** Base class for {@link CmsApp}s. */
-public abstract class AbstractCmsApp implements CmsApp {
-       private Map<String, CmsTheme> themes = Collections.synchronizedMap(new HashMap<>());
-
-       private List<CmsAppListener> cmsAppListeners = new ArrayList<>();
-
-       private Repository repository;
-
-       protected abstract String getThemeId(String uiName);
-
-       @Override
-       public CmsTheme getTheme(String uiName) {
-               String themeId = getThemeId(uiName);
-               if (themeId == null)
-                       return null;
-               if (!themes.containsKey(themeId))
-                       throw new IllegalArgumentException("Theme " + themeId + " not found.");
-               return themes.get(themeId);
-       }
-
-       @Override
-       public boolean allThemesAvailable() {
-               boolean themeMissing = false;
-               uiNames: for (String uiName : getUiNames()) {
-                       String themeId = getThemeId(uiName);
-                       if (RWT.DEFAULT_THEME_ID.equals(themeId))
-                               continue uiNames;
-                       if (!themes.containsKey(themeId)) {
-                               themeMissing = true;
-                               break uiNames;
-                       }
-               }
-               return !themeMissing;
-       }
-
-       public void addTheme(CmsTheme theme, Map<String, String> properties) {
-               themes.put(theme.getThemeId(), theme);
-               if (allThemesAvailable())
-                       for (CmsAppListener listener : cmsAppListeners)
-                               listener.themingUpdated();
-       }
-
-       public void removeTheme(CmsTheme theme, Map<String, String> properties) {
-               themes.remove(theme.getThemeId());
-       }
-
-       @Override
-       public void addCmsAppListener(CmsAppListener listener) {
-               cmsAppListeners.add(listener);
-               if (allThemesAvailable())
-                       listener.themingUpdated();
-       }
-
-       @Override
-       public void removeCmsAppListener(CmsAppListener listener) {
-               cmsAppListeners.remove(listener);
-       }
-
-       protected Repository getRepository() {
-               return repository;
-       }
-
-       public void setRepository(Repository repository) {
-               this.repository = repository;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsApp.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsApp.java
deleted file mode 100644 (file)
index bd7b003..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.argeo.cms.ui;
-
-import java.util.Set;
-
-import org.eclipse.swt.widgets.Composite;
-
-/** An extensible user interface base on the CMS backend. */
-public interface CmsApp {
-       /**
-        * If {@link Composite#setData(String, Object)} is set with this property, it
-        * indicates a different UI (typically with another theming. The {@link CmsApp}
-        * can use this information, but it doesn't have to be set, in which case a
-        * default UI must be provided. The provided value must belong to the values
-        * returned by {@link CmsApp#getUiNames()}.
-        */
-       final static String UI_NAME_PROPERTY = CmsApp.class.getName() + ".ui.name";
-
-       Set<String> getUiNames();
-
-       Composite initUi(Composite parent);
-
-       void refreshUi(Composite parent, String state);
-
-       void setState(Composite parent, String state);
-
-       CmsTheme getTheme(String uiName);
-
-       boolean allThemesAvailable();
-
-       void addCmsAppListener(CmsAppListener listener);
-
-       void removeCmsAppListener(CmsAppListener listener);
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsAppListener.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsAppListener.java
deleted file mode 100644 (file)
index 1fe3678..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.argeo.cms.ui;
-
-/** Notifies important events in a {@link CmsApp} life cycle. */
-public interface CmsAppListener {
-       /** Theming has been updated and should be reloaded. */
-       void themingUpdated();
-}
index ef6fd5f2e6c72ea46f61cca2d82b1150baae36ff..8c324ad7495ff7118955e832b2e4010d29691827 100644 (file)
@@ -1,8 +1,9 @@
 package org.argeo.cms.ui;
 
-import org.eclipse.swt.graphics.Point;
+import org.argeo.api.cms.Cms2DSize;
 
 /** Commons constants */
+@Deprecated
 public interface CmsConstants {
        // DATAKEYS
 //     public final static String STYLE = EclipseUiConstants.CSS_CLASS;
@@ -20,7 +21,7 @@ public interface CmsConstants {
        public final static String LOADING_IMAGE = "icons/loading.gif";
 
        public final static String NO_IMAGE = "icons/noPic-square-640px.png";
-       public final static Point NO_IMAGE_SIZE = new Point(320, 320);
+       public final static Cms2DSize NO_IMAGE_SIZE = new Cms2DSize(320, 320);
        public final static Float NO_IMAGE_RATIO = 1f;
        // MISCEALLENEOUS
        String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm";
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsEditable.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsEditable.java
deleted file mode 100644 (file)
index 72cc597..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.argeo.cms.ui;
-
-/** Abstraction of a simple edition life cycle. */
-public interface CmsEditable {
-
-       /** Whether the calling thread can edit, the value is immutable */
-       public Boolean canEdit();
-
-       public Boolean isEditing();
-
-       public void startEditing();
-
-       public void stopEditing();
-
-       public static CmsEditable NON_EDITABLE = new CmsEditable() {
-
-               @Override
-               public void stopEditing() {
-               }
-
-               @Override
-               public void startEditing() {
-               }
-
-               @Override
-               public Boolean isEditing() {
-                       return false;
-               }
-
-               @Override
-               public Boolean canEdit() {
-                       return false;
-               }
-       };
-
-       public static CmsEditable ALWAYS_EDITING = new CmsEditable() {
-
-               @Override
-               public void stopEditing() {
-               }
-
-               @Override
-               public void startEditing() {
-               }
-
-               @Override
-               public Boolean isEditing() {
-                       return true;
-               }
-
-               @Override
-               public Boolean canEdit() {
-                       return true;
-               }
-       };
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsImageManager.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsImageManager.java
deleted file mode 100644 (file)
index e0cfa31..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.argeo.cms.ui;
-
-import java.io.InputStream;
-
-import javax.jcr.Binary;
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Control;
-
-/** Read and write access to images. */
-public interface CmsImageManager {
-       /** Load image in control */
-       public Boolean load(Node node, Control control, Point size) throws RepositoryException;
-
-       /** @return (0,0) if not available */
-       public Point getImageSize(Node node) throws RepositoryException;
-
-       /**
-        * The related &lt;img&gt; tag, with src, width and height set.
-        * 
-        * @return null if not available
-        */
-       public String getImageTag(Node node) throws RepositoryException;
-
-       /**
-        * The related &lt;img&gt; tag, with url, width and height set. Caller must
-        * close the tag (or add additional attributes).
-        * 
-        * @return null if not available
-        */
-       public StringBuilder getImageTagBuilder(Node node, Point size) throws RepositoryException;
-
-       /**
-        * Returns the remotely accessible URL of the image (registering it if
-        * needed) @return null if not available
-        */
-       public String getImageUrl(Node node) throws RepositoryException;
-
-       public Binary getImageBinary(Node node) throws RepositoryException;
-
-       public Image getSwtImage(Node node) throws RepositoryException;
-
-       /** @return URL */
-       public String uploadImage(Node context, Node uploadFolder, String fileName, InputStream in, String contentType)
-                       throws RepositoryException;
-
-       @Deprecated
-       default String uploadImage(Node uploadFolder, String fileName, InputStream in) throws RepositoryException {
-               System.err.println("Context must be provided to " + CmsImageManager.class.getName());
-               return uploadImage(null, uploadFolder, fileName, in, null);
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsStyles.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsStyles.java
deleted file mode 100644 (file)
index 678a497..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.argeo.cms.ui;
-
-/** Styles references in the CSS. */
-@Deprecated
-public interface CmsStyles {
-       // General
-       public final static String CMS_SHELL = "cms_shell";
-       public final static String CMS_MENU_LINK = "cms_menu_link";
-
-       // Header
-       public final static String CMS_HEADER = "cms_header";
-       public final static String CMS_HEADER_LEAD = "cms_header-lead";
-       public final static String CMS_HEADER_CENTER = "cms_header-center";
-       public final static String CMS_HEADER_END = "cms_header-end";
-
-       public final static String CMS_LEAD = "cms_lead";
-       public final static String CMS_END = "cms_end";
-       public final static String CMS_FOOTER = "cms_footer";
-
-       public final static String CMS_USER_MENU = "cms_user_menu";
-       public final static String CMS_USER_MENU_LINK = "cms_user_menu-link";
-       public final static String CMS_USER_MENU_ITEM = "cms_user_menu-item";
-       public final static String CMS_LOGIN_DIALOG = "cms_login_dialog";
-       public final static String CMS_LOGIN_DIALOG_USERNAME = "cms_login_dialog-username";
-       public final static String CMS_LOGIN_DIALOG_PASSWORD = "cms_login_dialog-password";
-
-       // Body
-       public final static String CMS_SCROLLED_AREA = "cms_scrolled_area";
-       public final static String CMS_BODY = "cms_body";
-       public final static String CMS_STATIC_TEXT = "cms_static-text";
-       public final static String CMS_LINK = "cms_link";
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsTheme.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsTheme.java
deleted file mode 100644 (file)
index c93991b..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.argeo.cms.ui;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Set;
-
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Shell;
-
-/** A CMS theme which can be applied to web apps as well as desktop apps. */
-public interface CmsTheme {
-       /** Unique ID of this theme. */
-       String getThemeId();
-
-       /**
-        * Load a resource as an input stream, base don its relative path, or
-        * <code>null</code> if not found
-        */
-       InputStream getResourceAsStream(String resourceName) throws IOException;
-
-       /** Relative paths to standard web CSS. */
-       Set<String> getWebCssPaths();
-
-       /** Relative paths to RAP specific CSS. */
-       Set<String> getRapCssPaths();
-
-       /** Relative paths to SWT specific CSS. */
-       Set<String> getSwtCssPaths();
-
-       /** Relative paths to images such as icons. */
-       Set<String> getImagesPaths();
-
-       /** Relative paths to fonts. */
-       Set<String> getFontsPaths();
-
-       /** Tags to be added to the header section of the HTML page. */
-       String getHtmlHeaders();
-
-       /** The HTML body to use. */
-       String getBodyHtml();
-
-       /** The image registered at this path, or <code>null</code> if not found. */
-       Image getImage(String path);
-
-       /** The default icon size (typically the smallest). */
-       Integer getDefaultIconSize();
-
-       /** Loads one of the relative path provided by the other methods. */
-       InputStream loadPath(String path) throws IOException;
-
-       /**
-        * And icon with this file name (without the extension), with a best effort to
-        * find the appropriate size, or <code>null</code> if not found.
-        * 
-        * @param name          An icon file name without path and extension.
-        * @param preferredSize the preferred size, if <code>null</code>,
-        *                      {@link #getDefaultIconSize()} will be tried.
-        */
-       Image getIcon(String name, Integer preferredSize);
-
-       static CmsTheme getCmsTheme(Composite parent) {
-               CmsTheme theme = (CmsTheme) parent.getData(CmsTheme.class.getName());
-               if (theme == null) {
-                       // find parent shell
-                       Shell topShell = parent.getShell();
-                       while (topShell.getParent() != null)
-                               topShell = (Shell) topShell.getParent();
-                       theme = (CmsTheme) topShell.getData(CmsTheme.class.getName());
-                       parent.setData(CmsTheme.class.getName(), theme);
-               }
-               return theme;
-       }
-
-       static void registerCmsTheme(Shell shell, CmsTheme theme) {
-               // find parent shell
-               Shell topShell = shell;
-               while (topShell.getParent() != null)
-                       topShell = (Shell) topShell.getParent();
-               // check if already set
-               if (topShell.getData(CmsTheme.class.getName()) != null) {
-                       CmsTheme registeredTheme = (CmsTheme) topShell.getData(CmsTheme.class.getName());
-                       throw new IllegalArgumentException(
-                                       "Theme " + registeredTheme.getThemeId() + " already registered in this shell");
-               }
-               topShell.setData(CmsTheme.class.getName(), theme);
-       }
-
-}
index 00939e154ca2a5df106fb5b150f6dc33e6bc27ac..ec76321fee31e2cbcd56a4c3355f1017a07099b3 100644 (file)
@@ -3,6 +3,7 @@ package org.argeo.cms.ui;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
+import org.argeo.api.cms.MvcProvider;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java
deleted file mode 100644 (file)
index f8ab3a6..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.argeo.cms.ui;
-
-import java.security.PrivilegedAction;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.security.auth.login.LoginContext;
-
-import org.argeo.cms.auth.CmsSession;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Shell;
-
-/** Provides interaction with the CMS system. */
-public interface CmsView {
-       final static String CMS_VIEW_UID_PROPERTY = "argeo.cms.view.uid";
-       // String KEY = "org.argeo.cms.ui.view";
-
-       String getUid();
-
-       UxContext getUxContext();
-
-       // NAVIGATION
-       void navigateTo(String state);
-
-       // SECURITY
-       void authChange(LoginContext loginContext);
-
-       void logout();
-
-       // void registerCallbackHandler(CallbackHandler callbackHandler);
-
-       // SERVICES
-       void exception(Throwable e);
-
-       CmsImageManager getImageManager();
-
-       boolean isAnonymous();
-
-       /**
-        * Send an event to this topic. Does nothing by default., but if implemented it
-        * MUST set the {@link #CMS_VIEW_UID_PROPERTY} in the properties.
-        */
-       default void sendEvent(String topic, Map<String, Object> properties) {
-
-       }
-
-       /**
-        * Convenience methods for when {@link #sendEvent(String, Map)} only requires
-        * one single parameter.
-        */
-       default void sendEvent(String topic, String param, Object value) {
-               Map<String, Object> properties = new HashMap<>();
-               properties.put(param, value);
-               sendEvent(topic, properties);
-       }
-
-       default void applyStyles(Object widget) {
-
-       }
-
-       default <T> T doAs(PrivilegedAction<T> action) {
-               throw new UnsupportedOperationException();
-       }
-
-       default Void runAs(Runnable runnable) {
-               return doAs(new PrivilegedAction<Void>() {
-
-                       @Override
-                       public Void run() {
-                               if (runnable != null)
-                                       runnable.run();
-                               return null;
-                       }
-               });
-       }
-
-       default void stateChanged(String state, String title) {
-       }
-
-       default CmsSession getCmsSession() {
-               throw new UnsupportedOperationException();
-       }
-
-       default Object getData(String key) {
-               throw new UnsupportedOperationException();
-       }
-
-       @SuppressWarnings("unchecked")
-       default <T> T getUiContext(Class<T> clss) {
-               return (T) getData(clss.getName());
-       }
-
-       default <T> void setUiContext(Class<T> clss, T instance) {
-               setData(clss.getName(), instance);
-       }
-
-       default void setData(String key, Object value) {
-               throw new UnsupportedOperationException();
-       }
-
-       static CmsView getCmsView(Control parent) {
-               // find parent shell
-               Shell topShell = parent.getShell();
-               while (topShell.getParent() != null)
-                       topShell = (Shell) topShell.getParent();
-               return (CmsView) topShell.getData(CmsView.class.getName());
-       }
-
-       static void registerCmsView(Shell shell, CmsView view) {
-               // find parent shell
-               Shell topShell = shell;
-               while (topShell.getParent() != null)
-                       topShell = (Shell) topShell.getParent();
-               // check if already set
-               if (topShell.getData(CmsView.class.getName()) != null) {
-                       CmsView registeredView = (CmsView) topShell.getData(CmsView.class.getName());
-                       throw new IllegalArgumentException("Cms view " + registeredView + " already registered in this shell");
-               }
-               shell.setData(CmsView.class.getName(), view);
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/MvcProvider.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/MvcProvider.java
deleted file mode 100644 (file)
index f29d6b7..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.argeo.cms.ui;
-
-import java.util.function.BiFunction;
-
-/**
- * Stateless UI part creator. Takes a parent view (V) and a model context (M) in
- * order to create a view part (W) which can then be further configured. Such
- * object can be used as services and reference other part of the model which
- * are relevant for all created UI part.
- */
-@FunctionalInterface
-public interface MvcProvider<V, M, W> extends BiFunction<V, M, W> {
-       W createUiPart(V parent, M context);
-       
-       /**
-        * Whether this parent view is supported.
-        * 
-        * @return true by default.
-        */
-       default boolean isViewSupported(V parent) {
-               return true;
-       }
-
-       /**
-        * Whether this context is supported.
-        * 
-        * @return true by default.
-        */
-       default boolean isModelSupported(M context) {
-               return true;
-       }
-
-       default W apply(V parent, M context) {
-               if (!isViewSupported(parent))
-                       throw new IllegalArgumentException("Parent view " + parent + "is not supported.");
-               if (!isModelSupported(context))
-                       throw new IllegalArgumentException("Model context " + context + "is not supported.");
-               return createUiPart(parent, context);
-       }
-
-       default W createUiPart(V parent) {
-               return createUiPart(parent, null);
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/UxContext.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/UxContext.java
deleted file mode 100644 (file)
index 42d7ab3..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.argeo.cms.ui;
-
-public interface UxContext {
-       boolean isPortrait();
-
-       boolean isLandscape();
-
-       boolean isSquare();
-
-       boolean isSmall();
-
-       /**
-        * Is a production environment (must be false by default, and be explicitly
-        * set during the CMS deployment). When false, it can activate additional UI
-        * capabilities in order to facilitate QA.
-        */
-       boolean isMasterData();
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/ChangePasswordDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/ChangePasswordDialog.java
deleted file mode 100644 (file)
index 3728692..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.argeo.cms.ui.dialogs;
-
-import java.security.PrivilegedAction;
-import java.util.Arrays;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.CmsMsg;
-import org.argeo.cms.CmsUserManager;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.util.CmsUiUtils;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/** Dialog to change a password. */
-public class ChangePasswordDialog extends CmsMessageDialog {
-       private final static Log log = LogFactory.getLog(ChangePasswordDialog.class);
-
-       private CmsUserManager cmsUserManager;
-       private CmsView cmsView;
-
-       private PrivilegedAction<Integer> doIt;
-
-       public ChangePasswordDialog(Shell parentShell, String message, int kind, CmsUserManager cmsUserManager) {
-               super(parentShell, message, kind);
-               this.cmsUserManager = cmsUserManager;
-               cmsView = CmsView.getCmsView(parentShell);
-       }
-
-       @Override
-       protected Control createInputArea(Composite userSection) {
-               addFormLabel(userSection, CmsMsg.currentPassword.lead());
-               Text previousPassword = new Text(userSection, SWT.BORDER | SWT.PASSWORD);
-               previousPassword.setLayoutData(CmsUiUtils.fillWidth());
-               addFormLabel(userSection, CmsMsg.newPassword.lead());
-               Text newPassword = new Text(userSection, SWT.BORDER | SWT.PASSWORD);
-               newPassword.setLayoutData(CmsUiUtils.fillWidth());
-               addFormLabel(userSection, CmsMsg.repeatNewPassword.lead());
-               Text confirmPassword = new Text(userSection, SWT.BORDER | SWT.PASSWORD);
-               confirmPassword.setLayoutData(CmsUiUtils.fillWidth());
-
-               doIt = () -> {
-                       if (Arrays.equals(newPassword.getTextChars(), confirmPassword.getTextChars())) {
-                               try {
-                                       cmsUserManager.changeOwnPassword(previousPassword.getTextChars(), newPassword.getTextChars());
-                                       return OK;
-                               } catch (Exception e1) {
-                                       log.error("Could not change password", e1);
-                                       cancel();
-                                       CmsMessageDialog.openError(CmsMsg.invalidPassword.lead());
-                                       return CANCEL;
-                               }
-                       } else {
-                               cancel();
-                               CmsMessageDialog.openError(CmsMsg.repeatNewPassword.lead());
-                               return CANCEL;
-                       }
-               };
-
-               pack();
-               return previousPassword;
-       }
-
-       @Override
-       protected void okPressed() {
-               Integer returnCode = cmsView.doAs(doIt);
-               if (returnCode.equals(OK)) {
-                       super.okPressed();
-                       CmsMessageDialog.openInformation(CmsMsg.passwordChanged.lead());
-               }
-       }
-
-       private static Label addFormLabel(Composite parent, String label) {
-               Label lbl = new Label(parent, SWT.WRAP);
-               lbl.setText(label);
-//             CmsUiUtils.style(lbl, SuiteStyle.simpleLabel);
-               return lbl;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsFeedback.java
deleted file mode 100644 (file)
index 30e2ad3..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.argeo.cms.ui.dialogs;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.CmsMsg;
-import org.argeo.eclipse.ui.Selected;
-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.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/** A dialog feedback based on a {@link LightweightDialog}. */
-public class CmsFeedback extends LightweightDialog {
-       private final static Log log = LogFactory.getLog(CmsFeedback.class);
-
-       private String message;
-       private Throwable exception;
-
-       public CmsFeedback(Shell parentShell, String message, Throwable e) {
-               super(parentShell);
-               this.message = message;
-               this.exception = e;
-               log.error(message, e);
-       }
-
-       public static CmsFeedback show(String message, Throwable e) {
-               // rethrow ThreaDeath in order to make sure that RAP will properly clean
-               // up the UI thread
-               if (e instanceof ThreadDeath)
-                       throw (ThreadDeath) e;
-
-               try {
-                       CmsFeedback cmsFeedback = new CmsFeedback(null, message, e);
-                       cmsFeedback.setBlockOnOpen(false);
-                       cmsFeedback.open();
-                       return cmsFeedback;
-               } catch (Throwable e1) {
-                       log.error("Cannot open error feedback (" + e.getMessage() + "), original error below", e);
-                       return null;
-               }
-       }
-
-       public static CmsFeedback show(String message) {
-               CmsFeedback cmsFeedback = new CmsFeedback(null, message, null);
-               cmsFeedback.open();
-               return cmsFeedback;
-       }
-
-       /** Tries to find a display */
-       // private static Display getDisplay() {
-       // try {
-       // Display display = Display.getCurrent();
-       // if (display != null)
-       // return display;
-       // else
-       // return Display.getDefault();
-       // } catch (Exception e) {
-       // return Display.getCurrent();
-       // }
-       // }
-
-       protected Control createDialogArea(Composite parent) {
-               parent.setLayout(new GridLayout(2, false));
-
-               Label messageLbl = new Label(parent, SWT.WRAP);
-               if (message != null)
-                       messageLbl.setText(message);
-               else if (exception != null)
-                       messageLbl.setText(exception.getLocalizedMessage());
-
-               Button close = new Button(parent, SWT.FLAT);
-               close.setText(CmsMsg.close.lead());
-               close.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false));
-               close.addSelectionListener((Selected) (e) -> closeShell(OK));
-
-               // Composite composite = new Composite(dialogarea, SWT.NONE);
-               // composite.setLayout(new GridLayout(2, false));
-               // composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               if (exception != null) {
-                       Text stack = new Text(parent, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
-                       stack.setEditable(false);
-                       stack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
-                       StringWriter sw = new StringWriter();
-                       exception.printStackTrace(new PrintWriter(sw));
-                       stack.setText(sw.toString());
-               }
-
-               // parent.pack();
-               return messageLbl;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsMessageDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsMessageDialog.java
deleted file mode 100644 (file)
index eb881c6..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.argeo.cms.ui.dialogs;
-
-import org.argeo.cms.CmsMsg;
-import org.argeo.cms.ui.util.CmsUiUtils;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.Selected;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.TraverseEvent;
-import org.eclipse.swt.events.TraverseListener;
-import org.eclipse.swt.graphics.Point;
-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.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-
-/** Base class for dialogs displaying messages or small forms. */
-public class CmsMessageDialog extends LightweightDialog {
-       public final static int NONE = 0;
-       public final static int ERROR = 1;
-       public final static int INFORMATION = 2;
-       public final static int QUESTION = 3;
-       public final static int WARNING = 4;
-       public final static int CONFIRM = 5;
-       public final static int QUESTION_WITH_CANCEL = 6;
-
-       private int kind;
-       private String message;
-
-       public CmsMessageDialog(Shell parentShell, String message, int kind) {
-               super(parentShell);
-               this.kind = kind;
-               this.message = message;
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               parent.setLayout(new GridLayout());
-
-               TraverseListener traverseListener = new TraverseListener() {
-                       private static final long serialVersionUID = -1158892811534971856L;
-
-                       public void keyTraversed(TraverseEvent e) {
-                               if (e.detail == SWT.TRAVERSE_RETURN)
-                                       okPressed();
-                               else if (e.detail == SWT.TRAVERSE_ESCAPE)
-                                       cancelPressed();
-                       }
-               };
-
-               // message
-               Composite body = new Composite(parent, SWT.NONE);
-               body.addTraverseListener(traverseListener);
-               GridLayout bodyGridLayout = new GridLayout();
-               bodyGridLayout.marginHeight = 20;
-               bodyGridLayout.marginWidth = 20;
-               body.setLayout(bodyGridLayout);
-               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               if (message != null) {
-                       Label messageLbl = new Label(body, SWT.WRAP);
-                       CmsUiUtils.markup(messageLbl);
-                       messageLbl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-                       messageLbl.setFont(EclipseUiUtils.getBoldFont(parent));
-                       messageLbl.setText(message);
-               }
-
-               // buttons
-               Composite buttons = new Composite(parent, SWT.NONE);
-               buttons.addTraverseListener(traverseListener);
-               buttons.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
-               if (kind == INFORMATION || kind == WARNING || kind == ERROR || kind == ERROR) {
-                       GridLayout layout = new GridLayout(1, true);
-                       layout.marginWidth = 0;
-                       layout.marginHeight = 0;
-                       buttons.setLayout(layout);
-
-                       Button close = new Button(buttons, SWT.FLAT);
-                       close.setText(CmsMsg.close.lead());
-                       close.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-                       close.addSelectionListener((Selected) (e) -> closeShell(OK));
-                       close.setFocus();
-                       close.addTraverseListener(traverseListener);
-
-                       buttons.setTabList(new Control[] { close });
-               } else if (kind == CONFIRM || kind == QUESTION || kind == QUESTION_WITH_CANCEL) {
-                       Control input = createInputArea(body);
-                       if (input != null) {
-                               input.addTraverseListener(traverseListener);
-                               body.setTabList(new Control[] { input });
-                       }
-                       GridLayout layout = new GridLayout(2, true);
-                       layout.marginWidth = 0;
-                       layout.marginHeight = 0;
-                       buttons.setLayout(layout);
-
-                       Button cancel = new Button(buttons, SWT.FLAT);
-                       cancel.setText(CmsMsg.cancel.lead());
-                       cancel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-                       cancel.addSelectionListener((Selected) (e) -> cancelPressed());
-                       cancel.addTraverseListener(traverseListener);
-
-                       Button ok = new Button(buttons, SWT.FLAT);
-                       ok.setText(CmsMsg.ok.lead());
-                       ok.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-                       ok.addSelectionListener((Selected) (e) -> okPressed());
-                       ok.addTraverseListener(traverseListener);
-                       if (input == null)
-                               ok.setFocus();
-                       else
-                               input.setFocus();
-
-                       buttons.setTabList(new Control[] { ok, cancel });
-               }
-               // pack();
-               parent.setTabList(new Control[] { body, buttons });
-               return body;
-       }
-
-       protected Control createInputArea(Composite parent) {
-               return null;
-       }
-
-       protected void okPressed() {
-               closeShell(OK);
-       }
-
-       protected void cancelPressed() {
-               closeShell(CANCEL);
-       }
-
-       protected void cancel() {
-               closeShell(CANCEL);
-       }
-
-       protected Point getInitialSize() {
-               return new Point(400, 200);
-       }
-
-       public static boolean open(int kind, Shell parent, String message) {
-               CmsMessageDialog dialog = new CmsMessageDialog(parent, message, kind);
-               return dialog.open() == 0;
-       }
-
-       public static boolean openConfirm(String message) {
-               return open(CONFIRM, Display.getCurrent().getActiveShell(), message);
-       }
-
-       public static void openInformation(String message) {
-               open(INFORMATION, Display.getCurrent().getActiveShell(), message);
-       }
-
-       public static boolean openQuestion(String message) {
-               return open(QUESTION, Display.getCurrent().getActiveShell(), message);
-       }
-
-       public static void openWarning(String message) {
-               open(WARNING, Display.getCurrent().getActiveShell(), message);
-       }
-
-       public static void openError(String message) {
-               open(ERROR, Display.getCurrent().getActiveShell(), message);
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsWizardDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/CmsWizardDialog.java
deleted file mode 100644 (file)
index e4fe35d..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-package org.argeo.cms.ui.dialogs;
-
-import java.lang.reflect.InvocationTargetException;
-
-import org.argeo.cms.CmsMsg;
-import org.argeo.cms.ui.util.CmsUiUtils;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.Selected;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.wizard.IWizard;
-import org.eclipse.jface.wizard.IWizardContainer2;
-import org.eclipse.jface.wizard.IWizardPage;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.FormLayout;
-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.eclipse.swt.widgets.Shell;
-
-/** A wizard dialog based on {@link LightweightDialog}. */
-public class CmsWizardDialog extends LightweightDialog implements IWizardContainer2 {
-       private static final long serialVersionUID = -2123153353654812154L;
-
-       private IWizard wizard;
-       private IWizardPage currentPage;
-       private int currentPageIndex;
-
-       private Label titleBar;
-       private Label message;
-       private Composite[] pageBodies;
-       private Composite buttons;
-       private Button back;
-       private Button next;
-       private Button finish;
-
-       public CmsWizardDialog(Shell parentShell, IWizard wizard) {
-               super(parentShell);
-               this.wizard = wizard;
-               wizard.setContainer(this);
-               // create the pages
-               wizard.addPages();
-               currentPage = wizard.getStartingPage();
-               if (currentPage == null)
-                       throw new IllegalArgumentException("At least one wizard page is required");
-       }
-
-       @Override
-       protected Control createDialogArea(Composite parent) {
-               updateWindowTitle();
-
-               Composite messageArea = new Composite(parent, SWT.NONE);
-               messageArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               {
-                       messageArea.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(2, false)));
-                       titleBar = new Label(messageArea, SWT.WRAP);
-                       titleBar.setFont(EclipseUiUtils.getBoldFont(parent));
-                       titleBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
-                       updateTitleBar();
-                       Button cancelButton = new Button(messageArea, SWT.FLAT);
-                       cancelButton.setText(CmsMsg.cancel.lead());
-                       cancelButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false, 1, 3));
-                       cancelButton.addSelectionListener((Selected) (e) -> closeShell(CANCEL));
-                       message = new Label(messageArea, SWT.WRAP);
-                       message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 2));
-                       updateMessage();
-               }
-
-               Composite body = new Composite(parent, SWT.BORDER);
-               body.setLayout(new FormLayout());
-               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               pageBodies = new Composite[wizard.getPageCount()];
-               IWizardPage[] pages = wizard.getPages();
-               for (int i = 0; i < pages.length; i++) {
-                       pageBodies[i] = new Composite(body, SWT.NONE);
-                       pageBodies[i].setLayout(CmsUiUtils.noSpaceGridLayout());
-                       setSwitchingFormData(pageBodies[i]);
-                       pages[i].createControl(pageBodies[i]);
-               }
-               showPage(currentPage);
-
-               buttons = new Composite(parent, SWT.NONE);
-               buttons.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
-               {
-                       boolean singlePage = wizard.getPageCount() == 1;
-                       // singlePage = false;// dev
-                       GridLayout layout = new GridLayout(singlePage ? 1 : 3, true);
-                       layout.marginWidth = 0;
-                       layout.marginHeight = 0;
-                       buttons.setLayout(layout);
-                       // TODO revert order for right-to-left languages
-
-                       if (!singlePage) {
-                               back = new Button(buttons, SWT.PUSH);
-                               back.setText(CmsMsg.wizardBack.lead());
-                               back.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-                               back.addSelectionListener((Selected) (e) -> backPressed());
-
-                               next = new Button(buttons, SWT.PUSH);
-                               next.setText(CmsMsg.wizardNext.lead());
-                               next.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-                               next.addSelectionListener((Selected) (e) -> nextPressed());
-                       }
-                       finish = new Button(buttons, SWT.PUSH);
-                       finish.setText(CmsMsg.wizardFinish.lead());
-                       finish.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
-                       finish.addSelectionListener((Selected) (e) -> finishPressed());
-
-                       updateButtons();
-               }
-               return body;
-       }
-
-       @Override
-       public IWizardPage getCurrentPage() {
-               return currentPage;
-       }
-
-       @Override
-       public Shell getShell() {
-               return getForegoundShell();
-       }
-
-       @Override
-       public void showPage(IWizardPage page) {
-               IWizardPage[] pages = wizard.getPages();
-               int index = -1;
-               for (int i = 0; i < pages.length; i++) {
-                       if (page == pages[i]) {
-                               index = i;
-                               break;
-                       }
-               }
-               if (index < 0)
-                       throw new IllegalArgumentException("Cannot find index of wizard page " + page);
-               pageBodies[index].moveAbove(pageBodies[currentPageIndex]);
-
-               // // clear
-               // for (Control c : body.getChildren())
-               // c.dispose();
-               // page.createControl(body);
-               // body.layout(true, true);
-               currentPageIndex = index;
-               currentPage = page;
-       }
-
-       @Override
-       public void updateButtons() {
-               if (back != null)
-                       back.setEnabled(wizard.getPreviousPage(currentPage) != null);
-               if (next != null)
-                       next.setEnabled(wizard.getNextPage(currentPage) != null && currentPage.canFlipToNextPage());
-               if (finish != null) {
-                       finish.setEnabled(wizard.canFinish());
-               }
-       }
-
-       @Override
-       public void updateMessage() {
-               if (currentPage.getMessage() != null)
-                       message.setText(currentPage.getMessage());
-       }
-
-       @Override
-       public void updateTitleBar() {
-               if (currentPage.getTitle() != null)
-                       titleBar.setText(currentPage.getTitle());
-       }
-
-       @Override
-       public void updateWindowTitle() {
-               setTitle(wizard.getWindowTitle());
-       }
-
-       @Override
-       public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
-                       throws InvocationTargetException, InterruptedException {
-               runnable.run(null);
-       }
-
-       @Override
-       public void updateSize() {
-               // TODO pack?
-       }
-
-       protected boolean onCancel() {
-               return wizard.performCancel();
-       }
-
-       protected void nextPressed() {
-               IWizardPage page = wizard.getNextPage(currentPage);
-               showPage(page);
-               updateButtons();
-       }
-
-       protected void backPressed() {
-               IWizardPage page = wizard.getPreviousPage(currentPage);
-               showPage(page);
-               updateButtons();
-       }
-
-       protected void finishPressed() {
-               if (wizard.performFinish())
-                       closeShell(OK);
-       }
-
-       private static void setSwitchingFormData(Composite composite) {
-               FormData fdLabel = new FormData();
-               fdLabel.top = new FormAttachment(0, 0);
-               fdLabel.left = new FormAttachment(0, 0);
-               fdLabel.right = new FormAttachment(100, 0);
-               fdLabel.bottom = new FormAttachment(100, 0);
-               composite.setLayoutData(fdLabel);
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/LightweightDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/LightweightDialog.java
deleted file mode 100644 (file)
index 8f63479..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-package org.argeo.cms.ui.dialogs;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.eclipse.ui.EclipseUiException;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.FocusListener;
-import org.eclipse.swt.events.ShellAdapter;
-import org.eclipse.swt.events.ShellEvent;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-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.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** Generic lightweight dialog, not based on JFace. */
-public class LightweightDialog {
-       private final static Log log = LogFactory.getLog(LightweightDialog.class);
-
-       // must be the same value as org.eclipse.jface.window.Window#OK
-       public final static int OK = 0;
-       // must be the same value as org.eclipse.jface.window.Window#CANCEL
-       public final static int CANCEL = 1;
-
-       private Shell parentShell;
-       private Shell backgroundShell;
-       private Shell foregoundShell;
-
-       private Integer returnCode = null;
-       private boolean block = true;
-
-       private String title;
-
-       /** Tries to find a display */
-       private static Display getDisplay() {
-               try {
-                       Display display = Display.getCurrent();
-                       if (display != null)
-                               return display;
-                       else
-                               return Display.getDefault();
-               } catch (Exception e) {
-                       return Display.getCurrent();
-               }
-       }
-
-       public LightweightDialog(Shell parentShell) {
-               this.parentShell = parentShell;
-       }
-
-       public int open() {
-               if (foregoundShell != null)
-                       throw new EclipseUiException("There is already a shell");
-               backgroundShell = new Shell(parentShell, SWT.ON_TOP);
-               backgroundShell.setFullScreen(true);
-               // if (parentShell != null) {
-               // backgroundShell.setBounds(parentShell.getBounds());
-               // } else
-               // backgroundShell.setMaximized(true);
-               backgroundShell.setAlpha(128);
-               backgroundShell.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
-               foregoundShell = new Shell(backgroundShell, SWT.NO_TRIM | SWT.ON_TOP);
-               if (title != null)
-                       setTitle(title);
-               foregoundShell.setLayout(new GridLayout());
-               foregoundShell.setSize(getInitialSize());
-               createDialogArea(foregoundShell);
-               // shell.pack();
-               // shell.layout();
-
-               Rectangle shellBounds = parentShell != null ? parentShell.getBounds() : Display.getCurrent().getBounds();// RAP
-               Point dialogSize = foregoundShell.getSize();
-               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
-               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
-               foregoundShell.setLocation(x, y);
-
-               foregoundShell.addShellListener(new ShellAdapter() {
-                       private static final long serialVersionUID = -2701270481953688763L;
-
-                       @Override
-                       public void shellDeactivated(ShellEvent e) {
-                               if (hasChildShells())
-                                       return;
-                               if (returnCode == null)// not yet closed
-                                       closeShell(CANCEL);
-                       }
-
-                       @Override
-                       public void shellClosed(ShellEvent e) {
-                               notifyClose();
-                       }
-
-               });
-
-               backgroundShell.open();
-               foregoundShell.open();
-               // after the foreground shell has been opened
-               backgroundShell.addFocusListener(new FocusListener() {
-                       private static final long serialVersionUID = 3137408447474661070L;
-
-                       @Override
-                       public void focusLost(FocusEvent event) {
-                       }
-
-                       @Override
-                       public void focusGained(FocusEvent event) {
-                               if (hasChildShells())
-                                       return;
-                               if (returnCode == null)// not yet closed
-                                       closeShell(CANCEL);
-                       }
-               });
-
-               if (block) {
-                       block();
-               }
-               if (returnCode == null)
-                       returnCode = OK;
-               return returnCode;
-       }
-
-       public void block() {
-               try {
-                       runEventLoop(foregoundShell);
-               } catch (ThreadDeath t) {
-                       returnCode = CANCEL;
-                       if (log.isTraceEnabled())
-                               log.error("Thread death, canceling dialog", t);
-               } catch (Throwable t) {
-                       returnCode = CANCEL;
-                       log.error("Cannot open blocking lightweight dialog", t);
-               }
-       }
-
-       private boolean hasChildShells() {
-               if (foregoundShell == null)
-                       return false;
-               return foregoundShell.getShells().length != 0;
-       }
-
-       // public synchronized int openAndWait() {
-       // open();
-       // while (returnCode == null)
-       // try {
-       // wait(100);
-       // } catch (InterruptedException e) {
-       // // silent
-       // }
-       // return returnCode;
-       // }
-
-       private synchronized void notifyClose() {
-               if (returnCode == null)
-                       returnCode = CANCEL;
-               notifyAll();
-       }
-
-       protected void closeShell(int returnCode) {
-               this.returnCode = returnCode;
-               if (CANCEL == returnCode)
-                       onCancel();
-               if (foregoundShell != null && !foregoundShell.isDisposed()) {
-                       foregoundShell.close();
-                       foregoundShell.dispose();
-                       foregoundShell = null;
-               }
-
-               if (backgroundShell != null && !backgroundShell.isDisposed()) {
-                       backgroundShell.close();
-                       backgroundShell.dispose();
-               }
-       }
-
-       protected Point getInitialSize() {
-               // if (exception != null)
-               // return new Point(800, 600);
-               // else
-               return new Point(600, 400);
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogarea = new Composite(parent, SWT.NONE);
-               dialogarea.setLayout(new GridLayout());
-               dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               return dialogarea;
-       }
-
-       protected Shell getBackgroundShell() {
-               return backgroundShell;
-       }
-
-       protected Shell getForegoundShell() {
-               return foregoundShell;
-       }
-
-       public void setBlockOnOpen(boolean shouldBlock) {
-               block = shouldBlock;
-       }
-
-       public void pack() {
-               foregoundShell.pack();
-       }
-
-       private void runEventLoop(Shell loopShell) {
-               Display display;
-               if (foregoundShell == null) {
-                       display = Display.getCurrent();
-               } else {
-                       display = loopShell.getDisplay();
-               }
-
-               while (loopShell != null && !loopShell.isDisposed()) {
-                       try {
-                               if (!display.readAndDispatch()) {
-                                       display.sleep();
-                               }
-                       } catch (UnsupportedOperationException e) {
-                               throw e;
-                       } catch (Throwable e) {
-                               handleException(e);
-                       }
-               }
-               if (!display.isDisposed())
-                       display.update();
-       }
-
-       protected void handleException(Throwable t) {
-               if (t instanceof ThreadDeath) {
-                       // Don't catch ThreadDeath as this is a normal occurrence when
-                       // the thread dies
-                       throw (ThreadDeath) t;
-               }
-               // Try to keep running.
-               t.printStackTrace();
-       }
-
-       /** @return false, if the dialog should not be closed. */
-       protected boolean onCancel() {
-               return true;
-       }
-
-       public void setTitle(String title) {
-               this.title = title;
-               if (title != null && getForegoundShell() != null)
-                       getForegoundShell().setText(title);
-       }
-
-       public Integer getReturnCode() {
-               return returnCode;
-       }
-
-}
\ No newline at end of file
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/SingleValueDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/SingleValueDialog.java
deleted file mode 100644 (file)
index 45a227e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.argeo.cms.ui.dialogs;
-
-import org.eclipse.jface.window.Window;
-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.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/** A dialog asking a for a single value. */
-public class SingleValueDialog extends CmsMessageDialog {
-       private Text valueT;
-       private String value;
-       private String defaultValue;
-
-       public SingleValueDialog(Shell parentShell, String message) {
-               super(parentShell, message, QUESTION);
-       }
-
-       public SingleValueDialog(Shell parentShell, String message, String defaultValue) {
-               super(parentShell, message, QUESTION);
-               this.defaultValue = defaultValue;
-       }
-
-       @Override
-       protected Control createInputArea(Composite parent) {
-               valueT = new Text(parent, SWT.LEAD | SWT.BORDER | SWT.SINGLE);
-               valueT.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
-               if (defaultValue != null)
-                       valueT.setText(defaultValue);
-               return valueT;
-       }
-
-       @Override
-       protected void okPressed() {
-               value = valueT.getText();
-               super.okPressed();
-       }
-
-       public String getString() {
-               return value;
-       }
-
-       public Long getLong() {
-               return Long.valueOf(getString());
-       }
-
-       public Double getDouble() {
-               return Double.valueOf(getString());
-       }
-
-       public static String ask(String message) {
-               return ask(message, null);
-       }
-
-       public static String ask(String message, String defaultValue) {
-               SingleValueDialog svd = new SingleValueDialog(Display.getCurrent().getActiveShell(), message, defaultValue);
-               if (svd.open() == Window.OK)
-                       return svd.getString();
-               else
-                       return null;
-       }
-
-       public static Long askLong(String message) {
-               SingleValueDialog svd = new SingleValueDialog(Display.getCurrent().getActiveShell(), message);
-               if (svd.open() == Window.OK)
-                       return svd.getLong();
-               else
-                       return null;
-       }
-
-       public static Double askDouble(String message) {
-               SingleValueDialog svd = new SingleValueDialog(Display.getCurrent().getActiveShell(), message);
-               if (svd.open() == Window.OK)
-                       return svd.getDouble();
-               else
-                       return null;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/package-info.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/dialogs/package-info.java
deleted file mode 100644 (file)
index c88ac07..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/** SWT/JFace dialogs. */
-package org.argeo.cms.ui.dialogs;
\ No newline at end of file
index 2b3f61e943883edd819c620909d6fc2e5ff100ed..fd3f48e3a9cfa3b97c46ff22fa866e3b5e0429f1 100644 (file)
@@ -5,7 +5,7 @@ import java.util.List;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.viewers.EditablePart;
 import org.argeo.cms.ui.widgets.StyledControl;
 import org.argeo.eclipse.ui.EclipseUiUtils;
@@ -70,7 +70,7 @@ public class EditableMultiStringProperty extends StyledControl implements Editab
 
        /** To be overridden */
        protected void setContainerLayoutData(Composite composite) {
-               composite.setLayoutData(CmsUiUtils.fillWidth());
+               composite.setLayoutData(CmsSwtUtils.fillWidth());
        }
 
        @Override
@@ -115,8 +115,8 @@ public class EditableMultiStringProperty extends StyledControl implements Editab
        protected Label createValueLabel(Composite parent, int style, String value) {
                Label label = new Label(parent, style);
                label.setText("#" + value);
-               CmsUiUtils.markup(label);
-               CmsUiUtils.style(label, FormStyle.propertyText.style());
+               CmsSwtUtils.markup(label);
+               CmsSwtUtils.style(label, FormStyle.propertyText.style());
                return label;
        }
 
@@ -131,7 +131,7 @@ public class EditableMultiStringProperty extends StyledControl implements Editab
                Button deleteBtn = new Button(valCmp, SWT.FLAT);
                deleteBtn.setData(FormConstants.LINKED_VALUE, value);
                deleteBtn.addSelectionListener(removeValueSL);
-               CmsUiUtils.style(deleteBtn, FormStyle.delete.style() + FormStyle.BUTTON_SUFFIX);
+               CmsSwtUtils.style(deleteBtn, FormStyle.delete.style() + FormStyle.BUTTON_SUFFIX);
                GridData gd = new GridData();
                gd.heightHint = btnHeight;
                gd.widthHint = btnWidth;
@@ -146,7 +146,7 @@ public class EditableMultiStringProperty extends StyledControl implements Editab
                // The "add new value" text is not meant to change, so we can set it on
                // creation
                text.setMessage(message);
-               CmsUiUtils.style(text, style);
+               CmsSwtUtils.style(text, style);
                text.setFocus();
 
                text.addTraverseListener(new TraverseListener() {
@@ -211,8 +211,8 @@ public class EditableMultiStringProperty extends StyledControl implements Editab
                if (canEdit) {
                        Label lbl = new Label(box, getStyle());
                        lbl.setText(message);
-                       CmsUiUtils.style(lbl, style);
-                       CmsUiUtils.markup(lbl);
+                       CmsSwtUtils.style(lbl, style);
+                       CmsSwtUtils.markup(lbl);
                        if (mouseListener != null)
                                lbl.addMouseListener(mouseListener);
                        return lbl;
@@ -244,13 +244,13 @@ public class EditableMultiStringProperty extends StyledControl implements Editab
        }
 
        public synchronized void startEditing() {
-               CmsUiUtils.style(getControl(), FormStyle.propertyText.style());
+               CmsSwtUtils.style(getControl(), FormStyle.propertyText.style());
 //             getControl().setData(STYLE, FormStyle.propertyText.style());
                super.startEditing();
        }
 
        public synchronized void stopEditing() {
-               CmsUiUtils.style(getControl(), FormStyle.propertyMessage.style());
+               CmsSwtUtils.style(getControl(), FormStyle.propertyMessage.style());
 //             getControl().setData(STYLE, FormStyle.propertyMessage.style());
                super.stopEditing();
        }
index fd7095f87d4b0671147f9aa5b6f591945c97befe..8591a925f1a2ef1be55adcd79b41846ba9d785bc 100644 (file)
@@ -7,7 +7,7 @@ import java.util.GregorianCalendar;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.viewers.EditablePart;
 import org.argeo.cms.ui.widgets.StyledControl;
 import org.argeo.eclipse.ui.EclipseUiUtils;
@@ -91,17 +91,17 @@ public class EditablePropertyDate extends StyledControl implements EditablePart
 
        public synchronized void startEditing() {
                // if (dateTxt != null && !dateTxt.isDisposed())
-               CmsUiUtils.style(getControl(), FormStyle.propertyText);
+               CmsSwtUtils.style(getControl(), FormStyle.propertyText);
 //             getControl().setData(STYLE, FormStyle.propertyText.style());
                super.startEditing();
        }
 
        public synchronized void stopEditing() {
                if (EclipseUiUtils.isEmpty(dateTxt.getText()))
-                       CmsUiUtils.style(getControl(), FormStyle.propertyMessage);
+                       CmsSwtUtils.style(getControl(), FormStyle.propertyMessage);
 //                     getControl().setData(STYLE, FormStyle.propertyMessage.style());
                else
-                       CmsUiUtils.style(getControl(), FormStyle.propertyText);
+                       CmsSwtUtils.style(getControl(), FormStyle.propertyText);
 //             getControl().setData(STYLE, FormStyle.propertyText.style());
                super.stopEditing();
        }
@@ -120,27 +120,27 @@ public class EditablePropertyDate extends StyledControl implements EditablePart
 
        protected Label createLabel(Composite box, String style) {
                Label lbl = new Label(box, getStyle() | SWT.WRAP);
-               lbl.setLayoutData(CmsUiUtils.fillWidth());
-               CmsUiUtils.style(lbl, style);
-               CmsUiUtils.markup(lbl);
+               lbl.setLayoutData(CmsSwtUtils.fillWidth());
+               CmsSwtUtils.style(lbl, style);
+               CmsSwtUtils.markup(lbl);
                if (mouseListener != null)
                        lbl.addMouseListener(mouseListener);
                return lbl;
        }
 
        private Control createCustomEditableControl(Composite box, String style) {
-               box.setLayoutData(CmsUiUtils.fillWidth());
+               box.setLayoutData(CmsSwtUtils.fillWidth());
                Composite dateComposite = new Composite(box, SWT.NONE);
                GridLayout gl = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, false));
                gl.horizontalSpacing = fieldBtnSpacing;
                dateComposite.setLayout(gl);
                dateTxt = new Text(dateComposite, SWT.BORDER);
-               CmsUiUtils.style(dateTxt, style);
+               CmsSwtUtils.style(dateTxt, style);
                dateTxt.setLayoutData(new GridData(120, SWT.DEFAULT));
                dateTxt.setToolTipText(
                                "Enter a date with form \"" + FormUtils.DEFAULT_SHORT_DATE_FORMAT + "\" or use the calendar");
                openCalBtn = new Button(dateComposite, SWT.FLAT);
-               CmsUiUtils.style(openCalBtn, FormStyle.calendar.style() + FormStyle.BUTTON_SUFFIX);
+               CmsSwtUtils.style(openCalBtn, FormStyle.calendar.style() + FormStyle.BUTTON_SUFFIX);
                GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false);
                gd.heightHint = 17;
                openCalBtn.setLayoutData(gd);
@@ -224,8 +224,8 @@ public class EditablePropertyDate extends StyledControl implements EditablePart
                        super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP);
                        populate();
                        // Add border and shadow style
-                       CmsUiUtils.markup(CalendarPopup.this);
-                       CmsUiUtils.style(CalendarPopup.this, FormStyle.popupCalendar.style());
+                       CmsSwtUtils.markup(CalendarPopup.this);
+                       CmsSwtUtils.style(CalendarPopup.this, FormStyle.popupCalendar.style());
                        pack();
                        layout();
                        setLocation(source.toDisplay((source.getLocation().x - 2), (source.getSize().y) + 3));
index c170e8c2f9e5361a9f7306cb9db8d6e11ab7860d..09200935524f6072a5c957016e6f29e8a2d4face 100644 (file)
@@ -6,7 +6,7 @@ import static org.argeo.cms.ui.forms.FormStyle.propertyText;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.viewers.EditablePart;
 import org.argeo.cms.ui.widgets.EditableText;
 import org.argeo.eclipse.ui.EclipseUiUtils;
@@ -62,15 +62,15 @@ public class EditablePropertyString extends EditableText implements EditablePart
        }
 
        public synchronized void startEditing() {
-               CmsUiUtils.style(getControl(), FormStyle.propertyText);
+               CmsSwtUtils.style(getControl(), FormStyle.propertyText);
                super.startEditing();
        }
 
        public synchronized void stopEditing() {
                if (EclipseUiUtils.isEmpty(((Text) getControl()).getText()))
-                       CmsUiUtils.style(getControl(), FormStyle.propertyMessage);
+                       CmsSwtUtils.style(getControl(), FormStyle.propertyMessage);
                else
-                       CmsUiUtils.style(getControl(), FormStyle.propertyText);
+                       CmsSwtUtils.style(getControl(), FormStyle.propertyText);
                super.stopEditing();
        }
 
index 7d4612731758035c8b34526cc0144f62c663ae27..f3a56f7b9215187e42e3c9ddc2a0df5d9125a490 100644 (file)
@@ -5,8 +5,8 @@ import java.util.Observer;
 
 import javax.jcr.Node;
 
-import org.argeo.cms.ui.CmsEditable;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.api.cms.CmsEditable;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
@@ -57,10 +57,10 @@ public class FormEditorHeader implements SelectionListener, Observer {
                display = new Composite(parent, SWT.NONE);
                display.setLayoutData(layoutData);
 
-               CmsUiUtils.style(display, FormStyle.header.style());
+               CmsSwtUtils.style(display, FormStyle.header.style());
                display.setBackgroundMode(SWT.INHERIT_FORCE);
 
-               display.setLayout(CmsUiUtils.noSpaceGridLayout());
+               display.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                publishBtn = createSimpleBtn(display, getPublishButtonLabel());
                display.moveAbove(null);
@@ -70,7 +70,7 @@ public class FormEditorHeader implements SelectionListener, Observer {
        private Button createSimpleBtn(Composite parent, String label) {
                Button button = new Button(parent, SWT.FLAT | SWT.PUSH);
                button.setText(label);
-               CmsUiUtils.style(button, FormStyle.header.style());
+               CmsSwtUtils.style(button, FormStyle.header.style());
                button.addSelectionListener(this);
                return button;
        }
index 981f6efc5aafba314d0cab21c28f6b712d8cbc24..bf0e86beae2c27ad91d5d123c281b4ee990e62bd 100644 (file)
@@ -16,10 +16,10 @@ import javax.jcr.ValueFormatException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.ui.CmsEditable;
-import org.argeo.cms.ui.CmsImageManager;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.api.cms.CmsEditable;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.viewers.AbstractPageViewer;
 import org.argeo.cms.ui.viewers.EditablePart;
 import org.argeo.cms.ui.viewers.Section;
@@ -74,7 +74,7 @@ public class FormPageViewer extends AbstractPageViewer {
        // Context cached in the viewer
        // The reference to translate from text to calendar and reverse
        private DateFormat dateFormat = new SimpleDateFormat(FormUtils.DEFAULT_SHORT_DATE_FORMAT);
-       private CmsImageManager imageManager;
+       private CmsImageManager<Control, Node> imageManager;
        private FileUploadListener fileUploadListener;
 
        public FormPageViewer(Section mainSection, int style, CmsEditable cmsEditable) throws RepositoryException {
@@ -304,9 +304,9 @@ public class FormPageViewer extends AbstractPageViewer {
                return mainSection;
        }
 
-       protected CmsImageManager imageManager() {
+       protected CmsImageManager<Control, Node> imageManager() {
                if (imageManager == null)
-                       imageManager = CmsView.getCmsView(mainSection).getImageManager();
+                       imageManager = (CmsImageManager<Control, Node>) CmsSwtUtils.getCmsView(mainSection).getImageManager();
                return imageManager;
        }
 
@@ -315,8 +315,8 @@ public class FormPageViewer extends AbstractPageViewer {
                Section section = null;
                if (node != null) {
                        section = new Section(body, SWT.NO_FOCUS, node);
-                       section.setLayoutData(CmsUiUtils.fillWidth());
-                       section.setLayout(CmsUiUtils.noSpaceGridLayout());
+                       section.setLayoutData(CmsSwtUtils.fillWidth());
+                       section.setLayout(CmsSwtUtils.noSpaceGridLayout());
                }
                return section;
        }
@@ -328,7 +328,7 @@ public class FormPageViewer extends AbstractPageViewer {
                        EditablePropertyString eps = new EditablePropertyString(bodyRow, SWT.WRAP | SWT.LEFT, node, propName, msg);
                        eps.setMouseListener(getMouseListener());
                        eps.setFocusListener(getFocusListener());
-                       eps.setLayoutData(CmsUiUtils.fillWidth());
+                       eps.setLayoutData(CmsSwtUtils.fillWidth());
                }
        }
 
@@ -353,7 +353,7 @@ public class FormPageViewer extends AbstractPageViewer {
                        addListeners(emsp);
                        // emsp.setMouseListener(getMouseListener());
                        emsp.setStyle(FormStyle.propertyMessage.style());
-                       emsp.setLayoutData(CmsUiUtils.fillWidth());
+                       emsp.setLayoutData(CmsSwtUtils.fillWidth());
                }
        }
 
@@ -365,7 +365,7 @@ public class FormPageViewer extends AbstractPageViewer {
                // boolean isSmall = CmsView.getCmsView(parent).getUxContext().isSmall();
                Label label = new Label(parent, SWT.LEAD | SWT.WRAP);
                label.setText(value + " ");
-               CmsUiUtils.style(label, FormStyle.propertyLabel.style());
+               CmsSwtUtils.style(label, FormStyle.propertyLabel.style());
                GridData gd = new GridData(SWT.LEAD, vAlign, false, false);
                if (labelColWidth != null)
                        gd.widthHint = labelColWidth;
@@ -376,13 +376,13 @@ public class FormPageViewer extends AbstractPageViewer {
        protected Label newStyledLabel(Composite parent, String style, String value) {
                Label label = new Label(parent, SWT.NONE);
                label.setText(value);
-               CmsUiUtils.style(label, style);
+               CmsSwtUtils.style(label, style);
                return label;
        }
 
        protected Composite createRowLayoutComposite(Composite parent) throws RepositoryException {
                Composite bodyRow = new Composite(parent, SWT.NO_FOCUS);
-               bodyRow.setLayoutData(CmsUiUtils.fillWidth());
+               bodyRow.setLayoutData(CmsSwtUtils.fillWidth());
                RowLayout rl = new RowLayout(SWT.WRAP);
                rl.type = SWT.HORIZONTAL;
                rl.spacing = rowLayoutHSpacing;
@@ -448,24 +448,20 @@ public class FormPageViewer extends AbstractPageViewer {
                        // for a while
                        cleanedName = System.currentTimeMillis() % 100000 + "_" + cleanedName;
 
-                       try {
-                               imageManager().uploadImage(context, context, cleanedName, stream, details.getContentType());
-                               // TODO clean refresh strategy
-                               section.getDisplay().asyncExec(new Runnable() {
-                                       @Override
-                                       public void run() {
-                                               try {
-                                                       FormPageViewer.this.refresh(section);
-                                                       section.layout();
-                                                       section.getParent().layout();
-                                               } catch (RepositoryException re) {
-                                                       throw new JcrException("Unable to refresh " + "image section for " + context, re);
-                                               }
+                       imageManager().uploadImage(context, context, cleanedName, stream, details.getContentType());
+                       // TODO clean refresh strategy
+                       section.getDisplay().asyncExec(new Runnable() {
+                               @Override
+                               public void run() {
+                                       try {
+                                               FormPageViewer.this.refresh(section);
+                                               section.layout();
+                                               section.getParent().layout();
+                                       } catch (RepositoryException re) {
+                                               throw new JcrException("Unable to refresh " + "image section for " + context, re);
                                        }
-                               });
-                       } catch (RepositoryException re) {
-                               throw new JcrException("unable to upload image " + name + " at " + context, re);
-                       }
+                               }
+                       });
                }
        }
 
@@ -475,20 +471,20 @@ public class FormPageViewer extends AbstractPageViewer {
        }
 
        protected Img createImgComposite(Composite parent, Node node, Point preferredSize) throws RepositoryException {
-               Img img = new Img(parent, SWT.NONE, node, preferredSize) {
+               Img img = new Img(parent, SWT.NONE, node, new Cms2DSize(preferredSize.x, preferredSize.y)) {
                        private static final long serialVersionUID = 1297900641952417540L;
 
                        @Override
                        protected void setContainerLayoutData(Composite composite) {
-                               composite.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
+                               composite.setLayoutData(CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
                        }
 
                        @Override
                        protected void setControlLayoutData(Control control) {
-                               control.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
+                               control.setLayoutData(CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
                        }
                };
-               img.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
+               img.setLayoutData(CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
                updateContent(img);
                addListeners(img);
                return img;
@@ -497,7 +493,7 @@ public class FormPageViewer extends AbstractPageViewer {
        protected Composite addDeleteAbility(final Section section, final Node sessionNode, int topWeight,
                        int rightWeight) {
                Composite comp = new Composite(section, SWT.NONE);
-               comp.setLayoutData(CmsUiUtils.fillAll());
+               comp.setLayoutData(CmsSwtUtils.fillAll());
                comp.setLayout(new FormLayout());
 
                // The body to be populated
@@ -507,7 +503,7 @@ public class FormPageViewer extends AbstractPageViewer {
                if (getCmsEditable().canEdit()) {
                        // the delete button
                        Button deleteBtn = new Button(comp, SWT.FLAT);
-                       CmsUiUtils.style(deleteBtn, FormStyle.deleteOverlay.style());
+                       CmsSwtUtils.style(deleteBtn, FormStyle.deleteOverlay.style());
                        FormData formData = new FormData();
                        formData.right = new FormAttachment(rightWeight, 0);
                        formData.top = new FormAttachment(topWeight, 0);
index 7a05e2b2bdb841dd68531c0d566f7757ae6476c4..24067eaaa91de29d604ea2df51d16f1fc363d6c1 100644 (file)
@@ -1,6 +1,6 @@
 package org.argeo.cms.ui.forms;
 
-import org.argeo.cms.ui.util.CmsStyle;
+import org.argeo.api.cms.CmsStyle;
 
 /** Syles used */
 public enum FormStyle implements CmsStyle {
index a5475d6e5cf4a4a7bdc6294e703bb317fa2eb346..822473973d05b506f01c73c53be0fa10bc02cdec 100644 (file)
@@ -11,8 +11,8 @@ import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.cms.CmsView;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.CmsView;
 import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.eclipse.jface.fieldassist.ControlDecoration;
index 4a7e9bd3fb8dc3cc7702af54c4a7aca83e7ffec5..5a5ecdb8bf4be58e19c0476e779d16d4cad2e6a2 100644 (file)
@@ -21,7 +21,7 @@ import javax.jcr.Session;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.jcr.CmsJcrUtils;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.eclipse.ui.ColumnDefinition;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.eclipse.ui.fs.FileIconNameLabelProvider;
@@ -277,7 +277,7 @@ public class CmsFsBrowser extends Composite {
                else
                        nameStr = path.getFileName().toString();
                elemBtn.setText(nameStr + " >> ");
-               CmsUiUtils.style(elemBtn, FsStyles.BREAD_CRUMB_BTN);
+               CmsSwtUtils.style(elemBtn, FsStyles.BREAD_CRUMB_BTN);
                elemBtn.addSelectionListener(new SelectionAdapter() {
                        private static final long serialVersionUID = -4103695476023480651L;
 
@@ -323,7 +323,7 @@ public class CmsFsBrowser extends Composite {
        }
 
        private void populateBookmarks(Composite parent) {
-               CmsUiUtils.clear(parent);
+               CmsSwtUtils.clear(parent);
                parent.setLayout(new GridLayout());
                ISelectionChangedListener selList = new BookmarksSelChangeListener();
 
index f45629b04278900acb7bdf1b6237bce83c85ee1c..03ec415d8fc201b355ef5a03c6a4b35f92b8fe20 100644 (file)
@@ -18,7 +18,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.eclipse.ui.dialogs.SingleValue;
 import org.eclipse.jface.dialogs.MessageDialog;
@@ -70,7 +70,7 @@ public class FsContextMenu extends Shell {
 
                Composite boxCmp = new Composite(this, SWT.NO_FOCUS | SWT.BORDER);
                boxCmp.setLayout(EclipseUiUtils.noSpaceGridLayout());
-               CmsUiUtils.style(boxCmp, FsStyles.CONTEXT_MENU_BOX);
+               CmsSwtUtils.style(boxCmp, FsStyles.CONTEXT_MENU_BOX);
                createContextMenu(boxCmp);
 
                addShellListener(new ActionsShellListener());
@@ -82,8 +82,8 @@ public class FsContextMenu extends Shell {
                        Button btn = new Button(boxCmp, SWT.FLAT | SWT.PUSH | SWT.LEAD);
                        btn.setText(getLabel(actionId));
                        btn.setLayoutData(EclipseUiUtils.fillWidth());
-                       CmsUiUtils.markup(btn);
-                       CmsUiUtils.style(btn, actionId + FsStyles.BUTTON_SUFFIX);
+                       CmsSwtUtils.markup(btn);
+                       CmsSwtUtils.style(btn, actionId + FsStyles.BUTTON_SUFFIX);
                        btn.setData(KEY_ACTION_ID, actionId);
                        btn.addSelectionListener(asl);
                        actionButtons.put(actionId, btn);
index c2399968b0372b11ce547a7f2cc518faa1d2f855..c8582f0c124839552df82b55b22d3ba0febefaeb 100644 (file)
@@ -11,7 +11,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.NodeType;
 
 import org.apache.commons.io.FilenameUtils;
-import org.argeo.cms.ui.CmsImageManager;
+import org.argeo.api.cms.CmsImageManager;
 import org.argeo.cms.ui.widgets.Img;
 import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
index 5602d991b0b88a70f9dab4215ff3e618aec0a215..c5c1a01a2ac045a7d7e8ec6da9bf12fe62143c97 100644 (file)
@@ -2,9 +2,10 @@ package org.argeo.cms.ui.internal;
 
 import javax.jcr.RepositoryException;
 
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.cms.ui.widgets.EditableImage;
-import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Text;
@@ -14,7 +15,7 @@ public class SimpleEditableImage extends EditableImage {
        private static final long serialVersionUID = -5689145523114022890L;
 
        private String src;
-       private Point imageSize;
+       private Cms2DSize imageSize;
 
        public SimpleEditableImage(Composite parent, int swtStyle) {
                super(parent, swtStyle);
@@ -22,8 +23,7 @@ public class SimpleEditableImage extends EditableImage {
                getParent().layout();
        }
 
-       public SimpleEditableImage(Composite parent, int swtStyle, String src,
-                       Point imageSize) {
+       public SimpleEditableImage(Composite parent, int swtStyle, String src, Cms2DSize imageSize) {
                super(parent, swtStyle);
                this.src = src;
                this.imageSize = imageSize;
@@ -43,14 +43,13 @@ public class SimpleEditableImage extends EditableImage {
                if (src != null)
                        imgTag = CmsUiUtils.img(src, imageSize);
                else
-                       imgTag = CmsUiUtils.noImg(imageSize != null ? imageSize
-                                       : NO_IMAGE_SIZE);
+                       imgTag = CmsUiUtils.noImg(imageSize != null ? imageSize : NO_IMAGE_SIZE);
                return imgTag;
        }
 
        protected Text createText(Composite box, String style) {
                Text text = new Text(box, getStyle());
-               CmsUiUtils.style(text, style);
+               CmsSwtUtils.style(text, style);
                return text;
        }
 
@@ -62,11 +61,11 @@ public class SimpleEditableImage extends EditableImage {
                this.src = src;
        }
 
-       public Point getImageSize() {
+       public Cms2DSize getImageSize() {
                return imageSize;
        }
 
-       public void setImageSize(Point imageSize) {
+       public void setImageSize(Cms2DSize imageSize) {
                this.imageSize = imageSize;
        }
 
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/internal/rwt/UserUi.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/internal/rwt/UserUi.java
deleted file mode 100644 (file)
index 5e21cc4..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.argeo.cms.ui.internal.rwt;
-
-import org.argeo.cms.ui.util.LoginEntryPoint;
-import org.eclipse.rap.rwt.application.Application;
-import org.eclipse.rap.rwt.application.Application.OperationMode;
-import org.eclipse.rap.rwt.application.ApplicationConfiguration;
-
-public class UserUi implements ApplicationConfiguration {
-       @Override
-       public void configure(Application application) {
-               application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
-               application.addEntryPoint("/login", LoginEntryPoint.class, null);
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/PickUpUserDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/PickUpUserDialog.java
deleted file mode 100644 (file)
index d074254..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-package org.argeo.cms.ui.useradmin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.argeo.api.NodeConstants;
-import org.argeo.eclipse.ui.ColumnDefinition;
-import org.argeo.eclipse.ui.EclipseUiException;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.parts.LdifUsersTable;
-import org.argeo.naming.LdapAttrs;
-import org.argeo.naming.LdapObjs;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.dialogs.TrayDialog;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.layout.FillLayout;
-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.Shell;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/** Dialog with a user (or group) list to pick up one */
-public class PickUpUserDialog extends TrayDialog {
-       private static final long serialVersionUID = -1420106871173920369L;
-
-       // Business objects
-       private final UserAdmin userAdmin;
-       private User selectedUser;
-
-       // this page widgets and UI objects
-       private String title;
-       private LdifUsersTable userTableViewerCmp;
-       private TableViewer userViewer;
-       private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
-
-       /**
-        * A dialog to pick up a group or a user, showing a table with default
-        * columns
-        */
-       public PickUpUserDialog(Shell parentShell, String title, UserAdmin userAdmin) {
-               super(parentShell);
-               this.title = title;
-               this.userAdmin = userAdmin;
-
-               columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_ICON), "",
-                               24, 24));
-               columnDefs.add(new ColumnDefinition(
-                               new UserLP(UserLP.COL_DISPLAY_NAME), "Common Name", 150, 100));
-               columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_DOMAIN),
-                               "Domain", 100, 120));
-               columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_DN),
-                               "Distinguished Name", 300, 100));
-       }
-
-       /** A dialog to pick up a group or a user */
-       public PickUpUserDialog(Shell parentShell, String title,
-                       UserAdmin userAdmin, List<ColumnDefinition> columnDefs) {
-               super(parentShell);
-               this.title = title;
-               this.userAdmin = userAdmin;
-               this.columnDefs = columnDefs;
-       }
-
-       @Override
-       protected void okPressed() {
-               if (getSelected() == null)
-                       MessageDialog.openError(getShell(), "No user chosen",
-                                       "Please, choose a user or press Cancel.");
-               else
-                       super.okPressed();
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogArea = (Composite) super.createDialogArea(parent);
-               dialogArea.setLayout(new FillLayout());
-
-               Composite bodyCmp = new Composite(dialogArea, SWT.NO_FOCUS);
-               bodyCmp.setLayout(new GridLayout());
-
-               // Create and configure the table
-               userTableViewerCmp = new MyUserTableViewer(bodyCmp, SWT.MULTI
-                               | SWT.H_SCROLL | SWT.V_SCROLL);
-
-               userTableViewerCmp.setColumnDefinitions(columnDefs);
-               userTableViewerCmp.populateWithStaticFilters(false, false);
-               GridData gd = EclipseUiUtils.fillAll();
-               gd.minimumHeight = 300;
-               userTableViewerCmp.setLayoutData(gd);
-               userTableViewerCmp.refresh();
-
-               // Controllers
-               userViewer = userTableViewerCmp.getTableViewer();
-               userViewer.addDoubleClickListener(new MyDoubleClickListener());
-               userViewer
-                               .addSelectionChangedListener(new MySelectionChangedListener());
-
-               parent.pack();
-               return dialogArea;
-       }
-
-       public User getSelected() {
-               if (selectedUser == null)
-                       return null;
-               else
-                       return selectedUser;
-       }
-
-       protected void configureShell(Shell shell) {
-               super.configureShell(shell);
-               shell.setText(title);
-       }
-
-       class MyDoubleClickListener implements IDoubleClickListener {
-               public void doubleClick(DoubleClickEvent evt) {
-                       if (evt.getSelection().isEmpty())
-                               return;
-
-                       Object obj = ((IStructuredSelection) evt.getSelection())
-                                       .getFirstElement();
-                       if (obj instanceof User) {
-                               selectedUser = (User) obj;
-                               okPressed();
-                       }
-               }
-       }
-
-       class MySelectionChangedListener implements ISelectionChangedListener {
-               @Override
-               public void selectionChanged(SelectionChangedEvent event) {
-                       if (event.getSelection().isEmpty()) {
-                               selectedUser = null;
-                               return;
-                       }
-                       Object obj = ((IStructuredSelection) event.getSelection())
-                                       .getFirstElement();
-                       if (obj instanceof Group) {
-                               selectedUser = (Group) obj;
-                       }
-               }
-       }
-
-       private class MyUserTableViewer extends LdifUsersTable {
-               private static final long serialVersionUID = 8467999509931900367L;
-
-               private final String[] knownProps = { LdapAttrs.uid.name(),
-                               LdapAttrs.cn.name(), LdapAttrs.DN };
-
-               private Button showSystemRoleBtn;
-               private Button showUserBtn;
-
-               public MyUserTableViewer(Composite parent, int style) {
-                       super(parent, style);
-               }
-
-               protected void populateStaticFilters(Composite staticFilterCmp) {
-                       staticFilterCmp.setLayout(new GridLayout());
-                       showSystemRoleBtn = new Button(staticFilterCmp, SWT.CHECK);
-                       showSystemRoleBtn.setText("Show system roles  ");
-
-                       showUserBtn = new Button(staticFilterCmp, SWT.CHECK);
-                       showUserBtn.setText("Show users  ");
-
-                       SelectionListener sl = new SelectionAdapter() {
-                               private static final long serialVersionUID = -7033424592697691676L;
-
-                               @Override
-                               public void widgetSelected(SelectionEvent e) {
-                                       refresh();
-                               }
-                       };
-
-                       showSystemRoleBtn.addSelectionListener(sl);
-                       showUserBtn.addSelectionListener(sl);
-               }
-
-               @Override
-               protected List<User> listFilteredElements(String filter) {
-                       Role[] roles;
-                       try {
-                               StringBuilder builder = new StringBuilder();
-
-                               StringBuilder filterBuilder = new StringBuilder();
-                               if (notNull(filter))
-                                       for (String prop : knownProps) {
-                                               filterBuilder.append("(");
-                                               filterBuilder.append(prop);
-                                               filterBuilder.append("=*");
-                                               filterBuilder.append(filter);
-                                               filterBuilder.append("*)");
-                                       }
-
-                               String typeStr = "(" + LdapAttrs.objectClass.name() + "="
-                                               + LdapObjs.groupOfNames.name() + ")";
-                               if ((showUserBtn.getSelection()))
-                                       typeStr = "(|(" + LdapAttrs.objectClass.name() + "="
-                                                       + LdapObjs.inetOrgPerson.name() + ")" + typeStr
-                                                       + ")";
-
-                               if (!showSystemRoleBtn.getSelection())
-                                       typeStr = "(& " + typeStr + "(!(" + LdapAttrs.DN + "=*"
-                                                       + NodeConstants.ROLES_BASEDN + ")))";
-
-                               if (filterBuilder.length() > 1) {
-                                       builder.append("(&" + typeStr);
-                                       builder.append("(|");
-                                       builder.append(filterBuilder.toString());
-                                       builder.append("))");
-                               } else {
-                                       builder.append(typeStr);
-                               }
-                               roles = userAdmin.getRoles(builder.toString());
-                       } catch (InvalidSyntaxException e) {
-                               throw new EclipseUiException(
-                                               "Unable to get roles with filter: " + filter, e);
-                       }
-                       List<User> users = new ArrayList<User>();
-                       for (Role role : roles)
-                               if (!users.contains(role))
-                                       users.add((User) role);
-                       return users;
-               }
-       }
-
-       private boolean notNull(String string) {
-               if (string == null)
-                       return false;
-               else
-                       return !"".equals(string.trim());
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/UserLP.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/UserLP.java
deleted file mode 100644 (file)
index 05c6f37..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.argeo.cms.ui.useradmin;
-
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.auth.UserAdminUtils;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-/** Centralize label providers for the group table */
-class UserLP extends ColumnLabelProvider {
-       private static final long serialVersionUID = -4645930210988368571L;
-
-       final static String COL_ICON = "colID.icon";
-       final static String COL_DN = "colID.dn";
-       final static String COL_DISPLAY_NAME = "colID.displayName";
-       final static String COL_DOMAIN = "colID.domain";
-
-       final String currType;
-
-       // private Font italic;
-       private Font bold;
-
-       UserLP(String colId) {
-               this.currType = colId;
-       }
-
-       @Override
-       public Font getFont(Object element) {
-               // Current user as bold
-               if (UserAdminUtils.isCurrentUser(((User) element))) {
-                       if (bold == null)
-                               bold = JFaceResources.getFontRegistry().defaultFontDescriptor().setStyle(SWT.BOLD)
-                                               .createFont(Display.getCurrent());
-                       return bold;
-               }
-               return null;
-       }
-
-       @Override
-       public Image getImage(Object element) {
-               if (COL_ICON.equals(currType)) {
-                       User user = (User) element;
-                       String dn = user.getName();
-                       if (dn.endsWith(NodeConstants.ROLES_BASEDN))
-                               return UsersImages.ICON_ROLE;
-                       else if (user.getType() == Role.GROUP)
-                               return UsersImages.ICON_GROUP;
-                       else
-                               return UsersImages.ICON_USER;
-               } else
-                       return null;
-       }
-
-       @Override
-       public String getText(Object element) {
-               User user = (User) element;
-               return getText(user);
-
-       }
-
-       public String getText(User user) {
-               if (COL_DN.equals(currType))
-                       return user.getName();
-               else if (COL_DISPLAY_NAME.equals(currType))
-                       return UserAdminUtils.getCommonName(user);
-               else if (COL_DOMAIN.equals(currType))
-                       return UserAdminUtils.getDomainName(user);
-               else
-                       return "";
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/UsersImages.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/UsersImages.java
deleted file mode 100644 (file)
index eca4867..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.argeo.cms.ui.useradmin;
-
-import org.argeo.cms.ui.theme.CmsImages;
-import org.eclipse.swt.graphics.Image;
-
-/** Specific users icons. */
-public class UsersImages {
-       private final static String PREFIX = "icons/";
-
-       public final static Image ICON_USER = CmsImages.createImg(PREFIX + "person.png");
-       public final static Image ICON_GROUP = CmsImages.createImg(PREFIX + "group.png");
-       public final static Image ICON_ROLE = CmsImages.createImg(PREFIX + "role.gif");
-       public final static Image ICON_CHANGE_PASSWORD = CmsImages.createImg(PREFIX + "security.gif");
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/package-info.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/useradmin/package-info.java
deleted file mode 100644 (file)
index 3fc191c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/** SWT/JFace users management components. */
-package org.argeo.cms.ui.useradmin;
\ No newline at end of file
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/AbstractCmsTheme.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/AbstractCmsTheme.java
deleted file mode 100644 (file)
index c3fd796..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.argeo.cms.ui.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.argeo.cms.ui.CmsTheme;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.widgets.Display;
-
-/** Centralises some generic {@link CmsTheme} patterns. */
-public abstract class AbstractCmsTheme implements CmsTheme {
-       private Map<String, ImageData> imageCache = new HashMap<>();
-
-       private Map<String, Map<Integer, String>> iconPaths = new HashMap<>();
-
-       private Integer defaultIconSize = 16;
-
-       public Image getImage(String path) {
-               if (!imageCache.containsKey(path)) {
-                       try (InputStream in = getResourceAsStream(path)) {
-                               if (in == null)
-                                       return null;
-                               ImageData imageData = new ImageData(in);
-                               imageCache.put(path, imageData);
-                       } catch (IOException e) {
-                               throw new IllegalStateException(e);
-                       }
-               }
-               ImageData imageData = imageCache.get(path);
-               Image image = new Image(Display.getCurrent(), imageData);
-               return image;
-       }
-
-       @Override
-       public Image getIcon(String name, Integer preferredSize) {
-               if (preferredSize == null)
-                       preferredSize = defaultIconSize;
-               Map<Integer, String> subCache;
-               if (!iconPaths.containsKey(name))
-                       subCache = new HashMap<>();
-               else
-                       subCache = iconPaths.get(name);
-               Image image = null;
-               if (!subCache.containsKey(preferredSize)) {
-                       Image bestMatchSoFar = null;
-                       paths: for (String p : getImagesPaths()) {
-                               int lastSlash = p.lastIndexOf('/');
-                               String fileName = p;
-                               if (lastSlash >= 0)
-                                       fileName = p.substring(lastSlash + 1);
-                               int lastDot = fileName.lastIndexOf('.');
-                               if (lastDot >= 0)
-                                       fileName = fileName.substring(0, lastDot);
-                               if (fileName.equals(name)) {// matched
-                                       Image img = getImage(p);
-                                       int width = img.getBounds().width;
-                                       if (width == preferredSize) {// perfect match
-                                               subCache.put(preferredSize, p);
-                                               image = img;
-                                               break paths;
-                                       }
-                                       if (bestMatchSoFar == null) {
-                                               bestMatchSoFar = img;
-                                       } else {
-                                               if (Math.abs(width - preferredSize) < Math
-                                                               .abs(bestMatchSoFar.getBounds().width - preferredSize))
-                                                       bestMatchSoFar = img;
-                                       }
-                               }
-                       }
-
-                       if (image == null)
-                               image = bestMatchSoFar;
-               } else {
-                       image = getImage(subCache.get(preferredSize));
-               }
-
-               if (image != null && !iconPaths.containsKey(name))
-                       iconPaths.put(name, subCache);
-
-               return image;
-       }
-
-       @Override
-       public Integer getDefaultIconSize() {
-               return defaultIconSize;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/BundleCmsTheme.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/BundleCmsTheme.java
deleted file mode 100644 (file)
index 6b997e6..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-package org.argeo.cms.ui.util;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
-import org.apache.commons.io.IOUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-/**
- * Simplifies the theming of an app (only RAP is supported at this stage).<br>
- * 
- * Additional fonts listed in <code>/fonts.txt</code>.<br>
- * Additional (standard CSS) header in <code>/header.css</code>.<br>
- * RAP specific CSS files in <code>/rap/*.css</code>.<br>
- * All images added as additional resources based on extensions
- * <code>/ ** /*.{png,gif,jpeg,...}</code>.<br>
- */
-public class BundleCmsTheme extends AbstractCmsTheme {
-       public final static String DEFAULT_CMS_THEME_BUNDLE = "org.argeo.theme.argeo2";
-
-       public final static String CMS_THEME_PROPERTY = "argeo.cms.theme";
-       public final static String CMS_THEME_BUNDLE_PROPERTY = "argeo.cms.theme.bundle";
-
-       private final static String HEADER_CSS = "header.css";
-       private final static String FONTS_TXT = "fonts.txt";
-       private final static String BODY_HTML = "body.html";
-
-//     private final static Log log = LogFactory.getLog(BundleCmsTheme.class);
-
-       private String themeId;
-       private Set<String> webCssPaths = new TreeSet<>();
-       private Set<String> rapCssPaths = new TreeSet<>();
-       private Set<String> swtCssPaths = new TreeSet<>();
-       private Set<String> imagesPaths = new TreeSet<>();
-       private Set<String> fontsPaths = new TreeSet<>();
-
-       private String headerCss;
-       private List<String> fonts = new ArrayList<>();
-
-       private String bodyHtml="<body></body>";
-
-       private String basePath;
-       private String styleCssPath;
-//     private String webCssPath;
-//     private String rapCssPath;
-//     private String swtCssPath;
-       private Bundle themeBundle;
-
-       public BundleCmsTheme() {
-
-       }
-
-       public void init(BundleContext bundleContext, Map<String, String> properties) {
-               initResources(bundleContext, null);
-       }
-
-       public void destroy(BundleContext bundleContext, Map<String, String> properties) {
-
-       }
-
-       @Deprecated
-       public BundleCmsTheme(BundleContext bundleContext) {
-               this(bundleContext, null);
-       }
-
-       @Deprecated
-       public BundleCmsTheme(BundleContext bundleContext, String symbolicName) {
-               initResources(bundleContext, symbolicName);
-       }
-
-       private void initResources(BundleContext bundleContext, String symbolicName) {
-               if (symbolicName == null) {
-                       themeBundle = bundleContext.getBundle();
-//                     basePath = "/theme/";
-//                     cssPath = basePath;
-               } else {
-                       themeBundle = findThemeBundle(bundleContext, symbolicName);
-               }
-               basePath = "/";
-               styleCssPath = "/style/";
-//             webCssPath = "/css/";
-//             rapCssPath = "/rap/";
-//             swtCssPath = "/swt/";
-//             this.themeId = RWT.DEFAULT_THEME_ID;
-               this.themeId = themeBundle.getSymbolicName();
-               webCssPaths = addCss(themeBundle, "/css/");
-               rapCssPaths = addCss(themeBundle, "/rap/");
-               swtCssPaths = addCss(themeBundle, "/swt/");
-               addImages("*.png");
-               addImages("*.gif");
-               addImages("*.jpg");
-               addImages("*.jpeg");
-               addImages("*.svg");
-               addImages("*.ico");
-
-               addFonts("*.woff");
-               addFonts("*.woff2");
-
-               // fonts
-               URL fontsUrl = themeBundle.getEntry(basePath + FONTS_TXT);
-               if (fontsUrl != null) {
-                       loadFontsUrl(fontsUrl);
-               }
-
-               // common CSS header (plain CSS)
-               URL headerCssUrl = themeBundle.getEntry(basePath + HEADER_CSS);
-               if (headerCssUrl != null) {
-                       // added to plain Web CSS
-                       webCssPaths.add(basePath + HEADER_CSS);
-                       // and it will also be used by RAP:
-                       try (BufferedReader buffer = new BufferedReader(new InputStreamReader(headerCssUrl.openStream(), UTF_8))) {
-                               headerCss = buffer.lines().collect(Collectors.joining("\n"));
-                       } catch (IOException e) {
-                               throw new IllegalArgumentException("Cannot read " + headerCssUrl, e);
-                       }
-               }
-
-               // body
-               URL bodyUrl = themeBundle.getEntry(basePath + BODY_HTML);
-               if (bodyUrl != null) {
-                       loadBodyHtml(bodyUrl);
-               }
-}
-
-       public String getHtmlHeaders() {
-               StringBuilder sb = new StringBuilder();
-               if (headerCss != null) {
-                       sb.append("<style type='text/css'>\n");
-                       sb.append(headerCss);
-                       sb.append("\n</style>\n");
-               }
-               for (String link : fonts) {
-                       sb.append("<link rel='stylesheet' href='");
-                       sb.append(link);
-                       sb.append("'/>\n");
-               }
-               if (sb.length() == 0)
-                       return null;
-               else
-                       return sb.toString();
-       }
-       
-       
-
-       @Override
-       public String getBodyHtml() {
-               return bodyHtml;
-       }
-
-       Set<String> addCss(Bundle themeBundle, String path) {
-               Set<String> paths = new TreeSet<>();
-
-               // common CSS
-               Enumeration<URL> commonResources = themeBundle.findEntries(styleCssPath, "*.css", true);
-               if (commonResources != null) {
-                       while (commonResources.hasMoreElements()) {
-                               String resource = commonResources.nextElement().getPath();
-                               // remove first '/' so that RWT registers it
-                               resource = resource.substring(1);
-                               if (!resource.endsWith("/")) {
-                                       paths.add(resource);
-                               }
-                       }
-               }
-
-               // specific CSS
-               Enumeration<URL> themeResources = themeBundle.findEntries(path, "*.css", true);
-               if (themeResources != null) {
-                       while (themeResources.hasMoreElements()) {
-                               String resource = themeResources.nextElement().getPath();
-                               // remove first '/' so that RWT registers it
-                               resource = resource.substring(1);
-                               if (!resource.endsWith("/")) {
-                                       paths.add(resource);
-                               }
-                       }
-               }
-               return paths;
-       }
-
-       void loadFontsUrl(URL url) {
-               try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) {
-                       String line = null;
-                       while ((line = in.readLine()) != null) {
-                               line = line.trim();
-                               if (!line.equals("") && !line.startsWith("#")) {
-                                       fonts.add(line);
-                               }
-                       }
-               } catch (IOException e) {
-                       throw new IllegalArgumentException("Cannot load URL " + url, e);
-               }
-       }
-
-       void loadBodyHtml(URL url) {
-               try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) {
-               bodyHtml=       IOUtils.toString(url,StandardCharsets.UTF_8);
-               } catch (IOException e) {
-                       throw new IllegalArgumentException("Cannot load URL " + url, e);
-               }
-       }
-
-       void addImages(String pattern) {
-               Enumeration<URL> themeResources = themeBundle.findEntries(basePath, pattern, true);
-               if (themeResources == null)
-                       return;
-               while (themeResources.hasMoreElements()) {
-                       String resource = themeResources.nextElement().getPath();
-                       // remove first '/' so that RWT registers it
-                       resource = resource.substring(1);
-                       if (!resource.endsWith("/")) {
-//                             if (resources.containsKey(resource))
-//                                     log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
-//                             resources.put(resource, themeBRL);
-                               imagesPaths.add(resource);
-                       }
-
-               }
-
-       }
-
-       void addFonts(String pattern) {
-               Enumeration<URL> themeResources = themeBundle.findEntries(basePath, pattern, true);
-               if (themeResources == null)
-                       return;
-               while (themeResources.hasMoreElements()) {
-                       String resource = themeResources.nextElement().getPath();
-                       // remove first '/' so that RWT registers it
-                       resource = resource.substring(1);
-                       if (!resource.endsWith("/")) {
-//                             if (resources.containsKey(resource))
-//                                     log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
-//                             resources.put(resource, themeBRL);
-                               fontsPaths.add(resource);
-                       }
-
-               }
-
-       }
-
-       @Override
-       public InputStream getResourceAsStream(String resourceName) throws IOException {
-               URL res = themeBundle.getEntry(resourceName);
-               if (res == null) {
-                       res = themeBundle.getResource(resourceName);
-                       if (res == null)
-                               return null;
-//                             throw new IllegalArgumentException(
-//                                             "Resource " + resourceName + " not found in bundle " + themeBundle.getSymbolicName());
-               }
-               return res.openStream();
-       }
-
-       public String getThemeId() {
-               return themeId;
-       }
-
-//     public void setThemeId(String themeId) {
-//             this.themeId = themeId;
-//     }
-//
-//     public String getBasePath() {
-//             return basePath;
-//     }
-//
-//     public void setBasePath(String basePath) {
-//             this.basePath = basePath;
-//     }
-//
-//     public String getRapCssPath() {
-//             return rapCssPath;
-//     }
-//
-//     public void setRapCssPath(String cssPath) {
-//             this.rapCssPath = cssPath;
-//     }
-
-       @Override
-       public Set<String> getWebCssPaths() {
-               return webCssPaths;
-       }
-
-       @Override
-       public Set<String> getRapCssPaths() {
-               return rapCssPaths;
-       }
-
-       @Override
-       public Set<String> getSwtCssPaths() {
-               return swtCssPaths;
-       }
-
-       @Override
-       public Set<String> getImagesPaths() {
-               return imagesPaths;
-       }
-
-       @Override
-       public Set<String> getFontsPaths() {
-               return fontsPaths;
-       }
-
-       @Override
-       public InputStream loadPath(String path) throws IOException {
-               URL url = themeBundle.getResource(path);
-               if (url == null)
-                       throw new IllegalArgumentException(
-                                       "Path " + path + " not found in bundle " + themeBundle.getSymbolicName());
-               return url.openStream();
-       }
-
-       private static Bundle findThemeBundle(BundleContext bundleContext, String themeId) {
-               if (themeId == null)
-                       return null;
-               // TODO optimize
-               // TODO deal with multiple versions
-               Bundle themeBundle = null;
-               if (themeId != null) {
-                       for (Bundle bundle : bundleContext.getBundles())
-                               if (themeId.equals(bundle.getSymbolicName())) {
-                                       themeBundle = bundle;
-                                       break;
-                               }
-               }
-               return themeBundle;
-       }
-
-       @Override
-       public int hashCode() {
-               return themeId.hashCode();
-       }
-
-       @Override
-       public String toString() {
-               return "Bundle CMS Theme " + themeId;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsEvent.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsEvent.java
deleted file mode 100644 (file)
index ca0797b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.argeo.cms.ui.util;
-
-import org.argeo.cms.ui.CmsView;
-
-/**
- * Can be applied to {@link Enum}s in order to define events used by
- * {@link CmsView#sendEvent(String, java.util.Map)}.
- */
-public interface CmsEvent {
-       String name();
-
-       default String topic() {
-               return getTopicBase() + "/" + name();
-       }
-
-       default         String getTopicBase() {
-               return "argeo/cms";
-       }
-
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsIcon.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsIcon.java
deleted file mode 100644 (file)
index 33f13ad..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.argeo.cms.ui.util;
-
-import org.argeo.cms.ui.CmsTheme;
-import org.eclipse.swt.graphics.Image;
-
-/** Can be applied to {@link Enum}s in order to generated {@link Image}s. */
-public interface CmsIcon {
-       String name();
-
-       default Image getSmallIcon(CmsTheme theme) {
-               return theme.getIcon(name(), getSmallIconSize());
-       }
-
-       default Image getBigIcon(CmsTheme theme) {
-               return theme.getIcon(name(), getBigIconSize());
-       }
-
-       default Integer getSmallIconSize() {
-               return 16;
-       }
-
-       default Integer getBigIconSize() {
-               return 32;
-       }
-}
index 33772bc8ed1ae88fb9e07d559939e100fcc523b2..af7e4020d16e6e75778d9ff1953d171c785b98fb 100644 (file)
@@ -10,8 +10,10 @@ import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.cms.CmsStyle;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.jcr.CmsJcrUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.argeo.jcr.JcrException;
 import org.eclipse.rap.rwt.RWT;
@@ -90,10 +92,10 @@ public class CmsLink implements CmsUiProvider {
 //             }
 
                Composite comp = new Composite(parent, SWT.NONE);
-               comp.setLayout(CmsUiUtils.noSpaceGridLayout());
+               comp.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                Label link = new Label(comp, SWT.NONE);
-               CmsUiUtils.markup(link);
+               CmsSwtUtils.markup(link);
                GridData layoutData = new GridData(horizontalAlignment, verticalAlignment, false, false);
                if (image != null) {
                        if (imageHeight != null)
@@ -104,8 +106,8 @@ public class CmsLink implements CmsUiProvider {
                }
 
                link.setLayoutData(layoutData);
-               CmsUiUtils.style(comp, style != null ? style : getDefaultStyle());
-               CmsUiUtils.style(link, style != null ? style : getDefaultStyle());
+               CmsSwtUtils.style(comp, style != null ? style : getDefaultStyle());
+               CmsSwtUtils.style(link, style != null ? style : getDefaultStyle());
 
                // label
                StringBuilder labelText = new StringBuilder();
index 68f1e0f892ee4c1431d35445881968c69425ae4a..fc0c821463729f5be8c50b4936fdcfaea821e739 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.cms.ui.util;
 
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
@@ -14,7 +15,7 @@ public class CmsPane {
        private Composite supportArea;
 
        public CmsPane(Composite parent, int style) {
-               parent.setLayout(CmsUiUtils.noSpaceGridLayout());
+               parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
 
 //             qaArea = new Composite(parent, SWT.NONE);
 //             qaArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsStyle.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/CmsStyle.java
deleted file mode 100644 (file)
index ed2244b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.argeo.cms.ui.util;
-
-/** Can be applied to {@link Enum}s in order to generate (CSS) class names. */
-public interface CmsStyle {
-       String name();
-
-       /** @deprecated use {@link #style()} instead. */
-       @Deprecated
-       default String toStyleClass() {
-               return style();
-       }
-
-       default String style() {
-               String classPrefix = getClassPrefix();
-               return "".equals(classPrefix) ? name() : classPrefix + "-" + name();
-       }
-
-       default String getClassPrefix() {
-               return "";
-       }
-
-}
index 2bfeb43cfb593e7f62e6686acfe3cc55d308576c..ef4f7fa44b6de9f30fdff4af79ba7d37eb80f454 100644 (file)
@@ -6,8 +6,6 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.StringTokenizer;
 
 import javax.jcr.Node;
@@ -15,74 +13,39 @@ import javax.jcr.RepositoryException;
 import javax.servlet.http.HttpServletRequest;
 
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.api.cms.CmsView;
 import org.argeo.cms.jcr.CmsJcrUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsConstants;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.eclipse.ui.Selected;
-import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
-import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.service.ResourceManager;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.FormAttachment;
-import org.eclipse.swt.layout.FormData;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.layout.RowData;
-import org.eclipse.swt.layout.RowLayout;
-import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.Widget;
 
 /** Static utilities for the CMS framework. */
-public class CmsUiUtils implements CmsConstants {
+public class CmsUiUtils {
        // private final static Log log = LogFactory.getLog(CmsUiUtils.class);
 
        /*
         * CMS VIEW
         */
 
-       /** Sends an event via {@link CmsView#sendEvent(String, Map)}. */
-       public static void sendEventOnSelect(Control control, String topic, Map<String, Object> properties) {
-               SelectionListener listener = (Selected) (e) -> {
-                       CmsView.getCmsView(control.getParent()).sendEvent(topic, properties);
-               };
-               if (control instanceof Button) {
-                       ((Button) control).addSelectionListener(listener);
-               } else
-                       throw new UnsupportedOperationException("Control type " + control.getClass() + " is not supported.");
-       }
-
-       /**
-        * Convenience method to sends an event via
-        * {@link CmsView#sendEvent(String, Map)}.
-        */
-       public static void sendEventOnSelect(Control control, String topic, String key, Object value) {
-               Map<String, Object> properties = new HashMap<>();
-               properties.put(key, value);
-               sendEventOnSelect(control, topic, properties);
-       }
-
        /**
         * The CMS view related to this display, or null if none is available from this
         * call.
         * 
-        * @deprecated Use {@link CmsView#getCmsView(Composite)} instead.
+        * @deprecated Use {@link CmsSwtUtils#getCmsView(Composite)} instead.
         */
        @Deprecated
        public static CmsView getCmsView() {
 //             return UiContext.getData(CmsView.class.getName());
-               return CmsView.getCmsView(Display.getCurrent().getActiveShell());
+               return CmsSwtUtils.getCmsView(Display.getCurrent().getActiveShell());
        }
 
        public static StringBuilder getServerBaseUrl(HttpServletRequest request) {
@@ -99,7 +62,7 @@ public class CmsUiUtils implements CmsConstants {
        }
 
        //
-       public static String getDataUrl(Node node, HttpServletRequest request) throws RepositoryException {
+       public static String getDataUrl(Node node, HttpServletRequest request) {
                try {
                        StringBuilder buf = getServerBaseUrl(request);
                        buf.append(getDataPath(node));
@@ -110,21 +73,21 @@ public class CmsUiUtils implements CmsConstants {
        }
 
        /** A path in the node repository */
-       public static String getDataPath(Node node) throws RepositoryException {
+       public static String getDataPath(Node node) {
                return getDataPath(NodeConstants.EGO_REPOSITORY, node);
        }
 
-       public static String getDataPath(String cn, Node node) throws RepositoryException {
+       public static String getDataPath(String cn, Node node) {
                return CmsJcrUtils.getDataPath(cn, node);
        }
 
        /** Clean reserved URL characters for use in HTTP links. */
-       public static String getDataPathForUrl(Node node) throws RepositoryException {
+       public static String getDataPathForUrl(Node node) {
                return cleanPathForUrl(getDataPath(node));
        }
 
        /** Clean reserved URL characters for use in HTTP links. */
-       public static String cleanPathForUrl(String path) throws RepositoryException {
+       public static String cleanPathForUrl(String path) {
                StringTokenizer st = new StringTokenizer(path, "/");
                StringBuilder sb = new StringBuilder();
                while (st.hasMoreElements()) {
@@ -141,162 +104,19 @@ public class CmsUiUtils implements CmsConstants {
        @Deprecated
        public static RowData ROW_DATA_16px = new RowData(16, 16);
 
-       /*
-        * GRID LAYOUT
-        */
-       public static GridLayout noSpaceGridLayout() {
-               return noSpaceGridLayout(new GridLayout());
-       }
-
-       public static GridLayout noSpaceGridLayout(int columns) {
-               return noSpaceGridLayout(new GridLayout(columns, false));
-       }
-
-       /** @return the same layout, with spaces removed. */
-       public static GridLayout noSpaceGridLayout(GridLayout layout) {
-               layout.horizontalSpacing = 0;
-               layout.verticalSpacing = 0;
-               layout.marginWidth = 0;
-               layout.marginHeight = 0;
-               return layout;
-       }
-
-       public static GridData fillAll() {
-               return new GridData(SWT.FILL, SWT.FILL, true, true);
-       }
-
-       public static GridData fillWidth() {
-               return grabWidth(SWT.FILL, SWT.FILL);
-       }
-
-       public static GridData grabWidth(int horizontalAlignment, int verticalAlignment) {
-               return new GridData(horizontalAlignment, horizontalAlignment, true, false);
-       }
-
-       public static GridData fillHeight() {
-               return grabHeight(SWT.FILL, SWT.FILL);
-       }
-
-       public static GridData grabHeight(int horizontalAlignment, int verticalAlignment) {
-               return new GridData(horizontalAlignment, horizontalAlignment, false, true);
-       }
-
-       /*
-        * ROW LAYOUT
-        */
-       /** @return the same layout, with margins removed. */
-       public static RowLayout noMarginsRowLayout(RowLayout rowLayout) {
-               rowLayout.marginTop = 0;
-               rowLayout.marginBottom = 0;
-               rowLayout.marginLeft = 0;
-               rowLayout.marginRight = 0;
-               return rowLayout;
-       }
-
-       public static RowLayout noMarginsRowLayout(int type) {
-               return noMarginsRowLayout(new RowLayout(type));
-       }
-
-       public static RowData rowData16px() {
-               return new RowData(16, 16);
-       }
+       
 
        /*
         * FORM LAYOUT
         */
 
-       public static FormData coverAll() {
-               FormData fdLabel = new FormData();
-               fdLabel.top = new FormAttachment(0, 0);
-               fdLabel.left = new FormAttachment(0, 0);
-               fdLabel.right = new FormAttachment(100, 0);
-               fdLabel.bottom = new FormAttachment(100, 0);
-               return fdLabel;
-       }
-
-       /*
-        * STYLING
-        */
-
-       /** Style widget */
-       public static <T extends Widget> T style(T widget, String style) {
-               if (style == null)
-                       return widget;// does nothing
-               EclipseUiSpecificUtils.setStyleData(widget, style);
-               if (widget instanceof Control) {
-                       CmsView cmsView = CmsView.getCmsView((Control) widget);
-                       if (cmsView != null)
-                               cmsView.applyStyles(widget);
-               }
-               return widget;
-       }
-
-       /** Style widget */
-       public static <T extends Widget> T style(T widget, CmsStyle style) {
-               return style(widget, style.toStyleClass());
-       }
-
-       /** Enable markups on widget */
-       public static <T extends Widget> T markup(T widget) {
-               EclipseUiSpecificUtils.setMarkupData(widget);
-               return widget;
-       }
-
-       /** Disable markup validation. */
-       public static <T extends Widget> T disableMarkupValidation(T widget) {
-               EclipseUiSpecificUtils.setMarkupValidationDisabledData(widget);
-               return widget;
-       }
-
-       /**
-        * Apply markup and set text on {@link Label}, {@link Button}, {@link Text}.
-        * 
-        * @param widget the widget to style and to use in order to display text
-        * @param txt    the object to display via its <code>toString()</code> method.
-        *               This argument should not be null, but if it is null and
-        *               assertions are disabled "<null>" is displayed instead; if
-        *               assertions are enabled the call will fail.
-        * 
-        * @see #markup(Widget)
-        */
-       public static <T extends Widget> T text(T widget, Object txt) {
-               assert txt != null;
-               String str = txt != null ? txt.toString() : "<null>";
-               markup(widget);
-               if (widget instanceof Label)
-                       ((Label) widget).setText(str);
-               else if (widget instanceof Button)
-                       ((Button) widget).setText(str);
-               else if (widget instanceof Text)
-                       ((Text) widget).setText(str);
-               else
-                       throw new IllegalArgumentException("Unsupported widget type " + widget.getClass());
-               return widget;
-       }
-
-       /** A {@link Label} with markup activated. */
-       public static Label lbl(Composite parent, Object txt) {
-               return text(new Label(parent, SWT.NONE), txt);
-       }
-
-       /** A read-only {@link Text} whose content can be copy/pasted. */
-       public static Text txt(Composite parent, Object txt) {
-               return text(new Text(parent, SWT.NONE), txt);
-       }
+       
 
        @Deprecated
        public static void setItemHeight(Table table, int height) {
                table.setData(CmsConstants.ITEM_HEIGHT, height);
        }
 
-       /** Dispose all children of a Composite */
-       public static void clear(Composite composite) {
-               if (composite.isDisposed())
-                       return;
-               for (Control child : composite.getChildren())
-                       child.dispose();
-       }
-
        //
        // JCR
        //
@@ -328,6 +148,7 @@ public class CmsUiUtils implements CmsConstants {
        }
 
        // IMAGES
+
        public static String img(Node fileNode, String width, String height) {
                return img(null, fileNode, width, height);
        }
@@ -335,11 +156,7 @@ public class CmsUiUtils implements CmsConstants {
        public static String img(String serverBase, Node fileNode, String width, String height) {
 //             String src = (serverBase != null ? serverBase : "") + NodeUtils.getDataPath(fileNode);
                String src;
-               try {
-                       src = (serverBase != null ? serverBase : "") + getDataPathForUrl(fileNode);
-               } catch (RepositoryException e) {
-                       throw new JcrException("Cannot get URL data path for " + fileNode, e);
-               }
+               src = (serverBase != null ? serverBase : "") + getDataPathForUrl(fileNode);
                return imgBuilder(src, width, height).append("/>").toString();
        }
 
@@ -347,8 +164,8 @@ public class CmsUiUtils implements CmsConstants {
                return imgBuilder(src, width, height).append("/>").toString();
        }
 
-       public static String img(String src, Point size) {
-               return img(src, Integer.toString(size.x), Integer.toString(size.y));
+       public static String img(String src, Cms2DSize size) {
+               return img(src, Integer.toString(size.getWidth()), Integer.toString(size.getHeight()));
        }
 
        public static StringBuilder imgBuilder(String src, String width, String height) {
@@ -356,22 +173,22 @@ public class CmsUiUtils implements CmsConstants {
                                .append("' src='").append(src).append("'");
        }
 
-       public static String noImg(Point size) {
+       public static String noImg(Cms2DSize size) {
                ResourceManager rm = RWT.getResourceManager();
-               return CmsUiUtils.img(rm.getLocation(NO_IMAGE), size);
+               return CmsUiUtils.img(rm.getLocation(CmsConstants.NO_IMAGE), size);
        }
 
        public static String noImg() {
-               return noImg(NO_IMAGE_SIZE);
+               return noImg(CmsConstants.NO_IMAGE_SIZE);
        }
 
-       public static Image noImage(Point size) {
+       public static Image noImage(Cms2DSize size) {
                ResourceManager rm = RWT.getResourceManager();
                InputStream in = null;
                try {
-                       in = rm.getRegisteredContent(NO_IMAGE);
+                       in = rm.getRegisteredContent(CmsConstants.NO_IMAGE);
                        ImageData id = new ImageData(in);
-                       ImageData scaled = id.scaledTo(size.x, size.y);
+                       ImageData scaled = id.scaledTo(size.getWidth(), size.getHeight());
                        Image image = new Image(Display.getCurrent(), scaled);
                        return image;
                } finally {
index 6c4a870c49752f26731be354a492e49d7260d7da..d7f3d7c03d8bf23497d37074332e1390f57524f3 100644 (file)
@@ -9,8 +9,6 @@ import static org.argeo.cms.ui.CmsConstants.NO_IMAGE_SIZE;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
@@ -22,7 +20,9 @@ import javax.jcr.RepositoryException;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.ui.CmsImageManager;
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.jcr.JcrException;
 import org.argeo.jcr.JcrUtils;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.service.ResourceManager;
@@ -35,17 +35,17 @@ import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
 
 /** Manages only public images so far. */
-public class DefaultImageManager implements CmsImageManager {
+public class DefaultImageManager implements CmsImageManager<Control, Node> {
        private final static Log log = LogFactory.getLog(DefaultImageManager.class);
 //     private MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
 
-       public Boolean load(Node node, Control control, Point preferredSize) throws RepositoryException {
-               Point imageSize = getImageSize(node);
-               Point size;
+       public Boolean load(Node node, Control control, Cms2DSize preferredSize) {
+               Cms2DSize imageSize = getImageSize(node);
+               Cms2DSize size;
                String imgTag = null;
-               if (preferredSize == null || imageSize.x == 0 || imageSize.y == 0
-                               || (preferredSize.x == 0 && preferredSize.y == 0)) {
-                       if (imageSize.x != 0 && imageSize.y != 0) {
+               if (preferredSize == null || imageSize.getWidth() == 0 || imageSize.getHeight() == 0
+                               || (preferredSize.getWidth() == 0 && preferredSize.getHeight() == 0)) {
+                       if (imageSize.getWidth() != 0 && imageSize.getHeight() != 0) {
                                // actual image size if completely known
                                size = imageSize;
                        } else {
@@ -54,15 +54,15 @@ public class DefaultImageManager implements CmsImageManager {
                                imgTag = CmsUiUtils.noImg(size);
                        }
 
-               } else if (preferredSize.x != 0 && preferredSize.y != 0) {
+               } else if (preferredSize.getWidth() != 0 && preferredSize.getHeight() != 0) {
                        // given size if completely provided
                        size = preferredSize;
                } else {
                        // at this stage :
                        // image is completely known
-                       assert imageSize.x != 0 && imageSize.y != 0;
+                       assert imageSize.getWidth() != 0 && imageSize.getHeight() != 0;
                        // one and only one of the dimension as been specified
-                       assert preferredSize.x == 0 || preferredSize.y == 0;
+                       assert preferredSize.getWidth() == 0 || preferredSize.getHeight() == 0;
                        size = resizeTo(imageSize, preferredSize);
                }
 
@@ -87,7 +87,7 @@ public class DefaultImageManager implements CmsImageManager {
                } else if (control instanceof FileUpload) {
                        FileUpload lbl = (FileUpload) control;
                        lbl.setImage(CmsUiUtils.noImage(size));
-                       lbl.setSize(size);
+                       lbl.setSize(new Point(size.getWidth(), size.getHeight()));
                        return loaded;
                } else
                        loaded = false;
@@ -95,15 +95,17 @@ public class DefaultImageManager implements CmsImageManager {
                return loaded;
        }
 
-       private Point resizeTo(Point orig, Point constraints) {
-               if (constraints.x != 0 && constraints.y != 0) {
+       private Cms2DSize resizeTo(Cms2DSize orig, Cms2DSize constraints) {
+               if (constraints.getWidth() != 0 && constraints.getHeight() != 0) {
                        return constraints;
-               } else if (constraints.x == 0 && constraints.y == 0) {
+               } else if (constraints.getWidth() == 0 && constraints.getHeight() == 0) {
                        return orig;
-               } else if (constraints.y == 0) {// force width
-                       return new Point(constraints.x, scale(orig.y, orig.x, constraints.x));
-               } else if (constraints.x == 0) {// force height
-                       return new Point(scale(orig.x, orig.y, constraints.y), constraints.y);
+               } else if (constraints.getHeight() == 0) {// force width
+                       return new Cms2DSize(constraints.getWidth(),
+                                       scale(orig.getHeight(), orig.getWidth(), constraints.getWidth()));
+               } else if (constraints.getWidth() == 0) {// force height
+                       return new Cms2DSize(scale(orig.getWidth(), orig.getHeight(), constraints.getHeight()),
+                                       constraints.getHeight());
                }
                throw new IllegalArgumentException("Cannot resize " + orig + " to " + constraints);
        }
@@ -116,19 +118,19 @@ public class DefaultImageManager implements CmsImageManager {
                return ((float) a) / ((float) b);
        }
 
-       public Point getImageSize(Node node) throws RepositoryException {
+       public Cms2DSize getImageSize(Node node) {
                // TODO optimise
                Image image = getSwtImage(node);
-               return new Point(image.getBounds().width, image.getBounds().height);
+               return new Cms2DSize(image.getBounds().width, image.getBounds().height);
        }
 
        /** @return null if not available */
        @Override
-       public String getImageTag(Node node) throws RepositoryException {
+       public String getImageTag(Node node) {
                return getImageTag(node, getImageSize(node));
        }
 
-       private String getImageTag(Node node, Point size) throws RepositoryException {
+       private String getImageTag(Node node, Cms2DSize size) {
                StringBuilder buf = getImageTagBuilder(node, size);
                if (buf == null)
                        return null;
@@ -137,12 +139,12 @@ public class DefaultImageManager implements CmsImageManager {
 
        /** @return null if not available */
        @Override
-       public StringBuilder getImageTagBuilder(Node node, Point size) throws RepositoryException {
-               return getImageTagBuilder(node, Integer.toString(size.x), Integer.toString(size.y));
+       public StringBuilder getImageTagBuilder(Node node, Cms2DSize size) {
+               return getImageTagBuilder(node, Integer.toString(size.getWidth()), Integer.toString(size.getHeight()));
        }
 
        /** @return null if not available */
-       private StringBuilder getImageTagBuilder(Node node, String width, String height) throws RepositoryException {
+       private StringBuilder getImageTagBuilder(Node node, String width, String height) {
                String url = getImageUrl(node);
                if (url == null)
                        return null;
@@ -151,27 +153,35 @@ public class DefaultImageManager implements CmsImageManager {
 
        /** @return null if not available */
        @Override
-       public String getImageUrl(Node node) throws RepositoryException {
+       public String getImageUrl(Node node) {
                return CmsUiUtils.getDataPathForUrl(node);
        }
 
-       protected String getResourceName(Node node) throws RepositoryException {
-               String workspace = node.getSession().getWorkspace().getName();
-               if (node.hasNode(JCR_CONTENT))
-                       return workspace + '_' + node.getNode(JCR_CONTENT).getIdentifier();
-               else
-                       return workspace + '_' + node.getIdentifier();
+       protected String getResourceName(Node node) {
+               try {
+                       String workspace = node.getSession().getWorkspace().getName();
+                       if (node.hasNode(JCR_CONTENT))
+                               return workspace + '_' + node.getNode(JCR_CONTENT).getIdentifier();
+                       else
+                               return workspace + '_' + node.getIdentifier();
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
+               }
        }
 
-       public Binary getImageBinary(Node node) throws RepositoryException {
-               if (node.isNodeType(NT_FILE)) {
-                       return node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary();
-               } else {
-                       return null;
+       public Binary getImageBinary(Node node) {
+               try {
+                       if (node.isNodeType(NT_FILE)) {
+                               return node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getBinary();
+                       } else {
+                               return null;
+                       }
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
                }
        }
 
-       public Image getSwtImage(Node node) throws RepositoryException {
+       public Image getSwtImage(Node node) {
                InputStream inputStream = null;
                Binary binary = getImageBinary(node);
                if (binary == null)
@@ -179,6 +189,8 @@ public class DefaultImageManager implements CmsImageManager {
                try {
                        inputStream = binary.getStream();
                        return new Image(Display.getCurrent(), inputStream);
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
                } finally {
                        IOUtils.closeQuietly(inputStream);
                        JcrUtils.closeQuietly(binary);
@@ -186,8 +198,7 @@ public class DefaultImageManager implements CmsImageManager {
        }
 
        @Override
-       public String uploadImage(Node context, Node parentNode, String fileName, InputStream in, String contentType)
-                       throws RepositoryException {
+       public String uploadImage(Node context, Node parentNode, String fileName, InputStream in, String contentType) {
                InputStream inputStream = null;
                try {
                        String previousResourceName = null;
@@ -222,6 +233,8 @@ public class DefaultImageManager implements CmsImageManager {
                        return CmsUiUtils.getDataPath(fileNode);
                } catch (IOException e) {
                        throw new RuntimeException("Cannot upload image " + fileName + " in " + parentNode, e);
+               } catch (RepositoryException e) {
+                       throw new JcrException(e);
                } finally {
                        IOUtils.closeQuietly(inputStream);
                }
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/LoginEntryPoint.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/LoginEntryPoint.java
deleted file mode 100644 (file)
index 0bbed1d..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-package org.argeo.cms.ui.util;
-
-import java.util.Locale;
-import java.util.UUID;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.CmsException;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.ui.CmsImageManager;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.UxContext;
-import org.argeo.cms.ui.widgets.auth.CmsLogin;
-import org.argeo.cms.ui.widgets.auth.CmsLoginShell;
-import org.argeo.eclipse.ui.specific.UiContext;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.application.EntryPoint;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-
-public class LoginEntryPoint implements EntryPoint, CmsView {
-       protected final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-       protected final static String HEADER_AUTHORIZATION = "Authorization";
-       private final static Log log = LogFactory.getLog(LoginEntryPoint.class);
-       private LoginContext loginContext;
-       private UxContext uxContext = null;
-       private String uid;
-
-       @Override
-       public int createUI() {
-               uid = UUID.randomUUID().toString();
-               final Display display = createDisplay();
-//             UiContext.setData(CmsView.KEY, this);
-
-               CmsLoginShell loginShell = createCmsLoginShell();
-               CmsView.registerCmsView(loginShell.getShell(), this);
-               try {
-                       // try pre-auth
-                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, loginShell);
-                       loginContext.login();
-               } catch (LoginException e) {
-                       loginShell.createUi();
-                       loginShell.open();
-
-                       // HttpServletRequest request = RWT.getRequest();
-                       // String authorization = request.getHeader(HEADER_AUTHORIZATION);
-                       // if (authorization == null ||
-                       // !authorization.startsWith("Negotiate")) {
-                       // HttpServletResponse response = RWT.getResponse();
-                       // response.setStatus(401);
-                       // response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate");
-                       // response.setDateHeader("Date", System.currentTimeMillis());
-                       // response.setDateHeader("Expires", System.currentTimeMillis() +
-                       // (24 * 60 * 60 * 1000));
-                       // response.setHeader("Accept-Ranges", "bytes");
-                       // response.setHeader("Connection", "Keep-Alive");
-                       // response.setHeader("Keep-Alive", "timeout=5, max=97");
-                       // // response.setContentType("text/html; charset=UTF-8");
-                       // }
-
-                       while (!loginShell.getShell().isDisposed()) {
-                               if (!display.readAndDispatch())
-                                       display.sleep();
-                       }
-               }
-
-               if (CurrentUser.getUsername(getSubject()) == null)
-                       return -1;
-               uxContext = new SimpleUxContext();
-               return postLogin();
-       }
-
-       protected Display createDisplay() {
-               return new Display();
-       }
-
-       protected int postLogin() {
-               return 0;
-       }
-
-       protected HttpServletRequest getRequest() {
-               return RWT.getRequest();
-       }
-
-       protected CmsLoginShell createCmsLoginShell() {
-               return new CmsLoginShell(this) {
-
-                       @Override
-                       public void createContents(Composite parent) {
-                               LoginEntryPoint.this.createLoginPage(parent, this);
-                       }
-
-                       @Override
-                       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
-                                       SelectionListener loginSelectionListener) {
-                               LoginEntryPoint.this.extendsCredentialsBlock(credentialsBlock, selectedLocale, loginSelectionListener);
-                       }
-
-               };
-       }
-
-       /**
-        * To be overridden. CmsLogin#createCredentialsBlock() should be called at some
-        * point in order to create the credentials composite. In order to use the
-        * default layout, call CmsLogin#defaultCreateContents() but <b>not</b>
-        * CmsLogin#createContent(), since it would lead to a stack overflow.
-        */
-       protected void createLoginPage(Composite parent, CmsLogin login) {
-               login.defaultCreateContents(parent);
-       }
-
-       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
-                       SelectionListener loginSelectionListener) {
-
-       }
-
-       @Override
-       public String getUid() {
-               return uid;
-       }
-
-       @Override
-       public void navigateTo(String state) {
-               // TODO Auto-generated method stub
-
-       }
-
-       @Override
-       public void authChange(LoginContext loginContext) {
-               if (loginContext == null)
-                       throw new CmsException("Login context cannot be null");
-               // logout previous login context
-               if (this.loginContext != null)
-                       try {
-                               this.loginContext.logout();
-                       } catch (LoginException e1) {
-                               log.warn("Could not log out: " + e1);
-                       }
-               this.loginContext = loginContext;
-       }
-
-       @Override
-       public void logout() {
-               if (loginContext == null)
-                       throw new CmsException("Login context should not bet null");
-               try {
-                       CurrentUser.logoutCmsSession(loginContext.getSubject());
-                       loginContext.logout();
-               } catch (LoginException e) {
-                       throw new CmsException("Cannot log out", e);
-               }
-       }
-
-       @Override
-       public void exception(Throwable e) {
-               // TODO Auto-generated method stub
-
-       }
-
-       // @Override
-       // public LoginContext getLoginContext() {
-       // return loginContext;
-       // }
-
-       protected Subject getSubject() {
-               return loginContext.getSubject();
-       }
-
-       @Override
-       public boolean isAnonymous() {
-               return CurrentUser.isAnonymous(getSubject());
-       }
-
-       @Override
-       public CmsImageManager getImageManager() {
-               // TODO Auto-generated method stub
-               return null;
-       }
-
-       @Override
-       public UxContext getUxContext() {
-               return uxContext;
-       }
-}
\ No newline at end of file
index d581436599627671804b67af3ea60b3284f5800a..284d2bd0c5c4d2f06edfbedc04a1cc5f114edaca 100644 (file)
@@ -1,6 +1,6 @@
 package org.argeo.cms.ui.util;
 
-import org.argeo.cms.ui.CmsStyles;
+import org.argeo.cms.swt.CmsStyles;
 
 /**
  * Convenience class setting the custom style {@link CmsStyles#CMS_MENU_LINK} on
index 04ce5a290f7664bdc62d5de5addaf677103a52b3..e8bf66297e26a9d551f37cd32296e40dfeecded9 100644 (file)
@@ -7,7 +7,8 @@ import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.CmsStyles;
+import org.argeo.cms.swt.CmsStyles;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
@@ -29,7 +30,7 @@ public class SimpleCmsHeader implements CmsUiProvider {
                Composite header = new Composite(parent, SWT.NONE);
                header.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_HEADER);
                header.setBackgroundMode(SWT.INHERIT_DEFAULT);
-               header.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(3, false)));
+               header.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(3, false)));
 
                configurePart(context, header, lead);
                configurePart(context, header, center);
@@ -58,7 +59,7 @@ public class SimpleCmsHeader implements CmsUiProvider {
                part.setData(RWT.CUSTOM_VARIANT, custom);
                GridData gridData = new GridData(style, SWT.FILL, true, true);
                part.setLayoutData(gridData);
-               part.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(partProviders.size(), subPartsSameWidth)));
+               part.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(partProviders.size(), subPartsSameWidth)));
                for (CmsUiProvider uiProvider : partProviders) {
                        Control subPart = uiProvider.createUi(part, context);
                        subPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
index d394f23ac3803dca864946358475ee358ddf271b..63e504b7aaa1bc8ba7342046fcd1610bfe3431d6 100644 (file)
@@ -3,7 +3,7 @@ package org.argeo.cms.ui.util;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.CmsStyles;
+import org.argeo.cms.swt.CmsStyles;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
index 4bbd19cf9fb96c663092132daeeea781a596e11f..8ed06a292943f628761d18fa4f153f8128a7fb0b 100644 (file)
@@ -1,5 +1,7 @@
 package org.argeo.cms.ui.util;
 
+import org.argeo.api.cms.CmsStyle;
+
 /** Simple styles used by the CMS UI utilities. */
 public enum SimpleStyle implements CmsStyle {
        link;
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleUxContext.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/util/SimpleUxContext.java
deleted file mode 100644 (file)
index f85a1ab..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.argeo.cms.ui.util;
-
-import org.argeo.cms.ui.UxContext;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-
-public class SimpleUxContext implements UxContext {
-       private Point size;
-       private Point small = new Point(400, 400);
-
-       public SimpleUxContext() {
-               this(Display.getCurrent().getBounds());
-       }
-
-       public SimpleUxContext(Rectangle rect) {
-               this.size = new Point(rect.width, rect.height);
-       }
-
-       public SimpleUxContext(Point size) {
-               this.size = size;
-       }
-
-       @Override
-       public boolean isPortrait() {
-               return size.x >= size.y;
-       }
-
-       @Override
-       public boolean isLandscape() {
-               return size.x < size.y;
-       }
-
-       @Override
-       public boolean isSquare() {
-               return size.x == size.y;
-       }
-
-       @Override
-       public boolean isSmall() {
-               return size.x <= small.x || size.y <= small.y;
-       }
-
-       @Override
-       public boolean isMasterData() {
-               // TODO make it configurable
-               return true;
-       }
-
-}
index f53e552623b4cfd7545f7b76ad14407918b379ff..156a6082f5322c83648467ad21e799b161b3c566 100644 (file)
@@ -9,7 +9,8 @@ import java.util.Date;
 
 import org.apache.commons.io.IOUtils;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.CmsStyles;
+import org.argeo.cms.swt.CmsStyles;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.MouseEvent;
@@ -89,7 +90,7 @@ public class SystemNotifications extends Shell implements CmsStyles,
                                        .append(e.getMessage());
                }
                Label mailTo = new Label(pane, SWT.NONE);
-               CmsUiUtils.markup(mailTo);
+               CmsSwtUtils.markup(mailTo);
                mailTo.setText("<a href=\"" + mailToUrl + "\">Send details</a>");
                mailTo.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
 
index 07b60696be06797d113cf9975c12bcd595985345..316cb51c019019c82d2ae30dc5bf64f677b82f52 100644 (file)
@@ -3,7 +3,7 @@ package org.argeo.cms.ui.util;
 import javax.jcr.Node;
 
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.widgets.auth.CmsLoginShell;
+import org.argeo.cms.swt.auth.CmsLoginShell;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ShellAdapter;
 import org.eclipse.swt.events.ShellEvent;
index cc470e41478674e385429db7b7047f20168e9c89..317a7b55b2bcd3cc6ae48f91ec87c63581053dd0 100644 (file)
@@ -4,8 +4,8 @@ import javax.jcr.Node;
 
 import org.argeo.cms.CmsMsg;
 import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.ui.CmsStyles;
-import org.argeo.cms.ui.widgets.auth.CmsLoginShell;
+import org.argeo.cms.swt.CmsStyles;
+import org.argeo.cms.swt.auth.CmsLoginShell;
 import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.events.MouseEvent;
index e7dfb4b88e91c45fb859dca36c65554a06ee4f2a..7f846c93242bb36bd6835feb0fb33088fa1706ba 100644 (file)
@@ -6,6 +6,7 @@ import java.util.List;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.GridData;
@@ -20,7 +21,7 @@ public class VerticalMenu implements CmsUiProvider {
                Composite part = new Composite(parent, SWT.NONE);
                part.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false));
 //             part.setData(RWT.CUSTOM_VARIANT, custom);
-               part.setLayout(CmsUiUtils.noSpaceGridLayout());
+               part.setLayout(CmsSwtUtils.noSpaceGridLayout());
                for (CmsUiProvider uiProvider : items) {
                        Control subPart = uiProvider.createUi(part, context);
                        subPart.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false));
index e5ae67a794c51a50842937c5ab42a53989a20e14..60cb228437adcd784b5e848d4e9682a7a8e460af 100644 (file)
@@ -13,7 +13,7 @@ import javax.security.auth.Subject;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.ui.CmsEditable;
+import org.argeo.api.cms.CmsEditable;
 import org.argeo.cms.ui.widgets.ScrolledPage;
 import org.argeo.jcr.JcrException;
 import org.eclipse.jface.viewers.ContentViewer;
index dfd1438297e6ff86b7bd41718815689790ad8fc7..11162e87f344f768687e2a9df0c1289b7057f592 100644 (file)
@@ -8,8 +8,8 @@ import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.version.VersionManager;
 
+import org.argeo.api.cms.CmsEditable;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.CmsEditable;
 import org.argeo.cms.ui.CmsEditionEvent;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
index 88585e18506844551527d98f29b96db63459337a..d282eebbe72b5789aa7d31b634dbe81be198850a 100644 (file)
@@ -7,7 +7,7 @@ import java.util.Map;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.widgets.JcrComposite;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
@@ -38,7 +38,7 @@ public class Section extends JcrComposite {
                        } else {
                                relativeDepth = 0;
                        }
-                       setLayout(CmsUiUtils.noSpaceGridLayout());
+                       setLayout(CmsSwtUtils.noSpaceGridLayout());
                } catch (RepositoryException e) {
                        throw new IllegalStateException("Cannot create section from " + node, e);
                }
@@ -78,8 +78,8 @@ public class Section extends JcrComposite {
                        sectionHeader.dispose();
 
                sectionHeader = new Composite(parent, SWT.NONE);
-               sectionHeader.setLayoutData(CmsUiUtils.fillWidth());
-               sectionHeader.setLayout(CmsUiUtils.noSpaceGridLayout());
+               sectionHeader.setLayoutData(CmsSwtUtils.fillWidth());
+               sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout());
                // sectionHeader.moveAbove(null);
                // layout();
                return sectionHeader;
index f8ca531c3de96a254164afac2c4aa67c48bcdb6a..7bc0f79b504d0d886d9aa489aa2c7d277a9f1c1a 100644 (file)
@@ -1,6 +1,6 @@
 package org.argeo.cms.ui.widgets;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ShellAdapter;
 import org.eclipse.swt.events.ShellEvent;
@@ -24,7 +24,7 @@ public class ContextOverlay extends ScrolledPage {
        public ContextOverlay(Control control, int style) {
                super(createShell(control, style), SWT.NONE);
                Shell shell = getShell();
-               setLayoutData(CmsUiUtils.fillAll());
+               setLayoutData(CmsSwtUtils.fillAll());
                // TODO make autohide configurable?
                //shell.addShellListener(new AutoHideShellListener());
                this.control = control;
@@ -40,10 +40,10 @@ public class ContextOverlay extends ScrolledPage {
                if (control.isDisposed())
                        throw new IllegalArgumentException("Control is disposed");
                Shell shell = new Shell(control.getShell(), SWT.NO_TRIM);
-               shell.setLayout(CmsUiUtils.noSpaceGridLayout());
+               shell.setLayout(CmsSwtUtils.noSpaceGridLayout());
                Composite placeholder = new Composite(shell, SWT.BORDER);
-               placeholder.setLayoutData(CmsUiUtils.fillAll());
-               placeholder.setLayout(CmsUiUtils.noSpaceGridLayout());
+               placeholder.setLayoutData(CmsSwtUtils.fillAll());
+               placeholder.setLayout(CmsSwtUtils.noSpaceGridLayout());
                return placeholder;
        }
 
index 0a327cd512a64e339550a84c832aac0b7d8a224c..e5f269a40d572ea82e589863562f04089cfd7c84 100644 (file)
@@ -5,6 +5,8 @@ import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.util.CmsUiUtils;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.widgets.Composite;
@@ -17,21 +19,19 @@ public abstract class EditableImage extends StyledControl {
        private static final long serialVersionUID = -5689145523114022890L;
        private final static Log log = LogFactory.getLog(EditableImage.class);
 
-       private Point preferredImageSize;
+       private Cms2DSize preferredImageSize;
        private Boolean loaded = false;
 
        public EditableImage(Composite parent, int swtStyle) {
                super(parent, swtStyle);
        }
 
-       public EditableImage(Composite parent, int swtStyle,
-                       Point preferredImageSize) {
+       public EditableImage(Composite parent, int swtStyle, Cms2DSize preferredImageSize) {
                super(parent, swtStyle);
                this.preferredImageSize = preferredImageSize;
        }
 
-       public EditableImage(Composite parent, int style, Node node,
-                       boolean cacheImmediately, Point preferredImageSize)
+       public EditableImage(Composite parent, int style, Node node, boolean cacheImmediately, Cms2DSize preferredImageSize)
                        throws RepositoryException {
                super(parent, style, node, cacheImmediately);
                this.preferredImageSize = preferredImageSize;
@@ -49,15 +49,15 @@ public abstract class EditableImage extends StyledControl {
 
        /** To be overriden. */
        protected String createImgTag() throws RepositoryException {
-               return CmsUiUtils.noImg(preferredImageSize != null ? preferredImageSize
-                               : getSize());
+               return CmsUiUtils
+                               .noImg(preferredImageSize != null ? preferredImageSize : new Cms2DSize(getSize().x, getSize().y));
        }
 
        protected Label createLabel(Composite box, String style) {
                Label lbl = new Label(box, getStyle());
                // lbl.setLayoutData(CmsUiUtils.fillWidth());
-               CmsUiUtils.markup(lbl);
-               CmsUiUtils.style(lbl, style);
+               CmsSwtUtils.markup(lbl);
+               CmsSwtUtils.style(lbl, style);
                if (mouseListener != null)
                        lbl.addMouseListener(mouseListener);
                load(lbl);
@@ -83,7 +83,8 @@ public abstract class EditableImage extends StyledControl {
                        loaded = true;
                if (control != null) {
                        ((Label) control).setText(imgTag);
-                       control.setSize(preferredImageSize != null ? preferredImageSize
+                       control.setSize(preferredImageSize != null
+                                       ? new Point(preferredImageSize.getWidth(), preferredImageSize.getHeight())
                                        : getSize());
                } else {
                        loaded = false;
@@ -92,7 +93,7 @@ public abstract class EditableImage extends StyledControl {
                return loaded;
        }
 
-       public void setPreferredSize(Point size) {
+       public void setPreferredSize(Cms2DSize size) {
                this.preferredImageSize = size;
                if (!loaded) {
                        load((Label) getControl());
@@ -101,11 +102,11 @@ public abstract class EditableImage extends StyledControl {
 
        protected Text createText(Composite box, String style) {
                Text text = new Text(box, getStyle());
-               CmsUiUtils.style(text, style);
+               CmsSwtUtils.style(text, style);
                return text;
        }
 
-       public Point getPreferredImageSize() {
+       public Cms2DSize getPreferredImageSize() {
                return preferredImageSize;
        }
 
index 27b7c9b105ed4ad5e66790bd9f8cfe2fad0f0679..e3499ac4b91dc6790cad7ffa90fb3d32a172e407 100644 (file)
@@ -3,7 +3,7 @@ package org.argeo.cms.ui.widgets;
 import javax.jcr.Item;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.GridData;
@@ -54,10 +54,10 @@ public class EditableText extends StyledControl {
 
        protected Label createLabel(Composite box, String style) {
                Label lbl = new Label(box, getStyle() | SWT.WRAP);
-               lbl.setLayoutData(CmsUiUtils.fillWidth());
+               lbl.setLayoutData(CmsSwtUtils.fillWidth());
                if (style != null)
-                       CmsUiUtils.style(lbl, style);
-               CmsUiUtils.markup(lbl);
+                       CmsSwtUtils.style(lbl, style);
+               CmsSwtUtils.markup(lbl);
                if (mouseListener != null)
                        lbl.addMouseListener(mouseListener);
                return lbl;
@@ -66,10 +66,10 @@ public class EditableText extends StyledControl {
        protected Text createTextLabel(Composite box, String style) {
                Text lbl = new Text(box, getStyle() | SWT.MULTI);
                lbl.setEditable(false);
-               lbl.setLayoutData(CmsUiUtils.fillWidth());
+               lbl.setLayoutData(CmsSwtUtils.fillWidth());
                if (style != null)
-                       CmsUiUtils.style(lbl, style);
-               CmsUiUtils.markup(lbl);
+                       CmsSwtUtils.style(lbl, style);
+               CmsSwtUtils.markup(lbl);
                if (mouseListener != null)
                        lbl.addMouseListener(mouseListener);
                return lbl;
@@ -85,11 +85,11 @@ public class EditableText extends StyledControl {
 
                final Text text = new Text(box, getStyle() | SWT.MULTI | SWT.WRAP);
                text.setEditable(editable);
-               GridData textLayoutData = CmsUiUtils.fillWidth();
+               GridData textLayoutData = CmsSwtUtils.fillWidth();
                // textLayoutData.heightHint = preferredHeight;
                text.setLayoutData(textLayoutData);
                if (style != null)
-                       CmsUiUtils.style(text, style);
+                       CmsSwtUtils.style(text, style);
                text.setFocus();
                return text;
        }
index fb1091a028e49d6e5c1e76b37f58795399e8becc..3a4a60c9ff5ec6d2841f55f1d769ec4debd920be 100644 (file)
@@ -3,10 +3,10 @@ package org.argeo.cms.ui.widgets;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.argeo.cms.ui.CmsImageManager;
-import org.argeo.cms.ui.CmsView;
+import org.argeo.api.cms.Cms2DSize;
+import org.argeo.api.cms.CmsImageManager;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.internal.JcrFileUploadReceiver;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.cms.ui.viewers.NodePart;
 import org.argeo.cms.ui.viewers.Section;
 import org.argeo.cms.ui.viewers.SectionPart;
@@ -20,7 +20,6 @@ import org.eclipse.rap.rwt.widgets.FileUpload;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 
@@ -30,11 +29,11 @@ public class Img extends EditableImage implements SectionPart, NodePart {
 
        private final Section section;
 
-       private final CmsImageManager imageManager;
+       private final CmsImageManager<Control, Node> imageManager;
        private FileUploadHandler currentUploadHandler = null;
        private FileUploadListener fileUploadListener;
 
-       public Img(Composite parent, int swtStyle, Node imgNode, Point preferredImageSize) throws RepositoryException {
+       public Img(Composite parent, int swtStyle, Node imgNode, Cms2DSize preferredImageSize) throws RepositoryException {
                this(Section.findSection(parent), parent, swtStyle, imgNode, preferredImageSize, null);
                setStyle(TextStyles.TEXT_IMAGE);
        }
@@ -44,17 +43,19 @@ public class Img extends EditableImage implements SectionPart, NodePart {
                setStyle(TextStyles.TEXT_IMAGE);
        }
 
-       public Img(Composite parent, int swtStyle, Node imgNode, CmsImageManager imageManager) throws RepositoryException {
+       public Img(Composite parent, int swtStyle, Node imgNode, CmsImageManager<Control, Node> imageManager)
+                       throws RepositoryException {
                this(Section.findSection(parent), parent, swtStyle, imgNode, null, imageManager);
                setStyle(TextStyles.TEXT_IMAGE);
        }
 
-       Img(Section section, Composite parent, int swtStyle, Node imgNode, Point preferredImageSize,
-                       CmsImageManager imageManager) throws RepositoryException {
+       Img(Section section, Composite parent, int swtStyle, Node imgNode, Cms2DSize preferredImageSize,
+                       CmsImageManager<Control, Node> imageManager) throws RepositoryException {
                super(parent, swtStyle, imgNode, false, preferredImageSize);
                this.section = section;
-               this.imageManager = imageManager != null ? imageManager : CmsView.getCmsView(section).getImageManager();
-               CmsUiUtils.style(this, TextStyles.TEXT_IMG);
+               this.imageManager = imageManager != null ? imageManager
+                               : (CmsImageManager<Control, Node>) CmsSwtUtils.getCmsView(section).getImageManager();
+               CmsSwtUtils.style(this, TextStyles.TEXT_IMG);
        }
 
        @Override
@@ -78,14 +79,10 @@ public class Img extends EditableImage implements SectionPart, NodePart {
 
        @Override
        protected synchronized Boolean load(Control lbl) {
-               try {
-                       Node imgNode = getNode();
-                       boolean loaded = imageManager.load(imgNode, lbl, getPreferredImageSize());
-                       // getParent().layout();
-                       return loaded;
-               } catch (RepositoryException e) {
-                       throw new JcrException("Cannot load " + getNodeId() + " from image manager", e);
-               }
+               Node imgNode = getNode();
+               boolean loaded = imageManager.load(imgNode, lbl, getPreferredImageSize());
+               // getParent().layout();
+               return loaded;
        }
 
        protected Node getUploadFolder() {
@@ -97,7 +94,7 @@ public class Img extends EditableImage implements SectionPart, NodePart {
                return Jcr.getName(node) + '[' + Jcr.getIndex(node) + ']';
        }
 
-       protected CmsImageManager getImageManager() {
+       protected CmsImageManager<Control, Node> getImageManager() {
                return imageManager;
        }
 
@@ -109,7 +106,7 @@ public class Img extends EditableImage implements SectionPart, NodePart {
                currentUploadHandler = prepareUpload(receiver);
                final ServerPushSession pushSession = new ServerPushSession();
                final FileUpload fileUpload = new FileUpload(box, SWT.NONE);
-               CmsUiUtils.style(fileUpload, style);
+               CmsSwtUtils.style(fileUpload, style);
                fileUpload.addSelectionListener(new SelectionAdapter() {
                        private static final long serialVersionUID = -9158471843941668562L;
 
index 2d394c6f89ece6564efc347e177c93d63699ffc1..5d3576f2719cc1edc05208cc6685053d2125eb94 100644 (file)
@@ -7,7 +7,7 @@ import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
-import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.jcr.JcrException;
 import org.eclipse.swt.widgets.Composite;
 
@@ -57,7 +57,7 @@ public class JcrComposite extends Composite {
                                if (cacheImmediately)
                                        this.cache = node;
 //                             }
-                               setLayout(CmsUiUtils.noSpaceGridLayout());
+                               setLayout(CmsSwtUtils.noSpaceGridLayout());
                        } catch (RepositoryException e) {
                                throw new IllegalStateException("Cannot create composite from " + item, e);
                        }
index b413faf3e59352c439ea32d69db3ac830ed44cb0..84e4cce86f993705235e02f3325e1441ea79c487 100644 (file)
@@ -2,8 +2,8 @@ package org.argeo.cms.ui.widgets;
 
 import javax.jcr.Item;
 
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ui.CmsConstants;
-import org.argeo.cms.ui.util.CmsUiUtils;
 import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.FocusListener;
@@ -28,7 +28,7 @@ public abstract class StyledControl extends JcrComposite implements CmsConstants
 
        public StyledControl(Composite parent, int swtStyle) {
                super(parent, swtStyle);
-               setLayout(CmsUiUtils.noSpaceGridLayout());
+               setLayout(CmsSwtUtils.noSpaceGridLayout());
        }
 
        public StyledControl(Composite parent, int style, Item item) {
@@ -44,14 +44,14 @@ public abstract class StyledControl extends JcrComposite implements CmsConstants
        protected Composite createBox() {
                Composite box = new Composite(container, SWT.INHERIT_DEFAULT);
                setContainerLayoutData(box);
-               box.setLayout(CmsUiUtils.noSpaceGridLayout(3));
+               box.setLayout(CmsSwtUtils.noSpaceGridLayout(3));
                return box;
        }
 
        protected Composite createContainer() {
                Composite container = new Composite(this, SWT.INHERIT_DEFAULT);
                setContainerLayoutData(container);
-               container.setLayout(CmsUiUtils.noSpaceGridLayout());
+               container.setLayout(CmsSwtUtils.noSpaceGridLayout());
                return container;
        }
 
@@ -104,19 +104,19 @@ public abstract class StyledControl extends JcrComposite implements CmsConstants
                refreshControl(style);
 
                if (style != null) {
-                       CmsUiUtils.style(box, style + "_box");
-                       CmsUiUtils.style(container, style + "_container");
+                       CmsSwtUtils.style(box, style + "_box");
+                       CmsSwtUtils.style(container, style + "_container");
                }
        }
 
        /** To be overridden */
        protected void setControlLayoutData(Control control) {
-               control.setLayoutData(CmsUiUtils.fillWidth());
+               control.setLayoutData(CmsSwtUtils.fillWidth());
        }
 
        /** To be overridden */
        protected void setContainerLayoutData(Composite composite) {
-               composite.setLayoutData(CmsUiUtils.fillWidth());
+               composite.setLayoutData(CmsSwtUtils.fillWidth());
        }
 
        protected void clear(boolean deep) {
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/AbstractLoginDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/AbstractLoginDialog.java
deleted file mode 100644 (file)
index e7998cf..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.TrayDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.operation.ModalContext;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.osgi.framework.FrameworkUtil;
-
-/** Base for login dialogs */
-public abstract class AbstractLoginDialog extends TrayDialog implements CallbackHandler {
-       private static final long serialVersionUID = -8046708963512717709L;
-
-       private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
-
-       private Thread modalContextThread = null;
-       boolean processCallbacks = false;
-       boolean isCancelled = false;
-       Callback[] callbackArray;
-
-       protected final Callback[] getCallbacks() {
-               return this.callbackArray;
-       }
-
-       public abstract void internalHandle();
-
-       public boolean isCancelled() {
-               return isCancelled;
-       }
-
-       protected AbstractLoginDialog(Shell parentShell) {
-               super(parentShell);
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
-        * .callback.Callback[])
-        */
-       public void handle(final Callback[] callbacks) throws IOException {
-               // clean previous usage
-               if (processCallbacks) {
-                       // this handler was already used
-                       processCallbacks = false;
-               }
-
-               if (modalContextThread != null) {
-                       try {
-                               modalContextThread.join(1000);
-                       } catch (InterruptedException e) {
-                               // silent
-                       }
-                       modalContextThread = null;
-               }
-
-               // initialize
-               this.callbackArray = callbacks;
-               final Display display = Display.getDefault();
-               display.syncExec(new Runnable() {
-
-                       public void run() {
-                               isCancelled = false;
-                               setBlockOnOpen(false);
-                               open();
-
-                               final Button okButton = getButton(IDialogConstants.OK_ID);
-                               okButton.setText("Login");
-                               okButton.addSelectionListener(new SelectionListener() {
-                                       private static final long serialVersionUID = -200281625679096775L;
-
-                                       public void widgetSelected(final SelectionEvent event) {
-                                               processCallbacks = true;
-                                       }
-
-                                       public void widgetDefaultSelected(final SelectionEvent event) {
-                                               // nothing to do
-                                       }
-                               });
-                               final Button cancel = getButton(IDialogConstants.CANCEL_ID);
-                               cancel.addSelectionListener(new SelectionListener() {
-                                       private static final long serialVersionUID = -3826030278084915815L;
-
-                                       public void widgetSelected(final SelectionEvent event) {
-                                               isCancelled = true;
-                                               processCallbacks = true;
-                                       }
-
-                                       public void widgetDefaultSelected(final SelectionEvent event) {
-                                               // nothing to do
-                                       }
-                               });
-                       }
-               });
-               try {
-                       ModalContext.setAllowReadAndDispatch(true); // Works for now.
-                       ModalContext.run(new IRunnableWithProgress() {
-
-                               public void run(final IProgressMonitor monitor) {
-                                       modalContextThread = Thread.currentThread();
-                                       // Wait here until OK or cancel is pressed, then let it rip.
-                                       // The event
-                                       // listener
-                                       // is responsible for closing the dialog (in the
-                                       // loginSucceeded
-                                       // event).
-                                       while (!processCallbacks && (modalContextThread != null)
-                                                       && (modalContextThread == Thread.currentThread())
-                                                       && FrameworkUtil.getBundle(AbstractLoginDialog.class).getBundleContext() != null) {
-                                               // Note: SecurityUiPlugin.getDefault() != null is false
-                                               // when the OSGi runtime is shut down
-                                               try {
-                                                       Thread.sleep(100);
-                                                       // if (display.isDisposed()) {
-                                                       // log.warn("Display is disposed, killing login
-                                                       // dialog thread");
-                                                       // throw new ThreadDeath();
-                                                       // }
-                                               } catch (final Exception e) {
-                                                       // do nothing
-                                               }
-                                       }
-                                       processCallbacks = false;
-                                       // Call the adapter to handle the callbacks
-                                       if (!isCancelled())
-                                               internalHandle();
-                                       else
-                                               // clear callbacks are when cancelling
-                                               for (Callback callback : callbacks)
-                                                       if (callback instanceof PasswordCallback) {
-                                                               char[] arr = ((PasswordCallback) callback).getPassword();
-                                                               if (arr != null) {
-                                                                       Arrays.fill(arr, '*');
-                                                                       ((PasswordCallback) callback).setPassword(null);
-                                                               }
-                                                       } else if (callback instanceof NameCallback)
-                                                               ((NameCallback) callback).setName(null);
-                               }
-                       }, true, new NullProgressMonitor(), Display.getDefault());
-               } catch (ThreadDeath e) {
-                       isCancelled = true;
-                       log.debug("Thread " + Thread.currentThread().getId() + " died");
-                       throw e;
-               } catch (Exception e) {
-                       isCancelled = true;
-                       IOException ioe = new IOException("Unexpected issue in login dialog, see root cause for more details");
-                       ioe.initCause(e);
-                       throw ioe;
-               } finally {
-                       // so that the modal thread dies
-                       processCallbacks = true;
-                       // try {
-                       // // wait for the modal context thread to gracefully exit
-                       // modalContextThread.join();
-                       // } catch (InterruptedException ie) {
-                       // // silent
-                       // }
-                       modalContextThread = null;
-               }
-       }
-
-       protected void configureShell(Shell shell) {
-               super.configureShell(shell);
-               shell.setText("Authentication");
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CmsLogin.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CmsLogin.java
deleted file mode 100644 (file)
index 51c0ab4..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import static org.argeo.cms.CmsMsg.password;
-import static org.argeo.cms.CmsMsg.username;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Locale;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.LanguageCallback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.api.NodeConstants;
-import org.argeo.api.NodeState;
-import org.argeo.cms.CmsMsg;
-import org.argeo.cms.LocaleUtils;
-import org.argeo.cms.auth.HttpRequestCallback;
-import org.argeo.cms.ui.CmsStyles;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.internal.Activator;
-import org.argeo.cms.ui.util.CmsUiUtils;
-import org.argeo.eclipse.ui.specific.UiContext;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.events.TraverseEvent;
-import org.eclipse.swt.events.TraverseListener;
-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.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-public class CmsLogin implements CmsStyles, CallbackHandler {
-       private final static Log log = LogFactory.getLog(CmsLogin.class);
-
-       private Composite parent;
-       private Text usernameT, passwordT;
-       private Composite credentialsBlock;
-       private final SelectionListener loginSelectionListener;
-
-       private final Locale defaultLocale;
-       private LocaleChoice localeChoice = null;
-
-       private final CmsView cmsView;
-
-       // optional subject to be set explicitly
-       private Subject subject = null;
-
-       public CmsLogin(CmsView cmsView) {
-               this.cmsView = cmsView;
-               NodeState nodeState = Activator.getNodeState();
-               if (nodeState != null) {
-                       defaultLocale = nodeState.getDefaultLocale();
-                       List<Locale> locales = nodeState.getLocales();
-                       if (locales != null)
-                               localeChoice = new LocaleChoice(locales, defaultLocale);
-               } else {
-                       defaultLocale = Locale.getDefault();
-               }
-               loginSelectionListener = new SelectionListener() {
-                       private static final long serialVersionUID = -8832133363830973578L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               login();
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                       }
-               };
-       }
-
-       protected boolean isAnonymous() {
-               return cmsView.isAnonymous();
-       }
-
-       public final void createUi(Composite parent) {
-               this.parent = parent;
-               createContents(parent);
-       }
-
-       protected void createContents(Composite parent) {
-               defaultCreateContents(parent);
-       }
-
-       public final void defaultCreateContents(Composite parent) {
-               parent.setLayout(CmsUiUtils.noSpaceGridLayout());
-               Composite credentialsBlock = createCredentialsBlock(parent);
-               if (parent instanceof Shell) {
-                       credentialsBlock.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
-               }
-       }
-
-       public final Composite createCredentialsBlock(Composite parent) {
-               if (isAnonymous()) {
-                       return anonymousUi(parent);
-               } else {
-                       return userUi(parent);
-               }
-       }
-
-       public Composite getCredentialsBlock() {
-               return credentialsBlock;
-       }
-
-       protected Composite userUi(Composite parent) {
-               Locale locale = localeChoice == null ? this.defaultLocale : localeChoice.getSelectedLocale();
-               credentialsBlock = new Composite(parent, SWT.NONE);
-               credentialsBlock.setLayout(new GridLayout());
-               // credentialsBlock.setLayoutData(CmsUiUtils.fillAll());
-
-               specificUserUi(credentialsBlock);
-
-               Label l = new Label(credentialsBlock, SWT.NONE);
-               CmsUiUtils.style(l, CMS_USER_MENU_ITEM);
-               l.setText(CmsMsg.logout.lead(locale));
-               GridData lData = CmsUiUtils.fillWidth();
-               lData.widthHint = 120;
-               l.setLayoutData(lData);
-
-               l.addMouseListener(new MouseAdapter() {
-                       private static final long serialVersionUID = 6444395812777413116L;
-
-                       public void mouseDown(MouseEvent e) {
-                               logout();
-                       }
-               });
-               return credentialsBlock;
-       }
-
-       /** To be overridden */
-       protected void specificUserUi(Composite parent) {
-
-       }
-
-       protected Composite anonymousUi(Composite parent) {
-               Locale locale = localeChoice == null ? this.defaultLocale : localeChoice.getSelectedLocale();
-               // We need a composite for the traversal
-               credentialsBlock = new Composite(parent, SWT.NONE);
-               credentialsBlock.setLayout(new GridLayout());
-               // credentialsBlock.setLayoutData(CmsUiUtils.fillAll());
-               CmsUiUtils.style(credentialsBlock, CMS_LOGIN_DIALOG);
-
-               Integer textWidth = 120;
-               if (parent instanceof Shell)
-                       CmsUiUtils.style(parent, CMS_USER_MENU);
-               // new Label(this, SWT.NONE).setText(CmsMsg.username.lead());
-               usernameT = new Text(credentialsBlock, SWT.BORDER);
-               usernameT.setMessage(username.lead(locale));
-               CmsUiUtils.style(usernameT, CMS_LOGIN_DIALOG_USERNAME);
-               GridData gd = CmsUiUtils.fillWidth();
-               gd.widthHint = textWidth;
-               usernameT.setLayoutData(gd);
-
-               // new Label(this, SWT.NONE).setText(CmsMsg.password.lead());
-               passwordT = new Text(credentialsBlock, SWT.BORDER | SWT.PASSWORD);
-               passwordT.setMessage(password.lead(locale));
-               CmsUiUtils.style(passwordT, CMS_LOGIN_DIALOG_PASSWORD);
-               gd = CmsUiUtils.fillWidth();
-               gd.widthHint = textWidth;
-               passwordT.setLayoutData(gd);
-
-               TraverseListener tl = new TraverseListener() {
-                       private static final long serialVersionUID = -1158892811534971856L;
-
-                       public void keyTraversed(TraverseEvent e) {
-                               if (e.detail == SWT.TRAVERSE_RETURN)
-                                       login();
-                       }
-               };
-               credentialsBlock.addTraverseListener(tl);
-               usernameT.addTraverseListener(tl);
-               passwordT.addTraverseListener(tl);
-               parent.setTabList(new Control[] { credentialsBlock });
-               credentialsBlock.setTabList(new Control[] { usernameT, passwordT });
-
-               // Button
-               Button loginButton = new Button(credentialsBlock, SWT.PUSH);
-               loginButton.setText(CmsMsg.login.lead(locale));
-               loginButton.setLayoutData(CmsUiUtils.fillWidth());
-               loginButton.addSelectionListener(loginSelectionListener);
-
-               extendsCredentialsBlock(credentialsBlock, locale, loginSelectionListener);
-               if (localeChoice != null)
-                       createLocalesBlock(credentialsBlock);
-               return credentialsBlock;
-       }
-
-       /**
-        * To be overridden in order to provide custom login button and other links.
-        */
-       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
-                       SelectionListener loginSelectionListener) {
-
-       }
-
-       protected void updateLocale(Locale selectedLocale) {
-               // save already entered values
-               String usernameStr = usernameT.getText();
-               char[] pwd = passwordT.getTextChars();
-
-               for (Control child : parent.getChildren())
-                       child.dispose();
-               createContents(parent);
-               if (parent.getParent() != null)
-                       parent.getParent().layout(true, true);
-               else
-                       parent.layout();
-               usernameT.setText(usernameStr);
-               passwordT.setTextChars(pwd);
-       }
-
-       protected Composite createLocalesBlock(final Composite parent) {
-               Composite c = new Composite(parent, SWT.NONE);
-               CmsUiUtils.style(c, CMS_USER_MENU_ITEM);
-               c.setLayout(CmsUiUtils.noSpaceGridLayout());
-               c.setLayoutData(CmsUiUtils.fillAll());
-
-               SelectionListener selectionListener = new SelectionAdapter() {
-                       private static final long serialVersionUID = 4891637813567806762L;
-
-                       public void widgetSelected(SelectionEvent event) {
-                               Button button = (Button) event.widget;
-                               if (button.getSelection()) {
-                                       localeChoice.setSelectedIndex((Integer) event.widget.getData());
-                                       updateLocale(localeChoice.getSelectedLocale());
-                               }
-                       };
-               };
-
-               List<Locale> locales = localeChoice.getLocales();
-               for (Integer i = 0; i < locales.size(); i++) {
-                       Locale locale = locales.get(i);
-                       Button button = new Button(c, SWT.RADIO);
-                       CmsUiUtils.style(button, CMS_USER_MENU_ITEM);
-                       button.setData(i);
-                       button.setText(LocaleUtils.toLead(locale.getDisplayName(locale), locale) + " (" + locale + ")");
-                       // button.addListener(SWT.Selection, listener);
-                       button.addSelectionListener(selectionListener);
-                       if (i == localeChoice.getSelectedIndex())
-                               button.setSelection(true);
-               }
-               return c;
-       }
-
-       protected boolean login() {
-               // TODO use CmsVie in order to retrieve subject?
-               // Subject subject = cmsView.getLoginContext().getSubject();
-               // LoginContext loginContext = cmsView.getLoginContext();
-               try {
-                       //
-                       // LOGIN
-                       //
-                       // loginContext.logout();
-                       LoginContext loginContext;
-                       if (subject == null)
-                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, this);
-                       else
-                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, this);
-                       loginContext.login();
-                       cmsView.authChange(loginContext);
-                       return true;
-               } catch (LoginException e) {
-                       if (log.isTraceEnabled())
-                               log.warn("Login failed: " + e.getMessage(), e);
-                       else
-                               log.warn("Login failed: " + e.getMessage());
-
-                       try {
-                               Thread.sleep(3000);
-                       } catch (InterruptedException e2) {
-                               // silent
-                       }
-                       // ErrorFeedback.show("Login failed", e);
-                       return false;
-               }
-               // catch (LoginException e) {
-               // log.error("Cannot login", e);
-               // return false;
-               // }
-       }
-
-       protected void logout() {
-               cmsView.logout();
-               cmsView.navigateTo("~");
-       }
-
-       @Override
-       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-               for (Callback callback : callbacks) {
-                       if (callback instanceof NameCallback && usernameT != null)
-                               ((NameCallback) callback).setName(usernameT.getText());
-                       else if (callback instanceof PasswordCallback && passwordT != null)
-                               ((PasswordCallback) callback).setPassword(passwordT.getTextChars());
-                       else if (callback instanceof HttpRequestCallback) {
-                               ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
-                               ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse());
-                       } else if (callback instanceof LanguageCallback) {
-                               Locale toUse = null;
-                               if (localeChoice != null)
-                                       toUse = localeChoice.getSelectedLocale();
-                               else if (defaultLocale != null)
-                                       toUse = defaultLocale;
-
-                               if (toUse != null) {
-                                       ((LanguageCallback) callback).setLocale(toUse);
-                                       UiContext.setLocale(toUse);
-                               }
-
-                       }
-               }
-       }
-
-       public void setSubject(Subject subject) {
-               this.subject = subject;
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CmsLoginShell.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CmsLoginShell.java
deleted file mode 100644 (file)
index f260f83..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.ui.util.CmsUiUtils;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** The site-related user menu */
-public class CmsLoginShell extends CmsLogin {
-       private final Shell shell;
-
-       public CmsLoginShell(CmsView cmsView) {
-               super(cmsView);
-               shell = createShell();
-//             createUi(shell);
-       }
-
-       /** To be overridden. */
-       protected Shell createShell() {
-               Shell shell = new Shell(Display.getCurrent(), SWT.NO_TRIM);
-               shell.setMaximized(true);
-               return shell;
-       }
-
-       /** To be overridden. */
-       public void open() {
-               CmsUiUtils.style(shell, CMS_USER_MENU);
-               shell.open();
-       }
-
-       @Override
-       protected boolean login() {
-               boolean success = false;
-               try {
-                       success = super.login();
-                       return success;
-               } finally {
-                       if (success)
-                               closeShell();
-                       else {
-                               for (Control child : shell.getChildren())
-                                       child.dispose();
-                               createUi(shell);
-                               shell.layout();
-                               // TODO error message
-                       }
-               }
-       }
-
-       @Override
-       protected void logout() {
-               closeShell();
-               super.logout();
-       }
-
-       protected void closeShell() {
-               if (!shell.isDisposed()) {
-                       shell.close();
-                       shell.dispose();
-               }
-       }
-
-       public Shell getShell() {
-               return shell;
-       }
-       
-       public void createUi(){
-               createUi(shell);
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CompositeCallbackHandler.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/CompositeCallbackHandler.java
deleted file mode 100644 (file)
index 974b676..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextOutputCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * A composite that can populate itself based on {@link Callback}s. It can be
- * used directly as a {@link CallbackHandler} or be used by one by calling the
- * {@link #createCallbackHandlers(Callback[])}. Supported standard
- * {@link Callback}s are:<br>
- * <ul>
- * <li>{@link PasswordCallback}</li>
- * <li>{@link NameCallback}</li>
- * <li>{@link TextOutputCallback}</li>
- * </ul>
- * Supported Argeo {@link Callback}s are:<br>
- * <ul>
- * <li>{@link LocaleChoice}</li>
- * </ul>
- */
-public class CompositeCallbackHandler extends Composite implements CallbackHandler {
-       private static final long serialVersionUID = -928223893722723777L;
-
-       private boolean wasUsedAlready = false;
-       private boolean isSubmitted = false;
-       private boolean isCanceled = false;
-
-       public CompositeCallbackHandler(Composite parent, int style) {
-               super(parent, style);
-       }
-
-       @Override
-       public synchronized void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-               // reset
-               if (wasUsedAlready && !isSubmitted() && !isCanceled()) {
-                       cancel();
-                       for (Control control : getChildren())
-                               control.dispose();
-                       isSubmitted = false;
-                       isCanceled = false;
-               }
-
-               for (Callback callback : callbacks)
-                       checkCallbackSupported(callback);
-               // create controls synchronously in the UI thread
-               getDisplay().syncExec(new Runnable() {
-
-                       @Override
-                       public void run() {
-                               createCallbackHandlers(callbacks);
-                       }
-               });
-
-               if (!wasUsedAlready)
-                       wasUsedAlready = true;
-
-               // while (!isSubmitted() && !isCanceled()) {
-               // try {
-               // wait(1000l);
-               // } catch (InterruptedException e) {
-               // // silent
-               // }
-               // }
-
-               // cleanCallbacksAfterCancel(callbacks);
-       }
-
-       public void checkCallbackSupported(Callback callback) throws UnsupportedCallbackException {
-               if (callback instanceof TextOutputCallback || callback instanceof NameCallback
-                               || callback instanceof PasswordCallback || callback instanceof LocaleChoice) {
-                       return;
-               } else {
-                       throw new UnsupportedCallbackException(callback);
-               }
-       }
-
-       /**
-        * Set writable callbacks to null if the handle is canceled (check is done
-        * by the method)
-        */
-       public void cleanCallbacksAfterCancel(Callback[] callbacks) {
-               if (isCanceled()) {
-                       for (Callback callback : callbacks) {
-                               if (callback instanceof NameCallback) {
-                                       ((NameCallback) callback).setName(null);
-                               } else if (callback instanceof PasswordCallback) {
-                                       PasswordCallback pCallback = (PasswordCallback) callback;
-                                       char[] arr = pCallback.getPassword();
-                                       if (arr != null) {
-                                               Arrays.fill(arr, '*');
-                                               pCallback.setPassword(null);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       public void createCallbackHandlers(Callback[] callbacks) {
-               Composite composite = this;
-               for (int i = 0; i < callbacks.length; i++) {
-                       Callback callback = callbacks[i];
-                       if (callback instanceof TextOutputCallback) {
-                               createLabelTextoutputHandler(composite, (TextOutputCallback) callback);
-                       } else if (callback instanceof NameCallback) {
-                               createNameHandler(composite, (NameCallback) callback);
-                       } else if (callback instanceof PasswordCallback) {
-                               createPasswordHandler(composite, (PasswordCallback) callback);
-                       } else if (callback instanceof LocaleChoice) {
-                               createLocaleHandler(composite, (LocaleChoice) callback);
-                       }
-               }
-       }
-
-       protected Text createNameHandler(Composite composite, final NameCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-               final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
-               if (callback.getDefaultName() != null) {
-                       // set default value, if provided
-                       text.setText(callback.getDefaultName());
-                       callback.setName(callback.getDefaultName());
-               }
-               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               text.addModifyListener(new ModifyListener() {
-                       private static final long serialVersionUID = 7300032545287292973L;
-
-                       public void modifyText(ModifyEvent event) {
-                               callback.setName(text.getText());
-                       }
-               });
-               text.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = 1820530045857665111L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                               submit();
-                       }
-               });
-
-               text.addKeyListener(new KeyListener() {
-                       private static final long serialVersionUID = -8698107785092095713L;
-
-                       @Override
-                       public void keyReleased(KeyEvent e) {
-                       }
-
-                       @Override
-                       public void keyPressed(KeyEvent e) {
-                       }
-               });
-               return text;
-       }
-
-       protected Text createPasswordHandler(Composite composite, final PasswordCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-               final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD | SWT.BORDER);
-               passwordText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               passwordText.addModifyListener(new ModifyListener() {
-                       private static final long serialVersionUID = -7099363995047686732L;
-
-                       public void modifyText(ModifyEvent event) {
-                               callback.setPassword(passwordText.getTextChars());
-                       }
-               });
-               passwordText.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = 1820530045857665111L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                               submit();
-                       }
-               });
-               return passwordText;
-       }
-
-       protected Combo createLocaleHandler(Composite composite, final LocaleChoice callback) {
-               String[] labels = callback.getSupportedLocalesLabels();
-               if (labels.length == 0)
-                       return null;
-               Label label = new Label(composite, SWT.NONE);
-               label.setText("Language");
-
-               final Combo combo = new Combo(composite, SWT.READ_ONLY);
-               combo.setItems(labels);
-               combo.select(callback.getDefaultIndex());
-               combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               combo.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = 38678989091946277L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               callback.setSelectedIndex(combo.getSelectionIndex());
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                       }
-               });
-               return combo;
-       }
-
-       protected Label createLabelTextoutputHandler(Composite composite, final TextOutputCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getMessage());
-               GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
-               data.horizontalSpan = 2;
-               label.setLayoutData(data);
-               return label;
-               // TODO: find a way to pass this information
-               // int messageType = callback.getMessageType();
-               // int dialogMessageType = IMessageProvider.NONE;
-               // switch (messageType) {
-               // case TextOutputCallback.INFORMATION:
-               // dialogMessageType = IMessageProvider.INFORMATION;
-               // break;
-               // case TextOutputCallback.WARNING:
-               // dialogMessageType = IMessageProvider.WARNING;
-               // break;
-               // case TextOutputCallback.ERROR:
-               // dialogMessageType = IMessageProvider.ERROR;
-               // break;
-               // }
-               // setMessage(callback.getMessage(), dialogMessageType);
-       }
-
-       synchronized boolean isSubmitted() {
-               return isSubmitted;
-       }
-
-       synchronized boolean isCanceled() {
-               return isCanceled;
-       }
-
-       protected synchronized void submit() {
-               isSubmitted = true;
-               notifyAll();
-       }
-
-       protected synchronized void cancel() {
-               isCanceled = true;
-               notifyAll();
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/DefaultLoginDialog.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/DefaultLoginDialog.java
deleted file mode 100644 (file)
index 6ffc2ef..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import javax.security.auth.callback.CallbackHandler;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-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.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** Default authentication dialog, to be used as {@link CallbackHandler}. */
-public class DefaultLoginDialog extends AbstractLoginDialog {
-       private static final long serialVersionUID = -8551827590693035734L;
-
-       public DefaultLoginDialog() {
-               this(Display.getCurrent().getActiveShell());
-       }
-
-       public DefaultLoginDialog(Shell parentShell) {
-               super(parentShell);
-       }
-
-       protected Point getInitialSize() {
-               return new Point(350, 180);
-       }
-
-       @Override
-       protected Control createContents(Composite parent) {
-               Control control = super.createContents(parent);
-               parent.pack();
-
-               // Move the dialog to the center of the top level shell.
-               Rectangle shellBounds;
-               if (Display.getCurrent().getActiveShell() != null) // RCP
-                       shellBounds = Display.getCurrent().getActiveShell().getBounds();
-               else
-                       shellBounds = Display.getCurrent().getBounds();// RAP
-               Point dialogSize = parent.getSize();
-               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
-               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
-               parent.setLocation(x, y);
-               return control;
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogarea = (Composite) super.createDialogArea(parent);
-               CompositeCallbackHandler composite = new CompositeCallbackHandler(
-                               dialogarea, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               composite.createCallbackHandlers(getCallbacks());
-               return composite;
-       }
-
-       public void internalHandle() {
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/DynamicCallbackHandler.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/DynamicCallbackHandler.java
deleted file mode 100644 (file)
index e470bda..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.argeo.eclipse.ui.dialogs.LightweightDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-public class DynamicCallbackHandler implements CallbackHandler {
-
-       @Override
-       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-               Shell activeShell = Display.getCurrent().getActiveShell();
-               LightweightDialog dialog = new LightweightDialog(activeShell) {
-
-                       @Override
-                       protected Control createDialogArea(Composite parent) {
-                               CompositeCallbackHandler cch = new CompositeCallbackHandler(parent, SWT.NONE);
-                               cch.createCallbackHandlers(callbacks);
-                               return cch;
-                       }
-               };
-               dialog.setBlockOnOpen(true);
-               dialog.open();
-       }
-
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/LocaleChoice.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/LocaleChoice.java
deleted file mode 100644 (file)
index 677c879..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.argeo.cms.ui.widgets.auth;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-import javax.security.auth.callback.LanguageCallback;
-
-import org.argeo.cms.CmsException;
-import org.argeo.cms.LocaleUtils;
-
-/** Choose in a list of locales. TODO: replace with {@link LanguageCallback} */
-public class LocaleChoice {
-       private final List<Locale> locales;
-
-       private Integer selectedIndex = null;
-       private final Integer defaultIndex;
-
-       public LocaleChoice(List<Locale> locales, Locale defaultLocale) {
-               Integer defaultIndex = null;
-               this.locales = Collections.unmodifiableList(locales);
-               for (int i = 0; i < locales.size(); i++)
-                       if (locales.get(i).equals(defaultLocale))
-                               defaultIndex = i;
-
-               // based on language only
-               if (defaultIndex == null)
-                       for (int i = 0; i < locales.size(); i++)
-                               if (locales.get(i).getLanguage().equals(defaultLocale.getLanguage()))
-                                       defaultIndex = i;
-
-               if (defaultIndex == null)
-                       throw new CmsException("Default locale " + defaultLocale + " is not in available locales " + locales);
-               this.defaultIndex = defaultIndex;
-
-               this.selectedIndex = defaultIndex;
-       }
-
-       /**
-        * Convenience constructor based on a comma separated list of iso codes (en,
-        * en_US, fr_CA, etc.). Default selection is default locale.
-        */
-       public LocaleChoice(String locales, Locale defaultLocale) {
-               this(LocaleUtils.asLocaleList(locales), defaultLocale);
-       }
-
-       public String[] getSupportedLocalesLabels() {
-               String[] labels = new String[locales.size()];
-               for (int i = 0; i < locales.size(); i++) {
-                       Locale locale = locales.get(i);
-                       if (locale.getCountry().equals(""))
-                               labels[i] = locale.getDisplayLanguage(locale) + " [" + locale.getLanguage() + "]";
-                       else
-                               labels[i] = locale.getDisplayLanguage(locale) + " (" + locale.getDisplayCountry(locale) + ") ["
-                                               + locale.getLanguage() + "_" + locale.getCountry() + "]";
-
-               }
-               return labels;
-       }
-
-       public Locale getSelectedLocale() {
-               if (selectedIndex == null)
-                       return null;
-               return locales.get(selectedIndex);
-       }
-
-       public void setSelectedIndex(Integer selectedIndex) {
-               this.selectedIndex = selectedIndex;
-       }
-
-       public Integer getSelectedIndex() {
-               return selectedIndex;
-       }
-
-       public Integer getDefaultIndex() {
-               return defaultIndex;
-       }
-
-       public List<Locale> getLocales() {
-               return locales;
-       }
-
-       public Locale getDefaultLocale() {
-               return locales.get(getDefaultIndex());
-       }
-}
diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/package-info.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/widgets/auth/package-info.java
deleted file mode 100644 (file)
index 9a37a58..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/** Argeo CMS authentication widgets, based on SWT. */
-package org.argeo.cms.ui.widgets.auth;
\ No newline at end of file
diff --git a/org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java b/org.argeo.cms/src/org/argeo/cms/AbstractCmsApp.java
new file mode 100644 (file)
index 0000000..a7049a4
--- /dev/null
@@ -0,0 +1,69 @@
+package org.argeo.cms;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.argeo.api.cms.CmsApp;
+import org.argeo.api.cms.CmsAppListener;
+import org.argeo.api.cms.CmsTheme;
+
+/** Base class for {@link CmsApp}s. */
+public abstract class AbstractCmsApp implements CmsApp {
+       private Map<String, CmsTheme> themes = Collections.synchronizedMap(new HashMap<>());
+
+       private List<CmsAppListener> cmsAppListeners = new ArrayList<>();
+
+       protected abstract String getThemeId(String uiName);
+
+       @Override
+       public CmsTheme getTheme(String uiName) {
+               String themeId = getThemeId(uiName);
+               if (themeId == null)
+                       return null;
+               if (!themes.containsKey(themeId))
+                       throw new IllegalArgumentException("Theme " + themeId + " not found.");
+               return themes.get(themeId);
+       }
+
+       @Override
+       public boolean allThemesAvailable() {
+               boolean themeMissing = false;
+               uiNames: for (String uiName : getUiNames()) {
+                       String themeId = getThemeId(uiName);
+                       if ("org.eclipse.rap.rwt.theme.Default".equals(themeId))
+                               continue uiNames;
+                       if (!themes.containsKey(themeId)) {
+                               themeMissing = true;
+                               break uiNames;
+                       }
+               }
+               return !themeMissing;
+       }
+
+       public void addTheme(CmsTheme theme, Map<String, String> properties) {
+               themes.put(theme.getThemeId(), theme);
+               if (allThemesAvailable())
+                       for (CmsAppListener listener : cmsAppListeners)
+                               listener.themingUpdated();
+       }
+
+       public void removeTheme(CmsTheme theme, Map<String, String> properties) {
+               themes.remove(theme.getThemeId());
+       }
+
+       @Override
+       public void addCmsAppListener(CmsAppListener listener) {
+               cmsAppListeners.add(listener);
+               if (allThemesAvailable())
+                       listener.themingUpdated();
+       }
+
+       @Override
+       public void removeCmsAppListener(CmsAppListener listener) {
+               cmsAppListeners.remove(listener);
+       }
+
+}
index 4c09650d4b0546bdc5c6220a23f23de99903cf95..e854f5adfcd213bfbf31e2de2f97f3c44247727c 100644 (file)
@@ -14,6 +14,8 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.CmsSessionId;
 import org.argeo.api.security.AnonymousPrincipal;
 import org.argeo.api.security.DataAdminPrincipal;
 import org.argeo.api.security.NodeSecurityUtils;
@@ -186,7 +188,7 @@ class CmsAuthUtils {
                }
        }
 
-       public static CmsSession cmsSessionFromHttpSession(BundleContext bc, String httpSessionId) {
+       public static CmsSessionImpl cmsSessionFromHttpSession(BundleContext bc, String httpSessionId) {
                Authorization authorization = null;
                Collection<ServiceReference<CmsSession>> sr;
                try {
@@ -195,9 +197,9 @@ class CmsAuthUtils {
                } catch (InvalidSyntaxException e) {
                        throw new IllegalArgumentException("Cannot get CMS session for id " + httpSessionId, e);
                }
-               CmsSession cmsSession;
+               CmsSessionImpl cmsSession;
                if (sr.size() == 1) {
-                       cmsSession = bc.getService(sr.iterator().next());
+                       cmsSession = (CmsSessionImpl) bc.getService(sr.iterator().next());
 //                     locale = cmsSession.getLocale();
                        authorization = cmsSession.getAuthorization();
                        if (authorization.getName() == null)
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsSession.java
deleted file mode 100644 (file)
index ad91cb7..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.argeo.cms.auth;
-
-import java.time.ZonedDateTime;
-import java.util.Collection;
-import java.util.Locale;
-import java.util.UUID;
-
-import javax.naming.ldap.LdapName;
-import javax.security.auth.Subject;
-
-import org.argeo.naming.LdapAttrs;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.useradmin.Authorization;
-
-/** An authenticated user session. */
-public interface CmsSession {
-       final static String USER_DN = LdapAttrs.DN;
-       final static String SESSION_UUID = LdapAttrs.entryUUID.name();
-       final static String SESSION_LOCAL_ID = LdapAttrs.uniqueIdentifier.name();
-
-       UUID getUuid();
-
-       String getUserRole();
-       
-       LdapName getUserDn();
-
-       String getLocalId();
-
-       Authorization getAuthorization();
-       
-       Subject getSubject();
-
-       boolean isAnonymous();
-
-       ZonedDateTime getCreationTime();
-
-       ZonedDateTime getEnd();
-
-       Locale getLocale();
-
-       boolean isValid();
-
-       void registerView(String uid, Object view);
-
-       /** @return The {@link CmsSession} for this {@link Subject} or null. */
-       static CmsSession getCmsSession(BundleContext bc, Subject subject) {
-               if (subject.getPrivateCredentials(CmsSessionId.class).isEmpty())
-                       return null;
-               CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next();
-               String uuid = cmsSessionId.getUuid().toString();
-               Collection<ServiceReference<CmsSession>> sr;
-               try {
-                       sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")");
-               } catch (InvalidSyntaxException e) {
-                       throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e);
-               }
-               ServiceReference<CmsSession> cmsSessionRef;
-               if (sr.size() == 1) {
-                       cmsSessionRef = sr.iterator().next();
-                       return bc.getService(cmsSessionRef);
-               } else if (sr.size() == 0) {
-                       return null;
-               } else
-                       throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid);
-       }
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsSessionId.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsSessionId.java
deleted file mode 100644 (file)
index cc435ae..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.argeo.cms.auth;
-
-import java.util.UUID;
-
-import javax.security.auth.Subject;
-
-/**
- * The ID of a {@link CmsSession}, which must be available in the private
- * credentials of an authenticated {@link Subject}.
- */
-public class CmsSessionId {
-       private final UUID uuid;
-
-       public CmsSessionId(UUID value) {
-               if (value == null)
-                       throw new IllegalArgumentException("Value cannot be null");
-               this.uuid = value;
-       }
-
-       public UUID getUuid() {
-               return uuid;
-       }
-
-       @Override
-       public int hashCode() {
-               return uuid.hashCode();
-       }
-
-       @Override
-       public boolean equals(Object obj) {
-               return obj instanceof CmsSessionId && ((CmsSessionId) obj).getUuid().equals(uuid);
-       }
-
-       @Override
-       public String toString() {
-               return "Node Session " + uuid;
-       }
-
-}
index eaaf41ab72a458ee7acacb0778315922c9c52ba5..9808305ce0000c4132b933db09142efe5c71cc7b 100644 (file)
@@ -14,6 +14,8 @@ import javax.security.auth.Subject;
 import javax.security.auth.x500.X500Principal;
 
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.CmsSessionId;
 import org.argeo.cms.internal.auth.CmsSessionImpl;
 import org.argeo.cms.internal.auth.ImpliedByPrincipal;
 import org.argeo.cms.internal.kernel.Activator;
index 8cb524fbe344bd6b864a40b5bfd0f89555ba7a3a..c2dfead780ac8c9d71e2bbc932eafad00c15321e 100644 (file)
@@ -19,6 +19,7 @@ import javax.servlet.http.HttpSession;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.internal.auth.CmsSessionImpl;
 import org.argeo.cms.internal.kernel.Activator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -73,7 +74,7 @@ public class HttpSessionLoginModule implements LoginModule {
                        String httpSessionId = httpSession.getId();
                        if (log.isTraceEnabled())
                                log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
-                       CmsSession cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
+                       CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
                        if (cmsSession != null) {
                                authorization = cmsSession.getAuthorization();
                                locale = cmsSession.getLocale();
@@ -93,7 +94,7 @@ public class HttpSessionLoginModule implements LoginModule {
                                String httpSessionId = httpSession.getId();
                                if (log.isTraceEnabled())
                                        log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
-                               CmsSession cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
+                               CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
                                if (cmsSession != null) {
                                        authorization = cmsSession.getAuthorization();
                                        locale = cmsSession.getLocale();
index 734b874efff24743c9dc998f5c6aab0db9d67f16..4e9b4e07293188b62e31d4fcdf383e71f90ee613 100644 (file)
@@ -24,8 +24,8 @@ import javax.security.auth.x500.X500Principal;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
+import org.argeo.api.cms.CmsSession;
 import org.argeo.api.security.NodeSecurityUtils;
-import org.argeo.cms.auth.CmsSession;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
@@ -93,7 +93,6 @@ public class CmsSessionImpl implements CmsSession, Serializable {
                end = ZonedDateTime.now();
                serviceRegistration.unregister();
 
-
                try {
                        LoginContext lc;
                        if (isAnonymous()) {
@@ -133,12 +132,16 @@ public class CmsSessionImpl implements CmsSession, Serializable {
                return getEnd() != null;
        }
 
-       @Override
        public Authorization getAuthorization() {
                checkValid();
                return authorization;
        }
 
+       @Override
+       public String getDisplayName() {
+               return authorization.toString();
+       }
+
        @Override
        public UUID getUuid() {
                return uuid;
index e12456ebb4b73fe80883d26a3a3c3512c1eece2c..26046b246c9bdf329726152207ab1e1f20fc7477 100644 (file)
@@ -13,7 +13,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.io.IOUtils;
-import org.argeo.api.PublishNamespace;
+import org.argeo.cms.osgi.PublishNamespace;
 import org.argeo.osgi.util.FilterRequirement;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
index 8c9e4ba6cb8676d39d2294f37e7f6eaa479789ca..f29d9e98e9420a78b89d14d5a9c38180bf00c1b7 100644 (file)
@@ -16,7 +16,7 @@ import java.util.TreeMap;
 import java.util.TreeSet;
 
 import org.apache.commons.logging.Log;
-import org.argeo.api.DataModelNamespace;
+import org.argeo.cms.osgi.DataModelNamespace;
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
 
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/BundleCmsTheme.java b/org.argeo.cms/src/org/argeo/cms/osgi/BundleCmsTheme.java
new file mode 100644 (file)
index 0000000..75a2212
--- /dev/null
@@ -0,0 +1,360 @@
+package org.argeo.cms.osgi;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.api.cms.CmsTheme;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Simplifies the theming of an app (only RAP is supported at this stage).<br>
+ * 
+ * Additional fonts listed in <code>/fonts.txt</code>.<br>
+ * Additional (standard CSS) header in <code>/header.css</code>.<br>
+ * RAP specific CSS files in <code>/rap/*.css</code>.<br>
+ * All images added as additional resources based on extensions
+ * <code>/ ** /*.{png,gif,jpeg,...}</code>.<br>
+ */
+public class BundleCmsTheme implements CmsTheme {
+       public final static String DEFAULT_CMS_THEME_BUNDLE = "org.argeo.theme.argeo2";
+
+       public final static String CMS_THEME_PROPERTY = "argeo.cms.theme";
+       public final static String CMS_THEME_BUNDLE_PROPERTY = "argeo.cms.theme.bundle";
+
+       private final static String HEADER_CSS = "header.css";
+       private final static String FONTS_TXT = "fonts.txt";
+       private final static String BODY_HTML = "body.html";
+
+//     private final static Log log = LogFactory.getLog(BundleCmsTheme.class);
+
+       private String themeId;
+       private Set<String> webCssPaths = new TreeSet<>();
+       private Set<String> rapCssPaths = new TreeSet<>();
+       private Set<String> swtCssPaths = new TreeSet<>();
+       private Set<String> imagesPaths = new TreeSet<>();
+       private Set<String> fontsPaths = new TreeSet<>();
+
+       private String headerCss;
+       private List<String> fonts = new ArrayList<>();
+
+       private String bodyHtml="<body></body>";
+
+       private String basePath;
+       private String styleCssPath;
+//     private String webCssPath;
+//     private String rapCssPath;
+//     private String swtCssPath;
+       private Bundle themeBundle;
+
+       private Integer defaultIconSize = 16;
+
+       public BundleCmsTheme() {
+
+       }
+
+       public void init(BundleContext bundleContext, Map<String, String> properties) {
+               initResources(bundleContext, null);
+       }
+
+       public void destroy(BundleContext bundleContext, Map<String, String> properties) {
+
+       }
+
+       @Deprecated
+       public BundleCmsTheme(BundleContext bundleContext) {
+               this(bundleContext, null);
+       }
+
+       @Deprecated
+       public BundleCmsTheme(BundleContext bundleContext, String symbolicName) {
+               initResources(bundleContext, symbolicName);
+       }
+
+       private void initResources(BundleContext bundleContext, String symbolicName) {
+               if (symbolicName == null) {
+                       themeBundle = bundleContext.getBundle();
+//                     basePath = "/theme/";
+//                     cssPath = basePath;
+               } else {
+                       themeBundle = findThemeBundle(bundleContext, symbolicName);
+               }
+               basePath = "/";
+               styleCssPath = "/style/";
+//             webCssPath = "/css/";
+//             rapCssPath = "/rap/";
+//             swtCssPath = "/swt/";
+//             this.themeId = RWT.DEFAULT_THEME_ID;
+               this.themeId = themeBundle.getSymbolicName();
+               webCssPaths = addCss(themeBundle, "/css/");
+               rapCssPaths = addCss(themeBundle, "/rap/");
+               swtCssPaths = addCss(themeBundle, "/swt/");
+               addImages("*.png");
+               addImages("*.gif");
+               addImages("*.jpg");
+               addImages("*.jpeg");
+               addImages("*.svg");
+               addImages("*.ico");
+
+               addFonts("*.woff");
+               addFonts("*.woff2");
+
+               // fonts
+               URL fontsUrl = themeBundle.getEntry(basePath + FONTS_TXT);
+               if (fontsUrl != null) {
+                       loadFontsUrl(fontsUrl);
+               }
+
+               // common CSS header (plain CSS)
+               URL headerCssUrl = themeBundle.getEntry(basePath + HEADER_CSS);
+               if (headerCssUrl != null) {
+                       // added to plain Web CSS
+                       webCssPaths.add(basePath + HEADER_CSS);
+                       // and it will also be used by RAP:
+                       try (BufferedReader buffer = new BufferedReader(new InputStreamReader(headerCssUrl.openStream(), UTF_8))) {
+                               headerCss = buffer.lines().collect(Collectors.joining("\n"));
+                       } catch (IOException e) {
+                               throw new IllegalArgumentException("Cannot read " + headerCssUrl, e);
+                       }
+               }
+
+               // body
+               URL bodyUrl = themeBundle.getEntry(basePath + BODY_HTML);
+               if (bodyUrl != null) {
+                       loadBodyHtml(bodyUrl);
+               }
+}
+
+       public String getHtmlHeaders() {
+               StringBuilder sb = new StringBuilder();
+               if (headerCss != null) {
+                       sb.append("<style type='text/css'>\n");
+                       sb.append(headerCss);
+                       sb.append("\n</style>\n");
+               }
+               for (String link : fonts) {
+                       sb.append("<link rel='stylesheet' href='");
+                       sb.append(link);
+                       sb.append("'/>\n");
+               }
+               if (sb.length() == 0)
+                       return null;
+               else
+                       return sb.toString();
+       }
+       
+       
+
+       @Override
+       public String getBodyHtml() {
+               return bodyHtml;
+       }
+
+       Set<String> addCss(Bundle themeBundle, String path) {
+               Set<String> paths = new TreeSet<>();
+
+               // common CSS
+               Enumeration<URL> commonResources = themeBundle.findEntries(styleCssPath, "*.css", true);
+               if (commonResources != null) {
+                       while (commonResources.hasMoreElements()) {
+                               String resource = commonResources.nextElement().getPath();
+                               // remove first '/' so that RWT registers it
+                               resource = resource.substring(1);
+                               if (!resource.endsWith("/")) {
+                                       paths.add(resource);
+                               }
+                       }
+               }
+
+               // specific CSS
+               Enumeration<URL> themeResources = themeBundle.findEntries(path, "*.css", true);
+               if (themeResources != null) {
+                       while (themeResources.hasMoreElements()) {
+                               String resource = themeResources.nextElement().getPath();
+                               // remove first '/' so that RWT registers it
+                               resource = resource.substring(1);
+                               if (!resource.endsWith("/")) {
+                                       paths.add(resource);
+                               }
+                       }
+               }
+               return paths;
+       }
+
+       void loadFontsUrl(URL url) {
+               try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) {
+                       String line = null;
+                       while ((line = in.readLine()) != null) {
+                               line = line.trim();
+                               if (!line.equals("") && !line.startsWith("#")) {
+                                       fonts.add(line);
+                               }
+                       }
+               } catch (IOException e) {
+                       throw new IllegalArgumentException("Cannot load URL " + url, e);
+               }
+       }
+
+       void loadBodyHtml(URL url) {
+               try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) {
+               bodyHtml=       IOUtils.toString(url,StandardCharsets.UTF_8);
+               } catch (IOException e) {
+                       throw new IllegalArgumentException("Cannot load URL " + url, e);
+               }
+       }
+
+       void addImages(String pattern) {
+               Enumeration<URL> themeResources = themeBundle.findEntries(basePath, pattern, true);
+               if (themeResources == null)
+                       return;
+               while (themeResources.hasMoreElements()) {
+                       String resource = themeResources.nextElement().getPath();
+                       // remove first '/' so that RWT registers it
+                       resource = resource.substring(1);
+                       if (!resource.endsWith("/")) {
+//                             if (resources.containsKey(resource))
+//                                     log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
+//                             resources.put(resource, themeBRL);
+                               imagesPaths.add(resource);
+                       }
+
+               }
+
+       }
+
+       void addFonts(String pattern) {
+               Enumeration<URL> themeResources = themeBundle.findEntries(basePath, pattern, true);
+               if (themeResources == null)
+                       return;
+               while (themeResources.hasMoreElements()) {
+                       String resource = themeResources.nextElement().getPath();
+                       // remove first '/' so that RWT registers it
+                       resource = resource.substring(1);
+                       if (!resource.endsWith("/")) {
+//                             if (resources.containsKey(resource))
+//                                     log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
+//                             resources.put(resource, themeBRL);
+                               fontsPaths.add(resource);
+                       }
+
+               }
+
+       }
+
+       @Override
+       public InputStream getResourceAsStream(String resourceName) throws IOException {
+               URL res = themeBundle.getEntry(resourceName);
+               if (res == null) {
+                       res = themeBundle.getResource(resourceName);
+                       if (res == null)
+                               return null;
+//                             throw new IllegalArgumentException(
+//                                             "Resource " + resourceName + " not found in bundle " + themeBundle.getSymbolicName());
+               }
+               return res.openStream();
+       }
+
+       public String getThemeId() {
+               return themeId;
+       }
+
+//     public void setThemeId(String themeId) {
+//             this.themeId = themeId;
+//     }
+//
+//     public String getBasePath() {
+//             return basePath;
+//     }
+//
+//     public void setBasePath(String basePath) {
+//             this.basePath = basePath;
+//     }
+//
+//     public String getRapCssPath() {
+//             return rapCssPath;
+//     }
+//
+//     public void setRapCssPath(String cssPath) {
+//             this.rapCssPath = cssPath;
+//     }
+
+       @Override
+       public Set<String> getWebCssPaths() {
+               return webCssPaths;
+       }
+
+       @Override
+       public Set<String> getRapCssPaths() {
+               return rapCssPaths;
+       }
+
+       @Override
+       public Set<String> getSwtCssPaths() {
+               return swtCssPaths;
+       }
+
+       @Override
+       public Set<String> getImagesPaths() {
+               return imagesPaths;
+       }
+
+       @Override
+       public Set<String> getFontsPaths() {
+               return fontsPaths;
+       }
+
+       @Override
+       public Integer getDefaultIconSize() {
+               return defaultIconSize;
+       }
+
+       @Override
+       public InputStream loadPath(String path) throws IOException {
+               URL url = themeBundle.getResource(path);
+               if (url == null)
+                       throw new IllegalArgumentException(
+                                       "Path " + path + " not found in bundle " + themeBundle.getSymbolicName());
+               return url.openStream();
+       }
+
+       private static Bundle findThemeBundle(BundleContext bundleContext, String themeId) {
+               if (themeId == null)
+                       return null;
+               // TODO optimize
+               // TODO deal with multiple versions
+               Bundle themeBundle = null;
+               if (themeId != null) {
+                       for (Bundle bundle : bundleContext.getBundles())
+                               if (themeId.equals(bundle.getSymbolicName())) {
+                                       themeBundle = bundle;
+                                       break;
+                               }
+               }
+               return themeBundle;
+       }
+
+       @Override
+       public int hashCode() {
+               return themeId.hashCode();
+       }
+
+       @Override
+       public String toString() {
+               return "Bundle CMS Theme " + themeId;
+       }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/CmsOsgiUtils.java b/org.argeo.cms/src/org/argeo/cms/osgi/CmsOsgiUtils.java
new file mode 100644 (file)
index 0000000..424d62f
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.cms.osgi;
+
+import java.util.Collection;
+
+import javax.security.auth.Subject;
+
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.CmsSessionId;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public class CmsOsgiUtils {
+
+       /** @return The {@link CmsSession} for this {@link Subject} or null. */
+       public static CmsSession getCmsSession(BundleContext bc, Subject subject) {
+               if (subject.getPrivateCredentials(CmsSessionId.class).isEmpty())
+                       return null;
+               CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next();
+               String uuid = cmsSessionId.getUuid().toString();
+               Collection<ServiceReference<CmsSession>> sr;
+               try {
+                       sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")");
+               } catch (InvalidSyntaxException e) {
+                       throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e);
+               }
+               ServiceReference<CmsSession> cmsSessionRef;
+               if (sr.size() == 1) {
+                       cmsSessionRef = sr.iterator().next();
+                       return bc.getService(cmsSessionRef);
+               } else if (sr.size() == 0) {
+                       return null;
+               } else
+                       throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid);
+       }
+
+       /** Singleton.*/
+       private CmsOsgiUtils() {
+       }
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/DataModelNamespace.java b/org.argeo.cms/src/org/argeo/cms/osgi/DataModelNamespace.java
new file mode 100644 (file)
index 0000000..8e07061
--- /dev/null
@@ -0,0 +1,18 @@
+package org.argeo.cms.osgi;
+
+import org.osgi.resource.Namespace;
+
+/** CMS Data Model capability namespace. */
+public class DataModelNamespace extends Namespace {
+
+       public static final String CMS_DATA_MODEL_NAMESPACE = "cms.datamodel";
+       public static final String NAME = "name";
+       public static final String CND = "cnd";
+       /** If 'true', indicates that no repository should be published */
+       public static final String ABSTRACT = "abstract";
+
+       private DataModelNamespace() {
+               // empty
+       }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/osgi/PublishNamespace.java b/org.argeo.cms/src/org/argeo/cms/osgi/PublishNamespace.java
new file mode 100644 (file)
index 0000000..606d51f
--- /dev/null
@@ -0,0 +1,16 @@
+package org.argeo.cms.osgi;
+
+import org.osgi.resource.Namespace;
+
+/** Namespace defining which resources can be published. Typically use to expose icon of scripts to the web. */
+public class PublishNamespace extends Namespace {
+
+       public static final String CMS_PUBLISH_NAMESPACE = "cms.publish";
+       public static final String PKG = "pkg";
+       public static final String FILE = "file";
+
+       private PublishNamespace() {
+               // empty
+       }
+
+}
index 333fa1aa027f481090b4370e1d61ba8be16dcdf4..67db467ce25a62f19a5aec82821e0e4d41efd729 100644 (file)
@@ -8,8 +8,9 @@ import java.util.function.Supplier;
 import javax.security.auth.Subject;
 import javax.servlet.http.HttpServletRequest;
 
-import org.argeo.cms.auth.CmsSession;
+import org.argeo.api.cms.CmsSession;
 import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.osgi.CmsOsgiUtils;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.service.http.HttpContext;
@@ -59,7 +60,7 @@ public class ServletAuthUtils {
        public static CmsSession getCmsSession(HttpServletRequest req) {
                Subject subject = Subject
                                .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName()));
-               CmsSession cmsSession = CmsSession.getCmsSession(bundleContext, subject);
+               CmsSession cmsSession = CmsOsgiUtils.getCmsSession(bundleContext, subject);
                return cmsSession;
        }
 }