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