update copyright
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / inspections / DuplicateMnemonicInspection.java
blob7f4a09413b02efe861ec4e90b95330bcfbfa441e
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.inspections;
18 import com.intellij.openapi.module.Module;
19 import com.intellij.uiDesigner.FormEditingUtil;
20 import com.intellij.uiDesigner.StringDescriptorManager;
21 import com.intellij.uiDesigner.SwingProperties;
22 import com.intellij.uiDesigner.UIDesignerBundle;
23 import com.intellij.uiDesigner.core.SupportCode;
24 import com.intellij.uiDesigner.designSurface.GuiEditor;
25 import com.intellij.uiDesigner.lw.*;
26 import com.intellij.uiDesigner.quickFixes.QuickFix;
27 import com.intellij.uiDesigner.radComponents.RadComponent;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
31 import javax.swing.*;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.List;
36 /**
37 * @author yole
39 public class DuplicateMnemonicInspection extends BaseFormInspection {
40 private static final ThreadLocal<HashMap<IRootContainer, MnemonicMap>> myContainerMnemonicMap = new ThreadLocal<HashMap<IRootContainer, MnemonicMap>>() {
41 @Override
42 protected HashMap<IRootContainer, MnemonicMap> initialValue() {
43 return new HashMap<IRootContainer, MnemonicMap>();
47 public DuplicateMnemonicInspection() {
48 super("DuplicateMnemonic");
51 @NotNull
52 @Override
53 public String getDisplayName() {
54 return UIDesignerBundle.message("inspection.duplicate.mnemonics");
57 @Override public void startCheckForm(IRootContainer radRootContainer) {
58 myContainerMnemonicMap.get().put(radRootContainer, new MnemonicMap());
61 @Override public void doneCheckForm(IRootContainer rootContainer) {
62 myContainerMnemonicMap.get().remove(rootContainer);
65 protected void checkComponentProperties(Module module, IComponent component, FormErrorCollector collector) {
66 SupportCode.TextWithMnemonic twm = getTextWithMnemonic(module, component);
67 if (twm != null) {
68 checkTextWithMnemonic(module, component, twm, collector);
72 @Nullable
73 public static SupportCode.TextWithMnemonic getTextWithMnemonic(final Module module, final IComponent component) {
74 if (module.isDisposed()) return null;
75 IProperty prop = FormInspectionUtil.findProperty(component, SwingProperties.TEXT);
76 if (prop != null) {
77 Object propValue = prop.getPropertyValue(component);
78 if (propValue instanceof StringDescriptor) {
79 StringDescriptor descriptor = (StringDescriptor)propValue;
80 String value;
81 if (component instanceof RadComponent) {
82 value = StringDescriptorManager.getInstance(module).resolve((RadComponent) component, descriptor);
84 else {
85 value = StringDescriptorManager.getInstance(module).resolve(descriptor, null);
87 SupportCode.TextWithMnemonic twm = SupportCode.parseText(value);
88 if (twm.myMnemonicIndex >= 0 &&
89 (FormInspectionUtil.isComponentClass(module, component, JLabel.class) || FormInspectionUtil.isComponentClass(module, component, AbstractButton.class))) {
90 return twm;
94 return null;
97 private void checkTextWithMnemonic(final Module module,
98 final IComponent component,
99 final SupportCode.TextWithMnemonic twm,
100 final FormErrorCollector collector) {
101 IRootContainer root = FormEditingUtil.getRoot(component);
102 MnemonicMap map = myContainerMnemonicMap.get().get(root);
103 MnemonicKey key = buildMnemonicKey(twm, component);
104 if (map.containsKey(key)) {
105 IProperty prop = FormInspectionUtil.findProperty(component, SwingProperties.TEXT);
106 IComponent oldComponent = map.get(key);
107 collector.addError(getID(), component, prop,
108 UIDesignerBundle.message("inspection.duplicate.mnemonics.message",
109 FormInspectionUtil.getText(module, oldComponent),
110 FormInspectionUtil.getText(module, component)),
111 new EditorQuickFixProvider() {
112 public QuickFix createQuickFix(GuiEditor editor, RadComponent component) {
113 return new AssignMnemonicFix(editor, component,
114 UIDesignerBundle.message("inspection.duplicate.mnemonics.quickfix"));
118 else {
119 map.put(key, component);
123 private static MnemonicKey buildMnemonicKey(final SupportCode.TextWithMnemonic twm, final IComponent component) {
124 List<Integer> exclusiveContainerStack = new ArrayList<Integer>();
125 IContainer parent = component.getParentContainer();
126 IComponent child = component;
127 while(parent != null) {
128 if (parent.areChildrenExclusive()) {
129 exclusiveContainerStack.add(0, parent.indexOfComponent(child));
131 child = parent;
132 parent = parent.getParentContainer();
134 return new MnemonicKey(twm.getMnemonicChar(), exclusiveContainerStack);
137 private static class MnemonicKey {
138 private final char myMnemonicChar;
139 private final List<Integer> myExclusiveContainerStack;
141 public MnemonicKey(final char mnemonicChar, final List<Integer> exclusiveContainerStack) {
142 myMnemonicChar = mnemonicChar;
143 myExclusiveContainerStack = exclusiveContainerStack;
146 public boolean equals(final Object o) {
147 if (this == o) return true;
148 if (o == null || getClass() != o.getClass()) return false;
150 final MnemonicKey that = (MnemonicKey)o;
152 if (myMnemonicChar != that.myMnemonicChar) return false;
153 if (!myExclusiveContainerStack.equals(that.myExclusiveContainerStack)) return false;
155 return true;
158 public int hashCode() {
159 int result;
160 result = (int)myMnemonicChar;
161 result = 31 * result + myExclusiveContainerStack.hashCode();
162 return result;
166 private static class MnemonicMap extends HashMap<MnemonicKey, IComponent> {