package org.argeo.entity.ui.forms; import java.util.ArrayList; import java.util.List; import javax.jcr.Item; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.Term; 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; private final static Log log = LogFactory.getLog(MultiTermsPart.class); 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); rl.wrap = true; placeholder.setLayout(rl); List currentValue = getValue(); if (currentValue != null && !currentValue.isEmpty()) for (Term value : currentValue) { Composite block = new Composite(placeholder, SWT.NONE); block.setLayout(CmsUiUtils.noSpaceGridLayout(3)); Label lbl = new Label(block, SWT.SINGLE); String display = getTermLabel(value); lbl.setText(display); CmsUiUtils.style(lbl, style == null ? FormStyle.propertyText.style() : style); if (editable) lbl.addMouseListener((MouseDoubleClick) (e) -> { startEditing(); }); if (isEditing()) { ToolBar toolBar = new ToolBar(block, SWT.HORIZONTAL); ToolItem deleteItem = new ToolItem(toolBar, SWT.FLAT); styleDelete(deleteItem); deleteItem.addSelectionListener((Selected) (e) -> { // we retrieve them again here because they may have changed List curr = getValue(); List newValue = new ArrayList<>(); for (Term v : curr) { if (!v.equals(value)) newValue.add(v); } setValue(newValue); 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.getId()); List currentValue = getValue(); terms: for (Term term : terms) { if (currentValue != null && currentValue.contains(term)) continue terms; String display = getTermLabel(term); if (filter != null && !display.toLowerCase().contains(filter)) continue terms; Label termL = new Label(contextArea, SWT.WRAP); termL.setText(display); processTermListLabel(term, termL); if (isTermSelectable(term)) termL.addMouseListener((MouseDown) (e) -> { List newValue = new ArrayList<>(); List curr = getValue(); if (currentValue != null) newValue.addAll(curr); newValue.add(term); setValue(newValue); contextArea.hide(); stopEditing(); }); } contextArea.show(); } protected List getValue() { String property = typology.getId(); List curr = Jcr.getMultiple(getNode(), property); List res = new ArrayList<>(); if (curr != null) terms: for (String str : curr) { Term term = termsManager.getTerm(str); if (term == null) { log.warn("Ignoring term " + str + " as it was not found."); continue terms; } res.add(term); } return res; } protected void setValue(List value) { String property = typology.getId(); List ids = new ArrayList<>(); for (Term term : value) { ids.add(term.getId()); } Jcr.set(getNode(), property, ids); Jcr.save(getNode()); } }