Fix SearchTextField investigation

GitOrigin-RevId: 447d74a6c130e732190ad550b73772b0d02d62ec
This commit is contained in:
elena.korotkova
2020-10-20 16:38:20 +00:00
committed by intellij-monorepo-bot
parent 9eceb8a740
commit 2f45a7afc9
2 changed files with 81 additions and 95 deletions
@@ -1,7 +1,6 @@
// Copyright 2000-2020 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.ui;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
@@ -9,8 +8,9 @@ import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.JBPopupListener;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.components.JBList;
@@ -29,31 +29,6 @@ import java.util.ArrayList;
import java.util.List;
public class SearchTextField extends JPanel {
private class SearchHistoryAction extends AnAction{
private final @NlsSafe String name;
private final boolean enabled;
SearchHistoryAction(@NlsSafe String name, boolean enabled){
this.name = name;
this.enabled = enabled;
getTemplatePresentation().setText(name);
getTemplatePresentation().setEnabled(enabled);
setEnabled(enabled);
}
@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setText(name);
e.getPresentation().setEnabled(enabled);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
myTextField.setText(getTemplatePresentation().getText());
addCurrentTextToHistory();
historyItemChosen(getTemplatePresentation().getText());
}
}
public static final DataKey<SearchTextField> KEY = DataKey.create("search.text.field");
public static final KeyStroke SHOW_HISTORY_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK);
@@ -66,11 +41,10 @@ public class SearchTextField extends JPanel {
private final MyModel myModel;
private final TextFieldWithProcessing myTextField;
@Nullable
private JBPopup myPopup;
private ActionPopupMenu myNativeSearchPopup;
private DefaultActionGroup myHistoryPopupActionGroup = new DefaultActionGroup();
private final SearchHistoryAction noItemsSearchHistoryAction = new SearchHistoryAction(IdeBundle.message("no.recent.searches"), false);
private String myHistoryPropertyName;
private final boolean historyPopupEnabled;
public SearchTextField() {
this(true);
@@ -86,9 +60,9 @@ public class SearchTextField extends JPanel {
public SearchTextField(boolean historyPopupEnabled, @Nullable String historyPropertyName) {
super(new BorderLayout());
this.historyPopupEnabled = historyPopupEnabled;
myModel = new MyModel();
myTextField = new TextFieldWithProcessing() {
@Override
public void processKeyEvent(final KeyEvent e) {
@@ -133,15 +107,7 @@ public class SearchTextField extends JPanel {
setHistoryPropertyName(historyPropertyName);
if (historyPopupEnabled) {
DumbAwareAction.create(event -> {
if (myNativeSearchPopup != null) {
myNativeSearchPopup.getComponent().show(myTextField, 5, myTextField.getHeight());
} else if (myPopup == null || !myPopup.isVisible()) {
showPopup();
}
}).registerCustomShortcutSet(KeymapUtil.getActiveKeymapShortcuts("ShowSearchHistory"), myTextField);
} else if (historyPropertyName != null) {
if (historyPropertyName != null) {
myTextField.getActionMap().put("showPrevHistoryItem", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -166,20 +132,15 @@ public class SearchTextField extends JPanel {
myTextField.getInputMap().put(SHOW_HISTORY_KEYSTROKE, "showNextHistoryItem");
}
myTextField.putClientProperty("JTextField.variant", "search");
myTextField.putClientProperty("JTextField.variant", "searchWithJbPopup");
myTextField.putClientProperty("JTextField.Search.Gap", JBUIScale.scale(6));
myTextField.putClientProperty("JTextField.Search.CancelAction", (ActionListener)e -> {
myTextField.setText("");
onFieldCleared();
});
if (historyPopupEnabled) {
myHistoryPopupActionGroup = new DefaultActionGroup();
myNativeSearchPopup = ActionManager.getInstance()
.createActionPopupMenu(ActionPlaces.UNKNOWN, myHistoryPopupActionGroup);
updateMenu();
myTextField.putClientProperty("JTextField.Search.FindPopup", myNativeSearchPopup.getComponent());
}
DumbAwareAction.create(event -> {
showPopup();
}).registerCustomShortcutSet(KeymapUtil.getActiveKeymapShortcuts("ShowSearchHistory"), myTextField);
}
@Override
@@ -208,22 +169,6 @@ public class SearchTextField extends JPanel {
protected void onFocusGained() {
}
private void updateMenu() {
if (myNativeSearchPopup != null) {
myHistoryPopupActionGroup.removeAll();
final int itemsCount = myModel.getSize();
if (itemsCount == 0) {
myHistoryPopupActionGroup.add(noItemsSearchHistoryAction);
}
else {
for (int i = 0; i < itemsCount; i++) {
final String item = myModel.getElementAt(i);
addMenuItem(item);
}
}
}
}
/**
* @deprecated unused
*/
@@ -289,19 +234,13 @@ public class SearchTextField extends JPanel {
public void addCurrentTextToHistory() {
if (myModel.addElement(getText()) && myHistoryPropertyName != null) {
PropertiesComponent.getInstance().setValue(myHistoryPropertyName, StringUtil.join(getHistory(), "\n"));
reInitPopup();
}
}
protected void historyItemChosen(String item) {
}
private void addMenuItem(@NlsSafe String item) {
if (myNativeSearchPopup != null) {
myHistoryPopupActionGroup.remove(noItemsSearchHistoryAction);
myHistoryPopupActionGroup.add(new SearchHistoryAction(item, true));
}
}
public void selectText() {
getTextEditor().selectAll();
}
@@ -318,7 +257,7 @@ public class SearchTextField extends JPanel {
@Override
public void requestFocus() {
IdeFocusManager.getGlobalInstance()
.doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(getTextEditor(), true));
.doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(getTextEditor(), true));
}
protected void setHistoryPropertyName(String historyPropertyName) {
@@ -410,7 +349,7 @@ public class SearchTextField extends JPanel {
public void fireContentsChanged() {
fireContentsChanged(this, -1, -1);
updateMenu();
reInitPopup();
}
public void setItems(List<String> aList) {
@@ -440,19 +379,32 @@ public class SearchTextField extends JPanel {
protected void showPopup() {
addCurrentTextToHistory();
if (myPopup == null || !myPopup.isVisible()) {
final JList<String> list = new JBList<>(myModel);
final Runnable chooseRunnable = createItemChosenCallback(list);
myPopup = JBPopupFactory.getInstance().createListPopupBuilder(list)
.setMovable(false)
.setRequestFocus(true)
.setItemChoosenCallback(chooseRunnable).createPopup();
if ((myPopup == null || !myPopup.isVisible()) && historyPopupEnabled) {
reInitPopup();
if (isShowing()) {
myPopup.showUnderneathOf(getPopupLocationComponent());
}
}
}
private void reInitPopup() {
final JList<String> list = new JBList<>(myModel);
final Runnable chooseRunnable = createItemChosenCallback(list);
myPopup = JBPopupFactory.getInstance().createListPopupBuilder(list)
.setMovable(false)
.setRequestFocus(true)
.addListener(new JBPopupListener() {
@Override
public void onClosed(@NotNull LightweightWindowEvent event) {
//because jbpopup can be shown only once
reInitPopup();
}
})
.setItemChoosenCallback(chooseRunnable).createPopup();
myTextField.putClientProperty("JTextField.Search.FindPopup", myPopup);
myTextField.putClientProperty("JTextField.variant", "searchWithJbPopup");
}
protected Component getPopupLocationComponent() {
return this;
}
@@ -477,7 +429,7 @@ public class SearchTextField extends JPanel {
}
protected boolean preprocessEventForTextField(KeyEvent e) {
if (SHOW_HISTORY_KEYSTROKE.equals(KeyStroke.getKeyStrokeForEvent(e)) && getClientProperty("JTextField.Search.FindPopup") instanceof JPopupMenu) {
if (SHOW_HISTORY_KEYSTROKE.equals(KeyStroke.getKeyStrokeForEvent(e)) && getClientProperty("JTextField.Search.FindPopup") instanceof JBPopup) {
showPopup();
return true;
}
@@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ComponentUtil;
@@ -221,7 +222,11 @@ public abstract class TextFieldWithPopupHandlerUI extends BasicTextFieldUI imple
}
public static boolean isSearchField(Component c) {
return c instanceof JTextField && "search".equals(((JTextField)c).getClientProperty(VARIANT));
if(!(c instanceof JTextField)){
return false;
}
var variant = ((JTextField)c).getClientProperty(VARIANT);
return "search".equals(variant) || "searchWithJbPopup".equals(variant);
}
public static boolean isSearchFieldWithHistoryPopup(Component c) {
@@ -557,7 +562,15 @@ public abstract class TextFieldWithPopupHandlerUI extends BasicTextFieldUI imple
if (extension instanceof Extension) {
addExtension((Extension)extension);
}
addExtension(new SearchExtension());
addExtension(new SearchExtension(PopupState.forPopupMenu()));
addExtension(new ClearExtension());
}
else if ("searchWithJbPopup".equals(variant)) {
Object extension = getComponent().getClientProperty("search.extension");
if (extension instanceof Extension) {
addExtension((Extension)extension);
}
addExtension(new SearchExtension(PopupState.forPopup()));
addExtension(new ClearExtension());
}
}
@@ -618,9 +631,13 @@ public abstract class TextFieldWithPopupHandlerUI extends BasicTextFieldUI imple
private final class SearchExtension implements Extension {
private final PopupState<JPopupMenu> myPopupState = PopupState.forPopupMenu();
private final PopupState myPopupState;
private Rectangle bounds; // should be bound to IconHandler#bounds
public SearchExtension(PopupState popupState){
this.myPopupState = popupState;
}
@Override
public Icon getIcon(boolean hovered) {
return getSearchIcon(hovered, null != getActionOnClick());
@@ -645,16 +662,33 @@ public abstract class TextFieldWithPopupHandlerUI extends BasicTextFieldUI imple
@Override
public Runnable getActionOnClick() {
JTextComponent component = getComponent();
Object property = component == null ? null : component.getClientProperty(POPUP);
JPopupMenu popup = property instanceof JPopupMenu ? (JPopupMenu)property : null;
return popup == null ? null : () -> {
if (myPopupState.isRecentlyHidden()) return; // do not show new popup
Rectangle editor = getVisibleEditorRect();
if (editor != null) {
myPopupState.prepareToShow(popup);
popup.show(component, bounds.x, editor.y + editor.height);
}
};
if(component == null){
return null;
}
Object property = component.getClientProperty(POPUP);
if(property instanceof JPopupMenu){
JPopupMenu popup = (JPopupMenu) property;
return () -> {
if (myPopupState.isRecentlyHidden()) return; // do not show new popup
Rectangle editor = getVisibleEditorRect();
if (editor != null) {
myPopupState.prepareToShow(popup);
popup.show(component, bounds.x, editor.y + editor.height);
}
};
}
if(property instanceof JBPopup){
JBPopup popup = (JBPopup) property;
return () -> {
if (myPopupState.isRecentlyHidden()) return; // do not show new popup
Rectangle editor = getVisibleEditorRect();
if (editor != null) {
myPopupState.prepareToShow(popup);
popup.showUnderneathOf(component);
}
};
}
return null;
}
@Override