Java tutorial
/* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.find; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.find.editorHeaderActions.*; import com.intellij.find.impl.livePreview.LivePreviewController; import com.intellij.find.impl.livePreview.SearchResults; import com.intellij.icons.AllIcons; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.CustomComponentAction; import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.event.SelectionEvent; import com.intellij.openapi.editor.event.SelectionListener; import com.intellij.openapi.editor.impl.EditorHeaderComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.JBSplitter; import com.intellij.ui.LightColors; import com.intellij.ui.SearchTextField; import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.speedSearch.SpeedSearchSupply; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentListener; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; import java.util.Arrays; import java.util.regex.Pattern; /** * @author max, andrey.zaytsev */ public class EditorSearchComponent extends EditorHeaderComponent implements DataProvider, SelectionListener, SearchResults.SearchResultsListener { private JLabel myMatchInfoLabel; private LinkLabel myClickToHighlightLabel; private final Project myProject; private ActionToolbar myActionsToolbar; @NotNull public Editor getEditor() { return myEditor; } @NotNull private final Editor myEditor; public JTextComponent getSearchField() { return mySearchField; } private final JBSplitter mySplitPane = new JBSplitter(false); private final JPanel myLeftComponent = new JPanel(new BorderLayout()); private final JPanel myRightComponent = new JPanel(new BorderLayout()); { mySplitPane.setBorder(IdeBorderFactory.createEmptyBorder(1, 0, 2, 0)); mySplitPane.setHonorComponentsMinimumSize(true); mySplitPane.setProportion(0.25f); mySplitPane.setAndLoadSplitterProportionKey("FindSplitterProportion"); mySplitPane.setOpaque(false); mySplitPane.getDivider().setOpaque(false); myLeftComponent.setOpaque(false); myRightComponent.setOpaque(false); mySplitPane.setFirstComponent(myLeftComponent); mySplitPane.setSecondComponent(myRightComponent); add(mySplitPane, BorderLayout.NORTH); } private JTextComponent mySearchField; private JComponent mySearchRootComponent; public JTextComponent getReplaceField() { return myReplaceField; } private JTextComponent myReplaceField; private JComponent myReplaceRootComponent; private final Getter<JTextComponent> mySearchFieldGetter = new Getter<JTextComponent>() { @Override public JTextComponent get() { return mySearchField; } }; private final Getter<JTextComponent> myReplaceFieldGetter = new Getter<JTextComponent>() { @Override public JTextComponent get() { return myReplaceField; } }; private final Color myDefaultBackground; private JButton myReplaceButton; private JButton myReplaceAllButton; private JButton myExcludeButton; public static final Color COMPLETION_BACKGROUND_COLOR = new Color(235, 244, 254); private static final Color FOCUS_CATCHER_COLOR = new Color(0x9999ff); private JComponent myToolbarComponent; private final LivePreviewController myLivePreviewController; private final SearchResults mySearchResults; private final FindModel myFindModel; private JPanel myReplacementPane; public JComponent getToolbarComponent() { return myToolbarComponent; } private void updateReplaceButton() { if (myReplaceButton != null) { myReplaceButton.setEnabled(canReplaceCurrent()); } } public void restoreFindModel() { final FindModel model = FindManager.getInstance(myProject).getPreviousFindModel(); if (model != null) { myFindModel.copyFrom(model); updateUIWithFindModel(); } } private static FindModel createDefaultFindModel(Project p, Editor e) { FindModel findModel = new FindModel(); findModel.copyFrom(FindManager.getInstance(p).getFindInFileModel()); if (e.getSelectionModel().hasSelection()) { String selectedText = e.getSelectionModel().getSelectedText(); if (selectedText != null) { findModel.setStringToFind(selectedText); } } findModel.setPromptOnReplace(false); return findModel; } public EditorSearchComponent(@NotNull Editor editor, Project project) { this(editor, project, createDefaultFindModel(project, editor)); } @Override @Nullable public Object getData(@NonNls final String dataId) { if (SpeedSearchSupply.SPEED_SEARCH_CURRENT_QUERY.is(dataId)) { return mySearchField.getText(); } if (CommonDataKeys.EDITOR_EVEN_IF_INACTIVE.is(dataId)) { return myEditor; } return null; } @Override public void searchResultsUpdated(SearchResults sr) { if (mySearchField.getText().isEmpty()) { updateUIWithEmptyResults(); } else { int count = sr.getMatchesCount(); if (count <= mySearchResults.getMatchesLimit()) { myClickToHighlightLabel.setVisible(false); if (count > 0) { setRegularBackground(); if (count > 1) { myMatchInfoLabel.setText(count + " matches"); } else { myMatchInfoLabel.setText("1 match"); } } else { setNotFoundBackground(); myMatchInfoLabel.setText("No matches "); boldMatchInfo(); } } else { setRegularBackground(); myMatchInfoLabel.setText("More than " + mySearchResults.getMatchesLimit() + " matches"); myClickToHighlightLabel.setVisible(true); boldMatchInfo(); } } updateExcludeStatus(); } @Override public void cursorMoved() { updateExcludeStatus(); } @Override public void updateFinished() { } public EditorSearchComponent(@NotNull final Editor editor, final Project project, FindModel findModel) { myFindModel = findModel; myProject = project; myEditor = editor; mySearchResults = new SearchResults(myEditor, myProject); myLivePreviewController = new LivePreviewController(mySearchResults, this); myDefaultBackground = new JTextField().getBackground(); configureLeadPanel(); new SwitchToFind(this); new SwitchToReplace(this); myFindModel.addObserver(new FindModel.FindModelObserver() { @Override public void findModelChanged(FindModel findModel) { String stringToFind = myFindModel.getStringToFind(); if (!wholeWordsApplicable(stringToFind)) { myFindModel.setWholeWordsOnly(false); } updateUIWithFindModel(); updateResults(true); syncFindModels(FindManager.getInstance(myProject).getFindInFileModel(), myFindModel); } }); updateUIWithFindModel(); if (ApplicationManager.getApplication().isUnitTestMode()) { initLivePreview(); } } private void configureLeadPanel() { JPanel myLeadPanel = createLeadPane(); myRightComponent.add(myLeadPanel, BorderLayout.WEST); Ref<JComponent> ref = Ref.create(); mySearchField = createTextField(BorderLayout.NORTH, ref); mySearchRootComponent = ref.get(); SearchTextField searchTextField = (ref.get() instanceof SearchTextField) ? (SearchTextField) ref.get() : null; if (searchTextField != null) { setupHistoryToSearchField(searchTextField, FindSettings.getInstance().getRecentFindStrings()); } UIUtil.addUndoRedoActions(mySearchField); setupSearchFieldListener(); if (myActionsToolbar == null) { initToolbar(); } JPanel centerPanel = new JPanel(new BorderLayout()); centerPanel.setOpaque(false); centerPanel.add(myToolbarComponent, BorderLayout.CENTER); myRightComponent.add(centerPanel, BorderLayout.CENTER); if (myToolbarComponent instanceof ActionToolbarImpl) { new ShowMoreOptions(myToolbarComponent, mySearchField); } JPanel tailPanel = new NonOpaquePanel(new BorderLayout(5, 0)); JPanel tailContainer = new NonOpaquePanel(new BorderLayout(5, 0)); tailContainer.add(tailPanel, BorderLayout.EAST); centerPanel.add(tailContainer, BorderLayout.EAST); JLabel closeLabel = new JLabel(" ", AllIcons.Actions.Cross, SwingConstants.RIGHT); closeLabel.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { close(); } }); closeLabel.setToolTipText("Close search bar (Escape)"); tailPanel.add(closeLabel, BorderLayout.EAST); Utils.setSmallerFont(mySearchField); mySearchField.registerKeyboardAction(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (StringUtil.isEmpty(mySearchField.getText())) { close(); } else { requestFocus(myEditor.getContentComponent()); addTextToRecent(EditorSearchComponent.this.mySearchField); } } }, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, SystemInfo.isMac ? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK), JComponent.WHEN_FOCUSED); final String initialText = myFindModel.getStringToFind(); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { setInitialText(initialText); } }); new RestorePreviousSettingsAction(this, mySearchField); new VariantsCompletionAction(this, mySearchFieldGetter); // It registers a shortcut set automatically on construction Utils.setSmallerFontForChildren(myToolbarComponent); } private void setupHistoryToSearchField(SearchTextField field, String[] strings) { field.setHistorySize(20); field.setHistory(ContainerUtil.reverse(Arrays.asList(strings))); } private void initToolbar() { DefaultActionGroup actionGroup = new DefaultActionGroup("search bar", false); actionGroup.add(new ShowHistoryAction(mySearchFieldGetter, this)); actionGroup.add(new PrevOccurrenceAction(this, mySearchFieldGetter)); actionGroup.add(new NextOccurrenceAction(this, mySearchFieldGetter)); actionGroup.add(new AddOccurrenceAction(this)); actionGroup.add(new RemoveOccurrenceAction(this)); actionGroup.add(new SelectAllAction(this)); actionGroup.add(new FindAllAction(this)); actionGroup.add(new ToggleMultiline(this)); actionGroup.add(new ToggleMatchCase(this)); actionGroup.add(new ToggleRegex(this)); myMatchInfoLabel = new JLabel(); myClickToHighlightLabel = new LinkLabel("Click to highlight", null, new LinkListener() { @Override public void linkSelected(LinkLabel aSource, Object aLinkData) { setMatchesLimit(Integer.MAX_VALUE); updateResults(true); } }); myClickToHighlightLabel.setVisible(false); myActionsToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.EDITOR_TOOLBAR, actionGroup, true); myActionsToolbar.setSecondaryActionsTooltip("More Options(" + ShowMoreOptions.SHORT_CUT + ")"); actionGroup.addAction(new ToggleWholeWordsOnlyAction(this)); actionGroup.addAction(new ToggleInCommentsAction(this)).setAsSecondary(true); actionGroup.addAction(new ToggleInLiteralsOnlyAction(this)).setAsSecondary(true); actionGroup.addAction(new ToggleExceptCommentsAction(this)).setAsSecondary(true); actionGroup.addAction(new ToggleExceptLiteralsAction(this)).setAsSecondary(true); actionGroup.addAction(new ToggleExceptCommentsAndLiteralsAction(this)).setAsSecondary(true); actionGroup.addAction(new TogglePreserveCaseAction(this)); actionGroup.addAction(new ToggleSelectionOnlyAction(this)); class MyCustomComponentDoNothingAction extends AnAction implements CustomComponentAction { private final JComponent c; MyCustomComponentDoNothingAction(JComponent c) { this.c = c; c.setBorder(IdeBorderFactory.createEmptyBorder(new Insets(0, 10, 0, 0))); } @Override public void actionPerformed(AnActionEvent e) { } @Override public JComponent createCustomComponent(Presentation presentation) { return c; } } actionGroup.add(new MyCustomComponentDoNothingAction(myMatchInfoLabel)); actionGroup.add(new MyCustomComponentDoNothingAction(myClickToHighlightLabel)); myActionsToolbar.setLayoutPolicy(ActionToolbar.AUTO_LAYOUT_POLICY); myToolbarComponent = myActionsToolbar.getComponent(); myToolbarComponent.setBorder(null); myToolbarComponent.setOpaque(false); } public void selectAllText() { mySearchField.selectAll(); } private void setupSearchFieldListener() { mySearchField.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(javax.swing.event.DocumentEvent documentEvent) { searchFieldDocumentChanged(); } @Override public void removeUpdate(javax.swing.event.DocumentEvent documentEvent) { searchFieldDocumentChanged(); } @Override public void changedUpdate(javax.swing.event.DocumentEvent documentEvent) { searchFieldDocumentChanged(); } }); } private void searchFieldDocumentChanged() { setMatchesLimit(LivePreviewController.MATCHES_LIMIT); String text = mySearchField.getText(); myFindModel.setStringToFind(text); if (!StringUtil.isEmpty(text)) { updateResults(true); } else { nothingToSearchFor(); } } public boolean isRegexp() { return myFindModel.isRegularExpressions(); } public void setRegexp(boolean val) { myFindModel.setRegularExpressions(val); } public FindModel getFindModel() { return myFindModel; } private static void syncFindModels(FindModel to, FindModel from) { to.setCaseSensitive(from.isCaseSensitive()); to.setWholeWordsOnly(from.isWholeWordsOnly()); to.setRegularExpressions(from.isRegularExpressions()); to.setSearchContext(from.getSearchContext()); if (from.isReplaceState()) { to.setPreserveCase(from.isPreserveCase()); } } private void updateUIWithFindModel() { boolean needToResetFocus = false; myActionsToolbar.updateActionsImmediately(); if ((myFindModel.isMultiline() && mySearchField instanceof JTextField) || (!myFindModel.isMultiline() && mySearchField instanceof JTextArea)) { needToResetFocus = mySearchField.hasFocus(); myLeftComponent.removeAll(); myRightComponent.removeAll(); myReplaceRootComponent = null; mySearchRootComponent = null; configureLeadPanel(); if (myReplacementPane != null) { myReplacementPane = null; } } String stringToFind = myFindModel.getStringToFind(); if (!StringUtil.equals(stringToFind, mySearchField.getText())) { mySearchField.setText(stringToFind); } myLivePreviewController.setTrackingSelection(!myFindModel.isGlobal()); if (myFindModel.isReplaceState() && myReplacementPane == null) { configureReplacementPane(); } else if (!myFindModel.isReplaceState() && myReplacementPane != null) { if (myReplaceRootComponent != null) { myLeftComponent.remove(myReplaceRootComponent); myReplaceRootComponent = null; myReplaceField = null; } myRightComponent.remove(myReplacementPane); myReplacementPane = null; } if (myFindModel.isReplaceState()) { String stringToReplace = myFindModel.getStringToReplace(); if (!StringUtil.equals(stringToReplace, myReplaceField.getText())) { myReplaceField.setText(stringToReplace); } updateExcludeStatus(); } updateReplaceButton(); Utils.setSmallerFontForChildren(myToolbarComponent); revalidate(); if (needToResetFocus) mySearchField.requestFocusInWindow(); } private static boolean wholeWordsApplicable(String stringToFind) { return !stringToFind.startsWith(" ") && !stringToFind.startsWith("\t") && !stringToFind.endsWith(" ") && !stringToFind.endsWith("\t"); } private void setMatchesLimit(int value) { mySearchResults.setMatchesLimit(value); } private void configureReplacementPane() { myReplacementPane = new NonOpaquePanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); Ref<JComponent> ref = Ref.create(); myReplaceField = createTextField(BorderLayout.SOUTH, ref); myReplaceRootComponent = ref.get(); SearchTextField searchTextField = ref.get() instanceof SearchTextField ? (SearchTextField) ref.get() : null; if (searchTextField != null) { setupHistoryToSearchField(searchTextField, FindSettings.getInstance().getRecentReplaceStrings()); } UIUtil.addUndoRedoActions(myReplaceField); revalidate(); DocumentListener replaceFieldListener = new DocumentListener() { @Override public void insertUpdate(javax.swing.event.DocumentEvent documentEvent) { replaceFieldDocumentChanged(); } @Override public void removeUpdate(javax.swing.event.DocumentEvent documentEvent) { replaceFieldDocumentChanged(); } @Override public void changedUpdate(javax.swing.event.DocumentEvent documentEvent) { replaceFieldDocumentChanged(); } }; myReplaceField.getDocument().addDocumentListener(replaceFieldListener); if (!getFindModel().isMultiline()) { new ReplaceOnEnterAction(this, myReplaceField); } myReplaceField.setText(myFindModel.getStringToReplace()); myRightComponent.add(myReplacementPane, BorderLayout.SOUTH); myReplaceButton = new JButton("Replace"); myReplaceButton.setFocusable(false); myReplaceButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { replaceCurrent(); } }); myReplaceAllButton = new JButton("Replace all"); myReplaceAllButton.setFocusable(false); myReplaceAllButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { myLivePreviewController.performReplaceAll(); } }); myExcludeButton = new JButton(""); myExcludeButton.setFocusable(false); myExcludeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { myLivePreviewController.exclude(); moveCursor(SearchResults.Direction.DOWN); } }); if (!UISettings.getInstance().DISABLE_MNEMONICS_IN_CONTROLS) { myReplaceButton.setMnemonic('p'); myReplaceAllButton.setMnemonic('a'); myExcludeButton.setMnemonic('l'); } ActionGroup actionsGroup = new DefaultActionGroup(new ShowHistoryAction(myReplaceFieldGetter, this)); final ActionToolbar tb = ActionManager.getInstance().createActionToolbar("ReplaceBar", actionsGroup, true); tb.setLayoutPolicy(ActionToolbar.AUTO_LAYOUT_POLICY); final JComponent tbComponent = tb.getComponent(); tbComponent.setOpaque(false); tbComponent.setBorder(null); myReplacementPane.add(tbComponent); myReplacementPane.add(myReplaceButton); myReplacementPane.add(myReplaceAllButton); myReplacementPane.add(myExcludeButton); setSmallerFontAndOpaque(myReplaceButton); setSmallerFontAndOpaque(myReplaceAllButton); setSmallerFontAndOpaque(myExcludeButton); Utils.setSmallerFont(myReplaceField); new VariantsCompletionAction(this, myReplaceFieldGetter); new NextOccurrenceAction(this, myReplaceFieldGetter); new PrevOccurrenceAction(this, myReplaceFieldGetter); } private void replaceFieldDocumentChanged() { setMatchesLimit(LivePreviewController.MATCHES_LIMIT); myFindModel.setStringToReplace(myReplaceField.getText()); } private boolean canReplaceCurrent() { return myLivePreviewController != null && myLivePreviewController.canReplace(); } public void replaceCurrent() { if (mySearchResults.getCursor() != null) { myLivePreviewController.performReplace(); } } private void updateExcludeStatus() { if (myExcludeButton != null && mySearchResults != null) { FindResult cursor = mySearchResults.getCursor(); myExcludeButton.setText(cursor == null || !mySearchResults.isExcluded(cursor) ? "Exclude" : "Include"); myReplaceAllButton.setEnabled(mySearchResults.hasMatches()); myExcludeButton.setEnabled(cursor != null); updateReplaceButton(); } } private static JPanel createLeadPane() { return new NonOpaquePanel(new BorderLayout()); } public void showHistory(final boolean byClickingToolbarButton, JTextComponent textField) { FeatureUsageTracker.getInstance().triggerFeatureUsed("find.recent.search"); FindSettings settings = FindSettings.getInstance(); String[] recent = textField == mySearchField ? settings.getRecentFindStrings() : settings.getRecentReplaceStrings(); final boolean toShowAd = textField == mySearchField && textField.getText().isEmpty() && FindManager.getInstance(myProject).getPreviousFindModel() != null; Utils.showCompletionPopup(byClickingToolbarButton ? myToolbarComponent : null, new JBList((Object[]) ArrayUtil.reverseArray(recent)), "Recent " + (textField == mySearchField ? "Searches" : "Replaces"), textField, toShowAd ? RestorePreviousSettingsAction.getAd() : null); } private String gerRestoreFindModelAd() { return "Use " + KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0) + " to restore your last search/replace settings"; } private void paintBorderOfTextField(Graphics g) { if (!(UIUtil.isUnderAquaLookAndFeel() || UIUtil.isUnderGTKLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel()) && isFocusOwner()) { final Rectangle bounds = getBounds(); g.setColor(FOCUS_CATCHER_COLOR); g.drawRect(0, 0, bounds.width - 1, bounds.height - 1); } } private JTextComponent createTextField(Object constraint, Ref<JComponent> componentRef) { final JTextComponent editorTextField; if (myFindModel.isMultiline()) { editorTextField = new JTextArea("") { @Override protected void paintBorder(final Graphics g) { super.paintBorder(g); paintBorderOfTextField(g); } }; ((JTextArea) editorTextField).setColumns(25); ((JTextArea) editorTextField).setRows(3); final JScrollPane scrollPane = new JBScrollPane(editorTextField, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); myLeftComponent.add(scrollPane, constraint); componentRef.set(scrollPane); } else { SearchTextField stf = new SearchTextField(true); stf.setOpaque(false); editorTextField = stf.getTextEditor(); if (UIUtil.isUnderGTKLookAndFeel()) { editorTextField.setOpaque(false); } myLeftComponent.add(stf, constraint); componentRef.set(stf); } editorTextField.setMinimumSize(new Dimension(200, -1)); editorTextField.putClientProperty("AuxEditorComponent", Boolean.TRUE); editorTextField.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) { editorTextField.repaint(); } @Override public void focusLost(final FocusEvent e) { editorTextField.repaint(); } }); new CloseOnESCAction(this, editorTextField); return editorTextField; } public void setInitialText(final String initialText) { final String text = initialText != null ? initialText : ""; if (text.contains("\n")) { myFindModel.setMultiline(true); } setTextInField(text); mySearchField.selectAll(); } private void requestFocus(Component c) { IdeFocusManager.getInstance(myProject).requestFocus(c, true); } public void searchBackward() { moveCursor(SearchResults.Direction.UP); addTextToRecent(mySearchField); } public void searchForward() { moveCursor(SearchResults.Direction.DOWN); addTextToRecent(mySearchField); } public void addTextToRecent(JTextComponent textField) { final String text = textField.getText(); if (text.length() > 0) { if (textField == mySearchField) { FindSettings.getInstance().addStringToFind(text); if (mySearchRootComponent instanceof SearchTextField) { ((SearchTextField) mySearchRootComponent).addCurrentTextToHistory(); } } else { FindSettings.getInstance().addStringToReplace(text); if (myReplaceRootComponent instanceof SearchTextField) { ((SearchTextField) myReplaceRootComponent).addCurrentTextToHistory(); } } } } @Override public void selectionChanged(SelectionEvent e) { updateResults(false); } private void moveCursor(SearchResults.Direction direction) { myLivePreviewController.moveCursor(direction); } private static void setSmallerFontAndOpaque(final JComponent component) { Utils.setSmallerFont(component); component.setOpaque(false); } @Override public void requestFocus() { mySearchField.setSelectionStart(0); mySearchField.setSelectionEnd(mySearchField.getText().length()); requestFocus(mySearchField); } public void close() { IdeFocusManager.getInstance(myProject).requestFocus(myEditor.getContentComponent(), false); myLivePreviewController.dispose(); myEditor.setHeaderComponent(null); } @Override public void addNotify() { super.addNotify(); initLivePreview(); } private void initLivePreview() { myLivePreviewController.on(); myLivePreviewController.setUserActivityDelay(0); updateResults(false); myLivePreviewController.setUserActivityDelay(LivePreviewController.USER_ACTIVITY_TRIGGERING_DELAY); mySearchResults.addListener(this); } @Override public void removeNotify() { super.removeNotify(); myLivePreviewController.off(); mySearchResults.removeListener(this); addTextToRecent(mySearchField); if (myReplaceField != null) { addTextToRecent(myReplaceField); } } private void updateResults(final boolean allowedToChangedEditorSelection) { myMatchInfoLabel.setFont(myMatchInfoLabel.getFont().deriveFont(Font.PLAIN)); final String text = myFindModel.getStringToFind(); if (text.length() == 0) { nothingToSearchFor(); } else { if (myFindModel.isRegularExpressions()) { try { Pattern.compile(text); } catch (Exception e) { setNotFoundBackground(); myMatchInfoLabel.setText("Incorrect regular expression"); boldMatchInfo(); myClickToHighlightLabel.setVisible(false); mySearchResults.clear(); return; } } final FindManager findManager = FindManager.getInstance(myProject); if (allowedToChangedEditorSelection) { findManager.setFindWasPerformed(); FindModel copy = new FindModel(); copy.copyFrom(myFindModel); copy.setReplaceState(false); findManager.setFindNextModel(copy); } if (myLivePreviewController != null) { myLivePreviewController.updateInBackground(myFindModel, allowedToChangedEditorSelection); } } } private void nothingToSearchFor() { updateUIWithEmptyResults(); if (mySearchResults != null) { mySearchResults.clear(); } } private void updateUIWithEmptyResults() { setRegularBackground(); myMatchInfoLabel.setText(""); myClickToHighlightLabel.setVisible(false); } private void boldMatchInfo() { Font font = myMatchInfoLabel.getFont(); if (!font.isBold()) { myMatchInfoLabel.setFont(font.deriveFont(Font.BOLD)); } } private void setRegularBackground() { mySearchField.setBackground(myDefaultBackground); } private void setNotFoundBackground() { mySearchField.setBackground(LightColors.RED); } public String getTextInField() { return mySearchField.getText(); } public void setTextInField(final String text) { mySearchField.setText(text); myFindModel.setStringToFind(text); } public boolean hasMatches() { return mySearchResults != null && mySearchResults.hasMatches(); } @Override public Insets getInsets() { Insets insets = super.getInsets(); if (UIUtil.isUnderGTKLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel()) { insets.top += 1; insets.bottom += 2; } return insets; } public void selectAllOccurrences() { FindUtil.selectSearchResultsInEditor(myEditor, mySearchResults.getOccurrences().iterator(), -1); } public void removeOccurrence() { mySearchResults.prevOccurrence(true); } public void addNextOccurrence() { mySearchResults.nextOccurrence(true); } public void clearUndoInTextFields() { UIUtil.resetUndoRedoActions(mySearchField); UIUtil.resetUndoRedoActions(myReplaceField); } }