summaryrefslogtreecommitdiff
path: root/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2014-09-18 13:38:58 -0700
committerTor Norbye <tnorbye@google.com>2014-09-18 13:38:58 -0700
commitb5fb31ef6a38f19404859755dbd2e345215b97bf (patch)
treee8787c45e494dfcc558faf0f75956f8785c39b94 /platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
parente222a9e1e66670a56e926a6b0f3e10231eeeb1fb (diff)
parente782c57d74000722f9db4c9426317410520670c6 (diff)
downloadidea-b5fb31ef6a38f19404859755dbd2e345215b97bf.tar.gz
Merge remote-tracking branch 'aosp/upstream-master' into merge
Conflicts: .idea/libraries/asm_tools.xml .idea/libraries/bouncy_castle.xml .idea/libraries/builder_model.xml .idea/libraries/commons_compress.xml .idea/libraries/easymock_tools.xml .idea/libraries/freemarker_2_3_20.xml .idea/libraries/guava_tools.xml .idea/libraries/kxml2.xml .idea/libraries/lombok_ast.xml .idea/libraries/mockito.xml .idea/modules.xml .idea/vcs.xml build/scripts/layouts.gant updater/src/com/intellij/updater/Runner.java Change-Id: I8e1c173e00cd76c855b8a98543b0a0edfdd99d12
Diffstat (limited to 'platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java')
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java305
1 files changed, 145 insertions, 160 deletions
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
index e10367d583bf..817a042c9bc9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
@@ -20,7 +20,7 @@ import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.*;
import com.intellij.openapi.options.ex.ConfigurableWrapper;
-import com.intellij.openapi.options.ex.NodeConfigurable;
+import com.intellij.openapi.options.ex.SortedConfigurableGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
@@ -49,6 +49,7 @@ import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.TreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
@@ -63,6 +64,7 @@ import java.util.List;
* @author Sergey.Malenkov
*/
final class SettingsTreeView extends JComponent implements Disposable, OptionsEditorColleague {
+ private static final String NODE_ICON = "settings.tree.view.icon";
private static final Color NORMAL_NODE = new JBColor(Gray._60, Gray._140);
private static final Color WRONG_CONTENT = JBColor.RED;
private static final Color MODIFIED_CONTENT = JBColor.BLUE;
@@ -74,8 +76,9 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
private final MyRoot myRoot;
private final JScrollPane myScroller;
private JLabel mySeparator;
- private final MyRenderer myRenderer = new MyRenderer();
private final IdentityHashMap<Configurable, MyNode> myConfigurableToNodeMap = new IdentityHashMap<Configurable, MyNode>();
+ private final IdentityHashMap<UnnamedConfigurable, ConfigurableWrapper> myConfigurableToWrapperMap
+ = new IdentityHashMap<UnnamedConfigurable, ConfigurableWrapper>();
private final MergingUpdateQueue myQueue = new MergingUpdateQueue("SettingsTreeView", 150, false, this, this, this)
.setRestartTimerOnAdd(true);
@@ -96,9 +99,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myTree.setRowHeight(-1);
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
- myTree.setCellRenderer(myRenderer);
+ myTree.setCellRenderer(new MyRenderer());
myTree.setRootVisible(false);
myTree.setShowsRootHandles(false);
+ myTree.setExpandableItemsEnabled(false);
myScroller = ScrollPaneFactory.createScrollPane(myTree, true);
myScroller.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
@@ -139,7 +143,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
@NotNull
String[] getPathNames(Configurable configurable) {
ArrayDeque<String> path = new ArrayDeque<String>();
- MyNode node = myConfigurableToNodeMap.get(configurable);
+ MyNode node = findNode(configurable);
while (node != null) {
path.push(node.myDisplayName);
SimpleNode parent = node.getParent();
@@ -157,8 +161,9 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
@Nullable
- SimpleNode findNode(Configurable configurable) {
- return myConfigurableToNodeMap.get(configurable);
+ MyNode findNode(Configurable configurable) {
+ ConfigurableWrapper wrapper = myConfigurableToWrapperMap.get(configurable);
+ return myConfigurableToNodeMap.get(wrapper != null ? wrapper : configurable);
}
@Nullable
@@ -180,6 +185,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (configurable instanceof ConfigurableWrapper) {
ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
configurable = wrapper.getConfigurable();
+ myConfigurableToWrapperMap.put(configurable, wrapper);
}
if (type.isInstance(configurable)) {
return type.cast(configurable);
@@ -194,7 +200,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
return wrapper.getExtensionPoint().getProject();
}
- return findConfigurableProject(myConfigurableToNodeMap.get(configurable));
+ return findConfigurableProject(findNode(configurable));
}
@Nullable
@@ -214,15 +220,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
@Nullable
- private ConfigurableGroup findConfigurableGroupAt(int x, int y) {
+ private String findGroupNameAt(int x, int y) {
TreePath path = myTree.getClosestPathForLocation(x - myTree.getX(), y - myTree.getY());
while (path != null) {
MyNode node = extractNode(path);
if (node == null) {
return null;
}
- if (node.myComposite instanceof ConfigurableGroup) {
- return (ConfigurableGroup)node.myComposite;
+ if (myRoot == node.getParent()) {
+ return node.myDisplayName;
}
path = path.getParentPath();
}
@@ -267,10 +273,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
mySeparator.setFont(getFont().deriveFont(Font.BOLD));
}
int height = mySeparator.getPreferredSize().height;
- ConfigurableGroup group = findConfigurableGroupAt(0, height);
- if (group != null && group == findConfigurableGroupAt(0, -myRenderer.getSeparatorHeight())) {
+ String group = findGroupNameAt(0, height);
+ if (group != null && group.equals(findGroupNameAt(0, 0))) {
mySeparator.setBorder(BorderFactory.createEmptyBorder(0, 18, 0, 0));
- mySeparator.setText(group.getDisplayName());
+ mySeparator.setText(group);
Rectangle bounds = myScroller.getViewport().getBounds();
if (bounds.height > height) {
@@ -319,7 +325,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
public void run() {
if (configurable != myQueuedConfigurable) return;
- MyNode editorNode = myConfigurableToNodeMap.get(configurable);
+ MyNode editorNode = findNode(configurable);
FilteringTreeStructure.FilteringNode editorUiNode = myBuilder.getVisibleNodeFor(editorNode);
if (editorUiNode == null) return;
@@ -353,7 +359,8 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
private void fireSelected(Configurable configurable, ActionCallback callback) {
- myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
+ ConfigurableWrapper wrapper = myConfigurableToWrapperMap.get(configurable);
+ myFilter.myContext.fireSelected(wrapper != null ? wrapper : configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
}
@Override
@@ -396,11 +403,13 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (myGroups == null || myGroups.length == 0) {
return NO_CHILDREN;
}
- SimpleNode[] result = new SimpleNode[myGroups.length];
- for (int i = 0; i < myGroups.length; i++) {
- result[i] = new MyNode(this, myGroups[i]);
+ ArrayList<MyNode> list = new ArrayList<MyNode>();
+ for (ConfigurableGroup group : myGroups) {
+ for (Configurable configurable : group.getConfigurables()) {
+ list.add(new MyNode(this, configurable, 0));
+ }
}
- return result;
+ return list.toArray(new SimpleNode[list.size()]);
}
}
@@ -408,21 +417,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
private final Configurable.Composite myComposite;
private final Configurable myConfigurable;
private final String myDisplayName;
+ private final int myLevel;
- private MyNode(CachingSimpleNode parent, Configurable configurable) {
+ private MyNode(CachingSimpleNode parent, Configurable configurable, int level) {
super(parent);
myComposite = configurable instanceof Configurable.Composite ? (Configurable.Composite)configurable : null;
myConfigurable = configurable;
String name = configurable.getDisplayName();
myDisplayName = name != null ? name.replace("\n", " ") : "{ " + configurable.getClass().getSimpleName() + " }";
- }
-
- private MyNode(CachingSimpleNode parent, ConfigurableGroup group) {
- super(parent);
- myComposite = group;
- myConfigurable = group instanceof Configurable ? (Configurable)group : null;
- String name = group.getDisplayName();
- myDisplayName = name != null ? name.replace("\n", " ") : "{ " + group.getClass().getSimpleName() + " }";
+ myLevel = level;
}
@Override
@@ -439,7 +442,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
SimpleNode[] result = new SimpleNode[configurables.length];
for (int i = 0; i < configurables.length; i++) {
- result[i] = new MyNode(this, configurables[i]);
+ result[i] = new MyNode(this, configurables[i], myLevel + 1);
if (myConfigurable != null) {
myFilter.myContext.registerKid(myConfigurable, configurables[i]);
}
@@ -453,25 +456,17 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
}
- private final class MyRenderer extends GroupedElementsRenderer.Tree {
- private JLabel myNodeIcon;
- private JLabel myProjectIcon;
-
- protected JComponent createItemComponent() {
- myTextLabel = new ErrorLabel();
- return myTextLabel;
- }
+ private final class MyRenderer extends JPanel implements TreeCellRenderer {
+ private final JLabel myTextLabel = new ErrorLabel();
+ private final JLabel myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
+ private final JLabel myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
- @Override
- protected void layout() {
- myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
- myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
- myNodeIcon.setOpaque(false);
- myTextLabel.setOpaque(false);
- myProjectIcon.setOpaque(false);
- myRendererComponent.add(BorderLayout.CENTER, myComponent);
- myRendererComponent.add(BorderLayout.WEST, myNodeIcon);
- myRendererComponent.add(BorderLayout.EAST, myProjectIcon);
+ public MyRenderer() {
+ super(new BorderLayout());
+ myNodeIcon.setName(NODE_ICON);
+ add(BorderLayout.CENTER, myTextLabel);
+ add(BorderLayout.WEST, myNodeIcon);
+ add(BorderLayout.EAST, myProjectIcon);
}
public Component getTreeCellRendererComponent(JTree tree,
@@ -482,7 +477,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
int row,
boolean focused) {
myTextLabel.setFont(UIUtil.getLabelFont());
- myRendererComponent.setBackground(selected ? UIUtil.getTreeSelectionBackground() : myTree.getBackground());
+ setPreferredSize(null);
MyNode node = extractNode(value);
if (node == null) {
@@ -494,28 +489,19 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (myRoot == node.getParent()) {
myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
}
- TreePath path = tree.getPathForRow(row);
- if (path == null) {
- if (value instanceof DefaultMutableTreeNode) {
- path = new TreePath(((DefaultMutableTreeNode)value).getPath());
- }
- }
- int forcedWidth = 2000;
- if (path != null && tree.isVisible()) {
- Rectangle visibleRect = tree.getVisibleRect();
-
- int nestingLevel = tree.isRootVisible() ? path.getPathCount() - 1 : path.getPathCount() - 2;
-
- int left = UIUtil.getTreeLeftChildIndent();
- int right = UIUtil.getTreeRightChildIndent();
-
+ if (tree.isVisible()) {
+ int indent = node.myLevel * (UIUtil.getTreeLeftChildIndent() + UIUtil.getTreeRightChildIndent());
Insets treeInsets = tree.getInsets();
-
- int indent = (left + right) * nestingLevel + (treeInsets != null ? treeInsets.left + treeInsets.right : 0);
-
- forcedWidth = visibleRect.width > 0 ? visibleRect.width - indent : forcedWidth;
+ if (treeInsets != null) {
+ indent += treeInsets.left + treeInsets.right;
+ }
+ int visibleWidth = tree.getVisibleRect().width;
+ if (visibleWidth > indent) {
+ Dimension size = getPreferredSize();
+ size.width = visibleWidth - indent;
+ //setPreferredSize(size);
+ }
}
- myRendererComponent.setPrefereedWidth(forcedWidth - 4);
}
// update font color for modified configurables
myTextLabel.setForeground(selected ? UIUtil.getTreeSelectionForeground() : NORMAL_NODE);
@@ -537,15 +523,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (parent instanceof MyNode) {
if (myRoot == parent.getParent()) {
project = findConfigurableProject(node); // show icon for top-level nodes
- if (node.myConfigurable instanceof NodeConfigurable) { // special case for custom subgroups (build.tools)
- Configurable[] configurables = ((NodeConfigurable)node.myConfigurable).getConfigurables();
+ if (node.myConfigurable instanceof SortedConfigurableGroup) { // special case for custom subgroups (build.tools)
+ Configurable[] configurables = ((SortedConfigurableGroup)node.myConfigurable).getConfigurables();
if (configurables != null) { // assume that all configurables have the same project
project = findConfigurableProject(configurables[0]);
}
}
}
- else if (((MyNode)parent).myConfigurable instanceof NodeConfigurable) {
- if (((MyNode)node.getParent()).myConfigurable instanceof NodeConfigurable) {
+ else if (((MyNode)parent).myConfigurable instanceof SortedConfigurableGroup) {
+ if (((MyNode)node.getParent()).myConfigurable instanceof SortedConfigurableGroup) {
project = findConfigurableProject(node); // special case for custom subgroups
}
}
@@ -564,25 +550,20 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myProjectIcon.setVisible(false);
}
// configure node icon
- if (value instanceof DefaultMutableTreeNode) {
- DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
- TreePath treePath = new TreePath(treeNode.getPath());
- myNodeIcon.setIcon(myTree.getHandleIcon(treeNode, treePath));
- }
- else {
- myNodeIcon.setIcon(null);
+ Icon nodeIcon = null;
+ if (node != null) {
+ if (0 == node.getChildCount()) {
+ nodeIcon = myTree.getEmptyHandle();
+ }
+ else if (value instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
+ nodeIcon = myTree.isExpanded(new TreePath(treeNode.getPath()))
+ ? myTree.getExpandedHandle()
+ : myTree.getCollapsedHandle();
+ }
}
- return myRendererComponent;
- }
-
- int getSeparatorHeight() {
- return mySeparatorComponent.getParent() == null ? 0 : mySeparatorComponent.getPreferredSize().height;
- }
-
- public boolean isUnderHandle(Point point) {
- Point handlePoint = SwingUtilities.convertPoint(myRendererComponent, point, myNodeIcon);
- Rectangle bounds = myNodeIcon.getBounds();
- return bounds.x < handlePoint.x && bounds.getMaxX() >= handlePoint.x;
+ myNodeIcon.setIcon(nodeIcon);
+ return this;
}
}
@@ -616,11 +597,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
@Override
public void setUI(TreeUI ui) {
- TreeUI actualUI = ui;
- if (!(ui instanceof MyTreeUi)) {
- actualUI = new MyTreeUi();
- }
- super.setUI(actualUI);
+ super.setUI(ui instanceof MyTreeUi ? ui : new MyTreeUi());
}
@Override
@@ -659,84 +636,92 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
@Override
- protected void processMouseEvent(MouseEvent e) {
+ protected void processMouseEvent(MouseEvent event) {
MyTreeUi ui = (MyTreeUi)myTree.getUI();
- boolean toggleNow = MouseEvent.MOUSE_RELEASED == e.getID()
- && UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED)
- && !ui.isToggleEvent(e);
-
- if (toggleNow || MouseEvent.MOUSE_PRESSED == e.getID()) {
- TreePath path = getPathForLocation(e.getX(), e.getY());
- if (path != null) {
- Rectangle bounds = getPathBounds(path);
- if (bounds != null && path.getLastPathComponent() instanceof DefaultMutableTreeNode) {
- DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
- boolean selected = isPathSelected(path);
- boolean expanded = isExpanded(path);
- Component comp =
- myRenderer.getTreeCellRendererComponent(this, node, selected, expanded, node.isLeaf(), getRowForPath(path), isFocusOwner());
-
- comp.setBounds(bounds);
- comp.validate();
-
- Point point = new Point(e.getX() - bounds.x, e.getY() - bounds.y);
- if (myRenderer.isUnderHandle(point)) {
- if (toggleNow) {
- ui.toggleExpandState(path);
- }
- e.consume();
- return;
- }
- }
- }
+ if (!ui.processMouseEvent(event)) {
+ super.processMouseEvent(event);
}
-
- super.processMouseEvent(e);
}
+ }
- private final class MyTreeUi extends WideSelectionTreeUI {
+ private static final class MyTreeUi extends WideSelectionTreeUI {
+ boolean processMouseEvent(MouseEvent event) {
+ if (super.tree instanceof SimpleTree) {
+ SimpleTree tree = (SimpleTree)super.tree;
- @Override
- public void toggleExpandState(TreePath path) {
- super.toggleExpandState(path);
- }
+ boolean toggleNow = MouseEvent.MOUSE_RELEASED == event.getID()
+ && UIUtil.isActionClick(event, MouseEvent.MOUSE_RELEASED)
+ && !isToggleEvent(event);
- @Override
- public boolean isToggleEvent(MouseEvent event) {
- return super.isToggleEvent(event);
+ if (toggleNow || MouseEvent.MOUSE_PRESSED == event.getID()) {
+ Component component = tree.getDeepestRendererComponentAt(event.getX(), event.getY());
+ if (component != null && NODE_ICON.equals(component.getName())) {
+ if (toggleNow) {
+ toggleExpandState(tree.getPathForLocation(event.getX(), event.getY()));
+ }
+ event.consume();
+ return true;
+ }
+ }
}
+ return false;
+ }
- @Override
- protected boolean shouldPaintExpandControl(TreePath path,
- int row,
- boolean isExpanded,
- boolean hasBeenExpanded,
- boolean isLeaf) {
- return false;
- }
+ @Override
+ protected boolean shouldPaintExpandControl(TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
+ return false;
+ }
- @Override
- protected void paintHorizontalPartOfLeg(Graphics g,
- Rectangle clipBounds,
- Insets insets,
- Rectangle bounds,
- TreePath path,
- int row,
- boolean isExpanded,
- boolean hasBeenExpanded,
- boolean isLeaf) {
+ @Override
+ protected void paintHorizontalPartOfLeg(Graphics g,
+ Rectangle clipBounds,
+ Insets insets,
+ Rectangle bounds,
+ TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
- }
+ }
- @Override
- protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) {
- }
+ @Override
+ protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) {
+ }
- @Override
- public void paint(Graphics g, JComponent c) {
- GraphicsUtil.setupAntialiasing(g);
- super.paint(g, c);
+ @Override
+ public void paint(Graphics g, JComponent c) {
+ GraphicsUtil.setupAntialiasing(g);
+ super.paint(g, c);
+ }
+
+ @Override
+ protected void paintRow(Graphics g,
+ Rectangle clipBounds,
+ Insets insets,
+ Rectangle bounds,
+ TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
+ if (tree != null) {
+ int width = tree.getWidth();
+ Container parent = tree.getParent();
+ if (parent instanceof JViewport) {
+ JViewport viewport = (JViewport)parent;
+ width = viewport.getWidth() - viewport.getViewPosition().x;
+ }
+ width -= bounds.x;
+ if (bounds.width < width) {
+ bounds.width = width;
+ }
}
+ super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf);
}
}