changeset 1969:c302f038ab1e

Allow post-instantiation updating of TreeMapComponent model PR3059 Reviewed-by: jkang Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-June/019844.html Original-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-September/015799.html
author James Aziz <jaziz@redhat.com>
date Wed, 29 Jun 2016 12:22:56 -0400
parents 22f2df5a0100
children 53d2c83f487a
files client/swing/src/main/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponent.java client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponentTest.java vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SwingHeapTreeMapView.java
diffstat 3 files changed, 191 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponent.java	Wed Jun 29 11:45:27 2016 -0400
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponent.java	Wed Jun 29 12:22:56 2016 -0400
@@ -70,8 +70,10 @@
 import javax.swing.border.LineBorder;
 
 import com.redhat.thermostat.client.swing.ThermostatSwingCursors;
+import com.redhat.thermostat.client.swing.internal.LocaleResources;
 import com.redhat.thermostat.common.Size;
 import com.redhat.thermostat.common.Size.Unit;
+import com.redhat.thermostat.shared.locale.Translate;
 
 /**
  * This class allows to represent a hierarchical data structure as a TreeMap.
@@ -80,6 +82,8 @@
  */
 public class TreeMapComponent extends JComponent {
 
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
     private static final long serialVersionUID = 1L;
 
     /**
@@ -95,7 +99,7 @@
     /**
      * The tree to render as TreeMap.
      */
-    TreeMapNode tree;
+    private TreeMapNode tree;
 
     /**
      * Horizontal and vertical padding for nested component.
@@ -173,34 +177,44 @@
 
     private ToolTipRenderer tooltipRenderer;
 
+    public TreeMapComponent(Dimension d) {
+        this(null, d, null);
+    }
+
     /**
      * Constructor. It draw a TreeMap of the given tree in according to the 
      * {@Dimension} object in input.
      * 
      * @param tree the tree to represent as TreeMap.
      * @param d the dimension the TreeMap will fulfill.
-     *
      * @param renderer
-     * @throws NullPointerException if one of the parameters is null
+     * @throws NullPointerException if the dimension is null
      */
     public TreeMapComponent(TreeMapNode tree, Dimension d, ToolTipRenderer renderer) {
         super();
-        Objects.requireNonNull(tree);
         Objects.requireNonNull(d);
         this.tree = tree;
         lastDim = getSize();
         this.zoomStack = new Stack<>();
-        this.zoomStack.push(this.tree);
         this.observers = new ArrayList<>();
         this.tooltipRenderer = renderer;
 
+        if (tree != null) {
+            this.zoomStack.push(this.tree);
+            processAndDrawTreeMap(d);
+        }
+    }
+
+    public void processAndDrawTreeMap(Dimension d) {
+        Objects.requireNonNull(d);
+        Objects.requireNonNull(this.tree);
         // assign a rectangle to the tree's root in order to process the tree.
         Rectangle2D.Double area = new Rectangle2D.Double(0, 0, d.width, d.height);
 
         // calculate rectangles of tree's subtrees
         TreeProcessor.processTreeMap(tree, area);
 
-        drawTreeMap(tree); 
+        drawTreeMap(tree);
 
         addResizeListener(this);
         repaint();
@@ -214,6 +228,12 @@
         return this.tree;
     }
 
+    public void setModel(TreeMapNode tree) {
+        this.tree = Objects.requireNonNull(tree);
+        this.zoomStack.clear();
+        this.zoomStack.push(this.tree);
+    }
+
     public void setToolTipRenderer(ToolTipRenderer renderer) {
         this.tooltipRenderer = renderer;
     }
@@ -343,7 +363,7 @@
                     Dimension newDim = container.getSize();
 
                     if (isChangedSize(newDim)) {
-                        redrawTreeMap(tree); 
+                        redrawTreeMap(Objects.requireNonNull(tree));
                     }
                 } 
             }            
@@ -388,9 +408,11 @@
     /**
      * This method recalculates and redraws the TreeMap in according to the size
      * of this component and the actual {@link TreeMapNode} object.
+     *
+     * Package-private for testing only.
      */
