update copyright
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / palette / ComponentItemDialog.java
blob1437744be915acb10e0de95da9017406bd7612a5
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.uiDesigner.palette;
18 import com.intellij.CommonBundle;
19 import com.intellij.ide.util.TreeClassChooser;
20 import com.intellij.ide.util.TreeClassChooserFactory;
21 import com.intellij.ide.util.TreeFileChooser;
22 import com.intellij.openapi.editor.Document;
23 import com.intellij.openapi.fileTypes.StdFileTypes;
24 import com.intellij.openapi.help.HelpManager;
25 import com.intellij.openapi.module.ResourceFileUtil;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.ui.ComponentWithBrowseButton;
28 import com.intellij.openapi.ui.DialogWrapper;
29 import com.intellij.openapi.ui.Messages;
30 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
31 import com.intellij.openapi.vfs.VirtualFile;
32 import com.intellij.psi.*;
33 import com.intellij.psi.search.GlobalSearchScope;
34 import com.intellij.psi.search.ProjectScope;
35 import com.intellij.psi.util.InheritanceUtil;
36 import com.intellij.psi.util.PsiTreeUtil;
37 import com.intellij.ui.DocumentAdapter;
38 import com.intellij.ui.EditorTextField;
39 import com.intellij.uiDesigner.FormEditingUtil;
40 import com.intellij.uiDesigner.ImageFileFilter;
41 import com.intellij.uiDesigner.UIDesignerBundle;
42 import com.intellij.uiDesigner.compiler.Utils;
43 import com.intellij.uiDesigner.core.GridConstraints;
44 import com.intellij.uiDesigner.lw.LwRootContainer;
45 import org.jetbrains.annotations.NotNull;
47 import javax.swing.*;
48 import javax.swing.event.ChangeEvent;
49 import javax.swing.event.ChangeListener;
50 import javax.swing.event.DocumentEvent;
51 import java.awt.*;
52 import java.awt.event.ActionEvent;
53 import java.awt.event.ActionListener;
54 import java.awt.event.ItemEvent;
55 import java.awt.event.ItemListener;
56 import java.util.ArrayList;
58 /**
59 * @author Vladimir Kondratyev
61 public final class ComponentItemDialog extends DialogWrapper {
62 private JPanel myPanel;
63 private final ComponentWithBrowseButton<EditorTextField> myTfClassName;
64 private final Project myProject;
65 private final ComponentItem myItemToBeEdited;
66 private final boolean myOneOff;
67 private JLabel myLblIcon;
68 private TextFieldWithBrowseButton myTfIconPath;
69 private JCheckBox myChkHorCanShrink;
70 private JCheckBox myChkHorCanGrow;
71 private JCheckBox myChkHorWantGrow;
72 private JCheckBox myChkVerCanShrink;
73 private JCheckBox myChkVerCanGrow;
74 private JCheckBox myChkVerWantGrow;
75 private JPanel myClassNamePlaceholder;
76 private JRadioButton myClassRadioButton;
77 private JRadioButton myNestedFormRadioButton;
78 private TextFieldWithBrowseButton myTfNestedForm;
79 private JCheckBox myAutoCreateBindingCheckbox;
80 private JCheckBox myCanAttachLabelCheckbox;
81 private JPanel myHSizePolicyPanel;
82 private JPanel myVSizePolicyPanel;
83 private JComboBox myGroupComboBox;
84 private JLabel myGroupLabel;
85 private JCheckBox myIsContainerCheckBox;
86 private JLabel myErrorLabel;
87 private final EditorTextField myEditorTextField;
88 private Document myDocument;
90 /**
91 * @param itemToBeEdited item to be edited. If user closes dialog by "OK" button then
92 * @param oneOff
94 public ComponentItemDialog(final Project project, final Component parent, @NotNull ComponentItem itemToBeEdited, final boolean oneOff) {
95 super(parent, false);
96 myProject = project;
98 myItemToBeEdited = itemToBeEdited;
99 myOneOff = oneOff;
101 myEditorTextField = new EditorTextField("", project, StdFileTypes.JAVA);
102 myEditorTextField.setFontInheritedFromLAF(true);
103 myTfClassName = new ComponentWithBrowseButton<EditorTextField>(myEditorTextField, new MyChooseClassActionListener(project));
105 PsiFile boundForm = itemToBeEdited.getBoundForm();
106 if (boundForm != null) {
107 myNestedFormRadioButton.setSelected(true);
108 myTfNestedForm.setText(FormEditingUtil.buildResourceName(boundForm));
110 else {
111 myClassRadioButton.setSelected(true);
112 setEditorText(myItemToBeEdited.getClassName().replace('$', '.'));
114 updateEnabledTextField();
116 myTfClassName.getChildComponent().addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
117 public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
118 updateOKAction();
122 myTfClassName.getButton().setEnabled(!project.isDefault()); // chooser should not work in default project
123 myClassNamePlaceholder.setLayout(new BorderLayout());
124 myClassNamePlaceholder.add(myTfClassName, BorderLayout.CENTER);
126 myTfIconPath.setText(myItemToBeEdited.getIconPath());
127 myTfIconPath.addActionListener(new MyChooseFileActionListener(project, new ImageFileFilter(null), myTfIconPath,
128 UIDesignerBundle.message("add.component.choose.icon")));
130 myTfNestedForm.addActionListener(new MyChooseFileActionListener(project, new TreeFileChooser.PsiFileFilter() {
131 public boolean accept(PsiFile file) {
132 return file.getFileType().equals(StdFileTypes.GUI_DESIGNER_FORM);
134 }, myTfNestedForm, UIDesignerBundle.message("add.component.choose.form")));
136 myTfNestedForm.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
137 protected void textChanged(DocumentEvent e) {
138 updateOKAction();
142 final GridConstraints defaultConstraints = myItemToBeEdited.getDefaultConstraints();
144 // Horizontal size policy
146 final int hSizePolicy = defaultConstraints.getHSizePolicy();
147 myChkHorCanShrink.setSelected((hSizePolicy & GridConstraints.SIZEPOLICY_CAN_SHRINK) != 0);
148 myChkHorCanGrow.setSelected((hSizePolicy & GridConstraints.SIZEPOLICY_CAN_GROW) != 0);
149 myChkHorWantGrow.setSelected((hSizePolicy & GridConstraints.SIZEPOLICY_WANT_GROW) != 0);
152 // Vertical size policy
154 final int vSizePolicy = defaultConstraints.getVSizePolicy();
155 myChkVerCanShrink.setSelected((vSizePolicy & GridConstraints.SIZEPOLICY_CAN_SHRINK) != 0);
156 myChkVerCanGrow.setSelected((vSizePolicy & GridConstraints.SIZEPOLICY_CAN_GROW) != 0);
157 myChkVerWantGrow.setSelected((vSizePolicy & GridConstraints.SIZEPOLICY_WANT_GROW) != 0);
160 myIsContainerCheckBox.setSelected(itemToBeEdited.isContainer());
161 myAutoCreateBindingCheckbox.setSelected(itemToBeEdited.isAutoCreateBinding());
162 myCanAttachLabelCheckbox.setSelected(itemToBeEdited.isCanAttachLabel());
164 myLblIcon.setLabelFor(myTfIconPath);
165 myClassRadioButton.addChangeListener(new MyRadioChangeListener());
166 myNestedFormRadioButton.addChangeListener(new MyRadioChangeListener());
168 if (oneOff) {
169 myLblIcon.setVisible(false);
170 myTfIconPath.setVisible(false);
171 myCanAttachLabelCheckbox.setVisible(false);
172 myHSizePolicyPanel.setVisible(false);
173 myVSizePolicyPanel.setVisible(false);
176 updateOKAction();
178 init();
181 void showGroupChooser(GroupItem defaultGroup) {
182 myGroupLabel.setVisible(true);
183 myGroupComboBox.setVisible(true);
184 final ArrayList<GroupItem> groups = Palette.getInstance(myProject).getGroups();
185 myGroupComboBox.setModel(new DefaultComboBoxModel(groups.toArray()));
186 myGroupComboBox.setSelectedItem(defaultGroup);
187 myGroupComboBox.addItemListener(new ItemListener() {
188 public void itemStateChanged(ItemEvent e) {
189 updateOKAction();
192 updateOKAction();
195 GroupItem getSelectedGroup() {
196 return (GroupItem) myGroupComboBox.getSelectedItem();
199 private void setEditorText(final String className) {
200 final PsiManager manager = PsiManager.getInstance(myProject);
201 final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
202 PsiPackage defaultPackage = JavaPsiFacade.getInstance(manager.getProject()).findPackage("");
203 final PsiCodeFragment fragment = factory.createReferenceCodeFragment(className, defaultPackage, true, true);
204 myDocument = PsiDocumentManager.getInstance(manager.getProject()).getDocument(fragment);
205 myEditorTextField.setDocument(myDocument);
206 updateOKAction();
209 protected Action[] createActions() {
210 return new Action[]{getOKAction(), getCancelAction(), getHelpAction()};
213 protected void doHelpAction() {
214 HelpManager.getInstance().invokeHelp("reference.dialogs.addEditPaletteComponent");
217 protected void doOKAction() {
218 // TODO[vova] implement validation
219 if (myClassRadioButton.isSelected()) {
220 final String className = myDocument.getText().trim();
221 PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject));
222 if (psiClass != null) {
223 myItemToBeEdited.setClassName(getClassOrInnerName(psiClass));
225 else {
226 myItemToBeEdited.setClassName(className);
229 else {
230 if (!saveNestedForm()) return;
232 myItemToBeEdited.setIconPath(myTfIconPath.getText().trim());
235 final GridConstraints defaultConstraints = myItemToBeEdited.getDefaultConstraints();
236 // Horizontal size policy
237 defaultConstraints.setHSizePolicy(
238 (myChkHorCanShrink.isSelected() ? GridConstraints.SIZEPOLICY_CAN_SHRINK : 0) |
239 (myChkHorCanGrow.isSelected() ? GridConstraints.SIZEPOLICY_CAN_GROW : 0) |
240 (myChkHorWantGrow.isSelected() ? GridConstraints.SIZEPOLICY_WANT_GROW : 0)
243 // Vertical size policy
244 defaultConstraints.setVSizePolicy(
245 (myChkVerCanShrink.isSelected() ? GridConstraints.SIZEPOLICY_CAN_SHRINK : 0) |
246 (myChkVerCanGrow.isSelected() ? GridConstraints.SIZEPOLICY_CAN_GROW : 0) |
247 (myChkVerWantGrow.isSelected() ? GridConstraints.SIZEPOLICY_WANT_GROW : 0)
250 defaultConstraints.setFill(
251 (myChkHorWantGrow.isSelected() ? GridConstraints.FILL_HORIZONTAL : 0) |
252 (myChkVerWantGrow.isSelected() ? GridConstraints.FILL_VERTICAL : 0)
256 myItemToBeEdited.setIsContainer(myIsContainerCheckBox.isSelected());
257 myItemToBeEdited.setAutoCreateBinding(myAutoCreateBindingCheckbox.isSelected());
258 myItemToBeEdited.setCanAttachLabel(myCanAttachLabelCheckbox.isSelected());
260 super.doOKAction();
263 private boolean saveNestedForm() {
264 VirtualFile formFile = ResourceFileUtil.findResourceFileInProject(myProject, myTfNestedForm.getText());
265 if (formFile == null) {
266 Messages.showErrorDialog(getWindow(), UIDesignerBundle.message("add.component.cannot.load.form", myTfNestedForm.getText()), CommonBundle.getErrorTitle());
267 return false;
269 LwRootContainer lwRootContainer;
270 try {
271 lwRootContainer = Utils.getRootContainer(formFile.getInputStream(), null);
273 catch (Exception e) {
274 Messages.showErrorDialog(getWindow(), e.getMessage(), CommonBundle.getErrorTitle());
275 return false;
277 if (lwRootContainer.getClassToBind() == null) {
278 Messages.showErrorDialog(getWindow(), UIDesignerBundle.message("add.component.form.not.bound"), CommonBundle.getErrorTitle());
279 return false;
281 if (lwRootContainer.getComponent(0).getBinding() == null) {
282 Messages.showErrorDialog(getWindow(), UIDesignerBundle.message("add.component.root.not.bound"),
283 CommonBundle.getErrorTitle());
284 return false;
286 PsiClass psiClass =
287 JavaPsiFacade.getInstance(myProject).findClass(lwRootContainer.getClassToBind(), GlobalSearchScope.projectScope(myProject));
288 if (psiClass != null) {
289 myItemToBeEdited.setClassName(getClassOrInnerName(psiClass));
291 else {
292 myItemToBeEdited.setClassName(lwRootContainer.getClassToBind());
294 return true;
297 protected String getDimensionServiceKey() {
298 if (myOneOff) {
299 return "#com.intellij.uiDesigner.palette.ComponentItemDialog.OneOff";
301 return "#com.intellij.uiDesigner.palette.ComponentItemDialog";
304 public JComponent getPreferredFocusedComponent() {
305 return myTfClassName.getChildComponent();
308 protected JComponent createCenterPanel() {
309 return myPanel;
312 private void updateEnabledTextField() {
313 myEditorTextField.setEnabled(myClassRadioButton.isSelected());
314 myTfNestedForm.setEnabled(myNestedFormRadioButton.isSelected());
315 updateOKAction();
318 private void updateOKAction() {
319 setOKActionEnabled(isOKEnabled());
322 private boolean isOKEnabled() {
323 myErrorLabel.setText(" ");
324 if (myClassRadioButton.isSelected()) {
325 final PsiManager psiManager = PsiManager.getInstance(myProject);
326 if (!JavaPsiFacade.getInstance(psiManager.getProject()).getNameHelper().isQualifiedName(myDocument.getText())) {
327 if (myDocument.getTextLength() > 0) {
328 myErrorLabel.setText(UIDesignerBundle.message("add.component.error.qualified.name.required"));
330 return false;
332 PsiClass psiClass =
333 JavaPsiFacade.getInstance(psiManager.getProject()).findClass(myDocument.getText(), ProjectScope.getAllScope(myProject));
334 PsiClass componentClass =
335 JavaPsiFacade.getInstance(psiManager.getProject()).findClass(JComponent.class.getName(), ProjectScope.getAllScope(myProject));
336 if (psiClass != null && componentClass != null && !InheritanceUtil.isInheritorOrSelf(psiClass, componentClass, true)) {
337 myErrorLabel.setText(UIDesignerBundle.message("add.component.error.component.required"));
338 return false;
341 else {
342 if (myTfNestedForm.getText().length() == 0) {
343 return false;
346 if (myGroupComboBox.isVisible() && myGroupComboBox.getSelectedItem() == null) {
347 return false;
349 return true;
352 private static String getClassOrInnerName(final PsiClass aClass) {
353 PsiClass parentClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true);
354 if(parentClass != null) {
355 return getClassOrInnerName(parentClass) + "$" + aClass.getName();
357 return aClass.getQualifiedName();
360 private class MyChooseClassActionListener implements ActionListener {
361 private final Project myProject;
363 public MyChooseClassActionListener(final Project project) {
364 myProject = project;
367 public void actionPerformed(final ActionEvent e) {
368 final TreeClassChooserFactory factory = TreeClassChooserFactory.getInstance(myProject);
369 final TreeClassChooser chooser = factory.createInheritanceClassChooser(UIDesignerBundle.message("title.choose.component.class"),
370 GlobalSearchScope.allScope(myProject), JavaPsiFacade.getInstance(myProject).findClass(
371 JComponent.class.getName(), GlobalSearchScope.allScope(myProject)), true, true, null);
372 chooser.showDialog();
373 final PsiClass result = chooser.getSelectedClass();
374 if (result != null) {
375 setEditorText(result.getQualifiedName());
380 private static class MyChooseFileActionListener implements ActionListener {
381 private final Project myProject;
382 private final TreeFileChooser.PsiFileFilter myFilter;
383 private final TextFieldWithBrowseButton myTextField;
384 private final String myTitle;
386 public MyChooseFileActionListener(final Project project,
387 final TreeFileChooser.PsiFileFilter filter,
388 final TextFieldWithBrowseButton textField,
389 final String title) {
390 myProject = project;
391 myFilter = filter;
392 myTextField = textField;
393 myTitle = title;
396 public void actionPerformed(ActionEvent e) {
397 final TreeClassChooserFactory factory = TreeClassChooserFactory.getInstance(myProject);
398 PsiFile formFile = null;
399 if (myTextField.getText().length() > 0) {
400 VirtualFile formVFile = ResourceFileUtil.findResourceFileInScope(myTextField.getText(), myProject, ProjectScope.getAllScope(myProject));
401 if (formVFile != null) {
402 formFile = PsiManager.getInstance(myProject).findFile(formVFile);
405 TreeFileChooser fileChooser = factory.createFileChooser(myTitle, formFile, null, myFilter, true, true);
406 fileChooser.showDialog();
407 PsiFile file = fileChooser.getSelectedFile();
408 if (file != null) {
409 myTextField.setText(FormEditingUtil.buildResourceName(file));
414 private class MyRadioChangeListener implements ChangeListener {
415 public void stateChanged(ChangeEvent e) {
416 updateEnabledTextField();