IDEA-195193 Plugins: implement search

This commit is contained in:
Alexander Lobas
2018-08-22 19:27:14 +03:00
parent 6c40e13256
commit 075ab1676c
6 changed files with 103 additions and 11 deletions
@@ -255,7 +255,7 @@ public class SearchTextField extends JPanel {
}
}
private boolean toClearTextOnEscape() {
protected boolean toClearTextOnEscape() {
return ApplicationManager.getApplication() != null;
}
@@ -8,10 +8,7 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.newui.*;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.idea.IdeaApplication;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.ModalityState;
@@ -143,6 +140,9 @@ public class PluginManagerConfigurableNew
if (keyCode == KeyEvent.VK_ENTER || event.getKeyChar() == '\n') {
if (id == KeyEvent.KEY_PRESSED &&
(myCurrentSearchPanel.controller == null || !myCurrentSearchPanel.controller.handleEnter(event))) {
if (myCurrentSearchPanel.controller != null) {
myCurrentSearchPanel.controller.hidePopup();
}
showSearchPanel(mySearchTextField.getText());
}
return true;
@@ -154,6 +154,31 @@ public class PluginManagerConfigurableNew
return super.preprocessEventForTextField(event);
}
@Override
protected boolean toClearTextOnEscape() {
new AnAction() {
{
setEnabledInModalContext(true);
}
@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(!getText().isEmpty());
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
if (myCurrentSearchPanel.controller != null && myCurrentSearchPanel.controller.isPopupShow()) {
myCurrentSearchPanel.controller.hidePopup();
}
else {
setText("");
}
}
}.registerCustomShortcutSet(CommonShortcuts.ESCAPE, this);
return false;
}
@Override
protected void onFieldCleared() {
hideSearchPanel();
@@ -825,6 +850,8 @@ public class PluginManagerConfigurableNew
createPopup(new CollectionListModel<>(result), SearchPopup.Type.SearchQuery);
}
myPopup.data = query;
if (update) {
myPopup.update();
return;
@@ -839,7 +866,14 @@ public class PluginManagerConfigurableNew
@Override
protected void customizeCellRenderer(@NotNull JList list, Object value, int index, boolean selected, boolean hasFocus) {
IdeaPluginDescriptor descriptor = (IdeaPluginDescriptor)value;
append(descriptor.getName());
String splitter = (String)myPopup.data;
for (String partName : SearchQueryParser.split(descriptor.getName(), splitter)) {
append(partName, partName.equalsIgnoreCase(splitter)
? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES
: SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
if (isJBPlugin(descriptor)) {
append(" by JetBrains", SimpleTextAttributes.GRAY_ATTRIBUTES);
}
@@ -856,14 +890,36 @@ public class PluginManagerConfigurableNew
}
@NotNull
private List<IdeaPluginDescriptor> localSearchPlugins(String query) {
List<IdeaPluginDescriptor> descriptors = new ArrayList<>();
private List<IdeaPluginDescriptor> localSearchPlugins(@NotNull String query) {
IdeaPluginDescriptor descriptorEquals = null;
List<IdeaPluginDescriptor> descriptorsStartWith = new ArrayList<>();
List<IdeaPluginDescriptor> descriptorsContains = new ArrayList<>();
for (IdeaPluginDescriptor descriptor : getJBRepositoryList()) {
if (StringUtil.containsIgnoreCase(descriptor.getName(), query)) {
descriptors.add(descriptor);
String name = descriptor.getName();
if (descriptorEquals == null && name.equalsIgnoreCase(query)) {
descriptorEquals = descriptor;
}
else if (StringUtil.startsWithIgnoreCase(name, query)) {
descriptorsStartWith.add(descriptor);
}
else if (StringUtil.containsIgnoreCase(name, query)) {
descriptorsContains.add(descriptor);
}
}
return descriptors;
List<IdeaPluginDescriptor> result = new ArrayList<>();
if (descriptorEquals != null) {
result.add(descriptorEquals);
}
PluginsGroup.sortByName(descriptorsStartWith);
result.addAll(descriptorsStartWith);
PluginsGroup.sortByName(descriptorsContains);
result.addAll(descriptorsContains);
return result;
}
};
myTrendingSearchPanel =
@@ -67,6 +67,10 @@ public class PluginsGroup {
}
public void sortByName() {
sortByName(descriptors);
}
public static void sortByName(@NotNull List<IdeaPluginDescriptor> descriptors) {
ContainerUtil.sort(descriptors, (o1, o2) -> StringUtil.compare(o1.getName(), o2.getName(), true));
}
}
@@ -34,6 +34,8 @@ public class SearchPopup implements CaretListener {
public boolean skipCaretEvent;
public Object data;
public enum Type {
AttributeName, AttributeValue, SearchQuery
}
@@ -227,6 +227,10 @@ public abstract class SearchPopupController {
protected void handleAppendAttributeValue() {
}
public boolean isPopupShow() {
return myPopup != null && myPopup.isValid();
}
public void hidePopup() {
if (myPopup != null) {
myPopup.hide();
@@ -1,6 +1,7 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins.newui;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
@@ -15,6 +16,31 @@ import java.util.Set;
public abstract class SearchQueryParser {
public String searchQuery;
@NotNull
public static List<String> split(@NotNull String name, @NotNull String query) {
List<String> result = new ArrayList<>();
int length = name.length();
int queryLength = query.length();
int index = 0;
while (true) {
int end = StringUtil.indexOfIgnoreCase(name, query, index);
if (end == -1) {
break;
}
result.add(name.substring(index, end));
index = end + queryLength;
result.add(name.substring(end, index));
}
if (index < length) {
result.add(name.substring(index));
}
return result;
}
@NotNull
private static List<String> splitQuery(@NotNull String query) {
List<String> words = new ArrayList<>();