-    private void redrawTreeMap(TreeMapNode newRoot) {
-        tree = newRoot;
+    void redrawTreeMap(TreeMapNode newRoot) {
+        tree = Objects.requireNonNull(newRoot);
         Rectangle2D.Double newArea = tree.getRectangle();
         // give to the root node the size of this object so it can be recalculated
         newArea.width = getSize().width;
@@ -405,7 +427,7 @@
 
     boolean isZoomInEnabled(TreeMapNode node) {
         return !(node == null
-                || node.equals(this.tree)
+                || node.equals(Objects.requireNonNull(this.tree))
                 || node.isLeaf());
     }
 
@@ -676,7 +698,7 @@
         public void setNode(TreeMapNode node) {
             this.node = node;
             this.color = node.getColor();
-            this.setToolTipText(TreeMapComponent.this.tooltipRenderer.render(node));
+            this.setToolTipText(Objects.requireNonNull(TreeMapComponent.this.tooltipRenderer).render(node));
         }
         
         public TreeMapNode getNode() {
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponentTest.java	Wed Jun 29 11:45:27 2016 -0400
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponentTest.java	Wed Jun 29 12:22:56 2016 -0400
@@ -50,9 +50,14 @@
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import com.redhat.thermostat.client.swing.internal.LocaleResources;
+import com.redhat.thermostat.shared.locale.Translate;
+
 
 public class TreeMapComponentTest {
 
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
     private TreeMapComponent treeMap;
     private static TreeMapNode tree;
     private static TreeMapNode node1;
@@ -77,36 +82,74 @@
             @Override
             public void run() {
 
-                boolean catched = false;
+                boolean caught = false;
+
+                try {
+                    treeMap = new TreeMapComponent(dim);
+                } catch (NullPointerException e) {
+                    Assert.fail("Didn't expect exception.");
+                }
+                try {
+                    treeMap = new TreeMapComponent(null);
+                } catch (NullPointerException e) {
+                    caught = true;
+                }
+                assertTrue(caught);
+                caught = false;
 
                 try {
                     treeMap = new TreeMapComponent(tree, dim, new TreeMapComponent.WeightAsSizeRenderer());
                     // pass
-                 } catch(NullPointerException e) {
+                } catch (NullPointerException e) {
                     Assert.fail("Didn't expect exception.");
-                 }
+                }
                 try {
                     treeMap = new TreeMapComponent(null, null, new TreeMapComponent.WeightAsSizeRenderer());
-                } catch(NullPointerException e) {
-                    catched = true;
+                } catch (NullPointerException e) {
+                    caught = true;
                 }
-                assertTrue(catched);
-                catched = false;
+                assertTrue(caught);
+                caught = false;
 
                 try {
                     treeMap = new TreeMapComponent(tree, null, new TreeMapComponent.WeightAsSizeRenderer());
-                } catch(NullPointerException e) {
-                    catched = true;
+                } catch (NullPointerException e) {
+                    caught = true;
                 }
-                assertTrue(catched);
-                catched = false;
+                assertTrue(caught);
+            }
+        });
+    }
+
+    @Test
+    public final void testProcessAndDrawTreeMap() throws InvocationTargetException, InterruptedException {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    treeMap = new TreeMapComponent(tree, dim, new TreeMapComponent.WeightAsSizeRenderer());
+                    treeMap.processAndDrawTreeMap(dim);
+                } catch (NullPointerException e) {
+                    Assert.fail("Didn't expect exception.");
+                }
+
+                boolean caught = false;
+                try {
+                    treeMap = new TreeMapComponent(dim);
+                    treeMap.processAndDrawTreeMap(dim);
+                } catch (NullPointerException e) {
+                    caught = true;
+                }
+                assertTrue(caught);
+                caught = false;
 
                 try {
-                    treeMap = new TreeMapComponent(null, dim, new TreeMapComponent.WeightAsSizeRenderer());
-                } catch(NullPointerException e) {
-                    catched = true;
+                    treeMap = new TreeMapComponent(tree, dim, new TreeMapComponent.WeightAsSizeRenderer());
+                    treeMap.processAndDrawTreeMap(null);
+                } catch (NullPointerException e) {
+                    caught = true;
                 }
-                assertTrue(catched);
+                assertTrue(caught);
             }
         });
     }
@@ -124,7 +167,69 @@
     }
 
     @Test
