org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui.DynamicDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui.DynamicDialog.java

Source

/*
 * 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 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.length() > 0) {
                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;
    }

    @Nullable
    protected JComponent createCenterPanel() {
        return myPanel;
    }

    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() {
            public void run() {
                UndoManager.getInstance(myProject).undoableActionPerformed(new GlobalUndoableAction(document) {
                    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().size() == 0 && classElement.getProperties().size() == 0) {
                            myDynamicManager.removeClassElement(classElement);
                        }
                    }

                    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();
    }

    public void doCancelAction() {
        super.doCancelAction();

        DaemonCodeAnalyzer.getInstance(myProject).restart();
    }

    public JComponent getPreferredFocusedComponent() {
        return myTypeComboBox;
    }

    protected void setUpTypeLabel(String typeLabelText) {
        myTypeLabel.setText(typeLabelText);
    }
}