update copyrights
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInsight / intention / impl / config / IntentionSettingsTree.java
blob0914c51644fc5c03ce767441f79cbe1856825350
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.
17 /**
18 * @author cdr
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;
36 import javax.swing.*;
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;
42 import java.awt.*;
43 import java.util.*;
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() {
55 initTree();
58 public JTree getTree(){
59 return myTree;
62 public JComponent getComponent() {
63 return myComponent;
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);
72 if (text != null) {
73 SearchUtil.appendFragments(myFilter != null ? myFilter.getFilter() : null,
74 text,
75 attributes.getStyle(),
76 attributes.getFgColor(),
77 selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground(),
78 getTextRenderer());
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);
89 });
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() {
101 public void run() {
102 myTree.setSelectionRow(0);
105 myFilter.reset();
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() {
117 return true;
120 public void collapseAll() {
121 TreeUtil.collapseAll(myTree, 3);
124 public boolean canCollapse() {
125 return true;
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);
144 public void reset(){
145 resetCheckStatus();
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);
167 if (child == null) {
168 CheckedTreeNode newChild = new CheckedTreeNode(name);
169 treeModel.insertNodeInto(newChild, node, node.getChildCount());
170 child = newChild;
172 node = child;
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);
189 if (result!= 0) {
190 return result;
192 return data1.getFamily().compareTo(data2.getFamily());
195 return copy;
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);
209 return enabled;
211 else {
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)) {
230 found.set(node);
234 return found.get();
237 private static String getNodeText(CheckedTreeNode node) {
238 final Object userObject = node.getUserObject();
239 String text;
240 if (userObject instanceof String) {
241 text = (String)userObject;
243 else if (userObject instanceof IntentionActionMetaData) {
244 text = ((IntentionActionMetaData)userObject).getFamily();
246 else {
247 text = "???";
249 return text;
252 public void apply() {
253 CheckedTreeNode root = getRoot();
254 apply(root);
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());
263 else {
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());
279 else {
280 visitChildren(root, new CheckedNodeVisitor() {
281 public void visit(CheckedTreeNode node) {
282 apply(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();
299 else {
300 final boolean[] modified = new boolean[] { false };
301 visitChildren(root, new CheckedNodeVisitor() {
302 public void visit(CheckedTreeNode node) {
303 modified[0] |= isModified(node);
306 return modified[0];
310 public void dispose() {
311 myFilter.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() {
354 public void run() {
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;