From: Mathieu Baudier Date: Mon, 25 Jan 2021 08:54:42 +0000 (+0100) Subject: Move core projects to a separate directory. X-Git-Tag: argeo-suite-2.1.18~23 X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=commitdiff_plain;h=418ea1efbf3f0d6b706603c6ff1c0fdd17314773 Move core projects to a separate directory. --- diff --git a/core/org.argeo.entity.api/.classpath b/core/org.argeo.entity.api/.classpath new file mode 100644 index 0000000..e801ebf --- /dev/null +++ b/core/org.argeo.entity.api/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.entity.api/.gitignore b/core/org.argeo.entity.api/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.entity.api/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.entity.api/.project b/core/org.argeo.entity.api/.project new file mode 100644 index 0000000..1269cce --- /dev/null +++ b/core/org.argeo.entity.api/.project @@ -0,0 +1,28 @@ + + + org.argeo.entity.api + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/core/org.argeo.entity.api/META-INF/.gitignore b/core/org.argeo.entity.api/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.entity.api/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.entity.api/bnd.bnd b/core/org.argeo.entity.api/bnd.bnd new file mode 100644 index 0000000..ab46172 --- /dev/null +++ b/core/org.argeo.entity.api/bnd.bnd @@ -0,0 +1,5 @@ +Require-Capability:\ +cms.datamodel;filter:="(name=jcrx)" + +Provide-Capability:\ +cms.datamodel; name=entity; cnd=/org/argeo/entity/entity.cnd diff --git a/core/org.argeo.entity.api/build.properties b/core/org.argeo.entity.api/build.properties new file mode 100644 index 0000000..34d2e4d --- /dev/null +++ b/core/org.argeo.entity.api/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/core/org.argeo.entity.api/pom.xml b/core/org.argeo.entity.api/pom.xml new file mode 100644 index 0000000..dc13fe7 --- /dev/null +++ b/core/org.argeo.entity.api/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.entity.api + Entity API + jar + + + + org.argeo.commons + org.argeo.enterprise + ${version.argeo-commons} + + + diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/EntityConstants.java b/core/org.argeo.entity.api/src/org/argeo/entity/EntityConstants.java new file mode 100644 index 0000000..f7a2de8 --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/EntityConstants.java @@ -0,0 +1,8 @@ +package org.argeo.entity; + +/** Constant related to entities, typically used in an OSGi context. */ +public interface EntityConstants { + final static String TYPE = "entity.type"; + final static String DEFAULT_EDITORY_ID = "entity.defaultEditorId"; + +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/EntityDefinition.java b/core/org.argeo.entity.api/src/org/argeo/entity/EntityDefinition.java new file mode 100644 index 0000000..08aff61 --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/EntityDefinition.java @@ -0,0 +1,10 @@ +package org.argeo.entity; + +import javax.jcr.Node; + +/** The definition of an entity, a composite configurable data structure. */ +public interface EntityDefinition { + String getEditorId(Node entity); + + String getType(); +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/EntityNames.java b/core/org.argeo.entity.api/src/org/argeo/entity/EntityNames.java new file mode 100644 index 0000000..ede7447 --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/EntityNames.java @@ -0,0 +1,61 @@ +package org.argeo.entity; + +import org.argeo.naming.LdapAttrs; + +/** Constants used to name entity structures. */ +public interface EntityNames { + @Deprecated + final String FORM_BASE = "form"; + final String SUBMISSIONS_BASE = "submissions"; + @Deprecated + final String TERM = "term"; + final String NAME = "name"; + +// final String ENTITY_DEFINITIONS_PATH = "/entity"; + @Deprecated + final String TYPOLOGIES_PATH = "/" + TERM; + /** Administrative units. */ + final String ADM = "adm"; + + final String ENTITY_TYPE = "entity:type"; + // final String ENTITY_UID = "entity:uid"; + // final String ENTITY_NAME = "entity:name"; + + // GENERIC CONCEPTS + /** The language which is relevant. */ + final String XML_LANG = "xml:lang"; + /** The date which is relevant. */ + final String ENTITY_DATE = "entity:date"; + @Deprecated + final String ENTITY_RELATED_TO = "entity:relatedTo"; + + // DEFAULT FOLDER NAMES + final String MEDIA = "media"; + final String FILES = "files"; + + // LDAP-LIKE ENTITIES + @Deprecated + final String DISPLAY_NAME = LdapAttrs.displayName.property(); + // Persons + @Deprecated + final String GIVEN_NAME = LdapAttrs.givenName.property(); + @Deprecated + final String SURNAME = LdapAttrs.sn.property(); + @Deprecated + final String EMAIL = LdapAttrs.mail.property(); + @Deprecated + final String OU = LdapAttrs.ou.property(); + + // WGS84 + final String GEO_LAT = "geo:lat"; + final String GEO_LONG = "geo:long"; + final String GEO_ALT = "geo:alt"; + + // SVG + final String SVG_WIDTH = "svg:width"; + final String SVG_HEIGHT = "svg:height"; + final String SVG_LENGTH = "svg:length"; + final String SVG_UNIT = "svg:unit"; + final String SVG_DUR = "svg:dur"; + final String SVG_DIRECTION = "svg:direction"; +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/EntityType.java b/core/org.argeo.entity.api/src/org/argeo/entity/EntityType.java new file mode 100644 index 0000000..ecd6330 --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/EntityType.java @@ -0,0 +1,40 @@ +package org.argeo.entity; + +/** Types related to entities. */ +public enum EntityType implements JcrName { + // entity + entity, local, relatedTo, + // typology + typologies, terms, term, + // form + form, formSet, formSubmission, + // graphics + box, + // geography + geopoint, bearing, + // ldap + person, user; + + @Override + public String getPrefix() { + return prefix(); + } + + public static String prefix() { + return "entity"; + } + + public String basePath() { + return '/' + name(); + } + + @Override + public String getNamespace() { + return namespace(); + } + + public static String namespace() { + return "http://www.argeo.org/ns/entity"; + } + +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/EntityTypes.java b/core/org.argeo.entity.api/src/org/argeo/entity/EntityTypes.java new file mode 100644 index 0000000..ef35147 --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/EntityTypes.java @@ -0,0 +1,10 @@ +package org.argeo.entity; + +/** Types related to entities. */ +@Deprecated +public interface EntityTypes { + final static String ENTITY_ENTITY = "entity:entity"; + final static String ENTITY_DEFINITION = "entity:definition"; + + final static String ENTITY_PERSON = "entity:person"; +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/JcrName.java b/core/org.argeo.entity.api/src/org/argeo/entity/JcrName.java new file mode 100644 index 0000000..322c42e --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/JcrName.java @@ -0,0 +1,30 @@ +package org.argeo.entity; + +import java.util.function.Supplier; + +/** Can be applied to {@link Enum}s in order to generate prefixed names. */ +@FunctionalInterface +public interface JcrName extends Supplier { + String name(); + + default String getPrefix() { + return null; + } + + default String getNamespace() { + return null; + } + + @Override + default String get() { + String prefix = getPrefix(); + return prefix != null ? prefix + ":" + name() : name(); + } + + default String withNamespace() { + String namespace = getNamespace(); + if (namespace == null) + throw new UnsupportedOperationException("No namespace is specified for " + getClass()); + return "{" + namespace + "}" + name(); + } +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java b/core/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java new file mode 100644 index 0000000..a2b5951 --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java @@ -0,0 +1,8 @@ +package org.argeo.entity; + +import java.util.List; + +/** Provides optimised access and utilities around terms typologies. */ +public interface TermsManager { + List listAllTerms(String typology); +} diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/entity.cnd b/core/org.argeo.entity.api/src/org/argeo/entity/entity.cnd new file mode 100644 index 0000000..b30657d --- /dev/null +++ b/core/org.argeo.entity.api/src/org/argeo/entity/entity.cnd @@ -0,0 +1,99 @@ +// Standard namespaces + + +// see https://www.w3.org/2003/01/geo/ + + + + + + +[entity:entity] > mix:created, mix:referenceable +mixin + +[entity:local] > entity:entity +mixin +- entity:type (String) m + +[entity:relatedTo] +mixin ++ entity:relatedTo (nt:address) * + +// +// ENTITY DEFINITION +// +//[entity:definition] > entity:composite, mix:created, mix:lastModified, mix:referenceable +//- entity:type (String) multiple + +//[entity:part] + +//[entity:reference] + +//[entity:composite] +//orderable +//+ * (entity:part) +//+ * (entity:reference) +//+ * (entity:composite) + +// +// TYPOLOGY +// +[entity:typologies] ++ * (entity:terms) = entity:terms + +[entity:term] +orderable +- name (NAME) m +- * (*) ++ term (entity:term) = entity:term * + +[entity:terms] > mix:referenceable +orderable ++ term (entity:term) = entity:term * + +// +// FORM +// +[entity:form] +mixin + +[entity:formSubmission] +mixin + +[entity:formSet] > mix:title +mixin + +// +// GRAPHICS +// +[entity:box] +mixin +- svg:width (DOUBLE) +- svg:height (DOUBLE) +- svg:length (DOUBLE) +- svg:unit (STRING) +- svg:dur (DOUBLE) + +// LDAP-LIKE ENTITIES +// A real person +[entity:person] > entity:entity +mixin +- ldap:sn (String) +- ldap:givenName (String) +- ldap:mail (String) * + +[entity:user] > entity:person +mixin +- ldap:distinguishedName (String) +- ldap:uid (String) + +// GEOGRAPHY +[entity:geopoint] +mixin +- geo:long (DOUBLE) +- geo:lat (DOUBLE) +- geo:alt (DOUBLE) + +[entity:bearing] +mixin +- svg:direction (DOUBLE) diff --git a/core/org.argeo.entity.core/.classpath b/core/org.argeo.entity.core/.classpath new file mode 100644 index 0000000..e801ebf --- /dev/null +++ b/core/org.argeo.entity.core/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.entity.core/.gitignore b/core/org.argeo.entity.core/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.entity.core/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.entity.core/.project b/core/org.argeo.entity.core/.project new file mode 100644 index 0000000..1acff84 --- /dev/null +++ b/core/org.argeo.entity.core/.project @@ -0,0 +1,28 @@ + + + org.argeo.entity.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/core/org.argeo.entity.core/META-INF/.gitignore b/core/org.argeo.entity.core/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.entity.core/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.entity.core/bnd.bnd b/core/org.argeo.entity.core/bnd.bnd new file mode 100644 index 0000000..e69de29 diff --git a/core/org.argeo.entity.core/build.properties b/core/org.argeo.entity.core/build.properties new file mode 100644 index 0000000..34d2e4d --- /dev/null +++ b/core/org.argeo.entity.core/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/core/org.argeo.entity.core/pom.xml b/core/org.argeo.entity.core/pom.xml new file mode 100644 index 0000000..af56710 --- /dev/null +++ b/core/org.argeo.entity.core/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.entity.core + Entity Reference Implementation + jar + + + org.argeo.suite + org.argeo.entity.api + 2.1.18-SNAPSHOT + + + + + org.argeo.commons + org.argeo.cms + ${version.argeo-commons} + + + diff --git a/core/org.argeo.entity.core/src/org/argeo/entity/core/JcrEntityDefinition.java b/core/org.argeo.entity.core/src/org/argeo/entity/core/JcrEntityDefinition.java new file mode 100644 index 0000000..7fd26d1 --- /dev/null +++ b/core/org.argeo.entity.core/src/org/argeo/entity/core/JcrEntityDefinition.java @@ -0,0 +1,73 @@ +package org.argeo.entity.core; + +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.api.NodeUtils; +import org.argeo.entity.EntityConstants; +import org.argeo.entity.EntityDefinition; +import org.argeo.jcr.Jcr; +import org.osgi.framework.BundleContext; + +/** An entity definition based on a JCR data structure. */ +public class JcrEntityDefinition implements EntityDefinition { + private Repository repository; + + private String type; + private String defaultEditoryId; + + public void init(BundleContext bundleContext, Map properties) throws RepositoryException { + Session adminSession = NodeUtils.openDataAdminSession(repository, null); + try { + type = properties.get(EntityConstants.TYPE); + if (type == null) + throw new IllegalArgumentException("Entity type property " + EntityConstants.TYPE + " must be set."); + defaultEditoryId = properties.get(EntityConstants.DEFAULT_EDITORY_ID); +// String definitionPath = EntityNames.ENTITY_DEFINITIONS_PATH + '/' + type; +// if (!adminSession.itemExists(definitionPath)) { +// Node entityDefinition = JcrUtils.mkdirs(adminSession, definitionPath, EntityTypes.ENTITY_DEFINITION); +//// entityDefinition.addMixin(EntityTypes.ENTITY_DEFINITION); +// adminSession.save(); +// } + initJcr(adminSession); + } finally { + Jcr.logout(adminSession); + } + } + + /** To be overridden in order to perform additional initialisations. */ + protected void initJcr(Session adminSession) throws RepositoryException { + + } + + public void destroy(BundleContext bundleContext, Map properties) throws RepositoryException { + + } + + @Override + public String getEditorId(Node entity) { + return defaultEditoryId; + } + + @Override + public String getType() { + return type; + } + + protected Repository getRepository() { + return repository; + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public String toString() { + return "Entity Definition " + getType(); + } + +} diff --git a/core/org.argeo.entity.ui/.classpath b/core/org.argeo.entity.ui/.classpath new file mode 100644 index 0000000..e801ebf --- /dev/null +++ b/core/org.argeo.entity.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.entity.ui/.gitignore b/core/org.argeo.entity.ui/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.entity.ui/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.entity.ui/.project b/core/org.argeo.entity.ui/.project new file mode 100644 index 0000000..a1f7177 --- /dev/null +++ b/core/org.argeo.entity.ui/.project @@ -0,0 +1,28 @@ + + + org.argeo.entity.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/core/org.argeo.entity.ui/META-INF/.gitignore b/core/org.argeo.entity.ui/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.entity.ui/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.entity.ui/bnd.bnd b/core/org.argeo.entity.ui/bnd.bnd new file mode 100644 index 0000000..e7cd4cb --- /dev/null +++ b/core/org.argeo.entity.ui/bnd.bnd @@ -0,0 +1,3 @@ +Import-Package:\ +org.eclipse.swt,\ +* \ No newline at end of file diff --git a/core/org.argeo.entity.ui/build.properties b/core/org.argeo.entity.ui/build.properties new file mode 100644 index 0000000..34d2e4d --- /dev/null +++ b/core/org.argeo.entity.ui/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/core/org.argeo.entity.ui/pom.xml b/core/org.argeo.entity.ui/pom.xml new file mode 100644 index 0000000..be62b14 --- /dev/null +++ b/core/org.argeo.entity.ui/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.entity.ui + Entity UI + jar + + + org.argeo.suite + org.argeo.entity.core + 2.1.18-SNAPSHOT + + + + + org.argeo.commons + org.argeo.cms.ui + ${version.argeo-commons} + + + + + org.argeo.commons + org.argeo.eclipse.ui.rap + 2.1.91-SNAPSHOT + provided + + + + + org.argeo.tp + argeo-tp-rap-e4 + ${version.argeo-tp} + pom + provided + + + diff --git a/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java b/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java new file mode 100644 index 0000000..a7f240f --- /dev/null +++ b/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java @@ -0,0 +1,109 @@ +package org.argeo.entity.ui.forms; + +import javax.jcr.Item; + +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.util.CmsIcon; +import org.argeo.cms.ui.viewers.EditablePart; +import org.argeo.cms.ui.widgets.ContextOverlay; +import org.argeo.cms.ui.widgets.StyledControl; +import org.argeo.entity.TermsManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.ToolItem; + +/** Common logic between single and mutliple terms editable part. */ +public abstract class AbstractTermsPart extends StyledControl implements EditablePart { + private static final long serialVersionUID = -5497097995341927710L; + protected final TermsManager termsManager; + protected final String typology; + + protected final boolean editable; + + private CmsIcon deleteIcon; + private CmsIcon addIcon; + private CmsIcon cancelIcon; + + private Color highlightColor; + private Composite highlight; + + protected final CmsTheme theme; + + public AbstractTermsPart(Composite parent, int style, Item item, TermsManager termsManager, + String typology) { + super(parent, style, item); + this.termsManager = termsManager; + this.typology = typology; + this.theme = CmsTheme.getCmsTheme(parent); + editable = !(SWT.READ_ONLY == (style & SWT.READ_ONLY)); + highlightColor = parent.getDisplay().getSystemColor(SWT.COLOR_GRAY); + } + + protected void createHighlight(Composite block) { + highlight = new Composite(block, SWT.NONE); + highlight.setBackground(highlightColor); + GridData highlightGd = new GridData(SWT.FILL, SWT.FILL, false, false); + highlightGd.widthHint = 5; + highlightGd.heightHint = 3; + highlight.setLayoutData(highlightGd); + + } + + protected String getTermLabel(String name) { + return name; + } + + protected abstract void refresh(ContextOverlay contextArea, String filter, Text txt); + + protected boolean isTermSelectable(String term) { + return true; + } + + protected void processTermListLabel(String term, Label label) { + + } + + // + // STYLING + // + public void setDeleteIcon(CmsIcon deleteIcon) { + this.deleteIcon = deleteIcon; + } + + public void setAddIcon(CmsIcon addIcon) { + this.addIcon = addIcon; + } + + public void setCancelIcon(CmsIcon cancelIcon) { + this.cancelIcon = cancelIcon; + } + + protected TermsManager getTermsManager() { + return termsManager; + } + + protected void styleDelete(ToolItem deleteItem) { + if (deleteIcon != null) + deleteItem.setImage(deleteIcon.getSmallIcon(theme)); + else + deleteItem.setText("-"); + } + + protected void styleCancel(ToolItem cancelItem) { + if (cancelIcon != null) + cancelItem.setImage(cancelIcon.getSmallIcon(theme)); + else + cancelItem.setText("X"); + } + + protected void styleAdd(ToolItem addItem) { + if (addIcon != null) + addItem.setImage(addIcon.getSmallIcon(theme)); + else + addItem.setText("+"); + } +} diff --git a/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java b/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java new file mode 100644 index 0000000..1a12e90 --- /dev/null +++ b/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java @@ -0,0 +1,173 @@ +package org.argeo.entity.ui.forms; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Item; + +import org.argeo.cms.ui.forms.FormStyle; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.ui.viewers.EditablePart; +import org.argeo.cms.ui.widgets.ContextOverlay; +import org.argeo.eclipse.ui.MouseDoubleClick; +import org.argeo.eclipse.ui.MouseDown; +import org.argeo.eclipse.ui.Selected; +import org.argeo.entity.TermsManager; +import org.argeo.jcr.Jcr; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** {@link EditablePart} for multiple terms. */ +public class MultiTermsPart extends AbstractTermsPart { + private static final long serialVersionUID = -4961135649177920808L; + + public MultiTermsPart(Composite parent, int style, Item item, TermsManager termsManager, String typology) { + super(parent, style, item, termsManager, typology); + } + + @Override + protected Control createControl(Composite box, String style) { + Composite placeholder = new Composite(box, SWT.NONE); + RowLayout rl = new RowLayout(SWT.HORIZONTAL | SWT.WRAP); + placeholder.setLayout(rl); + List currentValue = Jcr.getMultiple(getNode(), typology); + if (currentValue != null && !currentValue.isEmpty()) + for (String value : currentValue) { + Composite block = new Composite(placeholder, SWT.NONE); + block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); + Label lbl = new Label(block, SWT.SINGLE); + String display = getTermLabel(value); + lbl.setText(display); + CmsUiUtils.style(lbl, style == null ? FormStyle.propertyText.style() : style); + if (editable) + lbl.addMouseListener((MouseDoubleClick) (e) -> { + startEditing(); + }); + if (isEditing()) { + ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); + ToolItem deleteItem = new ToolItem(toolBar, SWT.FLAT); + styleDelete(deleteItem); + deleteItem.addSelectionListener((Selected) (e) -> { + // we retrieve them again here because they may have changed + List curr = Jcr.getMultiple(getNode(), typology); + List newValue = new ArrayList<>(); + for (String v : curr) { + if (!v.equals(value)) + newValue.add(v); + } + Jcr.set(getNode(), typology, newValue); + Jcr.save(getNode()); + block.dispose(); + layout(true, true); + }); + + } + } + else {// empty + if (editable && !isEditing()) { + ToolBar toolBar = new ToolBar(placeholder, SWT.HORIZONTAL); + ToolItem addItem = new ToolItem(toolBar, SWT.FLAT); + styleAdd(addItem); + addItem.addSelectionListener((Selected) (e) -> { + startEditing(); + }); + } + } + + if (isEditing()) { + Composite block = new Composite(placeholder, SWT.NONE); + block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); + + createHighlight(block); + + Text txt = new Text(block, SWT.SINGLE | SWT.BORDER); + txt.setLayoutData(CmsUiUtils.fillWidth()); +// txt.setMessage("[new]"); + + CmsUiUtils.style(txt, style == null ? FormStyle.propertyText.style() : style); + + ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); + ToolItem cancelItem = new ToolItem(toolBar, SWT.FLAT); + styleCancel(cancelItem); + cancelItem.addSelectionListener((Selected) (e) -> { + stopEditing(); + }); + + ContextOverlay contextOverlay = new ContextOverlay(txt, SWT.NONE) { + private static final long serialVersionUID = -7980078594405384874L; + + @Override + protected void onHide() { + stopEditing(); + } + }; + contextOverlay.setLayout(new GridLayout()); + // filter + txt.addModifyListener((e) -> { + String filter = txt.getText().toLowerCase(); + if ("".equals(filter.trim())) + filter = null; + refresh(contextOverlay, filter, txt); + }); + txt.addFocusListener(new FocusListener() { + private static final long serialVersionUID = -6024501573409619949L; + + @Override + public void focusLost(FocusEvent event) { +// if (!contextOverlay.isDisposed() && contextOverlay.isShellVisible()) +// getDisplay().asyncExec(() -> stopEditing()); + } + + @Override + public void focusGained(FocusEvent event) { + // txt.setText(""); + if (!contextOverlay.isDisposed() && !contextOverlay.isShellVisible()) + refresh(contextOverlay, null, txt); + } + }); + layout(new Control[] { txt }); + // getDisplay().asyncExec(() -> txt.setFocus()); + } + return placeholder; + } + + @Override + protected void refresh(ContextOverlay contextArea, String filter, Text txt) { + CmsUiUtils.clear(contextArea); + List terms = termsManager.listAllTerms(typology); + List currentValue = Jcr.getMultiple(getNode(), typology); + terms: for (String term : terms) { + if (currentValue != null && currentValue.contains(term)) + continue terms; + String display = getTermLabel(term); + if (filter != null && !display.toLowerCase().contains(filter)) + continue terms; + Label termL = new Label(contextArea, SWT.WRAP); + termL.setText(display); + processTermListLabel(term, termL); + if (isTermSelectable(term)) + termL.addMouseListener((MouseDown) (e) -> { + List newValue = new ArrayList<>(); + List curr = Jcr.getMultiple(getNode(), typology); + if (currentValue != null) + newValue.addAll(curr); + newValue.add(term); + Jcr.set(getNode(), typology, newValue); + Jcr.save(getNode()); + contextArea.hide(); + stopEditing(); + }); + } + contextArea.show(); + } + +} diff --git a/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java b/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java new file mode 100644 index 0000000..e9fad04 --- /dev/null +++ b/core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java @@ -0,0 +1,143 @@ +package org.argeo.entity.ui.forms; + +import java.util.List; + +import javax.jcr.Item; + +import org.argeo.cms.ui.forms.FormStyle; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.ui.viewers.EditablePart; +import org.argeo.cms.ui.widgets.ContextOverlay; +import org.argeo.eclipse.ui.MouseDoubleClick; +import org.argeo.eclipse.ui.MouseDown; +import org.argeo.eclipse.ui.Selected; +import org.argeo.entity.TermsManager; +import org.argeo.jcr.Jcr; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** {@link EditablePart} for terms. */ +public class SingleTermPart extends AbstractTermsPart { + private static final long serialVersionUID = -4961135649177920808L; + + public SingleTermPart(Composite parent, int style, Item item, TermsManager termsManager, String typology) { + super(parent, style, item, termsManager, typology); + } + + @Override + protected Control createControl(Composite box, String style) { + if (isEditing()) { + Composite block = new Composite(box, SWT.NONE); + block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); + + createHighlight(block); + + Text txt = new Text(block, SWT.SINGLE | SWT.BORDER); + CmsUiUtils.style(txt, style == null ? FormStyle.propertyText.style() : style); + + ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); + ToolItem deleteItem = new ToolItem(toolBar, SWT.PUSH); + styleDelete(deleteItem); + deleteItem.addSelectionListener((Selected) (e) -> { + Jcr.set(getNode(), typology, null); + Jcr.save(getNode()); + stopEditing(); + }); + ToolItem cancelItem = new ToolItem(toolBar, SWT.PUSH); + styleCancel(cancelItem); + cancelItem.addSelectionListener((Selected) (e) -> { + stopEditing(); + }); + + ContextOverlay contextOverlay = new ContextOverlay(txt, SWT.NONE) { + private static final long serialVersionUID = -7980078594405384874L; + + @Override + protected void onHide() { + stopEditing(); + } + }; + contextOverlay.setLayout(new GridLayout()); + // filter + txt.addModifyListener((e) -> { + String filter = txt.getText().toLowerCase(); + if ("".equals(filter.trim())) + filter = null; + refresh(contextOverlay, filter, txt); + }); + txt.addFocusListener(new FocusListener() { + private static final long serialVersionUID = -6024501573409619949L; + + @Override + public void focusLost(FocusEvent event) { +// if (!contextOverlay.isDisposed() && contextOverlay.isShellVisible()) +// getDisplay().asyncExec(() -> stopEditing()); + } + + @Override + public void focusGained(FocusEvent event) { + // txt.setText(""); + if (!contextOverlay.isDisposed() && !contextOverlay.isShellVisible()) + refresh(contextOverlay, null, txt); + } + }); + layout(new Control[] { block }); + getDisplay().asyncExec(() -> txt.setFocus()); + return block; + } else { + Composite block = new Composite(box, SWT.NONE); + block.setLayout(CmsUiUtils.noSpaceGridLayout(2)); + String currentValue = Jcr.get(getNode(), typology); + if (currentValue != null) { + Label lbl = new Label(block, SWT.SINGLE); + String display = getTermLabel(currentValue); + lbl.setText(display); + CmsUiUtils.style(lbl, style == null ? FormStyle.propertyText.style() : style); + + lbl.addMouseListener((MouseDoubleClick) (e) -> { + startEditing(); + }); + } else { + ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); + ToolItem addItem = new ToolItem(toolBar, SWT.FLAT); + styleAdd(addItem); + addItem.addSelectionListener((Selected) (e) -> { + startEditing(); + }); + } + return block; + } + } + + @Override + protected void refresh(ContextOverlay contextArea, String filter, Text txt) { + CmsUiUtils.clear(contextArea); + List terms = termsManager.listAllTerms(typology); + terms: for (String term : terms) { + String display = getTermLabel(term); + if (filter != null && !display.toLowerCase().contains(filter)) + continue terms; + Label termL = new Label(contextArea, SWT.WRAP); + termL.setText(display); + processTermListLabel(term, termL); + if (isTermSelectable(term)) + termL.addMouseListener((MouseDown) (e) -> { + Jcr.set(getNode(), typology, term); + Jcr.save(getNode()); + contextArea.hide(); + stopEditing(); + }); + } + contextArea.show(); + // txt.setFocus(); + } + +} diff --git a/core/org.argeo.suite.core/.classpath b/core/org.argeo.suite.core/.classpath new file mode 100644 index 0000000..e801ebf --- /dev/null +++ b/core/org.argeo.suite.core/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.suite.core/.gitignore b/core/org.argeo.suite.core/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.suite.core/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.suite.core/.project b/core/org.argeo.suite.core/.project new file mode 100644 index 0000000..ab084af --- /dev/null +++ b/core/org.argeo.suite.core/.project @@ -0,0 +1,33 @@ + + + org.argeo.suite.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/core/org.argeo.suite.core/META-INF/.gitignore b/core/org.argeo.suite.core/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.suite.core/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.suite.core/OSGI-INF/maintenanceService.xml b/core/org.argeo.suite.core/OSGI-INF/maintenanceService.xml new file mode 100644 index 0000000..2d495c8 --- /dev/null +++ b/core/org.argeo.suite.core/OSGI-INF/maintenanceService.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.suite.core/OSGI-INF/termsManager.xml b/core/org.argeo.suite.core/OSGI-INF/termsManager.xml new file mode 100644 index 0000000..3e6d4c6 --- /dev/null +++ b/core/org.argeo.suite.core/OSGI-INF/termsManager.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/core/org.argeo.suite.core/bnd.bnd b/core/org.argeo.suite.core/bnd.bnd new file mode 100644 index 0000000..1b9efff --- /dev/null +++ b/core/org.argeo.suite.core/bnd.bnd @@ -0,0 +1,14 @@ +Bundle-ActivationPolicy: lazy + +Service-Component:\ +OSGI-INF/termsManager.xml,\ +OSGI-INF/maintenanceService.xml + +Import-Package:\ +javax.transaction,\ +org.osgi.service.useradmin,\ +javax.jcr.nodetype,\ +javax.jcr.security,\ +org.argeo.api,\ +org.argeo.entity,\ +* \ No newline at end of file diff --git a/core/org.argeo.suite.core/build.properties b/core/org.argeo.suite.core/build.properties new file mode 100644 index 0000000..6210e84 --- /dev/null +++ b/core/org.argeo.suite.core/build.properties @@ -0,0 +1,5 @@ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/ +source.. = src/ diff --git a/core/org.argeo.suite.core/pom.xml b/core/org.argeo.suite.core/pom.xml new file mode 100644 index 0000000..11bc02b --- /dev/null +++ b/core/org.argeo.suite.core/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.suite.core + Suite Core + jar + + + org.argeo.suite + org.argeo.entity.core + 2.1.18-SNAPSHOT + + + + + org.argeo.commons + org.argeo.cms + ${version.argeo-commons} + + + org.argeo.commons + org.argeo.maintenance + ${version.argeo-commons} + + + diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/RankedObject.java b/core/org.argeo.suite.core/src/org/argeo/suite/RankedObject.java new file mode 100644 index 0000000..bfba46e --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/RankedObject.java @@ -0,0 +1,98 @@ +package org.argeo.suite; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A container for an object whose relevance can be ranked. Typically used in an + * OSGi context with the service.ranking property. + */ +public class RankedObject { + private final static Log log = LogFactory.getLog(RankedObject.class); + + private final static String SERVICE_RANKING = "service.ranking"; +// private final static String SERVICE_ID = "service.id"; + + private T object; + private Map properties; + private final Long rank; + + public RankedObject(T object, Map properties) { + this(object, properties, extractRanking(properties)); + } + + public RankedObject(T object, Map properties, Long rank) { + super(); + this.object = object; + this.properties = properties; + this.rank = rank; + } + + private static Long extractRanking(Map properties) { + if (properties == null) + return 0l; + if (properties.containsKey(SERVICE_RANKING)) + return Long.valueOf(properties.get(SERVICE_RANKING).toString()); +// else if (properties.containsKey(SERVICE_ID)) +// return (Long) properties.get(SERVICE_ID); + else + return 0l; + } + + public T get() { + return object; + } + + public Map getProperties() { + return properties; + } + + public Long getRank() { + return rank; + } + + @Override + public int hashCode() { + return object.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof RankedObject)) + return false; + RankedObject other = (RankedObject) obj; + return rank.equals(other.rank) && object.equals(other.object); + } + + @Override + public String toString() { + return object.getClass().getName() + " with rank " + rank; + } + + public static RankedObject putIfHigherRank(Map> map, K key, T object, + Map properties) { + RankedObject rankedObject = new RankedObject<>(object, properties); + if (!map.containsKey(key)) { + map.put(key, rankedObject); + if (log.isTraceEnabled()) + log.trace( + "Added " + key + " as " + object.getClass().getName() + " with rank " + rankedObject.getRank()); + return rankedObject; + } else { + RankedObject current = map.get(key); + if (current.getRank() <= rankedObject.getRank()) { + map.put(key, rankedObject); + if (log.isTraceEnabled()) + log.trace("Replaced " + key + " by " + object.getClass().getName() + " with rank " + + rankedObject.getRank()); + return rankedObject; + } else { + return current; + } + } + + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/RankingKey.java b/core/org.argeo.suite.core/src/org/argeo/suite/RankingKey.java new file mode 100644 index 0000000..e099195 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/RankingKey.java @@ -0,0 +1,160 @@ +package org.argeo.suite; + +import java.util.Map; + +/** + * Key used to classify and filter available components (typically provided by + * OSGi services). + */ +@Deprecated +public class RankingKey implements Comparable { + public final static String SERVICE_PID = "service.pid"; + public final static String SERVICE_ID = "service.id"; + public final static String SERVICE_RANKING = "service.ranking"; + public final static String DATA_TYPE = "data.type"; + + private String pid; + private Integer ranking = 0; + private Long id = 0l; + private String dataType; + private String dataPath; + + public RankingKey(String pid, Integer ranking, Long id, String dataType, String dataPath) { + super(); + this.pid = pid; + this.ranking = ranking; + this.id = id; + this.dataType = dataType; + this.dataPath = dataPath; + } + + public RankingKey(Map properties) { + this.pid = properties.containsKey(SERVICE_PID) ? properties.get(SERVICE_PID).toString() : null; + this.ranking = properties.containsKey(SERVICE_RANKING) + ? Integer.parseInt(properties.get(SERVICE_RANKING).toString()) + : 0; + this.id = properties.containsKey(SERVICE_ID) ? (Long) properties.get(SERVICE_ID) : null; + + // Argeo specific + this.dataType = properties.containsKey(DATA_TYPE) ? properties.get(DATA_TYPE).toString() : null; + } + + @Override + public int hashCode() { + Integer result = 0; + if (pid != null) + result = +pid.hashCode(); + if (ranking != null) + result = +ranking; + if (dataType != null) + result = +dataType.hashCode(); + return result; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return new RankingKey(pid, ranking, id, dataType, dataPath); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(""); + if (pid != null) + sb.append(pid); + if (ranking != null && ranking != 0) + sb.append(' ').append(ranking); + if (dataType != null) + sb.append(' ').append(dataType); + return sb.toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof RankingKey)) + return false; + RankingKey other = (RankingKey) obj; + return equalsOrBothNull(pid, other.pid) && equalsOrBothNull(ranking, other.ranking) + && equalsOrBothNull(id, other.id) && equalsOrBothNull(dataType, other.dataType) + && equalsOrBothNull(dataPath, other.dataPath); + } + + @Override + public int compareTo(RankingKey o) { + if (pid != null && o.pid != null) { + if (pid.equals(o.pid)) { + if (ranking.equals(o.ranking)) + if (id != null && o.id != null) + return id.compareTo(o.id); + else + return 0; + else + return ranking.compareTo(o.ranking); + } else { + return pid.compareTo(o.pid); + } + + } else { + if (dataType != null && o.dataType != null) { + if (dataType.equals(o.dataType)) { + // TODO factorise + if (ranking.equals(o.ranking)) + if (id != null && o.id != null) + return id.compareTo(o.id); + else + return 0; + else + return ranking.compareTo(o.ranking); + } else { + return dataPath.compareTo(o.dataType); + } + } + } + return -1; + } + + public String getPid() { + return pid; + } + + public Integer getRanking() { + return ranking; + } + + public Long getId() { + return id; + } + + public String getDataType() { + return dataType; + } + + public String getDataPath() { + return dataPath; + } + + public static RankingKey minPid(String pid) { + return new RankingKey(pid, Integer.MIN_VALUE, null, null, null); + } + + public static RankingKey maxPid(String pid) { + return new RankingKey(pid, Integer.MAX_VALUE, null, null, null); + } + + public static RankingKey minDataType(String dataType) { + return new RankingKey(null, Integer.MIN_VALUE, null, dataType, null); + } + + public static RankingKey maxDataType(String dataType) { + return new RankingKey(null, Integer.MAX_VALUE, null, dataType, null); + } + + private static boolean equalsOrBothNull(Object o1, Object o2) { + if (o1 == null && o2 == null) + return true; + if (o1 == null && o2 != null) + return false; + if (o1 != null && o2 == null) + return false; + return o2.equals(o1); + } +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/SuiteRole.java b/core/org.argeo.suite.core/src/org/argeo/suite/SuiteRole.java new file mode 100644 index 0000000..382f50c --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/SuiteRole.java @@ -0,0 +1,19 @@ +package org.argeo.suite; + +import org.argeo.api.NodeConstants; +import org.argeo.naming.Distinguished; +import org.argeo.naming.LdapAttrs; + +/** Office specific roles used in the code */ +public enum SuiteRole implements Distinguished { + coworker, manager; + + public String getRolePrefix() { + return "org.argeo.suite"; + } + + public String dn() { + return new StringBuilder(LdapAttrs.cn.name()).append("=").append(getRolePrefix()).append(".").append(name()) + .append(",").append(NodeConstants.ROLES_BASEDN).toString(); + } +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java b/core/org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java new file mode 100644 index 0000000..e63b515 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java @@ -0,0 +1,99 @@ +package org.argeo.suite; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; +import javax.jcr.security.Privilege; +import javax.naming.ldap.LdapName; +import javax.security.auth.x500.X500Principal; + +import org.argeo.api.NodeConstants; +import org.argeo.cms.auth.CmsSession; +import org.argeo.entity.EntityType; +import org.argeo.jackrabbit.security.JackrabbitSecurityUtils; +import org.argeo.jcr.JcrException; +import org.argeo.jcr.JcrUtils; +import org.argeo.naming.LdapAttrs; + +/** Utilities around the Argeo Suite APIs. */ +public class SuiteUtils { + + public static String getUserNodePath(LdapName userDn) { + String uid = userDn.getRdn(userDn.size() - 1).getValue().toString(); + return EntityType.user.basePath() + '/' + uid; + } + + public static Node getOrCreateUserNode(Session adminSession, LdapName userDn) { + try { + Node usersBase = adminSession.getNode(EntityType.user.basePath()); + String uid = userDn.getRdn(userDn.size() - 1).getValue().toString(); + Node userNode; + if (!usersBase.hasNode(uid)) { + userNode = usersBase.addNode(uid, NodeType.NT_UNSTRUCTURED); + userNode.addMixin(EntityType.user.get()); + userNode.addMixin(NodeType.MIX_CREATED); + userNode.setProperty(LdapAttrs.distinguishedName.property(), userDn.toString()); + userNode.setProperty(LdapAttrs.uid.property(), uid); + adminSession.save(); + JackrabbitSecurityUtils.denyPrivilege(adminSession, userNode.getPath(), SuiteRole.coworker.dn(), + Privilege.JCR_READ); + JcrUtils.addPrivilege(adminSession, userNode.getPath(), new X500Principal(userDn.toString()).getName(), + Privilege.JCR_READ); + JcrUtils.addPrivilege(adminSession, userNode.getPath(), NodeConstants.ROLE_USER_ADMIN, + Privilege.JCR_ALL); + } else { + userNode = usersBase.getNode(uid); + } + return userNode; + } catch (RepositoryException e) { + throw new JcrException("Cannot create user node for " + userDn, e); + } + } + + public static Node getCmsSessionNode(Session session, CmsSession cmsSession) { + try { + return session.getNode(getUserNodePath(cmsSession.getUserDn()) + '/' + cmsSession.getUuid().toString()); + } catch (RepositoryException e) { + throw new JcrException("Cannot get session dir for " + cmsSession, e); + } + } + + public static Node getOrCreateCmsSessionNode(Session adminSession, CmsSession cmsSession) { + try { + LdapName userDn = cmsSession.getUserDn(); +// String uid = userDn.get(userDn.size() - 1); + Node userNode = getOrCreateUserNode(adminSession, userDn); +// if (!usersBase.hasNode(uid)) { +// userNode = usersBase.addNode(uid, NodeType.NT_UNSTRUCTURED); +// userNode.addMixin(EntityType.user.get()); +// userNode.addMixin(NodeType.MIX_CREATED); +// usersBase.setProperty(LdapAttrs.uid.property(), uid); +// usersBase.setProperty(LdapAttrs.distinguishedName.property(), userDn.toString()); +// adminSession.save(); +// } else { +// userNode = usersBase.getNode(uid); +// } + String cmsSessionUuid = cmsSession.getUuid().toString(); + Node cmsSessionNode; + if (!userNode.hasNode(cmsSessionUuid)) { + cmsSessionNode = userNode.addNode(cmsSessionUuid, NodeType.NT_UNSTRUCTURED); + cmsSessionNode.addMixin(NodeType.MIX_CREATED); + adminSession.save(); + JcrUtils.addPrivilege(adminSession, cmsSessionNode.getPath(), cmsSession.getUserRole(), + Privilege.JCR_ALL); + } else { + cmsSessionNode = userNode.getNode(cmsSessionUuid); + } + return cmsSessionNode; + } catch (RepositoryException e) { + throw new JcrException("Cannot create session dir for " + cmsSession, e); + } + } + + /** Singleton. */ + private SuiteUtils() { + + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java b/core/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java new file mode 100644 index 0000000..b6e997a --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java @@ -0,0 +1,72 @@ +package org.argeo.suite.core; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.ItemExistsException; +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.entity.EntityType; +import org.argeo.jcr.JcrUtils; +import org.argeo.maintenance.AbstractMaintenanceService; + +/** Base for custom initialisations. */ +public abstract class CustomMaintenanceService extends AbstractMaintenanceService { + private final static Log log = LogFactory.getLog(AbstractMaintenanceService.class); + + protected List getTypologies() { + return new ArrayList<>(); + } + + protected String getTypologiesLoadBase() { + return "/sys/terms"; + } + + protected void loadTypologies(Node customBaseNode) throws RepositoryException, IOException { + List typologies = getTypologies(); + if (!typologies.isEmpty()) { + Node termsBase = JcrUtils.getOrAdd(customBaseNode, EntityType.terms.name(), EntityType.typologies.get()); + for (String terms : typologies) { + loadTerms(termsBase, terms); + } + termsBase.getSession().save(); + } + } + + protected void loadTerms(Node termsBase, String name) throws IOException, RepositoryException { + try { + if (termsBase.hasNode(name)) + return; + + String termsLoadPath = getTypologiesLoadBase() + '/' + name + ".xml"; + URL termsUrl = getClass().getClassLoader().getResource(termsLoadPath); + if (termsUrl == null) + throw new IllegalArgumentException("Terms '" + name + "' not found."); + try (InputStream in = termsUrl.openStream()) { + termsBase.getSession().importXML(termsBase.getPath(), in, + ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); + } catch (ItemExistsException e) { + log.warn("Terms " + name + " exists with another UUID, removing it..."); + termsBase.getNode(name).remove(); + try (InputStream in = termsUrl.openStream()) { + termsBase.getSession().importXML(termsBase.getPath(), in, + ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); + } + } + if (log.isDebugEnabled()) + log.debug("Terms '" + name + "' loaded."); + termsBase.getSession().save(); + } catch (RepositoryException | IOException e) { + log.error("Cannot load terms '" + name + "': " + e.getMessage()); + throw e; + } + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java new file mode 100644 index 0000000..b217373 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java @@ -0,0 +1,39 @@ +package org.argeo.suite.core; + +import java.io.IOException; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; +import javax.jcr.security.Privilege; + +import org.argeo.api.NodeConstants; +import org.argeo.entity.EntityType; +import org.argeo.jcr.JcrUtils; +import org.argeo.maintenance.AbstractMaintenanceService; + +/** Initialises an Argeo Suite backend. */ +public class SuiteMaintenanceService extends AbstractMaintenanceService { + + @Override + public boolean prepareJcrTree(Session adminSession) throws RepositoryException, IOException { + boolean modified = false; + Node rootNode = adminSession.getRootNode(); + if (!rootNode.hasNode(EntityType.user.name())) { + rootNode.addNode(EntityType.user.name(), NodeType.NT_UNSTRUCTURED); + modified = true; + } + if (modified) + adminSession.save(); + return modified; + } + + @Override + public void configurePrivileges(Session adminSession) throws RepositoryException { + JcrUtils.addPrivilege(adminSession, EntityType.user.basePath(), NodeConstants.ROLE_USER_ADMIN, + Privilege.JCR_ALL); + //JcrUtils.addPrivilege(adminSession, "/", SuiteRole.coworker.dn(), Privilege.JCR_READ); + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java new file mode 100644 index 0000000..0c03dc5 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java @@ -0,0 +1,55 @@ +package org.argeo.suite.core; + +import java.util.ArrayList; +import java.util.List; + +/** + * A single term. Helper to optimise {@link SuiteTermsManager} implementation. + */ +class SuiteTerm { + private final String name; + private final String relativePath; + private final SuiteTypology typology; + private final String id; + + private final SuiteTerm parentTerm; + private final List subTerms = new ArrayList<>(); + + SuiteTerm(SuiteTypology typology, String relativePath, SuiteTerm parentTerm) { + this.typology = typology; + this.parentTerm = parentTerm; + this.relativePath = relativePath; + int index = relativePath.lastIndexOf('/'); + if (index > 0) { + this.name = relativePath.substring(index); + } else { + this.name = relativePath; + } + id = typology.getName() + '/' + relativePath; + } + + public String getName() { + return name; + } + + public String getRelativePath() { + return relativePath; + } + + SuiteTypology getTypology() { + return typology; + } + + public String getId() { + return id; + } + + List getSubTerms() { + return subTerms; + } + + SuiteTerm getParentTerm() { + return parentTerm; + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java new file mode 100644 index 0000000..1362f94 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java @@ -0,0 +1,96 @@ +package org.argeo.suite.core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.api.NodeConstants; +import org.argeo.api.NodeUtils; +import org.argeo.entity.EntityNames; +import org.argeo.entity.EntityType; +import org.argeo.entity.TermsManager; +import org.argeo.jcr.Jcr; +import org.argeo.jcr.JcrException; + +/** Argeo Suite implementation of terms manager. */ +public class SuiteTermsManager implements TermsManager { + private final Map terms = new HashMap<>(); + private final Map typologies = new HashMap<>(); + + // JCR + private Repository repository; + private Session adminSession; + + public void init() { + adminSession = NodeUtils.openDataAdminSession(repository, NodeConstants.SYS_WORKSPACE); + } + + @Override + public List listAllTerms(String typology) { + List res = new ArrayList<>(); + SuiteTypology t = getTypology(typology); + for (SuiteTerm term : t.getAllTerms()) { + res.add(term.getId()); + } + return res; + } + + SuiteTypology getTypology(String typology) { + SuiteTypology t = typologies.get(typology); + if (t == null) { + Node termsNode = Jcr.getNode(adminSession, "SELECT * FROM [{0}] WHERE NAME()=\"{1}\"", + EntityType.terms.get(), typology); + if (termsNode == null) + throw new IllegalArgumentException("Typology " + typology + " not found."); + t = loadTypology(termsNode); + } + return t; + } + + SuiteTypology loadTypology(Node termsNode) { + try { + SuiteTypology typology = new SuiteTypology(termsNode); + for (Node termNode : Jcr.iterate(termsNode.getNodes())) { + if (termNode.isNodeType(EntityType.term.get())) { + SuiteTerm term = loadTerm(typology, termNode, null); + if (!term.getSubTerms().isEmpty()) + typology.markNotFlat(); + typology.getSubTerms().add(term); + } + } + typologies.put(typology.getName(), typology); + return typology; + } catch (RepositoryException e) { + throw new JcrException("Cannot load typology from " + termsNode, e); + } + } + + SuiteTerm loadTerm(SuiteTypology typology, Node termNode, SuiteTerm parentTerm) throws RepositoryException { + String name = termNode.getProperty(EntityNames.NAME).getString(); + String relativePath = parentTerm == null ? name : parentTerm.getRelativePath() + '/' + name; + SuiteTerm term = new SuiteTerm(typology, relativePath, parentTerm); + terms.put(term.getId(), term); + for (Node subTermNode : Jcr.iterate(termNode.getNodes())) { + if (termNode.isNodeType(EntityType.term.get())) { + SuiteTerm subTerm = loadTerm(typology, subTermNode, term); + term.getSubTerms().add(subTerm); + } + } + return term; + } + + public void destroy() { + Jcr.logout(adminSession); + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java new file mode 100644 index 0000000..e84066c --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java @@ -0,0 +1,64 @@ +package org.argeo.suite.core; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; + +import org.argeo.jcr.Jcr; + +/** A typology. Helper to optimise {@link SuiteTermsManager} implementation. */ +class SuiteTypology { + private final String name; + private final Node node; + private boolean isFlat = true; + + private final List subTerms = new ArrayList<>(); + + public SuiteTypology(Node node) { + this.node = node; + this.name = Jcr.getName(this.node); + } + + public String getName() { + return name; + } + + public Node getNode() { + return node; + } + + void markNotFlat() { + if (isFlat) + isFlat = false; + } + + public boolean isFlat() { + return isFlat; + } + + public List getSubTerms() { + return subTerms; + } + + public List getAllTerms() { + if (isFlat) + return subTerms; + else { + List terms = new ArrayList<>(); + for (SuiteTerm subTerm : subTerms) { + terms.add(subTerm); + collectSubTerms(terms, subTerm); + } + return terms; + } + } + + private void collectSubTerms(List terms, SuiteTerm term) { + for (SuiteTerm subTerm : term.getSubTerms()) { + terms.add(subTerm); + collectSubTerms(terms, subTerm); + } + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/library/DocxExtractor.java b/core/org.argeo.suite.core/src/org/argeo/suite/library/DocxExtractor.java new file mode 100644 index 0000000..53e73f3 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/library/DocxExtractor.java @@ -0,0 +1,355 @@ +package org.argeo.suite.library; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.argeo.util.DigestUtils; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +/** Parses a .docx document, trying its best to extract text and table data. */ +public class DocxExtractor { + final static String T = "t"; + final static String TC = "tc"; + final static String TR = "tr"; + final static String TBL = "tbl"; + final static String P = "p"; + static boolean debug = false; + + final static String PROOF_ERR = "proofErr"; + final static String TYPE = "type"; + final static String SPELL_START = "spellStart"; + final static String SPELL_END = "spellEnd"; + + protected List tables = new ArrayList<>(); + protected List text = new ArrayList<>(); + protected Map media = new TreeMap<>(); + private Set mediaDigests = new HashSet<>(); + + protected void processTextItem(List lines, String str) { + lines.add(str); + } + + protected boolean skipMedia(String digest) { + return false; + } + + class DocxHandler extends DefaultHandler { + + private StringBuilder buffer = new StringBuilder(); + private Tbl currentTbl = null; + + boolean inSpellErr = false; + boolean inParagraph = false; + + @Override + public void startElement(String uri, String name, String qName, Attributes attributes) throws SAXException { + // System.out.println(localName + " " + qName + " " + uri.hashCode()); + if (P.equals(name)) { + if (debug && currentTbl == null) + System.out.println("# START PARA"); + inParagraph = true; + } else if (PROOF_ERR.equals(name)) { + String type = attributes.getValue(uri, TYPE); + if (SPELL_START.equals(type)) + inSpellErr = true; + else if (SPELL_END.equals(type)) + inSpellErr = false; + + } else if (TBL.equals(name)) { + if (currentTbl != null) { + Tbl childTbl = new Tbl(); + childTbl.parentTbl = currentTbl; + currentTbl = childTbl; + // throw new IllegalStateException("Already an active table"); + } else { + currentTbl = new Tbl(); + } + } + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (name.equals(T)) { +// if (inSpellErr) { +// // do not reset the buffer +// return; +// } + + if (currentTbl != null) { + currentTbl.appendText(buffer.toString()); + } else { + String str = buffer.toString(); + // replace NO-BREAK SPACE by regular space. + str = str.replace('\u00A0', ' '); + str = str.strip(); + if (!"".equals(str)) { + processTextItem(text, str); + } + } + } else if (name.equals(P)) { + if (debug && currentTbl == null) + System.out.println("# END PARA"); + if (currentTbl != null) { + currentTbl.currentRow.current.text.append('\n'); + } else { + + } + inParagraph = false; + } else if (name.equals(TC)) { + if (currentTbl != null) + currentTbl.closeColumn(); + } else if (name.equals(TR)) { + if (currentTbl != null) + currentTbl.closeRow(); + } else if (name.equals(TBL)) { + if (currentTbl != null) { + tables.add(currentTbl); + if (currentTbl.parentTbl != null) + currentTbl = currentTbl.parentTbl; + else + currentTbl = null; + } else { + throw new IllegalStateException("Closing a table while none was open."); + } + } + // reset the buffer + buffer.setLength(0); + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + buffer.append(ch, start, length); + } + + } + + public static class Tbl { + Tbl parentTbl = null; + Tr currentRow = new Tr(); + List
rows = new ArrayList<>(); + + void appendText(String str) { + currentRow.current.text.append(str); + } + + void closeColumn() { + currentRow.columns.add(currentRow.current); + currentRow.current = new Tc(); + } + + void closeRow() { + rows.add(currentRow); + currentRow = new Tr(); + } + + public List
getRows() { + return rows; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (Tr tr : rows) { + String txt = tr.toString(); + sb.append(txt).append('\n'); + } + return sb.toString(); + } + } + + public static class Tr { + Tc current = new Tc(); + List columns = new ArrayList<>(); + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (Tc tc : columns) { + sb.append("\"").append(tc.toString()).append("\"").append(','); + } + return sb.toString(); + } + + public List getColumns() { + return columns; + } + + } + + public static class Tc { + StringBuilder text = new StringBuilder(); + + @Override + public String toString() { + return text.toString().trim(); + } + + } + + protected void parse(Reader in) { + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + SAXParser saxParser = spf.newSAXParser(); + XMLReader xmlReader = saxParser.getXMLReader(); + xmlReader.setContentHandler(new DocxHandler()); + xmlReader.parse(new InputSource(in)); + } catch (ParserConfigurationException | SAXException | IOException e) { + throw new RuntimeException("Cannot parse document", e); + } + } + + public List getText() { + return text; + } + + public List getTables() { + return tables; + } + + public Map getMedia() { + return media; + } + + public void load(ZipInputStream zIn) { + try { + ZipEntry entry = null; + while ((entry = zIn.getNextEntry()) != null) { + if ("word/document.xml".equals(entry.getName())) { + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[2048]; + int len = 0; + while ((len = zIn.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + try (Reader reader = new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), + StandardCharsets.UTF_8)) { + parse(reader); + } + } + } else if (entry.getName().startsWith("word/media")) { + String fileName = entry.getName().substring(entry.getName().lastIndexOf('/') + 1); + int dotIndex = fileName.lastIndexOf('.'); + String ext = fileName.substring(dotIndex + 1).toLowerCase(); + // we ignore .jfif + if ("jpeg".equals(ext)) + ext = "jpg"; + fileName = fileName.substring(0, dotIndex) + "." + ext; + switch (ext) { + case "png": + case "jpg": + case "gif": + case "bmp": + case "tiff": + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[2048]; + int len = 0; + while ((len = zIn.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + byte[] bytes = out.toByteArray(); + String digest = DigestUtils.digest(DigestUtils.MD5, bytes); + if (skipMedia(digest)) + break; + if (!mediaDigests.contains(digest)) { + media.put(fileName, bytes); + mediaDigests.add(digest); + } + } + break; + default: + break; + } + } else { + // System.out.println(entry.getName()); + } + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // throw new IllegalArgumentException("No document.xml found"); + + } + +// public static Reader extractDocumentXml(ZipInputStream zIn) throws IOException { +// ZipEntry entry = null; +// while ((entry = zIn.getNextEntry()) != null) { +// if ("word/document.xml".equals(entry.getName())) { +// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { +// byte[] buffer = new byte[2048]; +// int len = 0; +// while ((len = zIn.read(buffer)) > 0) { +// out.write(buffer, 0, len); +// } +// return new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), StandardCharsets.UTF_8); +// } +// } else { +// System.out.println(entry.getName()); +// } +// } +// throw new IllegalArgumentException("No document.xml found"); +// } + +// protected static ZipInputStream openAsZip(String file) throws IOException { +// ZipInputStream zIn; +// Path path = Paths.get(file); +// zIn = new ZipInputStream(Files.newInputStream(path)); +// return zIn; +// } + + public static void main(String[] args) throws IOException { + if (args.length == 0) + throw new IllegalArgumentException("Provide a file path"); + Path p = Paths.get(args[0]); + + DocxExtractor importer = new DocxExtractor(); + try (ZipInputStream zIn = new ZipInputStream(Files.newInputStream(p))) { + importer.load(zIn); + } + // display + System.out.println("## TEXT"); + for (int i = 0; i < importer.text.size(); i++) { + String str = importer.text.get(i); + System.out.println(str); + } + + System.out.println("\n"); + + for (int i = 0; i < importer.tables.size(); i++) { + Tbl tbl = importer.tables.get(i); + System.out.println("## TABLE " + i); + System.out.println(tbl); + } + + System.out.println("## MEDIA"); + for (String fileName : importer.media.keySet()) { + int sizeKb = importer.media.get(fileName).length / 1024; + System.out.println(fileName + " " + sizeKb + " kB"); + } + } + +} diff --git a/core/org.argeo.suite.core/src/org/argeo/suite/util/XPathUtils.java b/core/org.argeo.suite.core/src/org/argeo/suite/util/XPathUtils.java new file mode 100644 index 0000000..66d9aa0 --- /dev/null +++ b/core/org.argeo.suite.core/src/org/argeo/suite/util/XPathUtils.java @@ -0,0 +1,177 @@ +package org.argeo.suite.util; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.util.ISO9075; + +/** Ease XPath generation for JCR requests */ +public class XPathUtils { + private final static Log log = LogFactory.getLog(XPathUtils.class); + + private final static String QUERY_XPATH = "xpath"; + + public static String descendantFrom(String parentPath) { + if (notEmpty(parentPath)) { + if ("/".equals(parentPath)) + parentPath = ""; + // Hardcoded dependency to Jackrabbit. Remove + String result = "/jcr:root" + ISO9075.encodePath(parentPath); + if (log.isTraceEnabled()) { + String result2 = "/jcr:root" + parentPath; + if (!result2.equals(result)) + log.warn("Encoded Path " + result2 + " --> " + result); + } + return result; + } else + return ""; + } + + public static String localAnd(String... conditions) { + StringBuilder builder = new StringBuilder(); + for (String condition : conditions) { + if (notEmpty(condition)) { + builder.append(" ").append(condition).append(" and "); + } + } + if (builder.length() > 3) + return builder.substring(0, builder.length() - 4); + else + return ""; + } + + public static String xPathNot(String condition) { + if (notEmpty(condition)) + return "not(" + condition + ")"; + else + return ""; + } + + public static String getFreeTextConstraint(String filter) throws RepositoryException { + StringBuilder builder = new StringBuilder(); + if (notEmpty(filter)) { + String[] strs = filter.trim().split(" "); + for (String token : strs) { + builder.append("jcr:contains(.,'*" + encodeXPathStringValue(token) + "*') and "); + } + return builder.substring(0, builder.length() - 4); + } + return ""; + } + + public static String getPropertyContains(String propertyName, String filter) throws RepositoryException { + if (notEmpty(filter)) + return "jcr:contains(@" + propertyName + ",'*" + encodeXPathStringValue(filter) + "*')"; + return ""; + } + + private final static DateFormat jcrRefFormatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'+02:00'"); + + /** + * @param propertyName + * @param calendar the reference date + * @param lowerOrGreater "<", ">" TODO validate ">=" + * @return + * @throws RepositoryException + */ + public static String getPropertyDateComparaison(String propertyName, Calendar cal, String lowerOrGreater) + throws RepositoryException { + if (cal != null) { + String jcrDateStr = jcrRefFormatter.format(cal.getTime()); + + // jcrDateStr = "2015-08-03T05:00:03:000Z"; + String result = "@" + propertyName + " " + lowerOrGreater + " xs:dateTime('" + jcrDateStr + "')"; + return result; + } + return ""; + } + + public static String getPropertyEquals(String propertyName, String value) { + if (notEmpty(value)) + return "@" + propertyName + "='" + encodeXPathStringValue(value) + "'"; + return ""; + } + + public static String encodeXPathStringValue(String propertyValue) { + // TODO implement safer mechanism to escape invalid characters + // Also check why we have used this regex in ResourceSerrviceImpl l 474 + // String cleanedKey = key.replaceAll("(?:')", "''"); + String result = propertyValue.replaceAll("'", "''"); + return result; + } + + public static void andAppend(StringBuilder builder, String condition) { + if (notEmpty(condition)) { + builder.append(condition); + builder.append(" and "); + } + } + + public static void appendOrderByProperties(StringBuilder builder, boolean ascending, String... propertyNames) { + if (propertyNames.length > 0) { + builder.append(" order by "); + for (String propName : propertyNames) + builder.append("@").append(propName).append(", "); + builder = builder.delete(builder.length() - 2, builder.length()); + if (ascending) + builder.append(" ascending "); + else + builder.append(" descending "); + } + } + + public static void appendAndPropStringCondition(StringBuilder builder, String propertyName, String filter) + throws RepositoryException { + if (notEmpty(filter)) { + andAppend(builder, getPropertyContains(propertyName, filter)); + } + } + + public static void appendAndNotPropStringCondition(StringBuilder builder, String propertyName, String filter) + throws RepositoryException { + if (notEmpty(filter)) { + String cond = getPropertyContains(propertyName, filter); + builder.append(xPathNot(cond)); + builder.append(" and "); + } + } + + public static Query createQuery(Session session, String queryString) throws RepositoryException { + QueryManager queryManager = session.getWorkspace().getQueryManager(); + // Localise JCR properties for XPATH + queryString = localiseJcrItemNames(queryString); + return queryManager.createQuery(queryString, QUERY_XPATH); + } + + private final static String NS_JCR = "\\{http://www.jcp.org/jcr/1.0\\}"; + private final static String NS_NT = "\\{http://www.jcp.org/jcr/nt/1.0\\}"; + private final static String NS_MIX = "\\{http://www.jcp.org/jcr/mix/1.0\\}"; + + /** + * Replace the generic namespace with the local "jcr:", "nt:", "mix:" values. It + * is a workaround that must be later cleaned + */ + public static String localiseJcrItemNames(String name) { + name = name.replaceAll(NS_JCR, "jcr:"); + name = name.replaceAll(NS_NT, "nt:"); + name = name.replaceAll(NS_MIX, "mix:"); + return name; + } + + private static boolean notEmpty(String stringToTest) { + return !(stringToTest == null || "".equals(stringToTest.trim())); + } + + /** Singleton. */ + private XPathUtils() { + + } +} diff --git a/core/org.argeo.suite.theme.default/.gitignore b/core/org.argeo.suite.theme.default/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.suite.theme.default/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.suite.theme.default/.project b/core/org.argeo.suite.theme.default/.project new file mode 100644 index 0000000..d157155 --- /dev/null +++ b/core/org.argeo.suite.theme.default/.project @@ -0,0 +1,27 @@ + + + org.argeo.suite.theme.default + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/core/org.argeo.suite.theme.default/META-INF/.gitignore b/core/org.argeo.suite.theme.default/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.suite.theme.default/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.suite.theme.default/OSGI-INF/cmsTheme.xml b/core/org.argeo.suite.theme.default/OSGI-INF/cmsTheme.xml new file mode 100644 index 0000000..66b8c44 --- /dev/null +++ b/core/org.argeo.suite.theme.default/OSGI-INF/cmsTheme.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.suite.theme.default/bnd.bnd b/core/org.argeo.suite.theme.default/bnd.bnd new file mode 100644 index 0000000..6c4a97c --- /dev/null +++ b/core/org.argeo.suite.theme.default/bnd.bnd @@ -0,0 +1,6 @@ +Service-Component:\ +OSGI-INF/cmsTheme.xml + +Import-Package:\ +org.argeo.cms.ui.util,\ +* \ No newline at end of file diff --git a/core/org.argeo.suite.theme.default/build.properties b/core/org.argeo.suite.theme.default/build.properties new file mode 100644 index 0000000..9cb37cd --- /dev/null +++ b/core/org.argeo.suite.theme.default/build.properties @@ -0,0 +1,3 @@ +bin.includes = META-INF/,\ + icons/,\ + OSGI-INF/ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/add.png b/core/org.argeo.suite.theme.default/icons/types/16/add.png new file mode 100644 index 0000000..5c06bf0 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/add.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/close.png b/core/org.argeo.suite.theme.default/icons/types/16/close.png new file mode 100644 index 0000000..af85e1a Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/close.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/dashboard.png b/core/org.argeo.suite.theme.default/icons/types/16/dashboard.png new file mode 100644 index 0000000..1235592 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/dashboard.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/delete.png b/core/org.argeo.suite.theme.default/icons/types/16/delete.png new file mode 100644 index 0000000..dd2f428 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/delete.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/document.png b/core/org.argeo.suite.theme.default/icons/types/16/document.png new file mode 100644 index 0000000..b168263 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/document.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/documents.png b/core/org.argeo.suite.theme.default/icons/types/16/documents.png new file mode 100644 index 0000000..56deec5 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/documents.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/folder.png b/core/org.argeo.suite.theme.default/icons/types/16/folder.png new file mode 100644 index 0000000..fefbb40 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/folder.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/inbox.png b/core/org.argeo.suite.theme.default/icons/types/16/inbox.png new file mode 100644 index 0000000..d1aa6af Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/inbox.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/location.png b/core/org.argeo.suite.theme.default/icons/types/16/location.png new file mode 100644 index 0000000..17c7070 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/location.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/logout.png b/core/org.argeo.suite.theme.default/icons/types/16/logout.png new file mode 100644 index 0000000..f685ea9 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/logout.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/map.png b/core/org.argeo.suite.theme.default/icons/types/16/map.png new file mode 100644 index 0000000..99690e6 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/map.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/organisation.png b/core/org.argeo.suite.theme.default/icons/types/16/organisation.png new file mode 100644 index 0000000..2e81a6c Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/organisation.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/people.png b/core/org.argeo.suite.theme.default/icons/types/16/people.png new file mode 100644 index 0000000..925d571 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/people.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/person.png b/core/org.argeo.suite.theme.default/icons/types/16/person.png new file mode 100644 index 0000000..8f518e1 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/person.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/refresh.png b/core/org.argeo.suite.theme.default/icons/types/16/refresh.png new file mode 100644 index 0000000..0d39107 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/refresh.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/save.png b/core/org.argeo.suite.theme.default/icons/types/16/save.png new file mode 100644 index 0000000..1c58ada Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/save.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/search.png b/core/org.argeo.suite.theme.default/icons/types/16/search.png new file mode 100644 index 0000000..d32874b Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/search.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/settings.png b/core/org.argeo.suite.theme.default/icons/types/16/settings.png new file mode 100644 index 0000000..ac2d8c9 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/settings.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/tag.png b/core/org.argeo.suite.theme.default/icons/types/16/tag.png new file mode 100644 index 0000000..cefdbb9 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/tag.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/task.png b/core/org.argeo.suite.theme.default/icons/types/16/task.png new file mode 100644 index 0000000..eeb7e01 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/task.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/16/user.png b/core/org.argeo.suite.theme.default/icons/types/16/user.png new file mode 100644 index 0000000..13a8f76 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/16/user.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/add.png b/core/org.argeo.suite.theme.default/icons/types/32/add.png new file mode 100644 index 0000000..15feb20 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/add.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/close.png b/core/org.argeo.suite.theme.default/icons/types/32/close.png new file mode 100644 index 0000000..d0729a5 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/close.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/dashboard.png b/core/org.argeo.suite.theme.default/icons/types/32/dashboard.png new file mode 100644 index 0000000..4c24f43 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/dashboard.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/delete.png b/core/org.argeo.suite.theme.default/icons/types/32/delete.png new file mode 100644 index 0000000..2ee3d88 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/delete.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/document.png b/core/org.argeo.suite.theme.default/icons/types/32/document.png new file mode 100644 index 0000000..a4653fa Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/document.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/documents.png b/core/org.argeo.suite.theme.default/icons/types/32/documents.png new file mode 100644 index 0000000..29db972 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/documents.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/folder.png b/core/org.argeo.suite.theme.default/icons/types/32/folder.png new file mode 100644 index 0000000..b98fc84 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/folder.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/inbox.png b/core/org.argeo.suite.theme.default/icons/types/32/inbox.png new file mode 100644 index 0000000..7583c99 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/inbox.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/location.png b/core/org.argeo.suite.theme.default/icons/types/32/location.png new file mode 100644 index 0000000..d9207f1 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/location.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/logout.png b/core/org.argeo.suite.theme.default/icons/types/32/logout.png new file mode 100644 index 0000000..2d8024f Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/logout.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/map.png b/core/org.argeo.suite.theme.default/icons/types/32/map.png new file mode 100644 index 0000000..9a82a96 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/map.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/organisation.png b/core/org.argeo.suite.theme.default/icons/types/32/organisation.png new file mode 100644 index 0000000..62890c2 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/organisation.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/people.png b/core/org.argeo.suite.theme.default/icons/types/32/people.png new file mode 100644 index 0000000..5f53288 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/people.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/person.png b/core/org.argeo.suite.theme.default/icons/types/32/person.png new file mode 100644 index 0000000..a6c5f1d Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/person.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/save.png b/core/org.argeo.suite.theme.default/icons/types/32/save.png new file mode 100644 index 0000000..d7597d1 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/save.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/search.png b/core/org.argeo.suite.theme.default/icons/types/32/search.png new file mode 100644 index 0000000..8d89a4a Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/search.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/settings.png b/core/org.argeo.suite.theme.default/icons/types/32/settings.png new file mode 100644 index 0000000..4e3fa20 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/settings.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/tag.png b/core/org.argeo.suite.theme.default/icons/types/32/tag.png new file mode 100644 index 0000000..907e216 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/tag.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/task.png b/core/org.argeo.suite.theme.default/icons/types/32/task.png new file mode 100644 index 0000000..b6bd243 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/task.png differ diff --git a/core/org.argeo.suite.theme.default/icons/types/32/user.png b/core/org.argeo.suite.theme.default/icons/types/32/user.png new file mode 100644 index 0000000..50fd404 Binary files /dev/null and b/core/org.argeo.suite.theme.default/icons/types/32/user.png differ diff --git a/core/org.argeo.suite.theme.default/pom.xml b/core/org.argeo.suite.theme.default/pom.xml new file mode 100644 index 0000000..9c81005 --- /dev/null +++ b/core/org.argeo.suite.theme.default/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.suite.theme.default + Suite Default Theme + jar + + + diff --git a/core/org.argeo.suite.theme.default/rap/work.css b/core/org.argeo.suite.theme.default/rap/work.css new file mode 100644 index 0000000..c0aaeb1 --- /dev/null +++ b/core/org.argeo.suite.theme.default/rap/work.css @@ -0,0 +1,181 @@ +.argeo-suite-header { + color: white; + background-color: #00294b; +} + +.argeo-suite-headerTitle { + font: bold 18px sans-serif; + color: white; + background-color: #00294b; +} + +.argeo-suite-leadPane { + background-color: #eee; +} + +Label.argeo-suite-leadPane { + font: 14px sans-serif; + color: #888; + background-color: #eee; +} + +Button.argeo-suite-leadPane:hover { + cursor:pointer; +} + +.argeo-suite-recentItems { + font: bold 14px sans-serif; + color: white; + background-color: #00294b; + padding: 8px 16px; +} + +.argeo-suite-titleContainer { + background-color: #00294b; + padding: 6px 8px 4px 8px; +} + +.argeo-suite-titleLabel { + font: bold 14px sans-serif; + color: white; + background-color: #00294b; +} + +.argeo-suite-subTitleLabel { + font: italic 14px sans-serif; + color: #777; + padding: 4px 8px; +} + +.argeo-suite-simpleLabel { + font: bold 14px sans-serif; + padding: 0px; +} + +.argeo-suite-simpleText { + font: 14px sans-serif; + padding: 0px; +} + +.argeo-suite-titleCell { + font: bold 14px sans-serif; + background-color: #ddd; +} + +.argeo-suite-inlineButton { + padding: 0px 4px; + font: 12px sans-serif; + border: 1px solid white; + color: white; + background-image: none; + background-color: #00294b; +} + +.argeo-suite-inlineButton:hover { + color: #00294b; + background-color: white; +} + +Composite.argeo-suite-mainTabBody { + background-color: #eee; + border: 1px solid #bbb; +} + +.argeo-suite-mainTab { + background-color: #eee; + border: 1px solid #888; +} + +ToolItem.argeo-suite-mainTab { + border: none; + background-color: #eee; +} + +ToolItem.argeo-suite-mainTab:hover { + background-color: #eee; +} + + +Button.argeo-suite-mainTab { + border: 1px solid #eee; + background-color: #eee; +} + +.argeo-suite-mainTab:hover { + background-color: #eee; +} + +Button.argeo-suite-mainTab:hover { + cursor: pointer; + background-color: #eee; +} + +.argeo-suite-mainTabSelected { + font: bold 14px sans-serif; + color: white; + /*background-color: #00294b;*/ + background-color: #5882b5; + border:1px solid #888; +} + +ToolItem.argeo-suite-mainTabSelected { + border: none; +} + +ToolItem.argeo-suite-mainTabSelected:hover { + background-color: #5882b5; +} + +Button.argeo-suite-mainTabSelected { + border: none; +} + +Sash { + border: 1px solid white; + background-image: none; + background-color: white; +} + +Sash:hover { + border: 1px solid #5882b5; + background-color: #5882b5; +} + +TreeItem{ + background-color:#fff; +} + +Tree-RowOverlay:selected { + color:#fff; + background-color:#5882b5; +} + +TableItem{ + background-color:#fff; +} + +Table-RowOverlay:selected { + color:#fff; + background-color:#5882b5; +} + +.argeo-suite-navigationBar{ + background-color:#ddd; +} + +.argeo-suite-navigationTitle{ + background-color:#ddd; + font:bold 14px sans-serif; +} + +.argeo-suite-navigationButton{ + color:#777; + background-color:#ddd; + font:bold 14px sans-serif; +} + +.argeo-suite-navigationButton:hover{ + cursor:pointer; + color:#ddd; + background-color:#777; +} diff --git a/core/org.argeo.suite.theme.default/swt/app.css b/core/org.argeo.suite.theme.default/swt/app.css new file mode 100644 index 0000000..4ac745d --- /dev/null +++ b/core/org.argeo.suite.theme.default/swt/app.css @@ -0,0 +1,129 @@ +.argeo-suite-header { + color: white; + background-color: #00294b; +} + +.argeo-suite-headerTitle { + font: bold 14px sans-serif; + color: white; + background-color: #00294b; +} + +.argeo-suite-leadPane { + background-color: #eee; +} + +Label.argeo-suite-leadPane { + font: 11px sans-serif; + color: #888; + background-color: #eee; +} + +Button.argeo-suite-leadPane:hover { + cursor: pointer; +} + +.argeo-suite-recentItems { + font: bold 13px sans-serif; + color: white; + background-color: #00294b; + padding: 8px 16px; +} + +.argeo-suite-titleContainer { + background-color: #00294b; +} + +.argeo-suite-titleLabel { + font: bold 13px sans-serif; + margin: 6px 8px 4px 8px; + color: white; + background-color: #00294b; +} + +.argeo-suite-subTitleLabel { + font: italic 14px sans-serif; + color: #777; + margin: 4px 8px; +} + +.argeo-suite-formLine { + padding: 4px 8px 4px 16px; +} + +.argeo-suite-simpleLabel { + font: normal 11px sans-serif; + border: 8px solid #eee; +} + +.argeo-suite-simpleText { + +} + +.argeo-suite-simpleInput { + padding: 4px 8px 4px 8px; +} + +.argeo-suite-titleCell { + font: bold 11px sans-serif; + background-color: #ddd; +} + +.argeo-suite-inlineButton { + padding: 0px 4px; + font: 12px sans-serif; + border: 1px solid white; + color: white; + background-image: none; + background-color: #00294b; +} + +.argeo-suite-inlineButton:hover { + color: #00294b; + background-color: white; +} + +Composite.argeo-suite-mainTabBody { + background-color: #eee; + border: 1px solid #bbb; +} + +.argeo-suite-mainTab { + background-color: #eee; + border: 1px solid #bbb; +} + +ToolItem.argeo-suite-mainTab { + border: none; + background-color: #eee; +} + +Button.argeo-suite-mainTab { + border: none; + background-color: #eee; +} + +.argeo-suite-mainTab:hover { + background-color: #eee; +} + +Button.argeo-suite-mainTab:hover { + cursor: pointer; + background-color: #eee; +} + +.argeo-suite-mainTabSelected { + font: bold 14px sans-serif; + color: white; + /*background-color: #00294b;*/ + background-color: #5882b5; + border: 1px solid #00294b; +} + +ToolItem.argeo-suite-mainTabSelected { + border: none; +} + +Button.argeo-suite-mainTabSelected { + border: none; +} \ No newline at end of file diff --git a/core/org.argeo.suite.ui.rap/.gitignore b/core/org.argeo.suite.ui.rap/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.suite.ui.rap/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.suite.ui.rap/.project b/core/org.argeo.suite.ui.rap/.project new file mode 100644 index 0000000..eff6bb0 --- /dev/null +++ b/core/org.argeo.suite.ui.rap/.project @@ -0,0 +1,27 @@ + + + org.argeo.suite.ui.rap + + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + + diff --git a/core/org.argeo.suite.ui.rap/META-INF/.gitignore b/core/org.argeo.suite.ui.rap/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.suite.ui.rap/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.suite.ui.rap/OSGI-INF/cmsWebApp.xml b/core/org.argeo.suite.ui.rap/OSGI-INF/cmsWebApp.xml new file mode 100644 index 0000000..4dfdcff --- /dev/null +++ b/core/org.argeo.suite.ui.rap/OSGI-INF/cmsWebApp.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.suite.ui.rap/bnd.bnd b/core/org.argeo.suite.ui.rap/bnd.bnd new file mode 100644 index 0000000..35b671b --- /dev/null +++ b/core/org.argeo.suite.ui.rap/bnd.bnd @@ -0,0 +1,6 @@ +Service-Component: OSGI-INF/cmsWebApp.xml + +Import-Package:\ +org.argeo.cms.web,\ +org.eclipse.rap.rwt.application,\ +* diff --git a/core/org.argeo.suite.ui.rap/build.properties b/core/org.argeo.suite.ui.rap/build.properties new file mode 100644 index 0000000..6210e84 --- /dev/null +++ b/core/org.argeo.suite.ui.rap/build.properties @@ -0,0 +1,5 @@ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/ +source.. = src/ diff --git a/core/org.argeo.suite.ui.rap/pom.xml b/core/org.argeo.suite.ui.rap/pom.xml new file mode 100644 index 0000000..4316afa --- /dev/null +++ b/core/org.argeo.suite.ui.rap/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.suite.ui.rap + Suite UI RAP + jar + + + org.argeo.suite + org.argeo.suite.ui + 2.1.18-SNAPSHOT + + + + + org.argeo.tp + argeo-tp-rap-e4 + ${version.argeo-tp} + pom + provided + + + diff --git a/core/org.argeo.suite.ui/.classpath b/core/org.argeo.suite.ui/.classpath new file mode 100644 index 0000000..e801ebf --- /dev/null +++ b/core/org.argeo.suite.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/org.argeo.suite.ui/.gitignore b/core/org.argeo.suite.ui/.gitignore new file mode 100644 index 0000000..09e3bc9 --- /dev/null +++ b/core/org.argeo.suite.ui/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/core/org.argeo.suite.ui/.project b/core/org.argeo.suite.ui/.project new file mode 100644 index 0000000..7146bab --- /dev/null +++ b/core/org.argeo.suite.ui/.project @@ -0,0 +1,33 @@ + + + org.argeo.suite.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/core/org.argeo.suite.ui/META-INF/.gitignore b/core/org.argeo.suite.ui/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/core/org.argeo.suite.ui/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/core/org.argeo.suite.ui/OSGI-INF/cmsApp.xml b/core/org.argeo.suite.ui/OSGI-INF/cmsApp.xml new file mode 100644 index 0000000..e42eeeb --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/cmsApp.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/core/org.argeo.suite.ui/OSGI-INF/dashboard.xml b/core/org.argeo.suite.ui/OSGI-INF/dashboard.xml new file mode 100644 index 0000000..f678b5b --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/dashboard.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/core/org.argeo.suite.ui/OSGI-INF/dashboardLayer.xml b/core/org.argeo.suite.ui/OSGI-INF/dashboardLayer.xml new file mode 100644 index 0000000..b60eafc --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/dashboardLayer.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/core/org.argeo.suite.ui/OSGI-INF/header.xml b/core/org.argeo.suite.ui/OSGI-INF/header.xml new file mode 100644 index 0000000..a8fc66d --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/header.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties b/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties new file mode 100644 index 0000000..3d08155 --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties @@ -0,0 +1,98 @@ +dashboard=dashboard +people=contacts +documents=documents +locations=locations +recentItems=recent items + +appTitle=Argeo Suite + +# +# PEOPLE +# org.argeo.people.ui.PeopleMsg +# +person=Person +organisation=Organisation + +# NewPersonWizard +firstName=First Name +lastName=Last Name +salutation=Salutation +email=Email +personWizardWindowTitle=New person +personWizardPageTitle=Create a contact + +# NewOrgWizard +legalName=Legal name +legalForm=Legal form +vatId=VAT ID +orgWizardWindowTitle=New organisation +orgWizardPageTitle=Create an organisation + + +# ContextAddressComposite +chooseAnOrganisation=Choose an organisation +street=Street +streetComplement=Street complement +zipCode=Zip code +city=City +state=State +country=Country +geopoint=Geopoint + +# FilteredOrderableEntityTable +filterHelp=Type filter criterion separated by a space + +# BankAccountComposite +accountHolder=Account holder +bankName=Bank name +currency=Currency +accountNumber=Account number +bankNumber=Bank number +BIC=BIC +IBAN=IBAN + +# EditJobDialog +position=Role +chosenItem=Chose item +department=Department +isPrimary=Is primary +searchAndChooseEntity=Search and choose a corresponding entity + +# ContactListCTab (e4) +notes=Notes +addAContact=Add a contact +contactValue=Contact value +linkedCompany=Linked company + +# OrgAdminInfoCTab (e4) +paymentAccount=Payment account + +# OrgEditor (e4) +orgDetails=Details +orgActivityLog=Activity log +team=Team +orgAdmin=Admin. + +# PersonEditor (e4) +personDetails=Contact details +personActivityLog=Activity log +personOrgs=Organisations +personSecurity=Security + +# PersonSecurityCTab (e4) +resetPassword=Reset password + +# Generic +label=Label +aCustomLabel=A custom label +description=Description +value=Value +name=Name +primary=Primary +add=Add +save=Save +pickUp=Pick up + +# Tags +confirmNewTag=Tag #{0} is not yet registered. Are you sure you want to create it? +cannotCreateTag=Tag #{0} is not yet registered and you don't have enough rights to create it. diff --git a/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle_de.properties b/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle_de.properties new file mode 100644 index 0000000..0af19c2 --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle_de.properties @@ -0,0 +1,98 @@ +dashboard=dashboard +people=Kontakte +documents=Dokumente +locations=Orte +recentItems=neulich + +appTitle=Argeo Suite + +# +# PEOPLE +# org.argeo.people.ui.PeopleMsg +# +person=Person +organisation=Organisation + +# NewPersonWizard +firstName=Vorname +lastName=Nachname +salutation=Salutation +email=E-Mail +personWizardWindowTitle=Neue Person +personWizardPageTitle=Kontakt erstellen + +# NewOrgWizard +legalName=Name +legalForm=Geschäftsform +vatId=Ust ID +orgWizardWindowTitle=Neue Organisation +orgWizardPageTitle=Organisation erstellen + + +# ContextAddressComposite +chooseAnOrganisation=Organisation wählen +street=Strasse +streetComplement=Strasse Zusatz +zipCode=PLZ +city=Stadt +state=Bundesland +country=Land +geopoint=Geopoint + +# FilteredOrderableEntityTable +filterHelp=Type filter criterion separated by a space + +# BankAccountComposite +accountHolder=Kontoinhaber +bankName=Name der Bank +currency=Währung +accountNumber=Kontonummer +bankNumber=BLZ +BIC=BIC +IBAN=IBAN + +# EditJobDialog +position=Rolle +chosenItem=Auswahl +department=Abteilung +isPrimary=Ist Primär +searchAndChooseEntity=Suche und wähle ein zugehöriges Objekt + +# ContactListCTab (e4) +notes=Bemerkungen +addAContact=Kontakt hinzufügen +contactValue=Kontakt value +linkedCompany=zugehörige Firma + +# OrgAdminInfoCTab (e4) +paymentAccount=Geschäftskonto + +# OrgEditor (e4) +orgDetails=Details +orgActivityLog=Aktivitäten Log +team=Team +orgAdmin=Admin. + +# PersonEditor (e4) +personDetails=Kontakt Daten +personActivityLog=Aktivitäten Log +personOrgs=Organisationen +personSecurity=Sicherheit + +# PersonSecurityCTab (e4) +resetPassword=Passwort zurücksetzen + +# Generic +label=Beschriftung +aCustomLabel=Eine spezifische Beschriftung +description=Beschreibung +value=Wert +name=Name +primary=Haupt- +add=Hinzufügen +save=Speichern +pickUp=Aussuchen + +# Tags +confirmNewTag=Das Hashtag '{0}' existiert noch nicht. WollenSie es hinzufügen? +cannotCreateTag=Das Hashtag '{0}' existiert nicht uns Sie haben nicht die Rechte, um es hinzufügen. diff --git a/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle_fr.properties b/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle_fr.properties new file mode 100644 index 0000000..225e5fd --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/l10n/bundle_fr.properties @@ -0,0 +1,102 @@ +dashboard=dashboard +people=contacts +documents=documents +locations=lieux +recentItems=récent + +appTitle=Argeo Suite + +# +# GENERIC +# + +# +# PEOPLE +# org.argeo.people.ui.PeopleMsg +# +person=Personne +organisation=Organisation + +# NewPersonWizard +firstName=Prénom +lastName=Nom +salutation=Salutation +email=Email +personWizardWindowTitle=Nouvelle personne +personWizardPageTitle=Créer un contact + +# NewOrgWizard +legalName=Nom +legalForm=Forme légale +vatId=ID TVA +orgWizardWindowTitle=Nouvelle organisation +orgWizardPageTitle=Créer une organisation + + +# ContextAddressComposite +chooseAnOrganisation=Choisir une organisation +street=Rue +streetComplement=Complément rue +zipCode=Code postal +city=Ville +state=État +country=Pays +geopoint=Géocoordonnées + +# FilteredOrderableEntityTable +filterHelp=Sasir les critères de filtrage séparés par des espaces + +# BankAccountComposite +accountHolder=Propriétaire du compte +bankName=Nom de la banque +currency=Devise +accountNumber=Numéro de compte +bankNumber=Numéro de banque +BIC=BIC +IBAN=IBAN + +# EditJobDialog +position=Rôle +chosenItem=Choisir une élément +department=Service +isPrimary=Principal +searchAndChooseEntity=Cherhcer et choisir l'entitée correspondante + +# ContactListCTab (e4) +notes=Notes +addAContact=Ajouter un contact +contactValue=Valeur +linkedCompany=Entreprise liée + +# OrgAdminInfoCTab (e4) +paymentAccount=Compte de paiement + +# OrgEditor (e4) +orgDetails=Détails +orgActivityLog=Activités +team=Équipe +orgAdmin=Admin. + +# PersonEditor (e4) +personDetails=Détails du contact +personActivityLog=Activités +personOrgs=Organisations +personSecurity=Accès + +# PersonSecurityCTab (e4) +resetPassword=Force le mot de passe + +# Generic +label=Étiquette +aCustomLabel=Une étiquette spécifique +description=Description +value=Valeur +name=Nom +primary=Principal +add=Ajouter +save=Sauver +pickUp=Choisir + +# Tags +confirmNewTag=Le tag #{0} n'existe pas encore. Voulez-vous le créer? +cannotCreateTag=Le tag #{0} n'existe pas encore et vous n'avez pas les droits pour le créer. diff --git a/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml b/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml new file mode 100644 index 0000000..9d3f2dd --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/leadPane.xml @@ -0,0 +1,12 @@ + + + + + + + + argeo.suite.ui.dashboardLayer +argeo.documents.ui.documentsLayer + + + diff --git a/core/org.argeo.suite.ui/OSGI-INF/loginScreen.xml b/core/org.argeo.suite.ui/OSGI-INF/loginScreen.xml new file mode 100644 index 0000000..0c5377a --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/loginScreen.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/core/org.argeo.suite.ui/OSGI-INF/recentItems.xml b/core/org.argeo.suite.ui/OSGI-INF/recentItems.xml new file mode 100644 index 0000000..8aaee16 --- /dev/null +++ b/core/org.argeo.suite.ui/OSGI-INF/recentItems.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/core/org.argeo.suite.ui/bnd.bnd b/core/org.argeo.suite.ui/bnd.bnd new file mode 100644 index 0000000..b49d736 --- /dev/null +++ b/core/org.argeo.suite.ui/bnd.bnd @@ -0,0 +1,18 @@ +Service-Component:\ +OSGI-INF/cmsApp.xml,\ +OSGI-INF/header.xml,\ +OSGI-INF/leadPane.xml,\ +OSGI-INF/loginScreen.xml,\ +OSGI-INF/recentItems.xml,\ +OSGI-INF/dashboard.xml,\ +OSGI-INF/dashboardLayer.xml + +Import-Package:\ +org.argeo.api,\ +org.eclipse.swt,\ +org.osgi.framework,\ +org.argeo.entity,\ +org.eclipse.core.commands.common,\ +org.eclipse.jface.window,\ +org.eclipse.jface.dialogs,\ +* diff --git a/core/org.argeo.suite.ui/build.properties b/core/org.argeo.suite.ui/build.properties new file mode 100644 index 0000000..d829967 --- /dev/null +++ b/core/org.argeo.suite.ui/build.properties @@ -0,0 +1,10 @@ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + config/,\ + OSGI-INF/loginScreen.xml,\ + OSGI-INF/dashboard.xml,\ + OSGI-INF/recentItems.xml,\ + OSGI-INF/dashboardLayer.xml +source.. = src/ diff --git a/core/org.argeo.suite.ui/config/cmsApp.properties b/core/org.argeo.suite.ui/config/cmsApp.properties new file mode 100644 index 0000000..1dec00e --- /dev/null +++ b/core/org.argeo.suite.ui/config/cmsApp.properties @@ -0,0 +1,3 @@ +service.pid=argeo.suite.ui.app + +event.topics=argeo/suite/* \ No newline at end of file diff --git a/core/org.argeo.suite.ui/config/dashboard.properties b/core/org.argeo.suite.ui/config/dashboard.properties new file mode 100644 index 0000000..1832543 --- /dev/null +++ b/core/org.argeo.suite.ui/config/dashboard.properties @@ -0,0 +1 @@ +service.pid=argeo.suite.ui.dashboard diff --git a/core/org.argeo.suite.ui/config/dashboardLayer.properties b/core/org.argeo.suite.ui/config/dashboardLayer.properties new file mode 100644 index 0000000..79abe4c --- /dev/null +++ b/core/org.argeo.suite.ui/config/dashboardLayer.properties @@ -0,0 +1,4 @@ +service.pid=argeo.suite.ui.dashboardLayer + +title=Dashboard +icon=dashboard \ No newline at end of file diff --git a/core/org.argeo.suite.ui/config/header.properties b/core/org.argeo.suite.ui/config/header.properties new file mode 100644 index 0000000..034d5f5 --- /dev/null +++ b/core/org.argeo.suite.ui/config/header.properties @@ -0,0 +1,4 @@ +service.pid=argeo.suite.ui.header +argeo.suite.ui=true + +argeo.suite.ui.header.title=%appTitle \ No newline at end of file diff --git a/core/org.argeo.suite.ui/config/leadPane.properties b/core/org.argeo.suite.ui/config/leadPane.properties new file mode 100644 index 0000000..0d7b193 --- /dev/null +++ b/core/org.argeo.suite.ui/config/leadPane.properties @@ -0,0 +1 @@ +service.pid=argeo.suite.ui.leadPane diff --git a/core/org.argeo.suite.ui/config/loginScreen.properties b/core/org.argeo.suite.ui/config/loginScreen.properties new file mode 100644 index 0000000..332614d --- /dev/null +++ b/core/org.argeo.suite.ui/config/loginScreen.properties @@ -0,0 +1 @@ +service.pid=argeo.suite.ui.loginScreen diff --git a/core/org.argeo.suite.ui/config/recentItems.properties b/core/org.argeo.suite.ui/config/recentItems.properties new file mode 100644 index 0000000..7321c55 --- /dev/null +++ b/core/org.argeo.suite.ui/config/recentItems.properties @@ -0,0 +1 @@ +service.pid=argeo.suite.ui.recentItems diff --git a/core/org.argeo.suite.ui/pom.xml b/core/org.argeo.suite.ui/pom.xml new file mode 100644 index 0000000..82656e2 --- /dev/null +++ b/core/org.argeo.suite.ui/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + org.argeo.suite + core + 2.1.18-SNAPSHOT + .. + + org.argeo.suite.ui + Suite UI + jar + + + org.argeo.suite + org.argeo.suite.core + 2.1.18-SNAPSHOT + + + org.argeo.suite + org.argeo.entity.ui + 2.1.18-SNAPSHOT + + + + + org.argeo.commons + org.argeo.eclipse.ui + ${version.argeo-commons} + + + org.argeo.commons + org.argeo.eclipse.ui.rap + ${version.argeo-commons} + provided + + + + + org.argeo.tp + argeo-tp-rap-e4 + ${version.argeo-tp} + pom + provided + + + diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java new file mode 100644 index 0000000..8c75f22 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java @@ -0,0 +1,182 @@ +package org.argeo.suite.ui; + +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.dialogs.CmsWizardDialog; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.Selected; +import org.argeo.naming.LdapAttrs; +import org.argeo.suite.SuiteRole; +import org.argeo.suite.ui.dialogs.NewUserWizard; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.osgi.service.useradmin.User; + +/** Entry to the admin area. */ +public class AdminEntryArea implements CmsUiProvider { + + private CmsUserManager cmsUserManager; + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + CmsTheme theme = CmsTheme.getCmsTheme(parent); + parent.setLayout(new GridLayout()); + TableViewer usersViewer = new TableViewer(parent); + usersViewer.setContentProvider(new UsersContentProvider()); + + TableViewerColumn idCol = new TableViewerColumn(usersViewer, SWT.NONE); + idCol.getColumn().setWidth(70); + idCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.uid.name()); + } + }); + + TableViewerColumn givenNameCol = new TableViewerColumn(usersViewer, SWT.NONE); + givenNameCol.getColumn().setWidth(150); + givenNameCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.givenName.name()); + } + }); + + TableViewerColumn snCol = new TableViewerColumn(usersViewer, SWT.NONE); + snCol.getColumn().setWidth(150); + snCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.sn.name()); + } + }); + + TableViewerColumn mailCol = new TableViewerColumn(usersViewer, SWT.NONE); + mailCol.getColumn().setWidth(400); + mailCol.setLabelProvider(new ColumnLabelProvider() { + + @Override + public String getText(Object element) { + + return getUserProperty(element, LdapAttrs.mail.name()); + } + }); + + Composite bottom = new Composite(parent, SWT.NONE); + bottom.setLayoutData(CmsUiUtils.fillWidth()); + bottom.setLayout(CmsUiUtils.noSpaceGridLayout()); + ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); + bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); + ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); + deleteItem.setEnabled(false); +// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); + deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); + ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); + addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); + usersViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + User user = (User) usersViewer.getStructuredSelection().getFirstElement(); + if (user != null) { +// Node userNode = getOrCreateUserNode(user, context); + CmsView.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), + SuiteEvent.eventProperties(user)); + } + + } + }); + usersViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + User user = (User) usersViewer.getStructuredSelection().getFirstElement(); + if (user != null) { +// Node userNode = getOrCreateUserNode(user, context); + CmsView.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), + SuiteEvent.eventProperties(user)); + deleteItem.setEnabled(true); + } else { + deleteItem.setEnabled(false); + } + } + }); + + addItem.addSelectionListener((Selected) (e) -> { + // SuiteUtils.getOrCreateUserNode(adminSession, userDn); + Wizard wizard = new NewUserWizard(null); + CmsWizardDialog dialog = new CmsWizardDialog(parent.getShell(), wizard); + // WizardDialog dialog = new WizardDialog(shell, wizard); + if (dialog.open() == Window.OK) { + // TODO create + } + }); + + usersViewer.getTable().setLayoutData(CmsUiUtils.fillAll()); + usersViewer.setInput(cmsUserManager); + + return usersViewer.getTable(); + } + +// private Node getOrCreateUserNode(User user, Node context) { +// return JcrUtils.mkdirs(Jcr.getSession(context), +// "/" + EntityType.user.name() + "/" + getUserProperty(user, LdapAttrs.uid.name()), +// EntityType.user.get()); +// } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; + } + + class UsersContentProvider implements IStructuredContentProvider { + + @Override + public Object[] getElements(Object inputElement) { + CmsUserManager cum = (CmsUserManager) inputElement; + Set users = cum.listUsersInGroup(SuiteRole.coworker.dn(), null); + return users.toArray(); + } + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultDashboard.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultDashboard.java new file mode 100644 index 0000000..9835b67 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultDashboard.java @@ -0,0 +1,31 @@ +package org.argeo.suite.ui; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +/** Provides a dashboard. */ +public class DefaultDashboard implements CmsUiProvider { + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + parent.setLayout(new GridLayout()); + CmsView cmsView = CmsView.getCmsView(parent); + if (cmsView.isAnonymous()) + throw new IllegalStateException("No user is not logged in"); + + Label lbl = new Label(parent, SWT.NONE); + lbl.setText("Welcome " + CurrentUser.getDisplayName() + "!"); + + return lbl; + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java new file mode 100644 index 0000000..7b8bb3e --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java @@ -0,0 +1,144 @@ +package org.argeo.suite.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.ui.widgets.TabbedArea; +import org.argeo.util.LangUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** An app layer based on an entry area and an editor area. */ +public class DefaultEditionLayer implements SuiteLayer { + private CmsUiProvider entryArea; + private CmsUiProvider workArea; + private List weights = new ArrayList<>(); + private boolean startMaximized = false; + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + if (entryArea != null) { + SashFormEditionArea sashFormEditionArea = new SashFormEditionArea(parent, parent.getStyle()); + entryArea.createUi(sashFormEditionArea.getEntryArea(), context); + if (this.workArea != null) { + this.workArea.createUi(sashFormEditionArea.getEditorArea(), context); + } + return sashFormEditionArea; + } else { + if (this.workArea != null) { + Composite area = new Composite(parent, SWT.NONE); + this.workArea.createUi(area, context); + return area; + } + CmsTheme theme = CmsTheme.getCmsTheme(parent); + TabbedArea tabbedArea = createTabbedArea(parent, theme); + return tabbedArea; + } + } + + @Override + public void view(CmsUiProvider uiProvider, Composite workArea, Node context) { + TabbedArea tabbedArea; + if (workArea instanceof SashFormEditionArea) { + tabbedArea = ((SashFormEditionArea) workArea).getTabbedArea(); + } else if (workArea instanceof TabbedArea) { + tabbedArea = (TabbedArea) workArea; + } else + throw new IllegalArgumentException("Unsupported work area " + workArea.getClass().getName()); + tabbedArea.view(uiProvider, context); + } + + @Override + public void open(CmsUiProvider uiProvider, Composite workArea, Node context) { + TabbedArea tabbedArea = ((SashFormEditionArea) workArea).getTabbedArea(); + tabbedArea.open(uiProvider, context); + } + + public void init(Map properties) { + weights = LangUtils.toStringList(properties.get(Property.weights.name())); + startMaximized = properties.containsKey(Property.startMaximized.name()) + && "true".equals(properties.get(Property.startMaximized.name())); + } + + public void setEntryArea(CmsUiProvider entryArea) { + this.entryArea = entryArea; + } + + public void setWorkArea(CmsUiProvider workArea) { + this.workArea = workArea; + } + + TabbedArea createTabbedArea(Composite parent, CmsTheme theme) { + TabbedArea tabbedArea = new TabbedArea(parent, SWT.NONE); + tabbedArea.setBodyStyle(SuiteStyle.mainTabBody.style()); + tabbedArea.setTabStyle(SuiteStyle.mainTab.style()); + tabbedArea.setTabSelectedStyle(SuiteStyle.mainTabSelected.style()); + tabbedArea.setCloseIcon(SuiteIcon.close.getSmallIcon(theme)); + tabbedArea.setLayoutData(CmsUiUtils.fillAll()); + return tabbedArea; + } + + /** A work area based on an entry area and and a tabbed area. */ + class SashFormEditionArea extends SashForm { + private static final long serialVersionUID = 2219125778722702618L; + private CmsTheme theme; + private Composite entryArea; + private Composite editorArea; + private TabbedArea tabbedArea; + + SashFormEditionArea(Composite parent, int style) { + super(parent, SWT.HORIZONTAL); + theme = CmsTheme.getCmsTheme(parent); + + if (SWT.RIGHT_TO_LEFT == (style & SWT.RIGHT_TO_LEFT)) {// arabic, hebrew, etc. + editorArea = new Composite(this, SWT.BORDER); + entryArea = new Composite(this, SWT.BORDER); + } else { + entryArea = new Composite(this, SWT.NONE); + editorArea = new Composite(this, SWT.NONE); + } + + if (weights.size() != 0) { + int[] actualWeight = new int[weights.size()]; + for (int i = 0; i < weights.size(); i++) { + actualWeight[i] = Integer.parseInt(weights.get(i)); + } + setWeights(actualWeight); + } else { + int[] actualWeights = new int[] { 3000, 7000 }; + setWeights(actualWeights); + } + if (startMaximized) + setMaximizedControl(editorArea); + editorArea.setLayout(new GridLayout()); + + if (DefaultEditionLayer.this.workArea == null) { + tabbedArea = createTabbedArea(editorArea, theme); + } + + } + + Composite getEntryArea() { + return entryArea; + } + + TabbedArea getTabbedArea() { + return tabbedArea; + } + + Composite getEditorArea() { + return editorArea; + } + + } +} \ No newline at end of file diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultHeader.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultHeader.java new file mode 100644 index 0000000..a251e14 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultHeader.java @@ -0,0 +1,97 @@ +package org.argeo.suite.ui; + +import java.util.Dictionary; +import java.util.Map; +import java.util.TreeMap; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.LocaleUtils; +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.util.LangUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedService; + +public class DefaultHeader implements CmsUiProvider, ManagedService { + public final static String TITLE_PROPERTY = "argeo.suite.ui.header.title"; + private Map properties; + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + CmsView cmsView = CmsView.getCmsView(parent); + CmsTheme theme = CmsTheme.getCmsTheme(parent); + + parent.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(3, true))); + + // TODO right to left + Composite lead = new Composite(parent, SWT.NONE); + CmsUiUtils.style(lead, SuiteStyle.header); + lead.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, false)); + lead.setLayout(new GridLayout()); + Label lbl = new Label(lead, SWT.NONE); + String title = properties.get(TITLE_PROPERTY); + lbl.setText(LocaleUtils.isLocaleKey(title) ? LocaleUtils.local(title, getClass().getClassLoader()).toString() + : title); + CmsUiUtils.style(lbl, SuiteStyle.headerTitle); + lbl.setLayoutData(CmsUiUtils.fillWidth()); + + Composite middle = new Composite(parent, SWT.NONE); + CmsUiUtils.style(middle, SuiteStyle.header); + middle.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false)); + middle.setLayout(new GridLayout()); + + Composite end = new Composite(parent, SWT.NONE); + CmsUiUtils.style(end, SuiteStyle.header); + end.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false)); + + if (!cmsView.isAnonymous()) { + end.setLayout(new GridLayout(2, false)); + Label userL = new Label(end, SWT.NONE); + CmsUiUtils.style(userL, SuiteStyle.header); + userL.setText(CurrentUser.getDisplayName()); + Button logoutB = new Button(end, SWT.FLAT); +// CmsUiUtils.style(logoutB, SuiteStyle.header); + logoutB.setImage(SuiteIcon.logout.getSmallIcon(theme)); + logoutB.addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = 7116760083964201233L; + + @Override + public void widgetSelected(SelectionEvent e) { + cmsView.logout(); + } + + }); + } else { + end.setLayout(new GridLayout(1, false)); + // required in order to avoid wrong height after logout + new Label(end, SWT.NONE).setText(""); + + } + return lbl; + } + + public void init(Map properties) { + this.properties = new TreeMap<>(properties); + } + + @Override + public void updated(Dictionary properties) throws ConfigurationException { + if (properties != null) + this.properties.putAll(LangUtils.dictToStringMap(properties)); + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLeadPane.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLeadPane.java new file mode 100644 index 0000000..a207e7a --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLeadPane.java @@ -0,0 +1,130 @@ +package org.argeo.suite.ui; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.api.NodeConstants; +import org.argeo.cms.Localized; +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.suite.RankedObject; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.osgi.framework.Constants; + +/** Side pane listing various perspectives. */ +public class DefaultLeadPane implements CmsUiProvider { + private final static Log log = LogFactory.getLog(DefaultLeadPane.class); + + public static enum Property { + defaultLayers, adminLayers; + } + + private Map> layers = Collections.synchronizedSortedMap(new TreeMap<>()); + private String[] defaultLayers; + private String[] adminLayers; + + @Override + public Control createUi(Composite parent, Node node) throws RepositoryException { + CmsView cmsView = CmsView.getCmsView(parent); + GridLayout layout = new GridLayout(); + layout.verticalSpacing = 10; + layout.marginTop = 10; + layout.marginLeft = 10; + layout.marginRight = 10; + parent.setLayout(layout); + + Button first = null; + for (String layerId : defaultLayers) { + if (layers.containsKey(layerId)) { + RankedObject layerObj = layers.get(layerId); + + // TODO deal with i10n + String titleStr = (String) layerObj.getProperties().get(SuiteLayer.Property.title.name()); + Localized title = null; + if (titleStr != null) + title = new Localized.Untranslated(titleStr); + + String iconName = (String) layerObj.getProperties().get(SuiteLayer.Property.icon.name()); + SuiteIcon icon = null; + if (iconName != null) + icon = SuiteIcon.valueOf(iconName); + + Button b = SuiteUiUtils.createLayerButton(parent, layerId, title, icon); + if (first == null) + first = b; + } + } + + // TODO factorise + boolean isAdmin = cmsView.doAs(() -> CurrentUser.isInRole(NodeConstants.ROLE_USER_ADMIN)); + if (isAdmin && adminLayers != null) + for (String layerId : adminLayers) { + if (layers.containsKey(layerId)) { + RankedObject layerObj = layers.get(layerId); + + // TODO deal with i10n + String titleStr = (String) layerObj.getProperties().get(SuiteLayer.Property.title.name()); + Localized title = null; + if (titleStr != null) + title = new Localized.Untranslated(titleStr); + + String iconName = (String) layerObj.getProperties().get(SuiteLayer.Property.icon.name()); + SuiteIcon icon = null; + if (iconName != null) + icon = SuiteIcon.valueOf(iconName); + + Button b = SuiteUiUtils.createLayerButton(parent, layerId, title, icon); + if (first == null) + first = b; + } + } + +// Button dashboardB = createButton(parent, SuiteMsg.dashboard.name(), SuiteMsg.dashboard, SuiteIcon.dashboard); + if (!cmsView.isAnonymous()) { +// createButton(parent, SuiteMsg.documents.name(), SuiteMsg.documents, SuiteIcon.documents); +// createButton(parent, SuiteMsg.people.name(), SuiteMsg.people, SuiteIcon.people); +// createButton(parent, SuiteMsg.locations.name(), SuiteMsg.locations, SuiteIcon.location); + } + return first; + } + + public void init(Map properties) { + defaultLayers = (String[]) properties.get(Property.defaultLayers.toString()); + if (defaultLayers == null) + throw new IllegalArgumentException("Default layers must be set."); + if (log.isDebugEnabled()) + log.debug("Default layers: " + Arrays.asList(defaultLayers)); + adminLayers = (String[]) properties.get(Property.adminLayers.toString()); + if (log.isDebugEnabled() && adminLayers != null) + log.debug("Admin layers: " + Arrays.asList(adminLayers)); + } + + public void addLayer(SuiteLayer layer, Map properties) { + if (properties.containsKey(Constants.SERVICE_PID)) { + String pid = (String) properties.get(Constants.SERVICE_PID); + RankedObject.putIfHigherRank(layers, pid, layer, properties); + } + } + + public void removeLayer(SuiteLayer layer, Map properties) { + if (properties.containsKey(Constants.SERVICE_PID)) { + String pid = (String) properties.get(Constants.SERVICE_PID); + if (layers.containsKey(pid)) { + if (layers.get(pid).equals(new RankedObject(layer, properties))) { + layers.remove(pid); + } + } + } + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLoginScreen.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLoginScreen.java new file mode 100644 index 0000000..3757a19 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLoginScreen.java @@ -0,0 +1,34 @@ +package org.argeo.suite.ui; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.widgets.auth.CmsLogin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** Provides a login screen. */ +public class DefaultLoginScreen implements CmsUiProvider { + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + CmsView cmsView = CmsView.getCmsView(parent); + if (!cmsView.isAnonymous()) + throw new IllegalStateException(CurrentUser.getUsername() + " is already logged in"); + + parent.setLayout(new GridLayout()); + Composite loginArea = new Composite(parent, SWT.NONE); + loginArea.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); + + CmsLogin cmsLogin = new CmsLogin(cmsView); + cmsLogin.createUi(loginArea); + return cmsLogin.getCredentialsBlock(); + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java new file mode 100644 index 0000000..b9aa5b7 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java @@ -0,0 +1,366 @@ +package org.argeo.suite.ui; + +import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty; + +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; +import javax.jcr.query.Query; +import javax.jcr.query.QueryResult; + +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.entity.EntityType; +import org.argeo.jcr.Jcr; +import org.argeo.jcr.JcrUtils; +import org.argeo.suite.ui.widgets.DelayedText; +import org.argeo.suite.util.XPathUtils; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +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.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.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** List recent items. */ +public class RecentItems implements CmsUiProvider { + private final static int SEARCH_TEXT_DELAY = 800; + private final static int SEARCH_DEFAULT_LIMIT = 100; + + private CmsTheme theme; + + private String entityType; + + static enum Property { + entityTypes; + } + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + theme = CmsTheme.getCmsTheme(parent); + parent.setLayout(new GridLayout()); +// parent.setLayout(CmsUiUtils.noSpaceGridLayout()); + parent.setLayout(new GridLayout()); + +// Composite top = new Composite(parent, SWT.BORDER); +// CmsUiUtils.style(top, SuiteStyle.recentItems); +// top.setLayoutData(CmsUiUtils.fillWidth()); +// top.setLayout(CmsUiUtils.noSpaceGridLayout(2)); +// Label lbl = new Label(top, SWT.FLAT); +// lbl.setLayoutData(CmsUiUtils.fillWidth()); +// lbl.setText(SuiteMsg.recentItems.lead()); +// CmsUiUtils.style(lbl, SuiteStyle.recentItems); +// +// ToolBar topToolBar = new ToolBar(top, SWT.NONE); +// ToolItem addItem = new ToolItem(topToolBar, SWT.FLAT); +//// CmsUiUtils.style(addItem, SuiteStyle.recentItems); +// addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); + + if (context == null) + return null; + SingleEntityViewer entityViewer = new SingleEntityViewer(parent, SWT.NONE, context.getSession()); + entityViewer.createUi(); + entityViewer.getViewer().getTable().setLayoutData(CmsUiUtils.fillAll()); + + Composite bottom = new Composite(parent, SWT.NONE); + bottom.setLayoutData(CmsUiUtils.fillWidth()); + bottom.setLayout(CmsUiUtils.noSpaceGridLayout()); + ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); + bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); + ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); + deleteItem.setEnabled(false); +// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); + deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); + ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); + addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); + entityViewer.getViewer().addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + Node node = (Node) entityViewer.getViewer().getStructuredSelection().getFirstElement(); + if (node != null) + CmsView.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), + SuiteEvent.eventProperties(node)); + + } + }); + entityViewer.getViewer().addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + Node node = (Node) entityViewer.getViewer().getStructuredSelection().getFirstElement(); + if (node != null) { + CmsView.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), + SuiteEvent.eventProperties(node)); + deleteItem.setEnabled(true); + } else { + deleteItem.setEnabled(false); + } + } + }); + + return entityViewer.filterTxt; + + } + + public void init(Map properties) { + // TODO manage multiple entities + entityType = properties.get(Property.entityTypes.name()); + } + + class SingleEntityViewer { + Composite parent; + Text filterTxt; + TableViewer viewer; + Session session; + + public SingleEntityViewer(Composite parent, int style, Session session) { + this.parent = parent; + this.session = session; + } + + public void createUi() { + // MainLayout + addFilterPanel(parent); + viewer = createListPart(parent, new SingleEntityLabelProvider()); + refreshFilteredList(); + + try { + String[] nodeTypes = entityType != null && entityType.contains(":") ? new String[] { entityType } + : null; + session.getWorkspace().getObservationManager().addEventListener(new EventListener() { + + @Override + public void onEvent(EventIterator events) { + parent.getDisplay().asyncExec(() -> refreshFilteredList()); + } + }, Event.PROPERTY_CHANGED | Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED, "/", true, + null, nodeTypes, false); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot add JCR observer", e); + } + + } + + private void addFilterPanel(Composite parent) { + // Use a delayed text: the query won't be done until the user stop + // typing for 800ms + int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL; + DelayedText delayedText = new DelayedText(parent, style, SEARCH_TEXT_DELAY); + filterTxt = delayedText.getText(); + filterTxt.setLayoutData(EclipseUiUtils.fillWidth()); + + // final ServerPushSession pushSession = new ServerPushSession(); + delayedText.addDelayedModifyListener(null, new ModifyListener() { + private static final long serialVersionUID = 5003010530960334977L; + + public void modifyText(ModifyEvent event) { + delayedText.getText().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + refreshFilteredList(); + } + }); + // pushSession.stop(); + } + }); + + // Jump to the first item of the list using the down arrow + filterTxt.addKeyListener(new KeyListener() { + private static final long serialVersionUID = -4523394262771183968L; + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0; + // boolean altPressed = (e.stateMask & SWT.ALT) != 0; + if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) { +// Object first = entityViewer.getElementAt(0); +// if (first != null) { +// entityViewer.getTable().setFocus(); +// entityViewer.setSelection(new StructuredSelection(first), true); +// } + e.doit = false; + } + } + }); + + parent.addDisposeListener((e) -> { + delayedText.close(); + }); + } + + protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) { +// parent.setLayout(new GridLayout()); +// parent.setLayout(CmsUiUtils.noSpaceGridLayout()); + + Composite tableComposite = new Composite(parent, SWT.NONE); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL + | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL); + tableComposite.setLayoutData(gd); + + TableViewer viewer = new TableViewer(tableComposite, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); + viewer.setLabelProvider(labelProvider); + + TableColumn singleColumn = new TableColumn(viewer.getTable(), SWT.V_SCROLL); + TableColumnLayout tableColumnLayout = new TableColumnLayout(); + tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(85)); + tableComposite.setLayout(tableColumnLayout); + + // Corresponding table & style + Table table = viewer.getTable(); +// Listener[] mouseDownListeners = table.getListeners(SWT.MouseDown); +// for (Listener listener : table.getListeners(SWT.MouseDown)) +// table.removeListener(SWT.MouseDown, listener); +// for (Listener listener : table.getListeners(SWT.MouseUp)) +// table.removeListener(SWT.MouseUp, listener); +// for (Listener listener : table.getListeners(SWT.MouseDoubleClick)) +// table.removeListener(SWT.MouseDoubleClick, listener); +// +// table.addMouseListener(new MouseListener() { +// +// @Override +// public void mouseUp(MouseEvent e) { +// System.out.println("Mouse up: "+e); +// } +// +// @Override +// public void mouseDown(MouseEvent e) { +// System.out.println("Mouse down: "+e); +// } +// +// @Override +// public void mouseDoubleClick(MouseEvent e) { +// System.out.println("Mouse double: "+e); +// +// } +// }); + table.setLinesVisible(true); + table.setHeaderVisible(false); + // CmsUiUtils.markup(table); + // CmsUiUtils.setItemHeight(table, 26); + + viewer.setContentProvider(new BasicNodeListContentProvider()); + return viewer; + } + +// public boolean setFocus() { +// refreshFilteredList(); +// return parent.setFocus(); +// } + + public void forceRefresh(Object object) { + refreshFilteredList(); + } + + protected void refreshFilteredList() { + try { + String filter = filterTxt.getText(); + // Prevents the query on the full repository + // if (isEmpty(filter)) { + // entityViewer.setInput(null); + // return; + // } + + // XPATH Query + String xpathQueryStr; + if (entityType != null) { + int indexColumn = entityType.indexOf(':'); + if (indexColumn > 0) {// JCR node type + xpathQueryStr = "//element(*, " + entityType + ") order by @jcr:created descending"; + } else { + xpathQueryStr = entityType.contains(":") ? "//element(*, " + entityType + ")" + : "//element(*, " + EntityType.entity.get() + ")[@entity:type='" + entityType + "']"; + } + } else { + xpathQueryStr = "//element(*, " + EntityType.entity.get() + ")"; + } +// String xpathQueryStr = "//element(*, " + ConnectTypes.CONNECT_ENTITY + ")"; + String xpathFilter = XPathUtils.getFreeTextConstraint(filter); + if (notEmpty(xpathFilter)) + xpathQueryStr += "[" + xpathFilter + "]"; + +// long begin = System.currentTimeMillis(); + // session.refresh(false); + Query xpathQuery = XPathUtils.createQuery(session, xpathQueryStr); + + xpathQuery.setLimit(SEARCH_DEFAULT_LIMIT); + QueryResult result = xpathQuery.execute(); + + NodeIterator nit = result.getNodes(); + viewer.setInput(JcrUtils.nodeIteratorToList(nit)); +// if (log.isTraceEnabled()) { +// long end = System.currentTimeMillis(); +// log.trace("Quick Search - Found: " + nit.getSize() + " in " + (end - begin) +// + " ms by executing XPath query (" + xpathQueryStr + ")."); +// } + } catch (RepositoryException e) { + throw new IllegalStateException("Unable to list entities", e); + } + } + + public TableViewer getViewer() { + return viewer; + } + + class SingleEntityLabelProvider extends ColumnLabelProvider { + private static final long serialVersionUID = -2209337675781795677L; + + @Override + public String getText(Object element) { + return Jcr.getTitle((Node) element); + } + + } + + class BasicNodeListContentProvider implements IStructuredContentProvider { + private static final long serialVersionUID = 1L; + // keep a cache of the Nodes in the content provider to be able to + // manage long request + private List nodes; + + public void dispose() { + } + + /** Expects a list of nodes as a new input */ + @SuppressWarnings("unchecked") + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + nodes = (List) newInput; + } + + public Object[] getElements(Object arg0) { + return nodes.toArray(); + } + } + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java new file mode 100644 index 0000000..dbed853 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java @@ -0,0 +1,517 @@ +package org.argeo.suite.ui; + +import static org.argeo.cms.ui.CmsView.CMS_VIEW_UID_PROPERTY; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.api.NodeUtils; +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.LocaleUtils; +import org.argeo.cms.auth.CmsSession; +import org.argeo.cms.ui.AbstractCmsApp; +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.dialogs.CmsFeedback; +import org.argeo.cms.ui.util.CmsEvent; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.specific.UiContext; +import org.argeo.entity.EntityConstants; +import org.argeo.entity.EntityNames; +import org.argeo.entity.EntityType; +import org.argeo.jcr.Jcr; +import org.argeo.suite.RankedObject; +import org.argeo.suite.SuiteUtils; +import org.argeo.util.LangUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.osgi.framework.Constants; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; +import org.osgi.service.useradmin.User; + +/** The Argeo Suite App. */ +public class SuiteApp extends AbstractCmsApp implements EventHandler { + private final static Log log = LogFactory.getLog(SuiteApp.class); + + public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath"; + public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName"; + public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId"; + + private String publicBasePath = null; + + private String pidPrefix; + private String headerPid; + private String leadPanePid; + private String loginScreenPid; +// private String DASHBOARD_PID = pidPrefix + "dashboard"; +// private String RECENT_ITEMS_PID = pidPrefix + "recentItems"; + + private String defaultUiName = "app"; + private String defaultThemeId = "org.argeo.suite.theme.default"; + + private Map> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>()); + private Map> uiProvidersByType = Collections.synchronizedMap(new HashMap<>()); + private Map> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>()); + private Map> layersByType = Collections.synchronizedSortedMap(new TreeMap<>()); + + private CmsUserManager cmsUserManager; + + // TODO make more optimal or via CmsSession/CmsView + private Map managedUis = new HashMap<>(); + +// private CmsUiProvider headerPart = null; + + public void init(Map properties) { + if (log.isDebugEnabled()) + log.info("Argeo Suite App started"); + + if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY)) + defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY); + if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY)) + defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY); + publicBasePath = LangUtils.get(properties, PUBLIC_BASE_PATH_PROPERTY); + + if (properties.containsKey(Constants.SERVICE_PID)) { + String servicePid = properties.get(Constants.SERVICE_PID).toString(); + if (servicePid.endsWith(".app")) { + pidPrefix = servicePid.substring(0, servicePid.length() - "app".length()); + } + } + + if (pidPrefix == null) + throw new IllegalArgumentException("PID prefix must be set."); + + headerPid = pidPrefix + "header"; + leadPanePid = pidPrefix + "leadPane"; + loginScreenPid = pidPrefix + "loginScreen"; + } + + public void destroy(Map properties) { + for (SuiteUi ui : managedUis.values()) + if (!ui.isDisposed()) + ui.dispose(); + if (log.isDebugEnabled()) + log.info("Argeo Suite App stopped"); + + } + + @Override + public Set getUiNames() { + HashSet uiNames = new HashSet<>(); + uiNames.add(defaultUiName); + return uiNames; + } + + @Override + public Composite initUi(Composite parent) { + String uiName = parent.getData(UI_NAME_PROPERTY) != null ? parent.getData(UI_NAME_PROPERTY).toString() : null; + CmsView cmsView = CmsView.getCmsView(parent); + if (cmsView == null) + throw new IllegalStateException("No CMS view is registered."); + CmsTheme theme = getTheme(uiName); + if (theme != null) + CmsTheme.registerCmsTheme(parent.getShell(), theme); + SuiteUi argeoSuiteUi = new SuiteUi(parent, SWT.INHERIT_DEFAULT); + String uid = cmsView.getUid(); + managedUis.put(uid, argeoSuiteUi); + argeoSuiteUi.addDisposeListener((e) -> { + managedUis.remove(uid); + if (log.isDebugEnabled()) + log.debug("Suite UI " + uid + " has been disposed."); + }); + refreshUi(argeoSuiteUi, null); + return argeoSuiteUi; + } + + @Override + public String getThemeId(String uiName) { + return defaultThemeId; + } + + @Override + public void refreshUi(Composite parent, String state) { + try { + Node context = null; + SuiteUi ui = (SuiteUi) parent; + CmsView cmsView = CmsView.getCmsView(parent); + if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login + ui.logout(); + refreshPart(findUiProvider(headerPid), ui.getHeader(), context); + ui.refreshBelowHeader(false); + refreshPart(findUiProvider(loginScreenPid), ui.getBelowHeader(), context); + ui.layout(true, true); + } else { + CmsSession cmsSession = cmsView.getCmsSession(); + if (ui.getUserDir() == null) { + if (cmsView.isAnonymous()) { + assert publicBasePath != null; + ui.initSessions(getRepository(), publicBasePath); + } else { + Session adminSession = null; + try { + adminSession = NodeUtils.openDataAdminSession(getRepository(), null); + Node userDir = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession); + ui.initSessions(getRepository(), userDir.getPath()); + } finally { + Jcr.logout(adminSession); + } + } + } + initLocale(cmsSession); + context = stateToNode(ui, state); + if (context == null) + context = ui.getUserDir(); + + refreshPart(findUiProvider(headerPid), ui.getHeader(), context); + ui.refreshBelowHeader(true); + for (String key : layersByPid.keySet()) { + SuiteLayer layer = layersByPid.get(key).get(); + ui.addLayer(key, layer); + } + refreshPart(findUiProvider(leadPanePid), ui.getLeadPane(), context); + ui.layout(true, true); + setState(parent, state); + } + } catch (Exception e) { + CmsFeedback.show("Unexpected exception", e); + } + } + + private void initLocale(CmsSession cmsSession) { + if (cmsSession == null) + return; + Locale locale = cmsSession.getLocale(); + UiContext.setLocale(locale); + LocaleUtils.setThreadLocale(locale); + + } + + private void refreshPart(CmsUiProvider uiProvider, Composite part, Node context) { + CmsUiUtils.clear(part); + uiProvider.createUiPart(part, context); + } + + private CmsUiProvider findUiProvider(String pid) { + if (!uiProvidersByPid.containsKey(pid)) + throw new IllegalArgumentException("No UI provider registered as " + pid); + return uiProvidersByPid.get(pid).get(); + } + + private T findByType(Map> byType, Node context) { + if (context == null) + throw new IllegalArgumentException("A node should be provided"); + try { + // mixins + Set types = new TreeSet<>(); + for (NodeType nodeType : context.getMixinNodeTypes()) { + String typeName = nodeType.getName(); + if (byType.containsKey(typeName)) { + types.add(typeName); + } + } + // primary node type + { + NodeType nodeType = context.getPrimaryNodeType(); + String typeName = nodeType.getName(); + if (byType.containsKey(typeName)) { + types.add(typeName); + } + for (NodeType mixin : nodeType.getDeclaredSupertypes()) { + if (byType.containsKey(mixin.getName())) { + types.add(mixin.getName()); + } + } + } + // entity type + if (context.isNodeType(EntityType.entity.get())) { + if (context.hasProperty(EntityNames.ENTITY_TYPE)) { + String typeName = context.getProperty(EntityNames.ENTITY_TYPE).getString(); + if (byType.containsKey(typeName)) { + types.add(typeName); + } + } + } + +// if (context.getPath().equals("/")) {// root node +// types.add("nt:folder"); +// } + if (NodeUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node + types.add("nt:folder"); + } + + if (types.size() == 0) + throw new IllegalArgumentException("No type found for " + context); + String type = types.iterator().next(); + if (!byType.containsKey(type)) + throw new IllegalArgumentException("No component found for " + context + " with type " + type); + return byType.get(type).get(); + } catch (RepositoryException e) { + throw new IllegalStateException(e); + } + } + + @Override + public void setState(Composite parent, String state) { + if (state == null || state.equals("~")) + return; + if (!state.startsWith("/") && !state.equals("~")) { + if (parent instanceof SuiteUi) { + SuiteUi ui = (SuiteUi) parent; + String currentLayerId = ui.getCurrentLayerId(); + if (state.equals(currentLayerId)) + return; // does nothing + else { + Map properties = new HashMap<>(); + properties.put(SuiteEvent.LAYER, state); + ui.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), properties); + } + } + return; + } + SuiteUi suiteUi = (SuiteUi) parent; + Node node = stateToNode(suiteUi, state); + if (node == null) { + suiteUi.getCmsView().navigateTo("~"); + } else { + suiteUi.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), SuiteEvent.eventProperties(node)); + suiteUi.getCmsView().sendEvent(SuiteEvent.refreshPart.topic(), SuiteEvent.eventProperties(node)); + } + } + + private String nodeToState(Node node) { + return '/' + Jcr.getWorkspaceName(node) + Jcr.getPath(node); + } + + private Node stateToNode(SuiteUi suiteUi, String state) { + if (suiteUi == null) + return null; + if (state == null || !state.startsWith("/")) + return null; + + String path = state.substring(1); + String workspace; + if (path.equals("")) { + workspace = null; + path = "/"; + } else { + int index = path.indexOf('/'); + if (index == 0) { + log.error("Cannot interpret " + state); +// cmsView.navigateTo("~"); + return null; + } else if (index > 0) { + workspace = path.substring(0, index); + path = path.substring(index); + } else {// index<0, assuming root node + workspace = path; + path = "/"; + } + } + Session session = suiteUi.getSession(workspace); + if (session == null) + return null; + Node node = Jcr.getNode(session, path); + return node; + } + + /* + * Events management + */ + + @Override + public void handleEvent(Event event) { + + // Specific UI related events + SuiteUi ui = getRelatedUi(event); + if (ui == null) + return; + try { +// String currentLayerId = ui.getCurrentLayerId(); +// SuiteLayer currentLayer = currentLayerId != null ? layersByPid.get(currentLayerId).get() : null; + if (isTopic(event, SuiteEvent.refreshPart)) { + Node node = getNode(ui, event); + if (node == null) + return; + CmsUiProvider uiProvider = findByType(uiProvidersByType, node); + SuiteLayer layer = findByType(layersByType, node); + ui.switchToLayer(layer, node); + ui.getCmsView().runAs(() -> layer.view(uiProvider, ui.getCurrentWorkArea(), node)); + ui.getCmsView().stateChanged(nodeToState(node), Jcr.getTitle(node)); + } else if (isTopic(event, SuiteEvent.openNewPart)) { + Node node = getNode(ui, event); + if (node == null) + return; + CmsUiProvider uiProvider = findByType(uiProvidersByType, node); + SuiteLayer layer = findByType(layersByType, node); + ui.switchToLayer(layer, node); + ui.getCmsView().runAs(() -> layer.open(uiProvider, ui.getCurrentWorkArea(), node)); + ui.getCmsView().stateChanged(nodeToState(node), Jcr.getTitle(node)); + } else if (isTopic(event, SuiteEvent.switchLayer)) { + String layerId = get(event, SuiteEvent.LAYER); + if (layerId != null) { +// ui.switchToLayer(layerId, ui.getUserDir()); + ui.getCmsView().runAs(() -> ui.switchToLayer(layerId, ui.getUserDir())); + ui.getCmsView().navigateTo(layerId); + } else { + Node node = getNode(ui, event); + if (node != null) { + SuiteLayer layer = findByType(layersByType, node); + ui.getCmsView().runAs(() -> ui.switchToLayer(layer, node)); + } + } + } + } catch (Exception e) { + log.error("Cannot handle event " + event, e); +// CmsView.getCmsView(ui).exception(e); + } + + } + + private Node getNode(SuiteUi ui, Event event) { + String nodePath = get(event, SuiteEvent.NODE_PATH); + String workspaceName = get(event, SuiteEvent.WORKSPACE); + Session session = ui.getSession(workspaceName); + Node node; + if (nodePath == null) { + // look for a user + String username = get(event, SuiteEvent.USERNAME); + if (username == null) + return null; + User user = cmsUserManager.getUser(username); + if (user == null) + return null; + LdapName userDn; + try { + userDn = new LdapName(user.getName()); + } catch (InvalidNameException e) { + throw new IllegalArgumentException("Badly formatted username", e); + } + String userNodePath = SuiteUtils.getUserNodePath(userDn); + if (Jcr.itemExists(session, userNodePath)) + node = Jcr.getNode(session, userNodePath); + else { + Session adminSession = null; + try { + adminSession = NodeUtils.openDataAdminSession(getRepository(), workspaceName); + SuiteUtils.getOrCreateUserNode(adminSession, userDn); + } finally { + Jcr.logout(adminSession); + } + node = Jcr.getNode(session, userNodePath); + } + } else { + node = Jcr.getNode(session, nodePath); + } + return node; + } + + private SuiteUi getRelatedUi(Event event) { + return managedUis.get(get(event, CMS_VIEW_UID_PROPERTY)); + } + + private static boolean isTopic(Event event, CmsEvent cmsEvent) { + return event.getTopic().equals(cmsEvent.topic()); + } + + private static String get(Event event, String key) { + Object value = event.getProperty(key); + if (value == null) + return null; +// throw new IllegalArgumentException("Property " + key + " must be set"); + return value.toString(); + + } + + /* + * Dependency injection. + */ + + public void addUiProvider(CmsUiProvider uiProvider, Map properties) { + if (properties.containsKey(Constants.SERVICE_PID)) { + String pid = (String) properties.get(Constants.SERVICE_PID); + RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties); + } + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) + RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties); + } + } + + public void removeUiProvider(CmsUiProvider uiProvider, Map properties) { + if (properties.containsKey(Constants.SERVICE_PID)) { + String pid = (String) properties.get(Constants.SERVICE_PID); + if (uiProvidersByPid.containsKey(pid)) { + if (uiProvidersByPid.get(pid).equals(new RankedObject(uiProvider, properties))) { + uiProvidersByPid.remove(pid); + } + } + } + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) { + if (uiProvidersByType.containsKey(type)) { + if (uiProvidersByType.get(type).equals(new RankedObject(uiProvider, properties))) { + uiProvidersByType.remove(type); + } + } + } + } + } + + public void addLayer(SuiteLayer layer, Map properties) { + if (properties.containsKey(Constants.SERVICE_PID)) { + String pid = (String) properties.get(Constants.SERVICE_PID); + RankedObject.putIfHigherRank(layersByPid, pid, layer, properties); + } + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) + RankedObject.putIfHigherRank(layersByType, type, layer, properties); + } + } + + public void removeLayer(SuiteLayer layer, Map properties) { + if (properties.containsKey(Constants.SERVICE_PID)) { + String pid = (String) properties.get(Constants.SERVICE_PID); + if (layersByPid.containsKey(pid)) { + if (layersByPid.get(pid).equals(new RankedObject(layer, properties))) { + layersByPid.remove(pid); + } + } + } + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) { + if (layersByType.containsKey(type)) { + if (layersByType.get(type).equals(new RankedObject(layer, properties))) { + layersByType.remove(type); + } + } + } + } + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java new file mode 100644 index 0000000..563cd21 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java @@ -0,0 +1,38 @@ +package org.argeo.suite.ui; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Node; + +import org.argeo.cms.ui.util.CmsEvent; +import org.argeo.jcr.Jcr; +import org.osgi.service.useradmin.User; + +/** Events specific to Argeo Suite. */ +public enum SuiteEvent implements CmsEvent { + openNewPart, refreshPart, switchLayer; + + public final static String LAYER = "layer"; +// public final static String NODE_ID = "nodeId"; + public final static String NODE_PATH = "path"; + public final static String USERNAME = "username"; + public final static String WORKSPACE = "workspace"; + + public String getTopicBase() { + return "argeo/suite/ui"; + } + + public static Map eventProperties(Node node) { + Map properties = new HashMap<>(); + properties.put(NODE_PATH, Jcr.getPath(node)); + properties.put(WORKSPACE, Jcr.getWorkspaceName(node)); + return properties; + } + + public static Map eventProperties(User user) { + Map properties = new HashMap<>(); + properties.put(USERNAME, user.getName()); + return properties; + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteIcon.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteIcon.java new file mode 100644 index 0000000..e40ba5a --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteIcon.java @@ -0,0 +1,16 @@ +package org.argeo.suite.ui; + +import org.argeo.cms.ui.util.CmsIcon; + +/** Icon names used by Argeo Suite. */ +public enum SuiteIcon implements CmsIcon { + add, save, close, search, delete, logout, dashboard, + // people + people, person, organisation, + // library + documents, document, folder, + // admin and settings + settings, user, + // misc + task, tag, location, inbox, map; +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java new file mode 100644 index 0000000..8af7611 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java @@ -0,0 +1,19 @@ +package org.argeo.suite.ui; + +import javax.jcr.Node; + +import org.argeo.cms.ui.CmsUiProvider; +import org.eclipse.swt.widgets.Composite; + +/** An UI layer for the main work area. */ +public interface SuiteLayer extends CmsUiProvider { + static enum Property { + title, icon, weights, startMaximized; + } + + void view(CmsUiProvider uiProvider, Composite workArea, Node context); + + default void open(CmsUiProvider uiProvider, Composite workArea, Node context) { + view(uiProvider, workArea, context); + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java new file mode 100644 index 0000000..3b376db --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java @@ -0,0 +1,34 @@ +package org.argeo.suite.ui; + +import org.argeo.cms.Localized; + +/** Localized messages. */ +public enum SuiteMsg implements Localized { + dashboard, people, documents, locations, recentItems, + // NewPersonWizard + firstName, lastName, salutation, email, personWizardWindowTitle, personWizardPageTitle, + // NewOrgWizard + orgWizardWindowTitle, orgWizardPageTitle, legalName, legalForm, vatId, + // ContextAddressComposite + chooseAnOrganisation, street, streetComplement, zipCode, city, state, country, geopoint, + // FilteredOrderableEntityTable + filterHelp, + // BankAccountComposite + accountHolder, bankName, currency, accountNumber, bankNumber, BIC, IBAN, + // EditJobDialog + position, chosenItem, department, isPrimary, searchAndChooseEntity, + // ContactListCTab (e4) + notes, addAContact, contactValue, linkedCompany, + // OrgAdminInfoCTab (e4) + paymentAccount, + // OrgEditor (e4) + orgDetails, orgActivityLog, team, orgAdmin, + // PersonEditor (e4) + personDetails, personActivityLog, personOrgs, personSecurity, + // PersonSecurityCTab (e4) + resetPassword, + // Generic + label, aCustomLabel, description, value, name, primary, add, save, pickup, + // Tag + confirmNewTag, cannotCreateTag; +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java new file mode 100644 index 0000000..5183fa4 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java @@ -0,0 +1,31 @@ +package org.argeo.suite.ui; + +import org.argeo.cms.ui.util.CmsStyle; + +/** Styles used by Argeo Suite work UI. */ +public enum SuiteStyle implements CmsStyle { + // Header + header, headerTitle, headerMenu, headerMenuItem, + // Recent items + recentItems, + // Lead pane + leadPane, leadPaneItem, leadPaneSectionTitle, leadPaneSubSectionTitle, + // Group composite + titleContainer, titleLabel, subTitleLabel, formLine, formColumn, navigationBar, navigationTitle, navigationButton, + // Forms elements + simpleLabel, simpleText, simpleInput, + // table + titleCell, + // layers + workArea, + // tabbed area + mainTabBody, mainTabSelected, mainTab, + // Buttons + inlineButton; + + @Override + public String getClassPrefix() { + return "argeo-suite"; + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java new file mode 100644 index 0000000..b245762 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java @@ -0,0 +1,226 @@ +package org.argeo.suite.ui; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.api.NodeConstants; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.jcr.Jcr; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Composite; + +/** The view for the default ergonomics of Argeo Suite. */ +class SuiteUi extends Composite { + private static final long serialVersionUID = 6207018859086689108L; + private final static Log log = LogFactory.getLog(SuiteUi.class); + private Composite header; + private Composite belowHeader; + private Composite leadPane; + private Composite dynamicArea; + + private Session sysSession; +// private Session homeSession; + private Node userDir; + + private Map layers = new HashMap<>(); + private Map workAreas = new HashMap<>(); + private String currentLayerId = null; + + private CmsView cmsView; + + public SuiteUi(Composite parent, int style) { + super(parent, style); + cmsView = CmsView.getCmsView(parent); + this.setLayout(CmsUiUtils.noSpaceGridLayout()); + + header = new Composite(this, SWT.NONE); + header.setLayout(CmsUiUtils.noSpaceGridLayout()); + CmsUiUtils.style(header, SuiteStyle.header); + header.setLayoutData(CmsUiUtils.fillWidth()); + + belowHeader = new Composite(this, SWT.NONE); + belowHeader.setLayoutData(CmsUiUtils.fillAll()); + } + + public void refreshBelowHeader(boolean initApp) { + CmsUiUtils.clear(belowHeader); + int style = getStyle(); + if (initApp) { + belowHeader.setLayout(CmsUiUtils.noSpaceGridLayout(2)); + + if (SWT.RIGHT_TO_LEFT == (style & SWT.RIGHT_TO_LEFT)) {// arabic, hebrew, etc. + dynamicArea = new Composite(belowHeader, SWT.NONE); + leadPane = new Composite(belowHeader, SWT.NONE); + } else { + leadPane = new Composite(belowHeader, SWT.NONE); + dynamicArea = new Composite(belowHeader, SWT.NONE); + } + leadPane.setLayoutData(CmsUiUtils.fillHeight()); + leadPane.setLayout(CmsUiUtils.noSpaceGridLayout()); + CmsUiUtils.style(leadPane, SuiteStyle.leadPane); + + dynamicArea.setLayoutData(CmsUiUtils.fillAll()); + dynamicArea.setLayout(new FormLayout()); + + } else { + belowHeader.setLayout(CmsUiUtils.noSpaceGridLayout()); + } + } + + /* + * LAYERS + */ + + Composite getCurrentWorkArea() { + if (currentLayerId == null) + throw new IllegalStateException("No current layer"); + return workAreas.get(currentLayerId); + } + + String getCurrentLayerId() { + return currentLayerId; + } + + private Composite getLayer(String id, Node context) { + if (!layers.containsKey(id)) + return null; + if (!workAreas.containsKey(id)) + initLayer(id, layers.get(id), context); + return workAreas.get(id); + } + + Composite switchToLayer(String layerId, Node context) { + Composite current = null; + if (currentLayerId != null) { + current = getCurrentWorkArea(); + if (currentLayerId.equals(layerId)) + return current; + } + if (context == null) { + if (!cmsView.isAnonymous()) + context = userDir; + } + Composite toShow = getLayer(layerId, context); + if (toShow != null) { + currentLayerId = layerId; + if (!isDisposed()) { +// getDisplay().syncExec(() -> { + if (!toShow.isDisposed()) { + toShow.moveAbove(null); + } else { + log.warn("Cannot show work area because it is disposed."); + toShow = initLayer(layerId, layers.get(layerId), context); + toShow.moveAbove(null); + } + dynamicArea.layout(true, true); +// }); + } + return toShow; + } else { + return current; + } + } + + Composite switchToLayer(SuiteLayer layer, Node context) { + // TODO make it more robust + for (String layerId : layers.keySet()) { + SuiteLayer l = layers.get(layerId); + if (layer == l) { + return switchToLayer(layerId, context); + } + } + throw new IllegalArgumentException("Layer is not registered."); + } + + void addLayer(String id, SuiteLayer layer) { + layers.put(id, layer); + } + + void removeLayer(String id) { + layers.remove(id); + if (workAreas.containsKey(id)) { + Composite workArea = workAreas.remove(id); + if (!workArea.isDisposed()) + workArea.dispose(); + } + } + + protected Composite initLayer(String id, SuiteLayer layer, Node context) { + Composite workArea = cmsView.doAs(() -> (Composite) layer.createUiPart(dynamicArea, context)); + CmsUiUtils.style(workArea, SuiteStyle.workArea); + workArea.setLayoutData(CmsUiUtils.coverAll()); + workAreas.put(id, workArea); + return workArea; + } + + synchronized void logout() { + userDir = null; + Jcr.logout(sysSession); +// Jcr.logout(homeSession); + currentLayerId = null; + workAreas.clear(); + } + + /* + * GETTERS / SETTERS + */ + + Composite getHeader() { + return header; + } + + Composite getLeadPane() { + return leadPane; + } + + Composite getBelowHeader() { + return belowHeader; + } + +// Session getSysSession() { +// return sysSession; +// } +// + synchronized void initSessions(Repository repository, String userDirPath) throws RepositoryException { + this.sysSession = repository.login(); +// this.homeSession = repository.login(NodeConstants.HOME_WORKSPACE); + userDir = sysSession.getNode(userDirPath); + addDisposeListener((e) -> { + Jcr.logout(sysSession); +// Jcr.logout(homeSession); + }); + } + + Node getUserDir() { + return userDir; + } + + Session getSysSession() { + return sysSession; + } + + Session getSession(String workspaceName) { + if (workspaceName == null) + return sysSession; + if (NodeConstants.SYS_WORKSPACE.equals(workspaceName)) + return sysSession; +// else if (NodeConstants.HOME_WORKSPACE.equals(workspaceName)) +// return homeSession; + else + throw new IllegalArgumentException("Unknown workspace " + workspaceName); + } + + public CmsView getCmsView() { + return cmsView; + } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUiUtils.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUiUtils.java new file mode 100644 index 0000000..8e9a9d5 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUiUtils.java @@ -0,0 +1,368 @@ +package org.argeo.suite.ui; + +import java.io.IOException; +import java.io.InputStream; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.cms.Localized; +import org.argeo.cms.ui.CmsEditable; +import org.argeo.cms.ui.CmsTheme; +import org.argeo.cms.ui.dialogs.LightweightDialog; +import org.argeo.cms.ui.util.CmsIcon; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.entity.EntityNames; +import org.argeo.entity.EntityType; +import org.argeo.jcr.Jcr; +import org.argeo.jcr.JcrUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.graphics.ImageData; +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.Label; +import org.eclipse.swt.widgets.Text; + +/** UI utilities related to the APAF project. */ +public class SuiteUiUtils { + + /** Singleton. */ + private SuiteUiUtils() { + } + + /** creates a title bar composite with label and optional button */ + public static void addTitleBar(Composite parent, String title, Boolean isEditable) { + Composite titleBar = new Composite(parent, SWT.NONE); + titleBar.setLayoutData(CmsUiUtils.fillWidth()); + CmsUiUtils.style(titleBar, SuiteStyle.titleContainer); + + titleBar.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(2, false))); + Label titleLbl = new Label(titleBar, SWT.NONE); + titleLbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); + CmsUiUtils.style(titleLbl, SuiteStyle.titleLabel); + titleLbl.setText(title); + + if (isEditable) { + Button editBtn = new Button(titleBar, SWT.PUSH); + editBtn.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); + CmsUiUtils.style(editBtn, SuiteStyle.inlineButton); + editBtn.setText("Edit"); + } + } + + public static Label addFormLabel(Composite parent, String label) { + Label lbl = new Label(parent, SWT.WRAP); + lbl.setText(label); + // lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, true)); + CmsUiUtils.style(lbl, SuiteStyle.simpleLabel); + return lbl; + } + + public static Text addFormTextField(Composite parent, String text, String message) { + return addFormTextField(parent, text, message, SWT.NONE); + } + + public static Text addFormTextField(Composite parent, String text, String message, int style) { + Text txt = new Text(parent, style); + if (text != null) + txt.setText(text); + if (message != null) + txt.setMessage(message); + txt.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, true)); + CmsUiUtils.style(txt, SuiteStyle.simpleText); + return txt; + } + + public static Text addFormInputField(Composite parent, String placeholder) { + Text txt = new Text(parent, SWT.BORDER); + + GridData gridData = CmsUiUtils.fillWidth(); + txt.setLayoutData(gridData); + + if (placeholder != null) + txt.setText(placeholder); + + CmsUiUtils.style(txt, SuiteStyle.simpleInput); + return txt; + } + + /** creates a single horizontal-block composite for key:value display */ + public static Text addFormLine(Composite parent, String label, String text) { + Composite lineComposite = new Composite(parent, SWT.NONE); + lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + lineComposite.setLayout(new GridLayout(2, false)); + CmsUiUtils.style(lineComposite, SuiteStyle.formLine); + addFormLabel(lineComposite, label); + Text txt = addFormTextField(lineComposite, text, null); + txt.setEditable(false); + txt.setLayoutData(CmsUiUtils.fillWidth()); + return txt; + } + + public static Text addFormLine(Composite parent, String label, Node node, String property, + CmsEditable cmsEditable) { + Composite lineComposite = new Composite(parent, SWT.NONE); + lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + lineComposite.setLayout(new GridLayout(2, false)); + CmsUiUtils.style(lineComposite, SuiteStyle.formLine); + addFormLabel(lineComposite, label); + String text = Jcr.get(node, property); +// int style = cmsEditable.isEditing() ? SWT.WRAP : SWT.WRAP; + Text txt = addFormTextField(lineComposite, text, null, SWT.WRAP); + if (cmsEditable != null && cmsEditable.isEditing()) { + txt.addModifyListener((e) -> { + Jcr.set(node, property, txt.getText()); + Jcr.save(node); + }); + } else { + txt.setEditable(false); + } + txt.setLayoutData(CmsUiUtils.fillWidth()); + return txt; + } + + public static Text addFormInput(Composite parent, String label, String placeholder) { + Composite lineComposite = new Composite(parent, SWT.NONE); + lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + lineComposite.setLayout(new GridLayout(2, false)); + CmsUiUtils.style(lineComposite, SuiteStyle.formLine); + addFormLabel(lineComposite, label); + Text txt = addFormInputField(lineComposite, placeholder); + txt.setLayoutData(CmsUiUtils.fillWidth()); + return txt; + } + + /** + * creates a single horizontal-block composite for key:value display, with + * offset value + */ + public static Text addFormLine(Composite parent, String label, String text, Integer offset) { + Composite lineComposite = new Composite(parent, SWT.NONE); + lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + lineComposite.setLayout(new GridLayout(3, false)); + CmsUiUtils.style(lineComposite, SuiteStyle.formLine); + Label offsetLbl = new Label(lineComposite, SWT.NONE); + GridData gridData = new GridData(); + gridData.widthHint = offset; + offsetLbl.setLayoutData(gridData); + addFormLabel(lineComposite, label); + Text txt = addFormTextField(lineComposite, text, null); + txt.setLayoutData(CmsUiUtils.fillWidth()); + return txt; + } + + /** creates a single vertical-block composite for key:value display */ + public static Text addFormColumn(Composite parent, String label, String text) { +// Composite columnComposite = new Composite(parent, SWT.NONE); +// columnComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); +// columnComposite.setLayout(new GridLayout(1, false)); + addFormLabel(parent, label); + Text txt = addFormTextField(parent, text, null); + txt.setEditable(false); + txt.setLayoutData(CmsUiUtils.fillWidth()); + return txt; + } + + public static Text addFormColumn(Composite parent, String label, Node node, String property, + CmsEditable cmsEditable) { +// Composite columnComposite = new Composite(parent, SWT.NONE); +// columnComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); +// columnComposite.setLayout(new GridLayout(1, false)); + addFormLabel(parent, label); + String text = Jcr.get(node, property); +// int style = cmsEditable.isEditing() ? SWT.WRAP : SWT.WRAP; + Text txt = addFormTextField(parent, text, null, SWT.WRAP); + if (cmsEditable != null && cmsEditable.isEditing()) { + txt.addModifyListener((e) -> { + Jcr.set(node, property, txt.getText()); + Jcr.save(node); + }); + } else { + txt.setEditable(false); + } + txt.setLayoutData(CmsUiUtils.fillWidth()); + return txt; + } + + public static Label createBoldLabel(Composite parent, Localized localized) { + Label label = new Label(parent, SWT.LEAD); + label.setText(localized.lead()); + label.setFont(EclipseUiUtils.getBoldFont(parent)); + label.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); + return label; + } + + public static Label addFormPicture(Composite parent, String label, Node fileNode) throws RepositoryException { + Composite lineComposite = new Composite(parent, SWT.NONE); + lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + lineComposite.setLayout(new GridLayout(2, true)); + CmsUiUtils.style(lineComposite, SuiteStyle.formLine); + addFormLabel(lineComposite, label); + + return addPicture(lineComposite, fileNode); + } + + public static Label addPicture(Composite parent, Node fileNode) throws RepositoryException { + return addPicture(parent, fileNode, null); + } + + public static Label addPicture(Composite parent, Node fileNode, Integer maxWidth) throws RepositoryException { + Node content = fileNode.getNode(Node.JCR_CONTENT); + // TODO move it deeper in the middleware. + if (!content.isNodeType(EntityType.box.get())) { + if (content.getSession().hasPermission(content.getPath(), Session.ACTION_SET_PROPERTY)) { + try (InputStream in = JcrUtils.getFileAsStream(fileNode)) { + ImageData imageData = new ImageData(in); + content.addMixin(EntityType.box.get()); + content.setProperty(EntityNames.SVG_WIDTH, imageData.width); + content.setProperty(EntityNames.SVG_HEIGHT, imageData.height); + content.getSession().save(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + // TODO optimise + Long width; + Long height; + if (content.isNodeType(EntityType.box.get())) { + width = content.getProperty(EntityNames.SVG_WIDTH).getLong(); + height = content.getProperty(EntityNames.SVG_HEIGHT).getLong(); + } else { + try (InputStream in = JcrUtils.getFileAsStream(fileNode)) { + ImageData imageData = new ImageData(in); + width = Long.valueOf(imageData.width); + height = Long.valueOf(imageData.height); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + if (maxWidth != null && width > maxWidth) { + Double ratio = maxWidth.doubleValue() / width.doubleValue(); + width = maxWidth.longValue(); + height = Math.round(ratio * height); + } + Label img = new Label(parent, SWT.NONE); + CmsUiUtils.markup(img); + img.setText(CmsUiUtils.img(fileNode, width.toString(), height.toString())); + if (parent.getLayout() instanceof GridLayout) { + GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); + gd.widthHint = width.intValue(); + gd.heightHint = height.intValue(); + img.setLayoutData(gd); + } + img.addMouseListener(new MouseListener() { + private static final long serialVersionUID = -1362242049325206168L; + + @Override + public void mouseUp(MouseEvent e) { + } + + @Override + public void mouseDown(MouseEvent e) { + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + LightweightDialog dialog = new LightweightDialog(img.getShell()) { + + @Override + protected Control createDialogArea(Composite parent) { + parent.setLayout(new GridLayout()); + ScrolledComposite scroll = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL); + scroll.setLayoutData(CmsUiUtils.fillAll()); + scroll.setLayout(CmsUiUtils.noSpaceGridLayout()); + scroll.setExpandHorizontal(true); + scroll.setExpandVertical(true); + // scroll.setAlwaysShowScrollBars(true); + + Composite c = new Composite(scroll, SWT.NONE); + scroll.setContent(c); + c.setLayout(new GridLayout()); + c.setLayoutData(CmsUiUtils.fillAll()); + Label bigImg = new Label(c, SWT.NONE); + CmsUiUtils.markup(bigImg); + bigImg.setText(CmsUiUtils.img(fileNode, Jcr.get(content, EntityNames.SVG_WIDTH), + Jcr.get(content, EntityNames.SVG_HEIGHT))); + bigImg.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); + return bigImg; + } + + @Override + protected Point getInitialSize() { + Point shellSize = img.getShell().getSize(); + return new Point(shellSize.x - 100, shellSize.y - 100); + } + + }; + dialog.open(); + } + }); + return img; + } + + public static Button createLayerButton(Composite parent, String layer, Localized msg, CmsIcon icon) { + CmsTheme theme = CmsTheme.getCmsTheme(parent); + Button button = new Button(parent, SWT.PUSH); + CmsUiUtils.style(button, SuiteStyle.leadPane); + if (icon != null) + button.setImage(icon.getBigIcon(theme)); + button.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, false)); + // button.setToolTipText(msg.lead()); + if (msg != null) { + Label lbl = new Label(parent, SWT.NONE); + CmsUiUtils.style(lbl, SuiteStyle.leadPane); + lbl.setText(msg.lead()); + lbl.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false)); + } + CmsUiUtils.sendEventOnSelect(button, SuiteEvent.switchLayer.topic(), SuiteEvent.LAYER, layer); + return button; + } + +// public static String createAndConfigureEntity(Shell shell, Session referenceSession, String mainMixin, +// String... additionnalProps) { +// +// Session tmpSession = null; +// Session mainSession = null; +// try { +// // FIXME would not work if home is another physical workspace +// tmpSession = referenceSession.getRepository().login(NodeConstants.HOME_WORKSPACE); +// Node draftNode = null; +// for (int i = 0; i < additionnalProps.length - 1; i += 2) { +// draftNode.setProperty(additionnalProps[i], additionnalProps[i + 1]); +// } +// Wizard wizard = null; +// CmsWizardDialog dialog = new CmsWizardDialog(shell, wizard); +// // WizardDialog dialog = new WizardDialog(shell, wizard); +// if (dialog.open() == Window.OK) { +// String parentPath = null;// "/" + appService.getBaseRelPath(mainMixin); +// // FIXME it should be possible to specify the workspace +// mainSession = referenceSession.getRepository().login(); +// Node parent = mainSession.getNode(parentPath); +// Node task = null;// appService.publishEntity(parent, mainMixin, draftNode); +//// task = appService.saveEntity(task, false); +// referenceSession.refresh(true); +// return task.getPath(); +// } +// return null; +// } catch (RepositoryException e1) { +// throw new JcrException( +// "Unable to create " + mainMixin + " entity with session " + referenceSession.toString(), e1); +// } finally { +// JcrUtils.logoutQuietly(tmpSession); +// JcrUtils.logoutQuietly(mainSession); +// } +// } + +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java new file mode 100644 index 0000000..04d7a7b --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java @@ -0,0 +1,86 @@ +package org.argeo.suite.ui; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.cms.ui.viewers.Section; +import org.argeo.naming.LdapAttrs; +import org.eclipse.swt.SWT; +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.Group; +import org.eclipse.swt.widgets.Text; +import org.osgi.service.useradmin.User; + +/** Edit a suite user. */ +public class SuiteUserUiProvider implements CmsUiProvider { + private String[] availableRoles; + private CmsUserManager cmsUserManager; + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + Section main = new Section(parent, SWT.NONE, context); + main.setLayoutData(CmsUiUtils.fillAll()); + + String uid = context.getName(); + User user = cmsUserManager.getUserFromLocalId(uid); + +// Text givenName = new Text(main, SWT.SINGLE); +// givenName.setText(getUserProperty(user, LdapAttrs.givenName.name())); + Text givenName = SuiteUiUtils.addFormInput(main, SuiteMsg.firstName.lead(), + getUserProperty(user, LdapAttrs.givenName.name())); + + Text sn = SuiteUiUtils.addFormInput(main, SuiteMsg.lastName.lead(), getUserProperty(user, LdapAttrs.sn.name())); + // sn.setText(getUserProperty(user, LdapAttrs.sn.name())); + + Text email = SuiteUiUtils.addFormInput(main, SuiteMsg.email.lead(), + getUserProperty(user, LdapAttrs.mail.name())); + // email.setText(getUserProperty(user, LdapAttrs.mail.name())); + + Text uidT = SuiteUiUtils.addFormLine(main, "uid", getUserProperty(user, LdapAttrs.uid.name())); + uidT.setText(uid); + +// Label dnL = new Label(main, SWT.NONE); +// dnL.setText(user.getName()); + + // roles + // Section rolesSection = new Section(main, SWT.NONE, context); + Group rolesSection = new Group(main, SWT.NONE); + rolesSection.setText("Roles"); + rolesSection.setLayoutData(CmsUiUtils.fillWidth()); + rolesSection.setLayout(new GridLayout()); + // new Label(rolesSection, SWT.NONE).setText("Roles:"); + List roles = Arrays.asList(cmsUserManager.getUserRoles(user.getName())); + for (String role : availableRoles) { + // new Label(rolesSection, SWT.NONE).setText(role); + Button radio = new Button(rolesSection, SWT.CHECK); + radio.setText(role); + if (roles.contains(role)) + radio.setSelection(true); + } + + return main; + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; + } + + public void init(Map properties) { + availableRoles = (String[]) properties.get("availableRoles"); + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonPage.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonPage.java new file mode 100644 index 0000000..ddd4488 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonPage.java @@ -0,0 +1,72 @@ +package org.argeo.suite.ui.dialogs; + +import org.argeo.suite.ui.SuiteMsg; +import org.argeo.suite.ui.SuiteUiUtils; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +public class NewPersonPage extends WizardPage { + private static final long serialVersionUID = -944349994177526468L; + protected Text lastNameTxt; + protected Text firstNameTxt; + protected Text emailTxt; + + protected NewPersonPage(String pageName) { + super(pageName); + setTitle(SuiteMsg.personWizardPageTitle.lead()); + } + + @Override + public void createControl(Composite parent) { + parent.setLayout(new GridLayout(2, false)); + + // FirstName + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName); + firstNameTxt = new Text(parent, SWT.BORDER); + firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // LastName + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName); + lastNameTxt = new Text(parent, SWT.BORDER); + lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.email); + emailTxt = new Text(parent, SWT.BORDER); + emailTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + ModifyListener ml = new ModifyListener() { + private static final long serialVersionUID = -1628130380128946886L; + + @Override + public void modifyText(ModifyEvent event) { + getContainer().updateButtons(); + } + }; + + firstNameTxt.addModifyListener(ml); + lastNameTxt.addModifyListener(ml); + emailTxt.addModifyListener(ml); + + // Don't forget this. + setControl(firstNameTxt); + firstNameTxt.setFocus(); + + } + +// public void updateNode(Node node, PeopleService peopleService, ResourcesService resourcesService) { +// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_LAST_NAME, PropertyType.STRING, lastNameTxt.getText()); +// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_FIRST_NAME, PropertyType.STRING, +// firstNameTxt.getText()); +// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_DISPLAY_NAME, PropertyType.STRING, +// firstNameTxt.getText() + " " + lastNameTxt.getText()); +// String email = emailTxt.getText(); +// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_PRIMARY_EMAIL, PropertyType.STRING, email); +// PeopleJcrUtils.createEmail(resourcesService, peopleService, node, email, true, null, null); +// } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonWizard.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonWizard.java new file mode 100644 index 0000000..9db5e04 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonWizard.java @@ -0,0 +1,151 @@ +package org.argeo.suite.ui.dialogs; + +import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty; + +import javax.jcr.Node; + +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.suite.ui.SuiteMsg; +import org.argeo.suite.ui.SuiteUiUtils; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +/** Ask first & last name. Update the passed node on finish */ +public class NewPersonWizard extends Wizard { + // private final static Log log = LogFactory.getLog(NewPersonWizard.class); + + // Context + private Node person; + + // This page widgets + protected Text lastNameTxt; + protected Text firstNameTxt; + // private Button useDistinctDisplayNameBtn; + // private Text displayNameTxt; + + public NewPersonWizard(Node person) { + this.person = person; + } + + @Override + public void addPages() { + try { + MainInfoPage page = new MainInfoPage("Main page"); + addPage(page); + } catch (Exception e) { + throw new RuntimeException("Cannot add page to wizard", e); + } + setWindowTitle(SuiteMsg.personWizardWindowTitle.lead()); + } + + /** + * Called when the user click on 'Finish' in the wizard. The task is then + * created and the corresponding session saved. + */ + @Override + public boolean performFinish() { + String lastName = lastNameTxt.getText(); + String firstName = firstNameTxt.getText(); + // String displayName = displayNameTxt.getText(); + // boolean useDistinct = useDistinctDisplayNameBtn.getSelection(); + if (EclipseUiUtils.isEmpty(lastName) && EclipseUiUtils.isEmpty(firstName)) { + MessageDialog.openError(getShell(), "Non-valid information", + "Please enter at least a name that is not empty."); + return false; + } else { +// ConnectJcrUtils.setJcrProperty(person, PEOPLE_LAST_NAME, PropertyType.STRING, lastName); +// ConnectJcrUtils.setJcrProperty(person, PEOPLE_FIRST_NAME, PropertyType.STRING, firstName); +// String fullName = firstName + " " + lastName; +// ConnectJcrUtils.setJcrProperty(person, PEOPLE_DISPLAY_NAME, PropertyType.STRING, fullName); + return true; + } + } + + @Override + public boolean performCancel() { + return true; + } + + @Override + public boolean canFinish() { + String lastName = lastNameTxt.getText(); + String firstName = firstNameTxt.getText(); + if (isEmpty(lastName) && isEmpty(firstName)) { + return false; + } else + return true; + } + + protected class MainInfoPage extends WizardPage { + private static final long serialVersionUID = 1L; + + public MainInfoPage(String pageName) { + super(pageName); + setTitle(SuiteMsg.personWizardPageTitle.lead()); + // setMessage("Please enter a last name and/or a first name."); + } + + public void createControl(Composite parent) { + parent.setLayout(new GridLayout(2, false)); + + // FirstName + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName); + firstNameTxt = new Text(parent, SWT.BORDER); + // firstNameTxt.setMessage("a first name"); + firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // LastName + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName); + lastNameTxt = new Text(parent, SWT.BORDER); + // lastNameTxt.setMessage("a last name"); + lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // Display Name + // useDistinctDisplayNameBtn = new Button(parent, SWT.CHECK); + // useDistinctDisplayNameBtn.setText("Define a disting display name"); + // useDistinctDisplayNameBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, + // true, false, 2, 1)); + // + // ConnectWorkbenchUtils.createBoldLabel(parent, "Display Name"); + // displayNameTxt = new Text(parent, SWT.BORDER); + // displayNameTxt.setMessage("an optional display name"); + // displayNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, + // false)); + // displayNameTxt.setEnabled(false); + // + // useDistinctDisplayNameBtn.addSelectionListener(new SelectionAdapter() { + // private static final long serialVersionUID = 1L; + // + // @Override + // public void widgetSelected(SelectionEvent e) { + // displayNameTxt.setEnabled(useDistinctDisplayNameBtn.getSelection()); + // } + // }); + + ModifyListener ml = new ModifyListener() { + private static final long serialVersionUID = -1628130380128946886L; + + @Override + public void modifyText(ModifyEvent event) { + getContainer().updateButtons(); + } + }; + + firstNameTxt.addModifyListener(ml); + lastNameTxt.addModifyListener(ml); + // displayNameTxt.addModifyListener(ml); + + // Don't forget this. + setControl(firstNameTxt); + firstNameTxt.setFocus(); + } + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewUserWizard.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewUserWizard.java new file mode 100644 index 0000000..5b4575d --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewUserWizard.java @@ -0,0 +1,151 @@ +package org.argeo.suite.ui.dialogs; + +import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty; + +import javax.jcr.Node; + +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.suite.ui.SuiteMsg; +import org.argeo.suite.ui.SuiteUiUtils; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +/** Ask first & last name. Update the passed node on finish */ +public class NewUserWizard extends Wizard { + // private final static Log log = LogFactory.getLog(NewPersonWizard.class); + + // Context + private Node person; + + // This page widgets + protected Text lastNameTxt; + protected Text firstNameTxt; + // private Button useDistinctDisplayNameBtn; + // private Text displayNameTxt; + + public NewUserWizard(Node person) { + this.person = person; + } + + @Override + public void addPages() { + try { + MainInfoPage page = new MainInfoPage("Main page"); + addPage(page); + } catch (Exception e) { + throw new RuntimeException("Cannot add page to wizard", e); + } + setWindowTitle(SuiteMsg.personWizardWindowTitle.lead()); + } + + /** + * Called when the user click on 'Finish' in the wizard. The task is then + * created and the corresponding session saved. + */ + @Override + public boolean performFinish() { + String lastName = lastNameTxt.getText(); + String firstName = firstNameTxt.getText(); + // String displayName = displayNameTxt.getText(); + // boolean useDistinct = useDistinctDisplayNameBtn.getSelection(); + if (EclipseUiUtils.isEmpty(lastName) && EclipseUiUtils.isEmpty(firstName)) { + MessageDialog.openError(getShell(), "Non-valid information", + "Please enter at least a name that is not empty."); + return false; + } else { +// ConnectJcrUtils.setJcrProperty(person, PEOPLE_LAST_NAME, PropertyType.STRING, lastName); +// ConnectJcrUtils.setJcrProperty(person, PEOPLE_FIRST_NAME, PropertyType.STRING, firstName); +// String fullName = firstName + " " + lastName; +// ConnectJcrUtils.setJcrProperty(person, PEOPLE_DISPLAY_NAME, PropertyType.STRING, fullName); + return true; + } + } + + @Override + public boolean performCancel() { + return true; + } + + @Override + public boolean canFinish() { + String lastName = lastNameTxt.getText(); + String firstName = firstNameTxt.getText(); + if (isEmpty(lastName) && isEmpty(firstName)) { + return false; + } else + return true; + } + + protected class MainInfoPage extends WizardPage { + private static final long serialVersionUID = 1L; + + public MainInfoPage(String pageName) { + super(pageName); + setTitle(SuiteMsg.personWizardPageTitle.lead()); + // setMessage("Please enter a last name and/or a first name."); + } + + public void createControl(Composite parent) { + parent.setLayout(new GridLayout(2, false)); + + // FirstName + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName); + firstNameTxt = new Text(parent, SWT.BORDER); + // firstNameTxt.setMessage("a first name"); + firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // LastName + SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName); + lastNameTxt = new Text(parent, SWT.BORDER); + // lastNameTxt.setMessage("a last name"); + lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // Display Name + // useDistinctDisplayNameBtn = new Button(parent, SWT.CHECK); + // useDistinctDisplayNameBtn.setText("Define a disting display name"); + // useDistinctDisplayNameBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, + // true, false, 2, 1)); + // + // ConnectWorkbenchUtils.createBoldLabel(parent, "Display Name"); + // displayNameTxt = new Text(parent, SWT.BORDER); + // displayNameTxt.setMessage("an optional display name"); + // displayNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, + // false)); + // displayNameTxt.setEnabled(false); + // + // useDistinctDisplayNameBtn.addSelectionListener(new SelectionAdapter() { + // private static final long serialVersionUID = 1L; + // + // @Override + // public void widgetSelected(SelectionEvent e) { + // displayNameTxt.setEnabled(useDistinctDisplayNameBtn.getSelection()); + // } + // }); + + ModifyListener ml = new ModifyListener() { + private static final long serialVersionUID = -1628130380128946886L; + + @Override + public void modifyText(ModifyEvent event) { + getContainer().updateButtons(); + } + }; + + firstNameTxt.addModifyListener(ml); + lastNameTxt.addModifyListener(ml); + // displayNameTxt.addModifyListener(ml); + + // Don't forget this. + setControl(firstNameTxt); + firstNameTxt.setFocus(); + } + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/AbstractConnectContextMenu.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/AbstractConnectContextMenu.java new file mode 100644 index 0000000..07f9cee --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/AbstractConnectContextMenu.java @@ -0,0 +1,133 @@ +package org.argeo.suite.ui.widgets; + +import java.util.HashMap; +import java.util.Map; + +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +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; + +/** + * Generic popup context menu for TableViewer to enable single sourcing between + * CMS and Workbench + */ +public abstract class AbstractConnectContextMenu { + + private Shell parentShell; + private Shell shell; + // Local context + + private final static String KEY_ACTION_ID = "actionId"; + private final String[] defaultActions; + private Map actionButtons = new HashMap(); + + public AbstractConnectContextMenu(Display display, String[] defaultActions) { + parentShell = display.getActiveShell(); + shell = new Shell(parentShell, SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); + this.defaultActions = defaultActions; + } + + protected void createControl() { + shell.setLayout(EclipseUiUtils.noSpaceGridLayout()); + Composite boxCmp = new Composite(shell, SWT.NO_FOCUS | SWT.BORDER); + boxCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); +// CmsUiUtils.style(boxCmp, ConnectUiStyles.CONTEXT_MENU_BOX); + createContextMenu(boxCmp); + shell.addShellListener(new ActionsShellListener()); + } + + protected void createContextMenu(Composite boxCmp) { + ActionsSelListener asl = new ActionsSelListener(); + for (String actionId : defaultActions) { + Button btn = new Button(boxCmp, SWT.FLAT | SWT.LEAD); + btn.setText(getLabel(actionId)); + btn.setLayoutData(EclipseUiUtils.fillWidth()); + CmsUiUtils.markup(btn); +// CmsUiUtils.style(btn, actionId + ConnectUiStyles.BUTTON_SUFFIX); + btn.setData(KEY_ACTION_ID, actionId); + btn.addSelectionListener(asl); + actionButtons.put(actionId, btn); + } + } + + protected void setVisible(boolean visible, String... buttonIds) { + for (String id : buttonIds) { + Button button = actionButtons.get(id); + button.setVisible(visible); + GridData gd = (GridData) button.getLayoutData(); + gd.heightHint = visible ? SWT.DEFAULT : 0; + } + } + + public void show(Control source, Point location, IStructuredSelection selection) { + if (shell.isDisposed()) { + shell = new Shell(Display.getCurrent(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); + createControl(); + } + if (shell.isVisible()) + shell.setVisible(false); + + if (aboutToShow(source, location, selection)) { + shell.pack(); + shell.layout(); + if (source instanceof Control) + shell.setLocation(((Control) source).toDisplay(location.x, location.y)); + shell.open(); + } + } + + protected Shell getParentShell() { + return parentShell; + } + + class StyleButton extends Label { + private static final long serialVersionUID = 7731102609123946115L; + + public StyleButton(Composite parent, int swtStyle) { + super(parent, swtStyle); + } + } + + class ActionsSelListener extends SelectionAdapter { + private static final long serialVersionUID = -1041871937815812149L; + + @Override + public void widgetSelected(SelectionEvent e) { + Object eventSource = e.getSource(); + if (eventSource instanceof Button) { + Button pressedBtn = (Button) eventSource; + performAction((String) pressedBtn.getData(KEY_ACTION_ID)); + shell.close(); + } + } + } + + class ActionsShellListener extends org.eclipse.swt.events.ShellAdapter { + private static final long serialVersionUID = -5092341449523150827L; + + @Override + public void shellDeactivated(ShellEvent e) { + setVisible(false); + shell.setVisible(false); + //shell.close(); + } + } + + protected abstract boolean performAction(String actionId); + + protected abstract boolean aboutToShow(Control source, Point location, IStructuredSelection selection); + + protected abstract String getLabel(String actionId); +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/ConnectAbstractDropDown.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/ConnectAbstractDropDown.java new file mode 100644 index 0000000..ffe733e --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/ConnectAbstractDropDown.java @@ -0,0 +1,194 @@ +package org.argeo.suite.ui.widgets; + +import java.util.Arrays; +import java.util.List; + +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.eclipse.rap.rwt.widgets.DropDown; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; + +/** + * Enable easy addition of a {@code DropDown} widget to a text with listeners + * configured + */ +public abstract class ConnectAbstractDropDown { + + private final Text text; + private final DropDown dropDown; + private boolean modifyFromList = false; + + // Current displayed text + private String userText = ""; + // Current displayed list items + private String[] values; + + // Fine tuning + boolean readOnly; + boolean refreshOnFocus; + + /** Implementing classes should call refreshValues() after initialisation */ + public ConnectAbstractDropDown(Text text) { + this(text, SWT.NONE, false); + } + + /** + * Implementing classes should call refreshValues() after initialisation + * + * @param text + * @param style + * only SWT.READ_ONLY is understood, check if the entered text is + * part of the legal choices. + */ + public ConnectAbstractDropDown(Text text, int style) { + this(text, style, false); + } + + /** + * Implementers should call refreshValues() once init has been done. + * + * @param text + * @param style + * only SWT.READ_ONLY is understood, check if the entered text is + * part of the legal choices. + * @param refreshOnFocus + * if true, the possible values are computed each time the focus is + * gained. It enables, among other to fine tune the getFilteredValues + * method depending on the current context + */ + public ConnectAbstractDropDown(Text text, int style, boolean refreshOnFocus) { + this.text = text; + dropDown = new DropDown(text); + Object obj = dropDown; + if (obj instanceof Widget) + CmsUiUtils.markup((Widget) obj); + readOnly = (style & SWT.READ_ONLY) != 0; + this.refreshOnFocus = refreshOnFocus; + addListeners(); + } + + /** + * Overwrite to force the refresh of the possible values on focus gained event + */ + protected boolean refreshOnFocus() { + return refreshOnFocus; + } + + public String getText() { + return text.getText(); + } + + public void init() { + refreshValues(); + } + + public void reset(String value) { + modifyFromList = true; + if (EclipseUiUtils.notEmpty(value)) + text.setText(value); + else + text.setText(""); + refreshValues(); + modifyFromList = false; + } + + /** Overwrite to provide specific filtering */ + protected abstract List getFilteredValues(String filter); + + protected void refreshValues() { + List filteredValues = getFilteredValues(text.getText()); + values = filteredValues.toArray(new String[filteredValues.size()]); + dropDown.setItems(values); + } + + protected void addListeners() { + addModifyListener(); + addSelectionListener(); + addDefaultSelectionListener(); + addFocusListener(); + } + + protected void addFocusListener() { + text.addFocusListener(new FocusListener() { + private static final long serialVersionUID = -7179112097626535946L; + + public void focusGained(FocusEvent event) { + if (refreshOnFocus) { + modifyFromList = true; + refreshValues(); + modifyFromList = false; + } + dropDown.setVisible(true); + } + + public void focusLost(FocusEvent event) { + dropDown.setVisible(false); + if (readOnly && values != null && !Arrays.asList(values).contains(userText)) { + modifyFromList = true; + text.setText(""); + refreshValues(); + modifyFromList = false; + } + } + }); + } + + private void addSelectionListener() { + Object obj = dropDown; + if (obj instanceof Widget) + ((Widget) obj).addListener(SWT.Selection, new Listener() { + private static final long serialVersionUID = -2357157809365135142L; + + public void handleEvent(Event event) { + if (event.index != -1) { + modifyFromList = true; + text.setText(values[event.index]); + modifyFromList = false; + text.selectAll(); + } else { + text.setText(userText); + text.setSelection(userText.length(), userText.length()); + text.setFocus(); + } + } + }); + } + + private void addDefaultSelectionListener() { + Object obj = dropDown; + if (obj instanceof Widget) + ((Widget) obj).addListener(SWT.DefaultSelection, new Listener() { + private static final long serialVersionUID = -5958008322630466068L; + + public void handleEvent(Event event) { + if (event.index != -1) { + text.setText(values[event.index]); + text.setSelection(event.text.length()); + dropDown.setVisible(false); + } + } + }); + } + + private void addModifyListener() { + text.addListener(SWT.Modify, new Listener() { + private static final long serialVersionUID = -4373972835244263346L; + + public void handleEvent(Event event) { + if (!modifyFromList) { + userText = text.getText(); + refreshValues(); + if (values.length == 1) + dropDown.setSelectionIndex(0); + dropDown.setVisible(true); + } + } + }); + } +} diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java new file mode 100644 index 0000000..a03c250 --- /dev/null +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java @@ -0,0 +1,127 @@ +package org.argeo.suite.ui.widgets; + +import java.util.Timer; +import java.util.TimerTask; + +import org.eclipse.rap.rwt.service.ServerPushSession; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Text; + +/** + * Text that introduce a timer in the attached ModifyListener. + * + * Note that corresponding ModifyEvent will *NOT* be sent in the UI thread. + * Calling ModifierInstance must be implemented in consequence. Note also that + * this delayed text only manages one listener at a time. + * + */ +public class DelayedText { + final int delay; + private Object lock = new Object(); + private MyTimer timer = new MyTimer(DelayedText.this.toString()); + private ModifyListener delayedModifyListener; + private ServerPushSession pushSession; + + private Text text; + + private ModifyListener modifyListener = new ModifyListener() { + private static final long serialVersionUID = 1117506414462641980L; + + public void modifyText(ModifyEvent e) { + ModifyEvent delayedEvent = null; + synchronized (lock) { + if (delayedModifyListener != null) { + Event tmpEvent = new Event(); + tmpEvent.widget = text; + tmpEvent.display = e.display; + tmpEvent.data = e.data; + tmpEvent.time = e.time; + delayedEvent = new ModifyEvent(tmpEvent); + } + } + final ModifyEvent timerModifyEvent = delayedEvent; + + synchronized (timer) { + if (timer.timerTask != null) { + timer.timerTask.cancel(); + timer.timerTask = null; + } + + if (delayedEvent != null) { + timer.timerTask = new TimerTask() { + public void run() { + synchronized (lock) { + delayedModifyListener.modifyText(timerModifyEvent); + // Bad approach: it is not a good idea to put a + // display.asyncExec in a lock... + // DelayedText.this.getDisplay().asyncExec(new + // Runnable() { + // @Override + // public void run() { + // delayedModifyListener.modifyText(timerModifyEvent); + // } + // } + // ); + } + synchronized (timer) { + timer.timerTask = null; + } + } + }; + timer.schedule(timer.timerTask, delay); + if (pushSession != null) + pushSession.start(); + } + } + }; + }; + + public DelayedText(Composite parent, int style, int delayInMs) { + // super(parent, style); + text = new Text(parent, style); + this.delay = delayInMs; + text.addModifyListener(modifyListener); + } + + /** + * Adds a modify text listener that will be delayed. If another Modify event + * happens during the waiting delay, the older event will be canceled an a new + * one will be scheduled after another new delay. + */ + public void addDelayedModifyListener(ServerPushSession pushSession, ModifyListener listener) { + synchronized (lock) { + delayedModifyListener = listener; + this.pushSession = pushSession; + } + } + + public void removeDelayedModifyListener(ModifyListener listener) { + synchronized (lock) { + delayedModifyListener = null; + pushSession = null; + } + } + + private class MyTimer extends Timer { + private TimerTask timerTask = null; + + public MyTimer(String name) { + super(name); + } + } + + public Text getText() { + return text; + } + + public void close() { + if (pushSession != null) + pushSession.stop(); + if (timer != null) + timer.cancel(); + }; + +} diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..c26b10f --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + org.argeo.suite + argeo-suite + 2.1.18-SNAPSHOT + .. + + core + Argeo Core Components + pom + + + org.argeo.entity.api + org.argeo.entity.core + org.argeo.entity.ui + + + org.argeo.suite.core + org.argeo.suite.ui + org.argeo.suite.ui.rap + org.argeo.suite.theme.default + + diff --git a/org.argeo.entity.api/.classpath b/org.argeo.entity.api/.classpath deleted file mode 100644 index e801ebf..0000000 --- a/org.argeo.entity.api/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.entity.api/.gitignore b/org.argeo.entity.api/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.entity.api/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.entity.api/.project b/org.argeo.entity.api/.project deleted file mode 100644 index 1269cce..0000000 --- a/org.argeo.entity.api/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.entity.api - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.argeo.entity.api/META-INF/.gitignore b/org.argeo.entity.api/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.entity.api/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.entity.api/bnd.bnd b/org.argeo.entity.api/bnd.bnd deleted file mode 100644 index ab46172..0000000 --- a/org.argeo.entity.api/bnd.bnd +++ /dev/null @@ -1,5 +0,0 @@ -Require-Capability:\ -cms.datamodel;filter:="(name=jcrx)" - -Provide-Capability:\ -cms.datamodel; name=entity; cnd=/org/argeo/entity/entity.cnd diff --git a/org.argeo.entity.api/build.properties b/org.argeo.entity.api/build.properties deleted file mode 100644 index 34d2e4d..0000000 --- a/org.argeo.entity.api/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - . diff --git a/org.argeo.entity.api/pom.xml b/org.argeo.entity.api/pom.xml deleted file mode 100644 index 8627265..0000000 --- a/org.argeo.entity.api/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.entity.api - Entity API - jar - - - - org.argeo.commons - org.argeo.enterprise - ${version.argeo-commons} - - - diff --git a/org.argeo.entity.api/src/org/argeo/entity/EntityConstants.java b/org.argeo.entity.api/src/org/argeo/entity/EntityConstants.java deleted file mode 100644 index f7a2de8..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/EntityConstants.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.entity; - -/** Constant related to entities, typically used in an OSGi context. */ -public interface EntityConstants { - final static String TYPE = "entity.type"; - final static String DEFAULT_EDITORY_ID = "entity.defaultEditorId"; - -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/EntityDefinition.java b/org.argeo.entity.api/src/org/argeo/entity/EntityDefinition.java deleted file mode 100644 index 08aff61..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/EntityDefinition.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.argeo.entity; - -import javax.jcr.Node; - -/** The definition of an entity, a composite configurable data structure. */ -public interface EntityDefinition { - String getEditorId(Node entity); - - String getType(); -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/EntityNames.java b/org.argeo.entity.api/src/org/argeo/entity/EntityNames.java deleted file mode 100644 index ede7447..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/EntityNames.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.argeo.entity; - -import org.argeo.naming.LdapAttrs; - -/** Constants used to name entity structures. */ -public interface EntityNames { - @Deprecated - final String FORM_BASE = "form"; - final String SUBMISSIONS_BASE = "submissions"; - @Deprecated - final String TERM = "term"; - final String NAME = "name"; - -// final String ENTITY_DEFINITIONS_PATH = "/entity"; - @Deprecated - final String TYPOLOGIES_PATH = "/" + TERM; - /** Administrative units. */ - final String ADM = "adm"; - - final String ENTITY_TYPE = "entity:type"; - // final String ENTITY_UID = "entity:uid"; - // final String ENTITY_NAME = "entity:name"; - - // GENERIC CONCEPTS - /** The language which is relevant. */ - final String XML_LANG = "xml:lang"; - /** The date which is relevant. */ - final String ENTITY_DATE = "entity:date"; - @Deprecated - final String ENTITY_RELATED_TO = "entity:relatedTo"; - - // DEFAULT FOLDER NAMES - final String MEDIA = "media"; - final String FILES = "files"; - - // LDAP-LIKE ENTITIES - @Deprecated - final String DISPLAY_NAME = LdapAttrs.displayName.property(); - // Persons - @Deprecated - final String GIVEN_NAME = LdapAttrs.givenName.property(); - @Deprecated - final String SURNAME = LdapAttrs.sn.property(); - @Deprecated - final String EMAIL = LdapAttrs.mail.property(); - @Deprecated - final String OU = LdapAttrs.ou.property(); - - // WGS84 - final String GEO_LAT = "geo:lat"; - final String GEO_LONG = "geo:long"; - final String GEO_ALT = "geo:alt"; - - // SVG - final String SVG_WIDTH = "svg:width"; - final String SVG_HEIGHT = "svg:height"; - final String SVG_LENGTH = "svg:length"; - final String SVG_UNIT = "svg:unit"; - final String SVG_DUR = "svg:dur"; - final String SVG_DIRECTION = "svg:direction"; -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/EntityType.java b/org.argeo.entity.api/src/org/argeo/entity/EntityType.java deleted file mode 100644 index ecd6330..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/EntityType.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.argeo.entity; - -/** Types related to entities. */ -public enum EntityType implements JcrName { - // entity - entity, local, relatedTo, - // typology - typologies, terms, term, - // form - form, formSet, formSubmission, - // graphics - box, - // geography - geopoint, bearing, - // ldap - person, user; - - @Override - public String getPrefix() { - return prefix(); - } - - public static String prefix() { - return "entity"; - } - - public String basePath() { - return '/' + name(); - } - - @Override - public String getNamespace() { - return namespace(); - } - - public static String namespace() { - return "http://www.argeo.org/ns/entity"; - } - -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/EntityTypes.java b/org.argeo.entity.api/src/org/argeo/entity/EntityTypes.java deleted file mode 100644 index ef35147..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/EntityTypes.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.argeo.entity; - -/** Types related to entities. */ -@Deprecated -public interface EntityTypes { - final static String ENTITY_ENTITY = "entity:entity"; - final static String ENTITY_DEFINITION = "entity:definition"; - - final static String ENTITY_PERSON = "entity:person"; -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/JcrName.java b/org.argeo.entity.api/src/org/argeo/entity/JcrName.java deleted file mode 100644 index 322c42e..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/JcrName.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.argeo.entity; - -import java.util.function.Supplier; - -/** Can be applied to {@link Enum}s in order to generate prefixed names. */ -@FunctionalInterface -public interface JcrName extends Supplier { - String name(); - - default String getPrefix() { - return null; - } - - default String getNamespace() { - return null; - } - - @Override - default String get() { - String prefix = getPrefix(); - return prefix != null ? prefix + ":" + name() : name(); - } - - default String withNamespace() { - String namespace = getNamespace(); - if (namespace == null) - throw new UnsupportedOperationException("No namespace is specified for " + getClass()); - return "{" + namespace + "}" + name(); - } -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java b/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java deleted file mode 100644 index a2b5951..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.entity; - -import java.util.List; - -/** Provides optimised access and utilities around terms typologies. */ -public interface TermsManager { - List listAllTerms(String typology); -} diff --git a/org.argeo.entity.api/src/org/argeo/entity/entity.cnd b/org.argeo.entity.api/src/org/argeo/entity/entity.cnd deleted file mode 100644 index b30657d..0000000 --- a/org.argeo.entity.api/src/org/argeo/entity/entity.cnd +++ /dev/null @@ -1,99 +0,0 @@ -// Standard namespaces - - -// see https://www.w3.org/2003/01/geo/ - - - - - - -[entity:entity] > mix:created, mix:referenceable -mixin - -[entity:local] > entity:entity -mixin -- entity:type (String) m - -[entity:relatedTo] -mixin -+ entity:relatedTo (nt:address) * - -// -// ENTITY DEFINITION -// -//[entity:definition] > entity:composite, mix:created, mix:lastModified, mix:referenceable -//- entity:type (String) multiple - -//[entity:part] - -//[entity:reference] - -//[entity:composite] -//orderable -//+ * (entity:part) -//+ * (entity:reference) -//+ * (entity:composite) - -// -// TYPOLOGY -// -[entity:typologies] -+ * (entity:terms) = entity:terms - -[entity:term] -orderable -- name (NAME) m -- * (*) -+ term (entity:term) = entity:term * - -[entity:terms] > mix:referenceable -orderable -+ term (entity:term) = entity:term * - -// -// FORM -// -[entity:form] -mixin - -[entity:formSubmission] -mixin - -[entity:formSet] > mix:title -mixin - -// -// GRAPHICS -// -[entity:box] -mixin -- svg:width (DOUBLE) -- svg:height (DOUBLE) -- svg:length (DOUBLE) -- svg:unit (STRING) -- svg:dur (DOUBLE) - -// LDAP-LIKE ENTITIES -// A real person -[entity:person] > entity:entity -mixin -- ldap:sn (String) -- ldap:givenName (String) -- ldap:mail (String) * - -[entity:user] > entity:person -mixin -- ldap:distinguishedName (String) -- ldap:uid (String) - -// GEOGRAPHY -[entity:geopoint] -mixin -- geo:long (DOUBLE) -- geo:lat (DOUBLE) -- geo:alt (DOUBLE) - -[entity:bearing] -mixin -- svg:direction (DOUBLE) diff --git a/org.argeo.entity.core/.classpath b/org.argeo.entity.core/.classpath deleted file mode 100644 index e801ebf..0000000 --- a/org.argeo.entity.core/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.entity.core/.gitignore b/org.argeo.entity.core/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.entity.core/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.entity.core/.project b/org.argeo.entity.core/.project deleted file mode 100644 index 1acff84..0000000 --- a/org.argeo.entity.core/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.entity.core - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.argeo.entity.core/META-INF/.gitignore b/org.argeo.entity.core/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.entity.core/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.entity.core/bnd.bnd b/org.argeo.entity.core/bnd.bnd deleted file mode 100644 index e69de29..0000000 diff --git a/org.argeo.entity.core/build.properties b/org.argeo.entity.core/build.properties deleted file mode 100644 index 34d2e4d..0000000 --- a/org.argeo.entity.core/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - . diff --git a/org.argeo.entity.core/pom.xml b/org.argeo.entity.core/pom.xml deleted file mode 100644 index 089d049..0000000 --- a/org.argeo.entity.core/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.entity.core - Entity Reference Implementation - jar - - - org.argeo.suite - org.argeo.entity.api - 2.1.18-SNAPSHOT - - - - - org.argeo.commons - org.argeo.cms - ${version.argeo-commons} - - - diff --git a/org.argeo.entity.core/src/org/argeo/entity/core/JcrEntityDefinition.java b/org.argeo.entity.core/src/org/argeo/entity/core/JcrEntityDefinition.java deleted file mode 100644 index 7fd26d1..0000000 --- a/org.argeo.entity.core/src/org/argeo/entity/core/JcrEntityDefinition.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.argeo.entity.core; - -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.NodeUtils; -import org.argeo.entity.EntityConstants; -import org.argeo.entity.EntityDefinition; -import org.argeo.jcr.Jcr; -import org.osgi.framework.BundleContext; - -/** An entity definition based on a JCR data structure. */ -public class JcrEntityDefinition implements EntityDefinition { - private Repository repository; - - private String type; - private String defaultEditoryId; - - public void init(BundleContext bundleContext, Map properties) throws RepositoryException { - Session adminSession = NodeUtils.openDataAdminSession(repository, null); - try { - type = properties.get(EntityConstants.TYPE); - if (type == null) - throw new IllegalArgumentException("Entity type property " + EntityConstants.TYPE + " must be set."); - defaultEditoryId = properties.get(EntityConstants.DEFAULT_EDITORY_ID); -// String definitionPath = EntityNames.ENTITY_DEFINITIONS_PATH + '/' + type; -// if (!adminSession.itemExists(definitionPath)) { -// Node entityDefinition = JcrUtils.mkdirs(adminSession, definitionPath, EntityTypes.ENTITY_DEFINITION); -//// entityDefinition.addMixin(EntityTypes.ENTITY_DEFINITION); -// adminSession.save(); -// } - initJcr(adminSession); - } finally { - Jcr.logout(adminSession); - } - } - - /** To be overridden in order to perform additional initialisations. */ - protected void initJcr(Session adminSession) throws RepositoryException { - - } - - public void destroy(BundleContext bundleContext, Map properties) throws RepositoryException { - - } - - @Override - public String getEditorId(Node entity) { - return defaultEditoryId; - } - - @Override - public String getType() { - return type; - } - - protected Repository getRepository() { - return repository; - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - - public String toString() { - return "Entity Definition " + getType(); - } - -} diff --git a/org.argeo.entity.ui/.classpath b/org.argeo.entity.ui/.classpath deleted file mode 100644 index e801ebf..0000000 --- a/org.argeo.entity.ui/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.entity.ui/.gitignore b/org.argeo.entity.ui/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.entity.ui/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.entity.ui/.project b/org.argeo.entity.ui/.project deleted file mode 100644 index a1f7177..0000000 --- a/org.argeo.entity.ui/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - org.argeo.entity.ui - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.argeo.entity.ui/META-INF/.gitignore b/org.argeo.entity.ui/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.entity.ui/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.entity.ui/bnd.bnd b/org.argeo.entity.ui/bnd.bnd deleted file mode 100644 index e7cd4cb..0000000 --- a/org.argeo.entity.ui/bnd.bnd +++ /dev/null @@ -1,3 +0,0 @@ -Import-Package:\ -org.eclipse.swt,\ -* \ No newline at end of file diff --git a/org.argeo.entity.ui/build.properties b/org.argeo.entity.ui/build.properties deleted file mode 100644 index 34d2e4d..0000000 --- a/org.argeo.entity.ui/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - . diff --git a/org.argeo.entity.ui/pom.xml b/org.argeo.entity.ui/pom.xml deleted file mode 100644 index f2399cf..0000000 --- a/org.argeo.entity.ui/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.entity.ui - Entity UI - jar - - - org.argeo.suite - org.argeo.entity.core - 2.1.18-SNAPSHOT - - - - - org.argeo.commons - org.argeo.cms.ui - ${version.argeo-commons} - - - - - org.argeo.commons - org.argeo.eclipse.ui.rap - 2.1.91-SNAPSHOT - provided - - - - - org.argeo.tp - argeo-tp-rap-e4 - ${version.argeo-tp} - pom - provided - - - diff --git a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java b/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java deleted file mode 100644 index a7f240f..0000000 --- a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.argeo.entity.ui.forms; - -import javax.jcr.Item; - -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.util.CmsIcon; -import org.argeo.cms.ui.viewers.EditablePart; -import org.argeo.cms.ui.widgets.ContextOverlay; -import org.argeo.cms.ui.widgets.StyledControl; -import org.argeo.entity.TermsManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolItem; - -/** Common logic between single and mutliple terms editable part. */ -public abstract class AbstractTermsPart extends StyledControl implements EditablePart { - private static final long serialVersionUID = -5497097995341927710L; - protected final TermsManager termsManager; - protected final String typology; - - protected final boolean editable; - - private CmsIcon deleteIcon; - private CmsIcon addIcon; - private CmsIcon cancelIcon; - - private Color highlightColor; - private Composite highlight; - - protected final CmsTheme theme; - - public AbstractTermsPart(Composite parent, int style, Item item, TermsManager termsManager, - String typology) { - super(parent, style, item); - this.termsManager = termsManager; - this.typology = typology; - this.theme = CmsTheme.getCmsTheme(parent); - editable = !(SWT.READ_ONLY == (style & SWT.READ_ONLY)); - highlightColor = parent.getDisplay().getSystemColor(SWT.COLOR_GRAY); - } - - protected void createHighlight(Composite block) { - highlight = new Composite(block, SWT.NONE); - highlight.setBackground(highlightColor); - GridData highlightGd = new GridData(SWT.FILL, SWT.FILL, false, false); - highlightGd.widthHint = 5; - highlightGd.heightHint = 3; - highlight.setLayoutData(highlightGd); - - } - - protected String getTermLabel(String name) { - return name; - } - - protected abstract void refresh(ContextOverlay contextArea, String filter, Text txt); - - protected boolean isTermSelectable(String term) { - return true; - } - - protected void processTermListLabel(String term, Label label) { - - } - - // - // STYLING - // - public void setDeleteIcon(CmsIcon deleteIcon) { - this.deleteIcon = deleteIcon; - } - - public void setAddIcon(CmsIcon addIcon) { - this.addIcon = addIcon; - } - - public void setCancelIcon(CmsIcon cancelIcon) { - this.cancelIcon = cancelIcon; - } - - protected TermsManager getTermsManager() { - return termsManager; - } - - protected void styleDelete(ToolItem deleteItem) { - if (deleteIcon != null) - deleteItem.setImage(deleteIcon.getSmallIcon(theme)); - else - deleteItem.setText("-"); - } - - protected void styleCancel(ToolItem cancelItem) { - if (cancelIcon != null) - cancelItem.setImage(cancelIcon.getSmallIcon(theme)); - else - cancelItem.setText("X"); - } - - protected void styleAdd(ToolItem addItem) { - if (addIcon != null) - addItem.setImage(addIcon.getSmallIcon(theme)); - else - addItem.setText("+"); - } -} diff --git a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java b/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java deleted file mode 100644 index 1a12e90..0000000 --- a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.argeo.entity.ui.forms; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Item; - -import org.argeo.cms.ui.forms.FormStyle; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.cms.ui.viewers.EditablePart; -import org.argeo.cms.ui.widgets.ContextOverlay; -import org.argeo.eclipse.ui.MouseDoubleClick; -import org.argeo.eclipse.ui.MouseDown; -import org.argeo.eclipse.ui.Selected; -import org.argeo.entity.TermsManager; -import org.argeo.jcr.Jcr; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; - -/** {@link EditablePart} for multiple terms. */ -public class MultiTermsPart extends AbstractTermsPart { - private static final long serialVersionUID = -4961135649177920808L; - - public MultiTermsPart(Composite parent, int style, Item item, TermsManager termsManager, String typology) { - super(parent, style, item, termsManager, typology); - } - - @Override - protected Control createControl(Composite box, String style) { - Composite placeholder = new Composite(box, SWT.NONE); - RowLayout rl = new RowLayout(SWT.HORIZONTAL | SWT.WRAP); - placeholder.setLayout(rl); - List currentValue = Jcr.getMultiple(getNode(), typology); - if (currentValue != null && !currentValue.isEmpty()) - for (String value : currentValue) { - Composite block = new Composite(placeholder, SWT.NONE); - block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); - Label lbl = new Label(block, SWT.SINGLE); - String display = getTermLabel(value); - lbl.setText(display); - CmsUiUtils.style(lbl, style == null ? FormStyle.propertyText.style() : style); - if (editable) - lbl.addMouseListener((MouseDoubleClick) (e) -> { - startEditing(); - }); - if (isEditing()) { - ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); - ToolItem deleteItem = new ToolItem(toolBar, SWT.FLAT); - styleDelete(deleteItem); - deleteItem.addSelectionListener((Selected) (e) -> { - // we retrieve them again here because they may have changed - List curr = Jcr.getMultiple(getNode(), typology); - List newValue = new ArrayList<>(); - for (String v : curr) { - if (!v.equals(value)) - newValue.add(v); - } - Jcr.set(getNode(), typology, newValue); - Jcr.save(getNode()); - block.dispose(); - layout(true, true); - }); - - } - } - else {// empty - if (editable && !isEditing()) { - ToolBar toolBar = new ToolBar(placeholder, SWT.HORIZONTAL); - ToolItem addItem = new ToolItem(toolBar, SWT.FLAT); - styleAdd(addItem); - addItem.addSelectionListener((Selected) (e) -> { - startEditing(); - }); - } - } - - if (isEditing()) { - Composite block = new Composite(placeholder, SWT.NONE); - block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); - - createHighlight(block); - - Text txt = new Text(block, SWT.SINGLE | SWT.BORDER); - txt.setLayoutData(CmsUiUtils.fillWidth()); -// txt.setMessage("[new]"); - - CmsUiUtils.style(txt, style == null ? FormStyle.propertyText.style() : style); - - ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); - ToolItem cancelItem = new ToolItem(toolBar, SWT.FLAT); - styleCancel(cancelItem); - cancelItem.addSelectionListener((Selected) (e) -> { - stopEditing(); - }); - - ContextOverlay contextOverlay = new ContextOverlay(txt, SWT.NONE) { - private static final long serialVersionUID = -7980078594405384874L; - - @Override - protected void onHide() { - stopEditing(); - } - }; - contextOverlay.setLayout(new GridLayout()); - // filter - txt.addModifyListener((e) -> { - String filter = txt.getText().toLowerCase(); - if ("".equals(filter.trim())) - filter = null; - refresh(contextOverlay, filter, txt); - }); - txt.addFocusListener(new FocusListener() { - private static final long serialVersionUID = -6024501573409619949L; - - @Override - public void focusLost(FocusEvent event) { -// if (!contextOverlay.isDisposed() && contextOverlay.isShellVisible()) -// getDisplay().asyncExec(() -> stopEditing()); - } - - @Override - public void focusGained(FocusEvent event) { - // txt.setText(""); - if (!contextOverlay.isDisposed() && !contextOverlay.isShellVisible()) - refresh(contextOverlay, null, txt); - } - }); - layout(new Control[] { txt }); - // getDisplay().asyncExec(() -> txt.setFocus()); - } - return placeholder; - } - - @Override - protected void refresh(ContextOverlay contextArea, String filter, Text txt) { - CmsUiUtils.clear(contextArea); - List terms = termsManager.listAllTerms(typology); - List currentValue = Jcr.getMultiple(getNode(), typology); - terms: for (String term : terms) { - if (currentValue != null && currentValue.contains(term)) - continue terms; - String display = getTermLabel(term); - if (filter != null && !display.toLowerCase().contains(filter)) - continue terms; - Label termL = new Label(contextArea, SWT.WRAP); - termL.setText(display); - processTermListLabel(term, termL); - if (isTermSelectable(term)) - termL.addMouseListener((MouseDown) (e) -> { - List newValue = new ArrayList<>(); - List curr = Jcr.getMultiple(getNode(), typology); - if (currentValue != null) - newValue.addAll(curr); - newValue.add(term); - Jcr.set(getNode(), typology, newValue); - Jcr.save(getNode()); - contextArea.hide(); - stopEditing(); - }); - } - contextArea.show(); - } - -} diff --git a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java b/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java deleted file mode 100644 index e9fad04..0000000 --- a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.argeo.entity.ui.forms; - -import java.util.List; - -import javax.jcr.Item; - -import org.argeo.cms.ui.forms.FormStyle; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.cms.ui.viewers.EditablePart; -import org.argeo.cms.ui.widgets.ContextOverlay; -import org.argeo.eclipse.ui.MouseDoubleClick; -import org.argeo.eclipse.ui.MouseDown; -import org.argeo.eclipse.ui.Selected; -import org.argeo.entity.TermsManager; -import org.argeo.jcr.Jcr; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; - -/** {@link EditablePart} for terms. */ -public class SingleTermPart extends AbstractTermsPart { - private static final long serialVersionUID = -4961135649177920808L; - - public SingleTermPart(Composite parent, int style, Item item, TermsManager termsManager, String typology) { - super(parent, style, item, termsManager, typology); - } - - @Override - protected Control createControl(Composite box, String style) { - if (isEditing()) { - Composite block = new Composite(box, SWT.NONE); - block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); - - createHighlight(block); - - Text txt = new Text(block, SWT.SINGLE | SWT.BORDER); - CmsUiUtils.style(txt, style == null ? FormStyle.propertyText.style() : style); - - ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); - ToolItem deleteItem = new ToolItem(toolBar, SWT.PUSH); - styleDelete(deleteItem); - deleteItem.addSelectionListener((Selected) (e) -> { - Jcr.set(getNode(), typology, null); - Jcr.save(getNode()); - stopEditing(); - }); - ToolItem cancelItem = new ToolItem(toolBar, SWT.PUSH); - styleCancel(cancelItem); - cancelItem.addSelectionListener((Selected) (e) -> { - stopEditing(); - }); - - ContextOverlay contextOverlay = new ContextOverlay(txt, SWT.NONE) { - private static final long serialVersionUID = -7980078594405384874L; - - @Override - protected void onHide() { - stopEditing(); - } - }; - contextOverlay.setLayout(new GridLayout()); - // filter - txt.addModifyListener((e) -> { - String filter = txt.getText().toLowerCase(); - if ("".equals(filter.trim())) - filter = null; - refresh(contextOverlay, filter, txt); - }); - txt.addFocusListener(new FocusListener() { - private static final long serialVersionUID = -6024501573409619949L; - - @Override - public void focusLost(FocusEvent event) { -// if (!contextOverlay.isDisposed() && contextOverlay.isShellVisible()) -// getDisplay().asyncExec(() -> stopEditing()); - } - - @Override - public void focusGained(FocusEvent event) { - // txt.setText(""); - if (!contextOverlay.isDisposed() && !contextOverlay.isShellVisible()) - refresh(contextOverlay, null, txt); - } - }); - layout(new Control[] { block }); - getDisplay().asyncExec(() -> txt.setFocus()); - return block; - } else { - Composite block = new Composite(box, SWT.NONE); - block.setLayout(CmsUiUtils.noSpaceGridLayout(2)); - String currentValue = Jcr.get(getNode(), typology); - if (currentValue != null) { - Label lbl = new Label(block, SWT.SINGLE); - String display = getTermLabel(currentValue); - lbl.setText(display); - CmsUiUtils.style(lbl, style == null ? FormStyle.propertyText.style() : style); - - lbl.addMouseListener((MouseDoubleClick) (e) -> { - startEditing(); - }); - } else { - ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); - ToolItem addItem = new ToolItem(toolBar, SWT.FLAT); - styleAdd(addItem); - addItem.addSelectionListener((Selected) (e) -> { - startEditing(); - }); - } - return block; - } - } - - @Override - protected void refresh(ContextOverlay contextArea, String filter, Text txt) { - CmsUiUtils.clear(contextArea); - List terms = termsManager.listAllTerms(typology); - terms: for (String term : terms) { - String display = getTermLabel(term); - if (filter != null && !display.toLowerCase().contains(filter)) - continue terms; - Label termL = new Label(contextArea, SWT.WRAP); - termL.setText(display); - processTermListLabel(term, termL); - if (isTermSelectable(term)) - termL.addMouseListener((MouseDown) (e) -> { - Jcr.set(getNode(), typology, term); - Jcr.save(getNode()); - contextArea.hide(); - stopEditing(); - }); - } - contextArea.show(); - // txt.setFocus(); - } - -} diff --git a/org.argeo.suite.core/.classpath b/org.argeo.suite.core/.classpath deleted file mode 100644 index e801ebf..0000000 --- a/org.argeo.suite.core/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.suite.core/.gitignore b/org.argeo.suite.core/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.suite.core/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.suite.core/.project b/org.argeo.suite.core/.project deleted file mode 100644 index ab084af..0000000 --- a/org.argeo.suite.core/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - org.argeo.suite.core - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.argeo.suite.core/META-INF/.gitignore b/org.argeo.suite.core/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.suite.core/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.suite.core/OSGI-INF/maintenanceService.xml b/org.argeo.suite.core/OSGI-INF/maintenanceService.xml deleted file mode 100644 index 2d495c8..0000000 --- a/org.argeo.suite.core/OSGI-INF/maintenanceService.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.suite.core/OSGI-INF/termsManager.xml b/org.argeo.suite.core/OSGI-INF/termsManager.xml deleted file mode 100644 index 3e6d4c6..0000000 --- a/org.argeo.suite.core/OSGI-INF/termsManager.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/org.argeo.suite.core/bnd.bnd b/org.argeo.suite.core/bnd.bnd deleted file mode 100644 index 1b9efff..0000000 --- a/org.argeo.suite.core/bnd.bnd +++ /dev/null @@ -1,14 +0,0 @@ -Bundle-ActivationPolicy: lazy - -Service-Component:\ -OSGI-INF/termsManager.xml,\ -OSGI-INF/maintenanceService.xml - -Import-Package:\ -javax.transaction,\ -org.osgi.service.useradmin,\ -javax.jcr.nodetype,\ -javax.jcr.security,\ -org.argeo.api,\ -org.argeo.entity,\ -* \ No newline at end of file diff --git a/org.argeo.suite.core/build.properties b/org.argeo.suite.core/build.properties deleted file mode 100644 index 6210e84..0000000 --- a/org.argeo.suite.core/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - OSGI-INF/ -source.. = src/ diff --git a/org.argeo.suite.core/pom.xml b/org.argeo.suite.core/pom.xml deleted file mode 100644 index 2ed110f..0000000 --- a/org.argeo.suite.core/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.suite.core - Suite Core - jar - - - org.argeo.suite - org.argeo.entity.core - 2.1.18-SNAPSHOT - - - - - org.argeo.commons - org.argeo.cms - ${version.argeo-commons} - - - org.argeo.commons - org.argeo.maintenance - ${version.argeo-commons} - - - diff --git a/org.argeo.suite.core/src/org/argeo/suite/RankedObject.java b/org.argeo.suite.core/src/org/argeo/suite/RankedObject.java deleted file mode 100644 index bfba46e..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/RankedObject.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.argeo.suite; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * A container for an object whose relevance can be ranked. Typically used in an - * OSGi context with the service.ranking property. - */ -public class RankedObject { - private final static Log log = LogFactory.getLog(RankedObject.class); - - private final static String SERVICE_RANKING = "service.ranking"; -// private final static String SERVICE_ID = "service.id"; - - private T object; - private Map properties; - private final Long rank; - - public RankedObject(T object, Map properties) { - this(object, properties, extractRanking(properties)); - } - - public RankedObject(T object, Map properties, Long rank) { - super(); - this.object = object; - this.properties = properties; - this.rank = rank; - } - - private static Long extractRanking(Map properties) { - if (properties == null) - return 0l; - if (properties.containsKey(SERVICE_RANKING)) - return Long.valueOf(properties.get(SERVICE_RANKING).toString()); -// else if (properties.containsKey(SERVICE_ID)) -// return (Long) properties.get(SERVICE_ID); - else - return 0l; - } - - public T get() { - return object; - } - - public Map getProperties() { - return properties; - } - - public Long getRank() { - return rank; - } - - @Override - public int hashCode() { - return object.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof RankedObject)) - return false; - RankedObject other = (RankedObject) obj; - return rank.equals(other.rank) && object.equals(other.object); - } - - @Override - public String toString() { - return object.getClass().getName() + " with rank " + rank; - } - - public static RankedObject putIfHigherRank(Map> map, K key, T object, - Map properties) { - RankedObject rankedObject = new RankedObject<>(object, properties); - if (!map.containsKey(key)) { - map.put(key, rankedObject); - if (log.isTraceEnabled()) - log.trace( - "Added " + key + " as " + object.getClass().getName() + " with rank " + rankedObject.getRank()); - return rankedObject; - } else { - RankedObject current = map.get(key); - if (current.getRank() <= rankedObject.getRank()) { - map.put(key, rankedObject); - if (log.isTraceEnabled()) - log.trace("Replaced " + key + " by " + object.getClass().getName() + " with rank " - + rankedObject.getRank()); - return rankedObject; - } else { - return current; - } - } - - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/RankingKey.java b/org.argeo.suite.core/src/org/argeo/suite/RankingKey.java deleted file mode 100644 index e099195..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/RankingKey.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.argeo.suite; - -import java.util.Map; - -/** - * Key used to classify and filter available components (typically provided by - * OSGi services). - */ -@Deprecated -public class RankingKey implements Comparable { - public final static String SERVICE_PID = "service.pid"; - public final static String SERVICE_ID = "service.id"; - public final static String SERVICE_RANKING = "service.ranking"; - public final static String DATA_TYPE = "data.type"; - - private String pid; - private Integer ranking = 0; - private Long id = 0l; - private String dataType; - private String dataPath; - - public RankingKey(String pid, Integer ranking, Long id, String dataType, String dataPath) { - super(); - this.pid = pid; - this.ranking = ranking; - this.id = id; - this.dataType = dataType; - this.dataPath = dataPath; - } - - public RankingKey(Map properties) { - this.pid = properties.containsKey(SERVICE_PID) ? properties.get(SERVICE_PID).toString() : null; - this.ranking = properties.containsKey(SERVICE_RANKING) - ? Integer.parseInt(properties.get(SERVICE_RANKING).toString()) - : 0; - this.id = properties.containsKey(SERVICE_ID) ? (Long) properties.get(SERVICE_ID) : null; - - // Argeo specific - this.dataType = properties.containsKey(DATA_TYPE) ? properties.get(DATA_TYPE).toString() : null; - } - - @Override - public int hashCode() { - Integer result = 0; - if (pid != null) - result = +pid.hashCode(); - if (ranking != null) - result = +ranking; - if (dataType != null) - result = +dataType.hashCode(); - return result; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return new RankingKey(pid, ranking, id, dataType, dataPath); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(""); - if (pid != null) - sb.append(pid); - if (ranking != null && ranking != 0) - sb.append(' ').append(ranking); - if (dataType != null) - sb.append(' ').append(dataType); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof RankingKey)) - return false; - RankingKey other = (RankingKey) obj; - return equalsOrBothNull(pid, other.pid) && equalsOrBothNull(ranking, other.ranking) - && equalsOrBothNull(id, other.id) && equalsOrBothNull(dataType, other.dataType) - && equalsOrBothNull(dataPath, other.dataPath); - } - - @Override - public int compareTo(RankingKey o) { - if (pid != null && o.pid != null) { - if (pid.equals(o.pid)) { - if (ranking.equals(o.ranking)) - if (id != null && o.id != null) - return id.compareTo(o.id); - else - return 0; - else - return ranking.compareTo(o.ranking); - } else { - return pid.compareTo(o.pid); - } - - } else { - if (dataType != null && o.dataType != null) { - if (dataType.equals(o.dataType)) { - // TODO factorise - if (ranking.equals(o.ranking)) - if (id != null && o.id != null) - return id.compareTo(o.id); - else - return 0; - else - return ranking.compareTo(o.ranking); - } else { - return dataPath.compareTo(o.dataType); - } - } - } - return -1; - } - - public String getPid() { - return pid; - } - - public Integer getRanking() { - return ranking; - } - - public Long getId() { - return id; - } - - public String getDataType() { - return dataType; - } - - public String getDataPath() { - return dataPath; - } - - public static RankingKey minPid(String pid) { - return new RankingKey(pid, Integer.MIN_VALUE, null, null, null); - } - - public static RankingKey maxPid(String pid) { - return new RankingKey(pid, Integer.MAX_VALUE, null, null, null); - } - - public static RankingKey minDataType(String dataType) { - return new RankingKey(null, Integer.MIN_VALUE, null, dataType, null); - } - - public static RankingKey maxDataType(String dataType) { - return new RankingKey(null, Integer.MAX_VALUE, null, dataType, null); - } - - private static boolean equalsOrBothNull(Object o1, Object o2) { - if (o1 == null && o2 == null) - return true; - if (o1 == null && o2 != null) - return false; - if (o1 != null && o2 == null) - return false; - return o2.equals(o1); - } -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/SuiteRole.java b/org.argeo.suite.core/src/org/argeo/suite/SuiteRole.java deleted file mode 100644 index 382f50c..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/SuiteRole.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.suite; - -import org.argeo.api.NodeConstants; -import org.argeo.naming.Distinguished; -import org.argeo.naming.LdapAttrs; - -/** Office specific roles used in the code */ -public enum SuiteRole implements Distinguished { - coworker, manager; - - public String getRolePrefix() { - return "org.argeo.suite"; - } - - public String dn() { - return new StringBuilder(LdapAttrs.cn.name()).append("=").append(getRolePrefix()).append(".").append(name()) - .append(",").append(NodeConstants.ROLES_BASEDN).toString(); - } -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java b/org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java deleted file mode 100644 index e63b515..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/SuiteUtils.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.argeo.suite; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.security.Privilege; -import javax.naming.ldap.LdapName; -import javax.security.auth.x500.X500Principal; - -import org.argeo.api.NodeConstants; -import org.argeo.cms.auth.CmsSession; -import org.argeo.entity.EntityType; -import org.argeo.jackrabbit.security.JackrabbitSecurityUtils; -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.argeo.naming.LdapAttrs; - -/** Utilities around the Argeo Suite APIs. */ -public class SuiteUtils { - - public static String getUserNodePath(LdapName userDn) { - String uid = userDn.getRdn(userDn.size() - 1).getValue().toString(); - return EntityType.user.basePath() + '/' + uid; - } - - public static Node getOrCreateUserNode(Session adminSession, LdapName userDn) { - try { - Node usersBase = adminSession.getNode(EntityType.user.basePath()); - String uid = userDn.getRdn(userDn.size() - 1).getValue().toString(); - Node userNode; - if (!usersBase.hasNode(uid)) { - userNode = usersBase.addNode(uid, NodeType.NT_UNSTRUCTURED); - userNode.addMixin(EntityType.user.get()); - userNode.addMixin(NodeType.MIX_CREATED); - userNode.setProperty(LdapAttrs.distinguishedName.property(), userDn.toString()); - userNode.setProperty(LdapAttrs.uid.property(), uid); - adminSession.save(); - JackrabbitSecurityUtils.denyPrivilege(adminSession, userNode.getPath(), SuiteRole.coworker.dn(), - Privilege.JCR_READ); - JcrUtils.addPrivilege(adminSession, userNode.getPath(), new X500Principal(userDn.toString()).getName(), - Privilege.JCR_READ); - JcrUtils.addPrivilege(adminSession, userNode.getPath(), NodeConstants.ROLE_USER_ADMIN, - Privilege.JCR_ALL); - } else { - userNode = usersBase.getNode(uid); - } - return userNode; - } catch (RepositoryException e) { - throw new JcrException("Cannot create user node for " + userDn, e); - } - } - - public static Node getCmsSessionNode(Session session, CmsSession cmsSession) { - try { - return session.getNode(getUserNodePath(cmsSession.getUserDn()) + '/' + cmsSession.getUuid().toString()); - } catch (RepositoryException e) { - throw new JcrException("Cannot get session dir for " + cmsSession, e); - } - } - - public static Node getOrCreateCmsSessionNode(Session adminSession, CmsSession cmsSession) { - try { - LdapName userDn = cmsSession.getUserDn(); -// String uid = userDn.get(userDn.size() - 1); - Node userNode = getOrCreateUserNode(adminSession, userDn); -// if (!usersBase.hasNode(uid)) { -// userNode = usersBase.addNode(uid, NodeType.NT_UNSTRUCTURED); -// userNode.addMixin(EntityType.user.get()); -// userNode.addMixin(NodeType.MIX_CREATED); -// usersBase.setProperty(LdapAttrs.uid.property(), uid); -// usersBase.setProperty(LdapAttrs.distinguishedName.property(), userDn.toString()); -// adminSession.save(); -// } else { -// userNode = usersBase.getNode(uid); -// } - String cmsSessionUuid = cmsSession.getUuid().toString(); - Node cmsSessionNode; - if (!userNode.hasNode(cmsSessionUuid)) { - cmsSessionNode = userNode.addNode(cmsSessionUuid, NodeType.NT_UNSTRUCTURED); - cmsSessionNode.addMixin(NodeType.MIX_CREATED); - adminSession.save(); - JcrUtils.addPrivilege(adminSession, cmsSessionNode.getPath(), cmsSession.getUserRole(), - Privilege.JCR_ALL); - } else { - cmsSessionNode = userNode.getNode(cmsSessionUuid); - } - return cmsSessionNode; - } catch (RepositoryException e) { - throw new JcrException("Cannot create session dir for " + cmsSession, e); - } - } - - /** Singleton. */ - private SuiteUtils() { - - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java b/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java deleted file mode 100644 index b6e997a..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.argeo.suite.core; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.ItemExistsException; -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.entity.EntityType; -import org.argeo.jcr.JcrUtils; -import org.argeo.maintenance.AbstractMaintenanceService; - -/** Base for custom initialisations. */ -public abstract class CustomMaintenanceService extends AbstractMaintenanceService { - private final static Log log = LogFactory.getLog(AbstractMaintenanceService.class); - - protected List getTypologies() { - return new ArrayList<>(); - } - - protected String getTypologiesLoadBase() { - return "/sys/terms"; - } - - protected void loadTypologies(Node customBaseNode) throws RepositoryException, IOException { - List typologies = getTypologies(); - if (!typologies.isEmpty()) { - Node termsBase = JcrUtils.getOrAdd(customBaseNode, EntityType.terms.name(), EntityType.typologies.get()); - for (String terms : typologies) { - loadTerms(termsBase, terms); - } - termsBase.getSession().save(); - } - } - - protected void loadTerms(Node termsBase, String name) throws IOException, RepositoryException { - try { - if (termsBase.hasNode(name)) - return; - - String termsLoadPath = getTypologiesLoadBase() + '/' + name + ".xml"; - URL termsUrl = getClass().getClassLoader().getResource(termsLoadPath); - if (termsUrl == null) - throw new IllegalArgumentException("Terms '" + name + "' not found."); - try (InputStream in = termsUrl.openStream()) { - termsBase.getSession().importXML(termsBase.getPath(), in, - ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); - } catch (ItemExistsException e) { - log.warn("Terms " + name + " exists with another UUID, removing it..."); - termsBase.getNode(name).remove(); - try (InputStream in = termsUrl.openStream()) { - termsBase.getSession().importXML(termsBase.getPath(), in, - ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); - } - } - if (log.isDebugEnabled()) - log.debug("Terms '" + name + "' loaded."); - termsBase.getSession().save(); - } catch (RepositoryException | IOException e) { - log.error("Cannot load terms '" + name + "': " + e.getMessage()); - throw e; - } - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java deleted file mode 100644 index b217373..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteMaintenanceService.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.argeo.suite.core; - -import java.io.IOException; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.security.Privilege; - -import org.argeo.api.NodeConstants; -import org.argeo.entity.EntityType; -import org.argeo.jcr.JcrUtils; -import org.argeo.maintenance.AbstractMaintenanceService; - -/** Initialises an Argeo Suite backend. */ -public class SuiteMaintenanceService extends AbstractMaintenanceService { - - @Override - public boolean prepareJcrTree(Session adminSession) throws RepositoryException, IOException { - boolean modified = false; - Node rootNode = adminSession.getRootNode(); - if (!rootNode.hasNode(EntityType.user.name())) { - rootNode.addNode(EntityType.user.name(), NodeType.NT_UNSTRUCTURED); - modified = true; - } - if (modified) - adminSession.save(); - return modified; - } - - @Override - public void configurePrivileges(Session adminSession) throws RepositoryException { - JcrUtils.addPrivilege(adminSession, EntityType.user.basePath(), NodeConstants.ROLE_USER_ADMIN, - Privilege.JCR_ALL); - //JcrUtils.addPrivilege(adminSession, "/", SuiteRole.coworker.dn(), Privilege.JCR_READ); - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java deleted file mode 100644 index 0c03dc5..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.argeo.suite.core; - -import java.util.ArrayList; -import java.util.List; - -/** - * A single term. Helper to optimise {@link SuiteTermsManager} implementation. - */ -class SuiteTerm { - private final String name; - private final String relativePath; - private final SuiteTypology typology; - private final String id; - - private final SuiteTerm parentTerm; - private final List subTerms = new ArrayList<>(); - - SuiteTerm(SuiteTypology typology, String relativePath, SuiteTerm parentTerm) { - this.typology = typology; - this.parentTerm = parentTerm; - this.relativePath = relativePath; - int index = relativePath.lastIndexOf('/'); - if (index > 0) { - this.name = relativePath.substring(index); - } else { - this.name = relativePath; - } - id = typology.getName() + '/' + relativePath; - } - - public String getName() { - return name; - } - - public String getRelativePath() { - return relativePath; - } - - SuiteTypology getTypology() { - return typology; - } - - public String getId() { - return id; - } - - List getSubTerms() { - return subTerms; - } - - SuiteTerm getParentTerm() { - return parentTerm; - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java deleted file mode 100644 index 1362f94..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.argeo.suite.core; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.api.NodeConstants; -import org.argeo.api.NodeUtils; -import org.argeo.entity.EntityNames; -import org.argeo.entity.EntityType; -import org.argeo.entity.TermsManager; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrException; - -/** Argeo Suite implementation of terms manager. */ -public class SuiteTermsManager implements TermsManager { - private final Map terms = new HashMap<>(); - private final Map typologies = new HashMap<>(); - - // JCR - private Repository repository; - private Session adminSession; - - public void init() { - adminSession = NodeUtils.openDataAdminSession(repository, NodeConstants.SYS_WORKSPACE); - } - - @Override - public List listAllTerms(String typology) { - List res = new ArrayList<>(); - SuiteTypology t = getTypology(typology); - for (SuiteTerm term : t.getAllTerms()) { - res.add(term.getId()); - } - return res; - } - - SuiteTypology getTypology(String typology) { - SuiteTypology t = typologies.get(typology); - if (t == null) { - Node termsNode = Jcr.getNode(adminSession, "SELECT * FROM [{0}] WHERE NAME()=\"{1}\"", - EntityType.terms.get(), typology); - if (termsNode == null) - throw new IllegalArgumentException("Typology " + typology + " not found."); - t = loadTypology(termsNode); - } - return t; - } - - SuiteTypology loadTypology(Node termsNode) { - try { - SuiteTypology typology = new SuiteTypology(termsNode); - for (Node termNode : Jcr.iterate(termsNode.getNodes())) { - if (termNode.isNodeType(EntityType.term.get())) { - SuiteTerm term = loadTerm(typology, termNode, null); - if (!term.getSubTerms().isEmpty()) - typology.markNotFlat(); - typology.getSubTerms().add(term); - } - } - typologies.put(typology.getName(), typology); - return typology; - } catch (RepositoryException e) { - throw new JcrException("Cannot load typology from " + termsNode, e); - } - } - - SuiteTerm loadTerm(SuiteTypology typology, Node termNode, SuiteTerm parentTerm) throws RepositoryException { - String name = termNode.getProperty(EntityNames.NAME).getString(); - String relativePath = parentTerm == null ? name : parentTerm.getRelativePath() + '/' + name; - SuiteTerm term = new SuiteTerm(typology, relativePath, parentTerm); - terms.put(term.getId(), term); - for (Node subTermNode : Jcr.iterate(termNode.getNodes())) { - if (termNode.isNodeType(EntityType.term.get())) { - SuiteTerm subTerm = loadTerm(typology, subTermNode, term); - term.getSubTerms().add(subTerm); - } - } - return term; - } - - public void destroy() { - Jcr.logout(adminSession); - } - - public void setRepository(Repository repository) { - this.repository = repository; - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java deleted file mode 100644 index e84066c..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.argeo.suite.core; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; - -import org.argeo.jcr.Jcr; - -/** A typology. Helper to optimise {@link SuiteTermsManager} implementation. */ -class SuiteTypology { - private final String name; - private final Node node; - private boolean isFlat = true; - - private final List subTerms = new ArrayList<>(); - - public SuiteTypology(Node node) { - this.node = node; - this.name = Jcr.getName(this.node); - } - - public String getName() { - return name; - } - - public Node getNode() { - return node; - } - - void markNotFlat() { - if (isFlat) - isFlat = false; - } - - public boolean isFlat() { - return isFlat; - } - - public List getSubTerms() { - return subTerms; - } - - public List getAllTerms() { - if (isFlat) - return subTerms; - else { - List terms = new ArrayList<>(); - for (SuiteTerm subTerm : subTerms) { - terms.add(subTerm); - collectSubTerms(terms, subTerm); - } - return terms; - } - } - - private void collectSubTerms(List terms, SuiteTerm term) { - for (SuiteTerm subTerm : term.getSubTerms()) { - terms.add(subTerm); - collectSubTerms(terms, subTerm); - } - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/library/DocxExtractor.java b/org.argeo.suite.core/src/org/argeo/suite/library/DocxExtractor.java deleted file mode 100644 index 53e73f3..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/library/DocxExtractor.java +++ /dev/null @@ -1,355 +0,0 @@ -package org.argeo.suite.library; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.argeo.util.DigestUtils; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -/** Parses a .docx document, trying its best to extract text and table data. */ -public class DocxExtractor { - final static String T = "t"; - final static String TC = "tc"; - final static String TR = "tr"; - final static String TBL = "tbl"; - final static String P = "p"; - static boolean debug = false; - - final static String PROOF_ERR = "proofErr"; - final static String TYPE = "type"; - final static String SPELL_START = "spellStart"; - final static String SPELL_END = "spellEnd"; - - protected List tables = new ArrayList<>(); - protected List text = new ArrayList<>(); - protected Map media = new TreeMap<>(); - private Set mediaDigests = new HashSet<>(); - - protected void processTextItem(List lines, String str) { - lines.add(str); - } - - protected boolean skipMedia(String digest) { - return false; - } - - class DocxHandler extends DefaultHandler { - - private StringBuilder buffer = new StringBuilder(); - private Tbl currentTbl = null; - - boolean inSpellErr = false; - boolean inParagraph = false; - - @Override - public void startElement(String uri, String name, String qName, Attributes attributes) throws SAXException { - // System.out.println(localName + " " + qName + " " + uri.hashCode()); - if (P.equals(name)) { - if (debug && currentTbl == null) - System.out.println("# START PARA"); - inParagraph = true; - } else if (PROOF_ERR.equals(name)) { - String type = attributes.getValue(uri, TYPE); - if (SPELL_START.equals(type)) - inSpellErr = true; - else if (SPELL_END.equals(type)) - inSpellErr = false; - - } else if (TBL.equals(name)) { - if (currentTbl != null) { - Tbl childTbl = new Tbl(); - childTbl.parentTbl = currentTbl; - currentTbl = childTbl; - // throw new IllegalStateException("Already an active table"); - } else { - currentTbl = new Tbl(); - } - } - } - - @Override - public void endElement(String uri, String name, String qName) throws SAXException { - if (name.equals(T)) { -// if (inSpellErr) { -// // do not reset the buffer -// return; -// } - - if (currentTbl != null) { - currentTbl.appendText(buffer.toString()); - } else { - String str = buffer.toString(); - // replace NO-BREAK SPACE by regular space. - str = str.replace('\u00A0', ' '); - str = str.strip(); - if (!"".equals(str)) { - processTextItem(text, str); - } - } - } else if (name.equals(P)) { - if (debug && currentTbl == null) - System.out.println("# END PARA"); - if (currentTbl != null) { - currentTbl.currentRow.current.text.append('\n'); - } else { - - } - inParagraph = false; - } else if (name.equals(TC)) { - if (currentTbl != null) - currentTbl.closeColumn(); - } else if (name.equals(TR)) { - if (currentTbl != null) - currentTbl.closeRow(); - } else if (name.equals(TBL)) { - if (currentTbl != null) { - tables.add(currentTbl); - if (currentTbl.parentTbl != null) - currentTbl = currentTbl.parentTbl; - else - currentTbl = null; - } else { - throw new IllegalStateException("Closing a table while none was open."); - } - } - // reset the buffer - buffer.setLength(0); - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - buffer.append(ch, start, length); - } - - } - - public static class Tbl { - Tbl parentTbl = null; - Tr currentRow = new Tr(); - List
rows = new ArrayList<>(); - - void appendText(String str) { - currentRow.current.text.append(str); - } - - void closeColumn() { - currentRow.columns.add(currentRow.current); - currentRow.current = new Tc(); - } - - void closeRow() { - rows.add(currentRow); - currentRow = new Tr(); - } - - public List
getRows() { - return rows; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (Tr tr : rows) { - String txt = tr.toString(); - sb.append(txt).append('\n'); - } - return sb.toString(); - } - } - - public static class Tr { - Tc current = new Tc(); - List columns = new ArrayList<>(); - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (Tc tc : columns) { - sb.append("\"").append(tc.toString()).append("\"").append(','); - } - return sb.toString(); - } - - public List getColumns() { - return columns; - } - - } - - public static class Tc { - StringBuilder text = new StringBuilder(); - - @Override - public String toString() { - return text.toString().trim(); - } - - } - - protected void parse(Reader in) { - try { - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(true); - SAXParser saxParser = spf.newSAXParser(); - XMLReader xmlReader = saxParser.getXMLReader(); - xmlReader.setContentHandler(new DocxHandler()); - xmlReader.parse(new InputSource(in)); - } catch (ParserConfigurationException | SAXException | IOException e) { - throw new RuntimeException("Cannot parse document", e); - } - } - - public List getText() { - return text; - } - - public List getTables() { - return tables; - } - - public Map getMedia() { - return media; - } - - public void load(ZipInputStream zIn) { - try { - ZipEntry entry = null; - while ((entry = zIn.getNextEntry()) != null) { - if ("word/document.xml".equals(entry.getName())) { - try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - byte[] buffer = new byte[2048]; - int len = 0; - while ((len = zIn.read(buffer)) > 0) { - out.write(buffer, 0, len); - } - try (Reader reader = new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), - StandardCharsets.UTF_8)) { - parse(reader); - } - } - } else if (entry.getName().startsWith("word/media")) { - String fileName = entry.getName().substring(entry.getName().lastIndexOf('/') + 1); - int dotIndex = fileName.lastIndexOf('.'); - String ext = fileName.substring(dotIndex + 1).toLowerCase(); - // we ignore .jfif - if ("jpeg".equals(ext)) - ext = "jpg"; - fileName = fileName.substring(0, dotIndex) + "." + ext; - switch (ext) { - case "png": - case "jpg": - case "gif": - case "bmp": - case "tiff": - try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - byte[] buffer = new byte[2048]; - int len = 0; - while ((len = zIn.read(buffer)) > 0) { - out.write(buffer, 0, len); - } - byte[] bytes = out.toByteArray(); - String digest = DigestUtils.digest(DigestUtils.MD5, bytes); - if (skipMedia(digest)) - break; - if (!mediaDigests.contains(digest)) { - media.put(fileName, bytes); - mediaDigests.add(digest); - } - } - break; - default: - break; - } - } else { - // System.out.println(entry.getName()); - } - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // throw new IllegalArgumentException("No document.xml found"); - - } - -// public static Reader extractDocumentXml(ZipInputStream zIn) throws IOException { -// ZipEntry entry = null; -// while ((entry = zIn.getNextEntry()) != null) { -// if ("word/document.xml".equals(entry.getName())) { -// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { -// byte[] buffer = new byte[2048]; -// int len = 0; -// while ((len = zIn.read(buffer)) > 0) { -// out.write(buffer, 0, len); -// } -// return new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), StandardCharsets.UTF_8); -// } -// } else { -// System.out.println(entry.getName()); -// } -// } -// throw new IllegalArgumentException("No document.xml found"); -// } - -// protected static ZipInputStream openAsZip(String file) throws IOException { -// ZipInputStream zIn; -// Path path = Paths.get(file); -// zIn = new ZipInputStream(Files.newInputStream(path)); -// return zIn; -// } - - public static void main(String[] args) throws IOException { - if (args.length == 0) - throw new IllegalArgumentException("Provide a file path"); - Path p = Paths.get(args[0]); - - DocxExtractor importer = new DocxExtractor(); - try (ZipInputStream zIn = new ZipInputStream(Files.newInputStream(p))) { - importer.load(zIn); - } - // display - System.out.println("## TEXT"); - for (int i = 0; i < importer.text.size(); i++) { - String str = importer.text.get(i); - System.out.println(str); - } - - System.out.println("\n"); - - for (int i = 0; i < importer.tables.size(); i++) { - Tbl tbl = importer.tables.get(i); - System.out.println("## TABLE " + i); - System.out.println(tbl); - } - - System.out.println("## MEDIA"); - for (String fileName : importer.media.keySet()) { - int sizeKb = importer.media.get(fileName).length / 1024; - System.out.println(fileName + " " + sizeKb + " kB"); - } - } - -} diff --git a/org.argeo.suite.core/src/org/argeo/suite/util/XPathUtils.java b/org.argeo.suite.core/src/org/argeo/suite/util/XPathUtils.java deleted file mode 100644 index 66d9aa0..0000000 --- a/org.argeo.suite.core/src/org/argeo/suite/util/XPathUtils.java +++ /dev/null @@ -1,177 +0,0 @@ -package org.argeo.suite.util; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.util.ISO9075; - -/** Ease XPath generation for JCR requests */ -public class XPathUtils { - private final static Log log = LogFactory.getLog(XPathUtils.class); - - private final static String QUERY_XPATH = "xpath"; - - public static String descendantFrom(String parentPath) { - if (notEmpty(parentPath)) { - if ("/".equals(parentPath)) - parentPath = ""; - // Hardcoded dependency to Jackrabbit. Remove - String result = "/jcr:root" + ISO9075.encodePath(parentPath); - if (log.isTraceEnabled()) { - String result2 = "/jcr:root" + parentPath; - if (!result2.equals(result)) - log.warn("Encoded Path " + result2 + " --> " + result); - } - return result; - } else - return ""; - } - - public static String localAnd(String... conditions) { - StringBuilder builder = new StringBuilder(); - for (String condition : conditions) { - if (notEmpty(condition)) { - builder.append(" ").append(condition).append(" and "); - } - } - if (builder.length() > 3) - return builder.substring(0, builder.length() - 4); - else - return ""; - } - - public static String xPathNot(String condition) { - if (notEmpty(condition)) - return "not(" + condition + ")"; - else - return ""; - } - - public static String getFreeTextConstraint(String filter) throws RepositoryException { - StringBuilder builder = new StringBuilder(); - if (notEmpty(filter)) { - String[] strs = filter.trim().split(" "); - for (String token : strs) { - builder.append("jcr:contains(.,'*" + encodeXPathStringValue(token) + "*') and "); - } - return builder.substring(0, builder.length() - 4); - } - return ""; - } - - public static String getPropertyContains(String propertyName, String filter) throws RepositoryException { - if (notEmpty(filter)) - return "jcr:contains(@" + propertyName + ",'*" + encodeXPathStringValue(filter) + "*')"; - return ""; - } - - private final static DateFormat jcrRefFormatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'+02:00'"); - - /** - * @param propertyName - * @param calendar the reference date - * @param lowerOrGreater "<", ">" TODO validate ">=" - * @return - * @throws RepositoryException - */ - public static String getPropertyDateComparaison(String propertyName, Calendar cal, String lowerOrGreater) - throws RepositoryException { - if (cal != null) { - String jcrDateStr = jcrRefFormatter.format(cal.getTime()); - - // jcrDateStr = "2015-08-03T05:00:03:000Z"; - String result = "@" + propertyName + " " + lowerOrGreater + " xs:dateTime('" + jcrDateStr + "')"; - return result; - } - return ""; - } - - public static String getPropertyEquals(String propertyName, String value) { - if (notEmpty(value)) - return "@" + propertyName + "='" + encodeXPathStringValue(value) + "'"; - return ""; - } - - public static String encodeXPathStringValue(String propertyValue) { - // TODO implement safer mechanism to escape invalid characters - // Also check why we have used this regex in ResourceSerrviceImpl l 474 - // String cleanedKey = key.replaceAll("(?:')", "''"); - String result = propertyValue.replaceAll("'", "''"); - return result; - } - - public static void andAppend(StringBuilder builder, String condition) { - if (notEmpty(condition)) { - builder.append(condition); - builder.append(" and "); - } - } - - public static void appendOrderByProperties(StringBuilder builder, boolean ascending, String... propertyNames) { - if (propertyNames.length > 0) { - builder.append(" order by "); - for (String propName : propertyNames) - builder.append("@").append(propName).append(", "); - builder = builder.delete(builder.length() - 2, builder.length()); - if (ascending) - builder.append(" ascending "); - else - builder.append(" descending "); - } - } - - public static void appendAndPropStringCondition(StringBuilder builder, String propertyName, String filter) - throws RepositoryException { - if (notEmpty(filter)) { - andAppend(builder, getPropertyContains(propertyName, filter)); - } - } - - public static void appendAndNotPropStringCondition(StringBuilder builder, String propertyName, String filter) - throws RepositoryException { - if (notEmpty(filter)) { - String cond = getPropertyContains(propertyName, filter); - builder.append(xPathNot(cond)); - builder.append(" and "); - } - } - - public static Query createQuery(Session session, String queryString) throws RepositoryException { - QueryManager queryManager = session.getWorkspace().getQueryManager(); - // Localise JCR properties for XPATH - queryString = localiseJcrItemNames(queryString); - return queryManager.createQuery(queryString, QUERY_XPATH); - } - - private final static String NS_JCR = "\\{http://www.jcp.org/jcr/1.0\\}"; - private final static String NS_NT = "\\{http://www.jcp.org/jcr/nt/1.0\\}"; - private final static String NS_MIX = "\\{http://www.jcp.org/jcr/mix/1.0\\}"; - - /** - * Replace the generic namespace with the local "jcr:", "nt:", "mix:" values. It - * is a workaround that must be later cleaned - */ - public static String localiseJcrItemNames(String name) { - name = name.replaceAll(NS_JCR, "jcr:"); - name = name.replaceAll(NS_NT, "nt:"); - name = name.replaceAll(NS_MIX, "mix:"); - return name; - } - - private static boolean notEmpty(String stringToTest) { - return !(stringToTest == null || "".equals(stringToTest.trim())); - } - - /** Singleton. */ - private XPathUtils() { - - } -} diff --git a/org.argeo.suite.theme.default/.gitignore b/org.argeo.suite.theme.default/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.suite.theme.default/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.suite.theme.default/.project b/org.argeo.suite.theme.default/.project deleted file mode 100644 index d157155..0000000 --- a/org.argeo.suite.theme.default/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - org.argeo.suite.theme.default - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/org.argeo.suite.theme.default/META-INF/.gitignore b/org.argeo.suite.theme.default/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.suite.theme.default/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.suite.theme.default/OSGI-INF/cmsTheme.xml b/org.argeo.suite.theme.default/OSGI-INF/cmsTheme.xml deleted file mode 100644 index 66b8c44..0000000 --- a/org.argeo.suite.theme.default/OSGI-INF/cmsTheme.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.suite.theme.default/bnd.bnd b/org.argeo.suite.theme.default/bnd.bnd deleted file mode 100644 index 6c4a97c..0000000 --- a/org.argeo.suite.theme.default/bnd.bnd +++ /dev/null @@ -1,6 +0,0 @@ -Service-Component:\ -OSGI-INF/cmsTheme.xml - -Import-Package:\ -org.argeo.cms.ui.util,\ -* \ No newline at end of file diff --git a/org.argeo.suite.theme.default/build.properties b/org.argeo.suite.theme.default/build.properties deleted file mode 100644 index 9cb37cd..0000000 --- a/org.argeo.suite.theme.default/build.properties +++ /dev/null @@ -1,3 +0,0 @@ -bin.includes = META-INF/,\ - icons/,\ - OSGI-INF/ diff --git a/org.argeo.suite.theme.default/icons/types/16/add.png b/org.argeo.suite.theme.default/icons/types/16/add.png deleted file mode 100644 index 5c06bf0..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/add.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/close.png b/org.argeo.suite.theme.default/icons/types/16/close.png deleted file mode 100644 index af85e1a..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/close.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/dashboard.png b/org.argeo.suite.theme.default/icons/types/16/dashboard.png deleted file mode 100644 index 1235592..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/dashboard.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/delete.png b/org.argeo.suite.theme.default/icons/types/16/delete.png deleted file mode 100644 index dd2f428..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/delete.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/document.png b/org.argeo.suite.theme.default/icons/types/16/document.png deleted file mode 100644 index b168263..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/document.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/documents.png b/org.argeo.suite.theme.default/icons/types/16/documents.png deleted file mode 100644 index 56deec5..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/documents.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/folder.png b/org.argeo.suite.theme.default/icons/types/16/folder.png deleted file mode 100644 index fefbb40..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/folder.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/inbox.png b/org.argeo.suite.theme.default/icons/types/16/inbox.png deleted file mode 100644 index d1aa6af..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/inbox.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/location.png b/org.argeo.suite.theme.default/icons/types/16/location.png deleted file mode 100644 index 17c7070..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/location.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/logout.png b/org.argeo.suite.theme.default/icons/types/16/logout.png deleted file mode 100644 index f685ea9..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/logout.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/map.png b/org.argeo.suite.theme.default/icons/types/16/map.png deleted file mode 100644 index 99690e6..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/map.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/organisation.png b/org.argeo.suite.theme.default/icons/types/16/organisation.png deleted file mode 100644 index 2e81a6c..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/organisation.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/people.png b/org.argeo.suite.theme.default/icons/types/16/people.png deleted file mode 100644 index 925d571..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/people.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/person.png b/org.argeo.suite.theme.default/icons/types/16/person.png deleted file mode 100644 index 8f518e1..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/person.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/refresh.png b/org.argeo.suite.theme.default/icons/types/16/refresh.png deleted file mode 100644 index 0d39107..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/refresh.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/save.png b/org.argeo.suite.theme.default/icons/types/16/save.png deleted file mode 100644 index 1c58ada..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/save.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/search.png b/org.argeo.suite.theme.default/icons/types/16/search.png deleted file mode 100644 index d32874b..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/search.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/settings.png b/org.argeo.suite.theme.default/icons/types/16/settings.png deleted file mode 100644 index ac2d8c9..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/settings.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/tag.png b/org.argeo.suite.theme.default/icons/types/16/tag.png deleted file mode 100644 index cefdbb9..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/tag.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/task.png b/org.argeo.suite.theme.default/icons/types/16/task.png deleted file mode 100644 index eeb7e01..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/task.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/16/user.png b/org.argeo.suite.theme.default/icons/types/16/user.png deleted file mode 100644 index 13a8f76..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/16/user.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/add.png b/org.argeo.suite.theme.default/icons/types/32/add.png deleted file mode 100644 index 15feb20..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/add.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/close.png b/org.argeo.suite.theme.default/icons/types/32/close.png deleted file mode 100644 index d0729a5..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/close.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/dashboard.png b/org.argeo.suite.theme.default/icons/types/32/dashboard.png deleted file mode 100644 index 4c24f43..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/dashboard.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/delete.png b/org.argeo.suite.theme.default/icons/types/32/delete.png deleted file mode 100644 index 2ee3d88..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/delete.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/document.png b/org.argeo.suite.theme.default/icons/types/32/document.png deleted file mode 100644 index a4653fa..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/document.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/documents.png b/org.argeo.suite.theme.default/icons/types/32/documents.png deleted file mode 100644 index 29db972..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/documents.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/folder.png b/org.argeo.suite.theme.default/icons/types/32/folder.png deleted file mode 100644 index b98fc84..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/folder.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/inbox.png b/org.argeo.suite.theme.default/icons/types/32/inbox.png deleted file mode 100644 index 7583c99..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/inbox.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/location.png b/org.argeo.suite.theme.default/icons/types/32/location.png deleted file mode 100644 index d9207f1..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/location.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/logout.png b/org.argeo.suite.theme.default/icons/types/32/logout.png deleted file mode 100644 index 2d8024f..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/logout.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/map.png b/org.argeo.suite.theme.default/icons/types/32/map.png deleted file mode 100644 index 9a82a96..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/map.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/organisation.png b/org.argeo.suite.theme.default/icons/types/32/organisation.png deleted file mode 100644 index 62890c2..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/organisation.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/people.png b/org.argeo.suite.theme.default/icons/types/32/people.png deleted file mode 100644 index 5f53288..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/people.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/person.png b/org.argeo.suite.theme.default/icons/types/32/person.png deleted file mode 100644 index a6c5f1d..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/person.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/save.png b/org.argeo.suite.theme.default/icons/types/32/save.png deleted file mode 100644 index d7597d1..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/save.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/search.png b/org.argeo.suite.theme.default/icons/types/32/search.png deleted file mode 100644 index 8d89a4a..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/search.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/settings.png b/org.argeo.suite.theme.default/icons/types/32/settings.png deleted file mode 100644 index 4e3fa20..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/settings.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/tag.png b/org.argeo.suite.theme.default/icons/types/32/tag.png deleted file mode 100644 index 907e216..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/tag.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/task.png b/org.argeo.suite.theme.default/icons/types/32/task.png deleted file mode 100644 index b6bd243..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/task.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/icons/types/32/user.png b/org.argeo.suite.theme.default/icons/types/32/user.png deleted file mode 100644 index 50fd404..0000000 Binary files a/org.argeo.suite.theme.default/icons/types/32/user.png and /dev/null differ diff --git a/org.argeo.suite.theme.default/pom.xml b/org.argeo.suite.theme.default/pom.xml deleted file mode 100644 index f48b083..0000000 --- a/org.argeo.suite.theme.default/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.suite.theme.default - Suite Default Theme - jar - - - diff --git a/org.argeo.suite.theme.default/rap/work.css b/org.argeo.suite.theme.default/rap/work.css deleted file mode 100644 index c0aaeb1..0000000 --- a/org.argeo.suite.theme.default/rap/work.css +++ /dev/null @@ -1,181 +0,0 @@ -.argeo-suite-header { - color: white; - background-color: #00294b; -} - -.argeo-suite-headerTitle { - font: bold 18px sans-serif; - color: white; - background-color: #00294b; -} - -.argeo-suite-leadPane { - background-color: #eee; -} - -Label.argeo-suite-leadPane { - font: 14px sans-serif; - color: #888; - background-color: #eee; -} - -Button.argeo-suite-leadPane:hover { - cursor:pointer; -} - -.argeo-suite-recentItems { - font: bold 14px sans-serif; - color: white; - background-color: #00294b; - padding: 8px 16px; -} - -.argeo-suite-titleContainer { - background-color: #00294b; - padding: 6px 8px 4px 8px; -} - -.argeo-suite-titleLabel { - font: bold 14px sans-serif; - color: white; - background-color: #00294b; -} - -.argeo-suite-subTitleLabel { - font: italic 14px sans-serif; - color: #777; - padding: 4px 8px; -} - -.argeo-suite-simpleLabel { - font: bold 14px sans-serif; - padding: 0px; -} - -.argeo-suite-simpleText { - font: 14px sans-serif; - padding: 0px; -} - -.argeo-suite-titleCell { - font: bold 14px sans-serif; - background-color: #ddd; -} - -.argeo-suite-inlineButton { - padding: 0px 4px; - font: 12px sans-serif; - border: 1px solid white; - color: white; - background-image: none; - background-color: #00294b; -} - -.argeo-suite-inlineButton:hover { - color: #00294b; - background-color: white; -} - -Composite.argeo-suite-mainTabBody { - background-color: #eee; - border: 1px solid #bbb; -} - -.argeo-suite-mainTab { - background-color: #eee; - border: 1px solid #888; -} - -ToolItem.argeo-suite-mainTab { - border: none; - background-color: #eee; -} - -ToolItem.argeo-suite-mainTab:hover { - background-color: #eee; -} - - -Button.argeo-suite-mainTab { - border: 1px solid #eee; - background-color: #eee; -} - -.argeo-suite-mainTab:hover { - background-color: #eee; -} - -Button.argeo-suite-mainTab:hover { - cursor: pointer; - background-color: #eee; -} - -.argeo-suite-mainTabSelected { - font: bold 14px sans-serif; - color: white; - /*background-color: #00294b;*/ - background-color: #5882b5; - border:1px solid #888; -} - -ToolItem.argeo-suite-mainTabSelected { - border: none; -} - -ToolItem.argeo-suite-mainTabSelected:hover { - background-color: #5882b5; -} - -Button.argeo-suite-mainTabSelected { - border: none; -} - -Sash { - border: 1px solid white; - background-image: none; - background-color: white; -} - -Sash:hover { - border: 1px solid #5882b5; - background-color: #5882b5; -} - -TreeItem{ - background-color:#fff; -} - -Tree-RowOverlay:selected { - color:#fff; - background-color:#5882b5; -} - -TableItem{ - background-color:#fff; -} - -Table-RowOverlay:selected { - color:#fff; - background-color:#5882b5; -} - -.argeo-suite-navigationBar{ - background-color:#ddd; -} - -.argeo-suite-navigationTitle{ - background-color:#ddd; - font:bold 14px sans-serif; -} - -.argeo-suite-navigationButton{ - color:#777; - background-color:#ddd; - font:bold 14px sans-serif; -} - -.argeo-suite-navigationButton:hover{ - cursor:pointer; - color:#ddd; - background-color:#777; -} diff --git a/org.argeo.suite.theme.default/swt/app.css b/org.argeo.suite.theme.default/swt/app.css deleted file mode 100644 index 4ac745d..0000000 --- a/org.argeo.suite.theme.default/swt/app.css +++ /dev/null @@ -1,129 +0,0 @@ -.argeo-suite-header { - color: white; - background-color: #00294b; -} - -.argeo-suite-headerTitle { - font: bold 14px sans-serif; - color: white; - background-color: #00294b; -} - -.argeo-suite-leadPane { - background-color: #eee; -} - -Label.argeo-suite-leadPane { - font: 11px sans-serif; - color: #888; - background-color: #eee; -} - -Button.argeo-suite-leadPane:hover { - cursor: pointer; -} - -.argeo-suite-recentItems { - font: bold 13px sans-serif; - color: white; - background-color: #00294b; - padding: 8px 16px; -} - -.argeo-suite-titleContainer { - background-color: #00294b; -} - -.argeo-suite-titleLabel { - font: bold 13px sans-serif; - margin: 6px 8px 4px 8px; - color: white; - background-color: #00294b; -} - -.argeo-suite-subTitleLabel { - font: italic 14px sans-serif; - color: #777; - margin: 4px 8px; -} - -.argeo-suite-formLine { - padding: 4px 8px 4px 16px; -} - -.argeo-suite-simpleLabel { - font: normal 11px sans-serif; - border: 8px solid #eee; -} - -.argeo-suite-simpleText { - -} - -.argeo-suite-simpleInput { - padding: 4px 8px 4px 8px; -} - -.argeo-suite-titleCell { - font: bold 11px sans-serif; - background-color: #ddd; -} - -.argeo-suite-inlineButton { - padding: 0px 4px; - font: 12px sans-serif; - border: 1px solid white; - color: white; - background-image: none; - background-color: #00294b; -} - -.argeo-suite-inlineButton:hover { - color: #00294b; - background-color: white; -} - -Composite.argeo-suite-mainTabBody { - background-color: #eee; - border: 1px solid #bbb; -} - -.argeo-suite-mainTab { - background-color: #eee; - border: 1px solid #bbb; -} - -ToolItem.argeo-suite-mainTab { - border: none; - background-color: #eee; -} - -Button.argeo-suite-mainTab { - border: none; - background-color: #eee; -} - -.argeo-suite-mainTab:hover { - background-color: #eee; -} - -Button.argeo-suite-mainTab:hover { - cursor: pointer; - background-color: #eee; -} - -.argeo-suite-mainTabSelected { - font: bold 14px sans-serif; - color: white; - /*background-color: #00294b;*/ - background-color: #5882b5; - border: 1px solid #00294b; -} - -ToolItem.argeo-suite-mainTabSelected { - border: none; -} - -Button.argeo-suite-mainTabSelected { - border: none; -} \ No newline at end of file diff --git a/org.argeo.suite.ui.rap/.gitignore b/org.argeo.suite.ui.rap/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.suite.ui.rap/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.suite.ui.rap/.project b/org.argeo.suite.ui.rap/.project deleted file mode 100644 index eff6bb0..0000000 --- a/org.argeo.suite.ui.rap/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - org.argeo.suite.ui.rap - - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - - diff --git a/org.argeo.suite.ui.rap/META-INF/.gitignore b/org.argeo.suite.ui.rap/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.suite.ui.rap/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.suite.ui.rap/OSGI-INF/cmsWebApp.xml b/org.argeo.suite.ui.rap/OSGI-INF/cmsWebApp.xml deleted file mode 100644 index 4dfdcff..0000000 --- a/org.argeo.suite.ui.rap/OSGI-INF/cmsWebApp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.suite.ui.rap/bnd.bnd b/org.argeo.suite.ui.rap/bnd.bnd deleted file mode 100644 index 35b671b..0000000 --- a/org.argeo.suite.ui.rap/bnd.bnd +++ /dev/null @@ -1,6 +0,0 @@ -Service-Component: OSGI-INF/cmsWebApp.xml - -Import-Package:\ -org.argeo.cms.web,\ -org.eclipse.rap.rwt.application,\ -* diff --git a/org.argeo.suite.ui.rap/build.properties b/org.argeo.suite.ui.rap/build.properties deleted file mode 100644 index 6210e84..0000000 --- a/org.argeo.suite.ui.rap/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - OSGI-INF/ -source.. = src/ diff --git a/org.argeo.suite.ui.rap/pom.xml b/org.argeo.suite.ui.rap/pom.xml deleted file mode 100644 index 1ffe19e..0000000 --- a/org.argeo.suite.ui.rap/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.suite.ui.rap - Suite UI RAP - jar - - - org.argeo.suite - org.argeo.suite.ui - 2.1.18-SNAPSHOT - - - - - org.argeo.tp - argeo-tp-rap-e4 - ${version.argeo-tp} - pom - provided - - - diff --git a/org.argeo.suite.ui/.classpath b/org.argeo.suite.ui/.classpath deleted file mode 100644 index e801ebf..0000000 --- a/org.argeo.suite.ui/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/org.argeo.suite.ui/.gitignore b/org.argeo.suite.ui/.gitignore deleted file mode 100644 index 09e3bc9..0000000 --- a/org.argeo.suite.ui/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin/ -/target/ diff --git a/org.argeo.suite.ui/.project b/org.argeo.suite.ui/.project deleted file mode 100644 index 7146bab..0000000 --- a/org.argeo.suite.ui/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - org.argeo.suite.ui - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - org.eclipse.pde.ds.core.builder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/org.argeo.suite.ui/META-INF/.gitignore b/org.argeo.suite.ui/META-INF/.gitignore deleted file mode 100644 index 4854a41..0000000 --- a/org.argeo.suite.ui/META-INF/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/MANIFEST.MF diff --git a/org.argeo.suite.ui/OSGI-INF/cmsApp.xml b/org.argeo.suite.ui/OSGI-INF/cmsApp.xml deleted file mode 100644 index e42eeeb..0000000 --- a/org.argeo.suite.ui/OSGI-INF/cmsApp.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/org.argeo.suite.ui/OSGI-INF/dashboard.xml b/org.argeo.suite.ui/OSGI-INF/dashboard.xml deleted file mode 100644 index f678b5b..0000000 --- a/org.argeo.suite.ui/OSGI-INF/dashboard.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/org.argeo.suite.ui/OSGI-INF/dashboardLayer.xml b/org.argeo.suite.ui/OSGI-INF/dashboardLayer.xml deleted file mode 100644 index b60eafc..0000000 --- a/org.argeo.suite.ui/OSGI-INF/dashboardLayer.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/org.argeo.suite.ui/OSGI-INF/header.xml b/org.argeo.suite.ui/OSGI-INF/header.xml deleted file mode 100644 index a8fc66d..0000000 --- a/org.argeo.suite.ui/OSGI-INF/header.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties b/org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties deleted file mode 100644 index 3d08155..0000000 --- a/org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties +++ /dev/null @@ -1,98 +0,0 @@ -dashboard=dashboard -people=contacts -documents=documents -locations=locations -recentItems=recent items - -appTitle=Argeo Suite - -# -# PEOPLE -# org.argeo.people.ui.PeopleMsg -# -person=Person -organisation=Organisation - -# NewPersonWizard -firstName=First Name -lastName=Last Name -salutation=Salutation -email=Email -personWizardWindowTitle=New person -personWizardPageTitle=Create a contact - -# NewOrgWizard -legalName=Legal name -legalForm=Legal form -vatId=VAT ID -orgWizardWindowTitle=New organisation -orgWizardPageTitle=Create an organisation - - -# ContextAddressComposite -chooseAnOrganisation=Choose an organisation -street=Street -streetComplement=Street complement -zipCode=Zip code -city=City -state=State -country=Country -geopoint=Geopoint - -# FilteredOrderableEntityTable -filterHelp=Type filter criterion separated by a space - -# BankAccountComposite -accountHolder=Account holder -bankName=Bank name -currency=Currency -accountNumber=Account number -bankNumber=Bank number -BIC=BIC -IBAN=IBAN - -# EditJobDialog -position=Role -chosenItem=Chose item -department=Department -isPrimary=Is primary -searchAndChooseEntity=Search and choose a corresponding entity - -# ContactListCTab (e4) -notes=Notes -addAContact=Add a contact -contactValue=Contact value -linkedCompany=Linked company - -# OrgAdminInfoCTab (e4) -paymentAccount=Payment account - -# OrgEditor (e4) -orgDetails=Details -orgActivityLog=Activity log -team=Team -orgAdmin=Admin. - -# PersonEditor (e4) -personDetails=Contact details -personActivityLog=Activity log -personOrgs=Organisations -personSecurity=Security - -# PersonSecurityCTab (e4) -resetPassword=Reset password - -# Generic -label=Label -aCustomLabel=A custom label -description=Description -value=Value -name=Name -primary=Primary -add=Add -save=Save -pickUp=Pick up - -# Tags -confirmNewTag=Tag #{0} is not yet registered. Are you sure you want to create it? -cannotCreateTag=Tag #{0} is not yet registered and you don't have enough rights to create it. diff --git a/org.argeo.suite.ui/OSGI-INF/l10n/bundle_de.properties b/org.argeo.suite.ui/OSGI-INF/l10n/bundle_de.properties deleted file mode 100644 index 0af19c2..0000000 --- a/org.argeo.suite.ui/OSGI-INF/l10n/bundle_de.properties +++ /dev/null @@ -1,98 +0,0 @@ -dashboard=dashboard -people=Kontakte -documents=Dokumente -locations=Orte -recentItems=neulich - -appTitle=Argeo Suite - -# -# PEOPLE -# org.argeo.people.ui.PeopleMsg -# -person=Person -organisation=Organisation - -# NewPersonWizard -firstName=Vorname -lastName=Nachname -salutation=Salutation -email=E-Mail -personWizardWindowTitle=Neue Person -personWizardPageTitle=Kontakt erstellen - -# NewOrgWizard -legalName=Name -legalForm=Geschäftsform -vatId=Ust ID -orgWizardWindowTitle=Neue Organisation -orgWizardPageTitle=Organisation erstellen - - -# ContextAddressComposite -chooseAnOrganisation=Organisation wählen -street=Strasse -streetComplement=Strasse Zusatz -zipCode=PLZ -city=Stadt -state=Bundesland -country=Land -geopoint=Geopoint - -# FilteredOrderableEntityTable -filterHelp=Type filter criterion separated by a space - -# BankAccountComposite -accountHolder=Kontoinhaber -bankName=Name der Bank -currency=Währung -accountNumber=Kontonummer -bankNumber=BLZ -BIC=BIC -IBAN=IBAN - -# EditJobDialog -position=Rolle -chosenItem=Auswahl -department=Abteilung -isPrimary=Ist Primär -searchAndChooseEntity=Suche und wähle ein zugehöriges Objekt - -# ContactListCTab (e4) -notes=Bemerkungen -addAContact=Kontakt hinzufügen -contactValue=Kontakt value -linkedCompany=zugehörige Firma - -# OrgAdminInfoCTab (e4) -paymentAccount=Geschäftskonto - -# OrgEditor (e4) -orgDetails=Details -orgActivityLog=Aktivitäten Log -team=Team -orgAdmin=Admin. - -# PersonEditor (e4) -personDetails=Kontakt Daten -personActivityLog=Aktivitäten Log -personOrgs=Organisationen -personSecurity=Sicherheit - -# PersonSecurityCTab (e4) -resetPassword=Passwort zurücksetzen - -# Generic -label=Beschriftung -aCustomLabel=Eine spezifische Beschriftung -description=Beschreibung -value=Wert -name=Name -primary=Haupt- -add=Hinzufügen -save=Speichern -pickUp=Aussuchen - -# Tags -confirmNewTag=Das Hashtag '{0}' existiert noch nicht. WollenSie es hinzufügen? -cannotCreateTag=Das Hashtag '{0}' existiert nicht uns Sie haben nicht die Rechte, um es hinzufügen. diff --git a/org.argeo.suite.ui/OSGI-INF/l10n/bundle_fr.properties b/org.argeo.suite.ui/OSGI-INF/l10n/bundle_fr.properties deleted file mode 100644 index 225e5fd..0000000 --- a/org.argeo.suite.ui/OSGI-INF/l10n/bundle_fr.properties +++ /dev/null @@ -1,102 +0,0 @@ -dashboard=dashboard -people=contacts -documents=documents -locations=lieux -recentItems=récent - -appTitle=Argeo Suite - -# -# GENERIC -# - -# -# PEOPLE -# org.argeo.people.ui.PeopleMsg -# -person=Personne -organisation=Organisation - -# NewPersonWizard -firstName=Prénom -lastName=Nom -salutation=Salutation -email=Email -personWizardWindowTitle=Nouvelle personne -personWizardPageTitle=Créer un contact - -# NewOrgWizard -legalName=Nom -legalForm=Forme légale -vatId=ID TVA -orgWizardWindowTitle=Nouvelle organisation -orgWizardPageTitle=Créer une organisation - - -# ContextAddressComposite -chooseAnOrganisation=Choisir une organisation -street=Rue -streetComplement=Complément rue -zipCode=Code postal -city=Ville -state=État -country=Pays -geopoint=Géocoordonnées - -# FilteredOrderableEntityTable -filterHelp=Sasir les critères de filtrage séparés par des espaces - -# BankAccountComposite -accountHolder=Propriétaire du compte -bankName=Nom de la banque -currency=Devise -accountNumber=Numéro de compte -bankNumber=Numéro de banque -BIC=BIC -IBAN=IBAN - -# EditJobDialog -position=Rôle -chosenItem=Choisir une élément -department=Service -isPrimary=Principal -searchAndChooseEntity=Cherhcer et choisir l'entitée correspondante - -# ContactListCTab (e4) -notes=Notes -addAContact=Ajouter un contact -contactValue=Valeur -linkedCompany=Entreprise liée - -# OrgAdminInfoCTab (e4) -paymentAccount=Compte de paiement - -# OrgEditor (e4) -orgDetails=Détails -orgActivityLog=Activités -team=Équipe -orgAdmin=Admin. - -# PersonEditor (e4) -personDetails=Détails du contact -personActivityLog=Activités -personOrgs=Organisations -personSecurity=Accès - -# PersonSecurityCTab (e4) -resetPassword=Force le mot de passe - -# Generic -label=Étiquette -aCustomLabel=Une étiquette spécifique -description=Description -value=Valeur -name=Nom -primary=Principal -add=Ajouter -save=Sauver -pickUp=Choisir - -# Tags -confirmNewTag=Le tag #{0} n'existe pas encore. Voulez-vous le créer? -cannotCreateTag=Le tag #{0} n'existe pas encore et vous n'avez pas les droits pour le créer. diff --git a/org.argeo.suite.ui/OSGI-INF/leadPane.xml b/org.argeo.suite.ui/OSGI-INF/leadPane.xml deleted file mode 100644 index 9d3f2dd..0000000 --- a/org.argeo.suite.ui/OSGI-INF/leadPane.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - argeo.suite.ui.dashboardLayer -argeo.documents.ui.documentsLayer - - - diff --git a/org.argeo.suite.ui/OSGI-INF/loginScreen.xml b/org.argeo.suite.ui/OSGI-INF/loginScreen.xml deleted file mode 100644 index 0c5377a..0000000 --- a/org.argeo.suite.ui/OSGI-INF/loginScreen.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/org.argeo.suite.ui/OSGI-INF/recentItems.xml b/org.argeo.suite.ui/OSGI-INF/recentItems.xml deleted file mode 100644 index 8aaee16..0000000 --- a/org.argeo.suite.ui/OSGI-INF/recentItems.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/org.argeo.suite.ui/bnd.bnd b/org.argeo.suite.ui/bnd.bnd deleted file mode 100644 index b49d736..0000000 --- a/org.argeo.suite.ui/bnd.bnd +++ /dev/null @@ -1,18 +0,0 @@ -Service-Component:\ -OSGI-INF/cmsApp.xml,\ -OSGI-INF/header.xml,\ -OSGI-INF/leadPane.xml,\ -OSGI-INF/loginScreen.xml,\ -OSGI-INF/recentItems.xml,\ -OSGI-INF/dashboard.xml,\ -OSGI-INF/dashboardLayer.xml - -Import-Package:\ -org.argeo.api,\ -org.eclipse.swt,\ -org.osgi.framework,\ -org.argeo.entity,\ -org.eclipse.core.commands.common,\ -org.eclipse.jface.window,\ -org.eclipse.jface.dialogs,\ -* diff --git a/org.argeo.suite.ui/build.properties b/org.argeo.suite.ui/build.properties deleted file mode 100644 index d829967..0000000 --- a/org.argeo.suite.ui/build.properties +++ /dev/null @@ -1,10 +0,0 @@ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - OSGI-INF/,\ - config/,\ - OSGI-INF/loginScreen.xml,\ - OSGI-INF/dashboard.xml,\ - OSGI-INF/recentItems.xml,\ - OSGI-INF/dashboardLayer.xml -source.. = src/ diff --git a/org.argeo.suite.ui/config/cmsApp.properties b/org.argeo.suite.ui/config/cmsApp.properties deleted file mode 100644 index 1dec00e..0000000 --- a/org.argeo.suite.ui/config/cmsApp.properties +++ /dev/null @@ -1,3 +0,0 @@ -service.pid=argeo.suite.ui.app - -event.topics=argeo/suite/* \ No newline at end of file diff --git a/org.argeo.suite.ui/config/dashboard.properties b/org.argeo.suite.ui/config/dashboard.properties deleted file mode 100644 index 1832543..0000000 --- a/org.argeo.suite.ui/config/dashboard.properties +++ /dev/null @@ -1 +0,0 @@ -service.pid=argeo.suite.ui.dashboard diff --git a/org.argeo.suite.ui/config/dashboardLayer.properties b/org.argeo.suite.ui/config/dashboardLayer.properties deleted file mode 100644 index 79abe4c..0000000 --- a/org.argeo.suite.ui/config/dashboardLayer.properties +++ /dev/null @@ -1,4 +0,0 @@ -service.pid=argeo.suite.ui.dashboardLayer - -title=Dashboard -icon=dashboard \ No newline at end of file diff --git a/org.argeo.suite.ui/config/header.properties b/org.argeo.suite.ui/config/header.properties deleted file mode 100644 index 034d5f5..0000000 --- a/org.argeo.suite.ui/config/header.properties +++ /dev/null @@ -1,4 +0,0 @@ -service.pid=argeo.suite.ui.header -argeo.suite.ui=true - -argeo.suite.ui.header.title=%appTitle \ No newline at end of file diff --git a/org.argeo.suite.ui/config/leadPane.properties b/org.argeo.suite.ui/config/leadPane.properties deleted file mode 100644 index 0d7b193..0000000 --- a/org.argeo.suite.ui/config/leadPane.properties +++ /dev/null @@ -1 +0,0 @@ -service.pid=argeo.suite.ui.leadPane diff --git a/org.argeo.suite.ui/config/loginScreen.properties b/org.argeo.suite.ui/config/loginScreen.properties deleted file mode 100644 index 332614d..0000000 --- a/org.argeo.suite.ui/config/loginScreen.properties +++ /dev/null @@ -1 +0,0 @@ -service.pid=argeo.suite.ui.loginScreen diff --git a/org.argeo.suite.ui/config/recentItems.properties b/org.argeo.suite.ui/config/recentItems.properties deleted file mode 100644 index 7321c55..0000000 --- a/org.argeo.suite.ui/config/recentItems.properties +++ /dev/null @@ -1 +0,0 @@ -service.pid=argeo.suite.ui.recentItems diff --git a/org.argeo.suite.ui/pom.xml b/org.argeo.suite.ui/pom.xml deleted file mode 100644 index 114ed7c..0000000 --- a/org.argeo.suite.ui/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - - org.argeo.suite - argeo-suite - 2.1.18-SNAPSHOT - .. - - org.argeo.suite.ui - Suite UI - jar - - - org.argeo.suite - org.argeo.suite.core - 2.1.18-SNAPSHOT - - - org.argeo.suite - org.argeo.entity.ui - 2.1.18-SNAPSHOT - - - - - org.argeo.commons - org.argeo.eclipse.ui - ${version.argeo-commons} - - - org.argeo.commons - org.argeo.eclipse.ui.rap - ${version.argeo-commons} - provided - - - - - org.argeo.tp - argeo-tp-rap-e4 - ${version.argeo-tp} - pom - provided - - - diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java deleted file mode 100644 index 8c75f22..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/AdminEntryArea.java +++ /dev/null @@ -1,182 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.Set; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.CmsUserManager; -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.argeo.cms.ui.dialogs.CmsWizardDialog; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.Selected; -import org.argeo.naming.LdapAttrs; -import org.argeo.suite.SuiteRole; -import org.argeo.suite.ui.dialogs.NewUserWizard; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.window.Window; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; -import org.osgi.service.useradmin.User; - -/** Entry to the admin area. */ -public class AdminEntryArea implements CmsUiProvider { - - private CmsUserManager cmsUserManager; - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - CmsTheme theme = CmsTheme.getCmsTheme(parent); - parent.setLayout(new GridLayout()); - TableViewer usersViewer = new TableViewer(parent); - usersViewer.setContentProvider(new UsersContentProvider()); - - TableViewerColumn idCol = new TableViewerColumn(usersViewer, SWT.NONE); - idCol.getColumn().setWidth(70); - idCol.setLabelProvider(new ColumnLabelProvider() { - - @Override - public String getText(Object element) { - - return getUserProperty(element, LdapAttrs.uid.name()); - } - }); - - TableViewerColumn givenNameCol = new TableViewerColumn(usersViewer, SWT.NONE); - givenNameCol.getColumn().setWidth(150); - givenNameCol.setLabelProvider(new ColumnLabelProvider() { - - @Override - public String getText(Object element) { - - return getUserProperty(element, LdapAttrs.givenName.name()); - } - }); - - TableViewerColumn snCol = new TableViewerColumn(usersViewer, SWT.NONE); - snCol.getColumn().setWidth(150); - snCol.setLabelProvider(new ColumnLabelProvider() { - - @Override - public String getText(Object element) { - - return getUserProperty(element, LdapAttrs.sn.name()); - } - }); - - TableViewerColumn mailCol = new TableViewerColumn(usersViewer, SWT.NONE); - mailCol.getColumn().setWidth(400); - mailCol.setLabelProvider(new ColumnLabelProvider() { - - @Override - public String getText(Object element) { - - return getUserProperty(element, LdapAttrs.mail.name()); - } - }); - - Composite bottom = new Composite(parent, SWT.NONE); - bottom.setLayoutData(CmsUiUtils.fillWidth()); - bottom.setLayout(CmsUiUtils.noSpaceGridLayout()); - ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); - bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); - ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); - deleteItem.setEnabled(false); -// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); - deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); - ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); - addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); - usersViewer.addDoubleClickListener(new IDoubleClickListener() { - - @Override - public void doubleClick(DoubleClickEvent event) { - User user = (User) usersViewer.getStructuredSelection().getFirstElement(); - if (user != null) { -// Node userNode = getOrCreateUserNode(user, context); - CmsView.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), - SuiteEvent.eventProperties(user)); - } - - } - }); - usersViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - User user = (User) usersViewer.getStructuredSelection().getFirstElement(); - if (user != null) { -// Node userNode = getOrCreateUserNode(user, context); - CmsView.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), - SuiteEvent.eventProperties(user)); - deleteItem.setEnabled(true); - } else { - deleteItem.setEnabled(false); - } - } - }); - - addItem.addSelectionListener((Selected) (e) -> { - // SuiteUtils.getOrCreateUserNode(adminSession, userDn); - Wizard wizard = new NewUserWizard(null); - CmsWizardDialog dialog = new CmsWizardDialog(parent.getShell(), wizard); - // WizardDialog dialog = new WizardDialog(shell, wizard); - if (dialog.open() == Window.OK) { - // TODO create - } - }); - - usersViewer.getTable().setLayoutData(CmsUiUtils.fillAll()); - usersViewer.setInput(cmsUserManager); - - return usersViewer.getTable(); - } - -// private Node getOrCreateUserNode(User user, Node context) { -// return JcrUtils.mkdirs(Jcr.getSession(context), -// "/" + EntityType.user.name() + "/" + getUserProperty(user, LdapAttrs.uid.name()), -// EntityType.user.get()); -// } - - private String getUserProperty(Object element, String key) { - Object value = ((User) element).getProperties().get(key); - return value != null ? value.toString() : null; - } - - class UsersContentProvider implements IStructuredContentProvider { - - @Override - public Object[] getElements(Object inputElement) { - CmsUserManager cum = (CmsUserManager) inputElement; - Set users = cum.listUsersInGroup(SuiteRole.coworker.dn(), null); - return users.toArray(); - } - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - } - - public void setCmsUserManager(CmsUserManager cmsUserManager) { - this.cmsUserManager = cmsUserManager; - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultDashboard.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultDashboard.java deleted file mode 100644 index 9835b67..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultDashboard.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.argeo.suite.ui; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; - -/** Provides a dashboard. */ -public class DefaultDashboard implements CmsUiProvider { - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - parent.setLayout(new GridLayout()); - CmsView cmsView = CmsView.getCmsView(parent); - if (cmsView.isAnonymous()) - throw new IllegalStateException("No user is not logged in"); - - Label lbl = new Label(parent, SWT.NONE); - lbl.setText("Welcome " + CurrentUser.getDisplayName() + "!"); - - return lbl; - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java deleted file mode 100644 index 7b8bb3e..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.cms.ui.widgets.TabbedArea; -import org.argeo.util.LangUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** An app layer based on an entry area and an editor area. */ -public class DefaultEditionLayer implements SuiteLayer { - private CmsUiProvider entryArea; - private CmsUiProvider workArea; - private List weights = new ArrayList<>(); - private boolean startMaximized = false; - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - if (entryArea != null) { - SashFormEditionArea sashFormEditionArea = new SashFormEditionArea(parent, parent.getStyle()); - entryArea.createUi(sashFormEditionArea.getEntryArea(), context); - if (this.workArea != null) { - this.workArea.createUi(sashFormEditionArea.getEditorArea(), context); - } - return sashFormEditionArea; - } else { - if (this.workArea != null) { - Composite area = new Composite(parent, SWT.NONE); - this.workArea.createUi(area, context); - return area; - } - CmsTheme theme = CmsTheme.getCmsTheme(parent); - TabbedArea tabbedArea = createTabbedArea(parent, theme); - return tabbedArea; - } - } - - @Override - public void view(CmsUiProvider uiProvider, Composite workArea, Node context) { - TabbedArea tabbedArea; - if (workArea instanceof SashFormEditionArea) { - tabbedArea = ((SashFormEditionArea) workArea).getTabbedArea(); - } else if (workArea instanceof TabbedArea) { - tabbedArea = (TabbedArea) workArea; - } else - throw new IllegalArgumentException("Unsupported work area " + workArea.getClass().getName()); - tabbedArea.view(uiProvider, context); - } - - @Override - public void open(CmsUiProvider uiProvider, Composite workArea, Node context) { - TabbedArea tabbedArea = ((SashFormEditionArea) workArea).getTabbedArea(); - tabbedArea.open(uiProvider, context); - } - - public void init(Map properties) { - weights = LangUtils.toStringList(properties.get(Property.weights.name())); - startMaximized = properties.containsKey(Property.startMaximized.name()) - && "true".equals(properties.get(Property.startMaximized.name())); - } - - public void setEntryArea(CmsUiProvider entryArea) { - this.entryArea = entryArea; - } - - public void setWorkArea(CmsUiProvider workArea) { - this.workArea = workArea; - } - - TabbedArea createTabbedArea(Composite parent, CmsTheme theme) { - TabbedArea tabbedArea = new TabbedArea(parent, SWT.NONE); - tabbedArea.setBodyStyle(SuiteStyle.mainTabBody.style()); - tabbedArea.setTabStyle(SuiteStyle.mainTab.style()); - tabbedArea.setTabSelectedStyle(SuiteStyle.mainTabSelected.style()); - tabbedArea.setCloseIcon(SuiteIcon.close.getSmallIcon(theme)); - tabbedArea.setLayoutData(CmsUiUtils.fillAll()); - return tabbedArea; - } - - /** A work area based on an entry area and and a tabbed area. */ - class SashFormEditionArea extends SashForm { - private static final long serialVersionUID = 2219125778722702618L; - private CmsTheme theme; - private Composite entryArea; - private Composite editorArea; - private TabbedArea tabbedArea; - - SashFormEditionArea(Composite parent, int style) { - super(parent, SWT.HORIZONTAL); - theme = CmsTheme.getCmsTheme(parent); - - if (SWT.RIGHT_TO_LEFT == (style & SWT.RIGHT_TO_LEFT)) {// arabic, hebrew, etc. - editorArea = new Composite(this, SWT.BORDER); - entryArea = new Composite(this, SWT.BORDER); - } else { - entryArea = new Composite(this, SWT.NONE); - editorArea = new Composite(this, SWT.NONE); - } - - if (weights.size() != 0) { - int[] actualWeight = new int[weights.size()]; - for (int i = 0; i < weights.size(); i++) { - actualWeight[i] = Integer.parseInt(weights.get(i)); - } - setWeights(actualWeight); - } else { - int[] actualWeights = new int[] { 3000, 7000 }; - setWeights(actualWeights); - } - if (startMaximized) - setMaximizedControl(editorArea); - editorArea.setLayout(new GridLayout()); - - if (DefaultEditionLayer.this.workArea == null) { - tabbedArea = createTabbedArea(editorArea, theme); - } - - } - - Composite getEntryArea() { - return entryArea; - } - - TabbedArea getTabbedArea() { - return tabbedArea; - } - - Composite getEditorArea() { - return editorArea; - } - - } -} \ No newline at end of file diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultHeader.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultHeader.java deleted file mode 100644 index a251e14..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultHeader.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.Dictionary; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.LocaleUtils; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.util.LangUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.osgi.service.cm.ConfigurationException; -import org.osgi.service.cm.ManagedService; - -public class DefaultHeader implements CmsUiProvider, ManagedService { - public final static String TITLE_PROPERTY = "argeo.suite.ui.header.title"; - private Map properties; - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - CmsView cmsView = CmsView.getCmsView(parent); - CmsTheme theme = CmsTheme.getCmsTheme(parent); - - parent.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(3, true))); - - // TODO right to left - Composite lead = new Composite(parent, SWT.NONE); - CmsUiUtils.style(lead, SuiteStyle.header); - lead.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, false)); - lead.setLayout(new GridLayout()); - Label lbl = new Label(lead, SWT.NONE); - String title = properties.get(TITLE_PROPERTY); - lbl.setText(LocaleUtils.isLocaleKey(title) ? LocaleUtils.local(title, getClass().getClassLoader()).toString() - : title); - CmsUiUtils.style(lbl, SuiteStyle.headerTitle); - lbl.setLayoutData(CmsUiUtils.fillWidth()); - - Composite middle = new Composite(parent, SWT.NONE); - CmsUiUtils.style(middle, SuiteStyle.header); - middle.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false)); - middle.setLayout(new GridLayout()); - - Composite end = new Composite(parent, SWT.NONE); - CmsUiUtils.style(end, SuiteStyle.header); - end.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false)); - - if (!cmsView.isAnonymous()) { - end.setLayout(new GridLayout(2, false)); - Label userL = new Label(end, SWT.NONE); - CmsUiUtils.style(userL, SuiteStyle.header); - userL.setText(CurrentUser.getDisplayName()); - Button logoutB = new Button(end, SWT.FLAT); -// CmsUiUtils.style(logoutB, SuiteStyle.header); - logoutB.setImage(SuiteIcon.logout.getSmallIcon(theme)); - logoutB.addSelectionListener(new SelectionAdapter() { - private static final long serialVersionUID = 7116760083964201233L; - - @Override - public void widgetSelected(SelectionEvent e) { - cmsView.logout(); - } - - }); - } else { - end.setLayout(new GridLayout(1, false)); - // required in order to avoid wrong height after logout - new Label(end, SWT.NONE).setText(""); - - } - return lbl; - } - - public void init(Map properties) { - this.properties = new TreeMap<>(properties); - } - - @Override - public void updated(Dictionary properties) throws ConfigurationException { - if (properties != null) - this.properties.putAll(LangUtils.dictToStringMap(properties)); - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLeadPane.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLeadPane.java deleted file mode 100644 index a207e7a..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLeadPane.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.api.NodeConstants; -import org.argeo.cms.Localized; -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.argeo.suite.RankedObject; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.osgi.framework.Constants; - -/** Side pane listing various perspectives. */ -public class DefaultLeadPane implements CmsUiProvider { - private final static Log log = LogFactory.getLog(DefaultLeadPane.class); - - public static enum Property { - defaultLayers, adminLayers; - } - - private Map> layers = Collections.synchronizedSortedMap(new TreeMap<>()); - private String[] defaultLayers; - private String[] adminLayers; - - @Override - public Control createUi(Composite parent, Node node) throws RepositoryException { - CmsView cmsView = CmsView.getCmsView(parent); - GridLayout layout = new GridLayout(); - layout.verticalSpacing = 10; - layout.marginTop = 10; - layout.marginLeft = 10; - layout.marginRight = 10; - parent.setLayout(layout); - - Button first = null; - for (String layerId : defaultLayers) { - if (layers.containsKey(layerId)) { - RankedObject layerObj = layers.get(layerId); - - // TODO deal with i10n - String titleStr = (String) layerObj.getProperties().get(SuiteLayer.Property.title.name()); - Localized title = null; - if (titleStr != null) - title = new Localized.Untranslated(titleStr); - - String iconName = (String) layerObj.getProperties().get(SuiteLayer.Property.icon.name()); - SuiteIcon icon = null; - if (iconName != null) - icon = SuiteIcon.valueOf(iconName); - - Button b = SuiteUiUtils.createLayerButton(parent, layerId, title, icon); - if (first == null) - first = b; - } - } - - // TODO factorise - boolean isAdmin = cmsView.doAs(() -> CurrentUser.isInRole(NodeConstants.ROLE_USER_ADMIN)); - if (isAdmin && adminLayers != null) - for (String layerId : adminLayers) { - if (layers.containsKey(layerId)) { - RankedObject layerObj = layers.get(layerId); - - // TODO deal with i10n - String titleStr = (String) layerObj.getProperties().get(SuiteLayer.Property.title.name()); - Localized title = null; - if (titleStr != null) - title = new Localized.Untranslated(titleStr); - - String iconName = (String) layerObj.getProperties().get(SuiteLayer.Property.icon.name()); - SuiteIcon icon = null; - if (iconName != null) - icon = SuiteIcon.valueOf(iconName); - - Button b = SuiteUiUtils.createLayerButton(parent, layerId, title, icon); - if (first == null) - first = b; - } - } - -// Button dashboardB = createButton(parent, SuiteMsg.dashboard.name(), SuiteMsg.dashboard, SuiteIcon.dashboard); - if (!cmsView.isAnonymous()) { -// createButton(parent, SuiteMsg.documents.name(), SuiteMsg.documents, SuiteIcon.documents); -// createButton(parent, SuiteMsg.people.name(), SuiteMsg.people, SuiteIcon.people); -// createButton(parent, SuiteMsg.locations.name(), SuiteMsg.locations, SuiteIcon.location); - } - return first; - } - - public void init(Map properties) { - defaultLayers = (String[]) properties.get(Property.defaultLayers.toString()); - if (defaultLayers == null) - throw new IllegalArgumentException("Default layers must be set."); - if (log.isDebugEnabled()) - log.debug("Default layers: " + Arrays.asList(defaultLayers)); - adminLayers = (String[]) properties.get(Property.adminLayers.toString()); - if (log.isDebugEnabled() && adminLayers != null) - log.debug("Admin layers: " + Arrays.asList(adminLayers)); - } - - public void addLayer(SuiteLayer layer, Map properties) { - if (properties.containsKey(Constants.SERVICE_PID)) { - String pid = (String) properties.get(Constants.SERVICE_PID); - RankedObject.putIfHigherRank(layers, pid, layer, properties); - } - } - - public void removeLayer(SuiteLayer layer, Map properties) { - if (properties.containsKey(Constants.SERVICE_PID)) { - String pid = (String) properties.get(Constants.SERVICE_PID); - if (layers.containsKey(pid)) { - if (layers.get(pid).equals(new RankedObject(layer, properties))) { - layers.remove(pid); - } - } - } - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLoginScreen.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLoginScreen.java deleted file mode 100644 index 3757a19..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultLoginScreen.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.argeo.suite.ui; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.argeo.cms.ui.widgets.auth.CmsLogin; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** Provides a login screen. */ -public class DefaultLoginScreen implements CmsUiProvider { - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - CmsView cmsView = CmsView.getCmsView(parent); - if (!cmsView.isAnonymous()) - throw new IllegalStateException(CurrentUser.getUsername() + " is already logged in"); - - parent.setLayout(new GridLayout()); - Composite loginArea = new Composite(parent, SWT.NONE); - loginArea.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); - - CmsLogin cmsLogin = new CmsLogin(cmsView); - cmsLogin.createUi(loginArea); - return cmsLogin.getCredentialsBlock(); - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java deleted file mode 100644 index b9aa5b7..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java +++ /dev/null @@ -1,366 +0,0 @@ -package org.argeo.suite.ui; - -import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty; - -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import javax.jcr.query.Query; -import javax.jcr.query.QueryResult; - -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.entity.EntityType; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrUtils; -import org.argeo.suite.ui.widgets.DelayedText; -import org.argeo.suite.util.XPathUtils; -import org.eclipse.jface.layout.TableColumnLayout; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.DoubleClickEvent; -import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -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.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.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; - -/** List recent items. */ -public class RecentItems implements CmsUiProvider { - private final static int SEARCH_TEXT_DELAY = 800; - private final static int SEARCH_DEFAULT_LIMIT = 100; - - private CmsTheme theme; - - private String entityType; - - static enum Property { - entityTypes; - } - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - theme = CmsTheme.getCmsTheme(parent); - parent.setLayout(new GridLayout()); -// parent.setLayout(CmsUiUtils.noSpaceGridLayout()); - parent.setLayout(new GridLayout()); - -// Composite top = new Composite(parent, SWT.BORDER); -// CmsUiUtils.style(top, SuiteStyle.recentItems); -// top.setLayoutData(CmsUiUtils.fillWidth()); -// top.setLayout(CmsUiUtils.noSpaceGridLayout(2)); -// Label lbl = new Label(top, SWT.FLAT); -// lbl.setLayoutData(CmsUiUtils.fillWidth()); -// lbl.setText(SuiteMsg.recentItems.lead()); -// CmsUiUtils.style(lbl, SuiteStyle.recentItems); -// -// ToolBar topToolBar = new ToolBar(top, SWT.NONE); -// ToolItem addItem = new ToolItem(topToolBar, SWT.FLAT); -//// CmsUiUtils.style(addItem, SuiteStyle.recentItems); -// addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); - - if (context == null) - return null; - SingleEntityViewer entityViewer = new SingleEntityViewer(parent, SWT.NONE, context.getSession()); - entityViewer.createUi(); - entityViewer.getViewer().getTable().setLayoutData(CmsUiUtils.fillAll()); - - Composite bottom = new Composite(parent, SWT.NONE); - bottom.setLayoutData(CmsUiUtils.fillWidth()); - bottom.setLayout(CmsUiUtils.noSpaceGridLayout()); - ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); - bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); - ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); - deleteItem.setEnabled(false); -// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); - deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); - ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); - addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); - entityViewer.getViewer().addDoubleClickListener(new IDoubleClickListener() { - - @Override - public void doubleClick(DoubleClickEvent event) { - Node node = (Node) entityViewer.getViewer().getStructuredSelection().getFirstElement(); - if (node != null) - CmsView.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), - SuiteEvent.eventProperties(node)); - - } - }); - entityViewer.getViewer().addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - Node node = (Node) entityViewer.getViewer().getStructuredSelection().getFirstElement(); - if (node != null) { - CmsView.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), - SuiteEvent.eventProperties(node)); - deleteItem.setEnabled(true); - } else { - deleteItem.setEnabled(false); - } - } - }); - - return entityViewer.filterTxt; - - } - - public void init(Map properties) { - // TODO manage multiple entities - entityType = properties.get(Property.entityTypes.name()); - } - - class SingleEntityViewer { - Composite parent; - Text filterTxt; - TableViewer viewer; - Session session; - - public SingleEntityViewer(Composite parent, int style, Session session) { - this.parent = parent; - this.session = session; - } - - public void createUi() { - // MainLayout - addFilterPanel(parent); - viewer = createListPart(parent, new SingleEntityLabelProvider()); - refreshFilteredList(); - - try { - String[] nodeTypes = entityType != null && entityType.contains(":") ? new String[] { entityType } - : null; - session.getWorkspace().getObservationManager().addEventListener(new EventListener() { - - @Override - public void onEvent(EventIterator events) { - parent.getDisplay().asyncExec(() -> refreshFilteredList()); - } - }, Event.PROPERTY_CHANGED | Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED, "/", true, - null, nodeTypes, false); - } catch (RepositoryException e) { - throw new IllegalStateException("Cannot add JCR observer", e); - } - - } - - private void addFilterPanel(Composite parent) { - // Use a delayed text: the query won't be done until the user stop - // typing for 800ms - int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL; - DelayedText delayedText = new DelayedText(parent, style, SEARCH_TEXT_DELAY); - filterTxt = delayedText.getText(); - filterTxt.setLayoutData(EclipseUiUtils.fillWidth()); - - // final ServerPushSession pushSession = new ServerPushSession(); - delayedText.addDelayedModifyListener(null, new ModifyListener() { - private static final long serialVersionUID = 5003010530960334977L; - - public void modifyText(ModifyEvent event) { - delayedText.getText().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - refreshFilteredList(); - } - }); - // pushSession.stop(); - } - }); - - // Jump to the first item of the list using the down arrow - filterTxt.addKeyListener(new KeyListener() { - private static final long serialVersionUID = -4523394262771183968L; - - @Override - public void keyReleased(KeyEvent e) { - } - - @Override - public void keyPressed(KeyEvent e) { - // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0; - // boolean altPressed = (e.stateMask & SWT.ALT) != 0; - if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) { -// Object first = entityViewer.getElementAt(0); -// if (first != null) { -// entityViewer.getTable().setFocus(); -// entityViewer.setSelection(new StructuredSelection(first), true); -// } - e.doit = false; - } - } - }); - - parent.addDisposeListener((e) -> { - delayedText.close(); - }); - } - - protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) { -// parent.setLayout(new GridLayout()); -// parent.setLayout(CmsUiUtils.noSpaceGridLayout()); - - Composite tableComposite = new Composite(parent, SWT.NONE); - GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL - | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL); - tableComposite.setLayoutData(gd); - - TableViewer viewer = new TableViewer(tableComposite, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); - viewer.setLabelProvider(labelProvider); - - TableColumn singleColumn = new TableColumn(viewer.getTable(), SWT.V_SCROLL); - TableColumnLayout tableColumnLayout = new TableColumnLayout(); - tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(85)); - tableComposite.setLayout(tableColumnLayout); - - // Corresponding table & style - Table table = viewer.getTable(); -// Listener[] mouseDownListeners = table.getListeners(SWT.MouseDown); -// for (Listener listener : table.getListeners(SWT.MouseDown)) -// table.removeListener(SWT.MouseDown, listener); -// for (Listener listener : table.getListeners(SWT.MouseUp)) -// table.removeListener(SWT.MouseUp, listener); -// for (Listener listener : table.getListeners(SWT.MouseDoubleClick)) -// table.removeListener(SWT.MouseDoubleClick, listener); -// -// table.addMouseListener(new MouseListener() { -// -// @Override -// public void mouseUp(MouseEvent e) { -// System.out.println("Mouse up: "+e); -// } -// -// @Override -// public void mouseDown(MouseEvent e) { -// System.out.println("Mouse down: "+e); -// } -// -// @Override -// public void mouseDoubleClick(MouseEvent e) { -// System.out.println("Mouse double: "+e); -// -// } -// }); - table.setLinesVisible(true); - table.setHeaderVisible(false); - // CmsUiUtils.markup(table); - // CmsUiUtils.setItemHeight(table, 26); - - viewer.setContentProvider(new BasicNodeListContentProvider()); - return viewer; - } - -// public boolean setFocus() { -// refreshFilteredList(); -// return parent.setFocus(); -// } - - public void forceRefresh(Object object) { - refreshFilteredList(); - } - - protected void refreshFilteredList() { - try { - String filter = filterTxt.getText(); - // Prevents the query on the full repository - // if (isEmpty(filter)) { - // entityViewer.setInput(null); - // return; - // } - - // XPATH Query - String xpathQueryStr; - if (entityType != null) { - int indexColumn = entityType.indexOf(':'); - if (indexColumn > 0) {// JCR node type - xpathQueryStr = "//element(*, " + entityType + ") order by @jcr:created descending"; - } else { - xpathQueryStr = entityType.contains(":") ? "//element(*, " + entityType + ")" - : "//element(*, " + EntityType.entity.get() + ")[@entity:type='" + entityType + "']"; - } - } else { - xpathQueryStr = "//element(*, " + EntityType.entity.get() + ")"; - } -// String xpathQueryStr = "//element(*, " + ConnectTypes.CONNECT_ENTITY + ")"; - String xpathFilter = XPathUtils.getFreeTextConstraint(filter); - if (notEmpty(xpathFilter)) - xpathQueryStr += "[" + xpathFilter + "]"; - -// long begin = System.currentTimeMillis(); - // session.refresh(false); - Query xpathQuery = XPathUtils.createQuery(session, xpathQueryStr); - - xpathQuery.setLimit(SEARCH_DEFAULT_LIMIT); - QueryResult result = xpathQuery.execute(); - - NodeIterator nit = result.getNodes(); - viewer.setInput(JcrUtils.nodeIteratorToList(nit)); -// if (log.isTraceEnabled()) { -// long end = System.currentTimeMillis(); -// log.trace("Quick Search - Found: " + nit.getSize() + " in " + (end - begin) -// + " ms by executing XPath query (" + xpathQueryStr + ")."); -// } - } catch (RepositoryException e) { - throw new IllegalStateException("Unable to list entities", e); - } - } - - public TableViewer getViewer() { - return viewer; - } - - class SingleEntityLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -2209337675781795677L; - - @Override - public String getText(Object element) { - return Jcr.getTitle((Node) element); - } - - } - - class BasicNodeListContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = 1L; - // keep a cache of the Nodes in the content provider to be able to - // manage long request - private List nodes; - - public void dispose() { - } - - /** Expects a list of nodes as a new input */ - @SuppressWarnings("unchecked") - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - nodes = (List) newInput; - } - - public Object[] getElements(Object arg0) { - return nodes.toArray(); - } - } - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java deleted file mode 100644 index dbed853..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java +++ /dev/null @@ -1,517 +0,0 @@ -package org.argeo.suite.ui; - -import static org.argeo.cms.ui.CmsView.CMS_VIEW_UID_PROPERTY; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.naming.InvalidNameException; -import javax.naming.ldap.LdapName; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.api.NodeUtils; -import org.argeo.cms.CmsUserManager; -import org.argeo.cms.LocaleUtils; -import org.argeo.cms.auth.CmsSession; -import org.argeo.cms.ui.AbstractCmsApp; -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.CmsView; -import org.argeo.cms.ui.dialogs.CmsFeedback; -import org.argeo.cms.ui.util.CmsEvent; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.specific.UiContext; -import org.argeo.entity.EntityConstants; -import org.argeo.entity.EntityNames; -import org.argeo.entity.EntityType; -import org.argeo.jcr.Jcr; -import org.argeo.suite.RankedObject; -import org.argeo.suite.SuiteUtils; -import org.argeo.util.LangUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.osgi.framework.Constants; -import org.osgi.service.event.Event; -import org.osgi.service.event.EventHandler; -import org.osgi.service.useradmin.User; - -/** The Argeo Suite App. */ -public class SuiteApp extends AbstractCmsApp implements EventHandler { - private final static Log log = LogFactory.getLog(SuiteApp.class); - - public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath"; - public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName"; - public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId"; - - private String publicBasePath = null; - - private String pidPrefix; - private String headerPid; - private String leadPanePid; - private String loginScreenPid; -// private String DASHBOARD_PID = pidPrefix + "dashboard"; -// private String RECENT_ITEMS_PID = pidPrefix + "recentItems"; - - private String defaultUiName = "app"; - private String defaultThemeId = "org.argeo.suite.theme.default"; - - private Map> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>()); - private Map> uiProvidersByType = Collections.synchronizedMap(new HashMap<>()); - private Map> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>()); - private Map> layersByType = Collections.synchronizedSortedMap(new TreeMap<>()); - - private CmsUserManager cmsUserManager; - - // TODO make more optimal or via CmsSession/CmsView - private Map managedUis = new HashMap<>(); - -// private CmsUiProvider headerPart = null; - - public void init(Map properties) { - if (log.isDebugEnabled()) - log.info("Argeo Suite App started"); - - if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY)) - defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY); - if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY)) - defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY); - publicBasePath = LangUtils.get(properties, PUBLIC_BASE_PATH_PROPERTY); - - if (properties.containsKey(Constants.SERVICE_PID)) { - String servicePid = properties.get(Constants.SERVICE_PID).toString(); - if (servicePid.endsWith(".app")) { - pidPrefix = servicePid.substring(0, servicePid.length() - "app".length()); - } - } - - if (pidPrefix == null) - throw new IllegalArgumentException("PID prefix must be set."); - - headerPid = pidPrefix + "header"; - leadPanePid = pidPrefix + "leadPane"; - loginScreenPid = pidPrefix + "loginScreen"; - } - - public void destroy(Map properties) { - for (SuiteUi ui : managedUis.values()) - if (!ui.isDisposed()) - ui.dispose(); - if (log.isDebugEnabled()) - log.info("Argeo Suite App stopped"); - - } - - @Override - public Set getUiNames() { - HashSet uiNames = new HashSet<>(); - uiNames.add(defaultUiName); - return uiNames; - } - - @Override - public Composite initUi(Composite parent) { - String uiName = parent.getData(UI_NAME_PROPERTY) != null ? parent.getData(UI_NAME_PROPERTY).toString() : null; - CmsView cmsView = CmsView.getCmsView(parent); - if (cmsView == null) - throw new IllegalStateException("No CMS view is registered."); - CmsTheme theme = getTheme(uiName); - if (theme != null) - CmsTheme.registerCmsTheme(parent.getShell(), theme); - SuiteUi argeoSuiteUi = new SuiteUi(parent, SWT.INHERIT_DEFAULT); - String uid = cmsView.getUid(); - managedUis.put(uid, argeoSuiteUi); - argeoSuiteUi.addDisposeListener((e) -> { - managedUis.remove(uid); - if (log.isDebugEnabled()) - log.debug("Suite UI " + uid + " has been disposed."); - }); - refreshUi(argeoSuiteUi, null); - return argeoSuiteUi; - } - - @Override - public String getThemeId(String uiName) { - return defaultThemeId; - } - - @Override - public void refreshUi(Composite parent, String state) { - try { - Node context = null; - SuiteUi ui = (SuiteUi) parent; - CmsView cmsView = CmsView.getCmsView(parent); - if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login - ui.logout(); - refreshPart(findUiProvider(headerPid), ui.getHeader(), context); - ui.refreshBelowHeader(false); - refreshPart(findUiProvider(loginScreenPid), ui.getBelowHeader(), context); - ui.layout(true, true); - } else { - CmsSession cmsSession = cmsView.getCmsSession(); - if (ui.getUserDir() == null) { - if (cmsView.isAnonymous()) { - assert publicBasePath != null; - ui.initSessions(getRepository(), publicBasePath); - } else { - Session adminSession = null; - try { - adminSession = NodeUtils.openDataAdminSession(getRepository(), null); - Node userDir = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession); - ui.initSessions(getRepository(), userDir.getPath()); - } finally { - Jcr.logout(adminSession); - } - } - } - initLocale(cmsSession); - context = stateToNode(ui, state); - if (context == null) - context = ui.getUserDir(); - - refreshPart(findUiProvider(headerPid), ui.getHeader(), context); - ui.refreshBelowHeader(true); - for (String key : layersByPid.keySet()) { - SuiteLayer layer = layersByPid.get(key).get(); - ui.addLayer(key, layer); - } - refreshPart(findUiProvider(leadPanePid), ui.getLeadPane(), context); - ui.layout(true, true); - setState(parent, state); - } - } catch (Exception e) { - CmsFeedback.show("Unexpected exception", e); - } - } - - private void initLocale(CmsSession cmsSession) { - if (cmsSession == null) - return; - Locale locale = cmsSession.getLocale(); - UiContext.setLocale(locale); - LocaleUtils.setThreadLocale(locale); - - } - - private void refreshPart(CmsUiProvider uiProvider, Composite part, Node context) { - CmsUiUtils.clear(part); - uiProvider.createUiPart(part, context); - } - - private CmsUiProvider findUiProvider(String pid) { - if (!uiProvidersByPid.containsKey(pid)) - throw new IllegalArgumentException("No UI provider registered as " + pid); - return uiProvidersByPid.get(pid).get(); - } - - private T findByType(Map> byType, Node context) { - if (context == null) - throw new IllegalArgumentException("A node should be provided"); - try { - // mixins - Set types = new TreeSet<>(); - for (NodeType nodeType : context.getMixinNodeTypes()) { - String typeName = nodeType.getName(); - if (byType.containsKey(typeName)) { - types.add(typeName); - } - } - // primary node type - { - NodeType nodeType = context.getPrimaryNodeType(); - String typeName = nodeType.getName(); - if (byType.containsKey(typeName)) { - types.add(typeName); - } - for (NodeType mixin : nodeType.getDeclaredSupertypes()) { - if (byType.containsKey(mixin.getName())) { - types.add(mixin.getName()); - } - } - } - // entity type - if (context.isNodeType(EntityType.entity.get())) { - if (context.hasProperty(EntityNames.ENTITY_TYPE)) { - String typeName = context.getProperty(EntityNames.ENTITY_TYPE).getString(); - if (byType.containsKey(typeName)) { - types.add(typeName); - } - } - } - -// if (context.getPath().equals("/")) {// root node -// types.add("nt:folder"); -// } - if (NodeUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node - types.add("nt:folder"); - } - - if (types.size() == 0) - throw new IllegalArgumentException("No type found for " + context); - String type = types.iterator().next(); - if (!byType.containsKey(type)) - throw new IllegalArgumentException("No component found for " + context + " with type " + type); - return byType.get(type).get(); - } catch (RepositoryException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void setState(Composite parent, String state) { - if (state == null || state.equals("~")) - return; - if (!state.startsWith("/") && !state.equals("~")) { - if (parent instanceof SuiteUi) { - SuiteUi ui = (SuiteUi) parent; - String currentLayerId = ui.getCurrentLayerId(); - if (state.equals(currentLayerId)) - return; // does nothing - else { - Map properties = new HashMap<>(); - properties.put(SuiteEvent.LAYER, state); - ui.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), properties); - } - } - return; - } - SuiteUi suiteUi = (SuiteUi) parent; - Node node = stateToNode(suiteUi, state); - if (node == null) { - suiteUi.getCmsView().navigateTo("~"); - } else { - suiteUi.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), SuiteEvent.eventProperties(node)); - suiteUi.getCmsView().sendEvent(SuiteEvent.refreshPart.topic(), SuiteEvent.eventProperties(node)); - } - } - - private String nodeToState(Node node) { - return '/' + Jcr.getWorkspaceName(node) + Jcr.getPath(node); - } - - private Node stateToNode(SuiteUi suiteUi, String state) { - if (suiteUi == null) - return null; - if (state == null || !state.startsWith("/")) - return null; - - String path = state.substring(1); - String workspace; - if (path.equals("")) { - workspace = null; - path = "/"; - } else { - int index = path.indexOf('/'); - if (index == 0) { - log.error("Cannot interpret " + state); -// cmsView.navigateTo("~"); - return null; - } else if (index > 0) { - workspace = path.substring(0, index); - path = path.substring(index); - } else {// index<0, assuming root node - workspace = path; - path = "/"; - } - } - Session session = suiteUi.getSession(workspace); - if (session == null) - return null; - Node node = Jcr.getNode(session, path); - return node; - } - - /* - * Events management - */ - - @Override - public void handleEvent(Event event) { - - // Specific UI related events - SuiteUi ui = getRelatedUi(event); - if (ui == null) - return; - try { -// String currentLayerId = ui.getCurrentLayerId(); -// SuiteLayer currentLayer = currentLayerId != null ? layersByPid.get(currentLayerId).get() : null; - if (isTopic(event, SuiteEvent.refreshPart)) { - Node node = getNode(ui, event); - if (node == null) - return; - CmsUiProvider uiProvider = findByType(uiProvidersByType, node); - SuiteLayer layer = findByType(layersByType, node); - ui.switchToLayer(layer, node); - ui.getCmsView().runAs(() -> layer.view(uiProvider, ui.getCurrentWorkArea(), node)); - ui.getCmsView().stateChanged(nodeToState(node), Jcr.getTitle(node)); - } else if (isTopic(event, SuiteEvent.openNewPart)) { - Node node = getNode(ui, event); - if (node == null) - return; - CmsUiProvider uiProvider = findByType(uiProvidersByType, node); - SuiteLayer layer = findByType(layersByType, node); - ui.switchToLayer(layer, node); - ui.getCmsView().runAs(() -> layer.open(uiProvider, ui.getCurrentWorkArea(), node)); - ui.getCmsView().stateChanged(nodeToState(node), Jcr.getTitle(node)); - } else if (isTopic(event, SuiteEvent.switchLayer)) { - String layerId = get(event, SuiteEvent.LAYER); - if (layerId != null) { -// ui.switchToLayer(layerId, ui.getUserDir()); - ui.getCmsView().runAs(() -> ui.switchToLayer(layerId, ui.getUserDir())); - ui.getCmsView().navigateTo(layerId); - } else { - Node node = getNode(ui, event); - if (node != null) { - SuiteLayer layer = findByType(layersByType, node); - ui.getCmsView().runAs(() -> ui.switchToLayer(layer, node)); - } - } - } - } catch (Exception e) { - log.error("Cannot handle event " + event, e); -// CmsView.getCmsView(ui).exception(e); - } - - } - - private Node getNode(SuiteUi ui, Event event) { - String nodePath = get(event, SuiteEvent.NODE_PATH); - String workspaceName = get(event, SuiteEvent.WORKSPACE); - Session session = ui.getSession(workspaceName); - Node node; - if (nodePath == null) { - // look for a user - String username = get(event, SuiteEvent.USERNAME); - if (username == null) - return null; - User user = cmsUserManager.getUser(username); - if (user == null) - return null; - LdapName userDn; - try { - userDn = new LdapName(user.getName()); - } catch (InvalidNameException e) { - throw new IllegalArgumentException("Badly formatted username", e); - } - String userNodePath = SuiteUtils.getUserNodePath(userDn); - if (Jcr.itemExists(session, userNodePath)) - node = Jcr.getNode(session, userNodePath); - else { - Session adminSession = null; - try { - adminSession = NodeUtils.openDataAdminSession(getRepository(), workspaceName); - SuiteUtils.getOrCreateUserNode(adminSession, userDn); - } finally { - Jcr.logout(adminSession); - } - node = Jcr.getNode(session, userNodePath); - } - } else { - node = Jcr.getNode(session, nodePath); - } - return node; - } - - private SuiteUi getRelatedUi(Event event) { - return managedUis.get(get(event, CMS_VIEW_UID_PROPERTY)); - } - - private static boolean isTopic(Event event, CmsEvent cmsEvent) { - return event.getTopic().equals(cmsEvent.topic()); - } - - private static String get(Event event, String key) { - Object value = event.getProperty(key); - if (value == null) - return null; -// throw new IllegalArgumentException("Property " + key + " must be set"); - return value.toString(); - - } - - /* - * Dependency injection. - */ - - public void addUiProvider(CmsUiProvider uiProvider, Map properties) { - if (properties.containsKey(Constants.SERVICE_PID)) { - String pid = (String) properties.get(Constants.SERVICE_PID); - RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties); - } - if (properties.containsKey(EntityConstants.TYPE)) { - List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); - for (String type : types) - RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties); - } - } - - public void removeUiProvider(CmsUiProvider uiProvider, Map properties) { - if (properties.containsKey(Constants.SERVICE_PID)) { - String pid = (String) properties.get(Constants.SERVICE_PID); - if (uiProvidersByPid.containsKey(pid)) { - if (uiProvidersByPid.get(pid).equals(new RankedObject(uiProvider, properties))) { - uiProvidersByPid.remove(pid); - } - } - } - if (properties.containsKey(EntityConstants.TYPE)) { - List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); - for (String type : types) { - if (uiProvidersByType.containsKey(type)) { - if (uiProvidersByType.get(type).equals(new RankedObject(uiProvider, properties))) { - uiProvidersByType.remove(type); - } - } - } - } - } - - public void addLayer(SuiteLayer layer, Map properties) { - if (properties.containsKey(Constants.SERVICE_PID)) { - String pid = (String) properties.get(Constants.SERVICE_PID); - RankedObject.putIfHigherRank(layersByPid, pid, layer, properties); - } - if (properties.containsKey(EntityConstants.TYPE)) { - List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); - for (String type : types) - RankedObject.putIfHigherRank(layersByType, type, layer, properties); - } - } - - public void removeLayer(SuiteLayer layer, Map properties) { - if (properties.containsKey(Constants.SERVICE_PID)) { - String pid = (String) properties.get(Constants.SERVICE_PID); - if (layersByPid.containsKey(pid)) { - if (layersByPid.get(pid).equals(new RankedObject(layer, properties))) { - layersByPid.remove(pid); - } - } - } - if (properties.containsKey(EntityConstants.TYPE)) { - List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); - for (String type : types) { - if (layersByType.containsKey(type)) { - if (layersByType.get(type).equals(new RankedObject(layer, properties))) { - layersByType.remove(type); - } - } - } - } - } - - public void setCmsUserManager(CmsUserManager cmsUserManager) { - this.cmsUserManager = cmsUserManager; - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java deleted file mode 100644 index 563cd21..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteEvent.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Node; - -import org.argeo.cms.ui.util.CmsEvent; -import org.argeo.jcr.Jcr; -import org.osgi.service.useradmin.User; - -/** Events specific to Argeo Suite. */ -public enum SuiteEvent implements CmsEvent { - openNewPart, refreshPart, switchLayer; - - public final static String LAYER = "layer"; -// public final static String NODE_ID = "nodeId"; - public final static String NODE_PATH = "path"; - public final static String USERNAME = "username"; - public final static String WORKSPACE = "workspace"; - - public String getTopicBase() { - return "argeo/suite/ui"; - } - - public static Map eventProperties(Node node) { - Map properties = new HashMap<>(); - properties.put(NODE_PATH, Jcr.getPath(node)); - properties.put(WORKSPACE, Jcr.getWorkspaceName(node)); - return properties; - } - - public static Map eventProperties(User user) { - Map properties = new HashMap<>(); - properties.put(USERNAME, user.getName()); - return properties; - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteIcon.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteIcon.java deleted file mode 100644 index e40ba5a..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteIcon.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.argeo.suite.ui; - -import org.argeo.cms.ui.util.CmsIcon; - -/** Icon names used by Argeo Suite. */ -public enum SuiteIcon implements CmsIcon { - add, save, close, search, delete, logout, dashboard, - // people - people, person, organisation, - // library - documents, document, folder, - // admin and settings - settings, user, - // misc - task, tag, location, inbox, map; -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java deleted file mode 100644 index 8af7611..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.suite.ui; - -import javax.jcr.Node; - -import org.argeo.cms.ui.CmsUiProvider; -import org.eclipse.swt.widgets.Composite; - -/** An UI layer for the main work area. */ -public interface SuiteLayer extends CmsUiProvider { - static enum Property { - title, icon, weights, startMaximized; - } - - void view(CmsUiProvider uiProvider, Composite workArea, Node context); - - default void open(CmsUiProvider uiProvider, Composite workArea, Node context) { - view(uiProvider, workArea, context); - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java deleted file mode 100644 index 3b376db..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.argeo.suite.ui; - -import org.argeo.cms.Localized; - -/** Localized messages. */ -public enum SuiteMsg implements Localized { - dashboard, people, documents, locations, recentItems, - // NewPersonWizard - firstName, lastName, salutation, email, personWizardWindowTitle, personWizardPageTitle, - // NewOrgWizard - orgWizardWindowTitle, orgWizardPageTitle, legalName, legalForm, vatId, - // ContextAddressComposite - chooseAnOrganisation, street, streetComplement, zipCode, city, state, country, geopoint, - // FilteredOrderableEntityTable - filterHelp, - // BankAccountComposite - accountHolder, bankName, currency, accountNumber, bankNumber, BIC, IBAN, - // EditJobDialog - position, chosenItem, department, isPrimary, searchAndChooseEntity, - // ContactListCTab (e4) - notes, addAContact, contactValue, linkedCompany, - // OrgAdminInfoCTab (e4) - paymentAccount, - // OrgEditor (e4) - orgDetails, orgActivityLog, team, orgAdmin, - // PersonEditor (e4) - personDetails, personActivityLog, personOrgs, personSecurity, - // PersonSecurityCTab (e4) - resetPassword, - // Generic - label, aCustomLabel, description, value, name, primary, add, save, pickup, - // Tag - confirmNewTag, cannotCreateTag; -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java deleted file mode 100644 index 5183fa4..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.argeo.suite.ui; - -import org.argeo.cms.ui.util.CmsStyle; - -/** Styles used by Argeo Suite work UI. */ -public enum SuiteStyle implements CmsStyle { - // Header - header, headerTitle, headerMenu, headerMenuItem, - // Recent items - recentItems, - // Lead pane - leadPane, leadPaneItem, leadPaneSectionTitle, leadPaneSubSectionTitle, - // Group composite - titleContainer, titleLabel, subTitleLabel, formLine, formColumn, navigationBar, navigationTitle, navigationButton, - // Forms elements - simpleLabel, simpleText, simpleInput, - // table - titleCell, - // layers - workArea, - // tabbed area - mainTabBody, mainTabSelected, mainTab, - // Buttons - inlineButton; - - @Override - public String getClassPrefix() { - return "argeo-suite"; - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java deleted file mode 100644 index b245762..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.api.NodeConstants; -import org.argeo.cms.ui.CmsView; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.jcr.Jcr; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.FormLayout; -import org.eclipse.swt.widgets.Composite; - -/** The view for the default ergonomics of Argeo Suite. */ -class SuiteUi extends Composite { - private static final long serialVersionUID = 6207018859086689108L; - private final static Log log = LogFactory.getLog(SuiteUi.class); - private Composite header; - private Composite belowHeader; - private Composite leadPane; - private Composite dynamicArea; - - private Session sysSession; -// private Session homeSession; - private Node userDir; - - private Map layers = new HashMap<>(); - private Map workAreas = new HashMap<>(); - private String currentLayerId = null; - - private CmsView cmsView; - - public SuiteUi(Composite parent, int style) { - super(parent, style); - cmsView = CmsView.getCmsView(parent); - this.setLayout(CmsUiUtils.noSpaceGridLayout()); - - header = new Composite(this, SWT.NONE); - header.setLayout(CmsUiUtils.noSpaceGridLayout()); - CmsUiUtils.style(header, SuiteStyle.header); - header.setLayoutData(CmsUiUtils.fillWidth()); - - belowHeader = new Composite(this, SWT.NONE); - belowHeader.setLayoutData(CmsUiUtils.fillAll()); - } - - public void refreshBelowHeader(boolean initApp) { - CmsUiUtils.clear(belowHeader); - int style = getStyle(); - if (initApp) { - belowHeader.setLayout(CmsUiUtils.noSpaceGridLayout(2)); - - if (SWT.RIGHT_TO_LEFT == (style & SWT.RIGHT_TO_LEFT)) {// arabic, hebrew, etc. - dynamicArea = new Composite(belowHeader, SWT.NONE); - leadPane = new Composite(belowHeader, SWT.NONE); - } else { - leadPane = new Composite(belowHeader, SWT.NONE); - dynamicArea = new Composite(belowHeader, SWT.NONE); - } - leadPane.setLayoutData(CmsUiUtils.fillHeight()); - leadPane.setLayout(CmsUiUtils.noSpaceGridLayout()); - CmsUiUtils.style(leadPane, SuiteStyle.leadPane); - - dynamicArea.setLayoutData(CmsUiUtils.fillAll()); - dynamicArea.setLayout(new FormLayout()); - - } else { - belowHeader.setLayout(CmsUiUtils.noSpaceGridLayout()); - } - } - - /* - * LAYERS - */ - - Composite getCurrentWorkArea() { - if (currentLayerId == null) - throw new IllegalStateException("No current layer"); - return workAreas.get(currentLayerId); - } - - String getCurrentLayerId() { - return currentLayerId; - } - - private Composite getLayer(String id, Node context) { - if (!layers.containsKey(id)) - return null; - if (!workAreas.containsKey(id)) - initLayer(id, layers.get(id), context); - return workAreas.get(id); - } - - Composite switchToLayer(String layerId, Node context) { - Composite current = null; - if (currentLayerId != null) { - current = getCurrentWorkArea(); - if (currentLayerId.equals(layerId)) - return current; - } - if (context == null) { - if (!cmsView.isAnonymous()) - context = userDir; - } - Composite toShow = getLayer(layerId, context); - if (toShow != null) { - currentLayerId = layerId; - if (!isDisposed()) { -// getDisplay().syncExec(() -> { - if (!toShow.isDisposed()) { - toShow.moveAbove(null); - } else { - log.warn("Cannot show work area because it is disposed."); - toShow = initLayer(layerId, layers.get(layerId), context); - toShow.moveAbove(null); - } - dynamicArea.layout(true, true); -// }); - } - return toShow; - } else { - return current; - } - } - - Composite switchToLayer(SuiteLayer layer, Node context) { - // TODO make it more robust - for (String layerId : layers.keySet()) { - SuiteLayer l = layers.get(layerId); - if (layer == l) { - return switchToLayer(layerId, context); - } - } - throw new IllegalArgumentException("Layer is not registered."); - } - - void addLayer(String id, SuiteLayer layer) { - layers.put(id, layer); - } - - void removeLayer(String id) { - layers.remove(id); - if (workAreas.containsKey(id)) { - Composite workArea = workAreas.remove(id); - if (!workArea.isDisposed()) - workArea.dispose(); - } - } - - protected Composite initLayer(String id, SuiteLayer layer, Node context) { - Composite workArea = cmsView.doAs(() -> (Composite) layer.createUiPart(dynamicArea, context)); - CmsUiUtils.style(workArea, SuiteStyle.workArea); - workArea.setLayoutData(CmsUiUtils.coverAll()); - workAreas.put(id, workArea); - return workArea; - } - - synchronized void logout() { - userDir = null; - Jcr.logout(sysSession); -// Jcr.logout(homeSession); - currentLayerId = null; - workAreas.clear(); - } - - /* - * GETTERS / SETTERS - */ - - Composite getHeader() { - return header; - } - - Composite getLeadPane() { - return leadPane; - } - - Composite getBelowHeader() { - return belowHeader; - } - -// Session getSysSession() { -// return sysSession; -// } -// - synchronized void initSessions(Repository repository, String userDirPath) throws RepositoryException { - this.sysSession = repository.login(); -// this.homeSession = repository.login(NodeConstants.HOME_WORKSPACE); - userDir = sysSession.getNode(userDirPath); - addDisposeListener((e) -> { - Jcr.logout(sysSession); -// Jcr.logout(homeSession); - }); - } - - Node getUserDir() { - return userDir; - } - - Session getSysSession() { - return sysSession; - } - - Session getSession(String workspaceName) { - if (workspaceName == null) - return sysSession; - if (NodeConstants.SYS_WORKSPACE.equals(workspaceName)) - return sysSession; -// else if (NodeConstants.HOME_WORKSPACE.equals(workspaceName)) -// return homeSession; - else - throw new IllegalArgumentException("Unknown workspace " + workspaceName); - } - - public CmsView getCmsView() { - return cmsView; - } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUiUtils.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUiUtils.java deleted file mode 100644 index 8e9a9d5..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUiUtils.java +++ /dev/null @@ -1,368 +0,0 @@ -package org.argeo.suite.ui; - -import java.io.IOException; -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.cms.Localized; -import org.argeo.cms.ui.CmsEditable; -import org.argeo.cms.ui.CmsTheme; -import org.argeo.cms.ui.dialogs.LightweightDialog; -import org.argeo.cms.ui.util.CmsIcon; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.entity.EntityNames; -import org.argeo.entity.EntityType; -import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.ScrolledComposite; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.graphics.ImageData; -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.Label; -import org.eclipse.swt.widgets.Text; - -/** UI utilities related to the APAF project. */ -public class SuiteUiUtils { - - /** Singleton. */ - private SuiteUiUtils() { - } - - /** creates a title bar composite with label and optional button */ - public static void addTitleBar(Composite parent, String title, Boolean isEditable) { - Composite titleBar = new Composite(parent, SWT.NONE); - titleBar.setLayoutData(CmsUiUtils.fillWidth()); - CmsUiUtils.style(titleBar, SuiteStyle.titleContainer); - - titleBar.setLayout(CmsUiUtils.noSpaceGridLayout(new GridLayout(2, false))); - Label titleLbl = new Label(titleBar, SWT.NONE); - titleLbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); - CmsUiUtils.style(titleLbl, SuiteStyle.titleLabel); - titleLbl.setText(title); - - if (isEditable) { - Button editBtn = new Button(titleBar, SWT.PUSH); - editBtn.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); - CmsUiUtils.style(editBtn, SuiteStyle.inlineButton); - editBtn.setText("Edit"); - } - } - - public static Label addFormLabel(Composite parent, String label) { - Label lbl = new Label(parent, SWT.WRAP); - lbl.setText(label); - // lbl.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, true)); - CmsUiUtils.style(lbl, SuiteStyle.simpleLabel); - return lbl; - } - - public static Text addFormTextField(Composite parent, String text, String message) { - return addFormTextField(parent, text, message, SWT.NONE); - } - - public static Text addFormTextField(Composite parent, String text, String message, int style) { - Text txt = new Text(parent, style); - if (text != null) - txt.setText(text); - if (message != null) - txt.setMessage(message); - txt.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, true, true)); - CmsUiUtils.style(txt, SuiteStyle.simpleText); - return txt; - } - - public static Text addFormInputField(Composite parent, String placeholder) { - Text txt = new Text(parent, SWT.BORDER); - - GridData gridData = CmsUiUtils.fillWidth(); - txt.setLayoutData(gridData); - - if (placeholder != null) - txt.setText(placeholder); - - CmsUiUtils.style(txt, SuiteStyle.simpleInput); - return txt; - } - - /** creates a single horizontal-block composite for key:value display */ - public static Text addFormLine(Composite parent, String label, String text) { - Composite lineComposite = new Composite(parent, SWT.NONE); - lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - lineComposite.setLayout(new GridLayout(2, false)); - CmsUiUtils.style(lineComposite, SuiteStyle.formLine); - addFormLabel(lineComposite, label); - Text txt = addFormTextField(lineComposite, text, null); - txt.setEditable(false); - txt.setLayoutData(CmsUiUtils.fillWidth()); - return txt; - } - - public static Text addFormLine(Composite parent, String label, Node node, String property, - CmsEditable cmsEditable) { - Composite lineComposite = new Composite(parent, SWT.NONE); - lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - lineComposite.setLayout(new GridLayout(2, false)); - CmsUiUtils.style(lineComposite, SuiteStyle.formLine); - addFormLabel(lineComposite, label); - String text = Jcr.get(node, property); -// int style = cmsEditable.isEditing() ? SWT.WRAP : SWT.WRAP; - Text txt = addFormTextField(lineComposite, text, null, SWT.WRAP); - if (cmsEditable != null && cmsEditable.isEditing()) { - txt.addModifyListener((e) -> { - Jcr.set(node, property, txt.getText()); - Jcr.save(node); - }); - } else { - txt.setEditable(false); - } - txt.setLayoutData(CmsUiUtils.fillWidth()); - return txt; - } - - public static Text addFormInput(Composite parent, String label, String placeholder) { - Composite lineComposite = new Composite(parent, SWT.NONE); - lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - lineComposite.setLayout(new GridLayout(2, false)); - CmsUiUtils.style(lineComposite, SuiteStyle.formLine); - addFormLabel(lineComposite, label); - Text txt = addFormInputField(lineComposite, placeholder); - txt.setLayoutData(CmsUiUtils.fillWidth()); - return txt; - } - - /** - * creates a single horizontal-block composite for key:value display, with - * offset value - */ - public static Text addFormLine(Composite parent, String label, String text, Integer offset) { - Composite lineComposite = new Composite(parent, SWT.NONE); - lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - lineComposite.setLayout(new GridLayout(3, false)); - CmsUiUtils.style(lineComposite, SuiteStyle.formLine); - Label offsetLbl = new Label(lineComposite, SWT.NONE); - GridData gridData = new GridData(); - gridData.widthHint = offset; - offsetLbl.setLayoutData(gridData); - addFormLabel(lineComposite, label); - Text txt = addFormTextField(lineComposite, text, null); - txt.setLayoutData(CmsUiUtils.fillWidth()); - return txt; - } - - /** creates a single vertical-block composite for key:value display */ - public static Text addFormColumn(Composite parent, String label, String text) { -// Composite columnComposite = new Composite(parent, SWT.NONE); -// columnComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); -// columnComposite.setLayout(new GridLayout(1, false)); - addFormLabel(parent, label); - Text txt = addFormTextField(parent, text, null); - txt.setEditable(false); - txt.setLayoutData(CmsUiUtils.fillWidth()); - return txt; - } - - public static Text addFormColumn(Composite parent, String label, Node node, String property, - CmsEditable cmsEditable) { -// Composite columnComposite = new Composite(parent, SWT.NONE); -// columnComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); -// columnComposite.setLayout(new GridLayout(1, false)); - addFormLabel(parent, label); - String text = Jcr.get(node, property); -// int style = cmsEditable.isEditing() ? SWT.WRAP : SWT.WRAP; - Text txt = addFormTextField(parent, text, null, SWT.WRAP); - if (cmsEditable != null && cmsEditable.isEditing()) { - txt.addModifyListener((e) -> { - Jcr.set(node, property, txt.getText()); - Jcr.save(node); - }); - } else { - txt.setEditable(false); - } - txt.setLayoutData(CmsUiUtils.fillWidth()); - return txt; - } - - public static Label createBoldLabel(Composite parent, Localized localized) { - Label label = new Label(parent, SWT.LEAD); - label.setText(localized.lead()); - label.setFont(EclipseUiUtils.getBoldFont(parent)); - label.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false)); - return label; - } - - public static Label addFormPicture(Composite parent, String label, Node fileNode) throws RepositoryException { - Composite lineComposite = new Composite(parent, SWT.NONE); - lineComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - lineComposite.setLayout(new GridLayout(2, true)); - CmsUiUtils.style(lineComposite, SuiteStyle.formLine); - addFormLabel(lineComposite, label); - - return addPicture(lineComposite, fileNode); - } - - public static Label addPicture(Composite parent, Node fileNode) throws RepositoryException { - return addPicture(parent, fileNode, null); - } - - public static Label addPicture(Composite parent, Node fileNode, Integer maxWidth) throws RepositoryException { - Node content = fileNode.getNode(Node.JCR_CONTENT); - // TODO move it deeper in the middleware. - if (!content.isNodeType(EntityType.box.get())) { - if (content.getSession().hasPermission(content.getPath(), Session.ACTION_SET_PROPERTY)) { - try (InputStream in = JcrUtils.getFileAsStream(fileNode)) { - ImageData imageData = new ImageData(in); - content.addMixin(EntityType.box.get()); - content.setProperty(EntityNames.SVG_WIDTH, imageData.width); - content.setProperty(EntityNames.SVG_HEIGHT, imageData.height); - content.getSession().save(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - // TODO optimise - Long width; - Long height; - if (content.isNodeType(EntityType.box.get())) { - width = content.getProperty(EntityNames.SVG_WIDTH).getLong(); - height = content.getProperty(EntityNames.SVG_HEIGHT).getLong(); - } else { - try (InputStream in = JcrUtils.getFileAsStream(fileNode)) { - ImageData imageData = new ImageData(in); - width = Long.valueOf(imageData.width); - height = Long.valueOf(imageData.height); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - if (maxWidth != null && width > maxWidth) { - Double ratio = maxWidth.doubleValue() / width.doubleValue(); - width = maxWidth.longValue(); - height = Math.round(ratio * height); - } - Label img = new Label(parent, SWT.NONE); - CmsUiUtils.markup(img); - img.setText(CmsUiUtils.img(fileNode, width.toString(), height.toString())); - if (parent.getLayout() instanceof GridLayout) { - GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); - gd.widthHint = width.intValue(); - gd.heightHint = height.intValue(); - img.setLayoutData(gd); - } - img.addMouseListener(new MouseListener() { - private static final long serialVersionUID = -1362242049325206168L; - - @Override - public void mouseUp(MouseEvent e) { - } - - @Override - public void mouseDown(MouseEvent e) { - } - - @Override - public void mouseDoubleClick(MouseEvent e) { - LightweightDialog dialog = new LightweightDialog(img.getShell()) { - - @Override - protected Control createDialogArea(Composite parent) { - parent.setLayout(new GridLayout()); - ScrolledComposite scroll = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL); - scroll.setLayoutData(CmsUiUtils.fillAll()); - scroll.setLayout(CmsUiUtils.noSpaceGridLayout()); - scroll.setExpandHorizontal(true); - scroll.setExpandVertical(true); - // scroll.setAlwaysShowScrollBars(true); - - Composite c = new Composite(scroll, SWT.NONE); - scroll.setContent(c); - c.setLayout(new GridLayout()); - c.setLayoutData(CmsUiUtils.fillAll()); - Label bigImg = new Label(c, SWT.NONE); - CmsUiUtils.markup(bigImg); - bigImg.setText(CmsUiUtils.img(fileNode, Jcr.get(content, EntityNames.SVG_WIDTH), - Jcr.get(content, EntityNames.SVG_HEIGHT))); - bigImg.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true)); - return bigImg; - } - - @Override - protected Point getInitialSize() { - Point shellSize = img.getShell().getSize(); - return new Point(shellSize.x - 100, shellSize.y - 100); - } - - }; - dialog.open(); - } - }); - return img; - } - - public static Button createLayerButton(Composite parent, String layer, Localized msg, CmsIcon icon) { - CmsTheme theme = CmsTheme.getCmsTheme(parent); - Button button = new Button(parent, SWT.PUSH); - CmsUiUtils.style(button, SuiteStyle.leadPane); - if (icon != null) - button.setImage(icon.getBigIcon(theme)); - button.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, false)); - // button.setToolTipText(msg.lead()); - if (msg != null) { - Label lbl = new Label(parent, SWT.NONE); - CmsUiUtils.style(lbl, SuiteStyle.leadPane); - lbl.setText(msg.lead()); - lbl.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false)); - } - CmsUiUtils.sendEventOnSelect(button, SuiteEvent.switchLayer.topic(), SuiteEvent.LAYER, layer); - return button; - } - -// public static String createAndConfigureEntity(Shell shell, Session referenceSession, String mainMixin, -// String... additionnalProps) { -// -// Session tmpSession = null; -// Session mainSession = null; -// try { -// // FIXME would not work if home is another physical workspace -// tmpSession = referenceSession.getRepository().login(NodeConstants.HOME_WORKSPACE); -// Node draftNode = null; -// for (int i = 0; i < additionnalProps.length - 1; i += 2) { -// draftNode.setProperty(additionnalProps[i], additionnalProps[i + 1]); -// } -// Wizard wizard = null; -// CmsWizardDialog dialog = new CmsWizardDialog(shell, wizard); -// // WizardDialog dialog = new WizardDialog(shell, wizard); -// if (dialog.open() == Window.OK) { -// String parentPath = null;// "/" + appService.getBaseRelPath(mainMixin); -// // FIXME it should be possible to specify the workspace -// mainSession = referenceSession.getRepository().login(); -// Node parent = mainSession.getNode(parentPath); -// Node task = null;// appService.publishEntity(parent, mainMixin, draftNode); -//// task = appService.saveEntity(task, false); -// referenceSession.refresh(true); -// return task.getPath(); -// } -// return null; -// } catch (RepositoryException e1) { -// throw new JcrException( -// "Unable to create " + mainMixin + " entity with session " + referenceSession.toString(), e1); -// } finally { -// JcrUtils.logoutQuietly(tmpSession); -// JcrUtils.logoutQuietly(mainSession); -// } -// } - -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java deleted file mode 100644 index 04d7a7b..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUserUiProvider.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.argeo.suite.ui; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.CmsUserManager; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.cms.ui.viewers.Section; -import org.argeo.naming.LdapAttrs; -import org.eclipse.swt.SWT; -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.Group; -import org.eclipse.swt.widgets.Text; -import org.osgi.service.useradmin.User; - -/** Edit a suite user. */ -public class SuiteUserUiProvider implements CmsUiProvider { - private String[] availableRoles; - private CmsUserManager cmsUserManager; - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - Section main = new Section(parent, SWT.NONE, context); - main.setLayoutData(CmsUiUtils.fillAll()); - - String uid = context.getName(); - User user = cmsUserManager.getUserFromLocalId(uid); - -// Text givenName = new Text(main, SWT.SINGLE); -// givenName.setText(getUserProperty(user, LdapAttrs.givenName.name())); - Text givenName = SuiteUiUtils.addFormInput(main, SuiteMsg.firstName.lead(), - getUserProperty(user, LdapAttrs.givenName.name())); - - Text sn = SuiteUiUtils.addFormInput(main, SuiteMsg.lastName.lead(), getUserProperty(user, LdapAttrs.sn.name())); - // sn.setText(getUserProperty(user, LdapAttrs.sn.name())); - - Text email = SuiteUiUtils.addFormInput(main, SuiteMsg.email.lead(), - getUserProperty(user, LdapAttrs.mail.name())); - // email.setText(getUserProperty(user, LdapAttrs.mail.name())); - - Text uidT = SuiteUiUtils.addFormLine(main, "uid", getUserProperty(user, LdapAttrs.uid.name())); - uidT.setText(uid); - -// Label dnL = new Label(main, SWT.NONE); -// dnL.setText(user.getName()); - - // roles - // Section rolesSection = new Section(main, SWT.NONE, context); - Group rolesSection = new Group(main, SWT.NONE); - rolesSection.setText("Roles"); - rolesSection.setLayoutData(CmsUiUtils.fillWidth()); - rolesSection.setLayout(new GridLayout()); - // new Label(rolesSection, SWT.NONE).setText("Roles:"); - List roles = Arrays.asList(cmsUserManager.getUserRoles(user.getName())); - for (String role : availableRoles) { - // new Label(rolesSection, SWT.NONE).setText(role); - Button radio = new Button(rolesSection, SWT.CHECK); - radio.setText(role); - if (roles.contains(role)) - radio.setSelection(true); - } - - return main; - } - - public void setCmsUserManager(CmsUserManager cmsUserManager) { - this.cmsUserManager = cmsUserManager; - } - - private String getUserProperty(Object element, String key) { - Object value = ((User) element).getProperties().get(key); - return value != null ? value.toString() : null; - } - - public void init(Map properties) { - availableRoles = (String[]) properties.get("availableRoles"); - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonPage.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonPage.java deleted file mode 100644 index ddd4488..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonPage.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.argeo.suite.ui.dialogs; - -import org.argeo.suite.ui.SuiteMsg; -import org.argeo.suite.ui.SuiteUiUtils; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; - -public class NewPersonPage extends WizardPage { - private static final long serialVersionUID = -944349994177526468L; - protected Text lastNameTxt; - protected Text firstNameTxt; - protected Text emailTxt; - - protected NewPersonPage(String pageName) { - super(pageName); - setTitle(SuiteMsg.personWizardPageTitle.lead()); - } - - @Override - public void createControl(Composite parent) { - parent.setLayout(new GridLayout(2, false)); - - // FirstName - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName); - firstNameTxt = new Text(parent, SWT.BORDER); - firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - // LastName - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName); - lastNameTxt = new Text(parent, SWT.BORDER); - lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.email); - emailTxt = new Text(parent, SWT.BORDER); - emailTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - ModifyListener ml = new ModifyListener() { - private static final long serialVersionUID = -1628130380128946886L; - - @Override - public void modifyText(ModifyEvent event) { - getContainer().updateButtons(); - } - }; - - firstNameTxt.addModifyListener(ml); - lastNameTxt.addModifyListener(ml); - emailTxt.addModifyListener(ml); - - // Don't forget this. - setControl(firstNameTxt); - firstNameTxt.setFocus(); - - } - -// public void updateNode(Node node, PeopleService peopleService, ResourcesService resourcesService) { -// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_LAST_NAME, PropertyType.STRING, lastNameTxt.getText()); -// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_FIRST_NAME, PropertyType.STRING, -// firstNameTxt.getText()); -// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_DISPLAY_NAME, PropertyType.STRING, -// firstNameTxt.getText() + " " + lastNameTxt.getText()); -// String email = emailTxt.getText(); -// ConnectJcrUtils.setJcrProperty(node, PeopleNames.PEOPLE_PRIMARY_EMAIL, PropertyType.STRING, email); -// PeopleJcrUtils.createEmail(resourcesService, peopleService, node, email, true, null, null); -// } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonWizard.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonWizard.java deleted file mode 100644 index 9db5e04..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewPersonWizard.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.argeo.suite.ui.dialogs; - -import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty; - -import javax.jcr.Node; - -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.suite.ui.SuiteMsg; -import org.argeo.suite.ui.SuiteUiUtils; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; - -/** Ask first & last name. Update the passed node on finish */ -public class NewPersonWizard extends Wizard { - // private final static Log log = LogFactory.getLog(NewPersonWizard.class); - - // Context - private Node person; - - // This page widgets - protected Text lastNameTxt; - protected Text firstNameTxt; - // private Button useDistinctDisplayNameBtn; - // private Text displayNameTxt; - - public NewPersonWizard(Node person) { - this.person = person; - } - - @Override - public void addPages() { - try { - MainInfoPage page = new MainInfoPage("Main page"); - addPage(page); - } catch (Exception e) { - throw new RuntimeException("Cannot add page to wizard", e); - } - setWindowTitle(SuiteMsg.personWizardWindowTitle.lead()); - } - - /** - * Called when the user click on 'Finish' in the wizard. The task is then - * created and the corresponding session saved. - */ - @Override - public boolean performFinish() { - String lastName = lastNameTxt.getText(); - String firstName = firstNameTxt.getText(); - // String displayName = displayNameTxt.getText(); - // boolean useDistinct = useDistinctDisplayNameBtn.getSelection(); - if (EclipseUiUtils.isEmpty(lastName) && EclipseUiUtils.isEmpty(firstName)) { - MessageDialog.openError(getShell(), "Non-valid information", - "Please enter at least a name that is not empty."); - return false; - } else { -// ConnectJcrUtils.setJcrProperty(person, PEOPLE_LAST_NAME, PropertyType.STRING, lastName); -// ConnectJcrUtils.setJcrProperty(person, PEOPLE_FIRST_NAME, PropertyType.STRING, firstName); -// String fullName = firstName + " " + lastName; -// ConnectJcrUtils.setJcrProperty(person, PEOPLE_DISPLAY_NAME, PropertyType.STRING, fullName); - return true; - } - } - - @Override - public boolean performCancel() { - return true; - } - - @Override - public boolean canFinish() { - String lastName = lastNameTxt.getText(); - String firstName = firstNameTxt.getText(); - if (isEmpty(lastName) && isEmpty(firstName)) { - return false; - } else - return true; - } - - protected class MainInfoPage extends WizardPage { - private static final long serialVersionUID = 1L; - - public MainInfoPage(String pageName) { - super(pageName); - setTitle(SuiteMsg.personWizardPageTitle.lead()); - // setMessage("Please enter a last name and/or a first name."); - } - - public void createControl(Composite parent) { - parent.setLayout(new GridLayout(2, false)); - - // FirstName - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName); - firstNameTxt = new Text(parent, SWT.BORDER); - // firstNameTxt.setMessage("a first name"); - firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - // LastName - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName); - lastNameTxt = new Text(parent, SWT.BORDER); - // lastNameTxt.setMessage("a last name"); - lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - // Display Name - // useDistinctDisplayNameBtn = new Button(parent, SWT.CHECK); - // useDistinctDisplayNameBtn.setText("Define a disting display name"); - // useDistinctDisplayNameBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, - // true, false, 2, 1)); - // - // ConnectWorkbenchUtils.createBoldLabel(parent, "Display Name"); - // displayNameTxt = new Text(parent, SWT.BORDER); - // displayNameTxt.setMessage("an optional display name"); - // displayNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, - // false)); - // displayNameTxt.setEnabled(false); - // - // useDistinctDisplayNameBtn.addSelectionListener(new SelectionAdapter() { - // private static final long serialVersionUID = 1L; - // - // @Override - // public void widgetSelected(SelectionEvent e) { - // displayNameTxt.setEnabled(useDistinctDisplayNameBtn.getSelection()); - // } - // }); - - ModifyListener ml = new ModifyListener() { - private static final long serialVersionUID = -1628130380128946886L; - - @Override - public void modifyText(ModifyEvent event) { - getContainer().updateButtons(); - } - }; - - firstNameTxt.addModifyListener(ml); - lastNameTxt.addModifyListener(ml); - // displayNameTxt.addModifyListener(ml); - - // Don't forget this. - setControl(firstNameTxt); - firstNameTxt.setFocus(); - } - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewUserWizard.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewUserWizard.java deleted file mode 100644 index 5b4575d..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/dialogs/NewUserWizard.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.argeo.suite.ui.dialogs; - -import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty; - -import javax.jcr.Node; - -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.suite.ui.SuiteMsg; -import org.argeo.suite.ui.SuiteUiUtils; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Text; - -/** Ask first & last name. Update the passed node on finish */ -public class NewUserWizard extends Wizard { - // private final static Log log = LogFactory.getLog(NewPersonWizard.class); - - // Context - private Node person; - - // This page widgets - protected Text lastNameTxt; - protected Text firstNameTxt; - // private Button useDistinctDisplayNameBtn; - // private Text displayNameTxt; - - public NewUserWizard(Node person) { - this.person = person; - } - - @Override - public void addPages() { - try { - MainInfoPage page = new MainInfoPage("Main page"); - addPage(page); - } catch (Exception e) { - throw new RuntimeException("Cannot add page to wizard", e); - } - setWindowTitle(SuiteMsg.personWizardWindowTitle.lead()); - } - - /** - * Called when the user click on 'Finish' in the wizard. The task is then - * created and the corresponding session saved. - */ - @Override - public boolean performFinish() { - String lastName = lastNameTxt.getText(); - String firstName = firstNameTxt.getText(); - // String displayName = displayNameTxt.getText(); - // boolean useDistinct = useDistinctDisplayNameBtn.getSelection(); - if (EclipseUiUtils.isEmpty(lastName) && EclipseUiUtils.isEmpty(firstName)) { - MessageDialog.openError(getShell(), "Non-valid information", - "Please enter at least a name that is not empty."); - return false; - } else { -// ConnectJcrUtils.setJcrProperty(person, PEOPLE_LAST_NAME, PropertyType.STRING, lastName); -// ConnectJcrUtils.setJcrProperty(person, PEOPLE_FIRST_NAME, PropertyType.STRING, firstName); -// String fullName = firstName + " " + lastName; -// ConnectJcrUtils.setJcrProperty(person, PEOPLE_DISPLAY_NAME, PropertyType.STRING, fullName); - return true; - } - } - - @Override - public boolean performCancel() { - return true; - } - - @Override - public boolean canFinish() { - String lastName = lastNameTxt.getText(); - String firstName = firstNameTxt.getText(); - if (isEmpty(lastName) && isEmpty(firstName)) { - return false; - } else - return true; - } - - protected class MainInfoPage extends WizardPage { - private static final long serialVersionUID = 1L; - - public MainInfoPage(String pageName) { - super(pageName); - setTitle(SuiteMsg.personWizardPageTitle.lead()); - // setMessage("Please enter a last name and/or a first name."); - } - - public void createControl(Composite parent) { - parent.setLayout(new GridLayout(2, false)); - - // FirstName - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.firstName); - firstNameTxt = new Text(parent, SWT.BORDER); - // firstNameTxt.setMessage("a first name"); - firstNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - // LastName - SuiteUiUtils.createBoldLabel(parent, SuiteMsg.lastName); - lastNameTxt = new Text(parent, SWT.BORDER); - // lastNameTxt.setMessage("a last name"); - lastNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - - // Display Name - // useDistinctDisplayNameBtn = new Button(parent, SWT.CHECK); - // useDistinctDisplayNameBtn.setText("Define a disting display name"); - // useDistinctDisplayNameBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, - // true, false, 2, 1)); - // - // ConnectWorkbenchUtils.createBoldLabel(parent, "Display Name"); - // displayNameTxt = new Text(parent, SWT.BORDER); - // displayNameTxt.setMessage("an optional display name"); - // displayNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, - // false)); - // displayNameTxt.setEnabled(false); - // - // useDistinctDisplayNameBtn.addSelectionListener(new SelectionAdapter() { - // private static final long serialVersionUID = 1L; - // - // @Override - // public void widgetSelected(SelectionEvent e) { - // displayNameTxt.setEnabled(useDistinctDisplayNameBtn.getSelection()); - // } - // }); - - ModifyListener ml = new ModifyListener() { - private static final long serialVersionUID = -1628130380128946886L; - - @Override - public void modifyText(ModifyEvent event) { - getContainer().updateButtons(); - } - }; - - firstNameTxt.addModifyListener(ml); - lastNameTxt.addModifyListener(ml); - // displayNameTxt.addModifyListener(ml); - - // Don't forget this. - setControl(firstNameTxt); - firstNameTxt.setFocus(); - } - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/AbstractConnectContextMenu.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/AbstractConnectContextMenu.java deleted file mode 100644 index 07f9cee..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/AbstractConnectContextMenu.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.argeo.suite.ui.widgets; - -import java.util.HashMap; -import java.util.Map; - -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -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; - -/** - * Generic popup context menu for TableViewer to enable single sourcing between - * CMS and Workbench - */ -public abstract class AbstractConnectContextMenu { - - private Shell parentShell; - private Shell shell; - // Local context - - private final static String KEY_ACTION_ID = "actionId"; - private final String[] defaultActions; - private Map actionButtons = new HashMap(); - - public AbstractConnectContextMenu(Display display, String[] defaultActions) { - parentShell = display.getActiveShell(); - shell = new Shell(parentShell, SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); - this.defaultActions = defaultActions; - } - - protected void createControl() { - shell.setLayout(EclipseUiUtils.noSpaceGridLayout()); - Composite boxCmp = new Composite(shell, SWT.NO_FOCUS | SWT.BORDER); - boxCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); -// CmsUiUtils.style(boxCmp, ConnectUiStyles.CONTEXT_MENU_BOX); - createContextMenu(boxCmp); - shell.addShellListener(new ActionsShellListener()); - } - - protected void createContextMenu(Composite boxCmp) { - ActionsSelListener asl = new ActionsSelListener(); - for (String actionId : defaultActions) { - Button btn = new Button(boxCmp, SWT.FLAT | SWT.LEAD); - btn.setText(getLabel(actionId)); - btn.setLayoutData(EclipseUiUtils.fillWidth()); - CmsUiUtils.markup(btn); -// CmsUiUtils.style(btn, actionId + ConnectUiStyles.BUTTON_SUFFIX); - btn.setData(KEY_ACTION_ID, actionId); - btn.addSelectionListener(asl); - actionButtons.put(actionId, btn); - } - } - - protected void setVisible(boolean visible, String... buttonIds) { - for (String id : buttonIds) { - Button button = actionButtons.get(id); - button.setVisible(visible); - GridData gd = (GridData) button.getLayoutData(); - gd.heightHint = visible ? SWT.DEFAULT : 0; - } - } - - public void show(Control source, Point location, IStructuredSelection selection) { - if (shell.isDisposed()) { - shell = new Shell(Display.getCurrent(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); - createControl(); - } - if (shell.isVisible()) - shell.setVisible(false); - - if (aboutToShow(source, location, selection)) { - shell.pack(); - shell.layout(); - if (source instanceof Control) - shell.setLocation(((Control) source).toDisplay(location.x, location.y)); - shell.open(); - } - } - - protected Shell getParentShell() { - return parentShell; - } - - class StyleButton extends Label { - private static final long serialVersionUID = 7731102609123946115L; - - public StyleButton(Composite parent, int swtStyle) { - super(parent, swtStyle); - } - } - - class ActionsSelListener extends SelectionAdapter { - private static final long serialVersionUID = -1041871937815812149L; - - @Override - public void widgetSelected(SelectionEvent e) { - Object eventSource = e.getSource(); - if (eventSource instanceof Button) { - Button pressedBtn = (Button) eventSource; - performAction((String) pressedBtn.getData(KEY_ACTION_ID)); - shell.close(); - } - } - } - - class ActionsShellListener extends org.eclipse.swt.events.ShellAdapter { - private static final long serialVersionUID = -5092341449523150827L; - - @Override - public void shellDeactivated(ShellEvent e) { - setVisible(false); - shell.setVisible(false); - //shell.close(); - } - } - - protected abstract boolean performAction(String actionId); - - protected abstract boolean aboutToShow(Control source, Point location, IStructuredSelection selection); - - protected abstract String getLabel(String actionId); -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/ConnectAbstractDropDown.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/ConnectAbstractDropDown.java deleted file mode 100644 index ffe733e..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/ConnectAbstractDropDown.java +++ /dev/null @@ -1,194 +0,0 @@ -package org.argeo.suite.ui.widgets; - -import java.util.Arrays; -import java.util.List; - -import org.argeo.cms.ui.util.CmsUiUtils; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.rap.rwt.widgets.DropDown; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Widget; - -/** - * Enable easy addition of a {@code DropDown} widget to a text with listeners - * configured - */ -public abstract class ConnectAbstractDropDown { - - private final Text text; - private final DropDown dropDown; - private boolean modifyFromList = false; - - // Current displayed text - private String userText = ""; - // Current displayed list items - private String[] values; - - // Fine tuning - boolean readOnly; - boolean refreshOnFocus; - - /** Implementing classes should call refreshValues() after initialisation */ - public ConnectAbstractDropDown(Text text) { - this(text, SWT.NONE, false); - } - - /** - * Implementing classes should call refreshValues() after initialisation - * - * @param text - * @param style - * only SWT.READ_ONLY is understood, check if the entered text is - * part of the legal choices. - */ - public ConnectAbstractDropDown(Text text, int style) { - this(text, style, false); - } - - /** - * Implementers should call refreshValues() once init has been done. - * - * @param text - * @param style - * only SWT.READ_ONLY is understood, check if the entered text is - * part of the legal choices. - * @param refreshOnFocus - * if true, the possible values are computed each time the focus is - * gained. It enables, among other to fine tune the getFilteredValues - * method depending on the current context - */ - public ConnectAbstractDropDown(Text text, int style, boolean refreshOnFocus) { - this.text = text; - dropDown = new DropDown(text); - Object obj = dropDown; - if (obj instanceof Widget) - CmsUiUtils.markup((Widget) obj); - readOnly = (style & SWT.READ_ONLY) != 0; - this.refreshOnFocus = refreshOnFocus; - addListeners(); - } - - /** - * Overwrite to force the refresh of the possible values on focus gained event - */ - protected boolean refreshOnFocus() { - return refreshOnFocus; - } - - public String getText() { - return text.getText(); - } - - public void init() { - refreshValues(); - } - - public void reset(String value) { - modifyFromList = true; - if (EclipseUiUtils.notEmpty(value)) - text.setText(value); - else - text.setText(""); - refreshValues(); - modifyFromList = false; - } - - /** Overwrite to provide specific filtering */ - protected abstract List getFilteredValues(String filter); - - protected void refreshValues() { - List filteredValues = getFilteredValues(text.getText()); - values = filteredValues.toArray(new String[filteredValues.size()]); - dropDown.setItems(values); - } - - protected void addListeners() { - addModifyListener(); - addSelectionListener(); - addDefaultSelectionListener(); - addFocusListener(); - } - - protected void addFocusListener() { - text.addFocusListener(new FocusListener() { - private static final long serialVersionUID = -7179112097626535946L; - - public void focusGained(FocusEvent event) { - if (refreshOnFocus) { - modifyFromList = true; - refreshValues(); - modifyFromList = false; - } - dropDown.setVisible(true); - } - - public void focusLost(FocusEvent event) { - dropDown.setVisible(false); - if (readOnly && values != null && !Arrays.asList(values).contains(userText)) { - modifyFromList = true; - text.setText(""); - refreshValues(); - modifyFromList = false; - } - } - }); - } - - private void addSelectionListener() { - Object obj = dropDown; - if (obj instanceof Widget) - ((Widget) obj).addListener(SWT.Selection, new Listener() { - private static final long serialVersionUID = -2357157809365135142L; - - public void handleEvent(Event event) { - if (event.index != -1) { - modifyFromList = true; - text.setText(values[event.index]); - modifyFromList = false; - text.selectAll(); - } else { - text.setText(userText); - text.setSelection(userText.length(), userText.length()); - text.setFocus(); - } - } - }); - } - - private void addDefaultSelectionListener() { - Object obj = dropDown; - if (obj instanceof Widget) - ((Widget) obj).addListener(SWT.DefaultSelection, new Listener() { - private static final long serialVersionUID = -5958008322630466068L; - - public void handleEvent(Event event) { - if (event.index != -1) { - text.setText(values[event.index]); - text.setSelection(event.text.length()); - dropDown.setVisible(false); - } - } - }); - } - - private void addModifyListener() { - text.addListener(SWT.Modify, new Listener() { - private static final long serialVersionUID = -4373972835244263346L; - - public void handleEvent(Event event) { - if (!modifyFromList) { - userText = text.getText(); - refreshValues(); - if (values.length == 1) - dropDown.setSelectionIndex(0); - dropDown.setVisible(true); - } - } - }); - } -} diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java deleted file mode 100644 index a03c250..0000000 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/DelayedText.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.argeo.suite.ui.widgets; - -import java.util.Timer; -import java.util.TimerTask; - -import org.eclipse.rap.rwt.service.ServerPushSession; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Text; - -/** - * Text that introduce a timer in the attached ModifyListener. - * - * Note that corresponding ModifyEvent will *NOT* be sent in the UI thread. - * Calling ModifierInstance must be implemented in consequence. Note also that - * this delayed text only manages one listener at a time. - * - */ -public class DelayedText { - final int delay; - private Object lock = new Object(); - private MyTimer timer = new MyTimer(DelayedText.this.toString()); - private ModifyListener delayedModifyListener; - private ServerPushSession pushSession; - - private Text text; - - private ModifyListener modifyListener = new ModifyListener() { - private static final long serialVersionUID = 1117506414462641980L; - - public void modifyText(ModifyEvent e) { - ModifyEvent delayedEvent = null; - synchronized (lock) { - if (delayedModifyListener != null) { - Event tmpEvent = new Event(); - tmpEvent.widget = text; - tmpEvent.display = e.display; - tmpEvent.data = e.data; - tmpEvent.time = e.time; - delayedEvent = new ModifyEvent(tmpEvent); - } - } - final ModifyEvent timerModifyEvent = delayedEvent; - - synchronized (timer) { - if (timer.timerTask != null) { - timer.timerTask.cancel(); - timer.timerTask = null; - } - - if (delayedEvent != null) { - timer.timerTask = new TimerTask() { - public void run() { - synchronized (lock) { - delayedModifyListener.modifyText(timerModifyEvent); - // Bad approach: it is not a good idea to put a - // display.asyncExec in a lock... - // DelayedText.this.getDisplay().asyncExec(new - // Runnable() { - // @Override - // public void run() { - // delayedModifyListener.modifyText(timerModifyEvent); - // } - // } - // ); - } - synchronized (timer) { - timer.timerTask = null; - } - } - }; - timer.schedule(timer.timerTask, delay); - if (pushSession != null) - pushSession.start(); - } - } - }; - }; - - public DelayedText(Composite parent, int style, int delayInMs) { - // super(parent, style); - text = new Text(parent, style); - this.delay = delayInMs; - text.addModifyListener(modifyListener); - } - - /** - * Adds a modify text listener that will be delayed. If another Modify event - * happens during the waiting delay, the older event will be canceled an a new - * one will be scheduled after another new delay. - */ - public void addDelayedModifyListener(ServerPushSession pushSession, ModifyListener listener) { - synchronized (lock) { - delayedModifyListener = listener; - this.pushSession = pushSession; - } - } - - public void removeDelayedModifyListener(ModifyListener listener) { - synchronized (lock) { - delayedModifyListener = null; - pushSession = null; - } - } - - private class MyTimer extends Timer { - private TimerTask timerTask = null; - - public MyTimer(String name) { - super(name); - } - } - - public Text getText() { - return text; - } - - public void close() { - if (pushSession != null) - pushSession.stop(); - if (timer != null) - timer.cancel(); - }; - -} diff --git a/pom.xml b/pom.xml index 2d4ef3f..36bd192 100644 --- a/pom.xml +++ b/pom.xml @@ -23,17 +23,7 @@ - - org.argeo.entity.api - org.argeo.entity.core - org.argeo.entity.ui - - - org.argeo.suite.core - org.argeo.suite.ui - org.argeo.suite.ui.rap - org.argeo.suite.theme.default - + core library publishing