update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / refactoring / extractMethodObject / ExtractMethodObjectDialog.java
blob9b600b7b934314d4975b8c3da888b15f22572f1f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.refactoring.extractMethodObject;
18 import com.intellij.openapi.editor.event.DocumentEvent;
19 import com.intellij.openapi.help.HelpManager;
20 import com.intellij.openapi.project.Project;
21 import com.intellij.openapi.util.text.StringUtil;
22 import com.intellij.openapi.wm.IdeFocusManager;
23 import com.intellij.psi.*;
24 import com.intellij.psi.util.PsiFormatUtil;
25 import com.intellij.refactoring.HelpID;
26 import com.intellij.refactoring.extractMethod.AbstractExtractDialog;
27 import com.intellij.refactoring.extractMethod.InputVariables;
28 import com.intellij.refactoring.ui.ConflictsDialog;
29 import com.intellij.refactoring.util.ParameterTablePanel;
30 import com.intellij.ui.EditorTextField;
31 import com.intellij.util.Function;
32 import com.intellij.util.VisibilityUtil;
33 import com.intellij.util.containers.MultiMap;
34 import com.intellij.util.ui.UIUtil;
35 import org.jetbrains.annotations.NonNls;
37 import javax.swing.*;
38 import java.awt.*;
39 import java.awt.event.ActionEvent;
40 import java.awt.event.ActionListener;
41 import java.util.Enumeration;
44 public class ExtractMethodObjectDialog extends AbstractExtractDialog {
45 private final Project myProject;
46 private final PsiType myReturnType;
47 private final PsiTypeParameterList myTypeParameterList;
48 private final PsiType[] myExceptions;
49 private final boolean myStaticFlag;
50 private final boolean myCanBeStatic;
51 private final PsiElement[] myElementsToExtract;
52 private final boolean myMultipleExitPoints;
54 private final InputVariables myVariableData;
55 private final PsiClass myTargetClass;
56 private boolean myWasStatic;
59 private JRadioButton myCreateInnerClassRb;
60 private JRadioButton myCreateAnonymousClassWrapperRb;
61 private JTextArea mySignatureArea;
62 private JCheckBox myCbMakeStatic;
63 private JCheckBox myCbMakeVarargs;
64 private JCheckBox myCbMakeVarargsAnonymous;
66 private JPanel myWholePanel;
67 private JPanel myParametersTableContainer;
68 private JRadioButton myPrivateRadioButton;
69 private JRadioButton myProtectedRadioButton;
70 private JRadioButton myPackageLocalRadioButton;
71 private JRadioButton myPublicRadioButton;
73 private EditorTextField myInnerClassName;
74 private EditorTextField myMethodName;
76 private JPanel myInnerClassPanel;
77 private JPanel myAnonymousClassPanel;
78 private JCheckBox myFoldCb;
79 private ButtonGroup myVisibilityGroup;
80 private ParameterTablePanel.VariableData[] myInputVariables;
83 public ExtractMethodObjectDialog(Project project, PsiClass targetClass, final InputVariables inputVariables, PsiType returnType,
84 PsiTypeParameterList typeParameterList, PsiType[] exceptions, boolean isStatic, boolean canBeStatic,
85 final PsiElement[] elementsToExtract, final boolean multipleExitPoints) {
86 super(project);
87 myProject = project;
88 myTargetClass = targetClass;
89 myReturnType = returnType;
90 myTypeParameterList = typeParameterList;
91 myExceptions = exceptions;
92 myStaticFlag = isStatic;
93 myCanBeStatic = canBeStatic;
94 myElementsToExtract = elementsToExtract;
95 myMultipleExitPoints = multipleExitPoints;
97 boolean canBeVarargs = false;
98 for (ParameterTablePanel.VariableData data : inputVariables.getInputVariables()) {
99 canBeVarargs |= data.type instanceof PsiArrayType;
101 canBeVarargs |= inputVariables.isFoldable() && inputVariables.isFoldingSelectedByDefault();
102 myWasStatic = canBeVarargs;
104 myVariableData = inputVariables;
106 setTitle(ExtractMethodObjectProcessor.REFACTORING_NAME);
108 // Create UI components
111 myCbMakeVarargs.setVisible(canBeVarargs);
112 myCbMakeVarargsAnonymous.setVisible(canBeVarargs);
114 // Initialize UI
115 init();
119 public boolean isMakeStatic() {
120 if (myStaticFlag) return true;
121 if (!myCanBeStatic) return false;
122 return myCbMakeStatic.isSelected();
125 public boolean isChainedConstructor() {
126 return false;
129 protected Action[] createActions() {
130 return new Action[]{getOKAction(), getCancelAction(), getHelpAction()};
133 public String getChosenMethodName() {
134 return myCreateInnerClassRb.isSelected() ? myInnerClassName.getText() : myMethodName.getText();
137 public ParameterTablePanel.VariableData[] getChosenParameters() {
138 return myInputVariables;
141 public JComponent getPreferredFocusedComponent() {
142 return myInnerClassName;
145 protected void doHelpAction() {
146 HelpManager.getInstance().invokeHelp(HelpID.EXTRACT_METHOD_OBJECT);
149 protected void doOKAction() {
150 MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
151 if (myCreateInnerClassRb.isSelected()) {
152 final PsiClass innerClass = myTargetClass.findInnerClassByName(myInnerClassName.getText(), false);
153 if (innerClass != null) {
154 conflicts.putValue(innerClass, "Inner class " + myInnerClassName.getText() + " already defined in class " + myTargetClass.getName());
157 if (conflicts.size() > 0) {
158 final ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, conflicts);
159 conflictsDialog.show();
160 if (!conflictsDialog.isOK()){
161 if (conflictsDialog.isShowConflicts()) close(CANCEL_EXIT_CODE);
162 return;
166 final JCheckBox makeVarargsCb = myCreateInnerClassRb.isSelected() ? myCbMakeVarargs : myCbMakeVarargsAnonymous;
167 if (makeVarargsCb != null && makeVarargsCb.isSelected()) {
168 final ParameterTablePanel.VariableData data = myInputVariables[myInputVariables.length - 1];
169 if (data.type instanceof PsiArrayType) {
170 data.type = new PsiEllipsisType(((PsiArrayType)data.type).getComponentType());
173 super.doOKAction();
176 private void updateVarargsEnabled() {
177 final boolean enabled = myInputVariables.length > 0 && myInputVariables[myInputVariables.length - 1].type instanceof PsiArrayType;
178 if (myCreateInnerClassRb.isSelected()) {
179 myCbMakeVarargs.setEnabled(enabled);
180 } else {
181 myCbMakeVarargsAnonymous.setEnabled(enabled);
185 private void update() {
186 myCbMakeStatic.setEnabled(myCanBeStatic && !myStaticFlag);
187 updateSignature();
188 final PsiNameHelper helper = JavaPsiFacade.getInstance(myProject).getNameHelper();
189 setOKActionEnabled((myCreateInnerClassRb.isSelected() && helper.isIdentifier(myInnerClassName.getText())) ||
190 (!myCreateInnerClassRb.isSelected() && helper.isIdentifier(myMethodName.getText())));
193 public String getVisibility() {
194 if (myPublicRadioButton.isSelected()) {
195 return PsiModifier.PUBLIC;
197 if (myPackageLocalRadioButton.isSelected()) {
198 return PsiModifier.PACKAGE_LOCAL;
200 if (myProtectedRadioButton.isSelected()) {
201 return PsiModifier.PROTECTED;
203 if (myPrivateRadioButton.isSelected()) {
204 return PsiModifier.PRIVATE;
206 return null;
210 protected JComponent createCenterPanel() {
211 mySignatureArea.setEditable(false);
212 myCreateInnerClassRb.setSelected(true);
213 enable(true);
214 final ActionListener enableDisableListener = new ActionListener() {
215 public void actionPerformed(final ActionEvent e) {
216 enable(myCreateInnerClassRb.isSelected());
219 myCreateInnerClassRb.addActionListener(enableDisableListener);
220 myCreateAnonymousClassWrapperRb.addActionListener(enableDisableListener);
221 myCreateAnonymousClassWrapperRb.setEnabled(!myMultipleExitPoints);
223 myFoldCb.setSelected(myVariableData.isFoldingSelectedByDefault());
224 myFoldCb.setVisible(myVariableData.isFoldable());
225 myVariableData.setFoldingAvailable(myFoldCb.isSelected());
226 myInputVariables = myVariableData.getInputVariables().toArray(new ParameterTablePanel.VariableData[myVariableData.getInputVariables().size()]);
227 myFoldCb.addActionListener(new ActionListener() {
228 public void actionPerformed(ActionEvent e) {
229 myVariableData.setFoldingAvailable(myFoldCb.isSelected());
230 myInputVariables = myVariableData.getInputVariables().toArray(new ParameterTablePanel.VariableData[myVariableData.getInputVariables().size()]);
231 myParametersTableContainer.removeAll();
232 myParametersTableContainer.add(createParametersPanel(), BorderLayout.CENTER);
233 updateSignature();
234 updateVarargsEnabled();
237 myParametersTableContainer.add(createParametersPanel(), BorderLayout.CENTER);
239 final ActionListener updateSugnatureListener = new ActionListener() {
240 public void actionPerformed(final ActionEvent e) {
241 updateSignature();
242 IdeFocusManager.getInstance(myProject).requestFocus(myCreateInnerClassRb.isSelected() ? myInnerClassName : myMethodName, false);
246 if (myStaticFlag || myCanBeStatic) {
247 myCbMakeStatic.setEnabled(!myStaticFlag);
248 myCbMakeStatic.setSelected(myStaticFlag);
250 myCbMakeStatic.addActionListener(updateSugnatureListener);
251 } else {
252 myCbMakeStatic.setSelected(false);
253 myCbMakeStatic.setEnabled(false);
256 updateVarargsEnabled();
258 myCbMakeVarargs.setSelected(myWasStatic);
259 myCbMakeVarargs.addActionListener(updateSugnatureListener);
261 myCbMakeVarargsAnonymous.setSelected(myWasStatic);
262 myCbMakeVarargsAnonymous.addActionListener(updateSugnatureListener);
264 final com.intellij.openapi.editor.event.DocumentAdapter nameListener = new com.intellij.openapi.editor.event.DocumentAdapter() {
265 @Override
266 public void documentChanged(final DocumentEvent e) {
267 update();
270 myInnerClassName.getDocument().addDocumentListener(nameListener);
271 myMethodName.getDocument().addDocumentListener(nameListener);
273 myPrivateRadioButton.setSelected(true);
275 myCreateInnerClassRb.addActionListener(updateSugnatureListener);
276 myCreateAnonymousClassWrapperRb.addActionListener(updateSugnatureListener);
278 final Enumeration<AbstractButton> visibilities = myVisibilityGroup.getElements();
279 while(visibilities.hasMoreElements()) {
280 visibilities.nextElement().addActionListener(updateSugnatureListener);
283 update();
285 return myWholePanel;
288 private void enable(boolean innerClassSelected){
289 UIUtil.setEnabled(myInnerClassPanel, innerClassSelected, true);
290 UIUtil.setEnabled(myAnonymousClassPanel, !innerClassSelected, true);
293 private JComponent createParametersPanel() {
294 return new ParameterTablePanel(myProject, myInputVariables, myElementsToExtract) {
295 protected void updateSignature() {
296 updateVarargsEnabled();
297 ExtractMethodObjectDialog.this.updateSignature();
300 protected void doEnterAction() {
301 clickDefaultButton();
304 protected void doCancelAction() {
305 ExtractMethodObjectDialog.this.doCancelAction();
308 protected boolean areTypesDirected() {
309 return true;
314 protected void updateSignature() {
315 if (mySignatureArea == null) return;
316 @NonNls StringBuffer buffer = getSignature();
317 mySignatureArea.setText(buffer.toString());
320 protected StringBuffer getSignature() {
321 final String INDENT = " ";
322 @NonNls StringBuffer buffer = new StringBuffer();
323 final String visibilityString = VisibilityUtil.getVisibilityString(getVisibility());
324 if (myCreateInnerClassRb.isSelected()) {
325 buffer.append(visibilityString);
326 if (buffer.length() > 0) {
327 buffer.append(" ");
329 if (isMakeStatic()) {
330 buffer.append("static ");
332 buffer.append("class ");
333 buffer.append(myInnerClassName.getText());
334 if (myTypeParameterList != null) {
335 buffer.append(myTypeParameterList.getText());
336 buffer.append(" ");
338 buffer.append("{\n");
339 buffer.append(INDENT);
340 buffer.append("public ");
341 buffer.append(myInnerClassName.getText());
342 methodSignature(INDENT, buffer);
343 buffer.append("\n}");
344 } else {
345 buffer.append("new Object(){\n");
346 buffer.append(INDENT);
347 buffer.append("private ");
348 buffer.append(PsiFormatUtil.formatType(myReturnType, 0, PsiSubstitutor.EMPTY));
349 buffer.append(" ");
350 buffer.append(myMethodName.getText());
351 methodSignature(INDENT, buffer);
352 buffer.append("\n}.");
353 buffer.append(myMethodName.getText());
354 buffer.append("(");
355 buffer.append(StringUtil.join(myInputVariables, new Function<ParameterTablePanel.VariableData, String>() {
356 public String fun(final ParameterTablePanel.VariableData variableData) {
357 return variableData.name;
359 }, ", "));
360 buffer.append(")");
363 return buffer;
366 private void methodSignature(final String INDENT, final StringBuffer buffer) {
367 buffer.append("(");
368 int count = 0;
369 final String indent = " ";
370 for (int i = 0; i < myInputVariables.length; i++) {
371 ParameterTablePanel.VariableData data = myInputVariables[i];
372 if (data.passAsParameter) {
373 //String typeAndModifiers = PsiFormatUtil.formatVariable(data.variable,
374 // PsiFormatUtil.SHOW_MODIFIERS | PsiFormatUtil.SHOW_TYPE);
375 PsiType type = data.type;
376 if (i == myInputVariables.length - 1 && type instanceof PsiArrayType && ((myCreateInnerClassRb.isSelected() && myCbMakeVarargs.isSelected()) || (myCreateAnonymousClassWrapperRb.isSelected() && myCbMakeVarargsAnonymous.isSelected()))) {
377 type = new PsiEllipsisType(((PsiArrayType)type).getComponentType());
380 String typeText = type.getPresentableText();
381 if (count > 0) {
382 buffer.append(", ");
384 buffer.append("\n");
385 buffer.append(indent);
386 buffer.append(typeText);
387 buffer.append(" ");
388 buffer.append(data.name);
389 count++;
392 buffer.append(")");
393 if (myExceptions.length > 0) {
394 buffer.append("\n");
395 buffer.append("throws\n");
396 for (PsiType exception : myExceptions) {
397 buffer.append(INDENT);
398 buffer.append(PsiFormatUtil.formatType(exception, 0, PsiSubstitutor.EMPTY));
399 buffer.append("\n");
402 buffer.append("{}");
405 public boolean createInnerClass() {
406 return myCreateInnerClassRb.isSelected();