From: Mathieu Baudier Date: Fri, 22 Jan 2021 10:36:45 +0000 (+0100) Subject: Support multiple terms. X-Git-Tag: argeo-suite-2.1.18~29 X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=commitdiff_plain;h=5401f7a23b5251bb37514f5495b75f79320bedc0 Support multiple terms. --- diff --git a/org.argeo.entity.ui/pom.xml b/org.argeo.entity.ui/pom.xml index 47c3da3..f2399cf 100644 --- a/org.argeo.entity.ui/pom.xml +++ b/org.argeo.entity.ui/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 org.argeo.suite @@ -24,6 +26,14 @@ ${version.argeo-commons} + + + org.argeo.commons + org.argeo.eclipse.ui.rap + 2.1.91-SNAPSHOT + provided + + org.argeo.tp 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 index 0000000..a7f240f --- /dev/null +++ b/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/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 index 0000000..e26fabe --- /dev/null +++ b/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java @@ -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 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 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 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<>(); + 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 index 0000000..e9fad04 --- /dev/null +++ b/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/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 index 7440822..0000000 --- a/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/TermsEditablePart.java +++ /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 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(); - } - -}