| /* |
| * Copyright 2000-2014 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 org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui; |
| |
| import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; |
| import com.intellij.openapi.command.CommandProcessor; |
| import com.intellij.openapi.command.undo.GlobalUndoableAction; |
| import com.intellij.openapi.command.undo.UndoManager; |
| import com.intellij.openapi.command.undo.UnexpectedUndoException; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.Document; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.openapi.ui.Messages; |
| import com.intellij.openapi.ui.ValidationInfo; |
| import com.intellij.psi.*; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.psi.search.ProjectScope; |
| import com.intellij.ui.EditorComboBoxEditor; |
| import com.intellij.ui.IdeBorderFactory; |
| import com.intellij.ui.table.JBTable; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.Nullable; |
| import org.jetbrains.plugins.groovy.GroovyBundle; |
| import org.jetbrains.plugins.groovy.GroovyFileType; |
| import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil; |
| import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicManager; |
| import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ParamInfo; |
| import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.elements.DClassElement; |
| import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.elements.DItemElement; |
| import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; |
| import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; |
| import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; |
| import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; |
| import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; |
| import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; |
| import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; |
| |
| import javax.swing.*; |
| import java.util.List; |
| |
| /** |
| * User: Dmitry.Krasilschikov |
| * Date: 18.12.2007 |
| */ |
| public abstract class DynamicDialog extends DialogWrapper { |
| private static final Logger LOG = Logger.getInstance(DynamicDialog.class); |
| |
| private JComboBox myClassComboBox; |
| private JPanel myPanel; |
| private JComboBox myTypeComboBox; |
| private JLabel myTypeLabel; |
| protected JBTable myParametersTable; |
| private JCheckBox myStaticCheckBox; |
| private JPanel myTablePane; |
| |
| private final DynamicManager myDynamicManager; |
| protected final Project myProject; |
| private final PsiElement myContext; |
| private final DynamicElementSettings mySettings; |
| |
| public DynamicDialog(PsiElement context, DynamicElementSettings settings, TypeConstraint[] typeConstraints, boolean isTableVisible) { |
| super(context.getProject(), true); |
| myProject = context.getProject(); |
| mySettings = settings; |
| myContext = context; |
| myDynamicManager = DynamicManager.getInstance(myProject); |
| |
| if (isTableVisible) { |
| myTablePane.setBorder(IdeBorderFactory.createTitledBorder(GroovyBundle.message("dynamic.properties.table.name"), false)); |
| } |
| else { |
| myTablePane.setVisible(false); |
| } |
| |
| setTitle(GroovyInspectionBundle.message("dynamic.element")); |
| setUpTypeComboBox(typeConstraints); |
| setUpContainingClassComboBox(); |
| setUpStaticComboBox(); |
| |
| init(); |
| } |
| |
| private void setUpStaticComboBox() { |
| myStaticCheckBox.setSelected(mySettings.isStatic()); |
| } |
| |
| public DynamicElementSettings getSettings() { |
| return mySettings; |
| } |
| |
| @Override |
| protected ValidationInfo doValidate() { |
| final GrTypeElement typeElement = getEnteredTypeName(); |
| if (typeElement == null) { |
| return new ValidationInfo(GroovyInspectionBundle.message("no.type.specified"), myTypeComboBox); |
| } |
| |
| final PsiType type = typeElement.getType(); |
| if (type instanceof PsiClassType && ((PsiClassType)type).resolve() == null) { |
| return new ValidationInfo(GroovyInspectionBundle.message("unresolved.type.status", type.getPresentableText()), myTypeComboBox); |
| } |
| return null; |
| } |
| |
| private void setUpContainingClassComboBox() { |
| String containingClassName = mySettings.getContainingClassName(); |
| PsiClass targetClass = JavaPsiFacade.getInstance(myProject).findClass(containingClassName, GlobalSearchScope.allScope(myProject)); |
| if (targetClass == null || targetClass instanceof SyntheticElement) { |
| if (!containingClassName.isEmpty()) { |
| myClassComboBox.addItem(containingClassName); |
| } |
| |
| if (!containingClassName.equals(CommonClassNames.JAVA_LANG_OBJECT)) { |
| myClassComboBox.addItem(CommonClassNames.JAVA_LANG_OBJECT); |
| } |
| |
| return; |
| } |
| |
| for (PsiClass aClass : PsiUtil.iterateSupers(targetClass, true)) { |
| myClassComboBox.addItem(aClass.getQualifiedName()); |
| } |
| } |
| |
| @Nullable |
| private Document createDocument(final String text) { |
| GroovyCodeFragment fragment = new GroovyCodeFragment(myProject, text); |
| fragment.setContext(myContext); |
| return PsiDocumentManager.getInstance(myProject).getDocument(fragment); |
| } |
| |
| private void setUpTypeComboBox(TypeConstraint[] typeConstraints) { |
| final EditorComboBoxEditor comboEditor = new EditorComboBoxEditor(myProject, GroovyFileType.GROOVY_FILE_TYPE); |
| |
| final Document document = createDocument(""); |
| LOG.assertTrue(document != null); |
| |
| comboEditor.setItem(document); |
| |
| myTypeComboBox.setEditor(comboEditor); |
| myTypeComboBox.setEditable(true); |
| myTypeComboBox.grabFocus(); |
| |
| PsiType type = typeConstraints.length == 1 ? typeConstraints[0].getDefaultType() : TypesUtil.getJavaLangObject(myContext); |
| myTypeComboBox.getEditor().setItem(createDocument(type.getCanonicalText())); |
| } |
| |
| @Nullable |
| public GrTypeElement getEnteredTypeName() { |
| final Document typeEditorDocument = getTypeEditorDocument(); |
| |
| if (typeEditorDocument == null) return null; |
| try { |
| return GroovyPsiElementFactory.getInstance(myProject).createTypeElement(typeEditorDocument.getText()); |
| } |
| catch (IncorrectOperationException e) { |
| return null; |
| } |
| } |
| |
| @Nullable |
| public Document getTypeEditorDocument() { |
| final Object item = myTypeComboBox.getEditor().getItem(); |
| |
| return item instanceof Document ? (Document)item : null; |
| } |
| |
| @Override |
| @Nullable |
| protected JComponent createCenterPanel() { |
| return myPanel; |
| } |
| |
| @Override |
| protected void doOKAction() { |
| super.doOKAction(); |
| |
| mySettings.setContainingClassName((String)myClassComboBox.getSelectedItem()); |
| mySettings.setStatic(myStaticCheckBox.isSelected()); |
| GrTypeElement typeElement = getEnteredTypeName(); |
| |
| if (typeElement == null) { |
| mySettings.setType(CommonClassNames.JAVA_LANG_OBJECT); |
| } |
| else { |
| PsiType type = typeElement.getType(); |
| if (type instanceof PsiPrimitiveType) { |
| type = TypesUtil.boxPrimitiveType(type, typeElement.getManager(), ProjectScope.getAllScope(myProject)); |
| } |
| |
| final String typeQualifiedName = type.getCanonicalText(); |
| |
| if (typeQualifiedName != null) { |
| mySettings.setType(typeQualifiedName); |
| } |
| else { |
| mySettings.setType(type.getPresentableText()); |
| } |
| } |
| |
| final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myContext.getContainingFile()); |
| |
| CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { |
| @Override |
| public void run() { |
| UndoManager.getInstance(myProject).undoableActionPerformed(new GlobalUndoableAction(document) { |
| @Override |
| public void undo() throws UnexpectedUndoException { |
| |
| final DItemElement itemElement; |
| if (mySettings.isMethod()) { |
| final List<ParamInfo> myPairList = mySettings.getParams(); |
| final String[] argumentsTypes = QuickfixUtil.getArgumentsTypes(myPairList); |
| itemElement = |
| myDynamicManager.findConcreteDynamicMethod(mySettings.getContainingClassName(), mySettings.getName(), argumentsTypes); |
| } |
| else { |
| itemElement = myDynamicManager.findConcreteDynamicProperty(mySettings.getContainingClassName(), mySettings.getName()); |
| } |
| |
| if (itemElement == null) { |
| Messages.showWarningDialog(myProject, GroovyInspectionBundle.message("Cannot.perform.undo.operation"), |
| GroovyInspectionBundle.message("Undo.disable")); |
| return; |
| } |
| final DClassElement classElement = myDynamicManager.getClassElementByItem(itemElement); |
| |
| if (classElement == null) { |
| Messages.showWarningDialog(myProject, GroovyInspectionBundle.message("Cannot.perform.undo.operation"), |
| GroovyInspectionBundle.message("Undo.disable")); |
| return; |
| } |
| |
| removeElement(itemElement); |
| |
| if (classElement.getMethods().isEmpty() && classElement.getProperties().isEmpty()) { |
| myDynamicManager.removeClassElement(classElement); |
| } |
| } |
| |
| @Override |
| public void redo() throws UnexpectedUndoException { |
| addElement(mySettings); |
| } |
| }); |
| |
| addElement(mySettings); |
| } |
| }, "Add dynamic element", null); |
| } |
| |
| private void removeElement(DItemElement itemElement) { |
| myDynamicManager.removeItemElement(itemElement); |
| myDynamicManager.fireChange(); |
| } |
| |
| public void addElement(final DynamicElementSettings settings) { |
| if (settings.isMethod()) { |
| myDynamicManager.addMethod(settings); |
| } |
| else { |
| myDynamicManager.addProperty(settings); |
| } |
| |
| myDynamicManager.fireChange(); |
| } |
| |
| @Override |
| public void doCancelAction() { |
| super.doCancelAction(); |
| |
| DaemonCodeAnalyzer.getInstance(myProject).restart(); |
| } |
| |
| @Override |
| public JComponent getPreferredFocusedComponent() { |
| return myTypeComboBox; |
| } |
| |
| protected void setUpTypeLabel(String typeLabelText) { |
| myTypeLabel.setText(typeLabelText); |
| } |
| } |