diff --git a/core/src/main/java/edu/umd/cs/piccolo/PCamera.java b/core/src/main/java/edu/umd/cs/piccolo/PCamera.java
index 8971f3a..4f8feb9 100644
--- a/core/src/main/java/edu/umd/cs/piccolo/PCamera.java
+++ b/core/src/main/java/edu/umd/cs/piccolo/PCamera.java
@@ -174,7 +174,11 @@
* modify the viewBounds parameter.
*/
public void repaintFromLayer(final PBounds viewBounds, final PNode repaintedLayer) {
- this.repaintFromLayer(viewBounds, (PLayer) repaintedLayer);
+ if (repaintedLayer instanceof PLayer) {
+ this.repaintFromLayer(viewBounds, (PLayer) repaintedLayer);
+ } else {
+ throw new RuntimeException("Passed non PLayer node to repaintFromLayer");
+ }
}
// ****************************************************************
diff --git a/core/src/main/java/edu/umd/cs/piccolo/activities/PTransformActivity.java b/core/src/main/java/edu/umd/cs/piccolo/activities/PTransformActivity.java
index ce287d4..14cae38 100644
--- a/core/src/main/java/edu/umd/cs/piccolo/activities/PTransformActivity.java
+++ b/core/src/main/java/edu/umd/cs/piccolo/activities/PTransformActivity.java
@@ -31,6 +31,7 @@
import java.awt.geom.AffineTransform;
import edu.umd.cs.piccolo.util.PAffineTransform;
+import edu.umd.cs.piccolo.util.PUtil;
/**
* PTransformActivity interpolates between two transforms setting its
@@ -111,7 +112,7 @@
* target when the transform activity stops stepping.
*/
public double[] getDestinationTransform() {
- return destination;
+ return (destination == null) ? null : (double[]) destination.clone();
}
/**
@@ -119,7 +120,7 @@
* target when the transform activity stops stepping.
*/
public void setDestinationTransform(final double[] newDestination) {
- destination = newDestination;
+ destination = (newDestination == null) ? null : (double[]) newDestination.clone();
}
protected void activityStarted() {
diff --git a/core/src/main/java/edu/umd/cs/piccolo/nodes/PImage.java b/core/src/main/java/edu/umd/cs/piccolo/nodes/PImage.java
index 8b53104..7426f54 100644
--- a/core/src/main/java/edu/umd/cs/piccolo/nodes/PImage.java
+++ b/core/src/main/java/edu/umd/cs/piccolo/nodes/PImage.java
@@ -128,31 +128,13 @@
* load the image using a MediaTracker before returning.
*/
public void setImage(final Image newImage) {
- final Image old = image;
+ final Image oldImage = image;
if (newImage == null || newImage instanceof BufferedImage) {
image = newImage;
}
- else { // else make sure the image is loaded
- final ImageIcon imageLoader = new ImageIcon(newImage);
- switch (imageLoader.getImageLoadStatus()) {
- case MediaTracker.LOADING:
- System.err.println("media tracker still loading image after requested to wait until finished");
-
- case MediaTracker.COMPLETE:
- image = imageLoader.getImage();
- break;
-
- case MediaTracker.ABORTED:
- System.err.println("media tracker aborted image load");
- image = null;
- break;
-
- case MediaTracker.ERRORED:
- System.err.println("media tracker errored image load");
- image = null;
- break;
- }
+ else {
+ image = getLoadedImage(newImage);
}
if (image != null) {
@@ -160,7 +142,25 @@
invalidatePaint();
}
- firePropertyChange(PROPERTY_CODE_IMAGE, PROPERTY_IMAGE, old, image);
+ firePropertyChange(PROPERTY_CODE_IMAGE, PROPERTY_IMAGE, oldImage, image);
+ }
+
+ /**
+ * Ensures the image is loaded enough (loading is fine)
+ *
+ * @param newImage to check
+ * @return image or null if not loaded enough.
+ */
+ private Image getLoadedImage(final Image newImage) {
+ final ImageIcon imageLoader = new ImageIcon(newImage);
+ switch (imageLoader.getImageLoadStatus()) {
+ case MediaTracker.LOADING:
+ return imageLoader.getImage();
+ case MediaTracker.COMPLETE:
+ return imageLoader.getImage();
+ default:
+ return null;
+ }
}
protected void paint(final PPaintContext paintContext) {
diff --git a/core/src/main/java/edu/umd/cs/piccolo/util/PUtil.java b/core/src/main/java/edu/umd/cs/piccolo/util/PUtil.java
index 26ca50f..1a22847 100644
--- a/core/src/main/java/edu/umd/cs/piccolo/util/PUtil.java
+++ b/core/src/main/java/edu/umd/cs/piccolo/util/PUtil.java
@@ -56,7 +56,7 @@
public static long DEFAULT_ACTIVITY_STEP_RATE = 20;
public static int ACTIVITY_SCHEDULER_FRAME_DELAY = 10;
- private static final int PATH_IS_DONE = -1;
+ private static final int PATH_TERMINATOR = -1;
public static Iterator NULL_ITERATOR = Collections.EMPTY_LIST.iterator();
public static Enumeration NULL_ENUMERATION = new Enumeration() {
@@ -197,7 +197,7 @@
path.closePath();
break;
- case PATH_IS_DONE:
+ case PATH_TERMINATOR:
return path;
default:
@@ -253,6 +253,6 @@
i.next();
}
- out.writeInt(PATH_IS_DONE);
- }
+ out.writeInt(PATH_TERMINATOR);
+ }
}
diff --git a/core/src/test/java/edu/umd/cs/piccolo/MockPCamera.java b/core/src/test/java/edu/umd/cs/piccolo/MockPCamera.java
new file mode 100644
index 0000000..3daf135
--- /dev/null
+++ b/core/src/test/java/edu/umd/cs/piccolo/MockPCamera.java
@@ -0,0 +1,49 @@
+/**
+ *
+ */
+package edu.umd.cs.piccolo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.umd.cs.piccolo.util.PBounds;
+
+class MockPCamera extends PCamera {
+ private static final long serialVersionUID = 1L;
+ private List notifications = new ArrayList();
+
+ public void repaintFromLayer(final PBounds bounds, final PLayer layer) {
+ notifications.add(new Notification("repaintFromLayer", bounds, layer));
+ super.repaintFromLayer(bounds, layer);
+ }
+
+ static class Notification {
+ private final String type;
+ private final PBounds bounds;
+ // this should really be PLayer
+ private final PNode layer;
+
+ private Notification(final String type, final PBounds bounds, final PNode layer) {
+ this.bounds = bounds;
+ this.layer = layer;
+ this.type = type;
+ }
+
+ public PNode getLayer() {
+ return layer;
+ }
+
+ public PBounds getBounds() {
+ return bounds;
+ }
+ }
+
+ public int getNotificationCount() {
+ return notifications.size();
+ }
+
+ public Notification getNotification(int i) {
+ return (Notification)notifications.get(i);
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java b/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java
index 16776a8..9ce2828 100644
--- a/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java
+++ b/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java
@@ -2,20 +2,16 @@
import java.awt.Cursor;
-import javax.swing.JPanel;
-
import junit.framework.TestCase;
import edu.umd.cs.piccolo.event.PInputEventListener;
import edu.umd.cs.piccolo.util.PBounds;
import edu.umd.cs.piccolo.util.PPaintContext;
public class PCanvasTest extends TestCase {
- private PCanvas canvas;
- private int pCanvasFinalizerCount;
+ private PCanvas canvas;
private MockPInputEventListener mockListener;
- public void setUp() {
- pCanvasFinalizerCount = 0;
+ public void setUp() {
canvas = new PCanvas();
mockListener = new MockPInputEventListener();
}
@@ -105,7 +101,7 @@
canvas.addInputEventListener(mockListener);
final PInputEventListener[] listeners = canvas.getInputEventListeners();
assertNotNull(listeners);
- assertEquals(3, listeners.length); // 3 since pan and zoom are attached
+ assertEquals(3, listeners.length); // zoom + pan + mockListener
// by default
}
@@ -114,34 +110,6 @@
canvas.removeInputEventListener(mockListener);
final PInputEventListener[] listeners = canvas.getInputEventListeners();
assertNotNull(listeners);
- assertEquals(2, listeners.length); // 3 since pan and zoom are attached
- // by default
+ assertEquals(2, listeners.length); // zoom + pan + mockListener
}
-
- public void testMemoryLeak() throws InterruptedException {
- final JPanel panel = new JPanel();
- for (int i = 0; i < 10; i++) {
- PCanvas canvas = new PCanvas() {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public void finalize() {
- pCanvasFinalizerCount++;
- }
- };
- panel.add(canvas);
- panel.remove(canvas);
- canvas = null;
- }
- System.gc();
- System.runFinalization();
- PCanvas.CURRENT_ZCANVAS = null;
-
- // Not sure why I need -1 here, but I do. If I create 10000 it'll always
- // be 1 less
- // assertEquals(10-1, pCanvasFinalizerCount);
- }
-
}
diff --git a/core/src/test/java/edu/umd/cs/piccolo/PLayerTest.java b/core/src/test/java/edu/umd/cs/piccolo/PLayerTest.java
index ea446f7..a3b623f 100644
--- a/core/src/test/java/edu/umd/cs/piccolo/PLayerTest.java
+++ b/core/src/test/java/edu/umd/cs/piccolo/PLayerTest.java
@@ -1,8 +1,6 @@
package edu.umd.cs.piccolo;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import junit.framework.TestCase;
import edu.umd.cs.piccolo.util.PBounds;
@@ -96,37 +94,10 @@
final PBounds bounds = new PBounds(0, 0, 100, 100);
layer.repaintFrom(bounds, layer);
- assertEquals(1, camera.notifications.size());
+ assertEquals(1, camera.getNotificationCount());
- final MockPCamera.Notification notification = (MockPCamera.Notification) camera.notifications.get(0);
- assertEquals(layer, notification.layer);
- assertEquals(bounds, notification.bounds);
- }
-
- static class MockPCamera extends PCamera {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- List notifications = new ArrayList();
-
- public void repaintFromLayer(final PBounds bounds, final PLayer layer) {
- notifications.add(new Notification("repaintFromLayer", bounds, layer));
- super.repaintFromLayer(bounds, layer);
- }
-
- class Notification {
- String type;
- PBounds bounds;
- // this should really be PLayer
- PNode layer;
-
- Notification(final String type, final PBounds bounds, final PNode layer) {
- this.bounds = bounds;
- this.layer = layer;
- this.type = type;
- }
- }
-
+ final MockPCamera.Notification notification = (MockPCamera.Notification) camera.getNotification(0);
+ assertEquals(layer, notification.getLayer());
+ assertEquals(bounds, notification.getBounds());
}
}
diff --git a/core/src/test/java/edu/umd/cs/piccolo/nodes/PImageTest.java b/core/src/test/java/edu/umd/cs/piccolo/nodes/PImageTest.java
index d598490..fb1811d 100644
--- a/core/src/test/java/edu/umd/cs/piccolo/nodes/PImageTest.java
+++ b/core/src/test/java/edu/umd/cs/piccolo/nodes/PImageTest.java
@@ -63,11 +63,11 @@
public void testCanBeCreatedFromFile() throws IOException {
final BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
- final File imgFile = File.createTempFile("test", ".jpeg");
- imgFile.deleteOnExit();
+ final File imgFile = File.createTempFile("test", ".jpeg");
ImageIO.write(img, "JPEG", imgFile);
-
+ imgFile.deleteOnExit();
final PImage imageNode = new PImage(imgFile.getAbsolutePath());
+ assertNotNull(imageNode.getImage());
assertEquals(100, imageNode.getImage().getWidth(null));
assertEquals(100, imageNode.getImage().getHeight(null));
}
diff --git a/core/src/test/java/edu/umd/cs/piccolo/nodes/PPathTest.java b/core/src/test/java/edu/umd/cs/piccolo/nodes/PPathTest.java
index 4baf035..f5cb1b5 100644
--- a/core/src/test/java/edu/umd/cs/piccolo/nodes/PPathTest.java
+++ b/core/src/test/java/edu/umd/cs/piccolo/nodes/PPathTest.java
@@ -76,9 +76,9 @@
final File file = File.createTempFile("test", "ser");
serializeToFile(srcPath, file);
-
- final PPath resultPath = deserializeFromFile(srcBounds, file);
-
+ final PPath resultPath = deserializeFromFile(srcBounds, file);
+ file.deleteOnExit();
+
assertEquals(resultPath.getBounds(), srcBounds);
}
@@ -87,8 +87,7 @@
PPath path;
final FileInputStream fin = new FileInputStream(file);
final ObjectInputStream in = new ObjectInputStream(fin);
- path = (PPath) in.readObject();
- file.delete();
+ path = (PPath) in.readObject();
return path;
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/activities/PPathActivity.java b/extras/src/main/java/edu/umd/cs/piccolox/activities/PPathActivity.java
index c402f33..0dd3cfc 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/activities/PPathActivity.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/activities/PPathActivity.java
@@ -29,6 +29,7 @@
package edu.umd.cs.piccolox.activities;
import edu.umd.cs.piccolo.activities.PInterpolatingActivity;
+import edu.umd.cs.piccolo.util.PUtil;
/**
* PPathActivity is the abstract base class for all path activity
@@ -67,12 +68,12 @@
return knots.length;
}
- public void setKnots(final float[] knots) {
- this.knots = knots;
+ public void setKnots(final float[] newKnots) {
+ this.knots = (newKnots == null) ? newKnots : (float[]) newKnots.clone();
}
public float[] getKnots() {
- return knots;
+ return (knots == null) ? knots : (float[]) knots.clone();
}
public void setKnot(final int index, final float knot) {
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java b/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java
index 748a0fb..d0b4b64 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java
@@ -62,8 +62,8 @@
public PPositionPathActivity(final long duration, final long stepRate, final int loopCount, final int mode,
final Target aTarget, final float[] knots, final Point2D[] positions) {
super(duration, stepRate, loopCount, mode, knots);
- target = aTarget;
- this.positions = positions;
+ target = aTarget;
+ this.positions = (Point2D[])positions.clone();
}
protected boolean isAnimation() {
@@ -71,7 +71,7 @@
}
public Point2D[] getPositions() {
- return positions;
+ return (Point2D[])positions.clone();
}
public Point2D getPosition(final int index) {
@@ -79,7 +79,7 @@
}
public void setPositions(final Point2D[] positions) {
- this.positions = positions;
+ this.positions = (Point2D[])positions.clone();
}
public void setPosition(final int index, final Point2D position) {
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java
index f3d412f..338cdb5 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java
@@ -326,7 +326,7 @@
final double scaleFactor = d.getWidth() / aCamera.getViewScale();
final Point2D scalePoint = focusNode.getGlobalFullBounds().getCenter2D();
- if (scaleFactor != 1) {
+ if (Math.abs(1f-scaleFactor) < 0.0001) {
aCamera.scaleViewAboutPoint(scaleFactor, scalePoint.getX(), scalePoint.getY());
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java
index fc4123c..9152099 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java
@@ -297,10 +297,10 @@
font = style.getFont(((DefaultStyledDocument) document).getCharacterElement(pos).getAttributes());
if (font == null) {
font = style.getFont(((DefaultStyledDocument) document).getParagraphElement(pos).getAttributes());
- }
- if (font == null) {
- font = style.getFont(rootElement.getAttributes());
- }
+ if (font == null) {
+ font = style.getFont(rootElement.getAttributes());
+ }
+ }
}
else {
font = style.getFont(rootElement.getAttributes());
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwing.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwing.java
index 13c1584..c084fdc 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwing.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwing.java
@@ -219,10 +219,10 @@
/**
* The cutoff at which the Swing component is rendered greek
*/
- private final double renderCutoff = 0.3;
+ private static final double GREEK_SCALE_CUT_OFF = 0.3d;
private JComponent component = null;
private double minFontSize = Double.MAX_VALUE;
- private Stroke defaultStroke = new BasicStroke();
+ private transient Stroke defaultStroke = new BasicStroke();
private Font defaultFont = new Font("Serif", Font.PLAIN, 12);
private PSwingCanvas canvas;
@@ -381,7 +381,7 @@
}
protected boolean shouldRenderGreek(final PPaintContext renderContext) {
- return renderContext.getScale() < renderCutoff
+ return renderContext.getScale() < GREEK_SCALE_CUT_OFF
// && pSwingCanvas.getInteracting()
|| minFontSize * renderContext.getScale() < 0.5;
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java
index 76064f1..ef93621 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java
@@ -44,9 +44,6 @@
* @author Lance E. Good
*/
public class PSwingCanvas extends PCanvas {
- /**
- *
- */
private static final long serialVersionUID = 1L;
public static final String SWING_WRAPPER_KEY = "Swing Wrapper";
private final ChildWrapper swingWrapper;
@@ -62,14 +59,9 @@
}
private void initRepaintManager() {
- final RepaintManager repaintManager = RepaintManager.currentManager(this);
- PSwingRepaintManager pSwingRepaintManager;
- if (repaintManager instanceof PSwingRepaintManager) {
- pSwingRepaintManager = (PSwingRepaintManager) repaintManager;
- }
- else {
- pSwingRepaintManager = new PSwingRepaintManager();
- RepaintManager.setCurrentManager(pSwingRepaintManager);
+ final RepaintManager repaintManager = RepaintManager.currentManager(this);
+ if (!(repaintManager instanceof PSwingRepaintManager)) {
+ RepaintManager.setCurrentManager(new PSwingRepaintManager());
}
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java
index ee936c8..9766a03 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java
@@ -66,6 +66,9 @@
/*
* Sync the (now obsolete) policy fields with the JScrollPane.
*/
+ if (!(parent instanceof JScrollPane)) {
+ throw new IllegalArgumentException("layoutContainer may only be applied to JScrollPanes");
+ }
final JScrollPane scrollPane = (JScrollPane) parent;
vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java
index f54fff7..f67e7cb 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java
@@ -225,6 +225,9 @@
* @param parent the container to lay out
*/
public void layoutContainer(final Container parent) {
+ if (!(parent instanceof JViewport)) {
+ throw new IllegalArgumentException("PViewport.layoutContainer may only be applied to JViewports");
+ }
final JViewport vp = (JViewport) parent;
final Component view = vp.getView();
diff --git a/extras/src/test/java/edu/umd/cs/piccolox/pswing/PSwingCanvasTest.java b/extras/src/test/java/edu/umd/cs/piccolox/pswing/PSwingCanvasTest.java
index 14e7b40..4c6bb01 100644
--- a/extras/src/test/java/edu/umd/cs/piccolox/pswing/PSwingCanvasTest.java
+++ b/extras/src/test/java/edu/umd/cs/piccolox/pswing/PSwingCanvasTest.java
@@ -28,7 +28,7 @@
*/
package edu.umd.cs.piccolox.pswing;
-import javax.swing.JPanel;
+import javax.swing.JLabel;
import junit.framework.TestCase;
@@ -40,33 +40,11 @@
public void setUp() {
finalizerCallCount = 0;
- }
-
- public void testMemoryLeak() throws InterruptedException {
- JPanel panel = new JPanel();
- for (int i = 0; i < 10; i++) {
- PSwingCanvas canvas = new PSwingCanvas() {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public void finalize() {
- finalizerCallCount++;
- }
- };
- panel.add(canvas);
- panel.remove(canvas);
- canvas = null;
- }
- panel = null;
- System.gc();
- System.runFinalization();
-
- // Not sure why I need -1 here, but I do. If I create 10000 it'll always
- // be 1 less
- // TODO: make this work in all environments. Will not work at the
- // command line for some.
- // assertEquals(10 - 1, finalizerCallCount);
+ }
+
+ public void testRemovePSwingDoesNothingWithForeignPSwing() {
+ PSwingCanvas canvas = new PSwingCanvas();
+ PSwing orphanPSwing = new PSwing(new JLabel());
+ canvas.removePSwing(orphanPSwing);
}
}