diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index 4251b47175d6..c1e80f64f551 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -34,6 +34,7 @@ import javax.swing.tree.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; +import java.lang.reflect.Method; import java.util.*; import java.util.List; import java.util.function.Consumer; @@ -41,6 +42,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; +import static com.intellij.util.ReflectionUtil.getDeclaredMethod; import static java.util.stream.Collectors.toList; public final class TreeUtil { @@ -1060,6 +1062,33 @@ public final class TreeUtil { } } + public static int getNodeDepth(@NotNull JTree tree, @NotNull TreePath path) { + int depth = path.getPathCount(); + if (!tree.isRootVisible()) depth--; + if (!tree.getShowsRootHandles()) depth--; + return depth; + } + + private static final class LazyRowX { + static final Method METHOD = getDeclaredMethod(BasicTreeUI.class, "getRowX", int.class, int.class); + } + + public static int getNodeRowX(@NotNull JTree tree, int row) { + Method method = LazyRowX.METHOD; + if (method == null) return -1; // system error + TreePath path = tree.getPathForRow(row); + if (path == null) return -1; // path does not exist + int depth = getNodeDepth(tree, path); + if (depth < 0) return -1; // root is not visible + try { + return (Integer)method.invoke(tree.getUI(), row, depth); + } + catch (Exception exception) { + LOG.error(exception); + return -1; // unexpected + } + } + @NotNull public static RelativePoint getPointForSelection(@NotNull JTree aTree) { final int[] rows = aTree.getSelectionRows(); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java index cf29f303acc7..c2cac63f3df9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java @@ -22,7 +22,6 @@ import com.intellij.ide.ui.search.SearchUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.QuickList; import com.intellij.openapi.actionSystem.impl.ActionMenu; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.keymap.KeyMapBundle; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapUtil; @@ -50,19 +49,17 @@ import org.jetbrains.annotations.Nullable; import javax.accessibility.AccessibleContext; import javax.swing.*; import javax.swing.event.TreeSelectionListener; -import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; -import java.lang.reflect.Method; import java.util.*; import java.util.List; import static com.intellij.util.ui.UIUtil.useSafely; +import static com.intellij.util.ui.tree.TreeUtil.getNodeRowX; public class ActionsTree { - private static final Logger LOG = Logger.getInstance(ActionsTree.class); private static final Icon EMPTY_ICON = EmptyIcon.ICON_18; private static final Icon CLOSE_ICON = AllIcons.Nodes.Folder; @@ -592,8 +589,7 @@ public class ActionsTree { icon = link.getIcon(); setIcon(getEvenIcon(link.getIcon())); Rectangle treeVisibleRect = tree.getVisibleRect(); - TreePath path = tree.getPathForRow(row); - int rowX = path != null ? getRowX((BasicTreeUI)tree.getUI(), row, path.getPathCount() - 1) : 0; + int rowX = getNodeRowX(tree, row); setupLinkDimensions(treeVisibleRect, rowX); } else { @@ -814,29 +810,6 @@ public class ActionsTree { config.restore(); } - private static Method ourGetRowXMethod = null; - - private static int getRowX(BasicTreeUI ui, int row, int depth) { - if (ourGetRowXMethod == null) { - try { - ourGetRowXMethod = BasicTreeUI.class.getDeclaredMethod("getRowX", int.class, int.class); - ourGetRowXMethod.setAccessible(true); - } - catch (NoSuchMethodException e) { - LOG.error(e); - } - } - if (ourGetRowXMethod != null) { - try { - return (Integer)ourGetRowXMethod.invoke(ui, row, depth); - } - catch (Exception e) { - LOG.error(e); - } - } - return 0; - } - private static class MyColoredTreeCellRenderer extends ColoredTreeCellRenderer { private int myHeight; diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java index 90d99bb8bf0f..1b505bf0c5a8 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java @@ -6,6 +6,7 @@ import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.ui.MouseEventAdapter; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,13 +42,6 @@ public final class DefaultTreeUI extends BasicTreeUI { return false; } - private static int getDepth(@NotNull JTree tree, @NotNull TreePath path) { - int depth = path.getPathCount(); - if (!tree.isRootVisible()) depth--; - if (!tree.getShowsRootHandles()) depth--; - return depth; - } - @NotNull private static Control.Painter getPainter(@NotNull JTree tree) { Object property = tree.getClientProperty(Control.Painter.class); @@ -182,7 +176,7 @@ public final class DefaultTreeUI extends BasicTreeUI { if (bounds == null) break; bounds.y += insets.top; - int depth = getDepth(tree, path); + int depth = TreeUtil.getNodeDepth(tree, path); boolean leaf = isLeaf(path.getLastPathComponent()); boolean expanded = !leaf && cache.getExpandedState(path); boolean selected = tree.isRowSelected(row); @@ -237,7 +231,7 @@ public final class DefaultTreeUI extends BasicTreeUI { protected boolean isLocationInExpandControl(TreePath path, int mouseX, int mouseY) { JTree tree = getTree(); if (tree == null || path == null || isLeaf(path.getLastPathComponent())) return false; - int depth = getDepth(tree, path); + int depth = TreeUtil.getNodeDepth(tree, path); Control.Painter painter = getPainter(tree); Insets insets = tree.getInsets(); if (insets != null) mouseX -= insets.left; @@ -250,7 +244,7 @@ public final class DefaultTreeUI extends BasicTreeUI { if (tree == null) return 0; TreePath path = getPathForRow(tree, row); if (path == null) return 0; - return getPainter(tree).getRendererOffset(control, getDepth(tree, path), isLeaf(path.getLastPathComponent())); + return getPainter(tree).getRendererOffset(control, TreeUtil.getNodeDepth(tree, path), isLeaf(path.getLastPathComponent())); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java index 02413a04fe8b..abf8d0e68073 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java @@ -1,7 +1,6 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xdebugger.impl.ui.tree; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ColoredTreeCellRenderer; @@ -18,18 +17,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.plaf.basic.BasicTreeUI; -import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.MouseEvent; -import java.lang.reflect.Method; + +import static com.intellij.util.ui.tree.TreeUtil.getNodeRowX; /** * @author nik */ class XDebuggerTreeRenderer extends ColoredTreeCellRenderer { - private static final Logger LOG = Logger.getInstance(XDebuggerTreeRenderer.class); - private final MyColoredTreeCellRenderer myLink = new MyColoredTreeCellRenderer(); private boolean myHaveLink; private int myLinkOffset; @@ -57,8 +53,7 @@ class XDebuggerTreeRenderer extends ColoredTreeCellRenderer { setIcon(node.getIcon()); Rectangle treeVisibleRect = tree.getParent() instanceof JViewport ? ((JViewport)tree.getParent()).getViewRect() : tree.getVisibleRect(); - TreePath path = tree.getPathForRow(row); - int rowX = path != null ? getRowX((BasicTreeUI)tree.getUI(), row, path.getPathCount() - 1) : 0; + int rowX = getNodeRowX(tree, row); if (myHaveLink) { setupLinkDimensions(treeVisibleRect, rowX); @@ -86,29 +81,6 @@ class XDebuggerTreeRenderer extends ColoredTreeCellRenderer { putClientProperty(ExpandableItemsHandler.RENDERER_DISABLED, myHaveLink); } - private static Method ourGetRowXMethod = null; - - private static int getRowX(BasicTreeUI ui, int row, int depth) { - if (ourGetRowXMethod == null) { - try { - ourGetRowXMethod = BasicTreeUI.class.getDeclaredMethod("getRowX", int.class, int.class); - ourGetRowXMethod.setAccessible(true); - } - catch (NoSuchMethodException e) { - LOG.error(e); - } - } - if (ourGetRowXMethod != null) { - try { - return (Integer)ourGetRowXMethod.invoke(ui, row, depth); - } - catch (Exception e) { - LOG.error(e); - } - } - return 0; - } - private void setupLinkDimensions(Rectangle treeVisibleRect, int rowX) { Dimension linkSize = myLink.getPreferredSize(); myLinkWidth = linkSize.width; diff --git a/plugins/stream-debugger/src/com/intellij/debugger/streams/ui/impl/TraceTreeCellRenderer.java b/plugins/stream-debugger/src/com/intellij/debugger/streams/ui/impl/TraceTreeCellRenderer.java index d16d643bcf83..26d66226ca46 100644 --- a/plugins/stream-debugger/src/com/intellij/debugger/streams/ui/impl/TraceTreeCellRenderer.java +++ b/plugins/stream-debugger/src/com/intellij/debugger/streams/ui/impl/TraceTreeCellRenderer.java @@ -1,7 +1,6 @@ // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.streams.ui.impl; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ColoredTreeCellRenderer; @@ -19,20 +18,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.plaf.basic.BasicTreeUI; -import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.MouseEvent; -import java.lang.reflect.Method; import static com.intellij.util.ui.UIUtil.useSafely; +import static com.intellij.util.ui.tree.TreeUtil.getNodeRowX; /** * @author Vitaliy.Bibaev */ public class TraceTreeCellRenderer extends ColoredTreeCellRenderer { - private static final Logger LOG = Logger.getInstance(TraceTreeCellRenderer.class); - private final MyColoredTreeCellRenderer myLink = new MyColoredTreeCellRenderer(); private boolean myHaveLink; private int myLinkOffset; @@ -60,8 +55,7 @@ public class TraceTreeCellRenderer extends ColoredTreeCellRenderer { setIcon(node.getIcon()); Rectangle treeVisibleRect = tree.getParent() instanceof JViewport ? ((JViewport)tree.getParent()).getViewRect() : tree.getVisibleRect(); - TreePath path = tree.getPathForRow(row); - int rowX = path != null ? getRowX((BasicTreeUI)tree.getUI(), row, path.getPathCount() - 1) : 0; + int rowX = getNodeRowX(tree, row); if (myHaveLink) { setupLinkDimensions(treeVisibleRect, rowX); @@ -89,29 +83,6 @@ public class TraceTreeCellRenderer extends ColoredTreeCellRenderer { putClientProperty(ExpandableItemsHandler.RENDERER_DISABLED, myHaveLink); } - private static Method ourGetRowXMethod = null; - - private static int getRowX(BasicTreeUI ui, int row, int depth) { - if (ourGetRowXMethod == null) { - try { - ourGetRowXMethod = BasicTreeUI.class.getDeclaredMethod("getRowX", int.class, int.class); - ourGetRowXMethod.setAccessible(true); - } - catch (NoSuchMethodException e) { - LOG.error(e); - } - } - if (ourGetRowXMethod != null) { - try { - return (Integer)ourGetRowXMethod.invoke(ui, row, depth); - } - catch (Exception e) { - LOG.error(e); - } - } - return 0; - } - private void setupLinkDimensions(Rectangle treeVisibleRect, int rowX) { Dimension linkSize = myLink.getPreferredSize(); myLinkWidth = linkSize.width;