diff --git a/core/src/main/java/edu/umd/cs/piccolo/nodes/PPath.java b/core/src/main/java/edu/umd/cs/piccolo/nodes/PPath.java index 695662d..09ab9c5 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/nodes/PPath.java +++ b/core/src/main/java/edu/umd/cs/piccolo/nodes/PPath.java @@ -102,7 +102,7 @@ private static final BasicStroke DEFAULT_STROKE = new BasicStroke(1.0f); private static final Color DEFAULT_STROKE_PAINT = Color.black; - private transient GeneralPath path; + protected transient GeneralPath path; private transient GeneralPath resizePath; private transient Stroke stroke; private transient boolean updatingBoundsFromPath; @@ -152,6 +152,7 @@ return result; } + public PPath() { strokePaint = DEFAULT_STROKE_PAINT; stroke = DEFAULT_STROKE; @@ -225,10 +226,9 @@ * need to take this into consideration. */ protected void internalUpdateBounds(double x, double y, double width, double height) { - if (updatingBoundsFromPath) + if (updatingBoundsFromPath || path == null) { return; - if (path == null) - return; + } if (resizePath != null) { path.reset(); 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 bf568b2..acbea32 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 @@ -96,70 +96,74 @@ return c; } - public static void writeStroke(Stroke aStroke, ObjectOutputStream out) throws IOException { - if (aStroke instanceof Serializable) { + public static void writeStroke(Stroke stroke, ObjectOutputStream out) throws IOException { + if (stroke instanceof Serializable) { out.writeBoolean(true); out.writeBoolean(true); - out.writeObject(aStroke); + out.writeObject(stroke); } - else if (aStroke instanceof BasicStroke) { + else if (stroke instanceof BasicStroke) { out.writeBoolean(true); out.writeBoolean(false); - BasicStroke s = (BasicStroke) aStroke; - - float[] dash = s.getDashArray(); - - if (dash == null) { - out.write(0); - } - else { - out.write(dash.length); - for (int i = 0; i < dash.length; i++) { - out.writeFloat(dash[i]); - } - } - - out.writeFloat(s.getLineWidth()); - out.writeInt(s.getEndCap()); - out.writeInt(s.getLineJoin()); - out.writeFloat(s.getMiterLimit()); - out.writeFloat(s.getDashPhase()); + writeBasicStroke((BasicStroke) stroke, out); } else { out.writeBoolean(false); } } - public static Stroke readStroke(ObjectInputStream in) throws IOException, ClassNotFoundException { - boolean wroteStroke = in.readBoolean(); - if (wroteStroke) { - boolean serializedStroke = in.readBoolean(); - if (serializedStroke) { - return (Stroke) in.readObject(); - } - else { - float[] dash = null; - int dashLength = in.read(); + private static void writeBasicStroke(BasicStroke basicStroke, ObjectOutputStream out) throws IOException { + float[] dash = basicStroke.getDashArray(); - if (dashLength != 0) { - dash = new float[dashLength]; - for (int i = 0; i < dashLength; i++) { - dash[i] = in.readFloat(); - } - } - - float lineWidth = in.readFloat(); - int endCap = in.readInt(); - int lineJoin = in.readInt(); - float miterLimit = in.readFloat(); - float dashPhase = in.readFloat(); - - return new BasicStroke(lineWidth, endCap, lineJoin, miterLimit, dash, dashPhase); - } + if (dash == null) { + out.write(0); } else { + out.write(dash.length); + for (int i = 0; i < dash.length; i++) { + out.writeFloat(dash[i]); + } + } + + out.writeFloat(basicStroke.getLineWidth()); + out.writeInt(basicStroke.getEndCap()); + out.writeInt(basicStroke.getLineJoin()); + out.writeFloat(basicStroke.getMiterLimit()); + out.writeFloat(basicStroke.getDashPhase()); + } + + public static Stroke readStroke(ObjectInputStream in) throws IOException, ClassNotFoundException { + boolean wroteStroke = in.readBoolean(); + if (!wroteStroke) { return null; } + + boolean serializedStroke = in.readBoolean(); + if (serializedStroke) { + return (Stroke) in.readObject(); + } + + return readBasicStroke(in); + } + + private static Stroke readBasicStroke(ObjectInputStream in) throws IOException { + float[] dash = null; + int dashLength = in.read(); + + if (dashLength != 0) { + dash = new float[dashLength]; + for (int i = 0; i < dashLength; i++) { + dash[i] = in.readFloat(); + } + } + + float lineWidth = in.readFloat(); + int endCap = in.readInt(); + int lineJoin = in.readInt(); + float miterLimit = in.readFloat(); + float dashPhase = in.readFloat(); + + return new BasicStroke(lineWidth, endCap, lineJoin, miterLimit, dash, dashPhase); } private static final int PATH_IS_DONE = -1; 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 b3a49a7..127c3a7 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 @@ -28,8 +28,6 @@ */ package edu.umd.cs.piccolo.nodes; -import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -37,20 +35,19 @@ import javax.imageio.ImageIO; import junit.framework.TestCase; -import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PPaintContext; public class PImageTest extends TestCase { - public PImageTest(String name) { - super(name); - } + public void testClone() { + final PImage srcNode = new PImage(new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB)); + final PImage clonedNode = (PImage) srcNode.clone(); + assertNotNull(clonedNode.getImage()); - public void testCopy() { - PImage aNode = new PImage(new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB)); - aNode = (PImage) aNode.clone(); - assertNotNull(aNode.getImage()); - assertEquals(aNode.getBounds(), new PBounds(0, 0, 100, 100)); + assertEquals(srcNode.getImage().getWidth(null), clonedNode.getImage().getWidth(null)); + assertEquals(srcNode.getImage().getHeight(null), clonedNode.getImage().getHeight(null)); + + assertEquals(srcNode.getBounds(), clonedNode.getBounds()); } public void testToString() { @@ -81,7 +78,7 @@ imgFile.deleteOnExit(); ImageIO.write(img, "JPEG", imgFile); - PImage imageNode = new PImage(imgFile.toURL()); + PImage imageNode = new PImage(imgFile.toURI().toURL()); 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 e9953cc..8be30a8 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 @@ -28,6 +28,9 @@ */ package edu.umd.cs.piccolo.nodes; +import java.awt.Color; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -36,48 +39,139 @@ import java.io.ObjectInputStream; import junit.framework.TestCase; -import edu.umd.cs.piccolo.nodes.PPath; +import edu.umd.cs.piccolo.MockPropertyChangeListener; +import edu.umd.cs.piccolo.PiccoloAsserts; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PObjectOutputStream; public class PPathTest extends TestCase { - public PPathTest(String name) { - super(name); + private MockPropertyChangeListener mockListener; + + public void setUp() { + mockListener = new MockPropertyChangeListener(); + } + + public void testStrokeIsNotNullByDefault() { + PPath path = new PPath(); + assertNotNull(path.getStroke()); + } + + public void testStrokePaintIsBlackByDefault() { + PPath path = new PPath(); + assertEquals(Color.BLACK, path.getStrokePaint()); + } + + public void testClone() { + PPath p = PPath.createEllipse(0, 0, 100, 100); + PBounds b = p.getBounds(); + p = (PPath) p.clone(); + assertEquals(p.getBounds(), b); + } + + public void testSerialization() throws IOException, ClassNotFoundException { + final PPath srcPath = PPath.createEllipse(0, 0, 100, 100); + final PBounds srcBounds = srcPath.getBounds(); + + File file = File.createTempFile("test", "ser"); + + serializeToFile(srcPath, file); + + PPath resultPath = deserializeFromFile(srcBounds, file); + + assertEquals(resultPath.getBounds(), srcBounds); + } + + private PPath deserializeFromFile(PBounds b, File file) + throws FileNotFoundException, IOException, ClassNotFoundException { + PPath path; + FileInputStream fin = new FileInputStream(file); + ObjectInputStream in = new ObjectInputStream(fin); + path = (PPath) in.readObject(); + file.delete(); + + return path; + } + + private void serializeToFile(PPath p, File file) + throws FileNotFoundException, IOException { + FileOutputStream fout = new FileOutputStream(file); + PObjectOutputStream out = new PObjectOutputStream(fout); + out.writeObjectTree(p); + out.flush(); + out.close(); + } + + public void testCreateRectangleReturnsValidPPath() { + PPath path = PPath.createRectangle(0, 0, 100, 50); + assertNotNull(path); + + // Seems like rounding is affecting the bounds greatly + PiccoloAsserts.assertEquals(new PBounds(0,0,100,50), path.getBounds(), 1); } - public void testCopy() { - PPath p = PPath.createEllipse(0, 0, 100, 100); - PBounds b = p.getBounds(); - p = (PPath) p.clone(); - assertEquals(p.getBounds(), b); + public void testCreateEllipseReturnsValidPPath() { + PPath path = PPath.createEllipse(0, 0, 100, 50); + assertNotNull(path); + + // Seems like rounding is affecting the bounds greatly + PiccoloAsserts.assertEquals(new PBounds(0,0,100,50), path.getBounds(), 1); + } + + public void testCreateRoundedRectReturnsValidPPath() { + PPath path = PPath.createRoundRectangle(0, 0, 100, 50, 10, 10); + assertNotNull(path); + + // Seems like rounding is affecting the bounds greatly + PiccoloAsserts.assertEquals(new PBounds(0,0,100,50), path.getBounds(), 1); + } + + public void testCreateLineReturnsValidPPath() { + PPath path = PPath.createLine(0,0, 100,0); + assertNotNull(path); + + // Seems like rounding is affecting the bounds greatly + PiccoloAsserts.assertEquals(new PBounds(0,0,100,0), path.getBounds(), 1); + } + + public void testCreatePolyLinePoint2DReturnsValidPPath() { + PPath path = PPath.createPolyline(new Point2D[] { + new Point2D.Double(0, 0), + new Point2D.Double(100, 50), + new Point2D.Double(100, 0) + }); + assertNotNull(path); + + // Seems like rounding is affecting the bounds greatly + PiccoloAsserts.assertEquals(new PBounds(0,0,100,50), path.getBounds(), 2); + } + + public void testCreatePolyLineFloatsReturnsValidPPath() { + PPath path = PPath.createPolyline(new float[] { 0, 100, 100}, new float[] { 0, 50, 0 }); + assertNotNull(path); + + // Seems like rounding is affecting the bounds greatly + PiccoloAsserts.assertEquals(new PBounds(0,0,100,50), path.getBounds(), 2); + } + + public void testSetStrokePaintPersists() { + PPath path = new PPath(); + path.setStrokePaint(Color.RED); + assertEquals(Color.RED, path.getStrokePaint()); + } + + public void testSetStrokeFiresPropertyChangeEvent() { + PPath path = new PPath(); + path.addPropertyChangeListener(PPath.PROPERTY_STROKE_PAINT, mockListener); + path.setStrokePaint(Color.RED); + assertEquals(1, mockListener.getPropertyChangeCount()); + } + + public void testChangingPathFiresPropertyChangeEvent() { + PPath path = new PPath(); + path.addPropertyChangeListener(PPath.PROPERTY_PATH, mockListener); + path.append(new Rectangle2D.Double(0, 0, 100, 50), true); + assertEquals(1, mockListener.getPropertyChangeCount()); } - public void testSaveToFile() { - PPath p = PPath.createEllipse(0, 0, 100, 100); - PBounds b = p.getBounds(); - try { - File file = new File("myfile"); - FileOutputStream fout = new FileOutputStream(file); - PObjectOutputStream out = new PObjectOutputStream(fout); - out.writeObjectTree(p); - out.flush(); - out.close(); - - FileInputStream fin = new FileInputStream(file); - ObjectInputStream in = new ObjectInputStream(fin); - p = (PPath) in.readObject(); - assertEquals(p.getBounds(), b); - file.delete(); - } - catch (FileNotFoundException e) { - assertTrue(false); - } - catch (ClassNotFoundException e) { - assertTrue(false); - } - catch (IOException e) { - assertTrue(false); - } - } } diff --git a/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java b/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java index 81fc8a4..ee79ff1 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java +++ b/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java @@ -30,13 +30,11 @@ import java.awt.Color; import java.awt.Font; -import java.beans.PropertyChangeListener; import javax.swing.JLabel; -import edu.umd.cs.piccolo.MockPropertyChangeListener; - import junit.framework.TestCase; +import edu.umd.cs.piccolo.MockPropertyChangeListener; public class PTextTest extends TestCase { @@ -73,7 +71,6 @@ textNode.setText(null); assertEquals("", textNode.getText()); } - public void testBoundsGrowWithTextByDefault() { PText text123 = new PText("123"); diff --git a/core/src/test/java/edu/umd/cs/piccolo/util/PObjectOutputStreamTest.java b/core/src/test/java/edu/umd/cs/piccolo/util/PObjectOutputStreamTest.java new file mode 100644 index 0000000..601ab7e --- /dev/null +++ b/core/src/test/java/edu/umd/cs/piccolo/util/PObjectOutputStreamTest.java @@ -0,0 +1,36 @@ +package edu.umd.cs.piccolo.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import junit.framework.TestCase; + +public class PObjectOutputStreamTest extends TestCase { + private PObjectOutputStream outStream; + private ByteArrayOutputStream outByteStream; + + public void setUp() throws IOException { + outByteStream = new ByteArrayOutputStream(); + outStream = new PObjectOutputStream(outByteStream); + } + + public void testToByteArrayThrowsExceptionOnNull() throws IOException { + try { + PObjectOutputStream.toByteArray(null); + } catch (NullPointerException e) { + // expected + } + } + + public void testToByteArrayOnEmptyStreamWorks() throws IOException { + outStream.flush(); + byte[] outputBytes = outByteStream.toByteArray(); + assertNotNull(outputBytes); + assertTrue("Header not output", outputBytes.length > 0); + } + + public void testWriteConditionalObjectAcceptsNull() throws IOException { + outStream.writeConditionalObject("A"); + + } +} 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 09a9619..ece1cfc 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 @@ -387,8 +387,8 @@ manager.lockRepaint(component); RenderingHints oldHints = g2.getRenderingHints(); - - g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + + g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); component.paint(g2); g2.setRenderingHints(oldHints);