Improve image management and ACR
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 25 Jun 2023 08:39:04 +0000 (10:39 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 25 Jun 2023 08:39:04 +0000 (10:39 +0200)
org.argeo.app.api/src/org/argeo/app/api/EntityNames.java
org.argeo.app.api/src/org/argeo/app/api/WGS84PosName.java [new file with mode: 0644]
org.argeo.app.jcr/src/org/argeo/internal/app/jcr/AppUserStateImpl.java
swt/org.argeo.app.swt/src/org/argeo/app/swt/docbook/DbkImageManager.java
swt/org.argeo.app.swt/src/org/argeo/app/swt/docbook/DocBookViewer.java
swt/org.argeo.app.swt/src/org/argeo/app/swt/forms/FormPageViewer.java
swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SuiteSwtUtils.java
swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java
swt/org.argeo.app.ui/src/org/argeo/app/ui/SuiteUiUtils.java

index b60a436d28b4f333affa6015140ffaccc0e9c7de..5b0707e10a89293e7d4795251f0616b5d3bddbac 100644 (file)
@@ -17,14 +17,14 @@ public interface EntityNames {
        /** Administrative units. */
        final String ADM = "adm";
 
+       @Deprecated
        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 language which is relevant. */
+//     final String XML_LANG = "xml:lang";
        /** The date which is relevant. */
+       @Deprecated
        final String ENTITY_DATE = "entity:date";
        @Deprecated
        final String ENTITY_RELATED_TO = "entity:relatedTo";
@@ -47,15 +47,24 @@ public interface EntityNames {
        final String OU = LdapAttr.ou.property();
 
        // WGS84
-       final String GEO_LAT = "geo:lat";
-       final String GEO_LONG = "geo:long";
-       final String GEO_ALT = "geo:alt";
+       @Deprecated
+       final String GEO_LAT = WGS84PosName.lat.get();
+       @Deprecated
+       final String GEO_LONG = WGS84PosName.lng.get();
+       @Deprecated
+       final String GEO_ALT = WGS84PosName.alt.get();
 
        // SVG
+       @Deprecated
        final String SVG_WIDTH = "svg:width";
+       @Deprecated
        final String SVG_HEIGHT = "svg:height";
+       @Deprecated
        final String SVG_LENGTH = "svg:length";
+       @Deprecated
        final String SVG_UNIT = "svg:unit";
+       @Deprecated
        final String SVG_DUR = "svg:dur";
+       @Deprecated
        final String SVG_DIRECTION = "svg:direction";
 }
diff --git a/org.argeo.app.api/src/org/argeo/app/api/WGS84PosName.java b/org.argeo.app.api/src/org/argeo/app/api/WGS84PosName.java
new file mode 100644 (file)
index 0000000..49de2d8
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.app.api;
+
+import org.argeo.api.acr.QNamed;
+
+/**
+ * Geographical coordinate in WGS84 reference datum.
+ * 
+ * @see https://www.w3.org/2003/01/geo/
+ */
+public enum WGS84PosName implements QNamed {
+       lat, lng("long"), alt;
+
+       private final String localName;
+
+       private WGS84PosName() {
+               localName = null;
+       }
+
+       private WGS84PosName(String localName) {
+               this.localName = localName;
+       }
+
+       @Override
+       public String getNamespace() {
+               return "http://www.w3.org/2003/01/geo/wgs84_pos#";
+       }
+
+       @Override
+       public String getDefaultPrefix() {
+               return "geo";
+       }
+
+       @Override
+       public String localName() {
+               if (localName != null)
+                       return localName;
+               return QNamed.super.localName();
+       }
+
+}
index faf217ac65fa853cf28bb1cf2571cca28787b3a3..bb2bc15be622c3a0a0f091816564dc3c6ede38e4 100644 (file)
@@ -8,7 +8,6 @@ import org.argeo.api.cms.CmsConstants;
 import org.argeo.api.cms.CmsSession;
 import org.argeo.app.api.AppUserState;
 import org.argeo.app.jcr.SuiteJcrUtils;
-import org.argeo.cms.acr.ContentUtils;
 import org.argeo.cms.jcr.acr.JcrContentProvider;
 import org.argeo.jcr.Jcr;
 
@@ -22,8 +21,7 @@ public class AppUserStateImpl implements AppUserState {
                        Node node = SuiteJcrUtils.getOrCreateCmsSessionNode(adminSession, session);
                        return node;
                });
-               Content userDir = contentSession
-                               .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + Jcr.getPath(userDirNode));
+               Content userDir = contentSession.get(Content.ROOT_PATH + CmsConstants.SYS_WORKSPACE + Jcr.getPath(userDirNode));
                return userDir;
        }
 
