From a79d7060994d8d214d869b3d1da0b95620d0846f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 16 May 2017 21:44:44 +0200 Subject: [PATCH] generify and cleanup a bit around ListSpeedSearch --- .../TurnRefsToSuperDialog.java | 2 +- .../editor/GutterIconsConfigurable.java | 4 +- .../AbstractNewProjectDialog.java | 4 +- .../src/com/intellij/ui/CheckBoxList.java | 20 +++++----- .../ExpandedItemListCellRendererWrapper.java | 8 ++-- .../com/intellij/ui/components/JBList.java | 28 ++++++++------ .../impl/welcomeScreen/FlatWelcomeFrame.java | 37 ++++++++----------- .../src/com/intellij/ui/ListSpeedSearch.java | 33 ++++++++++++----- .../src/com/intellij/ui/TreeUIHelperImpl.java | 3 +- .../plugin/ui/ExistingTemplatesComponent.java | 4 +- .../util/src/com/intellij/util/ui/UIUtil.java | 5 ++- 11 files changed, 79 insertions(+), 69 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java index 95712d769d51..9a7d30f70343 100644 --- a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java @@ -80,7 +80,7 @@ public class TurnRefsToSuperDialog extends RefactoringDialog { final JLabel classListLabel = new JLabel(); panel.add(classListLabel, BorderLayout.NORTH); - mySuperClassesList = new JBList<>(mySuperClasses.toArray()); + mySuperClassesList = new JBList<>(mySuperClasses); mySuperClassesList.setCellRenderer(new ClassCellRenderer(mySuperClassesList.getCellRenderer())); mySuperClassesList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); classListLabel.setText(RefactoringBundle.message("turnRefsToSuper.change.usages.to", mySubClass.getQualifiedName())); diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java index 3c5abb0f0b4d..da9865e71b74 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java @@ -33,10 +33,10 @@ import com.intellij.ui.ListSpeedSearch; import com.intellij.ui.SeparatorWithText; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.speedSearch.SpeedSearchSupply; +import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.hash.HashSet; import com.intellij.util.ui.EmptyIcon; @@ -221,7 +221,7 @@ public class GutterIconsConfigurable implements SearchableConfigurable, Configur }; myList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); myList.setBorder(BorderFactory.createEmptyBorder()); - new ListSpeedSearch(myList, (Convertor)o -> o instanceof JCheckBox ? ((JCheckBox)o).getText() : null); + new ListSpeedSearch<>(myList, (Function)JCheckBox::getText); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectDialog.java b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectDialog.java index 05a3c6a7fc03..3387311ca661 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/AbstractNewProjectDialog.java @@ -41,7 +41,7 @@ import java.awt.event.KeyEvent; * @author Dennis.Ushakov */ public abstract class AbstractNewProjectDialog extends DialogWrapper { - private Pair myPair; + private Pair> myPair; public AbstractNewProjectDialog() { super(ProjectManager.getInstance().getDefaultProject()); @@ -68,7 +68,7 @@ public abstract class AbstractNewProjectDialog extends DialogWrapper { DefaultActionGroup root = createRootStep(); Disposer.register(getDisposable(), () -> root.removeAll()); - Pair pair = FlatWelcomeFrame.createActionGroupPanel(root, getRootPane(), null, getDisposable()); + Pair> pair = FlatWelcomeFrame.createActionGroupPanel(root, getRootPane(), null, getDisposable()); JPanel component = pair.first; new AnAction() { @Override diff --git a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java index 03298b1968a0..fdbf91e0feb2 100644 --- a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java +++ b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java @@ -40,16 +40,16 @@ import java.util.Map; /** * @author oleg */ -public class CheckBoxList extends JBList { +public class CheckBoxList extends JBList { private final CellRenderer myCellRenderer; private CheckBoxListListener checkBoxListListener; private final BidirectionalMap myItemMap = new BidirectionalMap<>(); public CheckBoxList(final CheckBoxListListener checkBoxListListener) { - this(new DefaultListModel(), checkBoxListListener); + this(new DefaultListModel<>(), checkBoxListListener); } - public CheckBoxList(final DefaultListModel dataModel, final CheckBoxListListener checkBoxListListener) { + public CheckBoxList(DefaultListModel dataModel, CheckBoxListListener checkBoxListListener) { this(dataModel); setCheckBoxListListener(checkBoxListListener); } @@ -189,7 +189,7 @@ public class CheckBoxList extends JBList { @NotNull private JCheckBox getCheckBoxAt(int index) { - return (JCheckBox)getModel().getElementAt(index); + return getModel().getElementAt(index); } public void setStringItems(final Map items) { @@ -220,7 +220,7 @@ public class CheckBoxList extends JBList { JCheckBox checkBox = myItemMap.remove(oldItem); myItemMap.put(newItem, checkBox); checkBox.setText(newText); - DefaultListModel model = (DefaultListModel)getModel(); + DefaultListModel model = (DefaultListModel)getModel(); int ind = model.indexOf(checkBox); if (ind >= 0) { model.set(ind, checkBox); // to fire contentsChanged event @@ -229,7 +229,7 @@ public class CheckBoxList extends JBList { @Nullable public T getItemAt(int index) { - JCheckBox checkBox = (JCheckBox)getModel().getElementAt(index); + JCheckBox checkBox = getModel().getElementAt(index); List value = myItemMap.getKeysByValue(checkBox); return value == null || value.isEmpty() ? null : value.get(0); } @@ -240,7 +240,7 @@ public class CheckBoxList extends JBList { } public boolean isItemSelected(int index) { - return ((JCheckBox)getModel().getElementAt(index)).isSelected(); + return getModel().getElementAt(index).isSelected(); } public boolean isItemSelected(T item) { @@ -283,7 +283,7 @@ public class CheckBoxList extends JBList { return rootComponent; } - private class CellRenderer implements ListCellRenderer { + private class CellRenderer implements ListCellRenderer { private final Border mySelectedBorder; private final Border myBorder; private final Insets myBorderInsets; @@ -295,9 +295,7 @@ public class CheckBoxList extends JBList { } @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - JCheckBox checkbox = (JCheckBox)value; - + public Component getListCellRendererComponent(JList list, JCheckBox checkbox, int index, boolean isSelected, boolean cellHasFocus) { Color textColor = getForeground(isSelected); Color backgroundColor = getBackground(isSelected); Font font = getFont(); diff --git a/platform/platform-api/src/com/intellij/ui/ExpandedItemListCellRendererWrapper.java b/platform/platform-api/src/com/intellij/ui/ExpandedItemListCellRendererWrapper.java index f9661958a26e..2c97b499dc07 100644 --- a/platform/platform-api/src/com/intellij/ui/ExpandedItemListCellRendererWrapper.java +++ b/platform/platform-api/src/com/intellij/ui/ExpandedItemListCellRendererWrapper.java @@ -23,17 +23,17 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -public class ExpandedItemListCellRendererWrapper implements ListCellRenderer { - @NotNull private final ListCellRenderer myWrappee; +public class ExpandedItemListCellRendererWrapper implements ListCellRenderer { + @NotNull private final ListCellRenderer myWrappee; @NotNull private final ExpandableItemsHandler myHandler; - public ExpandedItemListCellRendererWrapper(@NotNull ListCellRenderer wrappee, @NotNull ExpandableItemsHandler handler) { + public ExpandedItemListCellRendererWrapper(@NotNull ListCellRenderer wrappee, @NotNull ExpandableItemsHandler handler) { myWrappee = wrappee; myHandler = handler; } @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent(JList list, T value, int index, boolean isSelected, boolean cellHasFocus) { GraphicsUtil.setAntialiasingType(list, AntialiasingType.getAAHintForSwingComponent()); Component result = myWrappee.getListCellRendererComponent(list, UIUtil.htmlInjectionGuard(value), index, isSelected, cellHasFocus); if (!myHandler.getExpandedItems().contains(index)) return result; diff --git a/platform/platform-api/src/com/intellij/ui/components/JBList.java b/platform/platform-api/src/com/intellij/ui/components/JBList.java index b01de23bb4e9..05335527a452 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBList.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBList.java @@ -22,7 +22,6 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; -import com.intellij.util.ArrayUtil; import com.intellij.util.NotNullFunction; import com.intellij.util.ui.*; import org.jetbrains.annotations.NotNull; @@ -40,6 +39,7 @@ import java.awt.*; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; /** @@ -47,38 +47,42 @@ import java.util.Collection; * @author Konstantin Bulenkov */ public class JBList extends JList implements ComponentWithEmptyText, ComponentWithExpandableItems{ - @NotNull private StatusText myEmptyText; - @NotNull private ExpandableItemsHandler myExpandableItemsHandler; + private StatusText myEmptyText; + private ExpandableItemsHandler myExpandableItemsHandler; @Nullable private AsyncProcessIcon myBusyIcon; private boolean myBusy; - public JBList() { init(); } - public JBList(@NotNull ListModel dataModel) { + public JBList(@NotNull ListModel dataModel) { super(dataModel); init(); } - public JBList(@NotNull Object... listData) { + public JBList(@NotNull E... listData) { super(createDefaultListModel(listData)); init(); } @NotNull - public static DefaultListModel createDefaultListModel(@NotNull Object... items) { - final DefaultListModel model = new DefaultListModel(); - for (Object item : items) { + public static DefaultListModel createDefaultListModel(@NotNull T... items) { + return createDefaultListModel(Arrays.asList(items)); + } + + @NotNull + public static DefaultListModel createDefaultListModel(@NotNull Iterable items) { + DefaultListModel model = new DefaultListModel<>(); + for (T item : items) { model.add(model.getSize(), item); } return model; } public JBList(@NotNull Collection items) { - this(ArrayUtil.toObjectArray(items)); + this(createDefaultListModel(items)); } @Override @@ -297,7 +301,7 @@ public class JBList extends JList implements ComponentWithEmptyText, Compo super.setCellRenderer(cellRenderer); return; } - super.setCellRenderer(new ExpandedItemListCellRendererWrapper(cellRenderer, myExpandableItemsHandler)); + super.setCellRenderer(new ExpandedItemListCellRendererWrapper<>(cellRenderer, myExpandableItemsHandler)); } public void installCellRenderer(@NotNull final NotNullFunction fun) { @@ -378,7 +382,7 @@ public class JBList extends JList implements ComponentWithEmptyText, Compo } protected class AccessibleJBListChild extends AccessibleJListChild { - public AccessibleJBListChild(JBList parent, int indexInParent) { + public AccessibleJBListChild(JBList parent, int indexInParent) { super(parent, indexInParent); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java index a0a48ae14b42..d51d80c2535b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java @@ -50,9 +50,8 @@ import com.intellij.ui.components.labels.ActionLink; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.popup.PopupFactoryImpl; import com.intellij.ui.popup.list.GroupedItemsListRenderer; -import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.Convertor; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.MouseEventAdapter; @@ -204,8 +203,8 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, Disposable, Ac return "Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName(); } - @Nullable - public static JComponent getPreferredFocusedComponent(@NotNull Pair pair) { + @NotNull + public static JComponent getPreferredFocusedComponent(@NotNull Pair> pair) { if (pair.second.getModel().getSize() == 1) { JBTextField textField = UIUtil.uiTraverser(pair.first).filter(JBTextField.class).first(); if (textField != null) { @@ -476,10 +475,10 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, Disposable, Ac private AnAction wrapGroups(AnAction action) { if (action instanceof ActionGroup && ((ActionGroup)action).isPopup()) { - final Pair panel = createActionGroupPanel((ActionGroup)action, mySlidingPanel, () -> goBack(), this); + final Pair> panel = createActionGroupPanel((ActionGroup)action, mySlidingPanel, () -> goBack(), this); final Runnable onDone = () -> { setTitle("New Project"); - final JBList list = panel.second; + final JBList list = panel.second; ScrollingUtil.ensureSelectionExists(list); final ListSelectionListener[] listeners = ((DefaultListSelectionModel)list.getSelectionModel()).getListeners(ListSelectionListener.class); @@ -489,9 +488,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, Disposable, Ac listener.valueChanged(new ListSelectionEvent(list, list.getSelectedIndex(), list.getSelectedIndex(), true)); } JComponent toFocus = getPreferredFocusedComponent(panel); - if (toFocus != null) { - IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(toFocus, true)); - } + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(toFocus, true)); }; final String name = action.getClass().getName(); mySlidingPanel.add(name, panel.first); @@ -783,23 +780,19 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, Disposable, Ac return getRootPane(); } - public static void notifyFrameClosed(JFrame frame) { - saveLocation(frame.getBounds()); - } - public static class WelcomeScreenActionsPanel { private JPanel root; private JPanel actions; } - - public static Pair createActionGroupPanel(final ActionGroup action, - final JComponent parent, - final Runnable backAction, - @NotNull Disposable parentDisposable) { + + public static Pair> createActionGroupPanel(final ActionGroup action, + final JComponent parent, + final Runnable backAction, + @NotNull Disposable parentDisposable) { JPanel actionsListPanel = new JPanel(new BorderLayout()); actionsListPanel.setBackground(getProjectsBackground()); final List groups = flattenActionGroups(action); - final DefaultListModel model = JBList.createDefaultListModel(ArrayUtil.toObjectArray(groups)); + final DefaultListModel model = JBList.createDefaultListModel(groups); final JBList list = new JBList<>(model); for (AnAction group : groups) { if (group instanceof Disposable) { @@ -957,10 +950,10 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, Disposable, Ac return back; } - public static void installQuickSearch(JBList list) { - new ListSpeedSearch(list, (Convertor)o -> { + public static void installQuickSearch(JBList list) { + new ListSpeedSearch<>(list, (Function)o -> { if (o instanceof AbstractActionWithPanel) { //to avoid dependency mess with ProjectSettingsStepBase - return ((AbstractActionWithPanel)o).getTemplatePresentation().getText(); + return o.getTemplatePresentation().getText(); } return null; }); diff --git a/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java index 0859178ebd26..395c48b52c84 100644 --- a/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java +++ b/platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java @@ -31,21 +31,33 @@ import javax.swing.*; import java.util.Arrays; import java.util.List; -public class ListSpeedSearch extends SpeedSearchBase { - private final Convertor myToStringConvertor; +public class ListSpeedSearch extends SpeedSearchBase> { + @Nullable private final Function myToStringConvertor; - public ListSpeedSearch(JList list) { - this(list, (Convertor)null); + public ListSpeedSearch(JList list) { + super(list); + myToStringConvertor = null; + registerSelectAll(list); } - public ListSpeedSearch(final JList list, @NotNull Function convertor) { - this(list, (Convertor)convertor::fun); - } - - public ListSpeedSearch(final JList list, @Nullable Convertor convertor) { + @SuppressWarnings("LambdaUnfriendlyMethodOverload") + public ListSpeedSearch(final JList list, @NotNull Function convertor) { super(list); myToStringConvertor = convertor; + registerSelectAll(list); + } + /** + * @deprecated use {@link #ListSpeedSearch(JList, Function)} + */ + @SuppressWarnings("LambdaUnfriendlyMethodOverload") + public ListSpeedSearch(final JList list, @Nullable Convertor convertor) { + super(list); + myToStringConvertor = convertor == null ? null : convertor::convert; + registerSelectAll(list); + } + + private void registerSelectAll(JList list) { new MySelectAllAction(list, this).registerCustomShortcutSet(list, null); } @@ -86,7 +98,8 @@ public class ListSpeedSearch extends SpeedSearchBase { @Override protected String getElementText(Object element) { if (myToStringConvertor != null) { - return myToStringConvertor.convert(element); + //noinspection unchecked + return myToStringConvertor.fun((T)element); } return element == null ? null : element.toString(); } diff --git a/platform/platform-impl/src/com/intellij/ui/TreeUIHelperImpl.java b/platform/platform-impl/src/com/intellij/ui/TreeUIHelperImpl.java index 64606b3423c1..8fcc86efd8b8 100644 --- a/platform/platform-impl/src/com/intellij/ui/TreeUIHelperImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/TreeUIHelperImpl.java @@ -20,6 +20,7 @@ import com.intellij.ui.table.JBTable; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.EditSourceOnDoubleClickHandler; import com.intellij.util.EditSourceOnEnterKeyHandler; +import com.intellij.util.Function; import com.intellij.util.containers.Convertor; import javax.swing.*; @@ -62,7 +63,7 @@ public class TreeUIHelperImpl extends TreeUIHelper { } public void installListSpeedSearch(JList list, Convertor convertor) { - new ListSpeedSearch(list, convertor); + new ListSpeedSearch(list, (Function)convertor::convert); } public void installEditSourceOnEnterKeyHandler(final JTree tree) { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/ExistingTemplatesComponent.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/ExistingTemplatesComponent.java index 8559e9a94d36..eaa75e812beb 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/ExistingTemplatesComponent.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/ExistingTemplatesComponent.java @@ -28,7 +28,7 @@ import com.intellij.structuralsearch.StructuralSearchUtil; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.ui.treeStructure.Tree; -import com.intellij.util.containers.Convertor; +import com.intellij.util.Function; import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; @@ -149,7 +149,7 @@ public class ExistingTemplatesComponent { historyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); historyList.setSelectedIndex(0); - final ListSpeedSearch speedSearch = new ListSpeedSearch(historyList, (Convertor)o -> o instanceof Configuration ? ((Configuration)o).getName() : o.toString()); + ListSpeedSearch speedSearch = new ListSpeedSearch<>(historyList, (Function)Configuration::getName); historyList.setCellRenderer(new ExistingTemplatesListCellRenderer(speedSearch)); configureSelectTemplateAction(historyList); } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index a4b925c2df65..3d0648da4ba4 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -2574,9 +2574,10 @@ public class UIUtil { } } //Escape error-prone HTML data (if any) when we use it in renderers, see IDEA-170768 - public static Object htmlInjectionGuard(Object toRender) { + public static T htmlInjectionGuard(T toRender) { if (toRender instanceof String && ((String)toRender).toLowerCase(Locale.US).startsWith("")) { - toRender = "" + StringUtil.escapeXml((String)toRender); + //noinspection unchecked + return (T) ("" + StringUtil.escapeXml((String)toRender)); } return toRender; }