cleanup
[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.event.TableModelEvent;
35 import javax.swing.event.TableModelListener;
36 import javax.swing.table.TableColumn;
37 import java.awt.*;
38 import java.util.EventObject;
39 import java.util.List;
40
41 /**
42  * User: Dmitry.Krasilschikov
43  * Date: 18.02.2008
44  */
45 public class DynamicMethodDialog extends DynamicDialog {
46
47   public DynamicMethodDialog(GrReferenceExpression referenceExpression) {
48     super(referenceExpression, QuickfixUtil.createSettings(referenceExpression), GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)referenceExpression.getParent()));
49     assert getSettings().isMethod();
50
51     final List<MyPair> pairs = getSettings().getPairs();
52     setupParameterTable(pairs);
53     setupParameterList(pairs);
54     setTitle(GroovyBundle.message("add.dynamic.method"));
55     setUpTypeLabel(GroovyBundle.message("dynamic.method.return.type"));
56   }
57
58   protected void setUpTableNameLabel(String text) {
59     super.setUpTableNameLabel(getSettings().getPairs().isEmpty() ? GroovyBundle.message("dynamic.properties.table.no.arguments") : text);
60   }
61
62   private void setupParameterTable(final List<MyPair> pairs) {
63     final JTable table = getParametersTable();
64
65     MySuggestedNameCellEditor suggestedNameCellEditor = new MySuggestedNameCellEditor(QuickfixUtil.getArgumentsNames(pairs));
66     table.setDefaultEditor(String.class, suggestedNameCellEditor);
67
68     suggestedNameCellEditor.addCellEditorListener(new CellEditorListener() {
69       public void editingStopped(ChangeEvent e) {
70         final int editingColumn = table.getSelectedColumn();
71         if (editingColumn != 0) return;
72
73         final int editingRow = table.getSelectedRow();
74         if (editingRow < 0 || editingRow >= pairs.size()) return;
75
76         String newNameValue = ((MySuggestedNameCellEditor)e.getSource()).getCellEditorValue();
77
78         final MyPair editingPair = pairs.get(editingRow);
79         editingPair.setFirst(newNameValue);
80       }
81
82       public void editingCanceled(ChangeEvent e) {
83       }
84     });
85   }
86
87   protected boolean isTableVisible() {
88     return true;
89   }
90
91   private void setupParameterList(List<MyPair> arguments) {
92     final JTable table = getParametersTable();
93
94     //TODO: add header
95     final ListTableModel<MyPair> dataModel = new ListTableModel<MyPair>(new NameColumnInfo(), new TypeColumnInfo());
96     dataModel.addTableModelListener(new TableModelListener() {
97       public void tableChanged(TableModelEvent e) {
98         fireDataChanged();
99       }
100     });
101     dataModel.setItems(arguments);
102     table.setModel(dataModel);
103     if (!arguments.isEmpty()) {
104       String max0 = arguments.get(0).first;
105       String max1 = arguments.get(0).second;
106       for (MyPair argument : arguments) {
107         if (argument.first.length() > max0.length()) max0 = argument.first;
108         if (argument.second.length() > max1.length()) max1 = argument.second;
109       }
110
111       final FontMetrics metrics = table.getFontMetrics(table.getFont());
112       final TableColumn column0 = table.getColumnModel().getColumn(0);
113       column0.setPreferredWidth(metrics.stringWidth(max0 + "  "));
114
115       final TableColumn column1 = table.getColumnModel().getColumn(1);
116       column1.setPreferredWidth(metrics.stringWidth(max1 + "  "));
117     }
118   }
119
120
121   private class TypeColumnInfo extends ColumnInfo<MyPair, String> {
122     public TypeColumnInfo() {
123       super(GroovyBundle.message("dynamic.name"));
124     }
125
126     public String valueOf(MyPair pair) {
127       return pair.second;
128     }
129
130     public boolean isCellEditable(MyPair stringPsiTypeMyPair) {
131       return false;
132     }
133
134     public void setValue(MyPair pair, String value) {
135       PsiType type;
136       try {
137         type = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(value).getType();
138       }
139       catch (IncorrectOperationException e) {
140         return;
141       }
142
143       if (type == null) return;
144       pair.setSecond(type.getCanonicalText());
145     }
146   }
147
148   private static class NameColumnInfo extends ColumnInfo<MyPair, String> {
149     public NameColumnInfo() {
150       super(GroovyBundle.message("dynamic.type"));
151     }
152
153     public boolean isCellEditable(MyPair myPair) {
154       return true;
155     }
156
157     public String valueOf(MyPair pair) {
158       return pair.first;
159     }
160   }
161
162   protected void updateOkStatus() {
163     super.updateOkStatus();
164
165     if (getParametersTable().isEditing()) setOKActionEnabled(false);
166   }
167
168   private static class MySuggestedNameCellEditor extends AbstractTableCellEditor {
169     JTextField myNameField;
170
171     public MySuggestedNameCellEditor(String[] names) {
172       myNameField = names.length == 0 ? new JTextField() : new JTextField(names[0]);
173     }
174
175     public String getCellEditorValue() {
176       return myNameField.getText();
177     }
178
179     public boolean isCellEditable(EventObject e) {
180       return true;
181     }
182
183     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
184       if (value instanceof String) {
185         myNameField.setText((String)value);
186       }
187       return myNameField;
188     }
189   }
190 }