blob: 1ab1a5246b54aaadcb029e49df4d139172d4afaa [file] [log] [blame]
/*
* Copyright 2000-2009 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.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.CommonBundle;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.daemon.impl.quickfix.ClassKind;
import com.intellij.ide.util.PackageUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.JavaProjectRootsUtil;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiNameHelper;
import com.intellij.refactoring.MoveDestination;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox;
import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.RecentsManager;
import com.intellij.ui.ReferenceEditorComboWithBrowseButton;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
public class CreateClassDialog extends DialogWrapper {
private final JLabel myInformationLabel = new JLabel("#");
private final JLabel myPackageLabel = new JLabel(CodeInsightBundle.message("dialog.create.class.destination.package.label"));
private final ReferenceEditorComboWithBrowseButton myPackageComponent;
private final JTextField myTfClassName = new MyTextField();
private final Project myProject;
private PsiDirectory myTargetDirectory;
private final String myClassName;
private final boolean myClassNameEditable;
private final Module myModule;
private final DestinationFolderComboBox myDestinationCB = new DestinationFolderComboBox() {
@Override
public String getTargetPackage() {
return myPackageComponent.getText().trim();
}
@Override
protected boolean reportBaseInTestSelectionInSource() {
return CreateClassDialog.this.reportBaseInTestSelectionInSource();
}
@Override
protected boolean reportBaseInSourceSelectionInTest() {
return CreateClassDialog.this.reportBaseInSourceSelectionInTest();
}
};
@NonNls private static final String RECENTS_KEY = "CreateClassDialog.RecentsKey";
public CreateClassDialog(@NotNull Project project,
@NotNull String title,
@NotNull String targetClassName,
@NotNull String targetPackageName,
@NotNull ClassKind kind,
boolean classNameEditable,
@Nullable Module defaultModule) {
super(project, true);
myClassNameEditable = classNameEditable;
myModule = defaultModule;
myClassName = targetClassName;
myProject = project;
myPackageComponent = new PackageNameReferenceEditorCombo(targetPackageName, myProject, RECENTS_KEY, CodeInsightBundle.message("dialog.create.class.package.chooser.title"));
myPackageComponent.setTextFieldPreferredWidth(40);
init();
if (!myClassNameEditable) {
setTitle(CodeInsightBundle.message("dialog.create.class.name", StringUtil.capitalize(kind.getDescription()), targetClassName));
}
else {
myInformationLabel.setText(CodeInsightBundle.message("dialog.create.class.label", kind.getDescription()));
setTitle(title);
}
myTfClassName.setText(myClassName);
myDestinationCB.setData(myProject, getBaseDir(targetPackageName), new Pass<String>() {
@Override
public void pass(String s) {
setErrorText(s);
}
}, myPackageComponent.getChildComponent());
}
protected boolean reportBaseInTestSelectionInSource() {
return false;
}
protected boolean reportBaseInSourceSelectionInTest() {
return false;
}
@NotNull
@Override
protected Action[] createActions() {
return new Action[]{getOKAction(), getCancelAction()};
}
@Override
public JComponent getPreferredFocusedComponent() {
return myClassNameEditable ? myTfClassName : myPackageComponent.getChildComponent();
}
@Override
protected JComponent createCenterPanel() {
return new JPanel(new BorderLayout());
}
@Override
protected JComponent createNorthPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbConstraints = new GridBagConstraints();
gbConstraints.insets = new Insets(4, 8, 4, 8);
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
gbConstraints.anchor = GridBagConstraints.WEST;
if (myClassNameEditable) {
gbConstraints.weightx = 0;
gbConstraints.gridwidth = 1;
panel.add(myInformationLabel, gbConstraints);
gbConstraints.insets = new Insets(4, 8, 4, 8);
gbConstraints.gridx = 1;
gbConstraints.weightx = 1;
gbConstraints.gridwidth = 1;
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
gbConstraints.anchor = GridBagConstraints.WEST;
panel.add(myTfClassName, gbConstraints);
myTfClassName.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
getOKAction().setEnabled(PsiNameHelper.getInstance(myProject).isIdentifier(myTfClassName.getText()));
}
});
getOKAction().setEnabled(StringUtil.isNotEmpty(myClassName));
}
gbConstraints.gridx = 0;
gbConstraints.gridy = 2;
gbConstraints.weightx = 0;
gbConstraints.gridwidth = 1;
panel.add(myPackageLabel, gbConstraints);
gbConstraints.gridx = 1;
gbConstraints.weightx = 1;
new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
myPackageComponent.getButton().doClick();
}
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK)), myPackageComponent.getChildComponent());
JPanel _panel = new JPanel(new BorderLayout());
_panel.add(myPackageComponent, BorderLayout.CENTER);
panel.add(_panel, gbConstraints);
gbConstraints.gridy = 3;
gbConstraints.gridx = 0;
gbConstraints.gridwidth = 2;
gbConstraints.insets.top = 12;
gbConstraints.anchor = GridBagConstraints.WEST;
gbConstraints.fill = GridBagConstraints.NONE;
final JBLabel label = new JBLabel(RefactoringBundle.message("target.destination.folder"));
panel.add(label, gbConstraints);
gbConstraints.gridy = 4;
gbConstraints.gridx = 0;
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
gbConstraints.insets.top = 4;
panel.add(myDestinationCB, gbConstraints);
final boolean isMultipleSourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(myProject).size() > 1;
myDestinationCB.setVisible(isMultipleSourceRoots);
label.setVisible(isMultipleSourceRoots);
label.setLabelFor(myDestinationCB);
return panel;
}
public PsiDirectory getTargetDirectory() {
return myTargetDirectory;
}
private String getPackageName() {
String name = myPackageComponent.getText();
return name != null ? name.trim() : "";
}
private static class MyTextField extends JTextField {
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
FontMetrics fontMetrics = getFontMetrics(getFont());
size.width = fontMetrics.charWidth('a') * 40;
return size;
}
}
@Override
protected void doOKAction() {
RecentsManager.getInstance(myProject).registerRecentEntry(RECENTS_KEY, myPackageComponent.getText());
final String packageName = getPackageName();
final String[] errorString = new String[1];
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
try {
final PackageWrapper targetPackage = new PackageWrapper(PsiManager.getInstance(myProject), packageName);
final MoveDestination destination = myDestinationCB.selectDirectory(targetPackage, false);
if (destination == null) return;
myTargetDirectory = ApplicationManager.getApplication().runWriteAction(new Computable<PsiDirectory>() {
@Override
public PsiDirectory compute() {
return destination.getTargetDirectory(getBaseDir(packageName));
}
});
if (myTargetDirectory == null) {
errorString[0] = ""; // message already reported by PackageUtil
return;
}
errorString[0] = RefactoringMessageUtil.checkCanCreateClass(myTargetDirectory, getClassName());
}
catch (IncorrectOperationException e) {
errorString[0] = e.getMessage();
}
}
}, CodeInsightBundle.message("create.directory.command"), null);
if (errorString[0] != null) {
if (errorString[0].length() > 0) {
Messages.showMessageDialog(myProject, errorString[0], CommonBundle.getErrorTitle(), Messages.getErrorIcon());
}
return;
}
super.doOKAction();
}
@Nullable
protected PsiDirectory getBaseDir(String packageName) {
return myModule == null? null : PackageUtil.findPossiblePackageDirectoryInModule(myModule, packageName);
}
@NotNull
public String getClassName() {
if (myClassNameEditable) {
return myTfClassName.getText();
}
else {
return myClassName;
}
}
}