From: Mathieu Baudier Date: Wed, 14 Sep 2022 11:38:32 +0000 (+0200) Subject: Improve ACR X-Git-Tag: v2.3.10~47 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=ea7d6818525ff88cc6b9ed0957c912545bd8eb81 Improve ACR --- diff --git a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java index 7cc611c9b..3522f1b42 100644 --- a/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java +++ b/jcr/org.argeo.cms.jcr.ui/src/org/argeo/cms/ui/util/CmsUiUtils.java @@ -154,23 +154,23 @@ public class CmsUiUtils { return noImg(AbstractImageManager.NO_IMAGE_SIZE); } - public static Image noImage(Cms2DSize size) { - ResourceManager rm = RWT.getResourceManager(); - InputStream in = null; - try { - in = rm.getRegisteredContent(AbstractImageManager.NO_IMAGE); - ImageData id = new ImageData(in); - ImageData scaled = id.scaledTo(size.getWidth(), size.getHeight()); - Image image = new Image(Display.getCurrent(), scaled); - return image; - } finally { - try { - in.close(); - } catch (IOException e) { - // silent - } - } - } +// public static Image noImage(Cms2DSize size) { +// ResourceManager rm = RWT.getResourceManager(); +// InputStream in = null; +// try { +// in = rm.getRegisteredContent(AbstractImageManager.NO_IMAGE); +// ImageData id = new ImageData(in); +// ImageData scaled = id.scaledTo(size.getWidth(), size.getHeight()); +// Image image = new Image(Display.getCurrent(), scaled); +// return image; +// } finally { +// try { +// in.close(); +// } catch (IOException e) { +// // silent +// } +// } +// } /** Lorem ipsum text to be used during development. */ public final static String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." diff --git a/org.argeo.api.acr/src/org/argeo/api/acr/Content.java b/org.argeo.api.acr/src/org/argeo/api/acr/Content.java index 3cdf8d7db..b605fa1e0 100644 --- a/org.argeo.api.acr/src/org/argeo/api/acr/Content.java +++ b/org.argeo.api.acr/src/org/argeo/api/acr/Content.java @@ -1,14 +1,15 @@ package org.argeo.api.acr; +import static org.argeo.api.acr.NamespaceUtils.unqualified; + import java.io.Closeable; import java.io.IOException; -import java.util.Collection; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import javax.xml.XMLConstants; import javax.xml.namespace.QName; /** @@ -28,29 +29,48 @@ public interface Content extends Iterable, Map { Optional get(QName key, Class clss); - default Object get(String key) { - if (key.indexOf(':') >= 0) - throw new IllegalArgumentException("Name " + key + " has a prefix"); - return get(new QName(XMLConstants.NULL_NS_URI, key, XMLConstants.DEFAULT_NS_PREFIX)); + Class getType(QName key); + + boolean isMultiple(QName key); + + List getMultiple(QName key, Class clss); + + /* + * ATTRIBUTES OPERATION HELPERS + */ + default boolean containsKey(QNamed key) { + return containsKey(key.qName()); } - default Object put(String key, Object value) { - if (key.indexOf(':') >= 0) - throw new IllegalArgumentException("Name " + key + " has a prefix"); - return put(new QName(XMLConstants.NULL_NS_URI, key, XMLConstants.DEFAULT_NS_PREFIX), value); + default Optional get(QNamed key, Class clss) { + return get(key.qName(), clss); } - default Object remove(String key) { - if (key.indexOf(':') >= 0) - throw new IllegalArgumentException("Name " + key + " has a prefix"); - return remove(new QName(XMLConstants.NULL_NS_URI, key, XMLConstants.DEFAULT_NS_PREFIX)); + default Object get(QNamed key) { + return get(key.qName()); } - Class getType(QName key); + default Object put(QNamed key, Object value) { + return put(key.qName(), value); + } - boolean isMultiple(QName key); + default Object remove(QNamed key) { + return remove(key.qName()); + } + + // TODO do we really need the helpers below? - Optional> getMultiple(QName key, Class clss); + default Object get(String key) { + return get(unqualified(key)); + } + + default Object put(String key, Object value) { + return put(unqualified(key), value); + } + + default Object remove(String key) { + return remove(unqualified(key)); + } @SuppressWarnings("unchecked") default List getMultiple(QName key) { @@ -60,14 +80,15 @@ public interface Content extends Iterable, Map { } catch (ClassCastException e) { throw new IllegalArgumentException("Requested type is not the default type"); } - Optional> res = getMultiple(key, type); - if (res == null) - return null; - else { - if (res.isEmpty()) - throw new IllegalStateException("Metadata " + key + " is not availabel as list of type " + type); - return res.get(); - } + List res = getMultiple(key, type); + return res; +// if (res == null) +// return null; +// else { +// if (res.isEmpty()) +// throw new IllegalStateException("Metadata " + key + " is not availabel as list of type " + type); +// return res.get(); +// } } /* @@ -83,9 +104,7 @@ public interface Content extends Iterable, Map { Content add(QName name, QName... classes); default Content add(String name, QName... classes) { - if (name.indexOf(':') >= 0) - throw new IllegalArgumentException("Name " + name + " has a prefix"); - return add(new QName(XMLConstants.NULL_NS_URI, name, XMLConstants.DEFAULT_NS_PREFIX), classes); + return add(unqualified(name), classes); } void remove(); @@ -119,6 +138,10 @@ public interface Content extends Iterable, Map { return false; } + default boolean hasContentClass(QNamed contentClass) { + return hasContentClass(contentClass.qName()); + } + /* * SIBLINGS */ @@ -154,6 +177,10 @@ public interface Content extends Iterable, Map { return false; } + default boolean hasChild(QNamed name) { + return hasChild(name.qName()); + } + default Content anyOrAddChild(QName name, QName... classes) { Content child = anyChild(name); if (child != null) @@ -161,6 +188,10 @@ public interface Content extends Iterable, Map { return this.add(name, classes); } + default Content anyOrAddChild(String name, QName... classes) { + return anyOrAddChild(unqualified(name), classes); + } + /** Any child with this name, or null if there is none */ default Content anyChild(QName name) { for (Content child : this) { @@ -170,23 +201,49 @@ public interface Content extends Iterable, Map { return null; } - /* - * CONVENIENCE METHODS - */ - default String attr(String key) { - Object obj = get(key); - if (obj == null) - return null; - return obj.toString(); + default List children(QName name) { + List res = new ArrayList<>(); + for (Content child : this) { + if (child.getName().equals(name)) + res.add(child); + } + return res; + } + + default Optional soleChild(QName name) { + List res = children(name); + if (res.isEmpty()) + return Optional.empty(); + if (res.size() > 1) + throw new IllegalStateException(this + " has multiple children with name " + name); + return Optional.of(res.get(0)); + } + + default Content child(QName name) { + return soleChild(name).orElseThrow(); + } + default Content child(QNamed name) { + return child(name.qName()); } + /* + * ATTR AS STRING + */ default String attr(QName key) { + // TODO check String type? Object obj = get(key); if (obj == null) return null; return obj.toString(); + } + default String attr(QNamed key) { + return attr(key.qName()); + } + + default String attr(String key) { + return attr(unqualified(key)); } // // default String attr(Object key) { diff --git a/org.argeo.api.acr/src/org/argeo/api/acr/NamespaceUtils.java b/org.argeo.api.acr/src/org/argeo/api/acr/NamespaceUtils.java index 64566ea0c..df582868b 100644 --- a/org.argeo.api.acr/src/org/argeo/api/acr/NamespaceUtils.java +++ b/org.argeo.api.acr/src/org/argeo/api/acr/NamespaceUtils.java @@ -65,6 +65,17 @@ public class NamespaceUtils { return !qName.getNamespaceURI().equals(XMLConstants.NULL_NS_URI); } + public static void checkNoPrefix(String unqualified) { + if (unqualified.indexOf(':') >= 0) + throw new IllegalArgumentException("Name " + unqualified + " has a prefix"); + } + + public static QName unqualified(String name) { + checkNoPrefix(name); + return new ContentName(XMLConstants.NULL_NS_URI, name, XMLConstants.DEFAULT_NS_PREFIX); + + } + /* * DEFAULT NAMESPACE CONTEXT OPERATIONS as specified in NamespaceContext */ diff --git a/org.argeo.api.acr/src/org/argeo/api/acr/QNamed.java b/org.argeo.api.acr/src/org/argeo/api/acr/QNamed.java new file mode 100644 index 000000000..063a7d321 --- /dev/null +++ b/org.argeo.api.acr/src/org/argeo/api/acr/QNamed.java @@ -0,0 +1,47 @@ +package org.argeo.api.acr; + +import java.util.function.Supplier; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; + +/** An optionally qualified name. Primarily meant to be used in enums. */ +public interface QNamed extends Supplier { + String name(); + + /** To be overridden when XML naming is not compatible with Java naming. */ + default String localName() { + return name(); + } + + default QName qName() { + return new ContentName(getNamespace(), localName(), getDefaultPrefix()); + } + + default String get(NamespaceContext namespaceContext) { + return namespaceContext.getPrefix(getNamespace()) + ":" + localName(); + } + + default String get() { + return getDefaultPrefix() + ":" + localName(); + } + + String getNamespace(); + + String getDefaultPrefix(); + + /** To be used by enums without namespace (typically XML attributes). */ + static interface Unqualified extends QNamed { + @Override + default String getNamespace() { + return XMLConstants.NULL_NS_URI; + } + + @Override + default String getDefaultPrefix() { + return XMLConstants.DEFAULT_NS_PREFIX; + } + + } +} diff --git a/org.argeo.api.acr/src/org/argeo/api/acr/spi/ProvidedContent.java b/org.argeo.api.acr/src/org/argeo/api/acr/spi/ProvidedContent.java index d9f378329..e2807c0ef 100644 --- a/org.argeo.api.acr/src/org/argeo/api/acr/spi/ProvidedContent.java +++ b/org.argeo.api.acr/src/org/argeo/api/acr/spi/ProvidedContent.java @@ -4,6 +4,8 @@ import org.argeo.api.acr.Content; /** A {@link Content} implementation. */ public interface ProvidedContent extends Content { + final static String ROOT_PATH = "/"; + ProvidedSession getSession(); ContentProvider getProvider(); @@ -19,4 +21,15 @@ public interface ProvidedContent extends Content { default ProvidedContent getMountPoint(String relativePath) { throw new UnsupportedOperationException("This content doe not support mount"); } + + default ProvidedContent getContent(String path) { + Content fileNode; + if (path.startsWith(ROOT_PATH)) {// absolute + fileNode = getSession().get(path); + } else {// relative + String absolutePath = getPath() + '/' + path; + fileNode = getSession().get(absolutePath); + } + return (ProvidedContent) fileNode; + } } diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/ux/Cms2DSize.java b/org.argeo.api.cms/src/org/argeo/api/cms/ux/Cms2DSize.java index 9667e8352..1ec753a18 100644 --- a/org.argeo.api.cms/src/org/argeo/api/cms/ux/Cms2DSize.java +++ b/org.argeo.api.cms/src/org/argeo/api/cms/ux/Cms2DSize.java @@ -6,7 +6,6 @@ public class Cms2DSize { private Integer height; public Cms2DSize() { - } public Cms2DSize(Integer width, Integer height) { @@ -31,4 +30,9 @@ public class Cms2DSize { this.height = height; } + @Override + public String toString() { + return Cms2DSize.class.getSimpleName() + "[" + width + "," + height + "]"; + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java b/org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java index 1cffef40e..ce05dc14c 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java @@ -55,34 +55,27 @@ public abstract class AbstractContent extends AbstractMap impleme @SuppressWarnings("unchecked") @Override - public Optional> getMultiple(QName key, Class clss) { + public List getMultiple(QName key, Class clss) { Object value = get(key); if (value == null) - return Optional.empty(); + return new ArrayList<>(); if (value instanceof List) { - try { - List res = (List) value; - return Optional.of(res); - } catch (ClassCastException e) { - List res = new ArrayList<>(); - List lst = (List) value; - try { - for (Object o : lst) { - A item = (A) o; - res.add(item); - } - return Optional.of(res); - } catch (ClassCastException e1) { - return Optional.empty(); - } + if (isDefaultAttrTypeRequested(clss)) + return (List) value; + List res = new ArrayList<>(); + List lst = (List) value; + for (Object o : lst) { + A item = clss.isAssignableFrom(String.class) ? (A) o.toString() : (A) o; + res.add(item); } + return res; } else {// singleton - try { - A res = (A) value; - return Optional.of(Collections.singletonList(res)); - } catch (ClassCastException e) { - return Optional.empty(); - } +// try { + A res = (A) value; + return Collections.singletonList(res); +// } catch (ClassCastException e) { +// return Optional.empty(); +// } } } diff --git a/org.argeo.cms/src/org/argeo/cms/acr/SvgAttrs.java b/org.argeo.cms/src/org/argeo/cms/acr/SvgAttrs.java new file mode 100644 index 000000000..0d3838732 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/acr/SvgAttrs.java @@ -0,0 +1,31 @@ +package org.argeo.cms.acr; + +import org.argeo.api.acr.QNamed; + +public enum SvgAttrs implements QNamed { + /** */ + width, + /** */ + height, + /** */ + length, + /** */ + unit, + /** */ + dur, + /** */ + direction, + // + ; + + @Override + public String getNamespace() { + return CmsContentTypes.SVG_1_1.getNamespace(); + } + + @Override + public String getDefaultPrefix() { + return CmsContentTypes.SVG_1_1.getDefaultPrefix(); + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/acr/fs/FsContent.java b/org.argeo.cms/src/org/argeo/cms/acr/fs/FsContent.java index d61827d50..b8f98d2c8 100644 --- a/org.argeo.cms/src/org/argeo/cms/acr/fs/FsContent.java +++ b/org.argeo.cms/src/org/argeo/cms/acr/fs/FsContent.java @@ -33,17 +33,21 @@ import javax.xml.transform.stream.StreamResult; import org.argeo.api.acr.Content; import org.argeo.api.acr.ContentName; import org.argeo.api.acr.ContentResourceException; +import org.argeo.api.acr.CrAttributeType; import org.argeo.api.acr.CrName; import org.argeo.api.acr.NamespaceUtils; import org.argeo.api.acr.spi.ContentProvider; import org.argeo.api.acr.spi.ProvidedContent; import org.argeo.api.acr.spi.ProvidedSession; +import org.argeo.api.cms.CmsLog; import org.argeo.cms.acr.AbstractContent; import org.argeo.cms.acr.ContentUtils; import org.argeo.util.FsUtils; /** Content persisted as a filesystem {@link Path}. */ public class FsContent extends AbstractContent implements ProvidedContent { + private CmsLog log = CmsLog.getLog(FsContent.class); + final static String USER_ = "user:"; private static final Map BASIC_KEYS; @@ -146,25 +150,41 @@ public class FsContent extends AbstractContent implements ProvidedContent { } // TODO perform trivial file conversion to other formats } + + // TODO better deal with multiple types if (value instanceof byte[]) { String str = new String((byte[]) value, StandardCharsets.UTF_8); String[] arr = str.split("\n"); + if (arr.length == 1) { - res = (A) arr[0]; + if (clss.isAssignableFrom(String.class)) { + res = (A) arr[0]; + } else { + res = (A) CrAttributeType.parse(arr[0]); + } } else { - List lst = new ArrayList<>(); + List lst = new ArrayList<>(); for (String s : arr) { - lst.add(s); + lst.add(CrAttributeType.parse(s)); } res = (A) lst; } } - if (res == null) - try { - res = (A) value; - } catch (ClassCastException e) { - return Optional.empty(); - } + if (res == null) { + if (isDefaultAttrTypeRequested(clss)) + return Optional.of((A) CrAttributeType.parse(value.toString())); + if (clss.isAssignableFrom(value.getClass())) + return Optional.of((A) value); + if (clss.isAssignableFrom(String.class)) + return Optional.of((A) value.toString()); + log.warn("Cannot interpret " + key + " in " + this); + return Optional.empty(); +// try { +// res = (A) value; +// } catch (ClassCastException e) { +// return Optional.empty(); +// } + } return Optional.of(res); } @@ -337,12 +357,10 @@ public class FsContent extends AbstractContent implements ProvidedContent { @Override public List getContentClasses() { List res = new ArrayList<>(); - Optional> value = getMultiple(CrName.cc.qName(), String.class); - if (!value.isEmpty()) { - for (String s : value.get()) { - QName name = NamespaceUtils.parsePrefixedName(provider, s); - res.add(name); - } + List value = getMultiple(CrName.cc.qName(), String.class); + for (String s : value) { + QName name = NamespaceUtils.parsePrefixedName(provider, s); + res.add(name); } if (Files.isDirectory(path)) res.add(CrName.collection.qName()); diff --git a/org.argeo.util/src/org/argeo/util/naming/QNamed.java b/org.argeo.util/src/org/argeo/util/naming/QNamed.java index 9eac3607a..bcbb4742a 100644 --- a/org.argeo.util/src/org/argeo/util/naming/QNamed.java +++ b/org.argeo.util/src/org/argeo/util/naming/QNamed.java @@ -3,6 +3,7 @@ package org.argeo.util.naming; import javax.xml.namespace.QName; /** A (possibly) qualified name. To be used in enums. */ +@Deprecated public interface QNamed { String name(); diff --git a/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrSwtImageManager.java b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrSwtImageManager.java index 5e83454de..e683d9630 100644 --- a/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrSwtImageManager.java +++ b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrSwtImageManager.java @@ -3,35 +3,46 @@ package org.argeo.cms.swt.acr; import java.io.InputStream; import org.argeo.api.acr.Content; +import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.ux.Cms2DSize; import org.argeo.cms.swt.AbstractSwtImageManager; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.ux.CmsUxUtils; import org.eclipse.swt.graphics.Image; public class AcrSwtImageManager extends AbstractSwtImageManager { @Override public String getImageUrl(Content node) { - // TODO Auto-generated method stub - return null; + return getDataPathForUrl(node); } @Override public String uploadImage(Content context, Content uploadFolder, String fileName, InputStream in, String contentType) { - // TODO Auto-generated method stub - return null; + throw new UnsupportedOperationException(); } @Override protected Image getSwtImage(Content node) { - // TODO Auto-generated method stub - return null; + throw new UnsupportedOperationException(); } @Override protected String noImg(Cms2DSize size) { - // TODO Auto-generated method stub - return null; + String dataPath = ""; + return CmsUxUtils.img(dataPath, size); } + protected String getDataPathForUrl(Content content) { + return CmsSwtUtils.cleanPathForUrl(getDataPath(content)); + } + + /** A path in the node repository */ + protected String getDataPath(Content node) { + // TODO make it more configurable? + StringBuilder buf = new StringBuilder(CmsConstants.PATH_DATA); + buf.append(node.getPath()); + return buf.toString(); + } } diff --git a/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/Img.java b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/Img.java new file mode 100644 index 000000000..eb52fc6a3 --- /dev/null +++ b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/Img.java @@ -0,0 +1,144 @@ +package org.argeo.cms.swt.acr; + +import org.argeo.api.acr.Content; +import org.argeo.api.acr.NamespaceUtils; +import org.argeo.api.acr.spi.ProvidedContent; +import org.argeo.api.cms.ux.Cms2DSize; +import org.argeo.api.cms.ux.CmsImageManager; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.swt.widgets.EditableImage; +import org.argeo.cms.ux.acr.ContentPart; +import org.argeo.eclipse.ui.specific.CmsFileUpload; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** An image within the Argeo Text framework */ +public class Img extends EditableImage implements SwtSectionPart, ContentPart { + private static final long serialVersionUID = 6233572783968188476L; + + private final SwtSection section; + + private final CmsImageManager imageManager; +// private FileUploadHandler currentUploadHandler = null; +// private FileUploadListener fileUploadListener; + + public Img(Composite parent, int swtStyle, Content imgNode, Cms2DSize preferredImageSize) { + this(SwtSection.findSection(parent), parent, swtStyle, imgNode, preferredImageSize, null); +// setStyle(TextStyles.TEXT_IMAGE); + } + + public Img(Composite parent, int swtStyle, Content imgNode) { + this(SwtSection.findSection(parent), parent, swtStyle, imgNode, null, null); +// setStyle(TextStyles.TEXT_IMAGE); + } + + public Img(Composite parent, int swtStyle, Content imgNode, CmsImageManager imageManager) { + this(SwtSection.findSection(parent), parent, swtStyle, imgNode, null, imageManager); +// setStyle(TextStyles.TEXT_IMAGE); + } + + Img(SwtSection section, Composite parent, int swtStyle, Content imgNode, Cms2DSize preferredImageSize, + CmsImageManager imageManager) { + super(parent, swtStyle, preferredImageSize); + this.section = section; + this.imageManager = imageManager != null ? imageManager + : (CmsImageManager) CmsSwtUtils.getCmsView(section).getImageManager(); +// CmsSwtUtils.style(this, TextStyles.TEXT_IMG); + setData(imgNode); + } + + @Override + protected Control createControl(Composite box, String style) { + if (isEditing()) { + return createImageChooser(box, style); + } else { + return createLabel(box, style); + } + } + + @Override + public synchronized void stopEditing() { + super.stopEditing(); +// fileUploadListener = null; + } + + @Override + protected synchronized Boolean load(Control lbl) { + Content imgNode = getContent(); + boolean loaded = imageManager.load(imgNode, lbl, getPreferredImageSize()); + // getParent().layout(); + return loaded; + } + + protected Content getUploadFolder() { + return getContent().getParent(); + } + + protected String getUploadName() { + Content node = getContent(); + // TODO centralise pattern? + return NamespaceUtils.toPrefixedName(node.getName()) + '[' + node.getSiblingIndex() + ']'; + } + + protected CmsImageManager getImageManager() { + return imageManager; + } + + protected Control createImageChooser(Composite box, String style) { +// JcrFileUploadReceiver receiver = new JcrFileUploadReceiver(this, getUploadFolder(), getUploadName(), +// imageManager); +// if (currentUploadHandler != null) +// currentUploadHandler.dispose(); +// currentUploadHandler = prepareUpload(receiver); +// final ServerPushSession pushSession = new ServerPushSession(); + final CmsFileUpload fileUpload = new CmsFileUpload(box, SWT.NONE); + CmsSwtUtils.style(fileUpload, style); + fileUpload.addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = -9158471843941668562L; + + @Override + public void widgetSelected(SelectionEvent e) { +// pushSession.start(); +// fileUpload.submit(currentUploadHandler.getUploadUrl()); + } + }); + return fileUpload; + } + +// protected FileUploadHandler prepareUpload(FileUploadReceiver receiver) { +// final FileUploadHandler uploadHandler = new FileUploadHandler(receiver); +// if (fileUploadListener != null) +// uploadHandler.addUploadListener(fileUploadListener); +// return uploadHandler; +// } + + @Override + public SwtSection getSection() { + return section; + } + +// public void setFileUploadListener(FileUploadListener fileUploadListener) { +// this.fileUploadListener = fileUploadListener; +// if (currentUploadHandler != null) +// currentUploadHandler.addUploadListener(fileUploadListener); +// } + + @Override + public Content getContent() { + return (Content) getData(); + } + + @Override + public String getPartId() { + return ((ProvidedContent) getContent()).getSessionLocalId(); + } + + @Override + public String toString() { + return "Img #" + getPartId(); + } + +} diff --git a/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/EditableImage.java b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/EditableImage.java new file mode 100644 index 000000000..e712e2fe6 --- /dev/null +++ b/swt/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/EditableImage.java @@ -0,0 +1,115 @@ +package org.argeo.cms.swt.widgets; + +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.ux.Cms2DSize; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.ux.AbstractImageManager; +import org.argeo.cms.ux.CmsUxUtils; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** A stylable and editable image. */ +public abstract class EditableImage extends StyledControl { + private static final long serialVersionUID = -5689145523114022890L; + private final static CmsLog log = CmsLog.getLog(EditableImage.class); + + private Cms2DSize preferredImageSize; + private Boolean loaded = false; + + public EditableImage(Composite parent, int swtStyle) { + super(parent, swtStyle); + } + + public EditableImage(Composite parent, int swtStyle, Cms2DSize preferredImageSize) { + super(parent, swtStyle); + this.preferredImageSize = preferredImageSize; + } + + @Override + protected void setContainerLayoutData(Composite composite) { + // composite.setLayoutData(fillWidth()); + } + + @Override + protected void setControlLayoutData(Control control) { + // control.setLayoutData(fillWidth()); + } + + /** To be overriden. */ + protected String createImgTag() { + return noImg(preferredImageSize != null ? preferredImageSize : new Cms2DSize(getSize().x, getSize().y)); + } + + protected Label createLabel(Composite box, String style) { + Label lbl = new Label(box, getStyle()); + // lbl.setLayoutData(CmsUiUtils.fillWidth()); + CmsSwtUtils.markup(lbl); + CmsSwtUtils.style(lbl, style); + if (mouseListener != null) + lbl.addMouseListener(mouseListener); + load(lbl); + return lbl; + } + + /** To be overriden. */ + protected synchronized Boolean load(Control control) { + String imgTag; + try { + imgTag = createImgTag(); + } catch (Exception e) { + // throw new CmsException("Cannot retrieve image", e); + log.error("Cannot retrieve image", e); + imgTag = noImg(preferredImageSize); + loaded = false; + } + + if (imgTag == null) { + loaded = false; + imgTag = noImg(preferredImageSize); + } else + loaded = true; + if (control != null) { + ((Label) control).setText(imgTag); + control.setSize(preferredImageSize != null + ? new Point(preferredImageSize.getWidth(), preferredImageSize.getHeight()) + : getSize()); + } else { + loaded = false; + } + getParent().layout(); + return loaded; + } + + public void setPreferredSize(Cms2DSize size) { + this.preferredImageSize = size; + if (!loaded) { + load((Label) getControl()); + } + } + + protected Text createText(Composite box, String style) { + Text text = new Text(box, getStyle()); + CmsSwtUtils.style(text, style); + return text; + } + + public Cms2DSize getPreferredImageSize() { + return preferredImageSize; + } + + public static String noImg(Cms2DSize size) { +// ResourceManager rm = RWT.getResourceManager(); +// String noImgPath=rm.getLocation(AbstractImageManager.NO_IMAGE); + // FIXME load it via package service + String noImgPath = ""; + return CmsUxUtils.img(noImgPath, size); + } + + public static String noImg() { + return noImg(AbstractImageManager.NO_IMAGE_SIZE); + } + +}