changeset 1985:c7d7084f1ed5

Add key bindings to TreeMapComponent 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/015767.html http://icedtea.classpath.org/pipermail/thermostat/2015-October/016708.html
author James Aziz <jaziz@redhat.com>
date Wed, 29 Jun 2016 12:23:09 -0400
parents ddc9c46e66a7
children 38e39491d46a
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
diffstat 2 files changed, 211 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponent.java	Wed Jun 29 12:23:09 2016 -0400
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponent.java	Wed Jun 29 12:23:09 2016 -0400
@@ -46,8 +46,10 @@
 import java.awt.Graphics;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
@@ -59,9 +61,13 @@
 import java.util.Objects;
 import java.util.Stack;
 
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
 import javax.swing.BorderFactory;
+import javax.swing.InputMap;
 import javax.swing.JComponent;
 import javax.swing.JLabel;
+import javax.swing.KeyStroke;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
@@ -185,6 +191,7 @@
         }
 
         addResizeListener(this);
+        addKeyBindings(this);
     }
 
     /**
@@ -349,6 +356,43 @@
         container.addComponentListener(adapter);
     }
 
+    private void addKeyBindings(final JComponent component) {
+        final int NO_MODIFIERS = 0;
+        final String ZOOM_OUT = "zoomOut";
+        final String ZOOM_FULL = "zoomFull";
+        final String ZOOM_IN = "zoomIn";
+        InputMap inputMap = component.getInputMap(WHEN_FOCUSED);
+        ActionMap actionMap = component.getActionMap();
+
+        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, NO_MODIFIERS), ZOOM_OUT);
+        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, NO_MODIFIERS), ZOOM_FULL);
+        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, NO_MODIFIERS), ZOOM_OUT);
+        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, NO_MODIFIERS), ZOOM_IN);
+
+        actionMap.put(ZOOM_OUT, new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                zoomOut();
+                lastClicked = null;
+            }
+        });
+        actionMap.put(ZOOM_FULL, new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                zoomFull();
+                lastClicked = null;
+            }
+        });
+        actionMap.put(ZOOM_IN, new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                if (lastClicked != null) {
+                    zoomIn(lastClicked.getNode());
+                }
+            }
+        });
+    }
+
     /**
      * This method checks if the given container has enough space to instantiate
      * a TreeMapComp object in it. If yes, a Label is cloned from an existing 
@@ -692,6 +736,7 @@
             MouseListener click = new MouseAdapter() {
                 @Override
                 public void mousePressed(MouseEvent e) {
+                    TreeMapComponent.this.requestFocusInWindow();
                     // one left click select the rectangle
                     if (SwingUtilities.isLeftMouseButton(e)) {
                         selectComp();
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponentTest.java	Wed Jun 29 12:23:09 2016 -0400
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/TreeMapComponentTest.java	Wed Jun 29 12:23:09 2016 -0400
@@ -36,25 +36,32 @@
 
 package com.redhat.thermostat.client.swing.components.experimental;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.jfree.chart.renderer.category.GradientBarPainter;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
 import java.awt.BorderLayout;
 import java.awt.Font;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
 import java.lang.reflect.InvocationTargetException;
 
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 public class TreeMapComponentTest {
 
@@ -72,6 +79,10 @@
         node1.addChild(node2);
     }
 
+    @Before
+    public void setup() {
+        treeMap = new TreeMapComponent();
+    }
 
     @Test
     public final void testTreeMapComponent() throws InvocationTargetException, InterruptedException {
@@ -110,7 +121,6 @@
 
             @Override
             public void run() {
-                treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
                 assertEquals(tree, treeMap.getTreeMapRoot());
             }
@@ -205,7 +215,6 @@
 
             @Override
             public void run() {
-                TreeMapComponent treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
 
                 treeMap.zoomIn(node1);
@@ -223,7 +232,6 @@
 
             @Override
             public void run() {
-                treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
 
                 treeMap.zoomOut();
@@ -246,7 +254,6 @@
 
             @Override
             public void run() {
-                treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
 
                 treeMap.zoomIn(node2);
@@ -263,7 +270,6 @@
 
             @Override
             public void run() {
-                treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
 
                 // the root is always in the stack
@@ -287,7 +293,6 @@
 
             @Override
             public void run() {
-                treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
 
                 treeMap.clearZoomCallsStack();
@@ -336,7 +341,6 @@
                 TreeMapNode grandchild = new TreeMapNode(1);
                 child.addChild(grandchild);
 
-                treeMap = new TreeMapComponent();
                 treeMap.setModel(tree);
                 treeMap.register(observer);
 
@@ -360,7 +364,6 @@
     @Test
     public final void testSetNode() {
         try {
-            treeMap = new TreeMapComponent();
             TreeMapComponent.Comp comp = treeMap.new Comp();
             comp.setNode(node1);
         } catch (NullPointerException e) {
@@ -368,6 +371,133 @@
         }
     }
 
+
+    public void performKeyboardShortcutTest(final KeyStroke keyStroke, final Runnable pre, final KeyShortcutTestResultHandler handler)
+            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) {
+                }
+            };
+
+            @Override
+            public void run() {
+                TreeMapNode child = new TreeMapNode(1);
+                tree.addChild(child);
+                TreeMapNode grandchild = new TreeMapNode(1);
+                child.addChild(grandchild);
+                treeMap.setModel(tree);
+                treeMap.zoomIn(child);
+                treeMap.zoomIn(grandchild);
+                pre.run();
+                treeMap.register(observer);
+                ActionListener action = treeMap.getActionForKeyStroke(keyStroke);
+                assertThat(action, is(not(equalTo(null))));
+                action.actionPerformed(null);
+                handler.handle(new KeyShortcutTestResults(zoomedIn, zoomedOut, zoomedFull));
+            }
+        });
+    }
+
+    public void performKeyboardShortcutTest(final KeyStroke keyStroke, final KeyShortcutTestResultHandler handler) throws InvocationTargetException, InterruptedException {
+        Runnable emptyPre = new Runnable() {
+            @Override
+            public void run() {}
+        };
+        performKeyboardShortcutTest(keyStroke, emptyPre, handler);
+    }
+
+    @Test
+    public void testKeyShortcutBackspace() throws InvocationTargetException, InterruptedException {
+        final int NO_MODIFIERS = 0;
+        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, NO_MODIFIERS);
+        performKeyboardShortcutTest(ks, new KeyShortcutTestResultHandler() {
+            @Override
+            public void handle(KeyShortcutTestResults results) {
+                assertThat(results.zoomedIn, is(false));
+                assertThat(results.zoomedOut, is(true));
+                assertThat(results.zoomedFull, is(false));
+                assertThat(treeMap.getClickedComponent(), is(equalTo(null)));
+            }
+        });
+    }
+
+    @Test
+    public void testKeyShortcutEscape() throws InvocationTargetException, InterruptedException {
+        final int NO_MODIFIERS = 0;
+        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, NO_MODIFIERS);
+        performKeyboardShortcutTest(ks, new KeyShortcutTestResultHandler() {
+            @Override
+            public void handle(KeyShortcutTestResults results) {
+                assertThat(results.zoomedIn, is(false));
+                assertThat(results.zoomedOut, is(true));
+                assertThat(results.zoomedFull, is(false));
+                assertThat(treeMap.getClickedComponent(), is(equalTo(null)));
+            }
+        });
+    }
+
+    @Test
+    public void testKeyShortcutHome() throws InvocationTargetException, InterruptedException {
+        final int NO_MODIFIERS = 0;
+        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_HOME, NO_MODIFIERS);
+        performKeyboardShortcutTest(ks, new KeyShortcutTestResultHandler() {
+            @Override
+            public void handle(KeyShortcutTestResults results) {
+                assertThat(results.zoomedIn, is(false));
+                assertThat(results.zoomedOut, is(false));
+                assertThat(results.zoomedFull, is(true));
+                assertThat(treeMap.getClickedComponent(), is(equalTo(null)));
+            }
+        });
+    }
+
+    //@Test
+    // FIXME: this test depends on lastClicked being set at some point prior to the test running, but this requires
+    // clicking on the painted TreeMap
+    public void testKeyShortcutEnter() throws InvocationTargetException, InterruptedException {
+        final int NO_MODIFIERS = 0;
+        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, NO_MODIFIERS);
+        performKeyboardShortcutTest(ks,
+            new Runnable() {
+                @Override
+                public void run() {
+                    treeMap.zoomFull();
+                }
+            },
+            new KeyShortcutTestResultHandler() {
+                @Override
+                public void handle(KeyShortcutTestResults results) {
+                    assertThat(results.zoomedIn, is(false));
+                    assertThat(results.zoomedOut, is(false));
+                    assertThat(results.zoomedFull, is(false));
+                    assertThat(treeMap.getClickedComponent(), is(equalTo(null)));
+                }
+            }
+        );
+    }
+
     public static void main(String[] args) {
         SwingUtilities.invokeLater(new Runnable() {
 
@@ -426,4 +556,20 @@
         });
     }
 
+    interface KeyShortcutTestResultHandler {
+        void handle(KeyShortcutTestResults results);
+    }
+
+    class KeyShortcutTestResults {
+        boolean zoomedIn = false;
+        boolean zoomedOut = false;
+        boolean zoomedFull = false;
+
+        public KeyShortcutTestResults(boolean zoomedIn, boolean zoomedOut, boolean zoomedFull) {
+            this.zoomedIn = zoomedIn;
+            this.zoomedOut = zoomedOut;
+            this.zoomedFull = zoomedFull;
+        }
+    }
+
 }