Snip2Code is shutting down.
It has been quite a ride, since 2013 when we launched our first prototype: thanks to the effort of you guys we collected more than 3 million snippets!
We are very proud to help all our users to be more efficient in their jobs, and to be the central point to share programming knowledge for everyone.
Our basic service is free, so we always survived on our own resources to give you Snip2Code.
Unfortunately, we are no more in the financial position to sustain this effort, and therefore we are announcing here our permanent shut down,
which will take place on August 1st, 2020.
Please save your private snippets using our backup function in the settings, here.
This will allow us to pay for the servers and the infrastructure. If you want to donate, Contact Us!
Top 1% !
Pearl of Wisdom
Popularity: 736th place

Published on:


Java SWT: Combobox with AutoSuggestion feature

This component can be safely used when you want to have a combobox with the capability to display automatic filtered suggestions based on the text already entered.
It uses a couple of callback actions so that the caller can specify what to do when ENTER key is hit and how to load suggestions.
The call back actions are specified by a simple interface Callback with a single method.
Copy Embed Code
<iframe id="embedFrame" style="width:600px; height:300px;"
Click on the embed code to copy it into your clipboard Width Height
Leave empty to retrieve all the content Start End
package com.snip2code.ui.swt; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import; import; import; import; import; import; import; import; import; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import com.snip2code.utils.Utils; /** * (c) 2011 snip2code inc. * This software is property of snip2code inc. Use or reproduction without permission is prohibited * * This widget creates a textfield with an autosuggestion feature. * The list of suggestion is shown when the user clicks on the text field or starts typing in the text field */ public class AutoSuggestionComposite extends Composite { protected static Logger log = Logger.getLogger(AutoSuggestionComposite.class); private Composite textBoxStackPanel; private StackLayout textboxLayout; private Text textBox; private Label tooltip; private Shell popupShell; private Table table; private String tooltipMsg; private ICallback<String, List<String>> loadSuggestionAction; private ICallback<String, String> onEnterAction; private String text; private int numOfDisplayedSuggestions; private static final String POPUPVISIB = "$$$POPUP_VISIB"; private String uniqueID; //used to differentiate AutoSuggestion composites in the same dialog private static Random rdn = new Random(); /** * Create the dialog. * @param parent * @param style * @param tooltipMsg message to display when no input is entered * @param numOfDisplayedSuggestions masimum number of items suggested in the popup of suggestions * @param loadSuggestionAction callback to routine that loads the suggestions for autocomplete * @param onEnterAction callback when enter is pressed on the textbox */ public AutoSuggestionComposite(Composite parent, int style, String tooltipMsg, int numOfDisplayedSuggestions, ICallback<String, List<String>> loadSuggestionAction, ICallback<String, String> onEnterAction) { super(parent, style); textboxLayout = new StackLayout(); this.loadSuggestionAction = loadSuggestionAction; this.onEnterAction = onEnterAction; this.numOfDisplayedSuggestions = numOfDisplayedSuggestions; this.tooltipMsg = tooltipMsg; uniqueID = rdn.nextInt() + tooltipMsg; createDialogArea(); } private void createDialogArea() { this.setBackground(SWTUIUtilities.WHITE); GridLayout gridLayout = new GridLayout(); gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; this.setLayout(gridLayout); //Panel with textbox and tooltip: textBoxStackPanel = new Composite(this, SWT.NONE); textBoxStackPanel.setLayout(textboxLayout); GridData gdPanel = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); gdPanel.verticalIndent = 2; textBoxStackPanel.setLayoutData(gdPanel); tooltip = new Label(textBoxStackPanel, SWT.NONE); tooltip.setBackground(SWTUIUtilities.WHITE); tooltip.setForeground(SWTUIUtilities.LIGHT_GREY); tooltip.setFont(SWTUIUtilities.LBL_TEXT); tooltip.setText(" " + tooltipMsg); //manual horizontal indent, cause StackLayout doesn't allow this feature tooltip.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { setControlVisib(textBox, true); textBoxStackPanel.layout(); textBox.setFocus(); loadSuggestions(null); } }); textBox = new Text(textBoxStackPanel, SWT.NONE); textBox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); textBox.setFont(SWTUIUtilities.LBL_TEXT); textBox.setBackground(SWTUIUtilities.WHITE); textBox.setData(POPUPVISIB, uniqueID); //popup for suggestions: popupShell = new Shell(getShell().getDisplay(), SWT.ON_TOP); popupShell.setLayout(new FillLayout()); popupShell.setData(POPUPVISIB, uniqueID); popupShell.setBackground(SWTUIUtilities.WHITE); table = new Table(popupShell, SWT.SINGLE); table.getVerticalBar().setVisible(false); table.setFont(SWTUIUtilities.LBL_TEXT); table.setData(POPUPVISIB, uniqueID); for (int i = 0; i < numOfDisplayedSuggestions; i++) { new TableItem(table, SWT.NONE); } //Key Listener for Keyboards events: textBox.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { boolean loadSuggestions = true; saveInput(); switch (e.keyCode) { case SWT.ARROW_DOWN: int index = (table.getSelectionIndex() + 1) % table.getItemCount(); table.setSelection(index); e.doit = false; break; case SWT.ARROW_UP: index = table.getSelectionIndex() - 1; if (index < 0) index = table.getItemCount() - 1; table.setSelection(index); e.doit = false; break; case SWT.CR: case SWT.LF: case 16777296: //enter in numeric keypad if (popupShell.isVisible() && table.getSelectionIndex() != -1) { textBox.setText(table.getSelection()[0].getText()); } loadSuggestions = false; execEnterAction(); break; case SWT.ESC: popupShell.setVisible(false); break; } //only for printable characters, load search history: if (loadSuggestions && (e.keyCode < 256)) loadSuggestions(textBox.getText()); log.debug("End of key listener"); } }); //make sure the input entered in the text box is saved and ready to use: textBox.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { log.debug("Focus lost by textbox of autosugg from " + tooltipMsg); saveInput(); checkTooltipVisib(); handleFocusLost(); } @Override public void focusGained(FocusEvent e) { if (isDisposed() || getShell().isDisposed() || getShell().getDisplay().isDisposed()) return; log.debug("Focus gained by textbox of autosugg from " + tooltipMsg); loadSuggestions(textBox.getText()); } }); textBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { checkTooltipVisib(); } }); table.addListener(SWT.DefaultSelection, new Listener() { public void handleEvent(Event event) { textBox.setText(table.getSelection()[0].getText()); execEnterAction(); } }); //hide the popup of suggestions if the focus is out: Listener focusOutListener = new Listener() { public void handleEvent(Event event) { handleFocusLost(); } }; table.addListener(SWT.FocusOut, focusOutListener); textBox.addListener(SWT.FocusOut, focusOutListener); textBoxStackPanel.addListener(SWT.FocusOut, focusOutListener); popupShell.addListener(SWT.FocusOut, focusOutListener); this.addListener(SWT.FocusOut, focusOutListener); getShell().addListener(SWT.Move, new Listener() { public void handleEvent(Event event) { popupShell.setVisible(false); checkTooltipVisib(); } }); checkTooltipVisib(); } private void handleFocusLost() { /* async is needed to wait until focus reaches its new Control */ if (isDisposed() || getShell().isDisposed() || getShell().getDisplay().isDisposed()) return; getShell().getDisplay().asyncExec(new Runnable() { public void run() { log.debug("Running handleFocusLost for " + tooltipMsg); if (isDisposed() || getShell().isDisposed() || getShell().getDisplay().isDisposed()) return; Control control = getShell().getDisplay().getFocusControl(); log.debug("handleFocusLost for " + tooltipMsg + ": control is " + control + ";uniqueID:" + uniqueID); if ((control == null) || (control.getData(POPUPVISIB) == null) || !control.getData(POPUPVISIB).toString().equals(uniqueID)) { popupShell.setVisible(false); } } }); } /** * Determines the visibility of textbox content vs tooltip when the textbox is empty */ public void checkTooltipVisib() { if (Utils.isNullOrEmpty(textBox.getText())) setControlVisib(tooltip, true); else setControlVisib(textBox, true); textBoxStackPanel.layout(); } private void execEnterAction() { saveInput(); popupShell.setVisible(false); onEnterAction.exec(text); } private void loadSuggestions(String prefix) { log.debug("loading suggestions for " + prefix); // if (Utils.isNullOrEmpty(prefix)) // return; Rectangle textBounds = getShell().getDisplay().map(textBoxStackPanel, null, textBox.getBounds()); //load suggestions: List<String> suggestions = loadSuggestionAction.exec(prefix); log.debug("loaded " + suggestions.size() + " suggestions"); table.setItemCount(suggestions.size()); TableItem[] items = table.getItems(); int maxWidthOfItem = 0; log.debug("Changing " + items.length + " items in TablePopup"); for (int i = 0; i < items.length; i++) { if (i < suggestions.size()) { String sugg = suggestions.get(i); if (!Utils.isNullOrEmpty(sugg)) { items[i].setText(sugg); int w = items[i].getBounds().width; if (w > maxWidthOfItem) maxWidthOfItem = w; } } } // //avoid the display of horizontal scrollbar when not needed (10 is the width of the scrollbar) // if ((maxWidthOfItem + 10) < textBounds.width) // table.pack(); //23 pixels is the height of 1 item in the drop down list; //always add a blank line at the end of the list to improve readability int popupHeight = (suggestions.size() + 1) * 23; log.debug("popupHeight for [" + this.tooltipMsg + "]:" + popupHeight); if (popupHeight <= 46) popupHeight = 46; //set a cap to the maximum height of the popup (17 lines): if (popupHeight > 391) { popupHeight = 391; table.getVerticalBar().setVisible(true); } else { //avoid the display of horizontal scrollbar when not needed (10 is the width of the scrollbar) if ((maxWidthOfItem + 10) < textBounds.width) table.pack(); table.getVerticalBar().setVisible(false); } log.debug("setBounds popup:" + textBounds.x + ";" + (textBounds.y + textBounds.height + 4) + ";" + textBounds.width + ";" + popupHeight); popupShell.setBounds(textBounds.x, textBounds.y + textBounds.height + 4, textBounds.width, popupHeight); popupShell.setVisible(true); } private void setControlVisib(Control c, boolean visible) { if (c == null) return; if (visible) textboxLayout.topControl = c; } private void saveInput() { text = textBox.getText(); if (text == null) text = ""; text = text.trim(); } /** * Returns the content of the textbox */ public String getText() { return text; } /** * Sets the content of the textbox */ public void setText(String text) { this.text = text; textBox.setText(text); setControlVisib(textBox, true); } /** * Hides the popup of suggestions */ public void hideSuggestions() { popupShell.setVisible(false); } @Override public void dispose() { if (popupShell != null) { hideSuggestions(); popupShell.dispose(); } super.dispose(); } }
If you want to be updated about similar snippets, Sign in and follow our Channels

blog comments powered by Disqus