Filtering kind of speedsearch for more list choosers + fix filtering performance for large lists.

This commit is contained in:
Maxim Shafirov
2009-10-22 20:46:46 +04:00
parent 031fd1ed10
commit 0e4d2bb041
15 changed files with 96 additions and 31 deletions
@@ -88,7 +88,8 @@ public class YourkitFilter implements Filter{
final JList list = new JList(myPsiFiles);
list.setCellRenderer(renderer);
renderer.installSpeedSearch(list);
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
renderer.installSpeedSearch(builder);
final Runnable runnable = new Runnable() {
public void run() {
@@ -106,7 +107,7 @@ public class YourkitFilter implements Filter{
final Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext());
new PopupChooserBuilder(list).
builder.
setTitle("Choose file").
setItemChoosenCallback(runnable).
createPopup().showInBestPositionFor(editor);
@@ -132,4 +133,4 @@ public class YourkitFilter implements Filter{
return 0;
}
}
}
}
@@ -115,7 +115,8 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setCellRenderer(renderer);
renderer.installSpeedSearch(list);
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
renderer.installSpeedSearch(builder);
Runnable runnable = new Runnable() {
public void run() {
@@ -135,7 +136,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
}
};
new PopupChooserBuilder(list).
builder.
setTitle(QuickFixBundle.message("target.class.chooser.title")).
setItemChoosenCallback(runnable).
createPopup().
@@ -93,7 +93,8 @@ public class CreateInnerClassFromUsageFix extends CreateClassFromUsageBaseFix {
PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setCellRenderer(renderer);
renderer.installSpeedSearch(list);
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
renderer.installSpeedSearch(builder);
Runnable runnable = new Runnable() {
public void run() {
@@ -118,7 +119,7 @@ public class CreateInnerClassFromUsageFix extends CreateClassFromUsageBaseFix {
}
};
new PopupChooserBuilder(list).
builder.
setTitle(QuickFixBundle.message("target.class.chooser.title")).
setItemChoosenCallback(runnable).
createPopup().
@@ -15,18 +15,18 @@
*/
package com.intellij.codeInsight.highlighting;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.codeInsight.CodeInsightBundle;
import javax.swing.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
public abstract class ChooseClassAndDoHighlightRunnable implements Runnable {
@@ -79,7 +79,8 @@ public abstract class ChooseClassAndDoHighlightRunnable implements Runnable {
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.setCellRenderer(renderer);
renderer.installSpeedSearch(myList);
final PopupChooserBuilder builder = new PopupChooserBuilder(myList);
renderer.installSpeedSearch(builder);
final Runnable callback = new Runnable() {
public void run() {
@@ -96,7 +97,7 @@ public abstract class ChooseClassAndDoHighlightRunnable implements Runnable {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
new PopupChooserBuilder(myList).
builder.
setTitle(myTitle).
setItemChoosenCallback(callback).
createPopup().
@@ -96,7 +96,6 @@ public class ImplementAbstractMethodHandler {
myList = new JList(result[0]);
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.setCellRenderer(renderer);
renderer.installSpeedSearch(myList);
final Runnable runnable = new Runnable(){
public void run() {
@@ -107,7 +106,10 @@ public class ImplementAbstractMethodHandler {
}
};
new PopupChooserBuilder(myList).
final PopupChooserBuilder builder = new PopupChooserBuilder(myList);
renderer.installSpeedSearch(builder);
builder.
setTitle(CodeInsightBundle.message("intention.implement.abstract.method.class.chooser.title")).
setItemChoosenCallback(runnable).
createPopup().
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.psi.NavigatablePsiElement;
@@ -39,7 +40,13 @@ public class PsiElementListNavigator {
else{
final JList list = new JList(targets);
list.setCellRenderer(listRenderer);
new PopupChooserBuilder(list).
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
if (listRenderer instanceof PsiElementListCellRenderer) {
((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder);
}
builder.
setTitle(title).
setMovable(true).
setItemChoosenCallback(new Runnable() {
@@ -23,9 +23,9 @@ import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.Navigatable;
@@ -96,7 +96,6 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
final JList list = new JList(elements);
list.setCellRenderer(renderer);
renderer.installSpeedSearch(list);
final Runnable runnable = new Runnable() {
public void run() {
@@ -112,9 +111,12 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
}
};
new PopupChooserBuilder(list).
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
renderer.installSpeedSearch(builder);
builder.
setTitle(title).
setItemChoosenCallback(runnable).
setMovable(true).
createPopup().showInBestPositionFor(editor);
}
}
@@ -16,9 +16,9 @@
package com.intellij.codeInsight.navigation;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.pom.Navigatable;
@@ -57,7 +57,6 @@ public final class NavigationUtil {
final String title, final PsiElementProcessor<T> processor) {
final JList list = new JList(elements);
list.setCellRenderer(renderer);
renderer.installSpeedSearch(list);
final Runnable runnable = new Runnable() {
public void run() {
@@ -75,6 +74,8 @@ public final class NavigationUtil {
if (title != null) {
builder.setTitle(title);
}
renderer.installSpeedSearch(builder);
return builder.setItemChoosenCallback(runnable).createPopup();
}
@@ -243,7 +243,7 @@ public class BookmarksAction extends AnAction implements DumbAware {
setSouthComponent(footerPanel).
setEastComponent(previewPanel).
setItemChoosenCallback(runnable).
setItemsNamer(new Function<Object, String>() {
setFilteringEnabled(new Function<Object, String>() {
public String fun(Object o) {
return ((ItemWrapper)o).speedSearchText();
}
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
@@ -33,6 +34,7 @@ import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.FileColorManager;
import com.intellij.ui.ListSpeedSearch;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Function;
import com.intellij.util.IconUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -185,6 +187,23 @@ public abstract class PsiElementListCellRenderer<T extends PsiElement> extends J
};
}
public void installSpeedSearch(PopupChooserBuilder builder) {
builder.setFilteringEnabled(new Function<Object, String>() {
public String fun(Object o) {
if (o instanceof PsiElement) {
return PsiElementListCellRenderer.this.getElementText((T)o);
}
else {
return o.toString();
}
}
});
}
/**
* User {@link #installSpeedSearch(com.intellij.openapi.ui.popup.PopupChooserBuilder)} instead
*/
@Deprecated
public void installSpeedSearch(JList list) {
new ListSpeedSearch(list) {
protected String getElementText(Object o) {
@@ -158,7 +158,7 @@ public class PopupChooserBuilder {
return this;
}
public PopupChooserBuilder setItemsNamer(Function<Object, String> namer) {
public PopupChooserBuilder setFilteringEnabled(Function<Object, String> namer) {
myItemsNamer = namer;
return this;
}
@@ -24,15 +24,19 @@ import com.intellij.openapi.util.Condition;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.util.ArrayList;
import java.util.List;
/**
* @author max
*/
public class FilteringListModel<T> extends DefaultListModel {
public class FilteringListModel<T> extends AbstractListModel {
private final JList myList;
private final ListModel myOriginalModel;
private final List<T> myData = new ArrayList<T>();
private Condition<T> myCondition = null;
private final ListDataListener myListDataListener = new ListDataListener() {
public void contentsChanged(ListDataEvent e) {
refilter();
@@ -64,21 +68,47 @@ public class FilteringListModel<T> extends DefaultListModel {
refilter();
}
private void removeAllElements() {
int index1 = myData.size() - 1;
if (index1 >= 0) {
myData.clear();
fireIntervalRemoved(this, 0, index1);
}
}
public void refilter() {
removeAllElements();
int count = 0;
for (int i = 0; i < myOriginalModel.getSize(); i++) {
final T elt = (T)myOriginalModel.getElementAt(i);
if (passElement(elt)) {
addToFiltered(elt);
count++;
}
}
if (count > 0) {
fireIntervalAdded(this, 0, count - 1);
}
}
protected void addToFiltered(T elt) {
addElement(elt);
myData.add(elt);
}
public int getSize() {
return myData.size();
}
public Object getElementAt(int index) {
return myData.get(index);
}
private boolean passElement(T element) {
return myCondition == null || myCondition.value(element);
}
public boolean contains(T value) {
return myData.contains(value);
}
}
@@ -113,7 +113,7 @@ public class ListWithFilter<T> extends JPanel {
myList.setSelectedIndex(fullMatchIndex);
}
if (myModel.getSize() <= myList.getSelectedIndex() || !myModel.contains(myList.getSelectedValue())) {
if (myModel.getSize() <= myList.getSelectedIndex() || !myModel.contains((T)myList.getSelectedValue())) {
myList.setSelectedIndex(0);
}
}
@@ -50,7 +50,7 @@ public class NameFilteringListModel<T> extends FilteringListModel<T> {
if (myNamer != null) {
String filterString = mySpeedSearch.getFilter().toUpperCase();
String candidateString = myNamer.fun(elt).toUpperCase();
int index = size() - 1;
int index = getSize() - 1;
if (myFullMatchIndex == -1 && filterString.equals(candidateString)) {
myFullMatchIndex = index;
@@ -194,7 +194,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
setSouthComponent(footerPanel).
setItemChoosenCallback(runnable).
addAdditionalChooseKeystroke(getAdditionalSelectKeystroke()).
setItemsNamer(new Function<Object, String>() {
setFilteringEnabled(new Function<Object, String>() {
public String fun(Object o) {
return o instanceof VirtualFile ? ((VirtualFile)o).getName() : "";
}