blob: ceae8aed2e44d622cf20e3525aa3b4bd33e565b2 [file] [log] [blame]
/*
* Copyright 2000-2011 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.refactoring.introduceField;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.refactoring.util.occurrences.OccurrenceManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* User: anna
* Date: 3/18/11
*/
public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceFieldPopup {
private final String myInitializerText;
private JCheckBox myReplaceAllCb;
private JCheckBox myMoveToAnotherClassCb;
public InplaceIntroduceConstantPopup(Project project,
Editor editor,
PsiClass parentClass,
PsiExpression expr,
PsiLocalVariable localVariable,
PsiExpression[] occurrences,
TypeSelectorManagerImpl typeSelectorManager,
PsiElement anchorElement,
PsiElement anchorElementIfAll, OccurrenceManager occurrenceManager) {
super(project, editor, expr, localVariable, occurrences, typeSelectorManager, IntroduceConstantHandler.REFACTORING_NAME,
parentClass, anchorElement, occurrenceManager, anchorElementIfAll);
myInitializerText = getExprText(expr, localVariable);
GridBagConstraints gc =
new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0);
myWholePanel.add(getPreviewComponent(), gc);
gc.gridy = 1;
myWholePanel.add(createRightPanel(), gc);
gc.gridy = 2;
myWholePanel.add(createLeftPanel(), gc);
}
@Nullable
private static String getExprText(PsiExpression expr, PsiLocalVariable localVariable) {
final String exprText = expr != null ? expr.getText() : null;
if (localVariable != null) {
final PsiExpression initializer = localVariable.getInitializer();
return initializer != null ? initializer.getText() : exprText;
}
else {
return exprText;
}
}
private JPanel createRightPanel() {
final JPanel right = new JPanel(new GridBagLayout());
final GridBagConstraints rgc =
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0);
myReplaceAllCb = new JCheckBox("Replace all occurrences");
myReplaceAllCb.setMnemonic('a');
myReplaceAllCb.setFocusable(false);
myReplaceAllCb.setVisible(myOccurrences.length > 1);
right.add(myReplaceAllCb, rgc);
return right;
}
private JPanel createLeftPanel() {
final JPanel left = new JPanel(new GridBagLayout());
myMoveToAnotherClassCb =
new JCheckBox("Move to another class", JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_MOVE_TO_ANOTHER_CLASS);
myMoveToAnotherClassCb.setMnemonic('m');
myMoveToAnotherClassCb.setFocusable(false);
left.add(myMoveToAnotherClassCb,
new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0),
0, 0));
return left;
}
private String getSelectedVisibility() {
if (myParentClass != null && myParentClass.isInterface()) {
return PsiModifier.PUBLIC;
}
String initialVisibility = JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY;
if (initialVisibility == null) {
initialVisibility = PsiModifier.PUBLIC;
}
return initialVisibility;
}
@Override
protected PsiVariable createFieldToStartTemplateOn(final String[] names, final PsiType psiType) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
return ApplicationManager.getApplication().runWriteAction(new Computable<PsiField>() {
@Override
public PsiField compute() {
PsiField field = elementFactory.createFieldFromText(
psiType.getCanonicalText() + " " + (getInputName() != null ? getInputName() : names[0]) + " = " + myInitializerText + ";",
myParentClass);
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true);
PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true);
final String visibility = getSelectedVisibility();
if (visibility != null) {
PsiUtil.setModifierProperty(field, visibility, true);
}
final PsiElement anchorElementIfAll = getAnchorElementIfAll();
PsiElement finalAnchorElement;
for (finalAnchorElement = anchorElementIfAll;
finalAnchorElement != null && finalAnchorElement.getParent() != myParentClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
field = BaseExpressionToFieldHandler.ConvertToFieldRunnable
.appendField(myExpr, BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, myParentClass, myParentClass, field, anchorMember);
myFieldRangeStart = myEditor.getDocument().createRangeMarker(field.getTextRange());
return field;
}
});
}
@Override
protected String[] suggestNames(PsiType defaultType, String propName) {
return IntroduceConstantDialog.createNameSuggestionGenerator(propName, myExpr != null && myExpr.isValid() ? myExpr : null, JavaCodeStyleManager.getInstance(myProject), null,
myParentClass)
.getSuggestedNameInfo(defaultType).names;
}
@Override
protected VariableKind getVariableKind() {
return VariableKind.STATIC_FINAL_FIELD;
}
@Override
public boolean isReplaceAllOccurrences() {
return myReplaceAllCb.isSelected();
}
@Override
public void setReplaceAllOccurrences(boolean allOccurrences) {
myReplaceAllCb.setSelected(allOccurrences);
}
@Override
protected void saveSettings(@NotNull PsiVariable psiVariable) {
super.saveSettings(psiVariable);
JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY = getSelectedVisibility();
}
@Override
protected boolean performRefactoring() {
JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_MOVE_TO_ANOTHER_CLASS = myMoveToAnotherClassCb.isSelected();
if (myMoveToAnotherClassCb.isSelected()) {
myEditor.putUserData(INTRODUCE_RESTART, true);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myEditor.putUserData(ACTIVE_INTRODUCE, InplaceIntroduceConstantPopup.this);
try {
final IntroduceConstantHandler constantHandler = new IntroduceConstantHandler();
final PsiLocalVariable localVariable = (PsiLocalVariable)getLocalVariable();
if (localVariable != null) {
constantHandler.invokeImpl(myProject, localVariable, myEditor);
}
else {
constantHandler.invokeImpl(myProject, myExpr, myEditor);
}
}
finally {
myEditor.putUserData(INTRODUCE_RESTART, false);
myEditor.putUserData(ACTIVE_INTRODUCE, null);
releaseResources();
if (myLocalMarker != null) {
myLocalMarker.dispose();
}
if (myExprMarker != null) {
myExprMarker.dispose();
}
}
}
});
return false;
}
return super.performRefactoring();
}
@Override
protected String getRefactoringId() {
return "refactoring.extractConstant";
}
@Override
protected boolean startsOnTheSameElement(RefactoringActionHandler handler, PsiElement element) {
return super.startsOnTheSameElement(handler, element) && handler instanceof IntroduceConstantHandler;
}
@Override
protected void performIntroduce() {
final BaseExpressionToFieldHandler.Settings settings =
new BaseExpressionToFieldHandler.Settings(getInputName(),
getExpr(),
getOccurrences(),
isReplaceAllOccurrences(), true,
true,
BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION,
getSelectedVisibility(), (PsiLocalVariable)getLocalVariable(),
getType(),
true,
myParentClass, false, false);
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
@Override
protected void run(Result result) throws Throwable {
if (getLocalVariable() != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, (PsiLocalVariable)getLocalVariable(), myParentClass, settings, true,
myOccurrences);
fieldRunnable.run();
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(),
myOccurrences, myOccurrenceManager,
getAnchorElementIfAll(), getAnchorElement(), myEditor, myParentClass);
convertToFieldRunnable.run();
}
}
}.execute();
}
@Override
protected JComponent getComponent() {
myReplaceAllCb.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
restartInplaceIntroduceTemplate();
}
});
return myWholePanel;
}
@Override
protected String getActionName() {
return "IntroduceConstant";
}
}