@Nullable public static VirtualFile getDirectory(@NotNull final FindModel findModel) { String directoryName = findModel.getDirectoryName(); if (findModel.isProjectScope() || StringUtil.isEmpty(directoryName)) { return null; } String path = directoryName.replace(File.separatorChar, '/'); VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path); if (virtualFile == null || !virtualFile.isDirectory()) { virtualFile = null; for (LocalFileProvider provider : ((VirtualFileManagerEx) VirtualFileManager.getInstance()).getLocalFileProviders()) { VirtualFile file = provider.findLocalVirtualFileByPath(path); if (file != null && file.isDirectory()) { if (file.getChildren().length > 0) { virtualFile = file; break; } if (virtualFile == null) { virtualFile = file; } } } } return virtualFile; }
private void updateResults(final boolean allowedToChangedEditorSelection) { final String text = myFindModel.getStringToFind(); if (text.length() == 0) { nothingToSearchFor(); } else { if (myFindModel.isRegularExpressions()) { try { Pattern.compile(text); } catch (Exception e) { setNotFoundBackground(); myClickToHighlightLabel.setVisible(false); mySearchResults.clear(); myMatchInfoLabel.setText("Incorrect regular expression"); 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 updateUIWithFindModel() { boolean needToResetSearchFocus = mySearchTextComponent.hasFocus(); boolean needToResetReplaceFocus = myReplaceTextComponent.hasFocus(); updateSearchComponent(); updateReplaceComponent(); if (myFindModel.isReplaceState()) { if (myReplaceFieldWrapper.getParent() == null) { myLeftPanel.add(myReplaceFieldWrapper, BorderLayout.CENTER); } if (myReplaceToolbarWrapper.getParent() == null) { myRightPanel.add(myReplaceToolbarWrapper, BorderLayout.CENTER); } if (needToResetReplaceFocus) { myReplaceTextComponent.requestFocusInWindow(); } } else { if (myReplaceFieldWrapper.getParent() != null) { myLeftPanel.remove(myReplaceFieldWrapper); } if (myReplaceToolbarWrapper.getParent() != null) { myRightPanel.remove(myReplaceToolbarWrapper); } } if (needToResetSearchFocus) mySearchTextComponent.requestFocusInWindow(); mySearchActionsToolbar1.updateActionsImmediately(); mySearchActionsToolbar2.updateActionsImmediately(); myReplaceActionsToolbar1.updateActionsImmediately(); myReplaceActionsToolbar2.updateActionsImmediately(); myReplaceToolbarWrapper.revalidate(); revalidate(); repaint(); myLivePreviewController.setTrackingSelection(!myFindModel.isGlobal()); }
private static FindModel createDefaultFindModel(Project project, Editor editor) { FindModel findModel = new FindModel(); findModel.copyFrom(FindManager.getInstance(project).getFindInFileModel()); if (editor.getSelectionModel().hasSelection()) { String selectedText = editor.getSelectionModel().getSelectedText(); if (selectedText != null) { findModel.setStringToFind(selectedText); } } findModel.setPromptOnReplace(false); return findModel; }
private void replaceFieldDocumentChanged() { setMatchesLimit(LivePreviewController.MATCHES_LIMIT); myFindModel.setStringToReplace(myReplaceTextComponent.getText()); if (myReplaceTextComponent instanceof JTextArea) { adjustRows((JTextArea) myReplaceTextComponent); } updateMultiLineStateIfNeed(); }
public void replaceInProject(@NotNull DataContext dataContext) { final FindManager findManager = FindManager.getInstance(myProject); final FindModel findModel = (FindModel) findManager.getFindInProjectModel().clone(); findModel.setReplaceState(true); FindInProjectUtil.setDirectoryName(findModel, dataContext); Editor editor = CommonDataKeys.EDITOR.getData(dataContext); FindUtil.initStringToFindWithSelection(findModel, editor); findManager.showFindDialog( findModel, new Runnable() { @Override public void run() { final PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject); if (!findModel.isProjectScope() && psiDirectory == null && findModel.getModuleName() == null && findModel.getCustomScope() == null) { return; } UsageViewManager manager = UsageViewManager.getInstance(myProject); if (manager == null) return; findManager.getFindInProjectModel().copyFrom(findModel); final FindModel findModelCopy = (FindModel) findModel.clone(); final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(true, findModelCopy); final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, true, presentation); UsageSearcherFactory factory = new UsageSearcherFactory(findModelCopy, psiDirectory, processPresentation); searchAndShowUsages( manager, factory, findModelCopy, presentation, processPresentation, findManager); } }); }
private void updateReplaceComponent() { final int oldCaretPosition = myReplaceTextComponent != null ? myReplaceTextComponent.getCaretPosition() : 0; String oldText = myReplaceTextComponent != null ? myReplaceTextComponent.getText() : myFindModel.getStringToReplace(); if (!updateTextComponent(false)) { return; } if (oldText != null) { myReplaceTextComponent.setText(oldText); } myReplaceTextComponent .getDocument() .addDocumentListener( new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { replaceFieldDocumentChanged(); } }); } }); if (!getFindModel().isMultiline()) { new ReplaceOnEnterAction(this, myReplaceTextComponent); } // myReplaceTextComponent.setText(myFindModel.getStringToReplace()); ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { myReplaceTextComponent.setCaretPosition(oldCaretPosition); } }); new VariantsCompletionAction(myReplaceTextComponent); new NextOccurrenceAction(this, myReplaceFieldWrapper); new PrevOccurrenceAction(this, myReplaceFieldWrapper); myReplaceFieldWrapper.revalidate(); myReplaceFieldWrapper.repaint(); }
private void searchFieldDocumentChanged() { setMatchesLimit(LivePreviewController.MATCHES_LIMIT); String text = mySearchTextComponent.getText(); myFindModel.setStringToFind(text); if (!StringUtil.isEmpty(text)) { updateResults(true); } else { nothingToSearchFor(); } if (mySearchTextComponent instanceof JTextArea) { adjustRows((JTextArea) mySearchTextComponent); } updateMultiLineStateIfNeed(); }
@NotNull public static UsageViewPresentation setupViewPresentation( final boolean toOpenInNewTab, @NotNull FindModel findModel) { final UsageViewPresentation presentation = new UsageViewPresentation(); final String scope = getTitleForScope(findModel); final String stringToFind = findModel.getStringToFind(); presentation.setScopeText(scope); if (stringToFind.isEmpty()) { presentation.setTabText("Files"); presentation.setToolwindowTitle(BundleBase.format("Files in {0}", scope)); presentation.setUsagesString("files"); } else { FindModel.SearchContext searchContext = findModel.getSearchContext(); String contextText = ""; if (searchContext != FindModel.SearchContext.ANY) { contextText = FindBundle.message( "find.context.presentation.scope.label", FindDialog.getPresentableName(searchContext)); } presentation.setTabText( FindBundle.message("find.usage.view.tab.text", stringToFind, contextText)); presentation.setToolwindowTitle( FindBundle.message("find.usage.view.toolwindow.title", stringToFind, scope, contextText)); presentation.setUsagesString(FindBundle.message("find.usage.view.usages.text", stringToFind)); presentation.setUsagesWord(FindBundle.message("occurrence")); presentation.setCodeUsagesString(FindBundle.message("found.occurrences")); presentation.setContextText(contextText); } presentation.setOpenInNewTab(toOpenInNewTab); presentation.setCodeUsages(false); presentation.setUsageTypeFilteringAvailable(true); return presentation; }
private static int addToUsages( @NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel, @NotNull final PsiFile psiFile, @NotNull int[] offsetRef, int maxUsages) { int count = 0; CharSequence text = document.getCharsSequence(); int textLength = document.getTextLength(); int offset = offsetRef[0]; Project project = psiFile.getProject(); FindManager findManager = FindManager.getInstance(project); while (offset < textLength) { FindResult result = findManager.findString(text, offset, findModel, psiFile.getVirtualFile()); if (!result.isStringFound()) break; final SearchScope customScope = findModel.getCustomScope(); if (customScope instanceof LocalSearchScope) { final TextRange range = new TextRange(result.getStartOffset(), result.getEndOffset()); if (!((LocalSearchScope) customScope).containsRange(psiFile, range)) break; } UsageInfo info = new FindResultUsageInfo(findManager, psiFile, offset, findModel, result); if (!consumer.process(info)) { throw new ProcessCanceledException(); } count++; final int prevOffset = offset; offset = result.getEndOffset(); if (prevOffset == offset) { // for regular expr the size of the match could be zero -> could be infinite loop in finding // usages! ++offset; } if (maxUsages > 0 && count >= maxUsages) { break; } } offsetRef[0] = offset; return count; }
public static void setDirectoryName(@NotNull FindModel model, @NotNull DataContext dataContext) { PsiElement psiElement = null; Project project = CommonDataKeys.PROJECT.getData(dataContext); if (project != null && !DumbServiceImpl.getInstance(project).isDumb()) { try { psiElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext); } catch (IndexNotReadyException ignore) { } } String directoryName = null; if (psiElement instanceof PsiDirectory) { directoryName = ((PsiDirectory) psiElement).getVirtualFile().getPresentableUrl(); } if (directoryName == null && psiElement instanceof PsiDirectoryContainer) { final PsiDirectory[] directories = ((PsiDirectoryContainer) psiElement).getDirectories(); directoryName = directories.length == 1 ? directories[0].getVirtualFile().getPresentableUrl() : null; } Module module = LangDataKeys.MODULE_CONTEXT.getData(dataContext); if (module != null) { model.setModuleName(module.getName()); } Editor editor = CommonDataKeys.EDITOR.getData(dataContext); if (model.getModuleName() == null || editor == null) { model.setDirectoryName(directoryName); model.setProjectScope( directoryName == null && module == null && !model.isCustomScope() || editor != null); if (directoryName != null) { model.setCustomScope(false); // to select "Directory: " radio button } // for convenience set directory name to directory of current file, note that we doesn't // change default projectScope if (directoryName == null) { VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext); if (virtualFile != null && !virtualFile.isDirectory()) virtualFile = virtualFile.getParent(); if (virtualFile != null) model.setDirectoryName(virtualFile.getPresentableUrl()); } } }
// returns number of hits static int processUsagesInFile( @NotNull final PsiFile psiFile, @NotNull final FindModel findModel, @NotNull final Processor<UsageInfo> consumer) { if (findModel.getStringToFind().isEmpty()) { if (!ApplicationManager.getApplication() .runReadAction((Computable<Boolean>) () -> consumer.process(new UsageInfo(psiFile)))) { throw new ProcessCanceledException(); } return 1; } final VirtualFile virtualFile = psiFile.getVirtualFile(); if (virtualFile == null) return 0; if (virtualFile.getFileType().isBinary()) return 0; // do not decompile .class files final Document document = ApplicationManager.getApplication() .runReadAction( (Computable<Document>) () -> virtualFile.isValid() ? FileDocumentManager.getInstance().getDocument(virtualFile) : null); if (document == null) return 0; final int[] offset = {0}; int count = 0; int found; ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator()); TooManyUsagesStatus tooManyUsagesStatus = TooManyUsagesStatus.getFrom(indicator); do { tooManyUsagesStatus.pauseProcessingIfTooManyUsages(); // wait for user out of read action found = ApplicationManager.getApplication() .runReadAction( (Computable<Integer>) () -> { if (!psiFile.isValid()) return 0; return addToUsages( document, consumer, findModel, psiFile, offset, USAGES_PER_READ_ACTION); }); count += found; } while (found != 0); return count; }
@NotNull private static String getTitleForScope(@NotNull final FindModel findModel) { String scopeName; if (findModel.isProjectScope()) { scopeName = FindBundle.message("find.scope.project.title"); } else if (findModel.getModuleName() != null) { scopeName = FindBundle.message("find.scope.module.title", findModel.getModuleName()); } else if (findModel.getCustomScopeName() != null) { scopeName = findModel.getCustomScopeName(); } else { scopeName = FindBundle.message("find.scope.directory.title", findModel.getDirectoryName()); } String result = scopeName; if (findModel.getFileFilter() != null) { result += " " + FindBundle.message("find.scope.files.with.mask", findModel.getFileFilter()); } return result; }
public void searchAndShowUsages( @NotNull UsageViewManager manager, @NotNull Factory<UsageSearcher> usageSearcherFactory, @NotNull final FindModel findModelCopy, @NotNull UsageViewPresentation presentation, @NotNull FindUsagesProcessPresentation processPresentation, final FindManager findManager) { presentation.setMergeDupLinesAvailable(false); final ReplaceContext[] context = new ReplaceContext[1]; manager.searchAndShowUsages( new UsageTarget[] { new FindInProjectUtil.StringUsageTarget(myProject, findModelCopy.getStringToFind()) }, usageSearcherFactory, processPresentation, presentation, new UsageViewManager.UsageViewStateListener() { @Override public void usageViewCreated(@NotNull UsageView usageView) { context[0] = new ReplaceContext(usageView, findModelCopy); addReplaceActions(context[0]); } @Override public void findingUsagesFinished(final UsageView usageView) { if (context[0] != null && findManager.getFindInProjectModel().isPromptOnReplace()) { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { replaceWithPrompt(context[0]); context[0].invalidateExcludedSetCache(); } }); } } }); }
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(); initUI(); new SwitchToFind(this); new SwitchToReplace(this, editor); 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(); } updateMultiLineStateIfNeed(); }
@NotNull static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { SearchScope customScope = findModel.getCustomScope(); VirtualFile directory = getDirectory(findModel); Module module = findModel.getModuleName() == null ? null : ModuleManager.getInstance(project).findModuleByName(findModel.getModuleName()); return findModel.isCustomScope() && customScope != null ? customScope.intersectWith(GlobalSearchScope.allScope(project)) : // we don't have to check for myProjectFileIndex.isExcluded(file) here like // FindInProjectTask.collectFilesInScope() does // because all found usages are guaranteed to be not in excluded dir directory != null ? forDirectory(project, findModel.isWithSubdirectories(), directory) : module != null ? module.getModuleContentScope() : findModel.isProjectScope() ? ProjectScope.getContentScope(project) : GlobalSearchScope.allScope(project); }
public void setTextInField(final String text) { mySearchTextComponent.setText(text); myFindModel.setStringToFind(text); }
@Override public String getName() { return myFindModel.getStringToFind().isEmpty() ? myFindModel.getFileFilter() : myFindModel.getStringToFind(); }
private void updateSearchComponent() { final int oldCaretPosition = mySearchTextComponent != null ? mySearchTextComponent.getCaretPosition() : 0; String oldText = mySearchTextComponent != null ? mySearchTextComponent.getText() : myFindModel.getStringToFind(); if (!updateTextComponent(true)) { return; } if (oldText != null) { mySearchTextComponent.setText(oldText); } mySearchTextComponent .getDocument() .addDocumentListener( new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { searchFieldDocumentChanged(); } }); } }); } }); mySearchTextComponent.registerKeyboardAction( new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (StringUtil.isEmpty(mySearchTextComponent.getText())) { close(); } else { requestFocus(myEditor.getContentComponent()); addTextToRecent(EditorSearchComponent.this.mySearchTextComponent); } } }, KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, SystemInfo.isMac ? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK), JComponent.WHEN_FOCUSED); ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { mySearchTextComponent.setCaretPosition(oldCaretPosition); } }); new RestorePreviousSettingsAction(this, mySearchTextComponent); new VariantsCompletionAction( mySearchTextComponent); // It registers a shortcut set automatically on construction }
private void updateMultiLineStateIfNeed() { myFindModel.setMultiline( mySearchTextComponent.getText().contains("\n") || myReplaceTextComponent.getText().contains("\n")); }
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 boolean updateTextComponent(final boolean search) { JTextComponent oldComponent = search ? mySearchTextComponent : myReplaceTextComponent; Color oldBackground = oldComponent != null ? oldComponent.getBackground() : null; Wrapper wrapper = search ? mySearchFieldWrapper : myReplaceFieldWrapper; boolean multiline = myFindModel.isMultiline(); if (multiline && oldComponent instanceof JTextArea) return false; if (!multiline && oldComponent instanceof JTextField) return false; final JTextComponent textComponent; if (multiline) { textComponent = new JTextArea(); ((JTextArea) textComponent).setColumns(25); ((JTextArea) textComponent).setRows(2); wrapper.setContent( new SearchWrapper(textComponent, new ShowHistoryAction(textComponent, this))); } else { SearchTextField searchTextField = new SearchTextField(true); searchTextField.setOpaque(false); textComponent = searchTextField.getTextEditor(); searchTextField.getTextEditor().setColumns(25); if (UIUtil.isUnderGTKLookAndFeel()) { textComponent.setOpaque(false); } setupHistoryToSearchField( searchTextField, search ? FindSettings.getInstance().getRecentFindStrings() : FindSettings.getInstance().getRecentReplaceStrings()); textComponent.registerKeyboardAction( new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { final String text = textComponent.getText(); myFindModel.setMultiline(true); ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { if (search) { mySearchTextComponent.setText(text + "\n"); } else { myReplaceTextComponent.setText(text + "\n"); } } }); } }, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.ALT_DOWN_MASK), JComponent.WHEN_FOCUSED); wrapper.setContent(searchTextField); } if (search) { mySearchTextComponent = textComponent; } else { myReplaceTextComponent = textComponent; } UIUtil.addUndoRedoActions(textComponent); Utils.setSmallerFont(textComponent); textComponent.putClientProperty("AuxEditorComponent", Boolean.TRUE); if (oldBackground != null) { textComponent.setBackground(oldBackground); } textComponent.addFocusListener( new FocusListener() { @Override public void focusGained(final FocusEvent e) { textComponent.repaint(); } @Override public void focusLost(final FocusEvent e) { textComponent.repaint(); } }); new CloseOnESCAction(this, textComponent); return true; }