498920707874381bcc972599ac809f45c4610767
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / annotator / intentions / dynamic / ui / DynamicMethodDialog.java
1 /*
2  * Copyright 2000-2012 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui;
17
18 import com.intellij.psi.PsiType;
19 import com.intellij.util.IncorrectOperationException;
20 import com.intellij.util.ui.AbstractTableCellEditor;
21 import com.intellij.util.ui.ColumnInfo;
22 import com.intellij.util.ui.ListTableModel;
23 import org.jetbrains.plugins.groovy.GroovyBundle;
24 import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil;
25 import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.MyPair;
26 import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
27 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
28 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
29 import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
30
31 import javax.swing.*;
32 import javax.swing.event.CellEditorListener;
33 import javax.swing.event.ChangeEvent;
34 import javax.swing.table.TableColumn;
35 import java.awt.*;
36 import java.util.EventObject;
37 import java.util.List;
38
39 /**
40  * User: Dmitry.Krasilschikov
41  * Date: 18.02.2008
42  */
43 public class DynamicMethodDialog extends DynamicDialog {
44
45   public DynamicMethodDialog(GrReferenceExpression referenceExpression) {
46     super(referenceExpression, QuickfixUtil.createSettings(referenceExpression),
47           GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)referenceExpression.getParent()), true);
48     assert getSettings().isMethod();
49
50     final List<MyPair> pairs = getSettings().getPairs();
51     setupParameterTable(pairs);
52     setupParameterList(pairs);
53     setTitle(GroovyBundle.message("add.dynamic.method"));
54     setUpTypeLabel(GroovyBundle.message("dynamic.method.return.type"));
55   }
56
57   private void setupParameterTable(final List<MyPair> pairs) {
58
59     MySuggestedNameCellEditor suggestedNameCellEditor = new MySuggestedNameCellEditor(QuickfixUtil.getArgumentsNames(pairs));
60     myParametersTable.setDefaultEditor(String.class, suggestedNameCellEditor);
61
62     suggestedNameCellEditor.addCellEditorListener(new CellEditorListener() {
63       public void editingStopped(ChangeEvent e) {
64         final int editingColumn = myParametersTable.getSelectedColumn();
65         if (editingColumn != 0) return;
66
67         final int editingRow = myParametersTable.getSelectedRow();
68         if (editingRow < 0 || editingRow >= pairs.size()) return;
69
70         String newNameValue = ((MySuggestedNameCellEditor)e.getSource()).getCellEditorValue();
71
72         final MyPair editingPair = pairs.get(editingRow);
73         editingPair.setFirst(newNameValue);
74       }
75
76       public void editingCanceled(ChangeEvent e) {
77       }
78     });
79   }
80
81   private void setupParameterList(List<MyPair> arguments) {
82     final ListTableModel<MyPair> dataModel = new ListTableModel<MyPair>(new NameColumnInfo(), new TypeColumnInfo());
83     dataModel.setItems(arguments);
84     myParametersTable.setModel(dataModel);
85
86     if (arguments.isEmpty()) return;
87
88     String max0 = arguments.get(0).first;
89     String max1 = arguments.get(0).second;
90     for (MyPair argument : arguments) {
91       if (argument.first.length() > max0.length()) max0 = argument.first;
92       if (argument.second.length() > max1.length()) max1 = argument.second;
93     }
94
95     final FontMetrics metrics = myParametersTable.getFontMetrics(myParametersTable.getFont());
96     final TableColumn column0 = myParametersTable.getColumnModel().getColumn(0);
97     column0.setPreferredWidth(metrics.stringWidth(max0 + "  "));
98
99     final TableColumn column1 = myParametersTable.getColumnModel().getColumn(1);
100     column1.setPreferredWidth(metrics.stringWidth(max1 + "  "));
101   }
102
103
104   private class TypeColumnInfo extends ColumnInfo<MyPair, String> {
105     public TypeColumnInfo() {
106       super(GroovyBundle.message("dynamic.name"));
107     }
108
109     public String valueOf(MyPair pair) {
110       return pair.second;
111     }
112
113     public boolean isCellEditable(MyPair stringPsiTypeMyPair) {
114       return false;
115     }
116
117     public void setValue(MyPair pair, String value) {
118       PsiType type;
119       try {
120         type = GroovyPsiElementFactory.getInstance(myProject).createTypeElement(value).getType();
121       }
122       catch (IncorrectOperationException e) {
123         return;
124       }
125
126       if (type == null) return;
127       pair.setSecond(type.getCanonicalText());
128     }
129   }
130
131   private static class NameColumnInfo extends ColumnInfo<MyPair, String> {
132     public NameColumnInfo() {
133       super(GroovyBundle.message("dynamic.type"));
134     }
135
136     public boolean isCellEditable(MyPair myPair) {
137       return true;
138     }
139
140     public String valueOf(MyPair pair) {
141       return pair.first;
142     }
143   }
144
145   private static class MySuggestedNameCellEditor extends AbstractTableCellEditor {
146     JTextField myNameField;
147
148     public MySuggestedNameCellEditor(String[] names) {
149       myNameField = names.length == 0 ? new JTextField() : new JTextField(names[0]);
150     }
151
152     public String getCellEditorValue() {
153       return myNameField.getText();
154     }
155
156     public boolean isCellEditable(EventObject e) {
157       return true;
158     }
159
160     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
161       if (value instanceof String) {
162         myNameField.setText((String)value);
163       }
164       return myNameField;
165     }
166   }
167 }