blob: cb502377f83bd273857d1a377a4474b4dbf80fee [file] [log] [blame]
/*
* Copyright 2000-2012 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.
*/
/**
* created at Sep 24, 2001
* @author Jeka
*/
package com.intellij.refactoring.move.moveInner;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.JavaProjectRootsUtil;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.MoveInstanceMembersUtil;
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil;
import com.intellij.refactoring.ui.NameSuggestionsField;
import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo;
import com.intellij.refactoring.ui.RefactoringDialog;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.ui.EditorTextField;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MoveInnerDialog extends RefactoringDialog {
private final Project myProject;
private final PsiClass myInnerClass;
private final PsiElement myTargetContainer;
private final MoveInnerProcessor myProcessor;
private EditorTextField myClassNameField;
private NameSuggestionsField myParameterField;
private JCheckBox myCbPassOuterClass;
private JPanel myPanel;
private JCheckBox myCbSearchInComments;
private JCheckBox myCbSearchForTextOccurences;
private PackageNameReferenceEditorCombo myPackageNameField;
private JLabel myPackageNameLabel;
private JLabel myClassNameLabel;
private JLabel myParameterNameLabel;
private SuggestedNameInfo mySuggestedNameInfo;
private final PsiClass myOuterClass;
@NonNls private static final String RECENTS_KEY = "MoveInnerDialog.RECENTS_KEY";
public MoveInnerDialog(Project project, PsiClass innerClass, MoveInnerProcessor processor, final PsiElement targetContainer) {
super(project, true);
myProject = project;
myInnerClass = innerClass;
myTargetContainer = targetContainer;
myOuterClass = myInnerClass.getContainingClass();
myProcessor = processor;
setTitle(MoveInnerImpl.REFACTORING_NAME);
init();
myPackageNameLabel.setLabelFor(myPackageNameField.getChildComponent());
myClassNameLabel.setLabelFor(myClassNameField);
myParameterNameLabel.setLabelFor(myParameterField);
}
public boolean isSearchInComments() {
return myCbSearchInComments.isSelected();
}
public boolean isSearchInNonJavaFiles() {
return myCbSearchForTextOccurences.isSelected();
}
public String getClassName() {
return myClassNameField.getText().trim();
}
@Nullable
public String getParameterName() {
if (myParameterField != null) {
return myParameterField.getEnteredName();
}
else {
return null;
}
}
public boolean isPassOuterClass() {
return myCbPassOuterClass.isSelected();
}
@NotNull
public PsiClass getInnerClass() {
return myInnerClass;
}
protected void init() {
myClassNameField.setText(myInnerClass.getName());
myClassNameField.selectAll();
if (!myInnerClass.hasModifierProperty(PsiModifier.STATIC)) {
myCbPassOuterClass.setSelected(true);
myCbPassOuterClass.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
myParameterField.setEnabled(myCbPassOuterClass.isSelected());
}
});
}
else {
myCbPassOuterClass.setSelected(false);
myCbPassOuterClass.setEnabled(false);
myParameterField.setEnabled(false);
}
if (myCbPassOuterClass.isEnabled()) {
boolean thisNeeded = isThisNeeded(myInnerClass, myOuterClass);
myCbPassOuterClass.setSelected(thisNeeded);
myParameterField.setEnabled(thisNeeded);
}
myCbPassOuterClass.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
boolean selected = myCbPassOuterClass.isSelected();
myParameterField.getComponent().setEnabled(selected);
}
});
if (!(myTargetContainer instanceof PsiDirectory)) {
myPackageNameField.setVisible(false);
myPackageNameLabel.setVisible(false);
}
super.init();
}
public static boolean isThisNeeded(final PsiClass innerClass, final PsiClass outerClass) {
final Map<PsiClass, Set<PsiMember>> classesToMembers = MoveInstanceMembersUtil.getThisClassesToMembers(innerClass);
for (PsiClass psiClass : classesToMembers.keySet()) {
if (InheritanceUtil.isInheritorOrSelf(outerClass, psiClass, true)) {
return true;
}
}
return false;
}
public JComponent getPreferredFocusedComponent() {
return myClassNameField;
}
protected String getDimensionServiceKey() {
return "#com.intellij.refactoring.move.moveInner.MoveInnerDialog";
}
protected JComponent createNorthPanel() {
return myPanel;
}
protected JComponent createCenterPanel() {
return null;
}
@Nullable
private PsiElement getTargetContainer() {
if (myTargetContainer instanceof PsiDirectory) {
final PsiDirectory psiDirectory = (PsiDirectory)myTargetContainer;
PsiPackage oldPackage = getTargetPackage();
String name = oldPackage == null ? "" : oldPackage.getQualifiedName();
final String targetName = myPackageNameField.getText();
if (!Comparing.equal(name, targetName)) {
final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(myProject);
final List<VirtualFile> contentSourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(myProject);
final PackageWrapper newPackage = new PackageWrapper(PsiManager.getInstance(myProject), targetName);
final VirtualFile targetSourceRoot;
if (contentSourceRoots.size() > 1) {
PsiDirectory initialDir = null;
if (oldPackage != null) {
final PsiDirectory[] directories = oldPackage.getDirectories();
final VirtualFile root = projectRootManager.getFileIndex().getContentRootForFile(psiDirectory.getVirtualFile());
for(PsiDirectory dir: directories) {
if (Comparing.equal(projectRootManager.getFileIndex().getContentRootForFile(dir.getVirtualFile()), root)) {
initialDir = dir;
}
}
}
final VirtualFile sourceRoot = MoveClassesOrPackagesUtil.chooseSourceRoot(newPackage, contentSourceRoots, initialDir);
if (sourceRoot == null) return null;
targetSourceRoot = sourceRoot;
}
else {
targetSourceRoot = contentSourceRoots.get(0);
}
PsiDirectory dir = RefactoringUtil.findPackageDirectoryInSourceRoot(newPackage, targetSourceRoot);
if (dir == null) {
dir = ApplicationManager.getApplication().runWriteAction(new NullableComputable<PsiDirectory>() {
public PsiDirectory compute() {
try {
return RefactoringUtil.createPackageDirectoryInSourceRoot(newPackage, targetSourceRoot);
}
catch (IncorrectOperationException e) {
return null;
}
}
});
}
return dir;
}
}
return myTargetContainer;
}
protected void doAction() {
String message = null;
final String className = getClassName();
final String parameterName = getParameterName();
PsiManager manager = PsiManager.getInstance(myProject);
if ("".equals(className)) {
message = RefactoringBundle.message("no.class.name.specified");
}
else {
if (!PsiNameHelper.getInstance(manager.getProject()).isIdentifier(className)) {
message = RefactoringMessageUtil.getIncorrectIdentifierMessage(className);
}
else {
if (myCbPassOuterClass.isSelected()) {
if ("".equals(parameterName)) {
message = RefactoringBundle.message("no.parameter.name.specified");
}
else {
if (!PsiNameHelper.getInstance(manager.getProject()).isIdentifier(parameterName)) {
message = RefactoringMessageUtil.getIncorrectIdentifierMessage(parameterName);
}
}
}
if (message == null) {
if (myTargetContainer instanceof PsiClass) {
PsiClass targetClass = (PsiClass)myTargetContainer;
PsiClass[] classes = targetClass.getInnerClasses();
for (PsiClass aClass : classes) {
if (className.equals(aClass.getName())) {
message = RefactoringBundle.message("inner.class.exists", className, targetClass.getName());
break;
}
}
}
else if (myTargetContainer instanceof PsiDirectory) {
message = RefactoringMessageUtil.checkCanCreateClass((PsiDirectory)myTargetContainer, className);
}
}
}
}
if (message != null) {
CommonRefactoringUtil.showErrorMessage(
MoveInnerImpl.REFACTORING_NAME,
message,
HelpID.MOVE_INNER_UPPER,
myProject);
return;
}
JavaRefactoringSettings.getInstance().MOVE_INNER_PREVIEW_USAGES = isPreviewUsages();
if (myCbPassOuterClass.isSelected() && mySuggestedNameInfo != null) {
mySuggestedNameInfo.nameChosen(getParameterName());
}
final PsiElement target = getTargetContainer();
if (target == null) return;
myProcessor.setup(getInnerClass(), className, isPassOuterClass(), parameterName,
isSearchInComments(), isSearchInNonJavaFiles(), target);
invokeRefactoring(myProcessor);
}
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp(HelpID.MOVE_INNER_UPPER);
}
private void createUIComponents() {
if (!myInnerClass.hasModifierProperty(PsiModifier.STATIC)) {
final PsiManager manager = myInnerClass.getManager();
PsiType outerType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(myInnerClass.getContainingClass());
mySuggestedNameInfo = JavaCodeStyleManager.getInstance(myProject).suggestVariableName(VariableKind.PARAMETER, null, null, outerType);
String[] variants = mySuggestedNameInfo.names;
myParameterField = new NameSuggestionsField(variants, myProject);
}
else {
myParameterField = new NameSuggestionsField(new String[]{""}, myProject);
myParameterField.getComponent().setEnabled(false);
}
myPackageNameField = new PackageNameReferenceEditorCombo("", myProject, RECENTS_KEY,
RefactoringBundle.message("choose.destination.package"));
PsiPackage psiPackage = getTargetPackage();
if (psiPackage != null) {
myPackageNameField.prependItem(psiPackage.getQualifiedName());
}
}
@Nullable
private PsiPackage getTargetPackage() {
if (myTargetContainer instanceof PsiDirectory) {
final PsiDirectory directory = (PsiDirectory)myTargetContainer;
return JavaDirectoryService.getInstance().getPackage(directory);
}
return null;
}
}