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.
20 package com
.intellij
.codeInsight
.intention
.impl
.config
;
22 import com
.intellij
.ide
.CommonActionsManager
;
23 import com
.intellij
.ide
.TreeExpander
;
24 import com
.intellij
.ide
.ui
.search
.SearchUtil
;
25 import com
.intellij
.openapi
.actionSystem
.ActionManager
;
26 import com
.intellij
.openapi
.actionSystem
.ActionPlaces
;
27 import com
.intellij
.openapi
.actionSystem
.ActionToolbar
;
28 import com
.intellij
.openapi
.actionSystem
.DefaultActionGroup
;
29 import com
.intellij
.openapi
.util
.Ref
;
30 import com
.intellij
.packageDependencies
.ui
.TreeExpansionMonitor
;
31 import com
.intellij
.ui
.*;
32 import com
.intellij
.util
.ArrayUtil
;
33 import com
.intellij
.util
.ui
.UIUtil
;
34 import com
.intellij
.util
.ui
.tree
.TreeUtil
;
37 import javax
.swing
.event
.TreeSelectionEvent
;
38 import javax
.swing
.event
.TreeSelectionListener
;
39 import javax
.swing
.tree
.DefaultMutableTreeNode
;
40 import javax
.swing
.tree
.DefaultTreeModel
;
41 import javax
.swing
.tree
.TreePath
;
44 import java
.util
.List
;
46 public abstract class IntentionSettingsTree
{
47 private JComponent myComponent
;
48 private CheckboxTree myTree
;
49 private FilterComponent myFilter
;
50 private JPanel myToolbarPanel
;
52 private final Map
<IntentionActionMetaData
, Boolean
> myIntentionToCheckStatus
= new HashMap
<IntentionActionMetaData
, Boolean
>();
54 protected IntentionSettingsTree() {
58 public JTree
getTree(){
62 public JComponent
getComponent() {
66 private void initTree() {
67 myTree
= new CheckboxTree(new CheckboxTree
.CheckboxTreeCellRenderer(true) {
68 public void customizeCellRenderer(JTree tree
, Object value
, boolean selected
, boolean expanded
, boolean leaf
, int row
, boolean hasFocus
) {
69 CheckedTreeNode node
= (CheckedTreeNode
)value
;
70 SimpleTextAttributes attributes
= node
.getUserObject() instanceof IntentionActionMetaData ? SimpleTextAttributes
.REGULAR_ATTRIBUTES
: SimpleTextAttributes
.REGULAR_BOLD_ATTRIBUTES
;
71 final String text
= getNodeText(node
);
73 SearchUtil
.appendFragments(myFilter
!= null ? myFilter
.getFilter() : null,
75 attributes
.getStyle(),
76 attributes
.getFgColor(),
77 selected ? UIUtil
.getTreeSelectionBackground() : UIUtil
.getTreeTextBackground(),
81 }, new CheckedTreeNode(null));
83 myTree
.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
84 public void valueChanged(TreeSelectionEvent e
) {
85 TreePath path
= e
.getPath();
86 Object userObject
= ((DefaultMutableTreeNode
)path
.getLastPathComponent()).getUserObject();
87 selectionChanged(userObject
);
91 myFilter
= new MyFilterComponent();
92 myComponent
= new JPanel(new BorderLayout());
93 JScrollPane scrollPane
= new JScrollPane(myTree
);
94 myToolbarPanel
= new JPanel(new BorderLayout());
95 myToolbarPanel
.add(createTreeToolbarPanel().getComponent(), BorderLayout
.WEST
);
96 myToolbarPanel
.add(myFilter
, BorderLayout
.CENTER
);
97 myComponent
.add(myToolbarPanel
, BorderLayout
.NORTH
);
98 myComponent
.add(scrollPane
, BorderLayout
.CENTER
);
100 SwingUtilities
.invokeLater(new Runnable() {
102 myTree
.setSelectionRow(0);
108 private ActionToolbar
createTreeToolbarPanel() {
109 final CommonActionsManager actionManager
= CommonActionsManager
.getInstance();
111 TreeExpander treeExpander
= new TreeExpander() {
112 public void expandAll() {
113 TreeUtil
.expandAll(myTree
);
116 public boolean canExpand() {
120 public void collapseAll() {
121 TreeUtil
.collapseAll(myTree
, 3);
124 public boolean canCollapse() {
129 DefaultActionGroup actions
= new DefaultActionGroup();
130 actions
.add(actionManager
.createExpandAllAction(treeExpander
, myTree
));
131 actions
.add(actionManager
.createCollapseAllAction(treeExpander
, myTree
));
133 return ActionManager
.getInstance().createActionToolbar(ActionPlaces
.MAIN_TOOLBAR
, actions
, true);
136 protected abstract void selectionChanged(Object selected
);
137 protected abstract List
<IntentionActionMetaData
> filterModel(String filter
, final boolean force
);
139 public void filter(List
<IntentionActionMetaData
> intentionsToShow
) {
140 refreshCheckStatus((CheckedTreeNode
)myTree
.getModel().getRoot());
141 reset(intentionsToShow
);
146 reset(IntentionManagerSettings
.getInstance().getMetaData());
149 private void resetCheckStatus() {
150 myIntentionToCheckStatus
.clear();
151 IntentionManagerSettings manager
= IntentionManagerSettings
.getInstance();
152 for (IntentionActionMetaData metaData
: manager
.getMetaData()) {
153 myIntentionToCheckStatus
.put(metaData
, manager
.isEnabled(metaData
));
157 private void reset(List
<IntentionActionMetaData
> intentionsToShow
) {
158 CheckedTreeNode root
= new CheckedTreeNode(null);
159 final DefaultTreeModel treeModel
= (DefaultTreeModel
)myTree
.getModel();
160 intentionsToShow
= sort(intentionsToShow
);
162 for (final IntentionActionMetaData metaData
: intentionsToShow
) {
163 String
[] category
= metaData
.myCategory
;
164 CheckedTreeNode node
= root
;
165 for (final String name
: category
) {
166 CheckedTreeNode child
= findChild(node
, name
);
168 CheckedTreeNode newChild
= new CheckedTreeNode(name
);
169 treeModel
.insertNodeInto(newChild
, node
, node
.getChildCount());
174 CheckedTreeNode newChild
= new CheckedTreeNode(metaData
);
175 treeModel
.insertNodeInto(newChild
, node
, node
.getChildCount());
177 resetCheckMark(root
);
178 treeModel
.setRoot(root
);
179 treeModel
.nodeChanged(root
);
182 private static List
<IntentionActionMetaData
> sort(final List
<IntentionActionMetaData
> intentionsToShow
) {
183 List
<IntentionActionMetaData
> copy
= new ArrayList
<IntentionActionMetaData
>(intentionsToShow
);
184 Collections
.sort(copy
, new Comparator
<IntentionActionMetaData
>() {
185 public int compare(final IntentionActionMetaData data1
, final IntentionActionMetaData data2
) {
186 String
[] category1
= data1
.myCategory
;
187 String
[] category2
= data2
.myCategory
;
188 int result
= ArrayUtil
.lexicographicCompare(category1
, category2
);
192 return data1
.getFamily().compareTo(data2
.getFamily());
198 private CheckedTreeNode
getRoot() {
199 return (CheckedTreeNode
)myTree
.getModel().getRoot();
202 private boolean resetCheckMark(final CheckedTreeNode root
) {
203 Object userObject
= root
.getUserObject();
204 if (userObject
instanceof IntentionActionMetaData
) {
205 IntentionActionMetaData metaData
= (IntentionActionMetaData
)userObject
;
206 Boolean b
= myIntentionToCheckStatus
.get(metaData
);
207 boolean enabled
= b
== null ?
false : b
.booleanValue();
208 root
.setChecked(enabled
);
212 root
.setChecked(false);
213 visitChildren(root
, new CheckedNodeVisitor() {
214 public void visit(CheckedTreeNode node
) {
215 if (resetCheckMark(node
)) {
216 root
.setChecked(true);
220 return root
.isChecked();
224 private static CheckedTreeNode
findChild(CheckedTreeNode node
, final String name
) {
225 final Ref
<CheckedTreeNode
> found
= new Ref
<CheckedTreeNode
>();
226 visitChildren(node
, new CheckedNodeVisitor() {
227 public void visit(CheckedTreeNode node
) {
228 String text
= getNodeText(node
);
229 if (name
.equals(text
)) {
237 private static String
getNodeText(CheckedTreeNode node
) {
238 final Object userObject
= node
.getUserObject();
240 if (userObject
instanceof String
) {
241 text
= (String
)userObject
;
243 else if (userObject
instanceof IntentionActionMetaData
) {
244 text
= ((IntentionActionMetaData
)userObject
).getFamily();
252 public void apply() {
253 CheckedTreeNode root
= getRoot();
257 private void refreshCheckStatus(final CheckedTreeNode root
) {
258 Object userObject
= root
.getUserObject();
259 if (userObject
instanceof IntentionActionMetaData
) {
260 IntentionActionMetaData actionMetaData
= (IntentionActionMetaData
)userObject
;
261 myIntentionToCheckStatus
.put(actionMetaData
, root
.isChecked());
264 visitChildren(root
, new CheckedNodeVisitor() {
265 public void visit(CheckedTreeNode node
) {
266 refreshCheckStatus(node
);
273 private static void apply(CheckedTreeNode root
) {
274 Object userObject
= root
.getUserObject();
275 if (userObject
instanceof IntentionActionMetaData
) {
276 IntentionActionMetaData actionMetaData
= (IntentionActionMetaData
)userObject
;
277 IntentionManagerSettings
.getInstance().setEnabled(actionMetaData
, root
.isChecked());
280 visitChildren(root
, new CheckedNodeVisitor() {
281 public void visit(CheckedTreeNode node
) {
288 public boolean isModified() {
289 return isModified(getRoot());
292 private static boolean isModified(CheckedTreeNode root
) {
293 Object userObject
= root
.getUserObject();
294 if (userObject
instanceof IntentionActionMetaData
) {
295 IntentionActionMetaData actionMetaData
= (IntentionActionMetaData
)userObject
;
296 boolean enabled
= IntentionManagerSettings
.getInstance().isEnabled(actionMetaData
);
297 return enabled
!= root
.isChecked();
300 final boolean[] modified
= new boolean[] { false };
301 visitChildren(root
, new CheckedNodeVisitor() {
302 public void visit(CheckedTreeNode node
) {
303 modified
[0] |= isModified(node
);
310 public void dispose() {
314 public void setFilter(String filter
){
315 myFilter
.setFilter(filter
);
318 public String
getFilter() {
319 return myFilter
.getFilter();
322 interface CheckedNodeVisitor
{
323 void visit(CheckedTreeNode node
);
325 private static void visitChildren(CheckedTreeNode node
, CheckedNodeVisitor visitor
) {
326 Enumeration children
= node
.children();
327 while (children
.hasMoreElements()) {
328 final CheckedTreeNode child
= (CheckedTreeNode
)children
.nextElement();
329 visitor
.visit(child
);
333 private class MyFilterComponent
extends FilterComponent
{
334 private final TreeExpansionMonitor
<DefaultMutableTreeNode
> myExpansionMonitor
= TreeExpansionMonitor
.install(myTree
);
336 public MyFilterComponent() {
337 super("INTENTION_FILTER_HISTORY", 10);
340 public void filter() {
341 final String filter
= getFilter();
342 if (filter
!= null && filter
.length() > 0) {
343 if (!myExpansionMonitor
.isFreeze()) {
344 myExpansionMonitor
.freeze();
347 IntentionSettingsTree
.this.filter(filterModel(filter
, true));
348 if (myTree
!= null) {
349 List
<TreePath
> expandedPaths
= TreeUtil
.collectExpandedPaths(myTree
);
350 ((DefaultTreeModel
)myTree
.getModel()).reload();
351 TreeUtil
.restoreExpandedPaths(myTree
, expandedPaths
);
353 SwingUtilities
.invokeLater(new Runnable() {
355 myTree
.setSelectionRow(0);
356 myTree
.requestFocus();
359 TreeUtil
.expandAll(myTree
);
360 if (filter
== null || filter
.length() == 0) {
361 TreeUtil
.collapseAll(myTree
, 0);
362 myExpansionMonitor
.restore();
366 protected void onlineFilter() {
367 final String filter
= getFilter();
368 if (filter
!= null && filter
.length() > 0) {
369 if (!myExpansionMonitor
.isFreeze()) {
370 myExpansionMonitor
.freeze();
373 IntentionSettingsTree
.this.filter(filterModel(filter
, true));
374 TreeUtil
.expandAll(myTree
);
375 if (filter
== null || filter
.length() == 0) {
376 TreeUtil
.collapseAll(myTree
, 0);
377 myExpansionMonitor
.restore();
382 public JPanel
getToolbarPanel() {
383 return myToolbarPanel
;