From 0e4d2bb041ab20d3a3ed33cb8b7023aea61d7234 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 22 Oct 2009 20:45:26 +0400 Subject: [PATCH] Filtering kind of speedsearch for more list choosers + fix filtering performance for large lists. --- .../intellij/execution/filters/YourkitFilter.java | 7 +++-- .../impl/quickfix/CreateFromUsageBaseFix.java | 5 ++-- .../quickfix/CreateInnerClassFromUsageFix.java | 5 ++-- .../ChooseClassAndDoHighlightRunnable.java | 17 ++++++----- .../impl/ImplementAbstractMethodHandler.java | 6 ++-- .../daemon/impl/PsiElementListNavigator.java | 9 +++++- .../codeInsight/navigation/GotoTargetHandler.java | 10 ++++--- .../codeInsight/navigation/NavigationUtil.java | 5 ++-- .../ide/bookmarks/actions/BookmarksAction.java | 2 +- .../ide/util/PsiElementListCellRenderer.java | 19 ++++++++++++ .../openapi/ui/popup/PopupChooserBuilder.java | 2 +- .../ui/speedSearch/FilteringListModel.java | 34 ++++++++++++++++++++-- .../intellij/ui/speedSearch/ListWithFilter.java | 2 +- .../ui/speedSearch/NameFilteringListModel.java | 2 +- .../ide/actions/BaseShowRecentFilesAction.java | 2 +- 15 files changed, 96 insertions(+), 31 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/filters/YourkitFilter.java b/java/execution/impl/src/com/intellij/execution/filters/YourkitFilter.java index 335ea9c062..45d5c3402b 100644 --- a/java/execution/impl/src/com/intellij/execution/filters/YourkitFilter.java +++ b/java/execution/impl/src/com/intellij/execution/filters/YourkitFilter.java @@ -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; } } -} \ No newline at end of file +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java index cdb043c6c2..6301f19fc5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java @@ -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(). diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java index 12443cdb5c..71d688822d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromUsageFix.java @@ -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(). diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java index cfdc1ddf0c..0892d0f94a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java +++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/ChooseClassAndDoHighlightRunnable.java @@ -15,18 +15,18 @@ */ package com.intellij.codeInsight.highlighting; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; -import com.intellij.openapi.editor.Editor; +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.ide.util.PsiClassListCellRenderer; -import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassType; 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(). diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java index a259201764..1420630738 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java @@ -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(). diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index a81ddc5ac9..b74b080811 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -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() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java index 2dddcbbca7..d35dac455c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java @@ -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); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java index 4acd1f4bc4..213a762273 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java @@ -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 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(); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index c91f60bd87..73b777affd 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -243,7 +243,7 @@ public class BookmarksAction extends AnAction implements DumbAware { setSouthComponent(footerPanel). setEastComponent(previewPanel). setItemChoosenCallback(runnable). - setItemsNamer(new Function() { + setFilteringEnabled(new Function() { public String fun(Object o) { return ((ItemWrapper)o).speedSearchText(); } diff --git a/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java b/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java index 62a17a60f2..71d2c66d80 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/ide/util/PsiElementListCellRenderer.java @@ -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 extends J }; } + public void installSpeedSearch(PopupChooserBuilder builder) { + builder.setFilteringEnabled(new Function() { + 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) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java index be8541c354..0cd8fadbe9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java @@ -158,7 +158,7 @@ public class PopupChooserBuilder { return this; } - public PopupChooserBuilder setItemsNamer(Function namer) { + public PopupChooserBuilder setFilteringEnabled(Function namer) { myItemsNamer = namer; return this; } diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/FilteringListModel.java b/platform/platform-api/src/com/intellij/ui/speedSearch/FilteringListModel.java index d7cba11cda..1e541312cd 100644 --- a/platform/platform-api/src/com/intellij/ui/speedSearch/FilteringListModel.java +++ b/platform/platform-api/src/com/intellij/ui/speedSearch/FilteringListModel.java @@ -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 extends DefaultListModel { +public class FilteringListModel extends AbstractListModel { private final JList myList; private final ListModel myOriginalModel; + private final List myData = new ArrayList(); private Condition myCondition = null; + private final ListDataListener myListDataListener = new ListDataListener() { public void contentsChanged(ListDataEvent e) { refilter(); @@ -64,21 +68,47 @@ public class FilteringListModel 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); + } } diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java b/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java index f686d756e8..3d9e368db6 100644 --- a/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java +++ b/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java @@ -113,7 +113,7 @@ public class ListWithFilter 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); } } diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/NameFilteringListModel.java b/platform/platform-api/src/com/intellij/ui/speedSearch/NameFilteringListModel.java index 6d1b213452..bcd9e0beb8 100644 --- a/platform/platform-api/src/com/intellij/ui/speedSearch/NameFilteringListModel.java +++ b/platform/platform-api/src/com/intellij/ui/speedSearch/NameFilteringListModel.java @@ -50,7 +50,7 @@ public class NameFilteringListModel extends FilteringListModel { 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; diff --git a/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java index 38c23a62bf..e3f27616e2 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java @@ -194,7 +194,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb setSouthComponent(footerPanel). setItemChoosenCallback(runnable). addAdditionalChooseKeystroke(getAdditionalSelectKeystroke()). - setItemsNamer(new Function() { + setFilteringEnabled(new Function() { public String fun(Object o) { return o instanceof VirtualFile ? ((VirtualFile)o).getName() : ""; } -- 2.11.4.GIT