index 5fe67e1256440089ef460d4dd80dc3049b26ac9a..7154652404eb5261e82304895933ddaf3071d031 100644 (file)
@@ -119,7 +119,7 @@ public class DbkImageManager extends AcrSwtImageManager {
                String fileref = imageDataNode.get(DbkAttr.fileref, String.class).orElse(null);
                if (fileref == null)
                        return null;
-               return ((ProvidedContent) baseFolder).getContent(fileref);
+               return ((ProvidedContent) baseFolder).getContent(fileref).get();
        }
 
        protected Content getMediaFolder() {
index 141a900be2a96543b410c944ab12875ee4497e28..594fe3af6293ac4607dc5a7056ad3765c8dc7e65 100644 (file)
@@ -150,7 +150,7 @@ public class DocBookViewer extends AbstractPageViewer {
 
                        } else if (part instanceof DbkImg) {
                                DbkImg editableImage = (DbkImg) part;
-                               imageManager.load(partContent, part.getControl(), editableImage.getPreferredImageSize());
+                               imageManager.load(partContent, part.getControl(), editableImage.getPreferredImageSize(), null);
                        } else if (part instanceof DbkVideo) {
                                DbkVideo video = (DbkVideo) part;
                                video.load(part.getControl());
index 840855e46c35a5541a7da8eb17f3f331fdb9ddc2..becbf158512e1715fa493c975df0c4631d97e2cd 100644 (file)
@@ -21,7 +21,6 @@ import org.argeo.cms.swt.acr.AbstractPageViewer;
 import org.argeo.cms.swt.acr.Img;
 import org.argeo.cms.swt.acr.SwtSection;
 import org.argeo.cms.swt.acr.SwtSectionPart;
-import org.argeo.cms.swt.widgets.EditableImage;
 import org.argeo.cms.swt.widgets.StyledControl;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.eclipse.rap.fileupload.FileDetails;
@@ -161,9 +160,9 @@ public class FormPageViewer extends AbstractPageViewer {
                } else if (part instanceof SwtSectionPart sectionPart) {
                        Content partNode = sectionPart.getContent();
                        // use control AFTER setting style, since it may have been reset
-                       if (part instanceof EditableImage) {
-                               EditableImage editableImage = (EditableImage) part;
-                               imageManager().load(partNode, part.getControl(), editableImage.getPreferredImageSize());
+                       if (part instanceof Img) {
+                               Img editableImage = (Img) part;
+                               imageManager().load(partNode, part.getControl(), editableImage.getPreferredImageSize(), null);
                        }
                }
        }
index dbcb3d8cd21c76be3410404ab7a49a640c8d121f..39cde1b8cfc01c59ce9d842b0a31070d7bded5a7 100644 (file)
@@ -6,22 +6,28 @@ import javax.xml.namespace.QName;
 
 import org.argeo.api.acr.Content;
 import org.argeo.api.acr.QNamed;
+import org.argeo.api.cms.ux.Cms2DSize;
 import org.argeo.api.cms.ux.CmsEditable;
 import org.argeo.api.cms.ux.CmsStyle;
 import org.argeo.app.ux.SuiteStyle;
 import org.argeo.cms.Localized;
 import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.Img;
 import org.argeo.cms.swt.dialogs.CmsFeedback;
-import org.argeo.cms.swt.widgets.EditableText;
+import org.argeo.cms.swt.dialogs.LightweightDialog;
 import org.argeo.cms.swt.widgets.CmsLink;
+import org.argeo.cms.swt.widgets.EditableText;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
 import org.eclipse.swt.events.FocusEvent;
 import org.eclipse.swt.events.FocusListener;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
@@ -172,30 +178,11 @@ public class SuiteSwtUtils {
                return label;
        }
 
-       public static Control addExternalLink(Composite parent, String label, String url, String plainCssAnchorClass,
-                       boolean newWindow) {
-               Label lbl = new Label(parent, SWT.NONE);
-               CmsSwtUtils.markup(lbl);
-               StringBuilder txt = new StringBuilder();
-               txt.append("<a");
-               if (plainCssAnchorClass != null)
-                       txt.append(" class='" + plainCssAnchorClass + "'");
-               txt.append(" href='").append(url).append("'");
-               if (newWindow) {
-                       txt.append(" target='blank_'");
-               }
-               txt.append(">");
-               txt.append(label);
-               txt.append("</a>");
-               lbl.setText(txt.toString());
-               return lbl;
-       }
-
        /*
         * CONTENT
         */
        public static String toLink(Content content) {
-               return content != null ? "#" + CmsSwtUtils.cleanPathForUrl(SwtArgeoApp.nodeToState(content)) : null;
+               return content != null ? "#" + CmsSwtUtils.cleanPathForUrl(content.getPath()) : null;
        }
 
        public static Text addFormLine(Composite parent, Localized label, Content content, QNamed property,
@@ -319,6 +306,10 @@ public class SuiteSwtUtils {
                return txt;
        }
 
+       /*
+        * LINKS
+        */
+
        /** Add a link to an internal content. */
        public static Control addLink(Composite parent, String label, Content node, CmsStyle style) {
                String target = toLink(node);
@@ -326,6 +317,134 @@ public class SuiteSwtUtils {
                return link.createUi(parent);
        }
 
+       public static Control addExternalLink(Composite parent, String label, String url, String plainCssAnchorClass,
+                       boolean newWindow) {
+               Label lbl = new Label(parent, SWT.NONE);
+               CmsSwtUtils.markup(lbl);
+               StringBuilder txt = new StringBuilder();
+               txt.append("<a");
+               if (plainCssAnchorClass != null)
+                       txt.append(" class='" + plainCssAnchorClass + "'");
+               txt.append(" href='").append(url).append("'");
+               if (newWindow) {
+                       txt.append(" target='blank_'");
+               }
+               txt.append(">");
+               txt.append(label);
+               txt.append("</a>");
+               lbl.setText(txt.toString());
+               return lbl;
+       }
+
+       /*
+        * IMAGES
+        */
+
+       public static Img addPicture(Composite parent, Content file) {
+               return addPicture(parent, file, null);
+       }
+
+       public static Img addPicture(Composite parent, Content file, Integer maxWidth) {
+               return addPicture(parent, file, maxWidth, null);
+       }
+
+       public static Img addPicture(Composite parent, Content file, Integer maxWidth, Content link) {
+               // TODO optimise
+//             Integer width;
+//             Integer height;
+//             if (file.hasContentClass(EntityType.box)) {
+//                     width = file.get(SvgAttrs.width, Integer.class).get();
+//                     height = file.get(SvgAttrs.height, Integer.class).get();
+//             } else {
+//                     try (InputStream in = file.open(InputStream.class)) {
+//                             ImageData imageData = new ImageData(in);
+//                             width = imageData.width;
+//                             height = imageData.height;
+//                     } catch (IOException e) {
+//                             throw new RuntimeException(e);
+//                     }
+//             }
+//
+//             if (maxWidth != null && width > maxWidth) {
+//                     Double ratio = maxWidth.doubleValue() / width.doubleValue();
+//                     width = maxWidth;
+//                     height = (int) Math.rint(ratio * height);
+//             }
+//             Label img = new Label(parent, SWT.NONE);
+//             CmsSwtUtils.markup(img);
+//             StringBuffer txt = new StringBuffer();
+//             String target = toLink(link);
+//             if (target != null)
+//                     txt.append("<a href='").append(target).append("'>");
+//             txt.append(CmsUiUtils.img(fileNode, width.toString(), height.toString()));
+//             if (target != null)
+//                     txt.append("</a>");
+//             img.setText(txt.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 img = new Img(parent, 0, file, new Cms2DSize(maxWidth != null ? maxWidth : 0, 0));
+               if (link != null)
+                       img.setLink(link);
+
+//             String target = toLink(link);
+               if (link == null)
+                       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(CmsSwtUtils.fillAll());
+                                                       scroll.setLayout(CmsSwtUtils.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(CmsSwtUtils.fillAll());
+                                                       Img bigImg = new Img(c, 0, file);
+//                                                     Label bigImg = new Label(c, SWT.NONE);
+//                                                     CmsSwtUtils.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();
+                               }
+                       });
+               img.initControl();
+               return img;
+       }
+
        /** singleton */
        private SuiteSwtUtils() {
        }
index b092e777727f7d6df0e78591d42e74a90e311939..816be08b269b6c1f513171d2e41edd8c00ab939e 100644 (file)
@@ -36,7 +36,6 @@ import org.argeo.app.ux.AppUi;
 import org.argeo.app.ux.SuiteUxEvent;
 import org.argeo.cms.LocaleUtils;
 import org.argeo.cms.Localized;
-import org.argeo.cms.acr.ContentUtils;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.swt.acr.SwtUiProvider;
 import org.argeo.cms.swt.dialogs.CmsFeedback;
@@ -249,7 +248,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber
                                        if (cmsSession == null || cmsView.isAnonymous()) {
                                                assert publicBasePath != null;
                                                Content userDir = contentSession
-                                                               .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + publicBasePath);
+                                                               .get(Content.ROOT_PATH + CmsConstants.SYS_WORKSPACE + publicBasePath);
                                                ui.setUserDir(userDir);
                                        } else {
                                                Content userDir = appUserState.getOrCreateSessionDir(contentSession, cmsSession);
@@ -469,7 +468,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber
        }
 
        // TODO move it to an internal package?
-       public static String nodeToState(Content node) {
+       private static String nodeToState(Content node) {
                return node.getPath();
        }
 
index 77d98b8e3bb55e7e5c5c752bf53acb7cc7a2f02c..e649bfc9b1f4118cb5c20f7ed5655609c724b047 100644 (file)
@@ -18,7 +18,6 @@ import org.argeo.api.cms.ux.CmsStyle;
 import org.argeo.app.api.EntityNames;
 import org.argeo.app.api.EntityType;
 import org.argeo.app.swt.ux.SuiteSwtUtils;
-import org.argeo.app.swt.ux.SwtArgeoApp;
 import org.argeo.app.ux.SuiteUxEvent;
 import org.argeo.cms.jcr.acr.JcrContent;
 import org.argeo.cms.swt.CmsSwtUtils;
@@ -221,8 +220,7 @@ public class SuiteUiUtils {
        }
 
        public static String toLink(Node node) {
-               return node != null ? "#" + CmsSwtUtils.cleanPathForUrl(SwtArgeoApp.nodeToState(JcrContent.nodeToContent(node)))
-                               : null;
+               return node != null ? "#" + CmsSwtUtils.cleanPathForUrl(JcrContent.nodeToContent(node).getPath()) : null;
        }
 
        public static Control addLink(Composite parent, String label, Node node, CmsStyle style)