IDEA-65711
[idea/community.git] / plugins / ui-designer / src / com / intellij / uiDesigner / inspections / NoLabelForInspection.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.inspections;
17
18 import com.intellij.openapi.command.CommandProcessor;
19 import com.intellij.openapi.module.Module;
20 import com.intellij.openapi.util.Ref;
21 import com.intellij.openapi.util.text.StringUtil;
22 import com.intellij.uiDesigner.FormEditingUtil;
23 import com.intellij.uiDesigner.SwingProperties;
24 import com.intellij.uiDesigner.UIDesignerBundle;
25 import com.intellij.uiDesigner.core.GridConstraints;
26 import com.intellij.uiDesigner.designSurface.GuiEditor;
27 import com.intellij.uiDesigner.lw.IComponent;
28 import com.intellij.uiDesigner.lw.IProperty;
29 import com.intellij.uiDesigner.palette.ComponentItem;
30 import com.intellij.uiDesigner.palette.Palette;
31 import com.intellij.uiDesigner.propertyInspector.IntrospectedProperty;
32 import com.intellij.uiDesigner.propertyInspector.properties.IntroComponentProperty;
33 import com.intellij.uiDesigner.quickFixes.QuickFix;
34 import com.intellij.uiDesigner.radComponents.RadComponent;
35 import org.jetbrains.annotations.NotNull;
36
37 import java.util.ArrayList;
38 import java.util.List;
39 import javax.swing.*;
40
41 /**
42  * @author yole
43  */
44 public class NoLabelForInspection extends BaseFormInspection {
45   public NoLabelForInspection() {
46     super("NoLabelFor");
47   }
48
49   @NotNull
50   @Override public String getDisplayName() {
51     return UIDesignerBundle.message("inspection.no.label.for");
52   }
53
54   protected void checkComponentProperties(final Module module, final IComponent component, FormErrorCollector collector) {
55     ComponentItem item = Palette.getInstance(module.getProject()).getItem(component.getComponentClassName());
56     if (item != null && item.isCanAttachLabel()) {
57       IComponent root = component;
58       while(root.getParentContainer() != null) {
59         root = root.getParentContainer();
60       }
61       final Ref<Boolean> found = new Ref<Boolean>(Boolean.FALSE);
62       final Ref<RadComponent> candidateLabel = new Ref<RadComponent>();
63       final List<RadComponent> allLabels = new ArrayList<RadComponent>();
64       FormEditingUtil.iterate(root, new FormEditingUtil.ComponentVisitor() {
65         public boolean visit(final IComponent c2) {
66           if (FormInspectionUtil.isComponentClass(module, c2, JLabel.class)) {
67             IProperty prop = FormInspectionUtil.findProperty(c2, SwingProperties.LABEL_FOR);
68             if (prop != null && component.getId().equals(prop.getPropertyValue(c2))) {
69               found.set(Boolean.TRUE);
70               return false;
71             }
72             else if (component instanceof RadComponent &&
73                      (prop == null || StringUtil.isEmpty((String)prop.getPropertyValue(c2)))) {
74               RadComponent radComponent = (RadComponent) component;
75               final RadComponent radComponent2 = ((RadComponent)c2);
76               allLabels.add(radComponent2);
77               if (radComponent.getParent() == radComponent2.getParent() && radComponent.getParent().getLayoutManager().isGrid()) {
78                 GridConstraints gc1 = radComponent.getConstraints();
79                 GridConstraints gc2 = radComponent2.getConstraints();
80                 int nextColumn = FormEditingUtil.nextCol(radComponent.getParent(), gc2.getColumn());
81                 int nextRow = FormEditingUtil.nextRow(radComponent.getParent(), gc2.getRow());
82                 if ((gc1.getRow() == gc2.getRow() && nextColumn == gc1.getColumn()) ||
83                     (gc1.getColumn() == gc2.getColumn() && nextRow == gc1.getRow())) {
84                   candidateLabel.set(radComponent2);
85                 }
86               }
87             }
88           }
89           return true;
90         }
91       });
92       if (!found.get().booleanValue()) {
93         if (!candidateLabel.isNull()) {
94           allLabels.clear();
95           allLabels.add(candidateLabel.get());
96         }
97         EditorQuickFixProvider[] quickFixProviders = new EditorQuickFixProvider[allLabels.size()];
98         for (int i = 0; i < quickFixProviders.length; i++) {
99           final RadComponent label = allLabels.get(i);
100           quickFixProviders[i] = new EditorQuickFixProvider() {
101             public QuickFix createQuickFix(GuiEditor editor, RadComponent component) {
102               return new MyQuickFix(editor, component, label);
103             }
104           };
105         }
106         collector.addError(getID(), component, null, UIDesignerBundle.message("inspection.no.label.for.error"), quickFixProviders);
107       }
108     }
109   }
110
111   private static class MyQuickFix extends QuickFix {
112     private final RadComponent myLabel;
113
114     public MyQuickFix(final GuiEditor editor, RadComponent component, RadComponent label) {
115       super(editor, UIDesignerBundle.message("inspection.no.label.for.quickfix",
116                                              label.getComponentTitle()), component);
117       myLabel = label;
118     }
119
120     public void run() {
121       if (!myEditor.ensureEditable()) {
122         return;
123       }
124       Runnable runnable = new Runnable() {
125         public void run() {
126           final Palette palette = Palette.getInstance(myEditor.getProject());
127           IntrospectedProperty[] props = palette.getIntrospectedProperties(myLabel);
128           boolean modified = false;
129           for(IntrospectedProperty prop: props) {
130             if (prop.getName().equals(SwingProperties.LABEL_FOR) && prop instanceof IntroComponentProperty) {
131               IntroComponentProperty icp = (IntroComponentProperty) prop;
132               icp.setValueEx(myLabel, myComponent.getId());
133               modified = true;
134               break;
135             }
136           }
137           if (modified) myEditor.refreshAndSave(false);
138         }
139       };
140       CommandProcessor.getInstance().executeCommand(myEditor.getProject(), runnable,
141                                                     UIDesignerBundle.message("inspection.no.label.for.command"), null);
142     }
143   }
144 }