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
.wrapreturnvalue
;
18 import com
.intellij
.ide
.util
.TreeClassChooser
;
19 import com
.intellij
.ide
.util
.TreeClassChooserFactory
;
20 import com
.intellij
.openapi
.help
.HelpManager
;
21 import com
.intellij
.openapi
.options
.ConfigurationException
;
22 import com
.intellij
.openapi
.project
.Project
;
23 import com
.intellij
.openapi
.util
.Iconable
;
24 import com
.intellij
.openapi
.util
.text
.StringUtil
;
25 import com
.intellij
.psi
.*;
26 import com
.intellij
.psi
.search
.GlobalSearchScope
;
27 import com
.intellij
.psi
.util
.TypeConversionUtil
;
28 import com
.intellij
.refactoring
.HelpID
;
29 import com
.intellij
.refactoring
.RefactorJBundle
;
30 import com
.intellij
.refactoring
.RefactoringBundle
;
31 import com
.intellij
.refactoring
.ui
.PackageNameReferenceEditorCombo
;
32 import com
.intellij
.refactoring
.ui
.RefactoringDialog
;
33 import com
.intellij
.ui
.DocumentAdapter
;
34 import com
.intellij
.ui
.ReferenceEditorComboWithBrowseButton
;
35 import com
.intellij
.util
.ui
.UIUtil
;
36 import org
.jetbrains
.annotations
.NotNull
;
39 import javax
.swing
.event
.DocumentEvent
;
40 import javax
.swing
.event
.DocumentListener
;
42 import java
.awt
.event
.ActionEvent
;
43 import java
.awt
.event
.ActionListener
;
45 @SuppressWarnings({"OverridableMethodCallInConstructor"})
46 class WrapReturnValueDialog
extends RefactoringDialog
{
48 private final PsiMethod sourceMethod
;
49 private JTextField sourceMethodTextField
;
51 private JRadioButton createNewClassButton
;
52 private JTextField classNameField
;
53 private PackageNameReferenceEditorCombo packageTextField
;
54 private JPanel myNewClassPanel
;
56 private ReferenceEditorComboWithBrowseButton existingClassField
;
57 private JRadioButton useExistingClassButton
;
58 private JComboBox myFieldsCombo
;
59 private JPanel myExistingClassPanel
;
61 private JPanel myWholePanel
;
63 private JRadioButton myCreateInnerClassButton
;
64 private JTextField myInnerClassNameTextField
;
65 private JPanel myCreateInnerPanel
;
66 private static final String RECENT_KEYS
= "WrapReturnValue.RECENT_KEYS";
68 WrapReturnValueDialog(PsiMethod sourceMethod
) {
69 super(sourceMethod
.getProject(), true);
70 this.sourceMethod
= sourceMethod
;
71 setTitle(RefactorJBundle
.message("wrap.return.value.title"));
75 protected String
getDimensionServiceKey() {
76 return "RefactorJ.WrapReturnValue";
79 protected void doAction() {
80 final boolean useExistingClass
= useExistingClassButton
.isSelected();
81 final boolean createInnerClass
= myCreateInnerClassButton
.isSelected();
82 final String existingClassName
= existingClassField
.getText().trim();
83 final String className
;
84 final String packageName
;
85 if (useExistingClass
) {
86 className
= StringUtil
.getShortName(existingClassName
);
87 packageName
= StringUtil
.getPackageName(existingClassName
);
89 else if (createInnerClass
) {
90 className
= getInnerClassName();
94 className
= getClassName();
95 packageName
= getPackageName();
98 new WrapReturnValueProcessor(className
, packageName
, sourceMethod
, useExistingClass
, createInnerClass
, (PsiField
)myFieldsCombo
.getSelectedItem()));
102 protected void canRun() throws ConfigurationException
{
103 final Project project
= sourceMethod
.getProject();
104 final JavaPsiFacade manager
= JavaPsiFacade
.getInstance(project
);
105 final PsiNameHelper nameHelper
= manager
.getNameHelper();
106 if (myCreateInnerClassButton
.isSelected()) {
107 final String innerClassName
= getInnerClassName().trim();
108 if (!nameHelper
.isIdentifier(innerClassName
)) throw new ConfigurationException("\'" + StringUtil
.first(innerClassName
, 10, true) + "\' is invalid inner class name");
109 if (sourceMethod
.getContainingClass().findInnerClassByName(innerClassName
, false) != null) throw new ConfigurationException("Inner class with name \'" + StringUtil
.first(innerClassName
, 10, true) + "\' already exist");
110 } else if (useExistingClassButton
.isSelected()) {
111 final String className
= existingClassField
.getText().trim();
112 if (className
.length() == 0 || !nameHelper
.isQualifiedName(className
)) {
113 throw new ConfigurationException("\'" + StringUtil
.last(className
, 10, true) + "\' is invalid qualified wrapper class name");
115 final Object item
= myFieldsCombo
.getSelectedItem();
117 throw new ConfigurationException("Wrapper field not found");
120 final String className
= getClassName();
121 if (className
.length() == 0 || !nameHelper
.isIdentifier(className
)) {
122 throw new ConfigurationException("\'" + StringUtil
.first(className
, 10, true) + "\' is invalid wrapper class name");
124 final String packageName
= getPackageName();
126 if (packageName
.length() == 0 || !nameHelper
.isQualifiedName(packageName
)) {
127 throw new ConfigurationException("\'" + StringUtil
.last(packageName
, 10, true) + "\' is invalid wrapper class package name");
132 private String
getInnerClassName() {
133 return myInnerClassNameTextField
.getText().trim();
137 public String
getPackageName() {
138 return packageTextField
.getText().trim();
142 public String
getClassName() {
143 return classNameField
.getText().trim();
146 protected JComponent
createCenterPanel() {
147 sourceMethodTextField
.setEditable(false);
149 final DocumentListener docListener
= new DocumentAdapter() {
150 protected void textChanged(final DocumentEvent e
) {
155 classNameField
.getDocument().addDocumentListener(docListener
);
156 myFieldsCombo
.addActionListener(new ActionListener() {
157 public void actionPerformed(final ActionEvent e
) {
161 myInnerClassNameTextField
.getDocument().addDocumentListener(docListener
);
163 final PsiFile file
= sourceMethod
.getContainingFile();
164 if (file
instanceof PsiJavaFile
) {
165 final String packageName
= ((PsiJavaFile
)file
).getPackageName();
166 packageTextField
.setText(packageName
);
169 final PsiClass containingClass
= sourceMethod
.getContainingClass();
170 final String containingClassName
= containingClass
instanceof PsiAnonymousClass ?
"Anonymous " + ((PsiAnonymousClass
)containingClass
).getBaseClassType().getClassName() : containingClass
.getName();
171 final String sourceMethodName
= sourceMethod
.getName();
172 sourceMethodTextField
.setText(containingClassName
+ '.' + sourceMethodName
);
173 final ButtonGroup buttonGroup
= new ButtonGroup();
174 buttonGroup
.add(useExistingClassButton
);
175 buttonGroup
.add(createNewClassButton
);
176 buttonGroup
.add(myCreateInnerClassButton
);
177 createNewClassButton
.setSelected(true);
178 final ActionListener enableListener
= new ActionListener() {
179 public void actionPerformed(ActionEvent actionEvent
) {
180 toggleRadioEnablement();
183 useExistingClassButton
.addActionListener(enableListener
);
184 createNewClassButton
.addActionListener(enableListener
);
185 myCreateInnerClassButton
.addActionListener(enableListener
);
186 toggleRadioEnablement();
188 final DefaultComboBoxModel model
= new DefaultComboBoxModel();
189 myFieldsCombo
.setModel(model
);
190 myFieldsCombo
.setRenderer(new DefaultListCellRenderer(){
192 public Component
getListCellRendererComponent(final JList list
,
195 final boolean isSelected
,
196 final boolean cellHasFocus
) {
197 final Component rendererComponent
= super.getListCellRendererComponent(list
, value
, index
, isSelected
, cellHasFocus
);
198 if (value
instanceof PsiField
) {
199 final PsiField field
= (PsiField
)value
;
200 setText(field
.getName());
201 setIcon(field
.getIcon(Iconable
.ICON_FLAG_VISIBILITY
));
203 return rendererComponent
;
206 existingClassField
.getChildComponent().getDocument().addDocumentListener(new com
.intellij
.openapi
.editor
.event
.DocumentAdapter() {
208 public void documentChanged(com
.intellij
.openapi
.editor
.event
.DocumentEvent e
) {
209 final PsiClass currentClass
= JavaPsiFacade
.getInstance(myProject
).findClass(existingClassField
.getText(), GlobalSearchScope
.allScope(myProject
));
210 if (currentClass
!= null) {
211 model
.removeAllElements();
212 for (PsiField field
: currentClass
.getFields()) {
213 final PsiType returnType
= sourceMethod
.getReturnType();
214 assert returnType
!= null;
215 if (TypeConversionUtil
.isAssignable(field
.getType(), returnType
)) {
216 model
.addElement(field
);
225 private void toggleRadioEnablement() {
226 UIUtil
.setEnabled(myExistingClassPanel
, useExistingClassButton
.isSelected(), true);
227 UIUtil
.setEnabled(myNewClassPanel
, createNewClassButton
.isSelected(), true);
228 UIUtil
.setEnabled(myCreateInnerPanel
, myCreateInnerClassButton
.isSelected(), true);
233 public JComponent
getPreferredFocusedComponent() {
234 return classNameField
;
237 protected void doHelpAction() {
238 HelpManager
.getInstance().invokeHelp(HelpID
.WrapReturnValue
);
241 private void createUIComponents() {
242 final com
.intellij
.openapi
.editor
.event
.DocumentAdapter adapter
= new com
.intellij
.openapi
.editor
.event
.DocumentAdapter() {
243 public void documentChanged(com
.intellij
.openapi
.editor
.event
.DocumentEvent e
) {
249 new PackageNameReferenceEditorCombo("", myProject
, RECENT_KEYS
, RefactoringBundle
.message("choose.destination.package"));
250 packageTextField
.getChildComponent().getDocument().addDocumentListener(adapter
);
252 existingClassField
= new ReferenceEditorComboWithBrowseButton(new ActionListener() {
253 public void actionPerformed(ActionEvent e
) {
254 final TreeClassChooser chooser
= TreeClassChooserFactory
.getInstance(getProject())
255 .createWithInnerClassesScopeChooser(RefactorJBundle
.message("select.wrapper.class"), GlobalSearchScope
.allScope(myProject
), null, null);
256 final String classText
= existingClassField
.getText();
257 final PsiClass currentClass
= JavaPsiFacade
.getInstance(myProject
).findClass(classText
, GlobalSearchScope
.allScope(myProject
));
258 if (currentClass
!= null) {
259 chooser
.selectClass(currentClass
);
261 chooser
.showDialog();
262 final PsiClass selectedClass
= chooser
.getSelectedClass();
263 if (selectedClass
!= null) {
264 existingClassField
.setText(selectedClass
.getQualifiedName());
267 }, "", PsiManager
.getInstance(myProject
), true, RECENT_KEYS
);
268 existingClassField
.getChildComponent().getDocument().addDocumentListener(adapter
);