Revision: 1163
Author:   heuermh
Date:     Thu Feb 23 14:00:48 2012
Log: Issue 236 ; adding zoom event handler that responds to mouse wheel events
http://code.google.com/p/piccolo2d/source/detail?r=1163

Added:
/piccolo2d.java/trunk/core/src/main/java/org/piccolo2d/event/PMouseWheelZoomEventHandler.java /piccolo2d.java/trunk/core/src/test/java/org/piccolo2d/event/PMouseWheelZoomEventHandlerTest.java /piccolo2d.java/trunk/examples/src/main/java/org/piccolo2d/examples/MouseWheelZoomExample.java
Modified:
/piccolo2d.java/trunk/examples/src/main/java/org/piccolo2d/examples/ExampleRunner.java

=======================================
--- /dev/null
+++ /piccolo2d.java/trunk/core/src/main/java/org/piccolo2d/event/PMouseWheelZoomEventHandler.java Thu Feb 23 14:00:48 2012
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2008-2012, Piccolo2D project, http://piccolo2d.org
+ * Copyright (c) 1998-2008, University of Maryland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its + * contributors may be used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.piccolo2d.event;
+
+import java.awt.Rectangle;
+import java.awt.geom.Point2D;
+
+import org.piccolo2d.PCamera;
+import org.piccolo2d.PCanvas;
+
+/**
+ * Zoom event handler that scales the camera view transform in response to mouse wheel events.
+ *
+ * @since 2.0
+ */
+public final class PMouseWheelZoomEventHandler extends PBasicInputEventHandler {
+    /** Default scale factor, <code>0.1d</code>. */
+    static final double DEFAULT_SCALE_FACTOR = 0.1d;
+
+    /** Scale factor. */
+    private double scaleFactor = DEFAULT_SCALE_FACTOR;
+
+    /** Zoom mode. */
+    private ZoomMode zoomMode = ZoomMode.ZOOM_ABOUT_CANVAS_CENTER;
+
+
+    /**
+     * Create a new mouse wheel zoom event handler.
+     */
+    public PMouseWheelZoomEventHandler() {
+        super();
+        PInputEventFilter eventFilter = new PInputEventFilter();
+        eventFilter.rejectAllEventTypes();
+        eventFilter.setAcceptsMouseWheelRotated(true);
+        setEventFilter(eventFilter);
+    }
+
+
+    /**
+ * Return the scale factor for this mouse wheel zoom event handler. Defaults to <code>DEFAULT_SCALE_FACTOR</code>.
+     *
+     * @see #DEFAULT_SCALE_FACTOR
+     * @return the scale factor for this mouse wheel zoom event handler
+     */
+    public double getScaleFactor() {
+        return scaleFactor;
+    }
+
+    /**
+ * Set the scale factor for this mouse wheel zoom event handler to <code>scaleFactor</code>.
+     *
+ * @param scaleFactor scale factor for this mouse wheel zoom event handler
+     */
+    public void setScaleFactor(final double scaleFactor) {
+        this.scaleFactor = scaleFactor;
+    }
+
+    /**
+     * Switch to zoom about mouse mode.
+     *
+     * @see ZoomMode#ZOOM_ABOUT_MOUSE
+     */
+    public void zoomAboutMouse() {
+        zoomMode = ZoomMode.ZOOM_ABOUT_MOUSE;
+    }
+
+    /**
+     * Switch to zoom about canvas center mode.
+     *
+     * @see ZoomMode#ZOOM_ABOUT_CANVAS_CENTER
+     */
+    public void zoomAboutCanvasCenter() {
+        zoomMode = ZoomMode.ZOOM_ABOUT_CANVAS_CENTER;
+    }
+
+    /**
+     * Switch to zoom about view center mode.
+     *
+     * @see ZoomMode#ZOOM_ABOUT_VIEW_CENTER
+     */
+    public void zoomAboutViewCenter() {
+        zoomMode = ZoomMode.ZOOM_ABOUT_VIEW_CENTER;
+    }
+
+    /**
+ * Return the zoom mode for this mouse wheel zoom event handler. Defaults to
+     * <code>ZoomMode.ZOOM_ABOUT_CANVAS_CENTER</code>.
+     *
+     * @return the zoom mode for this mouse wheel zoom event handler
+     */
+    ZoomMode getZoomMode() {
+        return zoomMode;
+    }
+
+    /** {@inheritDoc} */
+    public void mouseWheelRotated(final PInputEvent event) {
+        PCamera camera = event.getCamera();
+        double scale = 1.0d + event.getWheelRotation() * scaleFactor;
+        Point2D viewAboutPoint = getViewAboutPoint(event);
+ camera.scaleViewAboutPoint(scale, viewAboutPoint.getX(), viewAboutPoint.getY());
+    }
+
+    /**
+ * Return the view about point for the specified event according to the current zoom mode.
+     *
+     * @param event input event
+ * @return the view about point for the specified event according to the current zoom mode
+     */
+    private Point2D getViewAboutPoint(final PInputEvent event) {
+        switch (zoomMode) {
+            case ZOOM_ABOUT_MOUSE:
+                return event.getPosition();
+            case ZOOM_ABOUT_CANVAS_CENTER:
+ Rectangle canvasBounds = ((PCanvas) event.getComponent()).getBounds(); + Point2D canvasCenter = new Point2D.Double(canvasBounds.getCenterX(), canvasBounds.getCenterY()); + event.getPath().canvasToLocal(canvasCenter, event.getCamera());
+                return event.getCamera().localToView(canvasCenter);
+            case ZOOM_ABOUT_VIEW_CENTER:
+ return event.getCamera().getBoundsReference().getCenter2D();
+        }
+ throw new IllegalArgumentException("illegal zoom mode " + zoomMode);
+    }
+
+    /**
+     * Zoom mode.
+     */
+    enum ZoomMode {
+        /**
+         * Zoom about mouse mode.
+         */
+        ZOOM_ABOUT_MOUSE,
+
+        /**
+         * Zoom about canvas center mode.
+         */
+        ZOOM_ABOUT_CANVAS_CENTER,
+
+        /**
+         * Zoom about view center mode.
+         */
+        ZOOM_ABOUT_VIEW_CENTER;
+    }
+}
=======================================
--- /dev/null
+++ /piccolo2d.java/trunk/core/src/test/java/org/piccolo2d/event/PMouseWheelZoomEventHandlerTest.java Thu Feb 23 14:00:48 2012
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2008-2012, Piccolo2D project, http://piccolo2d.org
+ * Copyright (c) 1998-2008, University of Maryland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its + * contributors may be used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.piccolo2d.event;
+
+import static org.piccolo2d.event.PMouseWheelZoomEventHandler.DEFAULT_SCALE_FACTOR; +import static org.piccolo2d.event.PMouseWheelZoomEventHandler.ZoomMode.ZOOM_ABOUT_MOUSE; +import static org.piccolo2d.event.PMouseWheelZoomEventHandler.ZoomMode.ZOOM_ABOUT_CANVAS_CENTER; +import static org.piccolo2d.event.PMouseWheelZoomEventHandler.ZoomMode.ZOOM_ABOUT_VIEW_CENTER;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test for PMouseWheelZoomEventHandler.
+ */
+public final class PMouseWheelZoomEventHandlerTest extends TestCase {
+    private static final double TOLERANCE = 0.1d;
+
+    public void testConstructor() {
+        assertNotNull(new PMouseWheelZoomEventHandler());
+    }
+
+    public void testScaleFactor() {
+ PMouseWheelZoomEventHandler zoomHandler = new PMouseWheelZoomEventHandler(); + assertEquals(DEFAULT_SCALE_FACTOR, zoomHandler.getScaleFactor(), TOLERANCE);
+
+        zoomHandler.setScaleFactor(42.0d);
+        assertEquals(42.0d, zoomHandler.getScaleFactor(), TOLERANCE);
+    }
+
+    public void testDefaultZoomMode() {
+ PMouseWheelZoomEventHandler zoomHandler = new PMouseWheelZoomEventHandler();
+        assertSame(ZOOM_ABOUT_CANVAS_CENTER, zoomHandler.getZoomMode());
+    }
+
+    public void testZoomAboutMouse() {
+ PMouseWheelZoomEventHandler zoomHandler = new PMouseWheelZoomEventHandler();
+        zoomHandler.zoomAboutMouse();
+        assertSame(ZOOM_ABOUT_MOUSE, zoomHandler.getZoomMode());
+    }
+
+    public void testZoomAboutCanvasCenter() {
+ PMouseWheelZoomEventHandler zoomHandler = new PMouseWheelZoomEventHandler();
+        zoomHandler.zoomAboutCanvasCenter();
+        assertSame(ZOOM_ABOUT_CANVAS_CENTER, zoomHandler.getZoomMode());
+    }
+
+    public void testZoomAboutViewCenter() {
+ PMouseWheelZoomEventHandler zoomHandler = new PMouseWheelZoomEventHandler();
+        zoomHandler.zoomAboutViewCenter();
+        assertSame(ZOOM_ABOUT_VIEW_CENTER, zoomHandler.getZoomMode());
+    }
+}
=======================================
--- /dev/null
+++ /piccolo2d.java/trunk/examples/src/main/java/org/piccolo2d/examples/MouseWheelZoomExample.java Thu Feb 23 14:00:48 2012
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2008-2012, Piccolo2D project, http://piccolo2d.org
+ * Copyright (c) 1998-2008, University of Maryland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its + * contributors may be used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.piccolo2d.examples;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Paint;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Random;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JPanel;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+
+import org.piccolo2d.PCanvas;
+import org.piccolo2d.event.PMouseWheelZoomEventHandler;
+import org.piccolo2d.extras.PFrame;
+import org.piccolo2d.nodes.PPath;
+import org.piccolo2d.nodes.PText;
+
+/**
+ * Mouse wheel zoom example.
+ *
+ * @since 2.0
+ */
+public final class MouseWheelZoomExample extends PFrame {
+    /** Default serial version UID. */
+    private static final long serialVersionUID = 1L;
+
+    /** Number of text and rect nodes. */
+    private static final int N = 100;
+
+    /** Text paint. */
+    private static final Paint TEXT_PAINT = new Color(20, 20, 20, 200);
+
+    /** Source of randomness. */
+    private final Random random;
+
+
+    /**
+     * Create a new mouse wheel zoom example.
+     */
+    public MouseWheelZoomExample() {
+        this(null);
+    }
+
+    /**
+     * Create a new mouse wheel zoom example with the specified canvas.
+     *
+     * @param canvas canvas for this mouse wheel zoom example
+     */
+    public MouseWheelZoomExample(final PCanvas canvas) {
+        super("MouseWheelZoomExample", false, canvas);
+        random = new Random();
+    }
+
+
+    /** {@inheritDoc} */
+    public void initialize() {
+        for (int i = 0; i < N; i++) {
+            createTextNode(i);
+        }
+        for (int i = 0; i < N; i++) {
+            createRectNode(i);
+        }
+
+        // uninstall default zoom event handler
+ getCanvas().removeInputEventListener(getCanvas().getZoomEventHandler());
+
+        // install mouse wheel zoom event handler
+ final PMouseWheelZoomEventHandler mouseWheelZoomEventHandler = new PMouseWheelZoomEventHandler();
+        getCanvas().addInputEventListener(mouseWheelZoomEventHandler);
+
+        // create a toolbar
+        final JToolBar toolBar = new JToolBar();
+ final JToggleButton zoomAboutMouse = new JToggleButton("Zoom about mouse"); + final JToggleButton zoomAboutCanvasCenter = new JToggleButton("Zoom about canvas center"); + final JToggleButton zoomAboutViewCenter = new JToggleButton("Zoom about view center");
+        final ButtonGroup buttonGroup = new ButtonGroup();
+        buttonGroup.add(zoomAboutMouse);
+        buttonGroup.add(zoomAboutCanvasCenter);
+        buttonGroup.add(zoomAboutViewCenter);
+        toolBar.add(zoomAboutMouse);
+        toolBar.add(zoomAboutCanvasCenter);
+        toolBar.add(zoomAboutViewCenter);
+        toolBar.setFloatable(false);
+
+        zoomAboutMouse.addActionListener(new ActionListener() {
+                /** {@inheritDoc} */
+                public void actionPerformed(final ActionEvent event) {
+                    mouseWheelZoomEventHandler.zoomAboutMouse();
+                }
+            });
+        zoomAboutCanvasCenter.addActionListener(new ActionListener() {
+                /** {@inheritDoc} */
+                public void actionPerformed(final ActionEvent event) {
+                    mouseWheelZoomEventHandler.zoomAboutCanvasCenter();
+                }
+            });
+        zoomAboutViewCenter.addActionListener(new ActionListener() {
+                /** {@inheritDoc} */
+                public void actionPerformed(final ActionEvent event) {
+                    mouseWheelZoomEventHandler.zoomAboutViewCenter();
+                }
+            });
+
+        final JPanel contentPane = new JPanel();
+        contentPane.setLayout(new BorderLayout());
+        contentPane.add("North", toolBar);
+        contentPane.add("Center", getCanvas());
+        setContentPane(contentPane);
+        validate();
+    }
+
+    private void createTextNode(final int i) {
+        PText text = new PText("Label " + i);
+        text.setTextPaint(TEXT_PAINT);
+ text.setOffset(random.nextDouble() * 1000.0d - random.nextDouble() * 1000.0, + random.nextDouble() * 1000.0d - random.nextDouble() * 1000.0);
+        getCanvas().getLayer().addChild(text);
+    }
+
+    private void createRectNode(final int i) {
+ PPath path = PPath.createRectangle(0.0f, 0.0f, 50.0f * i/N + 10.0f, 50.0f * i/N + 10.0f);
+        int r = 200 * i/N + 45;
+        path.setPaint(new Color(r, 0, 0, 200));
+        path.setStrokePaint(new Color(r - 10, 0, 0, 200));
+ path.setOffset(random.nextDouble() * 1000.0d - random.nextDouble() * 1000.0, + random.nextDouble() * 1000.0d - random.nextDouble() * 1000.0);
+        getCanvas().getLayer().addChild(path);
+    }
+
+
+    /**
+     * Main.
+     *
+     * @param args command line arguments, ignored
+     */
+    public static void main(final String[] args) {
+        new MouseWheelZoomExample();
+    }
+}
=======================================
--- /piccolo2d.java/trunk/examples/src/main/java/org/piccolo2d/examples/ExampleRunner.java Tue Mar 15 15:23:53 2011 +++ /piccolo2d.java/trunk/examples/src/main/java/org/piccolo2d/examples/ExampleRunner.java Thu Feb 23 14:00:48 2012
@@ -76,13 +76,13 @@
ClipExample.class, CompositeExample.class, DynamicExample.class, EventHandlerExample.class, FullScreenNodeExample.class, GraphEditorExample.class, GridExample.class, GroupExample.class, HandleExample.class, HelloWorldExample.class, HierarchyZoomExample.class, HtmlViewExample.class, - KeyEventFocusExample.class, LayoutExample.class, LensExample.class, NavigationExample.class, - NodeCacheExample.class, NodeEventExample.class, NodeExample.class, NodeLinkExample.class, - P3DRectExample.class, PanToExample.class, PathExample.class, PositionExample.class, - PositionPathActivityExample.class, PulseExample.class, ScrollingExample.class, SelectionExample.class, - ShadowExample.class, SquiggleExample.class, StickyExample.class, StickyHandleLayerExample.class, - StrokeExample.class, TextExample.class, TooltipExample.class, TwoCanvasExample.class,
-                WaitForActivitiesExample.class });
+ KeyEventFocusExample.class, LayoutExample.class, LensExample.class, MouseWheelZoomExample.class, + NavigationExample.class, NodeCacheExample.class, NodeEventExample.class, NodeExample.class, + NodeLinkExample.class, P3DRectExample.class, PanToExample.class, PathExample.class, + PositionExample.class, PositionPathActivityExample.class, PulseExample.class, ScrollingExample.class, + SelectionExample.class, ShadowExample.class, SquiggleExample.class, StickyExample.class, + StickyHandleLayerExample.class, StrokeExample.class, TextExample.class, TooltipExample.class,
+                TwoCanvasExample.class, WaitForActivitiesExample.class });
     }

     /**

--
Piccolo2D Developers Group: http://groups.google.com/group/piccolo2d-dev?hl=en

Reply via email to