package jetbrains.mps.ide.java.platform.refactorings;
/*Generated by MPS */
import jetbrains.mps.ide.platform.refactoring.RefactoringDialog;
import jetbrains.mps.baseLanguage.util.plugin.refactorings.InlineMethodModel;
import org.jetbrains.mps.openapi.module.SRepository;
import jetbrains.mps.openapi.editor.EditorContext;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.project.MPSProject;
import jetbrains.mps.smodel.ModelAccessHelper;
import jetbrains.mps.util.Computable;
import org.jetbrains.annotations.Nullable;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
import javax.swing.border.EmptyBorder;
import javax.swing.ButtonGroup;
import javax.swing.JRadioButton;
import java.awt.Component;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import javax.swing.JOptionPane;
import javax.swing.AbstractAction;
import java.awt.event.ActionEvent;
import javax.swing.JComponent;
import java.awt.BorderLayout;
import org.jetbrains.annotations.NotNull;
import javax.swing.Action;
import jetbrains.mps.ide.findusages.model.SearchResults;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.ProgressIndicator;
import jetbrains.mps.baseLanguage.util.plugin.refactorings.MethodRefactoringUtils;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.progress.ProgressMonitorAdapter;
import javax.swing.JLabel;
import jetbrains.mps.editor.runtime.commands.EditorCommand;
import jetbrains.mps.ide.findusages.model.SearchResult;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.baseLanguage.util.plugin.refactorings.InlineMethodRefactoring;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.ide.platform.refactoring.RefactoringViewAction;
import jetbrains.mps.ide.platform.refactoring.RefactoringViewItem;
import jetbrains.mps.ide.platform.refactoring.RefactoringAccessEx;
public class InlineMethodDialog extends RefactoringDialog {
private InlineMethodModel myModel;
private InlineMethodDialog.PreviewAction myPreviewAction;
private boolean myForAll;
private final SRepository myEditorRepo;
private final EditorContext myEditorContext;
public InlineMethodDialog(final SNode node, MPSProject project, EditorContext editorContext) {
super(project.getProject(), true);
myEditorContext = editorContext;
myEditorRepo = myEditorContext.getRepository();
setTitle("Inline Method");
setResizable(false);
myModel = new ModelAccessHelper(myEditorRepo).runReadAction(new Computable<InlineMethodModel>() {
public InlineMethodModel compute() {
return new InlineMethodModel(node);
}
});
init();
}
@Nullable
@Override
protected String getHelpId() {
return "refactoring.inlineMethod";
}
private JPanel createCheckBoxes() {
JPanel checkboxesPanel = new JPanel();
checkboxesPanel.setLayout(new BoxLayout(checkboxesPanel, BoxLayout.Y_AXIS));
checkboxesPanel.setBorder(new EmptyBorder(10, 0, 0, 0));
ButtonGroup group = new ButtonGroup();
JRadioButton button1 = this.createButton(group, checkboxesPanel, false, "Inline this invocation only and keep the method");
JRadioButton button2 = this.createButton(group, checkboxesPanel, true, "Inline all invocations and remove the method");
if (myModel.isRecusive()) {
button2.setEnabled(false);
}
if (myModel.getMethodCall() != null) {
button1.setSelected(true);
myForAll = false;
} else {
button1.setEnabled(false);
button2.setSelected(true);
myForAll = true;
}
myPreviewAction.setEnabled(myForAll);
return checkboxesPanel;
}
public void tryToShow(Component parentComponent) {
final Wrappers._T<String> errors = new Wrappers._T<String>();
myEditorRepo.getModelAccess().runReadAction(new Runnable() {
public void run() {
errors.value = myModel.getErrors();
}
});
if (errors.value == null) {
show();
} else {
JOptionPane.showMessageDialog(parentComponent, errors.value, "Can't perform refactoring", JOptionPane.ERROR_MESSAGE);
}
}
private JRadioButton createButton(ButtonGroup group, JPanel checkboxesPanel, final boolean forAll, String text) {
JRadioButton button1 = new JRadioButton(new AbstractAction(text) {
@Override
public void actionPerformed(ActionEvent e) {
myForAll = forAll;
myPreviewAction.setEnabled(forAll);
}
});
group.add(button1);
checkboxesPanel.add(button1);
return button1;
}
@Nullable
@Override
protected JComponent createCenterPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(createCheckBoxes(), BorderLayout.CENTER);
return panel;
}
@Override
protected void createDefaultActions() {
super.createDefaultActions();
myPreviewAction = new InlineMethodDialog.PreviewAction();
}
@Override
@NotNull
protected Action[] createActions() {
return new Action[]{getRefactorAction(), myPreviewAction, getCancelAction()};
}
/**
* This method will be called on pressing "Refactor" button in dialog.
*
*/
@Override
protected void doRefactoringAction() {
SearchResults<SNode> usages = findUssages();
if (canExecuteRefactoring(usages)) {
performRefactoring(usages);
}
super.doRefactoringAction();
}
private boolean canExecuteRefactoring(SearchResults<SNode> usages) {
String problems = getProblems(usages);
if (problems.length() == 0) {
return true;
}
ProblemsDialog dialog = new ProblemsDialog(myProject, problems);
dialog.show();
return dialog.getExitCode() == DialogWrapper.NEXT_USER_EXIT_CODE;
}
private SearchResults<SNode> findUssages() {
if (!(myForAll)) {
return null;
}
final Wrappers._T<SearchResults<SNode>> usages = new Wrappers._T<SearchResults<SNode>>();
ProgressManager.getInstance().run(new Task.Modal(getProject(), "Searching for ussages", true) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
myEditorRepo.getModelAccess().runReadAction(new Runnable() {
public void run() {
usages.value = MethodRefactoringUtils.findMethodUsages(ProjectHelper.fromIdeaProject(getProject()).new ProjectScope(), myModel.getMethod(), new ProgressMonitorAdapter(indicator));
}
});
}
});
return usages.value;
}
private String getProblems(final SearchResults<SNode> usages) {
final StringBuilder sb = new StringBuilder();
ProgressManager.getInstance().run(new Task.Modal(getProject(), "Search for overriding methods", true) {
public void run(@NotNull final ProgressIndicator pi) {
myEditorRepo.getModelAccess().runReadAction(new Runnable() {
public void run() {
InlineMethodRefactoringAnalyzer analyzer;
if (myModel.getMethodCall() == null) {
analyzer = new InlineMethodRefactoringAnalyzer(null, myModel.getMethod());
} else {
analyzer = new InlineMethodRefactoringAnalyzer(myModel.getMethodCall().getNode(), myModel.getMethod());
}
analyzer.appendProblems(ProjectHelper.fromIdeaProject(getProject()).new ProjectScope(), usages, sb, new ProgressMonitorAdapter(pi));
}
});
}
});
return sb.toString();
}
@Nullable
@Override
protected JComponent createNorthPanel() {
JLabel label = new JLabel();
label.setText(myModel.getMethodPresentation());
return label;
}
private void performRefactoring(final SearchResults<SNode> usages) {
myEditorRepo.getModelAccess().executeCommand(new EditorCommand(myEditorContext) {
protected void doExecute() {
if (usages != null) {
for (SearchResult<SNode> res : ListSequence.fromList(usages.getSearchResults())) {
InlineMethodRefactoring ref = new InlineMethodRefactoring(res.getObject());
ref.doRefactor();
}
SNodeOperations.deleteNode(myModel.getMethod());
} else {
InlineMethodRefactoring ref = new InlineMethodRefactoring(myModel.getMethodCall().getNode());
ref.doRefactor();
}
}
});
}
public class PreviewAction extends DialogWrapper.DialogWrapperAction {
public PreviewAction() {
super("Preview");
}
@Override
protected void doAction(ActionEvent event) {
final SearchResults<SNode> usages = findUssages();
if (canExecuteRefactoring(usages)) {
RefactoringViewAction refactoringViewAction = new RefactoringViewAction() {
@Override
public void performAction(RefactoringViewItem item) {
item.close();
performRefactoring(usages);
}
};
RefactoringAccessEx.getInstance().showRefactoringView(getProject(), refactoringViewAction, usages, false, "refactoring");
}
close(DialogWrapper.OK_EXIT_CODE);
}
}
}