package com.intellij.javascript.flex.refactoring.moveClass; import com.intellij.ide.util.PlatformPackageUtil; import com.intellij.lang.LanguageNamesValidation; import com.intellij.lang.javascript.JSBundle; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.flex.FlexBundle; import com.intellij.lang.javascript.psi.ecmal4.JSQualifiedNamedElement; import com.intellij.lang.javascript.psi.resolve.JSNamedElementKind; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.lang.javascript.refactoring.ui.JSReferenceEditor; import com.intellij.lang.javascript.refactoring.util.JSRefactoringUtil; import com.intellij.lang.refactoring.NamesValidator; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.impl.DirectoryIndex; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiDirectoryContainer; import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.move.MoveCallback; import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.NonFocusableCheckBox; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ThreeState; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentEvent; import java.util.Collection; public class FlexMoveClassDialog extends RefactoringDialog { private static final Logger LOG = Logger.getInstance(FlexMoveClassDialog.class.getName()); private JLabel myElementLabel; private JSReferenceEditor myTargetPackageField; private JPanel myContentPane; private NonFocusableCheckBox myCbSearchInComments; private NonFocusableCheckBox myCbSearchTextOccurences; private NonFocusableCheckBox myCbMoveToAnotherSourceFolder; private JLabel myPackageLabel; private JTextField myClassNameField; private JLabel myClassNameLabel; private final Project myProject; private final Collection<JSQualifiedNamedElement> myElements; @Nullable private final PsiElement myTargetContainer; @Nullable private final MoveCallback myCallback; private final boolean myFileLocal; public FlexMoveClassDialog(Project project, Collection<JSQualifiedNamedElement> elements, @Nullable PsiElement targetContainer, @Nullable MoveCallback callback) { super(project, true); myProject = project; myElements = elements; myTargetContainer = targetContainer; myCallback = callback; final JSQualifiedNamedElement firstElement = myElements.iterator().next(); myFileLocal = JSResolveUtil.isFileLocalSymbol(firstElement); setSize(500, 130); String labelText; if (myFileLocal) { LOG.assertTrue(myElements.size() == 1); myClassNameLabel.setVisible(true); myClassNameLabel.setText( FlexBundle.message("element.name", JSBundle.message(JSNamedElementKind.kind(firstElement).humanReadableKey()))); myClassNameField.setVisible(true); myClassNameField.setText(myElements.iterator().next().getName()); myClassNameField.selectAll(); myPackageLabel.setText(FlexBundle.message("package.name.title")); setTitle(RefactoringBundle.message("move.inner.to.upper.level.title")); } else { myClassNameLabel.setVisible(false); myClassNameField.setVisible(false); myPackageLabel.setText(FlexBundle.message("to.package.title")); setTitle(RefactoringBundle.message("move.title")); } myElementLabel.setLabelFor(myTargetPackageField.getChildComponent()); if (elements.size() == 1) { labelText = FlexBundle.message(myFileLocal ? "move.file.local.0" : "move.0", StringUtil.decapitalize(JSBundle.message(JSNamedElementKind.kind(firstElement).humanReadableKey())), firstElement.getQualifiedName()); } else { labelText = FlexBundle.message("move.elements"); } myElementLabel.setText(labelText); myPackageLabel.setLabelFor(myTargetPackageField.getChildComponent()); init(); boolean canMoveToDifferentSourceRoot = !myFileLocal && ProjectRootManager.getInstance(myProject).getContentSourceRoots().length > 1; if (canMoveToDifferentSourceRoot) { myCbMoveToAnotherSourceFolder.setEnabled(true); } else { myCbMoveToAnotherSourceFolder.setEnabled(false); myCbMoveToAnotherSourceFolder.setSelected(false); } myClassNameField.getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { validateButtons(); } }); myTargetPackageField.addDocumentListener(new DocumentListener() { @Override public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) { validateButtons(); } }); } @Override protected void canRun() throws ConfigurationException { final NamesValidator namesValidator = LanguageNamesValidation.INSTANCE.forLanguage(JavaScriptSupportLoader.JAVASCRIPT.getLanguage()); if (myFileLocal) { final String className = myClassNameField.getText(); if (StringUtil.isEmpty(className)) { throw new ConfigurationException(FlexBundle.message("element.name.empty", JSBundle.message( JSNamedElementKind.kind(myElements.iterator().next()).humanReadableKey()))); } if (!namesValidator.isIdentifier(className, myProject)) { throw new ConfigurationException(FlexBundle.message("invalid.element.name", StringUtil .decapitalize(JSBundle.message(JSNamedElementKind.kind(myElements.iterator().next()).humanReadableKey())), className)); } } final String packageName = myTargetPackageField.getText(); for (final String s : StringUtil.split(packageName, ".")) { if (!namesValidator.isIdentifier(s, myProject)) { throw new ConfigurationException(JSBundle.message("invalid.package", packageName)); } } } private void createUIComponents() { String initialPackage; if (myTargetContainer instanceof PsiDirectoryContainer) { initialPackage = DirectoryIndex.getInstance(myProject) .getPackageName(((PsiDirectoryContainer)myTargetContainer).getDirectories()[0].getVirtualFile()); } else if (myTargetContainer instanceof PsiDirectory) { initialPackage = DirectoryIndex.getInstance(myProject) .getPackageName(((PsiDirectory)myTargetContainer).getVirtualFile()); } else { if (myFileLocal) { initialPackage = StringUtil.getPackageName(myElements.iterator().next().getQualifiedName()); } else { initialPackage = JSResolveUtil.getExpectedPackageNameFromFile(myElements.iterator().next().getContainingFile().getVirtualFile(), myProject); } } myTargetPackageField = JSReferenceEditor.forPackageName(initialPackage, myProject, FlexMoveClassDialog.class.getName() + ".target_package", GlobalSearchScope.projectScope(myProject), RefactoringBundle.message("choose.destination.package")); } @Override protected JComponent createCenterPanel() { return myContentPane; } @Override public JComponent getPreferredFocusedComponent() { return myClassNameField.isVisible() ? myClassNameField : myTargetPackageField.getChildComponent(); } @Override protected String getDimensionServiceKey() { return FlexMoveClassDialog.class.getName(); } @Override protected void doAction() { myTargetPackageField.updateRecents(); PsiElement firstElement = myElements.iterator().next(); PsiDirectory baseDir; if (myTargetContainer instanceof PsiDirectory) { baseDir = (PsiDirectory)myTargetContainer; } else { baseDir = PlatformPackageUtil.getDirectory(firstElement); } String nameToCheck = myFileLocal ? myClassNameField.getText() : null; PsiDirectory targetDirectory = JSRefactoringUtil.chooseOrCreateDirectoryForClass(myProject, ModuleUtilCore.findModuleForPsiElement(firstElement), GlobalSearchScope.projectScope(myProject), myTargetPackageField.getText(), nameToCheck, baseDir, myCbMoveToAnotherSourceFolder.isSelected() ? ThreeState.YES : ThreeState.NO); if (targetDirectory == null) { return; } // file-local case already checked by JSRefactoringUtil.chooseOrCreateDirectoryForClass (see nameToCheck) if (!myFileLocal) { try { for (PsiElement element : myElements) { MoveFilesOrDirectoriesUtil.checkMove(element.getContainingFile(), targetDirectory); } } catch (IncorrectOperationException e) { CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.getMessage(), getHelpId(), myProject); return; } } BaseRefactoringProcessor processor; if (myFileLocal) { processor = new FlexMoveInnerClassProcessor(myElements.iterator().next(), targetDirectory, myClassNameField.getText(), myTargetPackageField.getText(), myCbSearchInComments.isSelected(), myCbSearchTextOccurences.isSelected(), myCallback); } else { processor = new FlexMoveClassProcessor(myElements, targetDirectory, myTargetPackageField.getText(), myCbSearchInComments.isSelected(), myCbSearchTextOccurences.isSelected(), myCallback); } invokeRefactoring(processor); } @Override protected String getHelpId() { return myFileLocal ? "Move_Inner_to_Upper_Level_Dialog_for_ActionScript" : "refactoring.moveClass"; } }