X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=blobdiff_plain;f=org.argeo.app.ui%2Fsrc%2Forg%2Fargeo%2Fapp%2Fui%2Fwidgets%2FConnectAbstractDropDown.java;fp=org.argeo.app.ui%2Fsrc%2Forg%2Fargeo%2Fapp%2Fui%2Fwidgets%2FConnectAbstractDropDown.java;h=d1f1a2921a62acb0dd09d56e285c2de412d862c9;hp=0000000000000000000000000000000000000000;hb=6e56ffa34cb02ab04d028423aea342e3dfed4358;hpb=c285180bece610b2c2921d44fe14b6dde2123efa diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/widgets/ConnectAbstractDropDown.java b/org.argeo.app.ui/src/org/argeo/app/ui/widgets/ConnectAbstractDropDown.java new file mode 100644 index 0000000..d1f1a29 --- /dev/null +++ b/org.argeo.app.ui/src/org/argeo/app/ui/widgets/ConnectAbstractDropDown.java @@ -0,0 +1,194 @@ +package org.argeo.app.ui.widgets; + +import java.util.Arrays; +import java.util.List; + +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.eclipse.rap.rwt.widgets.DropDown; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; + +/** + * Enable easy addition of a {@code DropDown} widget to a text with listeners + * configured + */ +public abstract class ConnectAbstractDropDown { + + private final Text text; + private final DropDown dropDown; + private boolean modifyFromList = false; + + // Current displayed text + private String userText = ""; + // Current displayed list items + private String[] values; + + // Fine tuning + boolean readOnly; + boolean refreshOnFocus; + + /** Implementing classes should call refreshValues() after initialisation */ + public ConnectAbstractDropDown(Text text) { + this(text, SWT.NONE, false); + } + + /** + * Implementing classes should call refreshValues() after initialisation + * + * @param text + * @param style + * only SWT.READ_ONLY is understood, check if the entered text is + * part of the legal choices. + */ + public ConnectAbstractDropDown(Text text, int style) { + this(text, style, false); + } + + /** + * Implementers should call refreshValues() once init has been done. + * + * @param text + * @param style + * only SWT.READ_ONLY is understood, check if the entered text is + * part of the legal choices. + * @param refreshOnFocus + * if true, the possible values are computed each time the focus is + * gained. It enables, among other to fine tune the getFilteredValues + * method depending on the current context + */ + public ConnectAbstractDropDown(Text text, int style, boolean refreshOnFocus) { + this.text = text; + dropDown = new DropDown(text); + Object obj = dropDown; + if (obj instanceof Widget) + CmsSwtUtils.markup((Widget) obj); + readOnly = (style & SWT.READ_ONLY) != 0; + this.refreshOnFocus = refreshOnFocus; + addListeners(); + } + + /** + * Overwrite to force the refresh of the possible values on focus gained event + */ + protected boolean refreshOnFocus() { + return refreshOnFocus; + } + + public String getText() { + return text.getText(); + } + + public void init() { + refreshValues(); + } + + public void reset(String value) { + modifyFromList = true; + if (EclipseUiUtils.notEmpty(value)) + text.setText(value); + else + text.setText(""); + refreshValues(); + modifyFromList = false; + } + + /** Overwrite to provide specific filtering */ + protected abstract List getFilteredValues(String filter); + + protected void refreshValues() { + List filteredValues = getFilteredValues(text.getText()); + values = filteredValues.toArray(new String[filteredValues.size()]); + dropDown.setItems(values); + } + + protected void addListeners() { + addModifyListener(); + addSelectionListener(); + addDefaultSelectionListener(); + addFocusListener(); + } + + protected void addFocusListener() { + text.addFocusListener(new FocusListener() { + private static final long serialVersionUID = -7179112097626535946L; + + public void focusGained(FocusEvent event) { + if (refreshOnFocus) { + modifyFromList = true; + refreshValues(); + modifyFromList = false; + } + dropDown.setVisible(true); + } + + public void focusLost(FocusEvent event) { + dropDown.setVisible(false); + if (readOnly && values != null && !Arrays.asList(values).contains(userText)) { + modifyFromList = true; + text.setText(""); + refreshValues(); + modifyFromList = false; + } + } + }); + } + + private void addSelectionListener() { + Object obj = dropDown; + if (obj instanceof Widget) + ((Widget) obj).addListener(SWT.Selection, new Listener() { + private static final long serialVersionUID = -2357157809365135142L; + + public void handleEvent(Event event) { + if (event.index != -1) { + modifyFromList = true; + text.setText(values[event.index]); + modifyFromList = false; + text.selectAll(); + } else { + text.setText(userText); + text.setSelection(userText.length(), userText.length()); + text.setFocus(); + } + } + }); + } + + private void addDefaultSelectionListener() { + Object obj = dropDown; + if (obj instanceof Widget) + ((Widget) obj).addListener(SWT.DefaultSelection, new Listener() { + private static final long serialVersionUID = -5958008322630466068L; + + public void handleEvent(Event event) { + if (event.index != -1) { + text.setText(values[event.index]); + text.setSelection(event.text.length()); + dropDown.setVisible(false); + } + } + }); + } + + private void addModifyListener() { + text.addListener(SWT.Modify, new Listener() { + private static final long serialVersionUID = -4373972835244263346L; + + public void handleEvent(Event event) { + if (!modifyFromList) { + userText = text.getText(); + refreshValues(); + if (values.length == 1) + dropDown.setSelectionIndex(0); + dropDown.setVisible(true); + } + } + }); + } +}