void (int flyDelay) { mySearchTextField = new PluginSearchTextField() { @Override protected boolean preprocessEventForTextField(KeyEvent event) { int keyCode = event.getKeyCode(); int id = event.getID(); if (keyCode == KeyEvent.VK_ENTER || event.getKeyChar() == '\n') { if (id == KeyEvent.KEY_PRESSED && (mySearchPanel.controller == null || !mySearchPanel.controller.handleEnter(event))) { String text = getText(); if (!text.isEmpty()) { if (mySearchPanel.controller != null) { mySearchPanel.controller.hidePopup(); } showSearchPanel(text); } } return true; } if ((keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_UP) && id == KeyEvent.KEY_PRESSED && mySearchPanel.controller != null && mySearchPanel.controller.handleUpDown(event)) { return true; } 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 @NotNull ActionUpdateThread getActionUpdateThread() { return ActionUpdateThread.EDT; } @Override public void actionPerformed(@NotNull AnActionEvent e) { if (mySearchPanel.controller != null && mySearchPanel.controller.isPopupShow()) { mySearchPanel.controller.hidePopup(); } else { setText(""); } } }.registerCustomShortcutSet(CommonShortcuts.ESCAPE, this); return false; } @Override protected void onFieldCleared() { hideSearchPanel(); } @Override protected void showCompletionPopup() { if (mySearchPanel.controller != null && !mySearchPanel.controller.isPopupShow()) { showSearchPopup(); } } }; mySearchTextField.getTextEditor().getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(@NotNull DocumentEvent e) { if (!mySearchTextField.isSkipDocumentEvents() && !mySearchUpdateAlarm.isDisposed()) { mySearchUpdateAlarm.cancelAllRequests(); mySearchUpdateAlarm.addRequest(this::searchOnTheFly, flyDelay, ModalityState.stateForComponent(mySearchTextField)); } } private void searchOnTheFly() { String text = mySearchTextField.getText(); if (StringUtil.isEmptyOrSpaces(text)) { hideSearchPanel(); } else if (mySearchPanel.controller == null) { showSearchPanel(text); } else { mySearchPanel.controller.handleShowPopup(); } } }); mySearchTextField.setBorder(JBUI.Borders.customLine(PluginManagerConfigurable.SEARCH_FIELD_BORDER_COLOR)); JBTextField editor = mySearchTextField.getTextEditor(); editor.putClientProperty("JTextField.Search.Gap", JBUIScale.scale(6)); editor.putClientProperty("JTextField.Search.GapEmptyText", JBUIScale.scale(-1)); editor.putClientProperty(TextComponentEmptyText.STATUS_VISIBLE_FUNCTION, (Predicate<JBTextField>)field -> field.getText().isEmpty()); editor.setBorder(JBUI.Borders.empty(0, 6)); editor.setOpaque(true); editor.setBackground(PluginManagerConfigurable.SEARCH_BG_COLOR); editor.getAccessibleContext().setAccessibleName(IdeBundle.message("plugin.manager.search.accessible.name")); String text = IdeBundle.message("plugin.manager.options.command"); StatusText emptyText = mySearchTextField.getTextEditor().getEmptyText(); emptyText.appendText(text, new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, ListPluginComponent.GRAY_COLOR)); }