22922f454dd7b7a99347a204b6ad1ffc241125e0
[idea/community.git] / plugins / ui-designer / src / com / intellij / uiDesigner / wizard / BeanStep.java
1 /*
2  * Copyright 2000-2009 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 com.intellij.uiDesigner.wizard;
17
18 import com.intellij.ide.util.ClassFilter;
19 import com.intellij.ide.util.PackageChooserDialog;
20 import com.intellij.ide.util.TreeClassChooser;
21 import com.intellij.ide.util.TreeClassChooserFactory;
22 import com.intellij.ide.wizard.CommitStepException;
23 import com.intellij.ide.wizard.StepAdapter;
24 import com.intellij.openapi.module.Module;
25 import com.intellij.openapi.module.ModuleUtil;
26 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
27 import com.intellij.openapi.util.Comparing;
28 import com.intellij.openapi.util.IconLoader;
29 import com.intellij.psi.*;
30 import com.intellij.psi.search.GlobalSearchScope;
31 import com.intellij.uiDesigner.UIDesignerBundle;
32 import org.jetbrains.annotations.NotNull;
33
34 import javax.swing.*;
35 import java.awt.event.ActionEvent;
36 import java.awt.event.ActionListener;
37 import java.awt.event.ItemEvent;
38 import java.awt.event.ItemListener;
39
40 /**
41  * @author Anton Katilin
42  * @author Vladimir Kondratyev
43  */
44 final class BeanStep extends StepAdapter{
45   private JPanel myComponent;
46   private TextFieldWithBrowseButton myTfWitgBtnChooseClass;
47   private JRadioButton myRbBindToNewBean;
48   private JRadioButton myRbBindToExistingBean;
49   JTextField myTfShortClassName;
50   private TextFieldWithBrowseButton myTfWithBtnChoosePackage;
51   private final WizardData myData;
52
53   public BeanStep(@NotNull final WizardData data) {
54     myData = data;
55
56     final ItemListener itemListener = new ItemListener() {
57       public void itemStateChanged(final ItemEvent e) {
58         final boolean state = myRbBindToNewBean.isSelected();
59
60         myTfShortClassName.setEnabled(state);
61         myTfWithBtnChoosePackage.setEnabled(state);
62
63         myTfWitgBtnChooseClass.setEnabled(!state);
64       }
65     };
66     myRbBindToNewBean.addItemListener(itemListener);
67     myRbBindToExistingBean.addItemListener(itemListener);
68
69     {
70       final ButtonGroup buttonGroup = new ButtonGroup();
71       buttonGroup.add(myRbBindToNewBean);
72       buttonGroup.add(myRbBindToExistingBean);
73     }
74
75     myTfWitgBtnChooseClass.addActionListener(
76       new ActionListener() {
77         public void actionPerformed(final ActionEvent e) {
78           final TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myData.myProject).createWithInnerClassesScopeChooser(
79             UIDesignerBundle.message("title.choose.bean.class"),
80             GlobalSearchScope.projectScope(myData.myProject),
81             new ClassFilter() {
82               public boolean isAccepted(final PsiClass aClass) {
83                 return aClass.getParent() instanceof PsiJavaFile;
84               }
85             },
86             null);
87           chooser.showDialog();
88           final PsiClass aClass = chooser.getSelected();
89           if (aClass == null) {
90             return;
91           }
92           final String fqName = aClass.getQualifiedName();
93           myTfWitgBtnChooseClass.setText(fqName);
94         }
95       }
96     );
97
98     myTfWithBtnChoosePackage.addActionListener(new ActionListener() {
99       public void actionPerformed(final ActionEvent e) {
100         final PackageChooserDialog dialog = new PackageChooserDialog(UIDesignerBundle.message("title.choose.package"), myData.myProject);
101         dialog.selectPackage(myTfWithBtnChoosePackage.getText());
102         dialog.show();
103         final PsiPackage aPackage = dialog.getSelectedPackage();
104         if (aPackage != null) {
105           myTfWithBtnChoosePackage.setText(aPackage.getQualifiedName());
106         }
107       }
108     });
109   }
110
111   public void _init() {
112     // Select way of binding
113     if(myData.myBindToNewBean){
114       myRbBindToNewBean.setSelected(true);
115     }
116     else{
117       myRbBindToExistingBean.setSelected(true);
118     }
119
120     // New bean
121     myTfShortClassName.setText(myData.myShortClassName);
122     myTfWithBtnChoosePackage.setText(myData.myPackageName);
123
124     // Existing bean
125     myTfWitgBtnChooseClass.setText(
126       myData.myBeanClass != null ? myData.myBeanClass.getQualifiedName() : null
127     );
128   }
129
130   private void resetBindings(){
131     for(int i = myData.myBindings.length - 1; i >= 0; i--){
132       myData.myBindings[i].myBeanProperty = null;
133     }
134   }
135
136   public void _commit(boolean finishChosen) throws CommitStepException{
137     final boolean newBindToNewBean = myRbBindToNewBean.isSelected();
138     if(myData.myBindToNewBean != newBindToNewBean){
139       resetBindings();
140     }
141
142     myData.myBindToNewBean = newBindToNewBean;
143
144     if(myData.myBindToNewBean){ // new bean
145       final String oldShortClassName = myData.myShortClassName;
146       final String oldPackageName = myData.myPackageName;
147
148       final String shortClassName = myTfShortClassName.getText().trim();
149       if(shortClassName.length() == 0){
150         throw new CommitStepException(UIDesignerBundle.message("error.please.specify.class.name.of.the.bean.to.be.created"));
151       }
152       final PsiManager psiManager = PsiManager.getInstance(myData.myProject);
153       if(!JavaPsiFacade.getInstance(psiManager.getProject()).getNameHelper().isIdentifier(shortClassName)){
154         throw new CommitStepException(UIDesignerBundle.message("error.X.is.not.a.valid.class.name", shortClassName));
155       }
156
157       final String packageName = myTfWithBtnChoosePackage.getText().trim();
158       if(packageName.length() != 0 && JavaPsiFacade.getInstance(psiManager.getProject()).findPackage(packageName) == null){
159         throw new CommitStepException(UIDesignerBundle.message("error.package.with.name.X.does.not.exist", packageName));
160       }
161
162       myData.myShortClassName = shortClassName;
163       myData.myPackageName = packageName;
164
165       // check whether new class already exists
166       {
167         final String fullClassName = packageName.length() != 0 ? packageName + "." + shortClassName : shortClassName;
168         final Module module = ModuleUtil.findModuleForFile(myData.myFormFile, myData.myProject);
169         if (JavaPsiFacade.getInstance(psiManager.getProject())
170           .findClass(fullClassName, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)) != null) {
171           throw new CommitStepException(UIDesignerBundle.message("error.cannot.create.class.X.because.it.already.exists", fullClassName));
172         }
173       }
174
175       if(
176         !Comparing.equal(oldShortClassName, shortClassName) ||
177         !Comparing.equal(oldPackageName, packageName)
178       ){
179         // After bean class changed we need to reset all previously set bindings
180         resetBindings();
181       }
182     }
183     else{ // existing bean
184       final String oldFqClassName = myData.myBeanClass != null ? myData.myBeanClass.getQualifiedName() : null;
185       final String newFqClassName = myTfWitgBtnChooseClass.getText().trim();
186       if(newFqClassName.length() == 0){
187         throw new CommitStepException(UIDesignerBundle.message("error.please.specify.fully.qualified.name.of.bean.class"));
188       }
189       final PsiClass aClass =
190         JavaPsiFacade.getInstance(myData.myProject).findClass(newFqClassName, GlobalSearchScope.allScope(myData.myProject));
191       if(aClass == null){
192         throw new CommitStepException(UIDesignerBundle.message("error.class.with.name.X.does.not.exist", newFqClassName));
193       }
194       myData.myBeanClass = aClass;
195
196       if(!Comparing.equal(oldFqClassName, newFqClassName)){
197         // After bean class changed we need to reset all previously set bindings
198         resetBindings();
199       }
200     }
201   }
202
203   public JComponent getComponent() {
204     return myComponent;
205   }
206
207   public Icon getIcon() {
208     return IconLoader.getIcon("/com/intellij/uiDesigner/icons/dataBinding.png");
209   }
210 }