Mercurial > hg > release > thermostat-1.6
changeset 1721:56d0c53547c1
Prevent TreeMapComponent from zooming in to leaf nodes
Also prevent leaf nodes from being highlighted on click. When the mouse hovers
over an internal (non-leaf) node, the cursor is changed to a zoom icon to
indicate that double-clicking this region will zoom the view in.
Reviewed-by: omajid, jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-August/015084.html
PR2577
author | Andrew Azores <aazores@redhat.com> |
---|---|
date | Wed, 12 Aug 2015 16:46:08 -0400 |
parents | 53812b60ea0f |
children | 601243b928f6 |
files | client/swing/src/main/java/com/redhat/thermostat/client/swing/ThermostatSwingCursors.java vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapComponent.java vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNode.java vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNodeTest.java |
diffstat | 4 files changed, 126 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/ThermostatSwingCursors.java Wed Aug 12 16:46:08 2015 -0400 @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2015 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing; + +import com.redhat.thermostat.client.swing.components.FontAwesomeIcon; + +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Toolkit; + +public final class ThermostatSwingCursors { + + private static final Dimension BEST_CURSOR_DIMENSION = Toolkit.getDefaultToolkit().getBestCursorSize(18, 18); + private static final int CURSOR_SIZE = (int) Math.min(BEST_CURSOR_DIMENSION.getWidth(), BEST_CURSOR_DIMENSION.getHeight()); + + private ThermostatSwingCursors() {} + + public static Cursor getZoomIconCursor() { + char zoomIconId = '\uf00e'; + Point zoomCursorHotspot = new Point(CURSOR_SIZE / 2, CURSOR_SIZE / 2); + String zoomCursorName = "zoom-cursor"; + return Toolkit.getDefaultToolkit().createCustomCursor( + new FontAwesomeIcon(zoomIconId, CURSOR_SIZE).getImage(), + zoomCursorHotspot, + zoomCursorName + ); + } + +}
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapComponent.java Tue Aug 11 16:44:11 2015 +0200 +++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapComponent.java Wed Aug 12 16:46:08 2015 -0400 @@ -40,6 +40,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; @@ -65,6 +66,7 @@ import javax.swing.border.EtchedBorder; import javax.swing.border.LineBorder; +import com.redhat.thermostat.client.swing.ThermostatSwingCursors; import com.redhat.thermostat.vm.heap.analysis.common.ObjectHistogram; /** @@ -584,6 +586,7 @@ super(); thisComponent = this; addClickListener(this); + addMouseListener(this); } @Override @@ -642,7 +645,9 @@ // two middle click: zoom full if (e.getClickCount() == 2) { if (SwingUtilities.isLeftMouseButton(e)) { - zoomIn(getNode()); + if (!getNode().isLeaf()) { + zoomIn(getNode()); + } } else if (SwingUtilities.isRightMouseButton(e)) { zoomOut(); } else { @@ -655,16 +660,57 @@ } /** + * Add a mouse motion listener to this component. This allows for the mouse cursor to be changed into a + * magnifying glass icon when the cursor enters a zoomable component, and back to a default cursor when it + * exits a zoomable component. + * @param component the component which will have the mouse motion listener. + */ + private void addMouseListener(final JComponent component) { + MouseListener listener = new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + if (getNode().isLeaf()) { + setDefaultCursor(); + } else { + setZoomableCursor(); + } + } + + @Override + public void mouseExited(MouseEvent e) { + if (!getNode().isLeaf()) { + setDefaultCursor(); + } else { + setZoomableCursor(); + } + } + + private void setZoomableCursor() { + component.setCursor(ThermostatSwingCursors.getZoomIconCursor()); + } + + private void setDefaultCursor() { + component.setCursor(Cursor.getDefaultCursor()); + } + }; + component.addMouseListener(listener); + } + + /** * This method gives a darker color to this component and restore the * original color to the last selected component. */ private void selectComp() { if (lastClicked != null) { - lastClicked.setColor(lastClicked.getColor().brighter()); + if (!lastClicked.getNode().isLeaf()) { + lastClicked.setColor(lastClicked.getColor().brighter()); + } lastClicked.repaint(); } lastClicked = thisComponent; - setColor(getColor().darker()); + if (!getNode().isLeaf()) { + setColor(getColor().darker()); + } repaint(); } }
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNode.java Tue Aug 11 16:44:11 2015 +0200 +++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNode.java Wed Aug 12 16:46:08 2015 -0400 @@ -225,6 +225,10 @@ public List<TreeMapNode> getChildren() { return this.children; } + + public boolean isLeaf() { + return getChildren().isEmpty(); + } /** * Set as children list of this object the list given in input.
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNodeTest.java Tue Aug 11 16:44:11 2015 +0200 +++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNodeTest.java Wed Aug 12 16:46:08 2015 -0400 @@ -45,6 +45,7 @@ import java.awt.Color; import java.awt.geom.Rectangle2D; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -97,6 +98,14 @@ assertTrue(1 == node.getChildren().size()); } + @Test + public final void testIsLeaf() { + assertTrue(node.isLeaf()); + node.addChild(new TreeMapNode(null, 1)); + assertFalse(node.isLeaf()); + node.setChildren(Collections.<TreeMapNode>emptyList()); + assertTrue(node.isLeaf()); + } @Test public final void testGetAddInfo() {