Coder Social home page Coder Social logo

piccolo2d's People

Contributors

mro avatar

piccolo2d's Issues

PSwing components cause extraneous redraws

What steps will reproduce the problem?
1. Enable region management debugging to see repaint areas
2. Create a large canvas with other objects
3. Add a small PSwing component with a JPanel inside
4. Trigger a repaint on the PSwing component

What is the expected output? What do you see instead?
Only the area within the PSwing should be repainted, but instead redraw
events are fired for the region outside of the PSwing component.

Here is the proposed fix:

---
C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwingRepaintManager.j
ava
(revision 5)
+++
C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwingRepaintManager.j
ava
(revision 6)
         if (captureRepaint) {
             if (!isPainting(capturedComponent)) {
                 final PSwing vis = (PSwing)
capturedComponent.getClientProperty(PSwing.PSWING_PROPERTY);
                 if (vis != null) {
                     final double repaintX = captureX;
                     final double repaintY = captureY;
+                    // Make sure that the repaint bounds are not larger
than the enclosing PSwing
+                    final double repaintW = Math.min(vis.getWidth() -
captureX, w);
+                    final double repaintH = Math.min(vis.getHeight() -
captureY, h);
                     Runnable repainter = new Runnable() {
                         public void run() { 

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 7:21

Add FindBugs reporting to ant build

FindBugs
http://findbugs.sf.net

This issue has a few steps:

1) Vote on/configure findbugs to meet our needs via the filter mechanism:

http://findbugs.sourceforge.net/manual/filter.html

2) Add the findbugs ant plug-in to the current ant build

3) Publish the findbugs report to a reasonable location (a local /report
directory might be adequate for now)

Original issue reported on code.google.com by [email protected] on 20 Jun 2008 at 9:38

Keyboard focus doesn't work for multiple cameras

What steps will reproduce the problem?
1. Create 2 canvases that refer to different cameras, but the same root
2. Get the input manager and set the keyboard focus for the first canvas/camera
3. Get the input manager and set the keyboard focus for the second
canvas/camera

What is the expected output? What do you see instead?
Since the input manager is bound to the root, you only have one input
manager shared between the two sets of canvases and cameras.  Therefore,
when you change the focus in the second canvas/camera, the focus of the
first is lost.

The change below moves the input manager from the root to the camera node.
 For backwards compatibility, the PRoot.getDefaultInputManager can go down
the tree and select the first input manager it finds.

Here is the diff:
Index: src/edu/umd/cs/piccolo/PRoot.java
===================================================================
--- src/edu/umd/cs/piccolo/PRoot.java   (revision 23)
+++ src/edu/umd/cs/piccolo/PRoot.java   (revision 24)
@@ -36,9 +36,7 @@

 import javax.swing.*;
 import java.awt.event.ActionListener;
-import java.util.ArrayList;
 import java.util.Iterator;
-import java.util.List;

 /**
  * <b>PRoot</b> serves as the top node in Piccolo's runtime structure.
@@ -57,17 +55,14 @@
      * change event the new value will be a reference to the list of this
root's
      * input sources, but old value will always be null.
      */
-    public static final String PROPERTY_INPUT_SOURCES = "inputSources";
-    public static final int PROPERTY_CODE_INPUT_SOURCES = 1 << 14;
     public static final String PROPERTY_INTERACTING_CHANGED =
"INTERACTING_CHANGED_NOTIFICATION";
     public static final int PROPERTY_CODE_INTERACTING_CHANGED = 1 << 13;

-    protected transient boolean processingInputs;
+    protected transient boolean processActivities;
     protected transient boolean processInputsScheduled;

     private transient int interacting;
     private PInputManager defaultInputManager;
-    private transient List inputSources;
     private transient long globalTime;
     private PActivityScheduler activityScheduler;

@@ -86,7 +81,6 @@
      */
     public PRoot() {
         super();
-        inputSources = new ArrayList();
         globalTime = System.currentTimeMillis();
         activityScheduler = new PActivityScheduler(this);
     }
@@ -98,7 +92,7 @@
     /**
      * Add an activity to the activity scheduler associated with this root.
      * Activities are given a chance to run during each call to the roots
-     * <code>processInputs</code> method. When the activity has finished
+     * <code>processActivities</code> method. When the activity has finished
      * running it will automatically get removed.
      */
     public boolean addActivity(PActivity activity) {
@@ -131,7 +125,7 @@
         };

         while (activityScheduler.getActivitiesReference().size() > 0) {
-            processInputs();
+            processActivities();
             Iterator i = getAllNodes(cameraWithCanvas, null).iterator();
             while (i.hasNext()) {
                 PCamera each = (PCamera) i.next();
@@ -152,19 +146,6 @@
     }

     /**
-     * Get the default input manager to be used when processing input
-     * events. PCanvas's use this method when they forward new swing input
-     * events to the PInputManager.
-     */
-    public PInputManager getDefaultInputManager() {
-        if (defaultInputManager == null) {
-            defaultInputManager = new PInputManager();
-            addInputSource(defaultInputManager);
-        }
-        return defaultInputManager;
-    }
-
-    /**
      * Return true if this root has been marked as interacting. If so
      * the root will normally render at a lower quality that is faster.
      *
@@ -205,26 +186,6 @@
     }

     /**
-     * Advanced. If you want to add additional input sources to the roots
-     * UI process you can do that here. You will seldom do this unless you
-     * are making additions to the piccolo framework.
-     */
-    public void addInputSource(InputSource inputSource) {
-        inputSources.add(inputSource);
-        firePropertyChange(PROPERTY_CODE_INPUT_SOURCES,
PROPERTY_INPUT_SOURCES, null, inputSources);
-    }
-
-    /**
-     * Advanced. If you want to remove the default input source from the roots
-     * UI process you can do that here. You will seldom do this unless you
-     * are making additions to the piccolo framework.
-     */
-    public void removeInputSource(InputSource inputSource) {
-        inputSources.remove(inputSource);
-        firePropertyChange(PROPERTY_CODE_INPUT_SOURCES,
PROPERTY_INPUT_SOURCES, null, inputSources);
-    }
-
-    /**
      * Returns a new timer. This method allows subclasses, such as PSWTRoot to
      * create custom timers that will be used transparently by the Piccolo
      * framework.
@@ -239,7 +200,7 @@

     /**
      * Get the global Piccolo time. This is set to
System.currentTimeMillis() at
-     * the beginning of the roots <code>processInputs</code> method.
Activities
+     * the beginning of the roots <code>processActivities</code> method.
Activities
      * should usually use this global time instead of System.
      * currentTimeMillis() so that multiple activities will be synchronized.
      */
@@ -252,23 +213,17 @@
      * are processed. Activities are given a chance to run, and the bounds
caches
      * and any paint damage is validated.
      */
-    public void processInputs() {
-        PDebug.startProcessingInput();
-        processingInputs = true;
+    public void processActivities() {
+        PDebug.startProcessingActivities();
+        processActivities = true;

         globalTime = System.currentTimeMillis();
-        int count = inputSources == null ? 0 : inputSources.size();
-        for (int i = 0; i < count; i++) {
-            InputSource each = (InputSource) inputSources.get(i);
-            each.processInput();
-        }
-
         activityScheduler.processActivities(globalTime);
         validateFullBounds();
         validateFullPaint();

-        processingInputs = false;
-        PDebug.endProcessingInput();
+        processActivities = false;
+        PDebug.endProcessingActivities();
     }

     public void setFullBoundsInvalid(boolean fullLayoutInvalid) {
@@ -304,13 +259,13 @@

         PDebug.scheduleProcessInputs();

-        if (!processInputsScheduled && !processingInputs &&
+        if (!processInputsScheduled && !processActivities &&
                 (getFullBoundsInvalid() || getChildBoundsInvalid() ||
getPaintInvalid() || getChildPaintInvalid())) {

             processInputsScheduled = true;
             SwingUtilities.invokeLater(new Runnable() {
                 public void run() {
-                    processInputs();
+                    processActivities();
                     PRoot.this.processInputsScheduled = false;
                 }
             });
Index: src/edu/umd/cs/piccolo/activities/PActivityScheduler.java
===================================================================
--- src/edu/umd/cs/piccolo/activities/PActivityScheduler.java   (revision 23)
+++ src/edu/umd/cs/piccolo/activities/PActivityScheduler.java   (revision 24)
@@ -163,7 +163,7 @@
        if (activityTimer == null) {
            activityTimer = root.createTimer(PUtil.ACTIVITY_SCHEDULER_FRAME_DELAY,
new ActionListener() {
                public void actionPerformed(ActionEvent e) {
-                   root.processInputs();
+                    root.processActivities();
                }
            });
        }
Index: src/edu/umd/cs/piccolo/PCamera.java
===================================================================
--- src/edu/umd/cs/piccolo/PCamera.java (revision 23)
+++ src/edu/umd/cs/piccolo/PCamera.java (revision 24)
@@ -96,6 +83,7 @@
     public static final int VIEW_CONSTRAINT_CENTER = 2;

     private transient PComponent component;
+    private PInputManager inputManager;
     private transient List layers;
     private PAffineTransform viewTransform;
     private int viewConstraint;
@@ -128,6 +116,26 @@
     }

     /**
+     * Get the input manager to be used when processing input
+     * events. PCanvas's use this method when they forward new swing input
+     * events to the PInputManager.
+     */
+    public PInputManager getInputManager() {
+        if (inputManager == null) {
+            inputManager = new PInputManager();
+        }
+        return inputManager;
+    }
+
+    /**
+     * Set the input manager to be used when processing input
+     * events.
+     */
+    public void setInputManager(PInputManager inputManager) {
+        this.inputManager = inputManager;
+    }
+
+    /**
      * Repaint this camera, and forward the repaint request to the camera's
      * canvas if it is not null.
      */
Index: src/edu/umd/cs/piccolo/PInputManager.java
===================================================================
--- src/edu/umd/cs/piccolo/PInputManager.java   (revision 23)
+++ src/edu/umd/cs/piccolo/PInputManager.java   (revision 24)
@@ -257,13 +257,14 @@
     }

     public void processEventFromCamera(InputEvent event, int type, PCamera
camera) {
-        // queue input
+        // process input
         nextInput = event;
         nextType = type;
         nextInputSource = camera;
+        processInput();

         // tell root to process queued inputs
-        camera.getRoot().processInputs();
+        camera.getRoot().processActivities();
     }

     private void dispatchEventToListener(PInputEvent event, int type,
PInputEventListener listener) {
Index: src/edu/umd/cs/piccolo/PCanvas.java
===================================================================
--- src/edu/umd/cs/piccolo/PCanvas.java (revision 23)
+++ src/edu/umd/cs/piccolo/PCanvas.java (revision 24)
@@ -215,7 +215,7 @@

     /**
      * Return true if any activities that respond with true to the method
-     * isAnimating were run in the last PRoot.processInputs() loop. This
+     * isAnimating were run in the last PRoot.processActivities() loop. This
      * values is used by this canvas to determine the render quality
      * to use for the next paint.
      */
@@ -518,7 +518,7 @@
     }

     protected void sendInputEventToInputManager(InputEvent e, int type) {
-        getRoot().getDefaultInputManager().processEventFromCamera(e, type,
getCamera());
+        getCamera().getInputManager().processEventFromCamera(e, type,
getCamera());
     }

     public void setBounds(int x, int y, final int w, final int h) {
Index: src/edu/umd/cs/piccolo/util/PDebug.java
===================================================================
--- src/edu/umd/cs/piccolo/util/PDebug.java (revision 23)
+++ src/edu/umd/cs/piccolo/util/PDebug.java (revision 24)
@@ -29,17 +29,15 @@
  */
 package edu.umd.cs.piccolo.util;

-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
+import javax.swing.*;
+import java.awt.*;

-import javax.swing.SwingUtilities;
-
 /**
  * <b>PDebug</b> is used to set framework wide debugging flags.
- * <P>
- * @version 1.0
+ * <p/>
+ *
  * @author Jesse Grosjean
+ * @version 1.0
  */
 public class PDebug {

@@ -56,7 +54,7 @@

    private static long framesProcessed;
    private static long startProcessingOutputTime;
-   private static long startProcessingInputTime;
+    private static long startProcessingActivitiesTime;
    private static long processOutputTime;
    private static long processInputTime;
    private static boolean processingOutput;
@@ -125,12 +123,12 @@
        processingOutput = false;
    }

-   public static void startProcessingInput() {
-       startProcessingInputTime = System.currentTimeMillis();
+    public static void startProcessingActivities() {
+        startProcessingActivitiesTime = System.currentTimeMillis();
    }

-   public static void endProcessingInput() {
-       processInputTime += (System.currentTimeMillis() - startProcessingInputTime);
+    public static void endProcessingActivities() {
+        processInputTime += (System.currentTimeMillis() -
startProcessingActivitiesTime);
    }

    /**
Index: extras/edu/umd/cs/piccolox/swt/PSWTRoot.java
===================================================================
--- extras/edu/umd/cs/piccolox/swt/PSWTRoot.java    (revision 23)
+++ extras/edu/umd/cs/piccolox/swt/PSWTRoot.java    (revision 24)
@@ -41,13 +41,13 @@
            return;
        }

-       if (!processInputsScheduled && !processingInputs &&
+        if (!processInputsScheduled && !processActivities &&
            (getFullBoundsInvalid() || getChildBoundsInvalid() || getPaintInvalid()
|| getChildPaintInvalid())) {

            processInputsScheduled = true;
            composite.getDisplay().asyncExec(new Runnable() {
                public void run() {
-                   processInputs();
+                    processActivities();
                    processInputsScheduled = false;
                }
            });
Index: extras/edu/umd/cs/piccolox/swt/PSWTCanvas.java
===================================================================
--- extras/edu/umd/cs/piccolox/swt/PSWTCanvas.java  (revision 23)
+++ extras/edu/umd/cs/piccolox/swt/PSWTCanvas.java  (revision 24)
@@ -231,7 +222,7 @@

    /**
     * Return true if any activities that respond with true to the method
-    * isAnimating were run in the last PRoot.processInputs() loop. This
+     * isAnimating were run in the last PRoot.processActivities() loop. This
     * values is used by this canvas to determine the render quality
     * to use for the next paint.
     */
@@ -499,7 +476,7 @@
    }

    protected void sendInputEventToInputManager(InputEvent e, int type) {
-       getRoot().getDefaultInputManager().processEventFromCamera(e, type,
getCamera());
+        getCamera().getInputManager().processEventFromCamera(e, type,
getCamera());
    }

    public void setBounds(int x, int y, final int w, final int h) {
Index: examples/edu/umd/cs/piccolo/tutorial/SpecialEffects.java
===================================================================
--- examples/edu/umd/cs/piccolo/tutorial/SpecialEffects.java    (revision 23)
+++ examples/edu/umd/cs/piccolo/tutorial/SpecialEffects.java    (revision 24)
@@ -55,7 +56,7 @@
        PActivity a3 = aNode.animateToPositionScaleRotation(200, 100, 1, 0, 5000);

        // The animate activities will start immediately (in the next call to
-       // PRoot.processInputs) by default. Here we set their start times (in PRoot
+        // PRoot.processActivities) by default. Here we set their start
times (in PRoot
        // global time) so that they start when the previous one has finished.
        a1.setStartTime(currentTime);
        a2.startAfter(a1);
Index: examples/edu/umd/cs/piccolo/tutorial/PiccoloPresentation.java
===================================================================
--- examples/edu/umd/cs/piccolo/tutorial/PiccoloPresentation.java   (revision 23)
+++ examples/edu/umd/cs/piccolo/tutorial/PiccoloPresentation.java   (revision 24)
@@ -53,7 +53,7 @@

        getCanvas().requestFocus();
        getCanvas().addInputEventListener(eventHandler);
-   
getCanvas().getRoot().getDefaultInputManager().setKeyboardFocus(eventHandler);
+       
getCanvas().getCamera().getInputManager().setKeyboardFocus(eventHandler);
        getCanvas().removeInputEventListener(getCanvas().getZoomEventHandler());
        getCanvas().removeInputEventListener(getCanvas().getPanEventHandler());
    }
Index: examples/edu/umd/cs/piccolo/examples/SelectionExample.java
===================================================================
--- examples/edu/umd/cs/piccolo/examples/SelectionExample.java  (revision 23)
+++ examples/edu/umd/cs/piccolo/examples/SelectionExample.java  (revision 24)
@@ -40,7 +40,7 @@
        // Create a selection event handler
        PSelectionEventHandler selectionEventHandler = new
PSelectionEventHandler(getCanvas().getLayer(), getCanvas().getLayer());
        getCanvas().addInputEventListener(selectionEventHandler);
-   
getCanvas().getRoot().getDefaultInputManager().setKeyboardFocus(selectionEventHa
ndler);
+       
getCanvas().getCamera().getInputManager().setKeyboardFocus(selectionEventHandler
);

        PNotificationCenter.defaultCenter().addListener(this, 
                                                       "selectionChanged", 
Index: examples/edu/umd/cs/piccolo/examples/ActivityExample.java
===================================================================
--- examples/edu/umd/cs/piccolo/examples/ActivityExample.java   (revision 23)
+++ examples/edu/umd/cs/piccolo/examples/ActivityExample.java   (revision 24)
@@ -52,7 +53,7 @@

        // An activity will not run unless it is scheduled with the root. Once
        // it has been scheduled it will be given a chance to run during the next
-       // PRoot.processInputs() call.
+        // PRoot.processActivities() call.
        getCanvas().getRoot().addActivity(flash);

        // Use the PNode animate methods to create three activities that animate
@@ -63,7 +64,7 @@
        PActivity a3 = aNode.animateToPositionScaleRotation(200, 100, 1, 0, 5000);
        PActivity a4 = aNode.animateToTransparency(0.25f, 3000);

-       // the animate activities will start immediately (in the next call to
PRoot.processInputs)
+        // the animate activities will start immediately (in the next call
to PRoot.processActivities)
        // by default. Here we set their start times (in PRoot global time) so
that they start 
        // when the previous one has finished.
        a1.setStartTime(currentTime);

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 9:30

PFrame sets canvas size too large for the window

What steps will reproduce the problem?
1. Create a new PFrame
2. Fill the canvas with content that takes the whole screen

What is the expected output? What do you see instead?
The bottom and right edge of the canvas will be clipped by a few pixels
each way.

Here is the fix:
--- C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/PFrame.java  (revision 2)
+++ C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/PFrame.java  (revision 3)
@@ -98,7 +98,7 @@
        // Make canvas bounds follow containing frame bounds
        addComponentListener(new ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent e) {
-               canvas.setBounds(0, 0, getWidth(), getHeight());
+               canvas.setBounds(0, 0, getContentPane().getWidth(),
getContentPane().getHeight());
            }
        });


Original issue reported on code.google.com by steveonjava on 23 Jun 2008 at 11:09

PSwing mouse wheel support

Currently PSwing components don't handle mouse wheel events on their
contained Swing components.

Here is the proposed fix to add mouse wheel support to PSwing:
Index: extras/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java (revision 33)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java (revision 34)
@@ -11,7 +11,7 @@
 import java.awt.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
 import java.awt.geom.Point2D;
 import java.io.Serializable;

@@ -47,7 +47,7 @@
  * @author Sam R. Reid
  * @author Lance E. Good
  */
-public class PSwingMouseEvent extends MouseEvent implements Serializable {
+public class PSwingMouseEvent extends MouseEvent implements Serializable,
PSwingEvent {
     private int id;
     private PInputEvent event;

@@ -71,14 +71,12 @@
      * @param e  The original Java mouse event
      *           when in MOUSE_DRAGGED and MOUSE_RELEASED events.
      */
-    public static PSwingMouseEvent createMouseEvent( int id,
-                                                     MouseEvent e,
-                                                     PInputEvent pEvent ) {
-        if( id == PSwingMouseEvent.MOUSE_MOVED ||
-            id == PSwingMouseEvent.MOUSE_DRAGGED ) {
+    public static PSwingEvent createMouseEvent(int id, MouseEvent e,
PInputEvent pEvent) {
+        if (id == PSwingMouseEvent.MOUSE_MOVED || id ==
PSwingMouseEvent.MOUSE_DRAGGED) {
             return new PSwingMouseMotionEvent( id, e, pEvent );
-        }
-        else {
+        } else if (id == PSwingMouseEvent.MOUSE_WHEEL) {
+            return new PSwingMouseWheelEvent(id, (MouseWheelEvent) e, pEvent);
+        } else {
             return new PSwingMouseEvent( id, e, pEvent );
         }
     }
@@ -194,7 +192,6 @@
      * @param listener the MouseListener or MouseMotionListener to
dispatch to.
      */
     public void dispatchTo( Object listener ) {
-        if( listener instanceof MouseListener ) {
             MouseListener mouseListener = (MouseListener)listener;
             switch( getID() ) {
                 case PSwingMouseEvent.MOUSE_CLICKED:
@@ -216,20 +213,6 @@
                     throw new RuntimeException( "PMouseEvent with bad ID" );
             }
         }
-        else {
-            MouseMotionListener mouseMotionListener =
(MouseMotionListener)listener;
-            switch( getID() ) {
-                case PSwingMouseEvent.MOUSE_DRAGGED:
-                    mouseMotionListener.mouseDragged( this );
-                    break;
-                case PSwingMouseEvent.MOUSE_MOVED:
-                    mouseMotionListener.mouseMoved( this );
-                    break;
-                default:
-                    throw new RuntimeException( "PMouseMotionEvent with
bad ID" );
-            }
-        }
-    }

     /**
      * Set the souce of this event. As the event is fired up the tree the
source of the
@@ -240,4 +223,14 @@
     public void setSource( Object aSource ) {
         source = aSource;
     }
+
+    /**
+     * Returns this event as a mouse event.  This reduces the need to cast
instances of this
+     * interface when they are known to all extend MouseEvent.
+     *
+     * @return this object casted to a MouseEvent
+     */
+    public MouseEvent asMouseEvent() {
+        return this;
+    }
 }
\ No newline at end of file
Index: extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java   (revision 33)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java   (revision 34)
@@ -14,6 +14,7 @@
 import java.awt.*;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Point2D;
@@ -160,7 +161,8 @@
      * @param pSwingMouseEvent
      * @param aEvent
      */
-    void dispatchEvent(PSwingMouseEvent pSwingMouseEvent, PInputEvent
aEvent) {
+    void dispatchEvent(PSwingEvent pSwingMouseEvent, PInputEvent aEvent) {
+        MouseEvent mEvent = pSwingMouseEvent.asMouseEvent();
         Component comp = null;
         Point2D pt = null;
         PNode pickedNode = pSwingMouseEvent.getPath().getPickedNode();
@@ -177,7 +179,7 @@
             PNode grabNode = pickedNode;

             if (grabNode.isDescendentOf(canvas.getRoot())) {
-                pt = new Point2D.Double(pSwingMouseEvent.getX(),
pSwingMouseEvent.getY());
+                pt = new Point2D.Double(mEvent.getX(), mEvent.getY());
                 cameraToLocal(pSwingMouseEvent.getPath().getTopCamera(),
pt, grabNode);
                 prevPoint = new Point2D.Double(pt.getX(), pt.getY());

@@ -200,11 +202,11 @@
                 // Mouse Pressed gives focus - effects Mouse Drags and
                 // Mouse Releases
                 if (comp != null && pSwingMouseEvent.getID() ==
MouseEvent.MOUSE_PRESSED) {
-                    if (SwingUtilities.isLeftMouseButton(pSwingMouseEvent)) {
+                    if (SwingUtilities.isLeftMouseButton(mEvent)) {
                         leftButtonData.setState(swing, pickedNode, comp,
offX, offY);
-                    } else if
(SwingUtilities.isMiddleMouseButton(pSwingMouseEvent)) {
+                    } else if (SwingUtilities.isMiddleMouseButton(mEvent)) {
                         middleButtonData.setState(swing, pickedNode, comp,
offX, offY);
-                    } else if
(SwingUtilities.isRightMouseButton(pSwingMouseEvent)) {
+                    } else if (SwingUtilities.isRightMouseButton(mEvent)) {
                         rightButtonData.setState(swing, pickedNode, comp,
offX, offY);
                     }
                 }
@@ -214,42 +216,38 @@
         // This first case we don't want to give events to just
         // any Swing component - but to the one that got the
         // original mousePressed
-        if (pSwingMouseEvent.getID() == MouseEvent.MOUSE_DRAGGED ||
-                pSwingMouseEvent.getID() == MouseEvent.MOUSE_RELEASED) {
+        if (pSwingMouseEvent.getID() == MouseEvent.MOUSE_DRAGGED ||
pSwingMouseEvent.getID() == MouseEvent.MOUSE_RELEASED) {

             // LEFT MOUSE BUTTON
-            if (SwingUtilities.isLeftMouseButton(pSwingMouseEvent) &&
leftButtonData.getFocusedComponent() != null) {
+            if (SwingUtilities.isLeftMouseButton(mEvent) &&
leftButtonData.getFocusedComponent() != null) {
                 handleButton(pSwingMouseEvent, aEvent, leftButtonData);
             }

             // MIDDLE MOUSE BUTTON
-            if (SwingUtilities.isMiddleMouseButton(pSwingMouseEvent) &&
middleButtonData.getFocusedComponent() != null) {
+            if (SwingUtilities.isMiddleMouseButton(mEvent) &&
middleButtonData.getFocusedComponent() != null) {
                 handleButton(pSwingMouseEvent, aEvent, middleButtonData);
             }

             // RIGHT MOUSE BUTTON
-            if (SwingUtilities.isRightMouseButton(pSwingMouseEvent) &&
rightButtonData.getFocusedComponent() != null) {
+            if (SwingUtilities.isRightMouseButton(mEvent) &&
rightButtonData.getFocusedComponent() != null) {
                 handleButton(pSwingMouseEvent, aEvent, rightButtonData);
             }
         }
         // This case covers the cases mousePressed, mouseClicked,
-        // and mouseMoved events
-        else if ((pSwingMouseEvent.getID() == MouseEvent.MOUSE_PRESSED ||
-                pSwingMouseEvent.getID() == MouseEvent.MOUSE_CLICKED ||
-                pSwingMouseEvent.getID() == MouseEvent.MOUSE_MOVED) &&
-                (comp != null)) {
+        // mouseMoved, and mouseWheel events
+        else
+        if ((pSwingMouseEvent.getID() == MouseEvent.MOUSE_PRESSED ||
pSwingMouseEvent.getID() == MouseEvent.MOUSE_CLICKED ||
pSwingMouseEvent.getID() == MouseEvent.MOUSE_MOVED) && (comp != null)) {

-            MouseEvent e_temp = new MouseEvent(comp,
-                    pSwingMouseEvent.getID(),
-                    pSwingMouseEvent.getWhen(),
-                    pSwingMouseEvent.getModifiers(),
-                    (int) pt.getX() - offX,
-                    (int) pt.getY() - offY,
-                    pSwingMouseEvent.getClickCount(),
-                    pSwingMouseEvent.isPopupTrigger());
+            MouseEvent e_temp = new MouseEvent(comp,
pSwingMouseEvent.getID(), mEvent.getWhen(), mEvent.getModifiers(), (int)
pt.getX() - offX, (int) pt.getY() - offY, mEvent.getClickCount(),
mEvent.isPopupTrigger());

-            PSwingMouseEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
+            PSwingEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
             dispatchEvent(comp, e2);
+        } else if (pSwingMouseEvent.getID() == MouseEvent.MOUSE_WHEEL &&
(comp != null)) {
+            MouseWheelEvent mWEvent = (MouseWheelEvent) mEvent;
+            MouseWheelEvent e_temp = new MouseWheelEvent(comp,
pSwingMouseEvent.getID(), mEvent.getWhen(), mEvent.getModifiers(), (int)
pt.getX() - offX, (int) pt.getY() - offY, mEvent.getClickCount(),
mEvent.isPopupTrigger(), mWEvent.getScrollType(),
mWEvent.getScrollAmount(), mWEvent.getWheelRotation());
+
+            PSwingMouseWheelEvent e2 = new
PSwingMouseWheelEvent(e_temp.getID(), e_temp, aEvent);
+            dispatchEvent(comp, e2);
         }

         // Now we need to check if an exit or enter event needs to
@@ -260,9 +258,9 @@

             // This shouldn't happen - since we're only getting node events
             if (comp == null || pSwingMouseEvent.getID() ==
MouseEvent.MOUSE_EXITED) {
-                MouseEvent e_temp = createExitEvent(pSwingMouseEvent);
+                MouseEvent e_temp = createExitEvent(mEvent);

-                PSwingMouseEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
+                PSwingEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);

                 dispatchEvent(prevComponent, e2);
                 prevComponent = null;
@@ -270,19 +268,19 @@

             // This means mouseExited prevComponent and mouseEntered comp
             else if (prevComponent != comp) {
-                MouseEvent e_temp = createExitEvent(pSwingMouseEvent);
-                PSwingMouseEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
+                MouseEvent e_temp = createExitEvent(mEvent);
+                PSwingEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
                 dispatchEvent(prevComponent, e2);

-                e_temp = createEnterEvent(comp, pSwingMouseEvent, offX, offY);
+                e_temp = createEnterEvent(comp, mEvent, offX, offY);
                 e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(),
e_temp, aEvent);
-                comp.dispatchEvent(e2);
+                comp.dispatchEvent(e2.asMouseEvent());
             }
         } else {
             // This means mouseEntered
             if (comp != null) {
-                MouseEvent e_temp = createEnterEvent(comp,
pSwingMouseEvent, offX, offY);
-                PSwingMouseEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
+                MouseEvent e_temp = createEnterEvent(comp, mEvent, offX,
offY);
+                PSwingEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
                 dispatchEvent(comp, e2);
             }
         }
@@ -312,47 +310,38 @@
         }
     }

-    private MouseEvent createEnterEvent(Component comp, PSwingMouseEvent
e1, int offX, int offY) {
-        return new MouseEvent(comp, MouseEvent.MOUSE_ENTERED,
-                e1.getWhen(), 0,
-                (int) prevPoint.getX() - offX, (int) prevPoint.getY() - offY,
-                e1.getClickCount(), e1.isPopupTrigger());
+    private MouseEvent createEnterEvent(Component comp, MouseEvent e1, int
offX, int offY) {
+        return new MouseEvent(comp, MouseEvent.MOUSE_ENTERED,
e1.getWhen(), 0, (int) prevPoint.getX() - offX, (int) prevPoint.getY() -
offY, e1.getClickCount(), e1.isPopupTrigger());
     }

-    private MouseEvent createExitEvent(PSwingMouseEvent e1) {
-        return new MouseEvent(prevComponent, MouseEvent.MOUSE_EXITED,
-                e1.getWhen(), 0,
-                (int) prevPoint.getX() - (int) prevOff.getX(), (int)
prevPoint.getY() - (int) prevOff.getY(),
-                e1.getClickCount(), e1.isPopupTrigger());
+    private MouseEvent createExitEvent(MouseEvent e1) {
+        return new MouseEvent(prevComponent, MouseEvent.MOUSE_EXITED,
e1.getWhen(), 0, (int) prevPoint.getX() - (int) prevOff.getX(), (int)
prevPoint.getY() - (int) prevOff.getY(), e1.getClickCount(),
e1.isPopupTrigger());
     }

-    private void handleButton(PSwingMouseEvent e1, PInputEvent aEvent,
ButtonData buttonData) {
+    private void handleButton(PSwingEvent e1, PInputEvent aEvent,
ButtonData buttonData) {
+        MouseEvent m1 = e1.asMouseEvent();
         Point2D pt;
         if (buttonData.getPNode().isDescendentOf(canvas.getRoot())) {
-            pt = new Point2D.Double(e1.getX(), e1.getY());
+            pt = new Point2D.Double(m1.getX(), m1.getY());
             cameraToLocal(e1.getPath().getTopCamera(), pt,
buttonData.getPNode());
             //todo this probably won't handle viewing through multiple
cameras.
-            MouseEvent e_temp = new
MouseEvent(buttonData.getFocusedComponent(),
-                    e1.getID(), e1.getWhen(), e1.getModifiers(),
-                    (int) pt.getX() - buttonData.getOffsetX(),
-                    (int) pt.getY() - buttonData.getOffsetY(),
-                    e1.getClickCount(), e1.isPopupTrigger());
+            MouseEvent e_temp = new
MouseEvent(buttonData.getFocusedComponent(), e1.getID(), m1.getWhen(),
m1.getModifiers(), (int) pt.getX() - buttonData.getOffsetX(), (int)
pt.getY() - buttonData.getOffsetY(), m1.getClickCount(), m1.isPopupTrigger());

-            PSwingMouseEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
+            PSwingEvent e2 =
PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent);
             dispatchEvent(buttonData.getFocusedComponent(), e2);
         } else {
             dispatchEvent(buttonData.getFocusedComponent(), e1);
         }
-        e1.consume();
+        m1.consume();
         if (e1.getID() == MouseEvent.MOUSE_RELEASED) {
             buttonData.mouseReleased();
         }
     }

-    private void dispatchEvent(final Component target, final
PSwingMouseEvent event) {
+    private void dispatchEvent(final Component target, final PSwingEvent
event) {
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {
-                target.dispatchEvent(event);
+                target.dispatchEvent(event.asMouseEvent());
             }
         });
     }
@@ -361,8 +350,7 @@
         AffineTransform inverse = null;
         try {
             inverse = topCamera.getViewTransform().createInverse();
-        }
-        catch (NoninvertibleTransformException e) {
+        } catch (NoninvertibleTransformException e) {
             e.printStackTrace();
         }

@@ -393,11 +381,14 @@
             InputEvent sourceSwingEvent = aEvent.getSourceSwingEvent();
             if (sourceSwingEvent instanceof MouseEvent) {
                 MouseEvent swingMouseEvent = (MouseEvent) sourceSwingEvent;
-                PSwingMouseEvent pSwingMouseEvent =
PSwingMouseEvent.createMouseEvent(swingMouseEvent.getID(), swingMouseEvent,
aEvent);
+                if (sourceSwingEvent instanceof MouseWheelEvent) {
+
+                }
+                PSwingEvent pSwingMouseEvent =
PSwingMouseEvent.createMouseEvent(swingMouseEvent.getID(), swingMouseEvent,
aEvent);
                 if (!recursing) {
                     recursing = true;
                     dispatchEvent(pSwingMouseEvent, aEvent);
-                    if (pSwingMouseEvent.isConsumed()) {
+                    if (pSwingMouseEvent.asMouseEvent().isConsumed()) {
                         aEvent.setHandled(true);
                     }
                     recursing = false;
Index: extras/edu/umd/cs/piccolox/pswing/PSwingMouseWheelEvent.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingMouseWheelEvent.java    (revision 0)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingMouseWheelEvent.java    (revision 34)
@@ -0,0 +1,202 @@
+/**
+ * Copyright (C) 1998-2000 by University of Maryland, College Park, MD
20742, USA
+ * All rights reserved.
+ */
+package edu.umd.cs.piccolox.pswing;
+
+import edu.umd.cs.piccolo.PNode;
+import edu.umd.cs.piccolo.event.PInputEvent;
+import edu.umd.cs.piccolo.util.PPickPath;
+
+import java.awt.*;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.geom.Point2D;
+
+/**
+ * <b>PMouseMotionEvent</b> is an event which indicates that a mouse
motion action occurred in a node.
+ * <p/>
+ * This low-level event is generated by a node object for:
+ * <ul>
+ * <li> Mouse Motion Events
+ * <ul>
+ * <li>the mouse is moved
+ * <li>the mouse is dragged
+ * </ul>
+ * </ul>
+ * <p/>
+ * A PMouseEvent object is passed to every <code>PMouseMotionListener</code>
+ * or <code>PMouseMotionAdapter</code> object which registered to receive
+ * mouse motion events using the component's
<code>addMouseMotionListener</code>
+ * method. (<code>PMouseMotionAdapter</code> objects implement the
+ * <code>PMouseMotionListener</code> interface.) Each such listener object
+ * gets a <code>PMouseEvent</code> containing the mouse motion event.
+ * <p/>
+ * <p/>
+ * <b>Warning:</b> Serialized objects of this class will not be
+ * compatible with future Piccolo releases. The current serialization
support is
+ * appropriate for short term storage or RMI between applications running the
+ * same version of Piccolo. A future release of Piccolo will provide
support for long
+ * term persistence.
+ *
+ * @author Benjamin B. Bederson
+ * @author Sam R. Reid
+ * @author Lance E. Good
+ */
+public class PSwingMouseWheelEvent extends MouseWheelEvent implements
PSwingEvent {
+    private int id;
+    private PInputEvent event;
+
+    /**
+     * Constructs a new PMouseWheel event from a Java MouseWheelEvent.
+     *
+     * @param id The event type (MOUSE_WHEEL)
+     * @param e  The original Java mouse wheel event.
+     */
+    protected PSwingMouseWheelEvent(int id, MouseWheelEvent e, PInputEvent
event) {
+        super((Component) e.getSource(), e.getID(), e.getWhen(),
e.getModifiers(), e.getX(), e.getY(), e.getClickCount(),
e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(),
e.getWheelRotation());
+        this.id = id;
+        this.event = event;
+    }
+
+    /**
+     * Returns the x,y position of the event in the local coordinate
system of the node
+     * the event occurred on.
+     *
+     * @return a Point2D object containing the x and y coordinates local
to the node.
+     */
+    public Point2D getLocalPoint() {
+        return new Point2D.Double(getX(), getY());
+    }
+
+    /**
+     * Returns the horizontal x position of the event in the local
coordinate system
+     * of the node the event occurred on.
+     *
+     * @return x a double indicating horizontal position local to the node.
+     */
+    public double getLocalX() {
+        return getLocalPoint().getX();
+    }
+
+    /**
+     * Returns the vertical y position of the event in the local
coordinate system
+     * of the node the event occurred on.
+     *
+     * @return y a double indicating vertical position local to the node.
+     */
+    public double getLocalY() {
+        return getLocalPoint().getY();
+    }
+
+    /**
+     * Determine the event type.
+     *
+     * @return the id
+     */
+    public int getID() {
+        return id;
+    }
+
+    /**
+     * Determine the node the event originated at.  If an event percolates
+     * up the tree and is handled by an event listener higher up in the
+     * tree than the original node that generated the event, this returns
+     * the original node.  For mouse drag and release events, this is the
+     * node that the original matching press event went to - in other words,
+     * the event is 'grabbed' by the originating node.
+     *
+     * @return the node
+     */
+    public PNode getNode() {
+        return event.getPickedNode();
+    }
+
+    /**
+     * Determine the path the event took from the PCanvas down to the
visual component.
+     *
+     * @return the path
+     */
+    public PPickPath getPath() {
+        return event.getPath();
+    }
+
+    /**
+     * Determine the node the event originated at.  If an event percolates
+     * up the tree and is handled by an event listener higher up in the
+     * tree than the original node that generated the event, this returns
+     * the original node.  For mouse drag and release events, this is the
+     * node that the original matching press event went to - in other words,
+     * the event is 'grabbed' by the originating node.
+     *
+     * @return the node
+     */
+    public PNode getGrabNode() {
+        return event.getPickedNode();
+    }
+
+    /**
+     * Return the path from the PCanvas down to the currently grabbed object.
+     *
+     * @return the path
+     */
+    public PPickPath getGrabPath() {
+        return getPath();
+    }
+
+    /**
+     * Get the current node that is under the cursor. This may return a
different result then getGrabNode() when
+     * in a MOUSE_RELEASED or MOUSE_DRAGGED event.
+     *
+     * @return the current node.
+     */
+    public PNode getCurrentNode() {
+        return event.getPickedNode();
+    }
+
+    /**
+     * Get the path from the PCanvas down to the visual component
currently under the mouse.This may
+     * give a different result then getGrabPath() durring a MOUSE_DRAGGED
or MOUSE_RELEASED operation.
+     *
+     * @return the current path.
+     */
+    public PPickPath getCurrentPath() {
+        return getPath();
+    }
+
+    /**
+     * Calls appropriate method on the listener based on this events ID.
+     *
+     * @param listener the target for dispatch.
+     */
+    public void dispatchTo(Object listener) {
+        MouseWheelListener mouseWheelListener = (MouseWheelListener) listener;
+        switch (getID()) {
+            case PSwingMouseEvent.MOUSE_WHEEL:
+                mouseWheelListener.mouseWheelMoved(this);
+                break;
+            default:
+                throw new RuntimeException("PMouseWheelEvent with bad ID");
+        }
+    }
+
+    /**
+     * Set the souce of this event. As the event is fired up the tree the
source of the
+     * event will keep changing to reflect the scenegraph object that is
firing the event.
+     *
+     * @param aSource
+     */
+    public void setSource(Object aSource) {
+        source = aSource;
+    }
+
+    /**
+     * Returns this event as a mouse event.  This reduces the need to cast
instances of this
+     * interface when they are known to all extend MouseEvent.
+     *
+     * @return this object casted to a MouseEvent
+     */
+    public MouseWheelEvent asMouseEvent() {
+        return this;
+    }
+}
\ No newline at end of file
Index: extras/edu/umd/cs/piccolox/pswing/PSwingEvent.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingEvent.java  (revision 0)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingEvent.java  (revision 34)
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2007 Stephen Chin
+ *
+ * All rights reserved.
+ */
+package edu.umd.cs.piccolox.pswing;
+
+import edu.umd.cs.piccolo.PNode;
+import edu.umd.cs.piccolo.util.PPickPath;
+
+import java.awt.event.MouseEvent;
+import java.awt.geom.Point2D;
+
+public interface PSwingEvent {
+    /**
+     * Returns the x,y position of the event in the local coordinate
system of the node
+     * the event occurred on.
+     *
+     * @return a Point2D object containing the x and y coordinates local
to the node.
+     */
+    Point2D getLocalPoint();
+
+    /**
+     * Returns the horizontal x position of the event in the local
coordinate system
+     * of the node the event occurred on.
+     *
+     * @return x a double indicating horizontal position local to the node.
+     */
+    double getLocalX();
+
+    /**
+     * Returns the vertical y position of the event in the local
coordinate system
+     * of the node the event occurred on.
+     *
+     * @return y a double indicating vertical position local to the node.
+     */
+    double getLocalY();
+
+    /**
+     * Determine the event type.
+     *
+     * @return the id
+     */
+    int getID();
+
+    /**
+     * Determine the node the event originated at.  If an event percolates
+     * up the tree and is handled by an event listener higher up in the
+     * tree than the original node that generated the event, this returns
+     * the original node.  For mouse drag and release events, this is the
+     * node that the original matching press event went to - in other words,
+     * the event is 'grabbed' by the originating node.
+     *
+     * @return the node
+     */
+    PNode getNode();
+
+    /**
+     * Determine the path the event took from the PCanvas down to the
visual component.
+     *
+     * @return the path
+     */
+    PPickPath getPath();
+
+    /**
+     * Determine the node the event originated at.  If an event percolates
+     * up the tree and is handled by an event listener higher up in the
+     * tree than the original node that generated the event, this returns
+     * the original node.  For mouse drag and release events, this is the
+     * node that the original matching press event went to - in other words,
+     * the event is 'grabbed' by the originating node.
+     *
+     * @return the node
+     */
+    PNode getGrabNode();
+
+    /**
+     * Return the path from the PCanvas down to the currently grabbed object.
+     *
+     * @return the path
+     */
+    PPickPath getGrabPath();
+
+    /**
+     * Get the current node that is under the cursor. This may return a
different result then getGrabNode() when
+     * in a MOUSE_RELEASED or MOUSE_DRAGGED event.
+     *
+     * @return the current node.
+     */
+    PNode getCurrentNode();
+
+    /**
+     * Get the path from the PCanvas down to the visual component
currently under the mouse.This may
+     * give a different result then getGrabPath() durring a MOUSE_DRAGGED
or MOUSE_RELEASED operation.
+     *
+     * @return the current path.
+     */
+    PPickPath getCurrentPath();
+
+    /**
+     * Calls appropriate method on the listener based on this events ID.
+     *
+     * @param listener the MouseListener or MouseMotionListener to
dispatch to.
+     */
+    void dispatchTo(Object listener);
+
+    /**
+     * Set the souce of this event. As the event is fired up the tree the
source of the
+     * event will keep changing to reflect the scenegraph object that is
firing the event.
+     *
+     * @param aSource
+     */
+    void setSource(Object aSource);
+
+    /**
+     * Returns this event as a mouse event.  This reduces the need to cast
instances of this
+     * interface when they are known to all extend MouseEvent.
+     *
+     * @return this object casted to a MouseEvent
+     */
+    MouseEvent asMouseEvent();
+}

Original issue reported on code.google.com by steveonjava on 29 Jun 2008 at 11:20

Relocate svn root from piccolo to piccolo2d

rename the following children of https://piccolo2d.googlecode.com/svn/

piccolo.java -> piccolo2d.java
piccolo.net -> piccolo2d.net
pocketpiccolo.net -> pocketpiccolo2d.net

CAUTION: 
- this renders all checked-out working copies broken
- this makes file history hard to follow across this step

Original issue reported on code.google.com by [email protected] on 8 Jul 2008 at 10:46

remove child on PNode fails with NPE

What steps will reproduce the problem?
1. Create a PNode
2. Add an event handler that removes that PNode from the root.
3. Fire the event handler multiple times.

What is the expected output? What do you see instead?
Rather than failing gracefully, you get an NPE on every event after the
first one.  In most cases it is safe to return gracefully if there are no
nodes to remove (which is what the corresponding function on JComponent does).

The proposed fix is to check for existence of the node before removal so
the client code does not have to. 

Here is a diff of the change:
Index: src/edu/umd/cs/piccolo/PNode.java
===================================================================
--- src/edu/umd/cs/piccolo/PNode.java   (revision 22)
+++ src/edu/umd/cs/piccolo/PNode.java   (revision 23)
@@ -30,68 +30,38 @@

 package edu.umd.cs.piccolo;

-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
-import java.awt.GraphicsEnvironment;
-import java.awt.Image;
-import java.awt.Paint;
-import java.awt.Transparency;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Dimension2D;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.print.Book;
-import java.awt.print.PageFormat;
-import java.awt.print.Paper;
-import java.awt.print.Printable;
-import java.awt.print.PrinterJob;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-import javax.swing.event.EventListenerList;
-import javax.swing.event.SwingPropertyChangeSupport;
-import javax.swing.text.MutableAttributeSet;
-import javax.swing.text.SimpleAttributeSet;
-
 import edu.umd.cs.piccolo.activities.PActivity;
 import edu.umd.cs.piccolo.activities.PColorActivity;
 import edu.umd.cs.piccolo.activities.PInterpolatingActivity;
 import edu.umd.cs.piccolo.activities.PTransformActivity;
 import edu.umd.cs.piccolo.event.PInputEventListener;
-import edu.umd.cs.piccolo.util.PAffineTransform;
-import edu.umd.cs.piccolo.util.PBounds;
-import edu.umd.cs.piccolo.util.PNodeFilter;
-import edu.umd.cs.piccolo.util.PObjectOutputStream;
-import edu.umd.cs.piccolo.util.PPaintContext;
-import edu.umd.cs.piccolo.util.PPickPath;
-import edu.umd.cs.piccolo.util.PUtil;
+import edu.umd.cs.piccolo.util.*;

+import javax.swing.event.EventListenerList;
+import javax.swing.event.SwingPropertyChangeSupport;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.BufferedImage;
+import java.awt.print.*;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.*;
+import java.util.*;
+import java.util.List;
+
 /**
  * <b>PNode</b> is the central abstraction in Piccolo. All objects that are
  * visible on the screen are instances of the node class. All nodes may have 
  * other "child" nodes added to them.
- * <p>
+ * <p/>
  * See edu.umd.piccolo.examples.NodeExample.java for demonstrations of how
nodes
  * can be used and how new types of nodes can be created.
- * <P>
- * @version 1.0
+ * <p/>
+ *
  * @author Jesse Grosjean
+ * @version 1.0
  */
 public class PNode implements Cloneable, Serializable, Printable {

@@ -177,7 +147,8 @@
     * The property name that identifies a change in the set of this node's
direct children
     * (see {@link #getChildrenReference getChildrenReference}, {@link
#getChildrenIterator getChildrenIterator}).
     * In any property change event the new value will be a reference to this
node's children,
-    * but  old value will always be null. */
+     * but  old value will always be null.
+     */
     public static final String PROPERTY_CHILDREN = "children";
     public static final int PROPERTY_CODE_CHILDREN = 1 << 9;

@@ -203,6 +174,7 @@
     */
    public interface PSceneGraphDelegate {
        public void nodePaintInvalidated(PNode node);
+
        public void nodeFullBoundsInvalidated(PNode node);
    }

@@ -234,7 +206,7 @@

     /**
     * Constructs a new PNode.
-    * <P>
+     * <p/>
     * By default a node's paint is null, and bounds are empty. These values
     * must be set for the node to show up on the screen once it's added to
     * a scene graph. 
@@ -391,6 +363,7 @@
                public void setTransform(AffineTransform aTransform) {
                    PNode.this.setTransform(aTransform);
                }
+
                public void getSourceMatrix(double[] aSource) {
                    PNode.this.getTransformReference(true).getMatrix(aSource);
                }
@@ -425,6 +398,7 @@
                public Color getColor() {
                    return (Color) getPaint();
                }
+
                public void setColor(Color color) {
                    setPaint(color);
                }
@@ -528,11 +502,11 @@

    /**
     * Add an arbitrary key/value to this node.
-    * <p>
+     * <p/>
     * The <code>get/add attribute<code> methods provide access to
     * a small per-instance attribute set. Callers can use get/add attribute
     * to annotate nodes that were created by another module.
-    * <p>
+     * <p/>
     * If value is null this method will remove the attribute.
     */
    public void addAttribute(Object key, Object value) {
@@ -618,9 +592,11 @@
            public boolean hasNext() {
                return enumeration.hasMoreElements();
            }
+
            public Object next() {
                return enumeration.nextElement();
            }
+
            public void remove() {
                throw new UnsupportedOperationException();
            }
@@ -959,6 +935,7 @@
     * The listener is registered for all properties.
     * See the fields in PNode and subclasses that start
     * with PROPERTY_ to find out which properties exist.
+     *
     * @param listener  The PropertyChangeListener to be added
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
@@ -973,6 +950,7 @@
     * will be invoked only when a call on firePropertyChange names that
     * specific property. See the fields in PNode and subclasses that start
     * with PROPERTY_ to find out which properties are supported.
+     *
     * @param propertyName  The name of the property to listen on.
     * @param listener  The PropertyChangeListener to be added
     */
@@ -1157,10 +1135,10 @@
    /**
     * Set the bounds of this node to the given value. These bounds 
     * are stored in the local coordinate system of this node.
-    * 
+     * <p/>
     * If the width or height is less then or equal to zero then the bound's
     * emtpy bit will be set to true.
-    * 
+     * <p/>
     * Subclasses must call the super.setBounds() method.
     *  
     * @return true if the bounds changed.
@@ -1188,7 +1166,7 @@
     * Gives nodes a chance to update their internal structure
     * before bounds changed notifications are sent. When this message
     * is recived the nodes bounds field will contain the new value.
-    * 
+     * <p/>
     * See PPath for an example that uses this method.
     */
    protected void internalUpdateBounds(double x, double y, double width,
double height) {
@@ -1945,7 +1923,7 @@
     * the source anchor point coincides with the reference anchor
     * point. This can be useful for layout algorithms as it is
     * straightforward to position one object relative to another.
-    * <p>
+     * <p/>
     * For example, If you have two nodes, A and B, and you call
     * <PRE>
     *     Point2D srcPt = new Point2D.Double(1.0, 0.0);
@@ -1955,6 +1933,7 @@
     * The result is that A will move so that its upper-right corner is at
     * the same place as the upper-left corner of B, and the transition will
     * be smoothly animated over a period of 750 milliseconds.
+     *
     * @param srcPt The anchor point on this transform's node (normalized to
a unit square)
     * @param destPt The anchor point on destination bounds (normalized to a
unit square)
     * @param destBounds The bounds (in global coordinates) used to calculate
this transform's node
@@ -2812,8 +2791,12 @@
     * @return the removed child
     */
    public PNode removeChild(PNode child) {
-       return removeChild(indexOfChild(child));
+        int index = indexOfChild(child);
+        if (index == -1) {
+            return null;
    }
+        return removeChild(index);
+    }

    /**
     * Remove the child at the specified position of this group node's children.
@@ -2824,6 +2807,9 @@
     * @return the removed child
     */
    public PNode removeChild(int index) {
+        if (children == null) {
+            return null;
+        }
        PNode child = (PNode) children.remove(index);

        if (children.size() == 0) {

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 9:02

PSwing components not visible in testing frameworks

PSwing components do not work properly with Swing testing frameworks like
FEST-Swing, because of the visiblity settings.

Here is the proposed fix:
Index: extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java (revision 34)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java (revision 35)
@@ -73,6 +73,10 @@
         public PSwingCanvas getPSwingCanvas() {
             return pSwingCanvas;
         }
+
+        public boolean isShowing() {
+            return true;
     }
+    }

 }
\ No newline at end of file
Index: extras/edu/umd/cs/piccolox/pswing/PSwing.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 34)
+++ extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 35)
@@ -221,6 +221,7 @@
         reshape();
         swingEventHandler = new PSwingEventHandler(canvas, this);
         swingEventHandler.setActive(true);
+        setVisible(true);
     }

     /**

Original issue reported on code.google.com by steveonjava on 29 Jun 2008 at 11:24

Events from PSwing components are not consumed, and cause other interactions on the canvas

What steps will reproduce the problem?
1. Add a PSwing that overlaps another component
2. Click on the PSwing component

What is the expected output? What do you see instead?
Both the PSwing component and the node it overlaps will get the same event
even though the swing component consumed the event.

Here is the proposed fix:
Index: src/edu/umd/cs/piccolo/util/PPickPath.java
===================================================================
--- src/edu/umd/cs/piccolo/util/PPickPath.java  (revision 8)
+++ src/edu/umd/cs/piccolo/util/PPickPath.java  (revision 9)
@@ -258,10 +258,13 @@
                                for (int j = 0; j < listeners.length; j++) {
                                        PInputEventListener listener =
(PInputEv
entListener) listeners[j];
                                        listener.processEvent(aEvent, type);

+                    if (aEvent.isHandled()) {
+                        return;
                                }
                        }
                }
        }
+       }

        //****************************************************************
        // Transforming Geometry - Methods to transform geometry through
Index: build.xml
===================================================================
--- build.xml   (revision 8)
+++ build.xml   (revision 9)
@@ -268,7 +268,7 @@

     <javac srcdir="${build.tests.src}"
            destdir="${build.tests.dest}"
-                 
classpath="${build.dir}/${name}.jar;${build.dir}/${name}x.jar
"
+                 
classpath="${build.dir}/${name}.jar;${build.dir}/${name}x.jar
;${lib.dir}/junit.jar"
            debug="${debug}"
            deprecation="${deprecation}"
            optimize="${optimize}"/>
Index: extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java   (revision 8)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java   (revision 9)
@@ -237,7 +237,6 @@

             PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(
e_temp.get
ID(), e_temp, aEvent );
             dispatchEvent( comp, e2 );
-            pSwingMouseEvent.consume();
         }

         // Now we need to check if an exit or enter event needs to
@@ -254,11 +253,7 @@

                 dispatchEvent( prevComponent, e2 );
                 prevComponent = null;
-
-                if( pSwingMouseEvent.getID() == MouseEvent.MOUSE_EXITED ) {
-                    pSwingMouseEvent.consume();
                 }
-            }

             // This means mouseExited prevComponent and mouseEntered comp
             else if( prevComponent != comp ) {
@@ -392,6 +387,9 @@
                 if( !recursing ) {
                     recursing = true;
                     dispatchEvent( pSwingMouseEvent, aEvent );
+                    if (pSwingMouseEvent.isConsumed()) {
+                        aEvent.setHandled(true);
+                    }
                     recursing = false;
                 }
             } else {

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 7:48

Eliminate dependency on sun.* classes in PFixedWidthStroke

$ mvn install

...
~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:39:
warning: sun.dc.path.FastPathProducer is Sun proprietary API and may be
removed in a future release
import sun.dc.path.FastPathProducer;
                  ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:40:
warning: sun.dc.path.PathConsumer is Sun proprietary API and may be removed
in a future release
import sun.dc.path.PathConsumer;
                  ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:41:
warning: sun.dc.path.PathException is Sun proprietary API and may be
removed in a future release
import sun.dc.path.PathException;
                  ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:42:
warning: sun.dc.pr.PathDasher is Sun proprietary API and may be removed in
a future release
import sun.dc.pr.PathDasher;
                ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:43:
warning: sun.dc.pr.PathStroker is Sun proprietary API and may be removed in
a future release
import sun.dc.pr.PathStroker;
                ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:44:
warning: sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in
a future release
import sun.dc.pr.Rasterizer;
                ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:88:
warning: sun.dc.path.PathConsumer is Sun proprietary API and may be removed
in a future release
        public class FillAdapter implements PathConsumer {
                                            ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[136,23]
sun.dc.path.FastPathProducer is Sun proprietary API and may be removed in a
future release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[137,10]
sun.dc.path.PathException is Sun proprietary API and may be removed in a
future release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[148,9]
sun.dc.path.PathConsumer is Sun proprietary API and may be removed in a
future release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:81:
warning: sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in
a future release
                Rasterizer.BUTT, Rasterizer.ROUND, Rasterizer.SQUARE
                ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[81,19]
sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[81,37]
sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[85,2]
sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[85,20]
sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[85,38]
sun.dc.pr.Rasterizer is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:222:
warning: sun.dc.pr.PathStroker is Sun proprietary API and may be removed in
a future release
                PathStroker stroker = new PathStroker(filler);
                ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[222,28]
sun.dc.pr.PathStroker is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[223,2]
sun.dc.path.PathConsumer is Sun proprietary API and may be removed in a
future release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:268:
warning: sun.dc.pr.PathDasher is Sun proprietary API and may be removed in
a future release
                        PathDasher dasher = new PathDasher(stroker);
                        ^

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[268,27]
sun.dc.pr.PathDasher is Sun proprietary API and may be removed in a future
release

~/working/piccolo2d.java-trunk/extras/src/main/java/edu/umd/cs/piccolox/util/PFi
xedWidthStroke.java:[323,11]
sun.dc.path.PathException is Sun proprietary API and may be removed in a
future release

Original issue reported on code.google.com by [email protected] on 29 Jul 2008 at 4:15

Rephrase javadoc package comments

Currently the javadoc package comments come in a style

"This package supports Piccolo activities."

I'd like to rephrase them to a style

"Activities"

as the omitted text transports no information.

In other words: Change the verb-ish style to a noun-ish.

P.S.: As soon as this issue is marked accepted by e.g. Stephen or Michael, 
I'll change the comments and commit them to the trunk.

Original issue reported on code.google.com by [email protected] on 11 Jul 2008 at 8:25

PSwing doesn't work with certain swing components (tooltips, drop-downs, scrollbars (on mouse off), etc.)

What steps will reproduce the problem?
1. Create PSwing components that have a tooltip, drop-down, and scrollbar
2. Add the PSwing to a canvas where it is not at the top-left corner
3. Try to use the swing component

What is the expected output? What do you see instead?
Tooltips and drop-downs show up in the wrong location, and the scrollbar
works fine until you drag the cursor into the content region where it
mysteriously jumps.  (PComboBox is a workaround for the drop-down, but
requires a custom component)

Proposed fix:
(this is not a general purpose fix, because it relies upon the bounding
area of the PSwing component.  Therefore, if you do arbitrary transforms on
the PSwing component (for example rotation), the offset will be slightly off.

Index: extras/edu/umd/cs/piccolox/pswing/PSwing.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 12)
+++ extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 13)
@@ -194,7 +194,7 @@
             } else {
                 updateCanvas(null);
             }
-
+            reshape();
         }
     };

@@ -213,8 +213,8 @@
                 reshape();
             }
         });
+        listenForCanvas(this);
         reshape();
-        listenForCanvas(this);
     }

     /**
@@ -232,7 +232,11 @@
      * Ensures the bounds of the underlying component are accurate, and
sets the bounds of this PNode.
      */
     void reshape() {
-        component.setBounds(0, 0, component.getPreferredSize().width,
component.getPreferredSize().height);
+        Rectangle2D swingBounds = getGlobalBounds();
+        if (canvas != null) {
+           
canvas.getCamera().getViewTransformReference().transform(swingBounds,
swingBounds);
+        }
+        component.setBounds((int) swingBounds.getX(), (int)
swingBounds.getY(), component.getPreferredSize().width,
component.getPreferredSize().height);
         setBounds(0, 0, component.getPreferredSize().width,
component.getPreferredSize().height);
     }

@@ -249,6 +253,7 @@
      * @param renderContext Contains information about current render.
      */
     public void paint(PPaintContext renderContext) {
+        reshape();
         Graphics2D g2 = renderContext.getGraphics();

         if (defaultStroke == null) { 

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 8:09

PCanvas looses keyboard events when a child PSwing node has focus

Swing only dispatches events to the focused node, which means once a PSwing
component gets focus, Piccolo can no longer handle keyboard events.

What steps will reproduce the problem?
1. Create a canvas with some PSwing components
2. Add a keyboard listener on the canvas (or a PNode)
3. click on the PSwing component to give it focus.

What is the expected output? What do you see instead?
From this point on all keyboard events are handed off to the PSwing
component, and don't go through Piccolo.

Proposed fix:
Index: src/edu/umd/cs/piccolo/PCanvas.java
===================================================================
--- src/edu/umd/cs/piccolo/PCanvas.java (revision 11)
+++ src/edu/umd/cs/piccolo/PCanvas.java (revision 12)
@@ -65,7 +65,7 @@
     private boolean paintingImmediately;
     private boolean animatingOnLastPaint;
     private MouseListener mouseListener;
-    private KeyListener keyListener;
+    private KeyEventPostProcessor keyListener;
     private MouseWheelListener mouseWheelListener;
     private MouseMotionListener mouseMotionListener;

@@ -483,20 +483,20 @@
         }

         if (keyListener == null) {
-            keyListener = new KeyListener() {
-                public void keyPressed(KeyEvent e) {
-                    sendInputEventToInputManager(e, KeyEvent.KEY_PRESSED);
+            keyListener = new KeyEventPostProcessor() {
+                public boolean postProcessKeyEvent(KeyEvent e) {
+                    Component owner =
FocusManager.getCurrentManager().getFocusOwner();
+                    while (owner != null) {
+                        if (owner == PCanvas.this) {
+                            sendInputEventToInputManager(e, e.getID());
+                            return true;
                 }
-
-                public void keyReleased(KeyEvent e) {
-                    sendInputEventToInputManager(e, KeyEvent.KEY_RELEASED);
+                        owner = owner.getParent();
                 }
-
-                public void keyTyped(KeyEvent e) {
-                    sendInputEventToInputManager(e, KeyEvent.KEY_TYPED);
+                    return false;
                 }
             };
-            addKeyListener(keyListener);
+           
FocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor(keyListen
er);
         }
     }

@@ -508,7 +508,7 @@
         if (mouseListener != null) removeMouseListener(mouseListener);
         if (mouseMotionListener != null)
removeMouseMotionListener(mouseMotionListener);
         if (mouseWheelListener != null)
removeMouseWheelListener(mouseWheelListener);
-        if (keyListener != null) removeKeyListener(keyListener);
+        if (keyListener != null)
FocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor(keyLis
tener);

         mouseListener = null;
         mouseMotionListener = null;

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 8:03

build.sh has dos (CRLF) linefeeds

this prevents execution on a unix shell (bash)

Reproduce:

$ svn cat -r94 http://piccolo2d.googlecode.com/svn/piccolo.java/trunk/
build.sh | cat --show-nonprinting

Original issue reported on code.google.com by [email protected] on 8 Jul 2008 at 10:01

PSwing nodes prevent proper garbage collection

What steps will reproduce the problem?
1. add a PSwing node to another PNode
2. remove the PSwing node's parent from the canvas
3. force a garbage collection

What is the expected output? What do you see instead?
The PSwing node and its parent PNode should be collected because they are
no longer part of the canvas.  Instead, they are held in memory by the
Swing object that is contained in the PSwing node.

Here is the proposed fix to the PSwing class:
Index: C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwing.java
===================================================================
--- C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwing.java
(revision 3)
+++ C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwing.java
(revision 4)
@@ -187,10 +187,12 @@
     /*The parent listener for camera/canvas changes*/
     private PropertyChangeListener parentListener = new
PropertyChangeListener() {
         public void propertyChange( PropertyChangeEvent evt ) {
-            PNode source = (PNode)evt.getSource();
-            PNode parent = source.getParent();
+            PNode parent = (PNode) evt.getNewValue();
+            clearListeners((PNode) evt.getOldValue());
             if( parent != null ) {
                 listenForCanvas( parent );
+            } else {
+                updateCanvas( null );
             }

         }
@@ -478,7 +480,12 @@

             PNode parent = p;
 //            System.out.println( "parent = " + parent.getClass() );
-            if( parent instanceof PLayer ) {
+            if (parent instanceof PCamera) {
+                PCamera cam = (PCamera) parent;
+                if( cam.getComponent() instanceof PSwingCanvas ) {
+                    updateCanvas( (PSwingCanvas)cam.getComponent() );
+                }
+            } else if( parent instanceof PLayer ) {
                 PLayer player = (PLayer)parent;
 //                System.out.println( "Found player: with " +
player.getCameraCount() + " cameras" );
                 for( int i = 0; i < player.getCameraCount(); i++ ) {
@@ -521,6 +528,22 @@
     }

     /**
+     * Clear out all the listeners registered to make sure there are no
stray references
+     *
+     * @param fromParent Parent to start with for clearing listeners
+     */
+    private void clearListeners(PNode fromParent) {
+        if (fromParent == null) {
+            return;
+        }
+        if (listeningTo(fromParent)) {
+            fromParent.removePropertyChangeListener(
PNode.PROPERTY_PARENT, parentListener );
+            listeningTo.remove(fromParent);
+            clearListeners(fromParent.getParent());
+        }
+    }
+
+    /**
      * Removes this PSwing from previous PSwingCanvas (if any), and ensure
that this PSwing is attached to the new PSwingCanvas.
      * @param newCanvas the new PSwingCanvas (may be null)
      */
@@ -529,8 +552,8 @@
             if( canvas != null ) {
                 canvas.removePSwing( this );
             }
+            canvas = newCanvas;
             if( newCanvas != null ) {
-                canvas = newCanvas;
                 canvas.addPSwing( this );
                 reshape();
                 repaint();

Original issue reported on code.google.com by steveonjava on 23 Jun 2008 at 11:18

Multiple PSwingCanvases can't be used together

What steps will reproduce the problem?
1. Create a single frame
2. Add two separate PSwingCanvases
3. Add Swing components to each, and check the redraw

What is the expected output? What do you see instead?
Because the repaint manager is initalized per canvas, only one of the
canvases will draw properly.  The other one will fail to render, because
its repaint manager has been overridden.

The proposed fix checks the current repaint manager if set and uses that,
or creates a new PSwingRepaintManager if it is not of the right type.

Here is the diff:
Index: extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java (revision 23)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java (revision 24)
@@ -25,10 +25,8 @@

 public class PSwingCanvas extends PCanvas {
     public static final String SWING_WRAPPER_KEY = "Swing Wrapper";
-    private static PSwingRepaintManager pSwingRepaintManager = new
PSwingRepaintManager();

     private SwingWrapper swingWrapper;
-    private PSwingEventHandler swingEventHandler;

     /**
      * Construct a new PSwingCanvas.
@@ -36,11 +34,20 @@
     public PSwingCanvas() {
         swingWrapper = new SwingWrapper( this );
         add( swingWrapper );
+        initRepaintManager();
+        new PSwingEventHandler(this, getCamera()).setActive(true);
+    }
+
+    private void initRepaintManager() {
+        RepaintManager repaintManager = RepaintManager.currentManager(this);
+        PSwingRepaintManager pSwingRepaintManager;
+        if (repaintManager instanceof PSwingRepaintManager) {
+            pSwingRepaintManager = (PSwingRepaintManager) repaintManager;
+        } else {
+            pSwingRepaintManager = new PSwingRepaintManager();
         RepaintManager.setCurrentManager( pSwingRepaintManager );
+        }
         pSwingRepaintManager.addPSwingCanvas( this );
-
-        swingEventHandler = new PSwingEventHandler( this, getCamera()
);//todo or maybe getCameraLayer() or getRoot()?
-        swingEventHandler.setActive( true );
     }

     JComponent getSwingWrapper() {
@@ -65,7 +72,7 @@
             putClientProperty( SWING_WRAPPER_KEY, SWING_WRAPPER_KEY );
         }

-        public PSwingCanvas getpSwingCanvas() {
+        public PSwingCanvas getPSwingCanvas() {
             return pSwingCanvas;
         }
     }


Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 9:44

Add unit test coverage reporting to ant build

Cobertura
http://cobertura.sourceforge.net/

This issue has a couple steps:

1) Add the cobertura ant plug-in to the current ant build

3) Publish the cobertura unit test coverage report to a reasonable location
(a local /report directory might be adequate for now)

Original issue reported on code.google.com by [email protected] on 20 Jun 2008 at 9:40

Remove println to stdout/stderr in unit tests

$ mvn install

...
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running SerializationTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.453 sec
Running AffineTransformTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running PathNodeTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.015 sec
Running NodeTest
PNode@dcb03b[bounds=PBounds[EMPTY],fullBounds=PBounds[EMPTY],transform=AffineTra
nsform[[1.0,
0.0, 100.0], [0.0, 1.0, 100.0]],paint
=null,transparency=1.0,childrenCount=1,fullBoundsInvalid,pickable,childrenPickab
le,visible]
Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 sec
Running ZoomEventHandlerTest
PZoomEventHandler@178460d[minScale=0.0,maxScale=1.7976931348623157E308,viewZoomP
oint=null,minDragStartDistance=0.0,mousePressedCan
vasPoint=null,sequenceInitiatedButton=0,edu.umd.cs.piccolo.event.PInputEventFilt
er@13f210f]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 sec
Running TextNodeTest
PText@cafb56[text=hello
world,font=java.awt.Font[family=SansSerif,name=Helvetica,style=plain,size=12],bo
unds=PBounds[x=0.0,y=0.0,w
idth=57.36328125,height=15.09375],fullBounds=PBounds[EMPTY],transform=null,paint
=null,transparency=1.0,childrenCount=0,fullBoundsI
nvalid,pickable,childrenPickable,visible]
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running PickTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.031 sec
Running TransformActivityTest
PTransformActivity@165f738[source=[D@149b290,destination=[D@16a38b5,slowinSlowOu
t,startTime=1217347407109,duration=1000,stepRate=0
,nextStepTime=1217347407109]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running CameraNodeTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.015 sec
Running ImageNodeTest
PImage@113beb5[image=BufferedImage@14d7745: type = 2 DirectColorModel:
rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInte
rleavedRaster: width = 100 height = 100 #Bands = 4 xOff = 0 yOff = 0
dataOffset[0] 0,bounds=PBounds[x=0.0,y=0.0,width=100.0,height
=100.0],fullBounds=PBounds[x=0.0,y=0.0,width=100.0,height=100.0],transform=null,
paint=null,transparency=1.0,childrenCount=0,pickab
le,childrenPickable,visible]
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.094 sec

Original issue reported on code.google.com by [email protected] on 29 Jul 2008 at 4:13

Roll back PText.java to revision 11

Rather than release new public API added to PText after version 1.2 in
version 1.2.1, roll back PText.java to revision 11.

See also Issue 35.

Original issue reported on code.google.com by [email protected] on 9 Jul 2008 at 3:24

Animation quality change redraws the entire screen

What steps will reproduce the problem?
1. Turn on region debugging
2. Create a PCanvas with a simple node
3. Add an event listener on the node that causes it to change size/position
4. Fire the event listener.

What is the expected output? What do you see instead?
Notice that after the animation completes the entire screen is redrawn even
though the component only takes a small portion of the screen.

The proposed fix tracks region history of redraw events so that on when the
rendering quality is improved it can render the smallest possible region
that will make the entire screen consistent at that image quality.

Here is a diff of the fix:
Index: src/edu/umd/cs/piccolo/PCanvas.java
===================================================================
--- src/edu/umd/cs/piccolo/PCanvas.java (revision 25)
+++ src/edu/umd/cs/piccolo/PCanvas.java (revision 26)
@@ -538,6 +538,8 @@
                 (int) bounds.height);
     }

+    PBounds repaintBounds = new PBounds();
+
     public void paintComponent(Graphics g) {
         PDebug.startProcessingOutput();

@@ -545,6 +547,10 @@
         g2.setColor(getBackground());
         g2.fillRect(0, 0, getWidth(), getHeight());

+        if (getAnimating()) {
+            repaintBounds.add(g2.getClipBounds());
+        }
+
         // create new paint context and set render quality to lowest common
         // denominator render quality.
         PPaintContext paintContext = new PPaintContext(g2);
@@ -561,11 +567,12 @@
         // paint piccolo
         camera.fullPaint(paintContext);

-        // if switched state from animating to not animating invalidate
the entire
-        // screen so that it will be drawn with the default instead of
animating
+        // if switched state from animating to not animating invalidate
the repaint
+        // bounds so that it will be drawn with the default instead of
animating
         // render quality.
         if (!getAnimating() && animatingOnLastPaint) {
-            repaint();
+            repaint(repaintBounds);
+            repaintBounds.reset();
         }
         animatingOnLastPaint = getAnimating();


Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 9:57

http://code.google.com/p/piccolo2d/source/checkout page shows incorrect SVN URLs

The Source web page at

http://code.google.com/p/piccolo2d/source/checkout

shows incorrect SVN checkout URLs:

{https, http}://piccolo2d.googlecode.com/svn/trunk/

Since we have more than one trunk, the documentation on this page should be
expanded to show all three:

{https, http}://piccolo2d.googlecode.com/svn/piccolo.java/trunk/
{https, http}://piccolo2d.googlecode.com/svn/piccolo.net/trunk/
{https, http}://piccolo2d.googlecode.com/svn/pocketpiccolo.net/trunk/

Original issue reported on code.google.com by [email protected] on 20 Jun 2008 at 3:51

deploy maven site,

rather a process than a single action.

Therefore we have to find some kind of agreement - especially Will's voice 
is highly apprecitated here, as he holds the domain.

- where to?
  - www.piccolo2d.org/xy/?
  - google code website?
  - somewhere else?
- how? ftp, scp, erase+recreate or diff?
- how often? Release only? Nightly? Continuous Integration built?

Original issue reported on code.google.com by [email protected] on 22 Jul 2008 at 3:54

Start a release plan (wiki page)

issue#97

I think it's useful to have kinda roadmap with 

intention,
rough schedule,
issues per milestone,
release manager

per milestone listed (or just linked) from one wiki page.

Your opinion?

Original issue reported on code.google.com by [email protected] on 8 Jul 2008 at 11:12

PSwing components don't handle events across multiple cameras

What steps will reproduce the problem?
1. Create a few canvases that point to the same root object
2. Add some PSwing elements to the tree
3. Try clicking on the PSwing element in both canvases

What is the expected output? What do you see instead?
Only one canvas will be able to receive events due to how the
PSwingEventHandler is configured.

Here is the diff for the proposed fix:
Index: extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java (revision 24)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java (revision 25)
@@ -22,7 +22,6 @@
  * @author Sam R. Reid
  * @author Lance E. Good
  */
-
 public class PSwingCanvas extends PCanvas {
     public static final String SWING_WRAPPER_KEY = "Swing Wrapper";

@@ -35,7 +34,6 @@
         swingWrapper = new SwingWrapper(this);
         add(swingWrapper);
         initRepaintManager();
-        new PSwingEventHandler(this, getCamera()).setActive(true);
     }

     private void initRepaintManager() {
Index: extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java   (revision 24)
+++ extras/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java   (revision 25)
@@ -60,7 +60,26 @@
         listenNode = node;
     }

+    public void setCanvas(PSwingCanvas canvas) {
+        this.canvas = canvas;
+    }
+
     /**
+     * Changes the node that this SwingEventHandler is listening to
+     *
+     * @param listenNode PNode to listen for events on
+     */
+    public void setListenNode(PNode listenNode) {
+        if (active) {
+            setActive(false);
+            this.listenNode = listenNode;
+            setActive(true);
+        } else {
+            this.listenNode = listenNode;
+        }
+    }
+
+    /**
      * Constructs a new PSwingEventHandler for the given canvas.
      */
     public PSwingEventHandler( PSwingCanvas canvas ) {
@@ -72,14 +91,13 @@
      *
      * @param active
      */
-    void setActive( boolean active ) {
+    public void setActive(boolean active) {
         if( this.active && !active ) {
             if( listenNode != null ) {
                 this.active = false;
                 listenNode.removeInputEventListener( this );
             }
-        }
-        else if( !this.active && active ) {
+        } else if (!this.active && active) {
             if( listenNode != null ) {
                 this.active = true;
                 listenNode.addInputEventListener( this );
@@ -120,8 +138,7 @@
                     Point p = comp.getLocation();
                     if( comp instanceof Container ) {
                         comp = findShowingComponentAt( comp, x -
(int)p.getX(), y - (int)p.getY() );
-                    }
-                    else {
+                    } else {
                         comp = comp.getComponentAt( x - (int)p.getX(), y -
(int)p.getY() );
                     }
                     if( comp != null && comp.isShowing() ) {
@@ -185,11 +202,9 @@
                 if( comp != null && pSwingMouseEvent.getID() ==
MouseEvent.MOUSE_PRESSED ) {
                     if( SwingUtilities.isLeftMouseButton( pSwingMouseEvent
) ) {
                         leftButtonData.setState( swing, pickedNode, comp,
offX, offY );
-                    }
-                    else if( SwingUtilities.isMiddleMouseButton(
pSwingMouseEvent ) ) {
+                    } else if
(SwingUtilities.isMiddleMouseButton(pSwingMouseEvent)) {
                         middleButtonData.setState( swing, pickedNode,
comp, offX, offY );
-                    }
-                    else if( SwingUtilities.isRightMouseButton(
pSwingMouseEvent ) ) {
+                    } else if
(SwingUtilities.isRightMouseButton(pSwingMouseEvent)) {
                         rightButtonData.setState( swing, pickedNode, comp,
offX, offY );
                     }
                 }
@@ -208,14 +223,12 @@
             }

             // MIDDLE MOUSE BUTTON
-            if( SwingUtilities.isMiddleMouseButton( pSwingMouseEvent ) &&
middleButtonData.getFocusedComponent() != null )
-            {
+            if (SwingUtilities.isMiddleMouseButton(pSwingMouseEvent) &&
middleButtonData.getFocusedComponent() != null) {
                 handleButton( pSwingMouseEvent, aEvent, middleButtonData );
             }

             // RIGHT MOUSE BUTTON
-            if( SwingUtilities.isRightMouseButton( pSwingMouseEvent ) &&
rightButtonData.getFocusedComponent() != null )
-            {
+            if (SwingUtilities.isRightMouseButton(pSwingMouseEvent) &&
rightButtonData.getFocusedComponent() != null) {
                 handleButton( pSwingMouseEvent, aEvent, rightButtonData );
             }
         }
@@ -265,8 +278,7 @@
                 e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(),
e_temp, aEvent );
                 comp.dispatchEvent( e2 );
             }
-        }
-        else {
+        } else {
             // This means mouseEntered
             if( comp != null ) {
                 MouseEvent e_temp = createEnterEvent( comp,
pSwingMouseEvent, offX, offY );
@@ -328,11 +340,9 @@

             PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(
e_temp.getID(), e_temp, aEvent );
             dispatchEvent( buttonData.getFocusedComponent(), e2 );
-        }
-        else {
+        } else {
             dispatchEvent( buttonData.getFocusedComponent(), e1 );
         }
-        //buttonData.getPSwing().repaint();  //Experiment with
SliderExample (from Martin) suggests this line is unnecessary, and a
serious problem in performance.
         e1.consume();
         if( e1.getID() == MouseEvent.MOUSE_RELEASED ) {
             buttonData.mouseReleased();
Index: extras/edu/umd/cs/piccolox/pswing/PSwing.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 24)
+++ extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 25)
@@ -200,6 +200,8 @@
         }
     };

+    private PSwingEventHandler swingEventHandler;
+
     /**
      * Constructs a new visual component wrapper for the Swing component.
      *
@@ -217,6 +219,8 @@
         });
         listenForCanvas(this);
         reshape();
+        swingEventHandler = new PSwingEventHandler(canvas, this);
+        swingEventHandler.setActive(true);
     }

     /**
@@ -569,6 +573,7 @@
             canvas = newCanvas;
             if (newCanvas != null) {
                 canvas.addPSwing(this);
+                swingEventHandler.setCanvas(canvas);
                 reshape();
                 repaint();
             }

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 9:53

Double-buffering not disabled on child PSwing components added after creation

What steps will reproduce the problem?
1. Create a PSwing component with an empty JPanel
2. Add some components to the JPanel *after* the panel has already been
added to the PSwing container

What is the expected output? What do you see instead?
None of the children added after the panel has been added to the PSwing
component get double-buffering disabled, and therefore have render
artifacts when displayed in a canvas.

Here is the proposed fix:

Index: extras/edu/umd/cs/piccolox/pswing/PSwing.java
===================================================================
--- extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 14)
+++ extras/edu/umd/cs/piccolox/pswing/PSwing.java   (revision 15)
@@ -14,6 +14,8 @@
 import java.awt.*;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
+import java.awt.event.ContainerAdapter;
+import java.awt.event.ContainerEvent;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
@@ -421,20 +423,24 @@
      * @param c The Component to be recursively unDoubleBuffered
      */
     void init(Component c) {
-        Component[] children = null;
-        if (c instanceof Container) {
-            children = ((Container) c).getComponents();
-        }

         if (c.getFont() != null) {
             minFontSize = Math.min(minFontSize, c.getFont().getSize());
         }

+        if (c instanceof Container) {
+            Component[] children = ((Container) c).getComponents();
         if (children != null) {
             for (int j = 0; j < children.length; j++) {
                 init(children[j]);
             }
         }
+            ((Container) c).addContainerListener(new ContainerAdapter() {
+                public void componentAdded(ContainerEvent e) {
+                    init(e.getChild());
+                }
+            });
+        }

         if (c instanceof JComponent) {
             ((JComponent) c).setDoubleBuffered(false);

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 8:27

Multiple project entries at ohloh.net

There currently exists more than one ohloh project entry for Piccolo 2D

Piccolo Java, http://www.ohloh.net/projects/3604
Piccolo 2D, http://www.ohloh.net/projects/piccolo2d

I posted to the ohloh.net forums in an attempt to resolve this.

http://www.ohloh.net/forums/10/topics/1761

Original issue reported on code.google.com by [email protected] on 20 Jun 2008 at 5:22

Allow specification of rendering hints on a per-node basis

Currently rendering hints are specified on a per-canvas basis, e.g.

  PCanvas canvas = ...;
  canvas.setDefaultRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
  canvas.setAnimatingRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
  canvas.setInteractingRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);

It would be desireable to be able to specify rendering hints on a per-node
basis, if some nodes should be anti-aliased and some nodes should not be
anti-aliased on the same canvas.

The Simbrain project uses a workaround:

  /** {@inheritDoc} */
  protected void paint(final PPaintContext paintContext) {
    Graphics2D g = paintContext.getGraphics();

    // explicitly prevent antialiasing
   Object oldAntialiasingHint =
g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
   g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
   Object oldInterpolationHint =
g.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
   g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);

    // ... draw using g

    // attempt to revert to existing settings
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntialiasingHint);
    if (oldInterpolationHint != null) {
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
oldInterpolationHint);
    }
    else {
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    }
  }

See for example

PixelMatrixImageNode.java
http://tinyurl.com/5ecjbt


Source files from Simbrain may be relicensed for inclusion in Piccolo2D if
desired.

Original issue reported on code.google.com by [email protected] on 29 Jul 2008 at 4:37

Add checkstyle reporting to ant build

Checkstyle
http://checkstyle.sf.net

This issue has a few steps:

1) Vote on a source code convention to use, and configure it to meet our needs

2) Add the checkstyle ant plug-in to the current ant build

3) Publish the checkstyle report to a reasonable location (a local /report
directory might be adequate for now)

Original issue reported on code.google.com by [email protected] on 20 Jun 2008 at 9:33

PFixedWidthStrokes are not fixed width on Mac OSX

PFixedWidthStrokes are not fixed width on Mac OSX.

The Simbrain project uses a two-part workaround:

1) Strokes are defined with an operating system check

import org.apache.commons.lang.SystemUtils;
...

  /** Default grid stroke. */
  private static final Stroke DEFAULT_GRID_STROKE =
SystemUtils.IS_OS_MAC_OSX ? new BasicStroke(0.5f) : new
PFixedWidthStroke(0.5f);

2) The stroke is prepared using a StrokeUtils class before rendering in a
node's paint method

  /** {@inheritDoc} */
  protected final void paint(final PPaintContext paintContext) {
    Graphics2D g = paintContext.getGraphics();
    ...
    g.setStroke(StrokeUtils.prepareStroke(gridStroke, paintContext));


See for example

AbstractSensorMatrixNode.java
http://tinyurl.com/5mxwla

StrokeUtils.java
http://tinyurl.com/5grzox


Source files from Simbrain may be relicensed for inclusion in Piccolo2D if
desired.

Original issue reported on code.google.com by [email protected] on 29 Jul 2008 at 4:28

PSwing components cause full page re-rendering on add/remove operations

What steps will reproduce the problem?
1. Turn on region debugging
2. Add some PSwing components to a canvas
3. Remove one of the PSwing components

What is the expected output? What do you see instead?
On both addition and removal, the whole canvas will be redrawn, causing
rendering delays for a complicated UI.

Proposed fix:
--- C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwing.java
(revision 7)
+++ C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PSwing.java
(revision 8)
     private void updateCanvas( PSwingCanvas newCanvas ) {
...
                 reshape();
                 repaint();
-                canvas.invalidate();
-                canvas.revalidate();
-                canvas.repaint();
             }
         }
     }

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 7:26

Prepare the 1.3 release

Put the release together as development finishes.
- ReleaseNotes
- prepare and test release candidates
- feature the downloads
- upload to a maven repository - ideally repo1.maven.org

Original issue reported on code.google.com by [email protected] on 20 Jul 2008 at 12:56

Refactor static int NO_WRAP etc. on PText to type-safe enum

> edu.umd.cs.piccolo.nodes.PText
>
> Added:
>
> public static int NO_WRAP;
> public static int WRAP;
> public static int WRAP_CLIP;
> public void setWrapMode(int)

This should be refactored to a type-safe enum, so that it might be replaced
by a real enum if/when we go to jdk 1.5+.

Original issue reported on code.google.com by [email protected] on 2 Jul 2008 at 4:28

Name property for PNodes

PSwing components need a simple name property in order to be easily
identified.  This is especially in the case of automated testing where you
want to be able to easily script a user interface by referencing nodes on
screen.

The proposal is to add a name property (with matching getters and setters)
to the PNode class.  This is a requirement for the FEST-Swing Piccolo
integration (separate enhancement).

Here is the code diff:
Index: src/edu/umd/cs/piccolo/PNode.java
===================================================================
--- src/edu/umd/cs/piccolo/PNode.java   (revision 20)
+++ src/edu/umd/cs/piccolo/PNode.java   (revision 22)
@@ -230,6 +230,8 @@
    private boolean childBoundsInvalid;
    private boolean occluded;

+    private String name;
+
     /**
     * Constructs a new PNode.
     * <P>
@@ -246,6 +248,19 @@
        visible = true;
    }

+    public PNode(String name) {
+        this();
+        this.name = name;
+   }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
    //****************************************************************
    // Animation - Methods to animate this node.
    // 
@@ -3047,7 +3062,7 @@
     */
    protected String paramString() {
        StringBuffer result = new StringBuffer();
-       
+       result.append("name="+ (name == null ? "null" : name.toString()));
        result.append("bounds=" + (bounds == null ? "null" : bounds.toString()));
        result.append(",fullBounds=" + (fullBoundsCache == null ? "null" :
fullBoundsCache.toString()));
        result.append(",transform=" + (transform == null ? "null" :
transform.toString()));

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 8:42

PComboBox does not work when nested in a Panel

What steps will reproduce the problem?
1. Create a PComboBox
2. Add it to a Panel (with other components or a border so the panel
dimenions are larger than the combo box)
3. Add the Panel to a PSwing component

What is the expected output? What do you see instead?
The drop-down doesn't show up correctly, because it is using the width of
the panel rather than the width of the combo box.

Here is the fix:
PComboBox:
         if (pSwing == null || canvas == null) {
             throw new RuntimeException("PComboBox.setEnvironment( swing,
pCanvas );//has to be done manually at present");
         }
-        Rectangle2D r1c = pSwing.getBounds();
+        Rectangle2D r1c = new Rectangle2D.Double(pSwing.getX(),
pSwing.getY(), getWidth(), getHeight());
         pSwing.localToGlobal( r1c );
         canvas.getCamera().globalToLocal( r1c );
         r1c =
canvas.getCamera().getViewTransform().createTransformedShape( r1c
).getBounds2D();

And here is the updated test:

---
C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwing.java
(revision 4)
+++
C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwing.java
(revision 5)
@@ -118,12 +121,17 @@
         root.translate( 300, 200 );
         pCanvas.getLayer().addChild( root );

+        // A Combo Box
+        JPanel comboPanel = new JPanel();
+        comboPanel.setBorder( BorderFactory.createTitledBorder( "Combo
Box" ) );
         String[] listItems = {"Summer Teeth", "Mermaid Avenue", "Being
There", "A.M."};
         PComboBox box = new PComboBox( listItems );
-        swing = new PSwing(box );
-        swing.translate( 200, 250 );
+        comboPanel.add(box);
+        swing = new PSwing(comboPanel);
+        swing.translate( 200, 230 );
         pCanvas.getLayer().addChild( swing );
         box.setEnvironment( swing, pCanvas );//has to be done manually at
present

Original issue reported on code.google.com by steveonjava on 23 Jun 2008 at 11:39

Generics Support

When using Piccolo in the past it's always been annoying to me that it 
didn't use Generics.  It'd cut down on the code base a bit since there's 
lots of boilerplate iterator usage.

I know it's a bit early for feature requests, but... it would be nice.


Thanks

Original issue reported on code.google.com by allain.lalonde on 23 Jun 2008 at 1:53

Extra mouse movement events fired on mouse exit

What steps will reproduce the problem?
1. Create a PNode
2. Attach a PInputEventListener
3. Move the mouse out of the node.

What is the expected output? What do you see instead?
You should only receive a mouse movement event while in the node, but there
is an extra "surrogate" mouse moved event fired on exit.  The same is true
on mouse entry.

Please use labels and text to provide additional information.

Here is the proposed fix, which gets rid of the "surrogate" mouse event
mechanism, and fixes the handlers to work without this by setting the
previous mouse over properly:
Index: src/edu/umd/cs/piccolo/PInputManager.java
===================================================================
--- src/edu/umd/cs/piccolo/PInputManager.java   (revision 27)
+++ src/edu/umd/cs/piccolo/PInputManager.java   (revision 30)
@@ -175,10 +175,12 @@

     public void mouseEntered(PInputEvent event) {
         dispatchEventToListener(event, MouseEvent.MOUSE_ENTERED, mouseOver);
+        previousMouseOver = mouseOver;
     }

     public void mouseExited(PInputEvent event) {
         dispatchEventToListener(event, MouseEvent.MOUSE_EXITED,
previousMouseOver);
+        previousMouseOver = null;
     }

     public void mouseMoved(PInputEvent event) {
@@ -227,34 +229,18 @@

         PInputEvent e = new PInputEvent(this, nextInput, nextInputSource);

-        Point2D newCurrentCanvasPosition = null;
-        Point2D newLastCanvasPosition = null;
-
         if (e.isMouseEvent()) {
-            if (e.isMouseEnteredOrMouseExited()) {
-                PPickPath aPickPath = nextInputSource.pick(((MouseEvent)
nextInput).getX(), ((MouseEvent) nextInput).getY(), 1);
-                setMouseOver(aPickPath);
-                previousMouseOver = aPickPath;
-                newCurrentCanvasPosition = (Point2D)
currentCanvasPosition.clone();
-                newLastCanvasPosition = (Point2D) lastCanvasPosition.clone();
-            } else {
                 lastCanvasPosition.setLocation(currentCanvasPosition);
                 currentCanvasPosition.setLocation(((MouseEvent)
nextInput).getX(), ((MouseEvent) nextInput).getY());
                 PPickPath aPickPath =
nextInputSource.pick(currentCanvasPosition.getX(),
currentCanvasPosition.getY(), 1);
                 setMouseOver(aPickPath);
             }
-        }

         nextInput = null;
         nextInputSource = null;

         this.processEvent(e, nextType);
-
-        if (newCurrentCanvasPosition != null && newLastCanvasPosition !=
null) {
-            currentCanvasPosition.setLocation(newCurrentCanvasPosition);
-            lastCanvasPosition.setLocation(newLastCanvasPosition);
         }
-    }

     public void processEventFromCamera(InputEvent event, int type, PCamera
camera) {
         // process input
@@ -276,4 +262,3 @@
         }
     }
 }
-
Index: src/edu/umd/cs/piccolo/PCanvas.java
===================================================================
--- src/edu/umd/cs/piccolo/PCanvas.java (revision 27)
+++ src/edu/umd/cs/piccolo/PCanvas.java (revision 30)
@@ -340,28 +340,10 @@
                 }

                 public void mouseEntered(MouseEvent e) {
-                    MouseEvent simulated = null;
-
-                    if ((e.getModifiersEx() &
(InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON2_DOWN_MASK |
InputEvent.BUTTON3_DOWN_MASK)) != 0) {
-                        simulated = new MouseEvent((Component)
e.getSource(), MouseEvent.MOUSE_DRAGGED, e.getWhen(), e.getModifiers(),
e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
-                    } else {
-                        simulated = new MouseEvent((Component)
e.getSource(), MouseEvent.MOUSE_MOVED, e.getWhen(), e.getModifiers(),
e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
-                    }
-
                     sendInputEventToInputManager(e, MouseEvent.MOUSE_ENTERED);
-                    sendInputEventToInputManager(simulated,
simulated.getID());
                 }

                 public void mouseExited(MouseEvent e) {
-                    MouseEvent simulated = null;
-
-                    if ((e.getModifiersEx() &
(InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON2_DOWN_MASK |
InputEvent.BUTTON3_DOWN_MASK)) != 0) {
-                        simulated = new MouseEvent((Component)
e.getSource(), MouseEvent.MOUSE_DRAGGED, e.getWhen(), e.getModifiers(),
e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
-                    } else {
-                        simulated = new MouseEvent((Component)
e.getSource(), MouseEvent.MOUSE_MOVED, e.getWhen(), e.getModifiers(),
e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
-                    }
-
-                    sendInputEventToInputManager(simulated,
simulated.getID());
                     sendInputEventToInputManager(e, MouseEvent.MOUSE_EXITED);
                 }

Original issue reported on code.google.com by steveonjava on 29 Jun 2008 at 10:34

PFrameTest unit test fails on linux

$ mvn install

...
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running PFrameTest
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.326 sec
<<< FAILURE!
Running edu.umd.cs.piccolox.pswing.tests.TestPSwing
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec
Running edu.umd.cs.piccolox.pswing.tests.TestPSwingFull
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 sec
Running NotificationCenterTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.077 sec

Results :

Failed tests: 
  testComponentResized(PFrameTest)

Tests run: 2, Failures: 1, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] There are test failures.


$ cat extras/target/surefire-reports/PFrameTest.txt
-------------------------------------------------------------------------------
Test set: PFrameTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.327 sec
<<< FAILURE!
testComponentResized(PFrameTest)  Time elapsed: 0.264 sec  <<< FAILURE!
junit.framework.AssertionFailedError: Canvas height should be inset by
frame decoration size
    at junit.framework.Assert.fail(Assert.java:47)
    at junit.framework.Assert.assertTrue(Assert.java:20)
    at PFrameTest.testComponentResized(PFrameTest.java:25)

Original issue reported on code.google.com by [email protected] on 29 Jul 2008 at 4:09

Cannot turn off interacting at the PRoot level

Currently the ways of downgrading animation quality are to create an
animation or to set interacting on the Canvas.  However, if you are trying
to indicate that all canvases which are showing a particular node should
set interacting to true, there is no easy way to do this.

The proposed fix is to add a correlating setInteracting method to PRoot.

Here is a unified diff of the proposed fix:
Index: src/edu/umd/cs/piccolo/PRoot.java
===================================================================
--- src/edu/umd/cs/piccolo/PRoot.java   (revision 16)
+++ src/edu/umd/cs/piccolo/PRoot.java   (revision 17)
@@ -29,26 +29,25 @@
  */
 package edu.umd.cs.piccolo;

+import edu.umd.cs.piccolo.activities.PActivity;
+import edu.umd.cs.piccolo.activities.PActivityScheduler;
+import edu.umd.cs.piccolo.util.PDebug;
+import edu.umd.cs.piccolo.util.PNodeFilter;
+
+import javax.swing.*;
 import java.awt.event.ActionListener;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;

-import javax.swing.SwingUtilities;
-import javax.swing.Timer;
-
-import edu.umd.cs.piccolo.activities.PActivity;
-import edu.umd.cs.piccolo.activities.PActivityScheduler;
-import edu.umd.cs.piccolo.util.PDebug;
-import edu.umd.cs.piccolo.util.PNodeFilter;
-
 /**
  * <b>PRoot</b> serves as the top node in Piccolo's runtime structure. 
  * The PRoot responsible for running the main UI loop that processes
  * input from activities and external events.
- * <P>
+ * <p/>
+ *
+ * @author Jesse Grosjean
  * @version 1.1
- * @author Jesse Grosjean
  */
 public class PRoot extends PNode {

@@ -60,10 +59,13 @@
     */
    public static final String PROPERTY_INPUT_SOURCES = "inputSources";
     public static final int PROPERTY_CODE_INPUT_SOURCES = 1 << 14;
+    public static final String PROPERTY_INTERACTING_CHANGED =
"INTERACTING_CHANGED_NOTIFICATION";
+    public static final int PROPERTY_CODE_INTERACTING_CHANGED = 1 << 13;

    protected transient boolean processingInputs;
    protected transient boolean processInputsScheduled;

+    private transient int interacting;
    private PInputManager defaultInputManager;
    private transient List inputSources;
    private transient long globalTime;
@@ -122,6 +124,7 @@
            public boolean accept(PNode aNode) {
                return (aNode instanceof PCamera) && (((PCamera)aNode).getComponent()
!= null);
            }
+
            public boolean acceptChildrenOf(PNode aNode) {
                return true;
            }
@@ -162,6 +165,46 @@
    }

    /**
+     * Return true if this root has been marked as interacting. If so
+     * the root will normally render at a lower quality that is faster.
+     *
+     * @return True if this root has user interaction taking place
+     */
+    public boolean getInteracting() {
+        return interacting > 0;
+    }
+
+    /**
+     * Set if this root is interacting. If so the root will normally
+     * render at a lower quality that is faster. Also repaints the root if the
+     * the interaction has ended.
+     * <p/>
+     * This has similar functionality to the setInteracting method on Canvas,
+     * but this is the appropriate place to mark interactions that may occur
+     * in multiple canvases if this Root is shared.
+     *
+     * @param isInteracting True if this root has user interaction taking
place
+     * @see PCanvas#setInteracting(boolean)
+     */
+    public void setInteracting(boolean isInteracting) {
+        boolean wasInteracting = getInteracting();
+
+        if (isInteracting) {
+            interacting++;
+        } else {
+            interacting--;
+        }
+
+        isInteracting = getInteracting();
+        if (!isInteracting) {
+            repaint();
+        }
+        if (wasInteracting != isInteracting) {
+            firePropertyChange(PROPERTY_CODE_INTERACTING_CHANGED,
PROPERTY_INTERACTING_CHANGED, wasInteracting, isInteracting);
+        }
+    }
+
+    /**
     * Advanced. If you want to add additional input sources to the roots
     * UI process you can do that here. You will seldom do this unless you
     * are making additions to the piccolo framework.
Index: src/edu/umd/cs/piccolo/PCanvas.java
===================================================================
--- src/edu/umd/cs/piccolo/PCanvas.java (revision 16)
+++ src/edu/umd/cs/piccolo/PCanvas.java (revision 17)
@@ -34,6 +34,7 @@
 import edu.umd.cs.piccolo.event.PZoomEventHandler;
 import edu.umd.cs.piccolo.util.*;

+import javax.swing.FocusManager;
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
@@ -50,7 +51,7 @@
  */
 public class PCanvas extends JComponent implements PComponent {

-    public static final String INTERATING_CHANGED_NOTIFICATION =
"INTERATING_CHANGED_NOTIFICATION";
+    public static final String INTERACTING_CHANGED_NOTIFICATION =
"INTERACTING_CHANGED_NOTIFICATION";

     public static PCanvas CURRENT_ZCANVAS = null;

@@ -209,7 +210,7 @@
      * the canvas will normally render at a lower quality that is faster.
      */
     public boolean getInteracting() {
-        return interacting > 0;
+        return interacting > 0 || getRoot().getInteracting();
     }

     /**
@@ -248,7 +249,7 @@
         isInteracting = getInteracting();

         if (wasInteracting != isInteracting) {
-            firePropertyChange(INTERATING_CHANGED_NOTIFICATION,
wasInteracting, isInteracting);
+            firePropertyChange(INTERACTING_CHANGED_NOTIFICATION,
wasInteracting, isInteracting);
         }
     }

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 8:37

PInputEvent does not have camera information for keyboard events.

Even though there is a particular camera that lost received focus from an
event, Piccolo does not provide this information when a keyboard event
happens, which makes it difficult to do transform operations in a keyboard
event listener without an external reference to the Canvas/Camera.

Here is the proposed fix:
Index: src/edu/umd/cs/piccolo/event/PInputEvent.java
===================================================================
--- src/edu/umd/cs/piccolo/event/PInputEvent.java   (revision 13)
+++ src/edu/umd/cs/piccolo/event/PInputEvent.java   (revision 14)
@@ -29,15 +29,6 @@
  */
 package edu.umd.cs.piccolo.event;

-import java.awt.Cursor;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
-import java.awt.geom.Point2D;
-
-import javax.swing.SwingUtilities;
-
 import edu.umd.cs.piccolo.PCamera;
 import edu.umd.cs.piccolo.PComponent;
 import edu.umd.cs.piccolo.PInputManager;
@@ -45,31 +36,42 @@
 import edu.umd.cs.piccolo.util.PDimension;
 import edu.umd.cs.piccolo.util.PPickPath;

+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.geom.Point2D;
+
 /**
  * <b>PInputEvent</b> is used to notify PInputEventListeners of keyboard
and mouse
  * input. It has methods for normal event properties such as event
modifier keys
  * and event canvas location.
- * <P>
+ * <p/>
  * In addition is has methods to get the mouse position and delta in a
variety 
  * of coordinate systems.
- * <P>
+ * <p/>
  * Last of all it provides access to the dispatch manager that can be queried
  * to find the current mouse over, mouse focus, and keyboard focus.
- * <P>
+ * <p/>
+ *
+ * @author Jesse Grosjean
  * @version 1.0
- * @author Jesse Grosjean
  */
 public class PInputEvent {

    private InputEvent inputEvent;
    private PPickPath pickPath;
    private PInputManager inputManager;
+    private PCamera inputSource;
    private boolean handled;

-   public PInputEvent(PInputManager inputManager, InputEvent event) {
+    public PInputEvent(PInputManager inputManager, InputEvent event,
PCamera inputSource) {
        super();
        inputEvent = event;
        this.inputManager = inputManager;
+        this.inputSource = inputSource;
    }

    public void pushCursor(Cursor cursor) {
@@ -100,7 +102,7 @@
     * getTopCamera.
     */
    public PCamera getCamera() {
-       return getPath().getBottomCamera();
+        return getPath() == null ? inputSource : getPath().getBottomCamera();
    }

    /**
@@ -108,7 +110,7 @@
     * with the PCanvas that requested the current repaint.
     */
    public PCamera getTopCamera() {
-       return getPath().getTopCamera();
+        return getPath() == null ? inputSource : getPath().getTopCamera();
    }

    /**
Index: src/edu/umd/cs/piccolo/PInputManager.java
===================================================================
--- src/edu/umd/cs/piccolo/PInputManager.java   (revision 13)
+++ src/edu/umd/cs/piccolo/PInputManager.java   (revision 14)
@@ -29,27 +29,24 @@
  */
 package edu.umd.cs.piccolo;

-import java.awt.event.FocusEvent;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
-import java.awt.geom.Point2D;
-
 import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
 import edu.umd.cs.piccolo.event.PInputEvent;
 import edu.umd.cs.piccolo.event.PInputEventListener;
 import edu.umd.cs.piccolo.util.PPickPath;

+import java.awt.event.*;
+import java.awt.geom.Point2D;
+
 /**
  * <b>PInputManager</b> is responsible for dispatching PInputEvents
  * to node's event listeners. Events are dispatched from PRoot's processInputs
  * method.
- * <P>
+ * <p/>
+ *
+ * @author Jesse Grosjean
+ * @version 1.0
  * @see edu.umd.cs.piccolo.event.PInputEvent
  * @see PRoot
- * @version 1.0
- * @author Jesse Grosjean
  */
 public class PInputManager extends PBasicInputEventHandler implements
PRoot.InputSource {

@@ -90,7 +87,7 @@
     * Set the node that should recive key events.
     */ 
    public void setKeyboardFocus(PInputEventListener eventHandler) {        
-       PInputEvent focusEvent = new PInputEvent(this, null);
+        PInputEvent focusEvent = new PInputEvent(this, null, null);

        if (keyboardFocus != null) {
            dispatchEventToListener(focusEvent, FocusEvent.FOCUS_LOST, keyboardFocus);
@@ -195,7 +192,8 @@
        }
        pressedCount++;
        dispatchEventToListener(event, MouseEvent.MOUSE_PRESSED, mouseFocus);
-       if (pressedCount < 1 || pressedCount > 3) System.err.println("invalid
pressedCount on mouse pressed: " + pressedCount);
+        if (pressedCount < 1 || pressedCount > 3)
+            System.err.println("invalid pressedCount on mouse pressed: " +
pressedCount);
    }

    public void mouseReleased(PInputEvent event) {
@@ -205,7 +203,8 @@
        if (pressedCount == 0) {
            setMouseFocus(null);
        }
-       if (pressedCount < 0 || pressedCount > 2) System.err.println("invalid
pressedCount on mouse released: " + pressedCount);
+        if (pressedCount < 0 || pressedCount > 2)
+            System.err.println("invalid pressedCount on mouse released: "
+ pressedCount);
    }

    protected void checkForMouseEnteredAndExited(PInputEvent event) {       
@@ -226,7 +225,7 @@
    public void processInput() {
        if (nextInput == null) return;

-       PInputEvent e = new PInputEvent(this, nextInput);
+        PInputEvent e = new PInputEvent(this, nextInput, nextInputSource);

        Point2D newCurrentCanvasPosition = null;
        Point2D newLastCanvasPosition = null;

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 8:14

PComboBox doesn't use Metal, Windows, and Motif look and feels

What steps will reproduce the problem?
1. Set the look and feel to metal, windows, or motif
2. Create a PComboBox
3. The component style will not change

What is the expected output? What do you see instead?
The PComboBox component should respect the L&F set by the user

Here is the proposed fix:

---
C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PComboBox.java
(revision 4)
+++
C:/dev/piccolo.java-all/extras/edu/umd/cs/piccolox/pswing/PComboBox.java
(revision 5)
@@ -4,16 +4,19 @@
  */
 package edu.umd.cs.piccolox.pswing;

-import java.awt.Rectangle;
-import java.awt.geom.Rectangle2D;
-import java.io.Serializable;
-import java.util.Vector;
+import com.sun.java.swing.plaf.motif.MotifComboBoxUI;
+import com.sun.java.swing.plaf.windows.WindowsComboBoxUI;

-import javax.swing.ComboBoxModel;
-import javax.swing.JComboBox;
+import javax.swing.*;
+import javax.swing.plaf.ComboBoxUI;
 import javax.swing.plaf.basic.BasicComboBoxUI;
 import javax.swing.plaf.basic.BasicComboPopup;
 import javax.swing.plaf.basic.ComboPopup;
+import javax.swing.plaf.metal.MetalComboBoxUI;
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.util.Vector;

 /**
  * The <b>PComboBox</b> is used instead of a JComboBox in a Piccolo scene
graph.
@@ -54,8 +57,8 @@
      *
      * @param model The ComboBoxModel from which the list will be created
      */
-    public PComboBox( ComboBoxModel model ) {
-        super( model );
+    public PComboBox(ComboBoxModel model) {
+        super(model);
         init();
     }

@@ -64,8 +67,8 @@
      *
      * @param items The items to populate the PComboBox list
      */
-    public PComboBox( final Object items[] ) {
-        super( items );
+    public PComboBox(final Object items[]) {
+        super(items);
         init();
     }

@@ -74,8 +77,8 @@
      *
      * @param items The items to populate the PComboBox list
      */
-    public PComboBox( Vector items ) {
-        super( items );
+    public PComboBox(Vector items) {
+        super(items);
         init();
     }

@@ -91,7 +94,16 @@
      * Substitue our UI for the default
      */
     private void init() {
-        setUI( new PBasicComboBoxUI() );
+        ComboBoxUI ui = getUI();
+        if (ui instanceof MetalComboBoxUI) {
+            setUI(new PMetalComboBoxUI());
+        } else if (ui instanceof WindowsComboBoxUI) {
+            setUI(new PWindowsComboBoxUI());
+        } else if (ui instanceof MotifComboBoxUI) {
+            setUI(new PWindowsComboBoxUI());
+        } else {
+            setUI(new PBasicComboBoxUI());
+        }
     }

     /**
@@ -100,13 +112,13 @@
      * @param pSwing
      * @param canvas
      */
-    public void setEnvironment( PSwing pSwing, PSwingCanvas canvas ) {
+    public void setEnvironment(PSwing pSwing, PSwingCanvas canvas) {
         this.pSwing = pSwing;
         this.canvas = canvas;
     }

     /**
-     * The substitute look and feel - used to capture the mouse
+     * The basic substitute look and feel - used to capture the mouse
      * events on the arrowButton and the component itself and
      * to create our PopupMenu rather than the default
      */
@@ -116,8 +128,8 @@
          * Create our Popup instead of theirs
          */
         protected ComboPopup createPopup() {
-            PBasicComboPopup popup = new PBasicComboPopup( comboBox );
-            popup.getAccessibleContext().setAccessibleParent( comboBox );
+            PBasicComboPopup popup = new PBasicComboPopup(comboBox);
+            popup.getAccessibleContext().setAccessibleParent(comboBox);
             return popup;
         }
     }
@@ -131,11 +143,10 @@
         /**
          * @param combo The parent ComboBox
          */
-        public PBasicComboPopup( JComboBox combo ) {
-            super( combo );
+        public PBasicComboPopup(JComboBox combo) {
+            super(combo);
         }

-
         /**
          * Computes the bounds for the Popup in Piccolo if a
          * PMouseEvent has been received.  Otherwise, it uses the
@@ -147,35 +158,74 @@
          * @param ph corresponds to the height of the popup
          * @return The bounds for the PopupMenu
          */
-        protected Rectangle computePopupBounds( int px, int py, int pw,
int ph ) {
+        protected Rectangle computePopupBounds(int px, int py, int pw, int
ph) {
             Rectangle2D r = getNodeBoundsInCanvas();
-            Rectangle sup = super.computePopupBounds( px, py, pw, ph );
-            return new Rectangle( (int)r.getX(), (int)r.getMaxY(),
(int)sup.getWidth(), (int)sup.getHeight() );
+            Rectangle sup = super.computePopupBounds(px, py, pw, ph);
+            return new Rectangle((int) r.getX(), (int) r.getMaxY(), (int)
sup.getWidth(), (int) sup.getHeight());
         }
+
+
     }

-    private Rectangle2D getNodeBoundsInCanvas() {
-        if( pSwing == null || canvas == null ) {
-            throw new RuntimeException( "PComboBox.setEnvironment( swing,
pCanvas );//has to be done manually at present" );
+    /**
+     * The substitute Metal look and feel - used to capture the mouse
+     * events on the arrowButton and the component itself and
+     * to create our PopupMenu rather than the default
+     */
+    protected class PMetalComboBoxUI extends MetalComboBoxUI {
+
+        /**
+         * Create our Popup instead of theirs
+         */
+        protected ComboPopup createPopup() {
+            PBasicComboPopup popup = new PBasicComboPopup(comboBox);
+            popup.getAccessibleContext().setAccessibleParent(comboBox);
+            return popup;
         }
-        Rectangle2D r1c = pSwing.getBounds();
-        pSwing.localToGlobal( r1c );
-        canvas.getCamera().globalToLocal( r1c );
-        r1c =
canvas.getCamera().getViewTransform().createTransformedShape( r1c
).getBounds2D();
-        return r1c;
     }

-}
+    /**
+     * The substitute Windows look and feel - used to capture the mouse
+     * events on the arrowButton and the component itself and
+     * to create our PopupMenu rather than the default
+     */
+    protected class PWindowsComboBoxUI extends WindowsComboBoxUI {

+        /**
+         * Create our Popup instead of theirs
+         */
+        protected ComboPopup createPopup() {
+            PBasicComboPopup popup = new PBasicComboPopup(comboBox);
+            popup.getAccessibleContext().setAccessibleParent(comboBox);
+            return popup;
+        }
+    }

+    /**
+     * The substitute Motif look and feel - used to capture the mouse
+     * events on the arrowButton and the component itself and
+     * to create our PopupMenu rather than the default
+     */
+    protected class PMotifComboBoxUI extends MotifComboBoxUI {

+        /**
+         * Create our Popup instead of theirs
+         */
+        protected ComboPopup createPopup() {
+            PBasicComboPopup popup = new PBasicComboPopup(comboBox);
+            popup.getAccessibleContext().setAccessibleParent(comboBox);
+            return popup;
+        }
+    }

+    private Rectangle2D getNodeBoundsInCanvas() {
+        if (pSwing == null || canvas == null) {
+            throw new RuntimeException("PComboBox.setEnvironment( swing,
pCanvas );//has to be done manually at present");
+        }
+        Rectangle2D r1c = new Rectangle2D.Double(pSwing.getX(),
pSwing.getY(), getWidth(), getHeight());
+        pSwing.localToGlobal(r1c);
+        canvas.getCamera().globalToLocal(r1c);
+        return
canvas.getCamera().getViewTransform().createTransformedShape(r1c).getBounds2D();
+    }

Original issue reported on code.google.com by steveonjava on 23 Jun 2008 at 11:42

Support non-rectangular zooming of PCameras on nodes

The current methods on PCamera only allow zooming onto nodes with a
constrained scale.  This enhancement is to add a true fit-to-window scale
option.

Here is the proposed fix:
Index: src/edu/umd/cs/piccolo/PCamera.java
===================================================================
--- src/edu/umd/cs/piccolo/PCamera.java (revision 10)
+++ src/edu/umd/cs/piccolo/PCamera.java (revision 11)
@@ -59,14 +59,15 @@
  * Each camera maintains a view transform through which it views these
  * layers. Translating and scaling this view transform is how zooming
  * and panning are implemented.
- * <p>
+ * <p/>
  * Cameras are also the point through which all PInputEvents enter
Piccolo. The

  * canvas coordinate system, and the local coordinate system of the
topmost cam
era
  * should always be the same.
- * <p>
+ * <p/>
+ *
+ * @author Jesse Grosjean
+ * @version 1.0
  * @see PLayer
- * @version 1.0
- * @author Jesse Grosjean
  */
 public class PCamera extends PNode {

@@ -393,7 +394,6 @@
                return false;
        }

-
        //****************************************************************
        // View Transform - Methods for accessing the view transform. The
        // view transform is applied before painting and picking the cameras
@@ -502,6 +502,10 @@
                firePropertyChange(PROPERTY_CODE_VIEW_TRANSFORM,
PROPERTY_VIEW_T
RANSFORM, null, viewTransform);
        }

+    public PTransformActivity animateViewToCenterBounds(Rectangle2D
centerBound
s, boolean shouldScaleToFit, long duration) {
+        return animateViewToCenterBounds(centerBounds, shouldScaleToFit,
false,
 duration);
+    }
+
        /**
         * Animate the camera's view from its current transform when the
activit
y
         * starts to a new transform that centers the given bounds in the
camera

@@ -513,18 +517,26 @@
         * bounds fit fully within the cameras view bounds, else the camera
will

         * maintain its original scale.
         */
-       public PTransformActivity animateViewToCenterBounds(Rectangle2D
centerBo
unds, boolean shouldScaleToFit, long duration) {
+    public PTransformActivity animateViewToCenterBounds(Rectangle2D
centerBound
s, boolean shouldScaleToFit, boolean nonRectangularScale, long duration) {
                PBounds viewBounds = getViewBounds();
+        PAffineTransform newTransform = getViewTransform();
                PDimension delta =
viewBounds.deltaRequiredToCenter(centerBounds
);
-               PAffineTransform newTransform = getViewTransform();
                newTransform.translate(delta.width, delta.height);

                if (shouldScaleToFit) {
+            if (nonRectangularScale) {
+                double wS = viewBounds.getWidth() / centerBounds.getWidth();
+                double hS = viewBounds.getHeight() / centerBounds.getHeight();
+                newTransform.translate(centerBounds.getCenterX(),
centerBounds.
getCenterY());
+                newTransform.scale(wS, hS);
+                newTransform.translate(-centerBounds.getCenterX(),
-centerBound
s.getCenterY());
+            } else {
                        double s = Math.min(viewBounds.getWidth() /
centerBounds
.getWidth(), viewBounds.getHeight() / centerBounds.getHeight());
                        if (s != Double.POSITIVE_INFINITY && s != 0) {
                                newTransform.scaleAboutPoint(s,
centerBounds.get
CenterX(), centerBounds.getCenterY());
                        }
                }
+        }

                return animateViewToTransform(newTransform, duration);
        }
@@ -575,6 +587,7 @@
                        public void setTransform(AffineTransform aTransform) {
                                PCamera.this.setViewTransform(aTransform);
                        }
+
                        public void getSourceMatrix(double[] aSource) {
                                PCamera.this.viewTransform.getMatrix(aSource);
                        }
@@ -598,6 +611,7 @@
        public int getViewConstraint() {
                return viewConstraint;
        }
+
        public void setViewConstraint(int constraint) {
                viewConstraint = constraint;
                applyViewConstraints();

Original issue reported on code.google.com by steveonjava on 24 Jun 2008 at 7:54

Migrate ant build to maven2

Migrate the existing ant-based build to maven2.

Maven
http://maven.apache.org/

There is a lot of work involved in this (moving things around, mostly),
some of which might be broken out into separate issues:

 - Create project metadata
 - Convert directory structure (e.g. src/edu --> src/java/main/edu)
 - Add reporting plug-ins (Checkstyle, FindBugs, Cobertura, etc.)
 - Consider packaging with regards to core, extras, SWT
 - Consider building static website content with Maven
 - Document and implement the release process

Original issue reported on code.google.com by [email protected] on 20 Jun 2008 at 9:49

PActivity activityFinished gets called multiple times

What steps will reproduce the problem?
1. Create a new PActivity
2. Call action.terminate with a parameter of TERMINATE_AND_FINISH
3. Repeat the same call

What is the expected output? What do you see instead?
the activityFinished handler should only get called once, but will be
called as many times as you call the terminate method (along with a bunch
of activityStarted events)

Here is the proposed fix:
Index: src/edu/umd/cs/piccolo/activities/PActivity.java
===================================================================
--- src/edu/umd/cs/piccolo/activities/PActivity.java    (revision 30)
+++ src/edu/umd/cs/piccolo/activities/PActivity.java    (revision 31)
@@ -57,6 +58,7 @@
    private PActivityDelegate delegate;

    private boolean stepping;
+    private boolean done;
    private long nextStepTime;

    /**
@@ -66,7 +68,9 @@
     */
    public interface PActivityDelegate {
        public void activityStarted(PActivity activity);
+
        public void activityStepped(PActivity activity);
+
        public void activityFinished(PActivity activity);
    }

@@ -103,6 +107,7 @@
        startTime = aStartTime;
        nextStepTime = aStartTime;
        stepping = false;
+        done = false;
    }

    //****************************************************************
@@ -183,6 +188,13 @@
    }

    /**
+     * Return true if this activity is done.
+     */
+    public boolean isDone() {
+        return done;
+    }
+
+    /**
     * Return true if this activity is performing an animation. This is used
     * by the PCanvas to determine if it should set the render quality to
     * PCanvas.animatingRenderQuality or not for each frame it renders.
@@ -197,8 +209,7 @@
     * activity finishes.
     */
    protected void activityStarted() {
-       if (delegate != null)
-           delegate.activityStarted(this);
+        if (delegate != null) delegate.activityStarted(this);
    }

    /**
@@ -208,8 +219,7 @@
     * @param elapsedTime the amount of time that has passed relative to the
activities startTime.
     */ 
    protected void activityStep(long elapsedTime) {
-       if (delegate != null)
-           delegate.activityStepped(this);
+        if (delegate != null) delegate.activityStepped(this);
    }

    /**
@@ -217,8 +227,8 @@
     * activity has been removed from the PActivityScheduler queue.
     */
    protected void activityFinished() {
-       if (delegate != null)
-           delegate.activityFinished(this);
+        if (delegate != null) delegate.activityFinished(this);
+        done = true;
    }

    /**
@@ -262,11 +272,11 @@
    }

    /**
-    * Stop this activity immediately, and remove it from the activity
+     * If not done, stops this activity immediately, and remove it from
the activity
     * scheduler. The termination behavior determines when and if activityStarted
     * and activityFinished get called. The possible termination behaviors are as
     * follow:
-    * 
+     * <p/>
     * TERMINATE_WITHOUT_FINISHING - The method activityFinished will never
get called and
     * so the activity will be terminated midway.
     * TERMINATE_AND_FINISH - The method activityFinished will always get
called. And so the
@@ -276,6 +286,9 @@
     * if the activity has previously started.
     */
    public void terminate(int terminationBehavior) {
+        if (done) {
+            return;
+        }
        if (scheduler != null) {
            scheduler.removeActivity(this);
        }
@@ -283,6 +296,7 @@
        switch (terminationBehavior) {
            case TERMINATE_WITHOUT_FINISHING:
                stepping = false;
+                done = true;
                break;

            case TERMINATE_AND_FINISH:
@@ -293,7 +307,6 @@
                    activityStarted();
                    activityFinished();
                }
-
                break;

            case TERMINATE_AND_FINISH_IF_STEPPING:

Original issue reported on code.google.com by steveonjava on 29 Jun 2008 at 11:16

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.