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.
17 package com
.intellij
.codeInspection
.ex
;
19 import com
.intellij
.application
.options
.colors
.ColorAndFontDescriptionPanel
;
20 import com
.intellij
.application
.options
.colors
.ColorAndFontOptions
;
21 import com
.intellij
.application
.options
.colors
.InspectionColorSettingsPage
;
22 import com
.intellij
.application
.options
.colors
.TextAttributesDescription
;
23 import com
.intellij
.application
.options
.editor
.EditorOptionsProvider
;
24 import com
.intellij
.codeInsight
.daemon
.impl
.HighlightInfoType
;
25 import com
.intellij
.codeInsight
.daemon
.impl
.SeverityRegistrar
;
26 import com
.intellij
.codeInspection
.InspectionsBundle
;
27 import com
.intellij
.execution
.ExecutionBundle
;
28 import com
.intellij
.ide
.DataManager
;
29 import com
.intellij
.ide
.IdeBundle
;
30 import com
.intellij
.lang
.annotation
.HighlightSeverity
;
31 import com
.intellij
.openapi
.actionSystem
.*;
32 import com
.intellij
.openapi
.diagnostic
.Logger
;
33 import com
.intellij
.openapi
.editor
.colors
.CodeInsightColors
;
34 import com
.intellij
.openapi
.editor
.colors
.EditorColorsScheme
;
35 import com
.intellij
.openapi
.editor
.colors
.TextAttributesKey
;
36 import com
.intellij
.openapi
.editor
.markup
.TextAttributes
;
37 import com
.intellij
.openapi
.extensions
.Extensions
;
38 import com
.intellij
.openapi
.options
.SearchableConfigurable
;
39 import com
.intellij
.openapi
.options
.ShowSettingsUtil
;
40 import com
.intellij
.openapi
.options
.newEditor
.OptionsEditor
;
41 import com
.intellij
.openapi
.ui
.DialogWrapper
;
42 import com
.intellij
.openapi
.ui
.InputValidator
;
43 import com
.intellij
.openapi
.ui
.Messages
;
44 import com
.intellij
.openapi
.util
.Comparing
;
45 import com
.intellij
.openapi
.util
.Condition
;
46 import com
.intellij
.openapi
.util
.Factory
;
47 import com
.intellij
.openapi
.util
.IconLoader
;
48 import com
.intellij
.ui
.LightColors
;
49 import com
.intellij
.ui
.ListUtil
;
50 import com
.intellij
.ui
.ReorderableListController
;
51 import org
.jdom
.Element
;
52 import org
.jetbrains
.annotations
.NonNls
;
53 import org
.jetbrains
.annotations
.Nullable
;
56 import javax
.swing
.event
.ListSelectionEvent
;
57 import javax
.swing
.event
.ListSelectionListener
;
59 import java
.awt
.event
.ActionEvent
;
60 import java
.awt
.event
.ActionListener
;
62 import java
.util
.List
;
68 public class SeverityEditorDialog
extends DialogWrapper
{
69 private final JPanel myPanel
;
71 private final JList myOptionsList
= new JList();
72 private final ColorAndFontDescriptionPanel myOptionsPanel
= new ColorAndFontDescriptionPanel();
74 private SeverityRegistrar
.SeverityBasedTextAttributes myCurrentSelection
;
75 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInspection.ex.SeverityEditorDialog");
76 private final SeverityRegistrar mySeverityRegistrar
;
77 private final CardLayout myCard
;
78 private final JPanel myRightPanel
;
79 @NonNls private static final String DEFAULT
= "DEFAULT";
80 @NonNls private static final String EDITABLE
= "EDITABLE";
82 public SeverityEditorDialog(final JComponent parent
, final HighlightSeverity severity
, final SeverityRegistrar severityRegistrar
) {
84 mySeverityRegistrar
= severityRegistrar
;
85 myOptionsList
.setCellRenderer(new DefaultListCellRenderer() {
86 public Component
getListCellRendererComponent(JList list
, Object value
, int index
, boolean isSelected
, boolean cellHasFocus
) {
87 final Component rendererComponent
= super.getListCellRendererComponent(list
, value
, index
, isSelected
, cellHasFocus
);
88 if (value
instanceof SeverityRegistrar
.SeverityBasedTextAttributes
) {
89 setText(((SeverityRegistrar
.SeverityBasedTextAttributes
)value
).getSeverity().toString());
91 return rendererComponent
;
94 myOptionsList
.addListSelectionListener(new ListSelectionListener() {
95 public void valueChanged(ListSelectionEvent e
) {
96 if (myCurrentSelection
!= null) {
97 apply(myCurrentSelection
);
99 myCurrentSelection
= (SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getSelectedValue();
100 if (myCurrentSelection
!= null) {
101 reset(myCurrentSelection
);
102 myCard
.show(myRightPanel
, mySeverityRegistrar
.isDefaultSeverity(myCurrentSelection
.getSeverity()) ? DEFAULT
: EDITABLE
);
106 myOptionsList
.setSelectionMode(ListSelectionModel
.SINGLE_SELECTION
);
107 JScrollPane scrollPane
= new JScrollPane(myOptionsList
);
108 scrollPane
.setPreferredSize(new Dimension(230, 60));
109 JPanel leftPanel
= new JPanel(new BorderLayout());
110 leftPanel
.add(scrollPane
, BorderLayout
.CENTER
);
111 leftPanel
.add(createListToolbar(), BorderLayout
.NORTH
);
112 myPanel
= new JPanel(new BorderLayout());
113 myPanel
.add(leftPanel
, BorderLayout
.WEST
);
114 myCard
= new CardLayout();
115 myRightPanel
= new JPanel(myCard
);
116 final JPanel disabled
= new JPanel(new GridBagLayout());
117 final JButton button
= new JButton(InspectionsBundle
.message("severities.default.settings.message"));
118 button
.addActionListener(new ActionListener(){
119 public void actionPerformed(final ActionEvent e
) {
120 final String toConfigure
= getSelectedType().getSeverity(null).myName
;
122 myOptionsList
.clearSelection();
123 ColorAndFontOptions colorAndFontOptions
= null;
124 for (EditorOptionsProvider provider
: Extensions
.getExtensions(EditorOptionsProvider
.EP_NAME
)) {
125 if (provider
.getClass().isAssignableFrom(ColorAndFontOptions
.class)) {
126 colorAndFontOptions
= (ColorAndFontOptions
)provider
;
130 assert colorAndFontOptions
!= null;
131 final SearchableConfigurable javaPage
= colorAndFontOptions
.findSubConfigurable(InspectionColorSettingsPage
.class);
132 LOG
.assertTrue(javaPage
!= null);
133 final OptionsEditor optionsEditor
= OptionsEditor
.KEY
.getData(DataManager
.getInstance().getDataContext());
134 if (optionsEditor
!= null) {
135 optionsEditor
.select(javaPage
).doWhenDone(new Runnable(){
137 final Runnable runnable
= javaPage
.enableSearch(toConfigure
);
138 if (runnable
!= null) {
139 SwingUtilities
.invokeLater(runnable
);
144 ShowSettingsUtil
.getInstance().editConfigurable(PlatformDataKeys
.PROJECT
.getData(DataManager
.getInstance().getDataContext()), javaPage
);
148 disabled
.add(button
, new GridBagConstraints(0,0,1,1,0,0, GridBagConstraints
.CENTER
, GridBagConstraints
.NONE
, new Insets(0,0,0,0),0,0));
149 myRightPanel
.add(DEFAULT
, disabled
);
150 myRightPanel
.add(EDITABLE
, myOptionsPanel
);
151 myCard
.show(myRightPanel
, EDITABLE
);
152 myPanel
.add(myRightPanel
, BorderLayout
.CENTER
);
155 setTitle(InspectionsBundle
.message("severities.editor.dialog.title"));
156 reset((SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getSelectedValue());
159 private void fillList(final HighlightSeverity severity
) {
160 DefaultListModel model
= new DefaultListModel();
161 model
.removeAllElements();
162 final List
<SeverityRegistrar
.SeverityBasedTextAttributes
> infoTypes
= new ArrayList
<SeverityRegistrar
.SeverityBasedTextAttributes
>();
163 infoTypes
.addAll(mySeverityRegistrar
.getRegisteredHighlightingInfoTypes());
164 Collections
.sort(infoTypes
, new Comparator
<SeverityRegistrar
.SeverityBasedTextAttributes
>() {
165 public int compare(SeverityRegistrar
.SeverityBasedTextAttributes attributes1
, SeverityRegistrar
.SeverityBasedTextAttributes attributes2
) {
166 return - mySeverityRegistrar
.compare(attributes1
.getSeverity(), attributes2
.getSeverity());
169 SeverityRegistrar
.SeverityBasedTextAttributes preselection
= null;
170 for (SeverityRegistrar
.SeverityBasedTextAttributes type
: infoTypes
) {
171 model
.addElement(type
);
172 if (type
.getSeverity().equals(severity
)) {
176 myOptionsList
.setModel(model
);
177 myOptionsList
.setSelectedValue(preselection
, true);
181 private void apply(SeverityRegistrar
.SeverityBasedTextAttributes info
) {
182 final MyTextAttributesDescription description
=
183 new MyTextAttributesDescription(info
.getType().toString(), null, new TextAttributes(), info
.getType().getAttributesKey());
184 myOptionsPanel
.apply(description
, null);
185 @NonNls Element textAttributes
= new Element("temp");
187 description
.getTextAttributes().writeExternal(textAttributes
);
188 info
.getAttributes().readExternal(textAttributes
);
190 catch (Exception e
) {
195 private void reset(SeverityRegistrar
.SeverityBasedTextAttributes info
) {
196 final MyTextAttributesDescription description
=
197 new MyTextAttributesDescription(info
.getType().toString(), null, info
.getAttributes(), info
.getType().getAttributesKey());
198 @NonNls Element textAttributes
= new Element("temp");
200 info
.getAttributes().writeExternal(textAttributes
);
201 description
.getTextAttributes().readExternal(textAttributes
);
203 catch (Exception e
) {
206 myOptionsPanel
.reset(description
);
209 private JComponent
createListToolbar() {
210 DefaultActionGroup group
= new DefaultActionGroup();
211 final ReorderableListController
<SeverityRegistrar
.SeverityBasedTextAttributes
> controller
=
212 ReorderableListController
.create(myOptionsList
, group
);
213 controller
.addAddAction(IdeBundle
.message("action.add"), new Factory
<SeverityRegistrar
.SeverityBasedTextAttributes
>() {
215 public SeverityRegistrar
.SeverityBasedTextAttributes
create() {
216 final String name
= Messages
.showInputDialog(myPanel
, InspectionsBundle
.message("highlight.severity.create.dialog.name.label"),
217 InspectionsBundle
.message("highlight.severity.create.dialog.title"), Messages
.getQuestionIcon(),
218 "", new InputValidator() {
219 public boolean checkInput(final String inputString
) {
220 final ListModel listModel
= myOptionsList
.getModel();
221 for (int i
= 0; i
< listModel
.getSize(); i
++) {
222 final String severityName
= ((SeverityRegistrar
.SeverityBasedTextAttributes
)listModel
.getElementAt(i
)).getSeverity().myName
;
223 if (Comparing
.strEqual(severityName
, inputString
)) return false;
228 public boolean canClose(final String inputString
) {
229 return checkInput(inputString
);
232 if (name
== null) return null;
233 final TextAttributes textAttributes
= CodeInsightColors
.WARNINGS_ATTRIBUTES
.getDefaultAttributes();
234 HighlightInfoType
.HighlightInfoTypeImpl info
= new HighlightInfoType
.HighlightInfoTypeImpl(new HighlightSeverity(name
, 50),
235 TextAttributesKey
.createTextAttributesKey(name
));
236 return new SeverityRegistrar
.SeverityBasedTextAttributes(textAttributes
.clone(), info
);
239 final ReorderableListController
<SeverityRegistrar
.SeverityBasedTextAttributes
>.RemoveActionDescription removeAction
=
240 controller
.addRemoveAction(IdeBundle
.message("action.remove"));
241 removeAction
.setEnableCondition(new Condition
<SeverityRegistrar
.SeverityBasedTextAttributes
>() {
242 public boolean value(final SeverityRegistrar
.SeverityBasedTextAttributes pair
) {
243 return !mySeverityRegistrar
.isDefaultSeverity(pair
.getSeverity());
246 controller
.addAction(new MyMoveUpAction());
247 controller
.addAction(new MyMoveDownAction());
248 ActionToolbar toolbar
= ActionManager
.getInstance().createActionToolbar(ActionPlaces
.UNKNOWN
, group
, true);
249 return toolbar
.getComponent();
253 protected void doOKAction() {
254 apply((SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getSelectedValue());
255 final Collection
<SeverityRegistrar
.SeverityBasedTextAttributes
> infoTypes
=
256 new HashSet
<SeverityRegistrar
.SeverityBasedTextAttributes
>(mySeverityRegistrar
.getRegisteredHighlightingInfoTypes());
257 final ListModel listModel
= myOptionsList
.getModel();
258 final List
<String
> order
= new ArrayList
<String
>();
259 for (int i
= listModel
.getSize() - 1; i
>= 0 ;i
--) {
260 final SeverityRegistrar
.SeverityBasedTextAttributes info
=
261 (SeverityRegistrar
.SeverityBasedTextAttributes
)listModel
.getElementAt(i
);
262 order
.add(info
.getSeverity().myName
);
263 if (!mySeverityRegistrar
.isDefaultSeverity(info
.getSeverity())) {
264 infoTypes
.remove(info
);
265 final Color stripeColor
= info
.getAttributes().getErrorStripeColor();
266 mySeverityRegistrar
.registerSeverity(info
, stripeColor
!= null ? stripeColor
: LightColors
.YELLOW
);
269 for (SeverityRegistrar
.SeverityBasedTextAttributes info
: infoTypes
) {
270 mySeverityRegistrar
.unregisterSeverity(info
.getSeverity());
272 mySeverityRegistrar
.setOrder(order
);
277 protected JComponent
createCenterPanel() {
282 public HighlightInfoType
getSelectedType() {
283 final SeverityRegistrar
.SeverityBasedTextAttributes selection
=
284 (SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getSelectedValue();
285 return selection
!= null ? selection
.getType() : null;
288 private static class MyTextAttributesDescription
extends TextAttributesDescription
{
289 public MyTextAttributesDescription(final String name
, final String group
, final TextAttributes attributes
, final TextAttributesKey type
) {
290 super(name
, group
, attributes
, type
, null, null, null);
293 public void apply(EditorColorsScheme scheme
) {
297 public boolean isErrorStripeEnabled() {
302 public TextAttributes
getTextAttributes() {
303 return super.getTextAttributes();
307 private class MyMoveUpAction
extends AnAction
{
308 public MyMoveUpAction() {
309 super(ExecutionBundle
.message("move.up.action.name"), null, IconLoader
.getIcon("/actions/moveUp.png"));
312 public void actionPerformed(final AnActionEvent e
) {
313 apply(myCurrentSelection
);
314 ListUtil
.moveSelectedItemsUp(myOptionsList
);
317 public void update(final AnActionEvent e
) {
318 boolean canMove
= ListUtil
.canMoveSelectedItemsUp(myOptionsList
);
320 SeverityRegistrar
.SeverityBasedTextAttributes pair
=
321 (SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getSelectedValue();
322 if (pair
!= null && mySeverityRegistrar
.isDefaultSeverity(pair
.getSeverity())) {
323 final int newPosition
= myOptionsList
.getSelectedIndex() - 1;
324 pair
= (SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getModel().getElementAt(newPosition
);
325 if (mySeverityRegistrar
.isDefaultSeverity(pair
.getSeverity())) {
330 e
.getPresentation().setEnabled(canMove
);
334 private class MyMoveDownAction
extends AnAction
{
335 public MyMoveDownAction() {
336 super(ExecutionBundle
.message("move.down.action.name"), null, IconLoader
.getIcon("/actions/moveDown.png"));
339 public void actionPerformed(final AnActionEvent e
) {
340 apply(myCurrentSelection
);
341 ListUtil
.moveSelectedItemsDown(myOptionsList
);
344 public void update(final AnActionEvent e
) {
345 boolean canMove
= ListUtil
.canMoveSelectedItemsDown(myOptionsList
);
347 SeverityRegistrar
.SeverityBasedTextAttributes pair
=
348 (SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getSelectedValue();
349 if (pair
!= null && mySeverityRegistrar
.isDefaultSeverity(pair
.getSeverity())) {
350 final int newPosition
= myOptionsList
.getSelectedIndex() + 1;
351 pair
= (SeverityRegistrar
.SeverityBasedTextAttributes
)myOptionsList
.getModel().getElementAt(newPosition
);
352 if (mySeverityRegistrar
.isDefaultSeverity(pair
.getSeverity())) {
357 e
.getPresentation().setEnabled(canMove
);