+    public final void testSetModel() {
+        try {
+            treeMap = new TreeMapComponent(dim);
+            treeMap.setModel(tree);
+        } catch (NullPointerException e) {
+            Assert.fail("Didn't expect exception.");
+        }
+
+        boolean caught = false;
+        try {
+            treeMap = new TreeMapComponent(dim);
+            treeMap.setModel(null);
+        } catch (NullPointerException e) {
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public final void testRedrawTreeMap() throws InvocationTargetException, InterruptedException {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    treeMap = new TreeMapComponent(dim);
+                    treeMap.setToolTipRenderer(new TreeMapComponent.WeightAsSizeRenderer());
+                    treeMap.redrawTreeMap(node1);
+                } catch (NullPointerException e) {
+                    Assert.fail("Didn't expect exception.");
+                }
+
+                boolean caught = false;
+                try {
+                    treeMap = new TreeMapComponent(dim);
+                    treeMap.setToolTipRenderer(new TreeMapComponent.WeightAsSizeRenderer());
+                    treeMap.redrawTreeMap(null);
+                } catch (NullPointerException e) {
+                    caught = true;
+                }
+                assertTrue(caught);
+            }
+        });
+    }
+
+    @Test
     public final void testIsZoomInEnabled() throws InvocationTargetException, InterruptedException {
+        try {
+            treeMap = new TreeMapComponent(dim);
+            treeMap.setModel(tree);
+            treeMap.isZoomInEnabled(node1);
+        } catch (NullPointerException e) {
+            Assert.fail("Didn't expect exception.");
+        }
+
+        boolean caught = false;
+        try {
+            treeMap = new TreeMapComponent(dim);
+            treeMap.isZoomInEnabled(node1);
+        } catch (NullPointerException e) {
+            caught = true;
+        }
+        assertTrue(caught);
+
         SwingUtilities.invokeAndWait(new Runnable() {
             @Override
             public void run() {
@@ -216,7 +321,6 @@
         });
     }
 
-
     @Test
     public final void testClearZoomCallsStack() throws InvocationTargetException, InterruptedException {
         SwingUtilities.invokeAndWait(new Runnable() {
@@ -235,30 +339,30 @@
             }
         });
     }
-    
+
     @Test
     public final void testObserver() throws InvocationTargetException, InterruptedException {
         SwingUtilities.invokeAndWait(new Runnable() {
             boolean zoomedIn = false;
             boolean zoomedOut = false;
             boolean zoomedFull = false;
-            
+
             TreeMapObserver observer = new TreeMapObserver() {
                 @Override
                 public void notifyZoomOut() {
                     zoomedOut = true;
                 }
-                
+
                 @Override
                 public void notifyZoomIn(TreeMapNode node) {
                     zoomedIn = true;
                 }
-                
+
                 @Override
                 public void notifyZoomFull() {
                     zoomedFull = true;
                 }
-                
+
                 @Override
                 public void notifySelection(TreeMapNode node) {
                 }
@@ -273,21 +377,43 @@
 
                 treeMap = new TreeMapComponent(tree, dim, new TreeMapComponent.WeightAsSizeRenderer());
                 treeMap.register(observer);
-                
+
                 treeMap.zoomIn(child);
                 assertTrue("Should have zoomed in on child", zoomedIn);
                 zoomedIn = false;
 
                 treeMap.zoomIn(grandchild);
                 assertFalse("Should not have zoomed in on grandchild", zoomedIn);
-                
+
                 treeMap.zoomOut();
                 assertTrue("Should have zoomed out", zoomedOut);
-                
+
                 treeMap.zoomIn(child);
                 treeMap.zoomFull();
                 assertTrue("Should have zoomed full", zoomedFull);
             }
         });
     }
+
+    @Test
+    public final void testSetNode() {
+        try {
+            treeMap = new TreeMapComponent(dim);
+            treeMap.setToolTipRenderer(new TreeMapComponent.WeightAsSizeRenderer());
+            TreeMapComponent.Comp comp = treeMap.new Comp();
+            comp.setNode(node1);
+        } catch (NullPointerException e) {
+            Assert.fail("Didn't expect exception.");
+        }
+
+        boolean caught = false;
+        try {
+            treeMap = new TreeMapComponent(dim);
+            TreeMapComponent.Comp comp = treeMap.new Comp();
+            comp.setNode(node1);
+        } catch (NullPointerException e) {
+            caught = true;
+        }
+        assertTrue(caught);
+    }
 }
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SwingHeapTreeMapView.java	Wed Jun 29 11:45:27 2016 -0400
+++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SwingHeapTreeMapView.java	Wed Jun 29 12:22:56 2016 -0400
@@ -50,18 +50,23 @@
 
 public class SwingHeapTreeMapView extends HeapTreeMapView implements SwingComponent {
     
+    private TreeMapComponent treeMap;
+    private Dimension d;
     private final JPanel panel;
-
-    private TreeMapComponent treeMap;
     
     public SwingHeapTreeMapView() {
+        d = new Dimension();
+        treeMap = new TreeMapComponent(d);
+        treeMap.setToolTipRenderer(new TreeMapComponent.WeightAsSizeRenderer());
+
         panel = new JPanel();
         panel.setLayout(new BorderLayout());
     }
 
     @Override
     public void display(ObjectHistogram histogram) {
-        treeMap = new TreeMapComponent(HistogramConverter.convertToTreeMap(histogram), new Dimension(), new TreeMapComponent.WeightAsSizeRenderer());
+        treeMap.setModel(HistogramConverter.convertToTreeMap(histogram));
+        treeMap.processAndDrawTreeMap(d);
         panel.add(treeMap, BorderLayout.CENTER);
         panel.add(new TreeMapToolbar(treeMap), BorderLayout.NORTH);
     }