package com.intellij.ide.commander;
+import com.intellij.ide.ui.search.SearchUtil;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.NodeDescriptor;
-import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.util.Pair;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.SpeedSearchBase;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
final class ColoredCommanderRenderer extends ColoredListCellRenderer {
private final CommanderPanel myCommanderPanel;
if(attributes == null) attributes = new SimpleTextAttributes(Font.PLAIN, color);
final String text = value.toString();
- append(text != null? text : "", attributes);
+
+ if (myCommanderPanel.isEnableSearchHighlighting() && SpeedSearchBase.hasActiveSpeedSearch(list)) {
+ final SpeedSearchBase.SpeedSearchComparator comparator = myCommanderPanel.getListSpeedSearch().getComparator();
+ final String recentSearchText = comparator.getRecentSearchText();
+ if (recentSearchText != null && recentSearchText.length() > 0 && comparator.doCompare(recentSearchText, text)) {
+ final Matcher matcher = comparator.getRecentSearchMatcher();
+ final List<Pair<String, Integer>> searchTerms = new ArrayList<Pair<String, Integer>>();
+ for (int i = 0; i < matcher.groupCount(); i++) {
+ final int start = matcher.start(i + 1);
+ if (searchTerms.size() > 0) {
+ final Pair<String, Integer> recent = searchTerms.get(searchTerms.size() - 1);
+ if (start == recent.second + recent.first.length()) {
+ searchTerms.set(searchTerms.size() - 1, Pair.create(recent.first + matcher.group(i+1), recent.second));
+ continue;
+ }
+ }
+
+ searchTerms.add(Pair.create(matcher.group(i+1), start));
+ }
+
+ SearchUtil.appendFragmentsStrict(text, searchTerms, Font.PLAIN, attributes.getFgColor(),
+ selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground(), this);
+ } else {
+ append(text != null ? text : "", attributes);
+ }
+ }
+ else {
+ append(text != null ? text : "", attributes);
+ }
if (locationString != null && locationString.length() > 0) {
append(" (" + locationString + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
private boolean myActive = true;
private final List<CommanderHistoryListener> myHistoryListeners = ContainerUtil.createEmptyCOWList();
private boolean myMoveFocus = false;
+ private boolean myEnableSearchHighlighting;
- public CommanderPanel(final Project project, final boolean enablePopupMenu) {
+ public CommanderPanel(final Project project, final boolean enablePopupMenu, final boolean enableSearchHighlighting) {
super(new BorderLayout());
myProject = project;
+ myEnableSearchHighlighting = enableSearchHighlighting;
myModel = new MyModel();
myList = new JBList(myModel);
myList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
+ public boolean isEnableSearchHighlighting() {
+ return myEnableSearchHighlighting;
+ }
+
+ public ListSpeedSearch getListSpeedSearch() {
+ return myListSpeedSearch;
+ }
+
public void addHistoryListener(CommanderHistoryListener listener) {
myHistoryListeners.add(listener);
}
}
public MyCommanderPanel(Project _project) {
- super(_project, false);
+ super(_project, false, true);
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myListSpeedSearch.addChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
return new SpeedSearchBase.SpeedSearchComparator() {
public void translateCharacter(final StringBuilder buf, final char ch) {
if (ch == '*') {
+ if (buf.length() > 0 && "^*)(".indexOf(buf.charAt(buf.length() - 1)) == -1) buf.append(')');
buf.append(".*"); // overrides '*' handling to skip (,) in parameter lists
}
else {
if (ch == ':') {
+ if (buf.length() > 0 && "^*)(".indexOf(buf.charAt(buf.length() - 1)) == -1) buf.append(')');
buf.append(".*"); // get:int should match any getter returning int
+ buf.append('(');
}
super.translateCharacter(buf, ch);
}
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
+import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
}
private static void processConfigurables(final Configurable[] configurables,
- final HashMap<SearchableConfigurable, TreeSet<OptionDescription>> options) {
+ final HashMap<SearchableConfigurable, TreeSet<OptionDescription>> options) {
for (Configurable configurable : configurables) {
if (configurable instanceof SearchableConfigurable) {
TreeSet<OptionDescription> configurableOptions = new TreeSet<OptionDescription>();
private static String quoteStrictOccurences(final String textToMarkup, final String filter) {
String cur = "";
+ final String s = textToMarkup.toLowerCase();
for (String part : filter.split(" ")) {
- if (textToMarkup.toLowerCase().indexOf(part) != -1) {
+ if (s.indexOf(part) != -1) {
cur += "\"" + part + "\" ";
- } else {
+ }
+ else {
cur += part + " ";
}
}
final String toMark = textToMarkup.substring(idx, idx + option.length());
if (insideHtmlTagPattern.matcher(prefix).matches()) {
result += prefix + toMark;
- } else {
+ }
+ else {
result += prefix + "<font color='#ffffff' bgColor='#1d5da7'>" + toMark + "</font>";
}
beg = idx + option.length();
return result;
}
+ public static void appendFragmentsStrict(@NonNls final String text, @NotNull final List<Pair<String, Integer>> toHighlight,
+ final int style, final Color foreground,
+ final Color background, final SimpleColoredComponent c) {
+ if (text == null) return;
+ final SimpleTextAttributes plainAttributes = new SimpleTextAttributes(style, foreground);
+
+ final int[] lastOffset = {0};
+ ContainerUtil.process(toHighlight, new Processor<Pair<String, Integer>>() {
+ @Override
+ public boolean process(Pair<String, Integer> pair) {
+ if (pair.second > lastOffset[0]) {
+ c.append(text.substring(lastOffset[0], pair.second), new SimpleTextAttributes(style, foreground));
+ }
+
+ c.append(text.substring(pair.second, pair.second + pair.first.length()), new SimpleTextAttributes(background,
+ foreground, null,
+ style |
+ SimpleTextAttributes.STYLE_SEARCH_MATCH));
+ lastOffset[0] = pair.second + pair.first.length();
+ return true;
+ }
+ });
+
+ if (lastOffset[0] < text.length()) {
+ c.append(text.substring(lastOffset[0]), plainAttributes);
+ }
+ }
+
public static void appendFragments(String filter,
@NonNls String text,
final int style,
final Color foreground,
final Color background,
- final ColoredTreeCellRenderer textRenderer) {
+ final SimpleColoredComponent textRenderer) {
if (text == null) return;
if (filter == null || filter.length() == 0) {
textRenderer.append(text, new SimpleTextAttributes(style, foreground));
idx = text.indexOf(word) + word.length();
textRenderer.append(text.substring(idx - word.length(), idx), new SimpleTextAttributes(background,
foreground, null,
- style | SimpleTextAttributes.STYLE_SEARCH_MATCH));
+ style |
+ SimpleTextAttributes.STYLE_SEARCH_MATCH));
}
final String after = text.substring(idx, text.length());
if (after.length() > 0) textRenderer.append(after, new SimpleTextAttributes(background, foreground, null, style));
}
}
- private static void appendSelectedWords(final String text, final List<String> selectedWords, final int pos, int end, final String filter) {
+ private static void appendSelectedWords(final String text,
+ final List<String> selectedWords,
+ final int pos,
+ int end,
+ final String filter) {
if (pos < end) {
final Set<String> filters = SearchableOptionsRegistrar.getInstance().getProcessedWords(filter);
final String[] words = text.substring(pos, end).split("[\\W&&[^_-]]");
if (cancelPopups(activePopup) && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
return;
}
- if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED){
- searchField.process(new KeyEvent(searchField, KeyEvent.KEY_TYPED, e.getWhen(), e.getModifiers(), KeyEvent.VK_UNDEFINED, e.getKeyChar()));
+ if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
+ searchField.process(
+ new KeyEvent(searchField, KeyEvent.KEY_TYPED, e.getWhen(), e.getModifiers(), KeyEvent.VK_UNDEFINED, e.getKeyChar()));
}
}
}
for (int i = 0; i < len; ++i) {
translateCharacter(buf, pattern.charAt(i));
}
+
+ if (buf.length() > 0 && "*^".indexOf(buf.charAt(buf.length() - 1)) == -1) buf.append(')');
+ }
+
+ public String getRecentSearchText() {
+ return myRecentSearchText;
+ }
+
+ public Matcher getRecentSearchMatcher() {
+ return myRecentSearchMatcher;
}
public void translateCharacter(final StringBuilder buf, final char ch) {
// do not bother with other metachars
buf.append('\\');
}
+
if (Character.isUpperCase(ch)) {
+ if (buf.length() > 0 && "*^".indexOf(buf.charAt(buf.length() - 1)) == -1) buf.append(')');
// for camel humps
buf.append("[A-Za-z_]*");
+ buf.append('(');
+ } else {
+ if (buf.length() > 0 && "*^".indexOf(buf.charAt(buf.length() - 1)) != -1) buf.append('(');
}
+
+ if (buf.length() == 0 || buf.length() > 0 && "^".indexOf(buf.charAt(buf.length() - 1)) != -1) buf.append('(');
buf.append(ch);
}
}
}
private CommanderPanel createPanel() {
- final CommanderPanel panel = new CommanderPanel(myProject, true);
+ final CommanderPanel panel = new CommanderPanel(myProject, true, false);
panel.getList().addKeyListener(new KeyAdapter() {
public void keyPressed(final KeyEvent e) {