/* * Copyright (c) 2008-2010, Piccolo2D project, http://piccolo2d.org * Copyright (c) 1998-2008, University of Maryland * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of conditions * and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions * and the following disclaimer in the documentation and/or other materials provided with the * distribution. * * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its * contributors may be used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package edu.umd.cs.piccolox.pswing; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.IOException; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.RepaintManager; import junit.framework.TestCase; import edu.umd.cs.piccolo.util.PPaintContext; public class PSwingTest extends TestCase { public void setUp() { RepaintManager.setCurrentManager(new PSwingRepaintManager()); } public void testConstructorFailsOnNullComponent() { try { new PSwing(null); } catch (final NullPointerException e) { // expected } } public void testPSwingRegistersItselfWithComponent() { final JPanel panel = new JPanel(); final PSwing pSwing = new PSwing(panel); assertEquals(pSwing, panel.getClientProperty(PSwing.PSWING_PROPERTY)); } public void testGetComponentReturnsValidComponent() { final JPanel panel = new JPanel(); final PSwing pSwing = new PSwing(panel); assertEquals(panel, pSwing.getComponent()); } public void testPSwingResizesItselfWhenComponentIsResized() { final boolean[] reshaped = new boolean[1]; final JPanel panel = new JPanel(); new PSwing(panel) { public void updateBounds() { super.updateBounds(); reshaped[0] = true; } }; panel.setSize(100, 100); assertTrue(reshaped[0]); } public void testPSwingDelegatesPaintingToItsComponent() throws IOException { final JPanel panel = new JPanel(); final MockPaintingPSwing pSwing = new MockPaintingPSwing(panel); panel.setBackground(Color.RED); panel.setPreferredSize(new Dimension(100, 100)); final BufferedImage img = pSwing.paintComponent(); assertEquals(Color.RED.getRGB(), img.getRGB(50, 50)); } public void testHidingComponentHidesPSwing() { final JPanel panel = new JPanel(); final PSwing pSwing = new PSwing(panel); panel.setPreferredSize(new Dimension(100, 100)); pSwing.setBounds(0, 0, 00, 100); panel.setVisible(false); // Wow, do I hate this chunk of code. Turns out that the event dispatch // thread needs time to push the component hidden method before this // test passes // There has to be a way of forcing this without a sleep assertDelayedSuccess("setting component to invisible did not reflect in associated PSwing", 500, new Predicate() { public boolean isTrue() { return !pSwing.getVisible(); } }); } public void testAddingSwingComponentToWrappedHierarchyMakesItNotDoubleBuffer() { final JPanel panel = new JPanel(); final PSwing pSwing = new PSwing(panel); final JComponent child = new JLabel("Test Component"); child.setDoubleBuffered(true); panel.add(child); assertFalse(child.isDoubleBuffered()); } public void assertDelayedSuccess(String message, int delay, Predicate p) { int remainingTries = delay / 50; while (remainingTries > 0) { if (p.isTrue()) { return; } remainingTries--; try { Thread.sleep(50); } catch (InterruptedException e) { // do nothing } } fail(message); } public void assertDelayedSuccess(int delay, Predicate p) { assertDelayedSuccess("Failed asserting delayed success", delay, p); } private interface Predicate { boolean isTrue(); } public void testHidingPNodeHidesComponent() { final JPanel panel = new JPanel(); final PSwing pSwing = new PSwing(panel); pSwing.setVisible(false); assertFalse(panel.isVisible()); } public void testPaintTooSmallPaintsGreek() { final JPanel panel = new JPanel(); panel.setBounds(0, 0, 100, 100); final MockPaintingPSwing pSwing = new MockPaintingPSwing(panel); BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); graphics.setTransform(AffineTransform.getScaleInstance(0.01, 0.01)); PPaintContext paintContext = new PPaintContext(graphics); pSwing.paint(paintContext); assertTrue(pSwing.isPaintedGreek()); assertFalse(pSwing.isPaintedComponent()); } public void testPaintBigPaintsComponent() { final JPanel panel = new JPanel(); panel.setBounds(0, 0, 100, 100); final MockPaintingPSwing pSwing = new MockPaintingPSwing(panel); BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); graphics.setTransform(AffineTransform.getScaleInstance(5, 5)); PPaintContext paintContext = new PPaintContext(graphics); pSwing.paint(paintContext); assertFalse(pSwing.isPaintedGreek()); assertTrue(pSwing.isPaintedComponent()); } public void testGreekThresholdIsHonoured() { final JPanel panel = new JPanel(); panel.setBounds(0, 0, 100, 100); final MockPaintingPSwing pSwing = new MockPaintingPSwing(panel); pSwing.setGreekThreshold(2); BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); PPaintContext paintContext = new PPaintContext(graphics); pSwing.paint(paintContext); assertTrue(pSwing.isPaintedGreek()); assertFalse(pSwing.isPaintedComponent()); } public void testGreekThresholdIsPersisted() { final JPanel panel = new JPanel(); final MockPaintingPSwing pSwing = new MockPaintingPSwing(panel); pSwing.setGreekThreshold(2); assertEquals(2, pSwing.getGreekThreshold(), Double.MIN_VALUE); pSwing.setGreekThreshold(0.5); assertEquals(0.5, pSwing.getGreekThreshold(), Double.MIN_VALUE); } public void testAssertSettingJLabelWidthTooSmallGrowsIt() { final JLabel label = new JLabel("Hello"); PSwingCanvas canvas = new PSwingCanvas(); canvas.setBounds(0, 0, 100, 100); final MockPaintingPSwing swing = new MockPaintingPSwing(label); assertDelayedSuccess(500, new Predicate() { public boolean isTrue() { return label.getMinimumSize().getWidth() != 0; } }); swing.setWidth(10); canvas.getLayer().addChild(swing); canvas.doLayout(); // While paint, it uses the graphics element to determine the font's // display size and hence determine minimum size of JLabel. swing.paint(); assertFalse(10 == swing.getWidth()); } public void testAssertSettingJButtonWidthTooSmallGrowsIt() { JButton label = new JButton("Hello"); PSwingCanvas canvas = new PSwingCanvas(); canvas.setBounds(0, 0, 100, 100); MockPaintingPSwing swing = new MockPaintingPSwing(label); assertFalse(label.getMinimumSize().getWidth() == 0); swing.setWidth(10); canvas.getLayer().addChild(swing); canvas.doLayout(); // While paint, it uses the graphics element to determine the font's // display size and hence determine minimum size of JLabel. swing.paint(); assertFalse(10 == swing.getWidth()); } public void testPSwingAttachesItselfToItsCanvasWhenAddedToItsSceneGraph() { PSwingCanvas canvas1 = new PSwingCanvas(); PSwing label = new PSwing(new JLabel("Hello")); assertEquals(0, canvas1.getSwingWrapper().getComponentCount()); canvas1.getLayer().addChild(label); assertEquals(1, canvas1.getSwingWrapper().getComponentCount()); } public void testPSwingRemovesItselfFromItsCanvasWhenRemovedFromScene() { PSwingCanvas canvas1 = new PSwingCanvas(); PSwing label = new PSwing(new JLabel("Hello")); canvas1.getLayer().addChild(label); assertEquals(1, canvas1.getSwingWrapper().getComponentCount()); label.removeFromParent(); assertEquals(0, canvas1.getSwingWrapper().getComponentCount()); } public void testPSwingReattachesItselfWhenMovedFromCanvasToCanvas() { PSwingCanvas canvas1 = new PSwingCanvas(); PSwingCanvas canvas2 = new PSwingCanvas(); PSwing label = new PSwing(new JLabel("Hello")); canvas1.getLayer().addChild(label); canvas2.getLayer().addChild(label); assertEquals(0, canvas1.getSwingWrapper().getComponentCount()); assertEquals(1, canvas2.getSwingWrapper().getComponentCount()); } public class MockPaintingPSwing extends PSwing { private boolean paintedGreek; private boolean paintedComponent; public MockPaintingPSwing(JComponent component) { super(component); } public void paintOnto(BufferedImage image) { PPaintContext paintContext = new PPaintContext(image.createGraphics()); paint(paintContext); } public BufferedImage paint() { BufferedImage image = new BufferedImage((int) getWidth(), (int) getHeight(), BufferedImage.TYPE_INT_RGB); paintOnto(image); return image; } public BufferedImage paintComponent() { BufferedImage image = new BufferedImage((int) getWidth(), (int) getHeight(), BufferedImage.TYPE_INT_RGB); paintComponentOnto(image); return image; } public void paintComponentOnto(BufferedImage image) { paint(image.createGraphics()); } public void paint(Graphics2D paintContext) { super.paint(paintContext); paintedComponent = true; } public void paintAsGreek(Graphics2D paintContext) { super.paintAsGreek(paintContext); paintedGreek = true; } public boolean isPaintedGreek() { return paintedGreek; } public boolean isPaintedComponent() { return paintedComponent; } } }