/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.refactor.intoduceField; 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.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiField; import com.intellij.psi.PsiLocalVariable; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiType; import com.intellij.psi.PsiVariable; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.introduceField.AbstractInplaceIntroduceFieldPopup; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import com.intellij.refactoring.util.occurrences.OccurrenceManager; import gw.plugin.ij.refactor.GosuRenderFuction; 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; public class GosuInplaceIntroduceFieldPopup extends AbstractInplaceIntroduceFieldPopup { private final boolean myStatic; private final GosuIntroduceFieldPopupPanel myIntroduceFieldPanel; static GosuBaseExpressionToFieldHandler.InitializationPlace ourLastInitializerPlace; public GosuInplaceIntroduceFieldPopup(PsiLocalVariable localVariable, PsiClass parentClass, boolean aStatic, boolean currentMethodConstructor, PsiExpression[] occurrences, PsiExpression initializerExpression, TypeSelectorManagerImpl typeSelectorManager, Editor editor, final boolean allowInitInMethod, boolean allowInitInMethodIfAll, final PsiElement anchorElement, final PsiElement anchorElementIfAll, final OccurrenceManager occurrenceManager, Project project) { super(project, editor, initializerExpression, localVariable, occurrences, typeSelectorManager, IntroduceFieldHandler.REFACTORING_NAME, parentClass, anchorElement, occurrenceManager, anchorElementIfAll); myStatic = aStatic; myIntroduceFieldPanel = new GosuIntroduceFieldPopupPanel(parentClass, initializerExpression, localVariable, currentMethodConstructor, localVariable != null, aStatic, myOccurrences, allowInitInMethod, allowInitInMethodIfAll, typeSelectorManager); final GridBagConstraints constraints = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0); myWholePanel.add(getPreviewComponent(), constraints); final JComponent centerPanel = myIntroduceFieldPanel.createCenterPanel(); myWholePanel.add(centerPanel, constraints); myIntroduceFieldPanel.initializeControls(initializerExpression, ourLastInitializerPlace); } protected PsiField createFieldToStartTemplateOn(final String[] names, final PsiType defaultType) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); return ApplicationManager.getApplication().runWriteAction(new Computable<PsiField>() { @Override public PsiField compute() { PsiField field = elementFactory.createField(getInputName() != null ? getInputName() : names[0], defaultType); field = (PsiField) myParentClass.add(field); if (myExprText != null) { updateInitializer(elementFactory, field); } PsiUtil.setModifierProperty(field, PsiModifier.FINAL, myIntroduceFieldPanel.isDeclareFinal()); final String visibility = myIntroduceFieldPanel.getFieldVisibility(); if (visibility != null) { PsiUtil.setModifierProperty(field, visibility, true); } myFieldRangeStart = myEditor.getDocument().createRangeMarker(field.getTextRange()); return field; } }); } @Override protected String[] suggestNames(PsiType defaultType, String propName) { return suggestFieldName(defaultType, (PsiLocalVariable) getLocalVariable(), myExpr, myStatic, myParentClass).names; } @Override protected VariableKind getVariableKind() { return VariableKind.FIELD; } public static SuggestedNameInfo suggestFieldName(@Nullable PsiType defaultType, @Nullable final PsiLocalVariable localVariable, final PsiExpression initializer, final boolean forStatic, @NotNull final PsiClass parentClass) { return GosuIntroduceFieldDialog. createGenerator(forStatic, localVariable, initializer, localVariable != null, null, parentClass). getSuggestedNameInfo(defaultType); } public void setReplaceAllOccurrences(boolean replaceAllOccurrences) { myIntroduceFieldPanel.setReplaceAllOccurrences(replaceAllOccurrences); } @Override protected void updateTitle(@Nullable PsiVariable variable, String value) { if (variable == null || !variable.hasInitializer()) { super.updateTitle(variable, value); } else { final PsiExpression initializer = variable.getInitializer(); assert initializer != null; String text = variable.getText().replace(variable.getName(), value); text = text.replace(initializer.getText(), GosuRenderFuction.render(initializer)); setPreviewText(text); revalidate(); } } @Override protected void updateTitle(@Nullable PsiVariable variable) { if (variable != null) { updateTitle(variable, variable.getName()); } } public void setVisibility(String visibility) { myIntroduceFieldPanel.setVisibility(visibility); } @Override public boolean isReplaceAllOccurrences() { return myIntroduceFieldPanel.isReplaceAllOccurrences(); } @Override protected void saveSettings(@NotNull PsiVariable psiVariable) { super.saveSettings(psiVariable); JavaRefactoringSettings.getInstance().INTRODUCE_FIELD_VISIBILITY = myIntroduceFieldPanel.getFieldVisibility(); myIntroduceFieldPanel.saveFinalState(); } @Override protected JComponent getComponent() { myIntroduceFieldPanel.addOccurrenceListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { restartInplaceIntroduceTemplate(); } }); return myWholePanel; } private void updateInitializer(PsiElementFactory elementFactory, PsiField variable) { if (variable != null) { if (myIntroduceFieldPanel.getInitializerPlace() == GosuBaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION) { variable.setInitializer(elementFactory.createExpressionFromText(myExprText, variable)); } else { variable.setInitializer(null); } } } @Override protected String getActionName() { return "IntroduceField"; } public GosuBaseExpressionToFieldHandler.InitializationPlace getInitializerPlace() { return myIntroduceFieldPanel.getInitializerPlace(); } protected void performIntroduce() { ourLastInitializerPlace = myIntroduceFieldPanel.getInitializerPlace(); final GosuBaseExpressionToFieldHandler.Settings settings = new GosuBaseExpressionToFieldHandler.Settings(getInputName(), getExpr(), getOccurrences(), myIntroduceFieldPanel.isReplaceAllOccurrences(), myStatic, myIntroduceFieldPanel.isDeclareFinal(), myIntroduceFieldPanel.getInitializerPlace(), myIntroduceFieldPanel.getFieldVisibility(), (PsiLocalVariable) getLocalVariable(), getType(), myIntroduceFieldPanel.isDeleteVariable(), myParentClass, false, false); new WriteCommandAction(myProject, getCommandName(), getCommandName()) { @Override protected void run(Result result) throws Throwable { if (getLocalVariable() != null) { final GosuLocalToFieldHandler.IntroduceFieldRunnable fieldRunnable = new GosuLocalToFieldHandler.IntroduceFieldRunnable(false, (PsiLocalVariable) getLocalVariable(), myParentClass, settings, myStatic, myOccurrences); fieldRunnable.run(); } else { final GosuBaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable = new GosuBaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(), myOccurrences, myOccurrenceManager, getAnchorElementIfAll(), getAnchorElement(), myEditor, myParentClass); convertToFieldRunnable.run(); } } }.execute(); } }