* improved auto-completion

This commit is contained in:
Reinhard Pointner 2009-02-22 19:52:07 +00:00
parent 4346a6e05b
commit ab14e07924
2 changed files with 83 additions and 28 deletions

View File

@ -8,7 +8,6 @@ import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.net.URI; import java.net.URI;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; 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.SelectButtonTextField;
import net.sourceforge.tuned.ui.TunedUtilities; import net.sourceforge.tuned.ui.TunedUtilities;
import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.matchers.TextMatcherEditor;
import ca.odell.glazedlists.swing.AutoCompleteSupport; import ca.odell.glazedlists.swing.AutoCompleteSupport;
@ -73,7 +73,7 @@ public abstract class AbstractSearchPanel<S, E> extends FileBotPanel {
searchTextField.getSelectButton().setModel(createSearchEngines()); searchTextField.getSelectButton().setModel(createSearchEngines());
searchTextField.getSelectButton().setLabelProvider(createSearchEngineLabelProvider()); searchTextField.getSelectButton().setLabelProvider(createSearchEngineLabelProvider());
AutoCompleteSupport.install(searchTextField.getEditor(), searchHistory); AutoCompleteSupport.install(searchTextField.getEditor(), searchHistory).setFilterMode(TextMatcherEditor.CONTAINS);
TunedUtilities.putActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), searchAction); TunedUtilities.putActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), searchAction);
} }
@ -150,14 +150,30 @@ public abstract class AbstractSearchPanel<S, E> extends FileBotPanel {
return; return;
try { try {
// choose search result Collection<? extends SearchResult> results = get();
requestProcessor.setSearchResult(requestProcessor.selectSearchResult(get(), SwingUtilities.getWindowAncestor(AbstractSearchPanel.this)));
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(); tab.close();
return; return;
} }
// set search result
requestProcessor.setSearchResult(selectedSearchResult);
String historyEntry = requestProcessor.getHistoryEntry(); String historyEntry = requestProcessor.getHistoryEntry();
if (historyEntry != null && !searchHistory.contains(historyEntry)) { 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 { 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 // multiple results have been found, user must select one
SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(window, searchResults); SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(window, searchResults);

View File

@ -8,14 +8,21 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder; 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.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup; 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(selectButton, "h pref!, w pref!, sizegroupy this");
add(editor, "gap 0, w 195px!, sizegroupy this"); add(editor, "gap 0, w 195px!, sizegroupy this");
editor.setRenderer(new CompletionCellRenderer());
editor.setUI(new TextFieldComboBoxUI()); editor.setUI(new TextFieldComboBoxUI());
TunedUtilities.putActionForKeystroke(this, KeyStroke.getKeyStroke("ctrl UP"), new SpinClientAction(-1)); 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 { private class TextFieldComboBoxUI extends BasicComboBoxUI {
@Override @Override
@ -114,6 +153,27 @@ public class SelectButtonTextField<T> extends JComponent {
editor.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3)); editor.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
editor.addFocusListener(createFocusListener()); 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 @Override
public void focusLost(FocusEvent e) { public void focusLost(FocusEvent e) {
if (isPopupVisible(comboBox)) if (isPopupVisible(comboBox)) {
setPopupVisible(comboBox, false); setPopupVisible(comboBox, false);
}
} }
}; };
} }