IDEA-177846 Improve Replace in Path

This commit is contained in:
Vassiliy.Kudryashov
2017-09-26 19:13:47 +03:00
parent e5740af209
commit d795ce8368
8 changed files with 242 additions and 81 deletions
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.AutoPopupController;
import com.intellij.find.*;
import com.intellij.find.actions.ShowUsagesAction;
import com.intellij.find.editorHeaderActions.ShowMoreOptions;
import com.intellij.find.replaceInProject.ReplaceInProjectManager;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.ui.UISettings;
@@ -30,6 +31,7 @@ import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -65,6 +67,7 @@ import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.FindUsagesProcessPresentation;
import com.intellij.usages.Usage;
import com.intellij.usages.UsageInfo2UsageAdapter;
@@ -85,9 +88,7 @@ import javax.swing.table.DefaultTableModel;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -130,6 +131,8 @@ public class FindPopupPanel extends JBPanel implements FindUI {
private ActionButton myTabResultsButton;
private ActionButton myPinButton;
private JButton myOKButton;
private JButton myReplaceAllButton;
private JButton myReplaceSelectedButton;
private JTextArea mySearchComponent;
private JTextArea myReplaceComponent;
private String mySelectedContextName = FindBundle.message("find.context.anywhere.scope.label");
@@ -142,6 +145,7 @@ public class FindPopupPanel extends JBPanel implements FindUI {
private LoadingDecorator myLoadingDecorator;
private int myLoadingHash;
private JPanel myTitlePanel;
private String[] myMessageState = new String[2];
FindPopupPanel(@NotNull FindUIHelper helper) {
myHelper = helper;
@@ -413,37 +417,70 @@ public class FindPopupPanel extends JBPanel implements FindUI {
}
}.registerCustomShortcutSet(CustomShortcutSet.fromString("alt DOWN"), this);
myOKButton = new JButton(FindBundle.message("find.popup.find.button"));
myReplaceAllButton = new JButton(FindBundle.message("find.popup.replace.all.button"));
myReplaceSelectedButton = new JButton(FindBundle.message("find.popup.replace.selected.button", 0));
myReplaceSelectedButton.setToolTipText("Replace " + KeymapUtil.getKeystrokeText(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_DOWN_MASK)));
myOkActionListener = __ -> {
FindModel validateModel = myHelper.getModel().clone();
applyTo(validateModel, false);
ValidationInfo validationInfo = getValidationInfo(validateModel);
if (validationInfo == null) {
myHelper.getModel().copyFrom(validateModel);
myHelper.updateFindSettings();
myHelper.doOKAction();
}
else {
String message = validationInfo.message;
Messages.showMessageDialog(
this,
message,
CommonBundle.getErrorTitle(),
Messages.getErrorIcon()
);
return;
}
myIsPinned.set(false);
Disposer.dispose(myBalloon);
doOK(true);
};
myReplaceAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (myResultsPreviewTable.getRowCount() < 2
|| JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(FindPopupPanel.this,
FindBundle.message(
"find.replace.all.confirmation",
myMessageState[0],
getStringToFind(),
myMessageState[1],
getStringToReplace()),
FindBundle.message(
"find.replace.all.confirmation.title"),
JOptionPane.OK_CANCEL_OPTION)) {
doOK(false);
}
}
});
myReplaceSelectedButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int rowToSelect = myResultsPreviewTable.getSelectionModel().getMinSelectionIndex();
Map<Integer, Usage> usages = getSelectedUsages();
if (usages == null) {
return;
}
CommandProcessor.getInstance().executeCommand(myProject, () -> {
for (Map.Entry<Integer, Usage> entry : usages.entrySet()) {
try {
ReplaceInProjectManager.getInstance(myProject).replaceUsage(entry.getValue(), myHelper.getModel(), Collections.emptySet(), false);
((DefaultTableModel)myResultsPreviewTable.getModel()).removeRow(entry.getKey());
}
catch (FindManager.MalformedReplacementStringException ex) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
Messages.showErrorDialog(FindPopupPanel.this, ex.getMessage(), FindBundle.message("find.replace.invalid.replacement.string.title"));
}
break;
}
}
ApplicationManager.getApplication().invokeLater(() -> {
if (myResultsPreviewTable.getRowCount() > rowToSelect) {
myResultsPreviewTable.getSelectionModel().setSelectionInterval(rowToSelect, rowToSelect);
}
ScrollingUtil.ensureSelectionExists(myResultsPreviewTable);
});
}, FindBundle.message("find.replace.command"), null);
}
});
myOKButton.addActionListener(myOkActionListener);
boolean enterAsOK = Registry.is("ide.find.enter.as.ok", false);
new AnAction() {
new DumbAwareAction() {
@Override
public void actionPerformed(AnActionEvent e) {
if (enterAsOK || myHelper.isReplaceState()) {
if (enterAsOK ) {
myOkActionListener.actionPerformed(null);
} else {
navigateToSelectedUsage();
@@ -453,7 +490,6 @@ public class FindPopupPanel extends JBPanel implements FindUI {
new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
if (myHelper.isReplaceState()) return;
if (enterAsOK) {
navigateToSelectedUsage();
} else {
@@ -529,7 +565,7 @@ public class FindPopupPanel extends JBPanel implements FindUI {
myResultsPreviewTable.setFocusable(false);
myResultsPreviewTable.getEmptyText().setShowAboveCenter(false);
myResultsPreviewTable.setShowColumns(false);
myResultsPreviewTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myResultsPreviewTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
myResultsPreviewTable.setShowGrid(false);
myResultsPreviewTable.setIntercellSpacing(JBUI.emptySize());
new DoubleClickListener() {
@@ -550,6 +586,7 @@ public class FindPopupPanel extends JBPanel implements FindUI {
myResultsPreviewTable);
ScrollingUtil.installActions(myResultsPreviewTable, false, mySearchComponent);
ScrollingUtil.installActions(myResultsPreviewTable, false, myReplaceComponent);
ScrollingUtil.installActions(myResultsPreviewTable, false, myReplaceSelectedButton);
ActionListener helpAction = __ -> HelpManager.getInstance().invokeHelp("reference.dialogs.findinpath");
registerKeyboardAction(helpAction,KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0),JComponent.WHEN_IN_FOCUSED_WINDOW);
@@ -562,27 +599,31 @@ public class FindPopupPanel extends JBPanel implements FindUI {
}
};
Disposer.register(myDisposable, myUsagePreviewPanel);
myResultsPreviewTable.getSelectionModel().addListSelectionListener(e -> {
if (e.getValueIsAdjusting()) return;
int index = myResultsPreviewTable.getSelectedRow();
if (index != -1) {
UsageInfo2UsageAdapter adapter = (UsageInfo2UsageAdapter)myResultsPreviewTable.getModel().getValueAt(index, 0);
myUsagePreviewPanel.updateLayout(adapter.isValid() ? Arrays.asList(adapter.getMergedInfos()) : null);
VirtualFile file = adapter.getFile();
String path = "";
if (file != null) {
String relativePath = VfsUtilCore.getRelativePath(file, myProject.getBaseDir());
if (relativePath == null) relativePath = file.getPath();
path = "<html><body>&nbsp;&nbsp;&nbsp;" +
relativePath
.replace(file.getName(), "<b>" + file.getName() + "</b>") + "</body></html>";
Runnable updatePreviewRunnable = () -> {
if (Disposer.isDisposed(myDisposable)) return;
int[] selectedRows = myResultsPreviewTable.getSelectedRows();
final List<UsageInfo> selection = new SmartList<>();
VirtualFile file = null;
for (int row : selectedRows) {
UsageInfo2UsageAdapter adapter = (UsageInfo2UsageAdapter)myResultsPreviewTable.getModel().getValueAt(row, 0);
file = adapter.getFile();
if (adapter.isValid()) {
selection.addAll(Arrays.asList(adapter.getMergedInfos()));
}
myUsagePreviewPanel.setBorder(IdeBorderFactory.createTitledBorder(path, false, new JBInsets(8, 0, 0, 0)).setShowLine(false));
}
String title = getTitle(file);
myReplaceSelectedButton.setText(FindBundle.message("find.popup.replace.selected.button", selection.size()));
myUsagePreviewPanel.updateLayout(selection);
if (myUsagePreviewPanel.getCannotPreviewMessage(selection) == null && title != null) {
myUsagePreviewPanel.setBorder(IdeBorderFactory.createTitledBorder(title, false, new JBInsets(8, 0, 0, 0)).setShowLine(false));
}
else {
myUsagePreviewPanel.updateLayout(null);
myUsagePreviewPanel.setBorder(IdeBorderFactory.createBorder());
myUsagePreviewPanel.setBorder(JBUI.Borders.empty());
}
};
myResultsPreviewTable.getSelectionModel().addListSelectionListener(e -> {
if (e.getValueIsAdjusting()) return;
ApplicationManager.getApplication().invokeLater(updatePreviewRunnable);
});
mySearchRescheduleOnCancellationsAlarm = new Alarm();
@@ -607,6 +648,8 @@ public class FindPopupPanel extends JBPanel implements FindUI {
myOKHintLabel.setEnabled(false);
bottomPanel.add(myOKHintLabel, "gapright 10");
bottomPanel.add(myOKButton);
bottomPanel.add(myReplaceAllButton);
bottomPanel.add(myReplaceSelectedButton);
myCodePreviewComponent = myUsagePreviewPanel.createComponent();
splitter.setSecondComponent(myCodePreviewComponent);
@@ -654,6 +697,40 @@ public class FindPopupPanel extends JBPanel implements FindUI {
});
}
private void doOK(boolean promptOnReplace) {
FindModel validateModel = myHelper.getModel().clone();
applyTo(validateModel, false);
ValidationInfo validationInfo = getValidationInfo(validateModel);
if (validationInfo == null) {
myHelper.getModel().copyFrom(validateModel);
myHelper.getModel().setPromptOnReplace(promptOnReplace);
myHelper.updateFindSettings();
myHelper.doOKAction();
}
else {
String message = validationInfo.message;
Messages.showMessageDialog(
this,
message,
CommonBundle.getErrorTitle(),
Messages.getErrorIcon()
);
return;
}
myIsPinned.set(false);
Disposer.dispose(myBalloon);
}
@Nullable
private String getTitle(@Nullable VirtualFile file) {
if (file == null) return null;
String path = VfsUtilCore.getRelativePath(file, myProject.getBaseDir());
if (path == null) path = file.getPath();
return "<html><body>&nbsp;&nbsp;&nbsp;" + path.replace(file.getName(), "<b>" + file.getName() + "</b>") + "</body></html>";
}
@NotNull
private static StateRestoringCheckBox createCheckBox(String message) {
StateRestoringCheckBox checkBox = new StateRestoringCheckBox(FindBundle.message(message));
@@ -737,7 +814,7 @@ public class FindPopupPanel extends JBPanel implements FindUI {
} else {
myOKHintLabel.setText(KeymapUtil.getKeystrokeText(ENTER_WITH_MODIFIERS));
}
myOKButton.setText(FindBundle.message(isReplaceState ? "find.popup.replace.button" : "find.popup.find.button"));
myOKButton.setText(FindBundle.message("find.popup.find.button"));
}
private void updateControls() {
@@ -765,6 +842,8 @@ public class FindPopupPanel extends JBPanel implements FindUI {
myCbCaseSensitive.makeSelectable();
}
}
myReplaceAllButton.setVisible(myHelper.isReplaceState());
myReplaceSelectedButton.setVisible(myHelper.isReplaceState());
}
private void updateScopeDetailsPanel() {
@@ -852,14 +931,16 @@ public class FindPopupPanel extends JBPanel implements FindUI {
myHelper.myPreviousModel = myHelper.getModel().clone();
myReplaceAllButton.setEnabled(false);
myReplaceSelectedButton.setEnabled(false);
myReplaceSelectedButton.setText(FindBundle.message("find.popup.replace.selected.button", 0));
myCodePreviewComponent.setVisible(false);
mySearchTextArea.setInfoText(null);
myResultsPreviewTable.setModel(model);
if (result != null) {
myResultsPreviewTable.getEmptyText().setText(UIBundle.message("message.nothingToShow") + " ("+result.message+")");
onStop(hash);
onStop(hash, result.message);
return;
}
@@ -867,7 +948,6 @@ public class FindPopupPanel extends JBPanel implements FindUI {
FindInProjectUtil.getScopeFromModel(myProject, myHelper.myPreviousModel), myProject);
myResultsPreviewTable.getColumnModel().getColumn(0).setCellRenderer(
new FindDialog.UsageTableCellRenderer(myCbFileFilter.isSelected(), false, scope));
myResultsPreviewTable.getEmptyText().setText("Searching...");
onStart(hash);
final AtomicInteger resultsCount = new AtomicInteger();
@@ -925,20 +1005,26 @@ public class FindPopupPanel extends JBPanel implements FindUI {
}
int occurrences = resultsCount.get();
int filesWithOccurrences = resultsFilesCount.get();
if (occurrences == 0) myResultsPreviewTable.getEmptyText().setText(UIBundle.message("message.nothingToShow"));
myCodePreviewComponent.setVisible(occurrences > 0);
myReplaceAllButton.setEnabled(occurrences > 0);
myReplaceSelectedButton.setEnabled(occurrences > 0);
StringBuilder stringBuilder = new StringBuilder();
if (occurrences > 0) {
stringBuilder.append(Math.min(ShowUsagesAction.getUsagesPageSize(), occurrences));
boolean foundAllUsages = occurrences < ShowUsagesAction.getUsagesPageSize();
myMessageState[0] = String.valueOf(occurrences);
if (!foundAllUsages) {
stringBuilder.append("+");
myMessageState[0] += "+";
}
stringBuilder.append(UIBundle.message("message.matches", occurrences));
stringBuilder.append(" in ");
stringBuilder.append(filesWithOccurrences);
myMessageState[1] = String.valueOf(filesWithOccurrences);
if (!foundAllUsages) {
stringBuilder.append("+");
myMessageState[1] += "+";
}
stringBuilder.append(UIBundle.message("message.files", filesWithOccurrences));
}
@@ -976,14 +1062,23 @@ public class FindPopupPanel extends JBPanel implements FindUI {
private void onStart(int hash) {
myLoadingHash = hash;
myLoadingDecorator.startLoading(false);
myResultsPreviewTable.getEmptyText().setText("Searching...");
}
private void onStop(int hash) {
onStop(hash, null);
}
private void onStop(int hash, String message) {
if (hash != myLoadingHash) {
return;
}
UIUtil.invokeLaterIfNeeded(() -> myLoadingDecorator.stopLoading());
UIUtil.invokeLaterIfNeeded(() -> {
myResultsPreviewTable.getEmptyText().setText(message != null ? UIBundle.message("message.nothingToShow.with.problem", message)
: UIBundle.message("message.nothingToShow"));
myLoadingDecorator.stopLoading();
});
}
@Override
@@ -1072,14 +1167,10 @@ public class FindPopupPanel extends JBPanel implements FindUI {
model.setSearchContext(searchContext);
model.setRegularExpressions(myCbRegularExpressions.isSelected());
String stringToFind = getStringToFind();
model.setStringToFind(stringToFind);
model.setStringToFind(getStringToFind());
if (model.isReplaceState()) {
model.setPromptOnReplace(true);
model.setReplaceAll(false);
String stringToReplace = getStringToReplace();
model.setStringToReplace(StringUtil.convertLineSeparators(stringToReplace));
model.setStringToReplace(StringUtil.convertLineSeparators(getStringToReplace()));
}
@@ -1098,29 +1189,35 @@ public class FindPopupPanel extends JBPanel implements FindUI {
}
private void navigateToSelectedUsage() {
Usage[] usages = getSelectedUsages();
Map<Integer, Usage> usages = getSelectedUsages();
if (usages != null) {
applyTo(FindManager.getInstance(myProject).getFindInProjectModel(), false);
myBalloon.cancel();
usages[0].navigate(true);
for (int i = 1; i < usages.length; ++i) usages[i].highlightInEditor();
boolean first = true;
for (Usage usage : usages.values()) {
if (first) {
usage.navigate(true);
}
else {
usage.highlightInEditor();
}
first = false;
}
}
}
@Nullable
private Usage[] getSelectedUsages() {
private Map<Integer, Usage> getSelectedUsages() {
int[] rows = myResultsPreviewTable.getSelectedRows();
List<Usage> usages = null;
Map<Integer, Usage> result = null;
for (int row : rows) {
Object valueAt = myResultsPreviewTable.getModel().getValueAt(row, 0);
if (valueAt instanceof Usage) {
if (usages == null) usages = new SmartList<>();
Usage at = (Usage)valueAt;
usages.add(at);
if (result == null) result = ContainerUtil.newLinkedHashMap();
result.put(row, (Usage)valueAt);
}
}
return usages != null ? ContainerUtil.toArray(usages, Usage.EMPTY_ARRAY) : null;
return result;
}
public static ActionToolbarImpl createToolbar(AnAction... actions) {
@@ -152,6 +152,7 @@ public class ReplaceInProjectManager {
final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(findModel.isOpenInNewTab(), findModelCopy);
final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, true, presentation);
processPresentation.setShowFindOptionsPrompt(findModel.isPromptOnReplace());
UsageSearcherFactory factory = new UsageSearcherFactory(findModelCopy, processPresentation);
searchAndShowUsages(manager, factory, findModelCopy, presentation, processPresentation, findManager);
@@ -214,9 +215,9 @@ public class ReplaceInProjectManager {
@Override
public void findingUsagesFinished(final UsageView usageView) {
if (context[0] != null && findManager.getFindInProjectModel().isPromptOnReplace()) {
if (context[0] != null && !processPresentation.isShowFindOptionsPrompt()) {
TransactionGuard.submitTransaction(myProject, () -> {
replaceWithPrompt(context[0]);
replaceUsagesUnderCommand(context[0], usageView.getUsages());
context[0].invalidateExcludedSetCache();
});
}
@@ -354,7 +355,27 @@ public class ReplaceInProjectManager {
}
private void addReplaceActions(final ReplaceContext replaceContext) {
final Runnable replaceRunnable = () -> replaceUsagesUnderCommand(replaceContext, replaceContext.getUsageView().getUsages());
final Runnable replaceRunnable = () -> {
Set<Usage> usages = replaceContext.getUsageView().getUsages();
Set<VirtualFile> files = new HashSet<>();
if (usages.isEmpty()) return;
for (Usage usage : usages) {
if (usage instanceof UsageInfo2UsageAdapter) {
files.add(((UsageInfo2UsageAdapter)usage).getFile());
}
}
if (files.size() < 2 ||
JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(replaceContext.getUsageView().getComponent(),
FindBundle.message("find.replace.all.confirmation",
usages.size(),
replaceContext.getFindModel().getStringToFind(),
files.size(),
replaceContext.getFindModel().getStringToReplace()),
FindBundle.message("find.replace.all.confirmation.title"),
JOptionPane.OK_CANCEL_OPTION)) {
replaceUsagesUnderCommand(replaceContext, usages);
}
};
replaceContext.getUsageView().addButtonToLowerPane(replaceRunnable, FindBundle.message("find.replace.all.action"));
final Runnable replaceSelectedRunnable =
@@ -24,7 +24,8 @@ find.what.usages.of.classes.and.interfaces=Usages of &classes and interfaces
find.dialog.find.button=Find
find.popup.find.button=Open in Find Window
find.popup.replace.button=Replace in Find Window...
find.popup.replace.all.button=Repl&ace All
find.popup.replace.selected.button=&Replace{0,choice,0#|1#|2# {0} occurrences}
find.usages.in.file.dialog.title=Find Usages in File
find.usages.dialog.title=Find Usages
find.open.in.new.tab.checkbox=Open in new ta&b
@@ -71,7 +72,7 @@ find.all.button=Find &All
find.text.to.find.label=Text to &find:
find.replace.with.label=Replace &with:
find.filter.file.name.group=File name filter
find.filter.file.mask.checkbox=File m&ask(s)
find.filter.file.mask.checkbox=File mas&k(s)
find.context.combo.label=Conte&xt:\u0020
find.context.anywhere.scope.label=Anywhere
find.context.in.comments.scope.label=In Comments
@@ -129,9 +130,11 @@ find.replace.occurrences.found.in.read.only.files.status=Occurrences found in re
find.replace.select.on.editor.command=Select on Editor
find.replace.found.usage.title=Replace Usage {0} of {1} Found - {2}
find.replace.command=Replace
find.replace.all.action=Replace All
find.replace.all.action=&Replace All
find.replace.all.action.description=&Do Replace Al&&l
find.replace.selected.action=Rep&lace &&Selected
find.replace.all.confirmation=<html><body>Replace {0} ocurrences of ''{1}'' across<br>{2} files with ''{3}''?
find.replace.all.confirmation.title=Replace All
find.replace.selected.action=Repl&ace Selected
find.replace.occurrences.in.read.only.files.prompt=Occurrences found in read-only files.\nThe operation will not affect them.\nContinue anyway?
find.replace.occurrences.in.read.only.files.title=Read-only Files Found
find.scope.custom.radio=Cu&stom:
@@ -142,7 +145,7 @@ occurrence=occurrence
results.options.group=Result options
find.popup.case.sensitive=Match &case
find.popup.whole.words=Wo&rds
find.popup.whole.words=W&ords
find.popup.regex=Re&gex
find.popup.filemask=File m&ask:
find.popup.scope.project=In &Project
@@ -168,6 +168,7 @@ file.chooser.save.dialog.file.name=File name:
tool.window.name.documentation=Documentation
message.nothingToShow=Nothing to show
message.nothingToShow.with.problem=Nothing to show ({0})
message.noMatchesFound=No matches found
message.matches={0,choice, 0# matches|1# match|2# matches}
message.files={0,choice, 0# files|1# file|2# files}
@@ -60,6 +60,7 @@ usage.type.read=Value read
usage.type.write=Value write
preview.usages.action.text=Preview {0}
select.the.usage.to.preview=Select {0} to preview
several.occurrences.selected=<html><body><center>Several files selected.<br>Select occurrences from one file to preview.</center></body></html>
usages.were.filtered.out={0,number} {0,choice, 1#usage was|2#usages were} filtered out
show.usages.only.usage=It''s the only usage in {0}
all.usages.are.in.this.line=All {0} usages in {1} are in this line
@@ -311,7 +311,17 @@ class SearchForUsagesRunnable implements Runnable {
usageView = new UsageViewImpl(myProject, myPresentation, mySearchFor, mySearcherFactory);
usageView.associateProgress(indicator);
if (myUsageViewRef.compareAndSet(null, usageView)) {
openView(usageView);
if (myProcessPresentation.isShowFindOptionsPrompt()) {
openView(usageView);
} else {
UsageViewImpl[] tmp = new UsageViewImpl[]{usageView};
SwingUtilities.invokeLater(() -> {
if (myProject.isDisposed()) return;
if (myListener != null) {
myListener.usageViewCreated(tmp[0]);
}
});
}
final Usage firstUsage = myFirstUsage.get();
if (firstUsage != null) {
final UsageViewImpl finalUsageView = usageView;
@@ -221,14 +221,35 @@ public class UsagePreviewPanel extends UsageContextPanelBase implements DataProv
}
}
@Nullable
public final String getCannotPreviewMessage(@Nullable final List<UsageInfo> infos) {
if (infos == null || infos.isEmpty()) {
return UsageViewBundle.message("select.the.usage.to.preview", myPresentation.getUsagesWord());
} else {
PsiFile psiFile = null;
for (UsageInfo info : infos) {
PsiElement element = info.getElement();
if (element == null) continue;
PsiFile file = element.getContainingFile();
if (psiFile == null) {
psiFile = file;
} else {
if (psiFile != file) {
return UsageViewBundle.message("several.occurrences.selected");
}
}
}
}
return null;
}
@Override
public void updateLayoutLater(@Nullable final List<UsageInfo> infos) {
if (infos == null) {
String cannotPreviewMessage = getCannotPreviewMessage(infos);
if (cannotPreviewMessage != null) {
releaseEditor();
removeAll();
JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview", myPresentation.getUsagesWord()), SwingConstants.CENTER);
JComponent titleComp = new JLabel(cannotPreviewMessage, SwingConstants.CENTER);
add(titleComp, BorderLayout.CENTER);
revalidate();
}
@@ -1098,6 +1098,7 @@ public class UsageViewImpl implements UsageView {
@Override
public void removeUsagesBulk(@NotNull Collection<Usage> usages) {
int selectionRow = myTree.getMinSelectionRow();
Set<UsageNode> nodes = usagesToNodes(usages.stream()).collect(Collectors.toSet());
usages.forEach(u -> myUsageNodes.remove(u));
@@ -1106,6 +1107,10 @@ public class UsageViewImpl implements UsageView {
if (isDisposed) return;
DefaultTreeModel treeModel = (DefaultTreeModel)myTree.getModel();
((GroupNode)treeModel.getRoot()).removeUsagesBulk(nodes, treeModel);
int rowToSelect = Math.min(myTree.getRowCount() - 1, selectionRow);
if (rowToSelect >=0) {
myTree.setSelectionRow(rowToSelect);
}
});
}
}
@@ -1240,7 +1245,9 @@ public class UsageViewImpl implements UsageView {
@Override
public void close() {
cancelCurrentSearch();
UsageViewManager.getInstance(myProject).closeContent(myContent);
if (myContent != null) {
UsageViewManager.getInstance(myProject).closeContent(myContent);
}
}
private void saveSplitterProportions() {