* improved auto-completion
This commit is contained in:
parent
4346a6e05b
commit
ab14e07924
|
@ -8,7 +8,6 @@ import java.awt.Window;
|
|||
import java.awt.event.ActionEvent;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -34,6 +33,7 @@ import net.sourceforge.tuned.ui.LabelProvider;
|
|||
import net.sourceforge.tuned.ui.SelectButtonTextField;
|
||||
import net.sourceforge.tuned.ui.TunedUtilities;
|
||||
import ca.odell.glazedlists.EventList;
|
||||
import ca.odell.glazedlists.matchers.TextMatcherEditor;
|
||||
import ca.odell.glazedlists.swing.AutoCompleteSupport;
|
||||
|
||||
|
||||
|
@ -73,7 +73,7 @@ public abstract class AbstractSearchPanel<S, E> extends FileBotPanel {
|
|||
searchTextField.getSelectButton().setModel(createSearchEngines());
|
||||
searchTextField.getSelectButton().setLabelProvider(createSearchEngineLabelProvider());
|
||||
|
||||
AutoCompleteSupport.install(searchTextField.getEditor(), searchHistory);
|
||||
AutoCompleteSupport.install(searchTextField.getEditor(), searchHistory).setFilterMode(TextMatcherEditor.CONTAINS);
|
||||
|
||||
TunedUtilities.putActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), searchAction);
|
||||
}
|
||||
|
@ -150,14 +150,30 @@ public abstract class AbstractSearchPanel<S, E> extends FileBotPanel {
|
|||
return;
|
||||
|
||||
try {
|
||||
// choose search result
|
||||
requestProcessor.setSearchResult(requestProcessor.selectSearchResult(get(), SwingUtilities.getWindowAncestor(AbstractSearchPanel.this)));
|
||||
Collection<? extends SearchResult> results = get();
|
||||
|
||||
if (requestProcessor.getSearchResult() == null) {
|
||||
SearchResult selectedSearchResult = null;
|
||||
|
||||
switch (results.size()) {
|
||||
case 0:
|
||||
Logger.getLogger("ui").log(Level.WARNING, String.format("'%s' has not been found.", requestProcessor.request.getSearchText()));
|
||||
break;
|
||||
case 1:
|
||||
selectedSearchResult = results.iterator().next();
|
||||
break;
|
||||
default:
|
||||
selectedSearchResult = requestProcessor.selectSearchResult(results, SwingUtilities.getWindowAncestor(AbstractSearchPanel.this));
|
||||
break;
|
||||
}
|
||||
|
||||
if (selectedSearchResult == null) {
|
||||
tab.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// set search result
|
||||
requestProcessor.setSearchResult(selectedSearchResult);
|
||||
|
||||
String historyEntry = requestProcessor.getHistoryEntry();
|
||||
|
||||
if (historyEntry != null && !searchHistory.contains(historyEntry)) {
|
||||
|
@ -324,28 +340,6 @@ public abstract class AbstractSearchPanel<S, E> extends FileBotPanel {
|
|||
|
||||
|
||||
protected SearchResult selectSearchResult(Collection<? extends SearchResult> searchResults, Window window) throws Exception {
|
||||
|
||||
switch (searchResults.size()) {
|
||||
case 0:
|
||||
Logger.getLogger("ui").warning(String.format("'%s' has not been found.", request.getSearchText()));
|
||||
return null;
|
||||
case 1:
|
||||
return searchResults.iterator().next();
|
||||
}
|
||||
|
||||
List<SearchResult> exactMatches = new LinkedList<SearchResult>();
|
||||
|
||||
// find exact matches
|
||||
for (SearchResult result : searchResults) {
|
||||
if (result.getName().toLowerCase().startsWith(request.getSearchText().toLowerCase())) {
|
||||
exactMatches.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (exactMatches.size() == 1) {
|
||||
return exactMatches.get(0);
|
||||
}
|
||||
|
||||
// multiple results have been found, user must select one
|
||||
SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(window, searchResults);
|
||||
|
||||
|
|
|
@ -8,14 +8,21 @@ import java.awt.event.ActionEvent;
|
|||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.LineBorder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.plaf.basic.BasicComboBoxUI;
|
||||
import javax.swing.plaf.basic.BasicComboPopup;
|
||||
import javax.swing.plaf.basic.ComboPopup;
|
||||
|
@ -41,6 +48,7 @@ public class SelectButtonTextField<T> extends JComponent {
|
|||
add(selectButton, "h pref!, w pref!, sizegroupy this");
|
||||
add(editor, "gap 0, w 195px!, sizegroupy this");
|
||||
|
||||
editor.setRenderer(new CompletionCellRenderer());
|
||||
editor.setUI(new TextFieldComboBoxUI());
|
||||
|
||||
TunedUtilities.putActionForKeystroke(this, KeyStroke.getKeyStroke("ctrl UP"), new SpinClientAction(-1));
|
||||
|
@ -87,6 +95,37 @@ public class SelectButtonTextField<T> extends JComponent {
|
|||
}
|
||||
|
||||
|
||||
private class CompletionCellRenderer extends DefaultListCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
setBorder(new EmptyBorder(1, 4, 1, 4));
|
||||
|
||||
String highlightText = SelectButtonTextField.this.getText().substring(0, ((TextFieldComboBoxUI) editor.getUI()).getEditor().getSelectionStart());
|
||||
|
||||
// highlight the matching sequence
|
||||
Matcher matcher = Pattern.compile(highlightText, Pattern.LITERAL | Pattern.CASE_INSENSITIVE).matcher(value.toString());
|
||||
|
||||
// use no-break, because we really don't want line-wrapping in our table cells
|
||||
StringBuffer htmlText = new StringBuffer("<html><nobr>");
|
||||
|
||||
if (matcher.find()) {
|
||||
matcher.appendReplacement(htmlText, "<span style='font-weight: bold; text-decoration: underline;'>$0</span>");
|
||||
}
|
||||
|
||||
matcher.appendTail(htmlText);
|
||||
|
||||
htmlText.append("</nobr></html>");
|
||||
|
||||
setText(htmlText.toString());
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class TextFieldComboBoxUI extends BasicComboBoxUI {
|
||||
|
||||
@Override
|
||||
|
@ -114,6 +153,27 @@ public class SelectButtonTextField<T> extends JComponent {
|
|||
editor.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
|
||||
|
||||
editor.addFocusListener(createFocusListener());
|
||||
|
||||
editor.getDocument().addDocumentListener(new DocumentListener() {
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
popup.getList().repaint();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
popup.getList().repaint();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
popup.getList().repaint();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,8 +212,9 @@ public class SelectButtonTextField<T> extends JComponent {
|
|||
*/
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (isPopupVisible(comboBox))
|
||||
if (isPopupVisible(comboBox)) {
|
||||
setPopupVisible(comboBox, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue