Support multiple terms.
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 22 Jan 2021 10:36:45 +0000 (11:36 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 22 Jan 2021 10:36:45 +0000 (11:36 +0100)
org.argeo.entity.ui/pom.xml
org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java [new file with mode: 0644]
org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java [new file with mode: 0644]
org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java [new file with mode: 0644]
org.argeo.entity.ui/src/org/argeo/entity/ui/forms/TermsEditablePart.java [deleted file]

index 47c3da36f10dd50c79a16928df4a27cd2dde2bb3..f2399cf01442827b78c1e2ee53726aa0231069a6 100644 (file)
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.suite</groupId>
                        <version>${version.argeo-commons}</version>
                </dependency>
 
+               <!-- Specific -->
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.eclipse.ui.rap</artifactId>
+                       <version>2.1.91-SNAPSHOT</version>
+                       <scope>provided</scope>
+               </dependency>
+
                <!-- Eclipse E4 -->
                <dependency>
                        <groupId>org.argeo.tp</groupId>
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
new file mode 100644 (file)
index 0000000..a7f240f
--- /dev/null
@@ -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/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
new file mode 100644 (file)
index 0000000..e26fabe
--- /dev/null
@@ -0,0 +1,170 @@
+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<String> 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) -> {
+                                               List<String> newValue = new ArrayList<>();
+                                               for (String v : currentValue) {
+                                                       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<String> terms = termsManager.listAllTerms(typology);
+               List<String> 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<String> newValue = new ArrayList<>();
+                                       if (currentValue != null)
+                                               newValue.addAll(currentValue);
+                                       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
new file mode 100644 (file)
index 0000000..e9fad04
--- /dev/null
@@ -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<String> 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.entity.ui/src/org/argeo/entity/ui/forms/TermsEditablePart.java b/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/TermsEditablePart.java
deleted file mode 100644 (file)
index 7440822..0000000
+++ /dev/null
@@ -1,120 +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.cms.ui.widgets.StyledControl;
-import org.argeo.eclipse.ui.MouseDoubleClick;
-import org.argeo.eclipse.ui.MouseDown;
-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;
-
-/** {@link EditablePart} for terms. */
-public class TermsEditablePart extends StyledControl implements EditablePart {
-       private static final long serialVersionUID = -4961135649177920808L;
-       private TermsManager termsManager;
-       private String typology;
-
-       public TermsEditablePart(Composite parent, int style, Item item, TermsManager termsManager, String typology) {
-               super(parent, style, item);
-               this.termsManager = termsManager;
-               this.typology = typology;
-       }
-
-       @Override
-       protected Control createControl(Composite box, String style) {
-               if (isEditing()) {
-                       Text txt = new Text(box, SWT.SINGLE | SWT.BORDER);
-                       CmsUiUtils.style(txt, style == null ? FormStyle.propertyText.style() : style);
-
-                       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 txt;
-               } else {
-                       Label lbl = new Label(box, SWT.SINGLE);
-               //      lbl.setEditable(false);
-                       String currentValue = Jcr.get(getNode(), typology);
-                       if (currentValue != null) {
-                               String display = getTermLabel(currentValue);
-                               lbl.setText(display);
-                       } else
-                               lbl.setText("[" + typology + "]");
-                       CmsUiUtils.style(lbl, style == null ? FormStyle.propertyText.style() : style);
-
-                       lbl.addMouseListener((MouseDoubleClick) (e) -> {
-                               startEditing();
-                       });
-                       return lbl;
-               }
-       }
-
-       protected String getTermLabel(String name) {
-               return name;
-       }
-
-       protected void refresh(ContextOverlay contextArea, String filter, Text txt) {
-               CmsUiUtils.clear(contextArea);
-               List<String> 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);
-                       termL.addMouseListener((MouseDown) (e) -> {
-                               Jcr.set(getNode(), typology, term);
-                               Jcr.save(getNode());
-                               contextArea.hide();
-                               stopEditing();
-                       });
-               }
-               contextArea.show();
-               // txt.setFocus();
-       }
-
-}