diff --git a/examples/edu/umd/cs/piccolo/examples/PSwingExample.java b/examples/edu/umd/cs/piccolo/examples/PSwingExample.java index 54cfd17..8dd7ba7 100644 --- a/examples/edu/umd/cs/piccolo/examples/PSwingExample.java +++ b/examples/edu/umd/cs/piccolo/examples/PSwingExample.java @@ -35,7 +35,7 @@ } } ); js.setBorder( BorderFactory.createTitledBorder( "Test JSlider" ) ); - PSwing pSwing = new PSwing( pswingCanvas, js ); + PSwing pSwing = new PSwing( js ); pSwing.translate( 100, 100 ); l.addChild( pSwing ); diff --git a/examples/edu/umd/cs/piccolo/examples/SliderExample.java b/examples/edu/umd/cs/piccolo/examples/SliderExample.java index f956ded..fbfa5ed 100644 --- a/examples/edu/umd/cs/piccolo/examples/SliderExample.java +++ b/examples/edu/umd/cs/piccolo/examples/SliderExample.java @@ -75,7 +75,7 @@ buttonPreset.setLocation( 240, 285 ); tabPanel.add( buttonPreset ); // Create a pswing object for the tab panel - swing = new PSwing( canvas, tabPanel ); + swing = new PSwing( tabPanel ); swing.translate( 0, 0 ); // Add the pswing object to the canvas canvas.getLayer().addChild( swing ); diff --git a/extras/edu/umd/cs/piccolox/pswing/PSwing.java b/extras/edu/umd/cs/piccolox/pswing/PSwing.java index 21fccb4..3bd2e74 100644 --- a/extras/edu/umd/cs/piccolox/pswing/PSwing.java +++ b/extras/edu/umd/cs/piccolox/pswing/PSwing.java @@ -1,415 +1,546 @@ -/** - * Copyright (C) 1998-2000 by University of Maryland, College Park, MD 20742, USA - * All rights reserved. - */ -package edu.umd.cs.piccolox.pswing; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; - -import javax.swing.JComponent; -import javax.swing.RepaintManager; - -import edu.umd.cs.piccolo.PNode; -import edu.umd.cs.piccolo.util.PBounds; -import edu.umd.cs.piccolo.util.PPaintContext; - -/* - This message was sent to Sun on August 27, 1999 - - ----------------------------------------------- - - We are currently developing Piccolo, a "scenegraph" for use in 2D graphics. - One of our ultimate goals is to support Swing lightweight components - within Piccolo, whose graphical space supports arbitray affine transforms. - The challenge in this pursuit is getting the components to respond and - render properly though not actually displayed in a standard Java component - hierarchy. - - - The first issues involved making the Swing components focusable and - showing. This was accomplished by adding the Swing components to a 0x0 - JComponent which was in turn added to our main Piccolo application component. - To our good fortune, a Java component is showing merely if it and its - ancestors are showing and not based on whether it is ACTUALLY visible. - Likewise, focus in a JComponent depends merely on the component's - containing window having focus. - - - The second issue involved capturing the repaint calls on a Swing - component. Normally, for a repaint and the consequent call to - paintImmediately, a Swing component obtains the Graphics object necessary - to render itself through the Java component heirarchy. However, for Piccolo - we would like the component to render using a Graphics object that Piccolo - may have arbitrarily transformed in some way. By capturing in the - RepaintManager the repaint calls made on our special Swing components, we - are able to redirect the repaint requests through the Piccolo architecture to - put the Graphics in its proper context. Unfortunately, this means that - if the Swing component contains other Swing components, then any repaint - requests made by one of these nested components must go through - the Piccolo architecture then through the top level Swing component - down to the nested Swing component. This normally doesn't cause a - problem. However, if calling paint on one of these nested - children causes a call to repaint then an infinite loop ensues. This does - in fact happen in the Swing components that use cell renderers. Before - the cell renderer is painted, it is invalidated and consequently - repainted. We solved this problem by putting a lock on repaint calls for - a component while that component is painting. (A similar problem faced - the Swing team over this same issue. They solved it by inserting a - CellRendererPane to capture the renderer's invalidate calls.) - - - Another issue arose over the forwarding of mouse events to the Swing - components. Since our Swing components are not actually displayed on - screen in the standard manner, we must manually dispatch any MouseEvents - we want the component to receive. Hence, we needed to find the deepest - visible component at a particular location that accepts MouseEvents. - Finding the deepest visible component at a point was achieved with the - "findComponentAt" method in java.awt.Container. With the - "getListeners(Class listenerType)" method added in JDK1.3 Beta we are able - to determine if the component has any Mouse Listeners. However, we haven't - yet found a way to determine if MouseEvents have been specifically enabled - for a component. The package private method "eventEnabled" in - java.awt.Component does exactly what we want but is, of course, - inaccessible. In order to dispatch events correctly we would need a - public accessor to the method "boolean eventEnabled(AWTEvent)" in - java.awt.Component. - - - Still another issue involves the management of cursors when the mouse is - over a Swing component in our application. To the Java mechanisms, the - mouse never appears to enter the bounds of the Swing components since they - are contained by a 0x0 JComponent. Hence, we must manually change the - cursor when the mouse enters one of the Swing components in our - application. This generally works but becomes a problem if the Swing - component's cursor changes while we are over that Swing component (for - instance, if you resize a Table Column). In order to manage cursors - properly, we would need setCursor to fire property change events. - - - With the above fixes, most Swing components work. The only Swing - components that are definitely broken are ToolTips and those that rely on - JPopupMenu. In order to implement ToolTips properly, we would need to have - a method in ToolTipManager that allows us to set the current manager, as - is possible with RepaintManager. In order to implement JPopupMenu, we - will likely need to reimplement JPopupMenu to function in Piccolo with - a transformed Graphics and to insert itself in the proper place in the - Piccolo scenegraph. - -*/ - - -/** - * PSwing is used to add Swing Components to a Piccolo canvas. - *

- * Example: adding a swing JButton to a PCanvas: - *

- *     PSwingCanvas canvas = new PSwingCanvas();
- *     JButton button = new JButton("Button");
- *     swing = new PSwing(canvas, button);
- *     canvas.getLayer().addChild(swing);
- * 
- * 

- * NOTE: PSwing has the current limitation that it does not listen for - * Container events. This is only an issue if you create a PSwing - * and later add Swing components to the PSwing's component hierarchy - * that do not have double buffering turned off or have a smaller font - * size than the minimum font size of the original PSwing's component - * hierarchy. - *

- * For instance, the following bit of code will give unexpected - * results: - *

- *            JPanel panel = new JPanel();
- *            PSwing swing = new PSwing(panel);
- *            JPanel newChild = new JPanel();
- *            newChild.setDoubleBuffered(true);
- *            panel.add(newChild);
- *       
- *

- * NOTE: PSwing cannot be correctly interacted with through multiple cameras. - * There is no support for it yet. - *

- * NOTE: PSwing is java.io.Serializable. - *

- * Warning: 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 Sam R. Reid - * @author Benjamin B. Bederson - * @author Lance E. Good - */ -public class PSwing extends PNode implements Serializable, PropertyChangeListener { - - - /** - * Used as a hashtable key for this object in the Swing component's - * client properties. - */ - public static final String PSWING_PROPERTY = "PSwing"; - private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform(); - private static PBounds TEMP_REPAINT_BOUNDS2 = new PBounds(); - private static boolean highQualityRender = false; - - /** - * The cutoff at which the Swing component is rendered greek - */ - private double renderCutoff = 0.3; - private JComponent component = null; - private double minFontSize = Double.MAX_VALUE; - private Stroke defaultStroke = new BasicStroke(); - private Font defaultFont = new Font( "Serif", Font.PLAIN, 12 ); - private BufferedImage buffer; - private PSwingCanvas pSwingCanvas; - - /** - * Constructs a new visual component wrapper for the Swing component - * and adds the Swing component to the SwingWrapper component of - * the PCanvas - * - * @param canvas The PSwingCanvas to which the Swing component will - * be added - * @param component The swing component to be wrapped - */ - public PSwing( PSwingCanvas canvas, JComponent component ) { - this.pSwingCanvas = canvas; - this.component = component; - component.putClientProperty( PSWING_PROPERTY, this ); - init( component ); - this.pSwingCanvas.getSwingWrapper().add( component ); - component.revalidate(); - reshape(); - } - - /** - * 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 ); - setBounds( 0, 0, component.getPreferredSize().width, component.getPreferredSize().height ); - } - - /** - * Determines if the Swing component should be rendered normally or - * as a filled rectangle. - *

- * The transform, clip, and composite will be set appropriately when this object - * is rendered. It is up to this object to restore the transform, clip, and composite of - * the Graphics2D if this node changes any of them. However, the color, font, and stroke are - * unspecified by Piccolo. This object should set those things if they are used, but - * they do not need to be restored. - * - * @param renderContext Contains information about current render. - */ - public void paint( PPaintContext renderContext ) { - Graphics2D g2 = renderContext.getGraphics(); - - if( defaultStroke == null ) { - defaultStroke = new BasicStroke(); - } - g2.setStroke( defaultStroke ); - - if( defaultFont == null ) { - defaultFont = new Font( "Serif", Font.PLAIN, 12 ); - } - - g2.setFont( defaultFont ); - - if( component.getParent() == null ) { - pSwingCanvas.getSwingWrapper().add( component ); - component.revalidate(); - } - - if( shouldRenderGreek( renderContext ) ) { - paintAsGreek( g2 ); - } - else { - paint( g2 ); - } - - } - - protected boolean shouldRenderGreek( PPaintContext renderContext ) { - return ( renderContext.getScale() < renderCutoff && pSwingCanvas.getInteracting() ) || - minFontSize * renderContext.getScale() < 0.5; - } - - /** - * Paints the Swing component as greek. - * - * @param g2 The graphics used to render the filled rectangle - */ - public void paintAsGreek( Graphics2D g2 ) { - Color background = component.getBackground(); - Color foreground = component.getForeground(); - Rectangle2D rect = getBounds(); - - if( background != null ) { - g2.setColor( background ); - } - g2.fill( rect ); - - if( foreground != null ) { - g2.setColor( foreground ); - } - g2.draw( rect ); - } - - /** - * Renders to a buffered image, then draws that to the screen. - * - * @param g2 The graphics on which to render the JComponent. - */ - public void paint( Graphics2D g2 ) { - if( component.getBounds().isEmpty() ) { - // The component has not been initialized yet. - return; - } - - PSwingRepaintManager manager = (PSwingRepaintManager)RepaintManager.currentManager( component ); - manager.lockRepaint( component ); - - if( buffer == null || buffer.getWidth() != component.getWidth() || buffer.getHeight() != component.getHeight() ) - { - buffer = new BufferedImage( component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB ); - } - else { - Graphics2D bufferedGraphics = buffer.createGraphics(); - bufferedGraphics.setBackground( Color.black ); - bufferedGraphics.clipRect( 0, 0, component.getWidth(), component.getHeight() ); - } - Graphics2D bufferedGraphics = buffer.createGraphics(); - - //optionally prepare buffered graphics for better rendering. - if( highQualityRender ) { - bufferedGraphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); - bufferedGraphics.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC ); - } - - component.paint( bufferedGraphics ); - Object origHint = g2.getRenderingHint( RenderingHints.KEY_INTERPOLATION ); - g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC ); - g2.drawRenderedImage( buffer, IDENTITY_TRANSFORM ); - if( origHint != null ) { - g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, origHint ); - } - else { - g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ); - } - - manager.unlockRepaint( component ); - } - - /** - * Repaints the specified portion of this visual component - * Note that the input parameter may be modified as a result of this call. - * - * @param repaintBounds - */ - public void repaint( PBounds repaintBounds ) { - Shape sh = getTransform().createTransformedShape( repaintBounds ); - TEMP_REPAINT_BOUNDS2.setRect( sh.getBounds2D() ); - repaintFrom( TEMP_REPAINT_BOUNDS2, this ); - } - - /** - * Sets the Swing component's bounds to its preferred bounds - * unless it already is set to its preferred size. Also - * updates the visual components copy of these bounds - */ - public void computeBounds() { - if( !component.getBounds().isEmpty() ) { - Dimension d = component.getPreferredSize(); - getBoundsReference().setRect( 0, 0, d.getWidth(), d.getHeight() ); - if( !component.getSize().equals( d ) ) { - component.setBounds( 0, 0, (int)d.getWidth(), (int)d.getHeight() ); - } - } - } - - /** - * Returns the Swing component that this visual component wraps - * - * @return The Swing component that this visual component wraps - */ - public JComponent getComponent() { - return component; - } - - /** - * We need to turn off double buffering of Swing components within - * Piccolo since all components contained within a native container - * use the same buffer for double buffering. With normal Swing - * widgets this is fine, but for Swing components within Piccolo this - * causes problems. This function recurses the component tree - * rooted at c, and turns off any double buffering in use. It also - * updates the minimum font size based on the font size of c and adds - * a property change listener to listen for changes to the font. - * - * @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( children != null ) { - for( int j = 0; j < children.length; j++ ) { - init( children[j] ); - } - } - - if( c instanceof JComponent ) { - ( (JComponent)c ).setDoubleBuffered( false ); - c.addPropertyChangeListener( "font", this ); - } - } - - /** - * Listens for changes in font on components rooted at this PSwing - */ - public void propertyChange( PropertyChangeEvent evt ) { - if( component.isAncestorOf( (Component)evt.getSource() ) && - ( (Component)evt.getSource() ).getFont() != null ) { - minFontSize = Math.min( minFontSize, ( (Component)evt.getSource() ).getFont().getSize() ); - } - } - - private void readObject( ObjectInputStream in ) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - init( component ); - } - - /** - * Set high quality buffer rendering. - * - * @param highQuality - */ - public static void setHighQualityRender( boolean highQuality ) { - highQualityRender = highQuality; - } -} +/** + * 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.PCamera; +import edu.umd.cs.piccolo.PLayer; +import edu.umd.cs.piccolo.PNode; +import edu.umd.cs.piccolo.util.PBounds; +import edu.umd.cs.piccolo.util.PPaintContext; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; + +/* + This message was sent to Sun on August 27, 1999 + + ----------------------------------------------- + + We are currently developing Piccolo, a "scenegraph" for use in 2D graphics. + One of our ultimate goals is to support Swing lightweight components + within Piccolo, whose graphical space supports arbitray affine transforms. + The challenge in this pursuit is getting the components to respond and + render properly though not actually displayed in a standard Java component + hierarchy. + + + The first issues involved making the Swing components focusable and + showing. This was accomplished by adding the Swing components to a 0x0 + JComponent which was in turn added to our main Piccolo application component. + To our good fortune, a Java component is showing merely if it and its + ancestors are showing and not based on whether it is ACTUALLY visible. + Likewise, focus in a JComponent depends merely on the component's + containing window having focus. + + + The second issue involved capturing the repaint calls on a Swing + component. Normally, for a repaint and the consequent call to + paintImmediately, a Swing component obtains the Graphics object necessary + to render itself through the Java component heirarchy. However, for Piccolo + we would like the component to render using a Graphics object that Piccolo + may have arbitrarily transformed in some way. By capturing in the + RepaintManager the repaint calls made on our special Swing components, we + are able to redirect the repaint requests through the Piccolo architecture to + put the Graphics in its proper context. Unfortunately, this means that + if the Swing component contains other Swing components, then any repaint + requests made by one of these nested components must go through + the Piccolo architecture then through the top level Swing component + down to the nested Swing component. This normally doesn't cause a + problem. However, if calling paint on one of these nested + children causes a call to repaint then an infinite loop ensues. This does + in fact happen in the Swing components that use cell renderers. Before + the cell renderer is painted, it is invalidated and consequently + repainted. We solved this problem by putting a lock on repaint calls for + a component while that component is painting. (A similar problem faced + the Swing team over this same issue. They solved it by inserting a + CellRendererPane to capture the renderer's invalidate calls.) + + + Another issue arose over the forwarding of mouse events to the Swing + components. Since our Swing components are not actually displayed on + screen in the standard manner, we must manually dispatch any MouseEvents + we want the component to receive. Hence, we needed to find the deepest + visible component at a particular location that accepts MouseEvents. + Finding the deepest visible component at a point was achieved with the + "findComponentAt" method in java.awt.Container. With the + "getListeners(Class listenerType)" method added in JDK1.3 Beta we are able + to determine if the component has any Mouse Listeners. However, we haven't + yet found a way to determine if MouseEvents have been specifically enabled + for a component. The package private method "eventEnabled" in + java.awt.Component does exactly what we want but is, of course, + inaccessible. In order to dispatch events correctly we would need a + public accessor to the method "boolean eventEnabled(AWTEvent)" in + java.awt.Component. + + + Still another issue involves the management of cursors when the mouse is + over a Swing component in our application. To the Java mechanisms, the + mouse never appears to enter the bounds of the Swing components since they + are contained by a 0x0 JComponent. Hence, we must manually change the + cursor when the mouse enters one of the Swing components in our + application. This generally works but becomes a problem if the Swing + component's cursor changes while we are over that Swing component (for + instance, if you resize a Table Column). In order to manage cursors + properly, we would need setCursor to fire property change events. + + + With the above fixes, most Swing components work. The only Swing + components that are definitely broken are ToolTips and those that rely on + JPopupMenu. In order to implement ToolTips properly, we would need to have + a method in ToolTipManager that allows us to set the current manager, as + is possible with RepaintManager. In order to implement JPopupMenu, we + will likely need to reimplement JPopupMenu to function in Piccolo with + a transformed Graphics and to insert itself in the proper place in the + Piccolo scenegraph. + +*/ + + +/** + * PSwing is used to add Swing Components to a Piccolo canvas. + *

+ * Example: adding a swing JButton to a PCanvas: + *

+ *     PSwingCanvas canvas = new PSwingCanvas();
+ *     JButton button = new JButton("Button");
+ *     swing = new PSwing(canvas, button);
+ *     canvas.getLayer().addChild(swing);
+ * 
+ * 

+ * NOTE: PSwing has the current limitation that it does not listen for + * Container events. This is only an issue if you create a PSwing + * and later add Swing components to the PSwing's component hierarchy + * that do not have double buffering turned off or have a smaller font + * size than the minimum font size of the original PSwing's component + * hierarchy. + *

+ * For instance, the following bit of code will give unexpected + * results: + *

+ *            JPanel panel = new JPanel();
+ *            PSwing swing = new PSwing(panel);
+ *            JPanel newChild = new JPanel();
+ *            newChild.setDoubleBuffered(true);
+ *            panel.add(newChild);
+ *       
+ *

+ * NOTE: PSwing cannot be correctly interacted with through multiple cameras. + * There is no support for it yet. + *

+ * NOTE: PSwing is java.io.Serializable. + *

+ * Warning: 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 Sam R. Reid + * @author Benjamin B. Bederson + * @author Lance E. Good + * + * 3-23-2007 edited to automatically detect PCamera/PSwingCanvas to allow single-arg constructor usage + */ +public class PSwing extends PNode implements Serializable, PropertyChangeListener { + + + /** + * Used as a hashtable key for this object in the Swing component's + * client properties. + */ + public static final String PSWING_PROPERTY = "PSwing"; + private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform(); + private static PBounds TEMP_REPAINT_BOUNDS2 = new PBounds(); + + /** + * The cutoff at which the Swing component is rendered greek + */ + private double renderCutoff = 0.3; + private JComponent component = null; + private double minFontSize = Double.MAX_VALUE; + private Stroke defaultStroke = new BasicStroke(); + private Font defaultFont = new Font( "Serif", Font.PLAIN, 12 ); + private BufferedImage buffer; + private static final Color BUFFER_BACKGROUND_COLOR = new Color( 0, 0, 0, 0 ); + private PSwingCanvas canvas; + + //////////////////////////////////////////////////////////// + ///////Following fields are for automatic canvas/camera detection + //////////////////////////////////////////////////////////// + /*/keep track of which nodes we've attached listeners to since no built in support in PNode*/ + private ArrayList listeningTo = new ArrayList(); + + /*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(); + if( parent != null ) { + listenForCanvas( parent ); + } + + } + }; + + /** + * Constructs a new visual component wrapper for the Swing component. + * + * @param component The swing component to be wrapped + */ + public PSwing(JComponent component) { + this.component = component; + component.putClientProperty( PSWING_PROPERTY, this ); + init( component ); + component.revalidate(); + component.addPropertyChangeListener( new PropertyChangeListener() { + public void propertyChange( PropertyChangeEvent evt ) { + reshape(); + } + } ); + reshape(); + listenForCanvas( this ); + } + + /** + * Deprecated constructor for application code still depending on this signature. + * @param pSwingCanvas + * @param component + * @deprecated + */ + public PSwing(PSwingCanvas pSwingCanvas, JComponent component) { + this(component); + } + + /** + * 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 ); + setBounds( 0, 0, component.getPreferredSize().width, component.getPreferredSize().height ); + } + + /** + * Determines if the Swing component should be rendered normally or + * as a filled rectangle. + *

+ * The transform, clip, and composite will be set appropriately when this object + * is rendered. It is up to this object to restore the transform, clip, and composite of + * the Graphics2D if this node changes any of them. However, the color, font, and stroke are + * unspecified by Piccolo. This object should set those things if they are used, but + * they do not need to be restored. + * + * @param renderContext Contains information about current render. + */ + public void paint( PPaintContext renderContext ) { + Graphics2D g2 = renderContext.getGraphics(); + + if( defaultStroke == null ) { + defaultStroke = new BasicStroke(); + } + g2.setStroke( defaultStroke ); + + if( defaultFont == null ) { + defaultFont = new Font( "Serif", Font.PLAIN, 12 ); + } + + g2.setFont( defaultFont ); + + if( component.getParent() == null ) { +// pSwingCanvas.getSwingWrapper().add( component ); + component.revalidate(); + } + + if( shouldRenderGreek( renderContext ) ) { + paintAsGreek( g2 ); + } + else { + paint( g2 ); + } + + } + + protected boolean shouldRenderGreek( PPaintContext renderContext ) { + return ( renderContext.getScale() < renderCutoff +// && pSwingCanvas.getInteracting() + ) || + minFontSize * renderContext.getScale() < 0.5; + } + + /** + * Paints the Swing component as greek. + * + * @param g2 The graphics used to render the filled rectangle + */ + public void paintAsGreek( Graphics2D g2 ) { + Color background = component.getBackground(); + Color foreground = component.getForeground(); + Rectangle2D rect = getBounds(); + + if( background != null ) { + g2.setColor( background ); + } + g2.fill( rect ); + + if( foreground != null ) { + g2.setColor( foreground ); + } + g2.draw( rect ); + } + + /** + * Remove from the SwingWrapper; throws an exception if no canvas is associated with this PSwing. + */ + public void removeFromSwingWrapper() { + if( canvas != null && Arrays.asList( this.canvas.getSwingWrapper().getComponents() ).contains( component ) ) { + this.canvas.getSwingWrapper().remove( component ); + } + } + + /** + * Renders to a buffered image, then draws that image to the + * drawing surface associated with g2 (usually the screen). + * + * @param g2 graphics context for rendering the JComponent + */ + public void paint( Graphics2D g2 ) { + if( component.getBounds().isEmpty() ) { + // The component has not been initialized yet. + return; + } + + PSwingRepaintManager manager = (PSwingRepaintManager)RepaintManager.currentManager( component ); + manager.lockRepaint( component ); + + Graphics2D bufferedGraphics = null; + if( !isBufferValid() ) { + // Get the graphics context associated with a new buffered image. + // Use TYPE_INT_ARGB_PRE so that transparent components look good on Windows. + buffer = new BufferedImage( component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE ); + bufferedGraphics = buffer.createGraphics(); + } + else { + // Use the graphics context associated with the existing buffered image + bufferedGraphics = buffer.createGraphics(); + // Clear the buffered image to prevent artifacts on Macintosh + bufferedGraphics.setBackground( BUFFER_BACKGROUND_COLOR ); + bufferedGraphics.clearRect( 0, 0, component.getWidth(), component.getHeight() ); + } + + // Start with the rendering hints from the provided graphics context + bufferedGraphics.setRenderingHints( g2.getRenderingHints() ); + + //PSwing sometimes causes JComponent text to render with "..." when fractional font metrics are enabled. These are now always disabled for the offscreen buffer. + bufferedGraphics.setRenderingHint( RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF ); + + // Draw the component to the buffer + component.paint( bufferedGraphics ); + + // Draw the buffer to g2's associated drawing surface + g2.drawRenderedImage( buffer, IDENTITY_TRANSFORM ); + + manager.unlockRepaint( component ); + } + + /** + * Tells whether the buffer for the image of the Swing components + * is currently valid. + * + * @return true if the buffer is currently valid + */ + private boolean isBufferValid() { + return !( buffer == null || buffer.getWidth() != component.getWidth() || buffer.getHeight() != component.getHeight() ); + } + + /** + * Repaints the specified portion of this visual component + * Note that the input parameter may be modified as a result of this call. + * + * @param repaintBounds + */ + public void repaint( PBounds repaintBounds ) { + Shape sh = getTransform().createTransformedShape( repaintBounds ); + TEMP_REPAINT_BOUNDS2.setRect( sh.getBounds2D() ); + repaintFrom( TEMP_REPAINT_BOUNDS2, this ); + } + + /** + * Sets the Swing component's bounds to its preferred bounds + * unless it already is set to its preferred size. Also + * updates the visual components copy of these bounds + */ + public void computeBounds() { + reshape(); +// if( !component.getBounds().isEmpty() ) { +// Dimension d = component.getPreferredSize(); +// getBoundsReference().setRect( 0, 0, d.getWidth(), d.getHeight() ); +// if( !component.getSize().equals( d ) ) { +// component.setBounds( 0, 0, (int)d.getWidth(), (int)d.getHeight() ); +// } +// } + } + + /** + * Returns the Swing component that this visual component wraps + * + * @return The Swing component that this visual component wraps + */ + public JComponent getComponent() { + return component; + } + + /** + * We need to turn off double buffering of Swing components within + * Piccolo since all components contained within a native container + * use the same buffer for double buffering. With normal Swing + * widgets this is fine, but for Swing components within Piccolo this + * causes problems. This function recurses the component tree + * rooted at c, and turns off any double buffering in use. It also + * updates the minimum font size based on the font size of c and adds + * a property change listener to listen for changes to the font. + * + * @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( children != null ) { + for( int j = 0; j < children.length; j++ ) { + init( children[j] ); + } + } + + if( c instanceof JComponent ) { + ( (JComponent)c ).setDoubleBuffered( false ); + c.addPropertyChangeListener( "font", this ); + c.addComponentListener( new ComponentAdapter() { + public void componentResized( ComponentEvent e ) { + computeBounds(); + } + + public void componentShown( ComponentEvent e ) { + computeBounds(); + } + } ); + } + } + + /** + * Listens for changes in font on components rooted at this PSwing + */ + public void propertyChange( PropertyChangeEvent evt ) { + if( component.isAncestorOf( (Component)evt.getSource() ) && + ( (Component)evt.getSource() ).getFont() != null ) { + minFontSize = Math.min( minFontSize, ( (Component)evt.getSource() ).getFont().getSize() ); + } + } + + private void readObject( ObjectInputStream in ) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + init( component ); + } + + //////////////////////////////////////////////////////////// + ///////Start methods for automatic canvas detection + //////////////////////////////////////////////////////////// + /** + * Attaches a listener to the specified node and all its parents to listen + * for a change in the PSwingCanvas. Only PROPERTY_PARENT listeners are added + * so this code wouldn't handle if a PLayer were viewed by a different PCamera + * since that constitutes a child change. + * @param node The child node at which to begin a parent-based traversal for adding listeners. + */ + private void listenForCanvas( PNode node ) { + //need to get the full tree for this node + PNode p = node; + while( p != null ) { + listenToNode( p ); + + PNode parent = p; +// System.out.println( "parent = " + parent.getClass() ); + 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++ ) { + PCamera cam = player.getCamera( i ); + if( cam.getComponent() instanceof PSwingCanvas ) { + updateCanvas( (PSwingCanvas)cam.getComponent() ); + break; + } + } + } + p = p.getParent(); + } + } + + /** + * Attach a listener to the specified node, if one has not already been attached. + * @param node the node to listen to for parent/pcamera/pcanvas changes + */ + private void listenToNode( PNode node ) { +// System.out.println( "listeningTo.size() = " + listeningTo.size() ); + if( !listeningTo( node ) ) { + listeningTo.add( node ); + node.addPropertyChangeListener( PNode.PROPERTY_PARENT, parentListener ); + } + } + + /** + * Determine whether this PSwing is already listening to the specified node for camera/canvas changes. + * @param node the node to check + * @return true if this PSwing is already listening to the specified node for camera/canvas changes + */ + private boolean listeningTo( PNode node ) { + for( int i = 0; i < listeningTo.size(); i++ ) { + PNode pNode = (PNode)listeningTo.get( i ); + if( pNode == node ) { + return true; + } + } + return false; + } + + /** + * 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) + */ + private void updateCanvas( PSwingCanvas newCanvas ) { + if( newCanvas != canvas ) { + if( canvas != null ) { + canvas.removePSwing( this ); + } + if( newCanvas != null ) { + canvas = newCanvas; + canvas.addPSwing( this ); + reshape(); + repaint(); + canvas.invalidate(); + canvas.revalidate(); + canvas.repaint(); + } + } + } + //////////////////////////////////////////////////////////// + ///////End methods for automatic canvas detection + //////////////////////////////////////////////////////////// +} diff --git a/extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java b/extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java index 8f6ecd6..d7263f8 100644 --- a/extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java +++ b/extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java @@ -1,65 +1,73 @@ -/* Copyright 2003-2005, University of Colorado */ - -/* - * CVS Info - - * Filename : $Source: /fs/cvs/piccolo/piccolo/extras/edu/umd/cs/piccolox/pswing/PSwingCanvas.java,v $ - * Branch : $Name: $ - * Modified by : $Author: jesse $ - * Revision : $Revision: 1.1 $ - * Date modified : $Date: 2006/01/05 16:54:26 $ - */ -package edu.umd.cs.piccolox.pswing; - -import edu.umd.cs.piccolo.PCanvas; - -import javax.swing.*; -import java.awt.*; - -/** - * The PSwingCanvas is a PCanvas that can display Swing components with the PSwing adapter. - * - * @author Benjamin B. Bederson - * @author Sam R. Reid - * @author Lance E. Good - */ - -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. - */ - public PSwingCanvas() { - swingWrapper = new SwingWrapper( this ); - add( swingWrapper ); - RepaintManager.setCurrentManager( pSwingRepaintManager ); - pSwingRepaintManager.addPSwingCanvas( this ); - - swingEventHandler = new PSwingEventHandler( this, getCamera() );//todo or maybe getCameraLayer() or getRoot()? - swingEventHandler.setActive( true ); - } - - JComponent getSwingWrapper() { - return swingWrapper; - } - - static class SwingWrapper extends JComponent { - private PSwingCanvas pSwingCanvas; - - public SwingWrapper( PSwingCanvas pSwingCanvas ) { - this.pSwingCanvas = pSwingCanvas; - setSize( new Dimension( 0, 0 ) ); - setPreferredSize( new Dimension( 0, 0 ) ); - putClientProperty( SWING_WRAPPER_KEY, SWING_WRAPPER_KEY ); - } - - public PSwingCanvas getpSwingCanvas() { - return pSwingCanvas; - } - } - +/* Copyright 2003-2005, University of Colorado */ + +/* + * CVS Info - + * Filename : $Source$ + * Branch : $Name$ + * Modified by : $Author: samreid $ + * Revision : $Revision: 13998 $ + * Date modified : $Date: 2007-03-22 17:51:34 -0600 (Thu, 22 Mar 2007) $ + */ +package edu.umd.cs.piccolox.pswing; + +import edu.umd.cs.piccolo.PCanvas; + +import javax.swing.*; +import java.awt.*; + +/** + * The PSwingCanvas is a PCanvas that can display Swing components with the PSwing adapter. + * + * @author Benjamin B. Bederson + * @author Sam R. Reid + * @author Lance E. Good + */ + +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. + */ + public PSwingCanvas() { + swingWrapper = new SwingWrapper( this ); + add( swingWrapper ); + RepaintManager.setCurrentManager( pSwingRepaintManager ); + pSwingRepaintManager.addPSwingCanvas( this ); + + swingEventHandler = new PSwingEventHandler( this, getCamera() );//todo or maybe getCameraLayer() or getRoot()? + swingEventHandler.setActive( true ); + } + + JComponent getSwingWrapper() { + return swingWrapper; + } + + public void addPSwing( PSwing pSwing ) { + swingWrapper.add( pSwing.getComponent() ); + } + + public void removePSwing( PSwing pSwing ) { + swingWrapper.remove( pSwing.getComponent() ); + } + + private static class SwingWrapper extends JComponent { + private PSwingCanvas pSwingCanvas; + + public SwingWrapper( PSwingCanvas pSwingCanvas ) { + this.pSwingCanvas = pSwingCanvas; + setSize( new Dimension( 0, 0 ) ); + setPreferredSize( new Dimension( 0, 0 ) ); + putClientProperty( SWING_WRAPPER_KEY, SWING_WRAPPER_KEY ); + } + + public PSwingCanvas getpSwingCanvas() { + return pSwingCanvas; + } + } + } \ No newline at end of file diff --git a/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwing.java b/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwing.java index becd62a..6bc08e1 100644 --- a/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwing.java +++ b/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwing.java @@ -1,134 +1,134 @@ -package edu.umd.cs.piccolox.pswing.tests; - -import edu.umd.cs.piccolo.PNode; -import edu.umd.cs.piccolo.event.PZoomEventHandler; -import edu.umd.cs.piccolo.nodes.PText; -import edu.umd.cs.piccolox.pswing.PComboBox; -import edu.umd.cs.piccolox.pswing.PSwing; -import edu.umd.cs.piccolox.pswing.PSwingCanvas; - -import javax.swing.*; -import javax.swing.border.LineBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * User: Sam Reid - * Date: Jul 11, 2005 - * Time: 12:15:55 PM - * Copyright (c) Jul 11, 2005 by Sam Reid - */ - -public class TestPSwing { - public static void main( String[] args ) { - PSwingCanvas pCanvas = new PSwingCanvas(); - final PText pText = new PText( "PText" ); - pCanvas.getLayer().addChild( pText ); - JFrame frame = new JFrame( "Test Piccolo" ); - - frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); - frame.setContentPane( pCanvas ); - frame.setSize( 600, 800 ); - frame.setVisible( true ); - - PText text2 = new PText( "Text2" ); - text2.setFont( new Font( "Lucida Sans", Font.BOLD, 18 ) ); - pCanvas.getLayer().addChild( text2 ); - text2.translate( 100, 100 ); - text2.addInputEventListener( new PZoomEventHandler() ); - - pCanvas.removeInputEventListener( pCanvas.getPanEventHandler() ); - - JButton jButton = new JButton( "MyButton!" ); - jButton.addActionListener( new ActionListener() { - public void actionPerformed( ActionEvent e ) { - System.out.println( "TestZSwing.actionPerformed!!!!!!!!!!!!!!*********************" ); - } - } ); - final PSwing pSwing = new PSwing( pCanvas, jButton ); - pCanvas.getLayer().addChild( pSwing ); - pSwing.repaint(); - - JSpinner jSpinner = new JSpinner(); - jSpinner.setPreferredSize( new Dimension( 100, jSpinner.getPreferredSize().height ) ); - PSwing pSpinner = new PSwing( pCanvas, jSpinner ); - pCanvas.getLayer().addChild( pSpinner ); - pSpinner.translate( 0, 150 ); - - JCheckBox jcb = new JCheckBox( "CheckBox", true ); - jcb.addActionListener( new ActionListener() { - public void actionPerformed( ActionEvent e ) { - System.out.println( "TestZSwing.JCheckBox.actionPerformed" ); - } - } ); - jcb.addChangeListener( new ChangeListener() { - public void stateChanged( ChangeEvent e ) { - System.out.println( "TestPSwing.JChekbox.stateChanged@" + System.currentTimeMillis() ); - } - } ); - PSwing pCheckBox = new PSwing( pCanvas, jcb ); - pCanvas.getLayer().addChild( pCheckBox ); - pCheckBox.translate( 100, 0 ); - - // Growable JTextArea - JTextArea textArea = new JTextArea( "This is a growable TextArea.\nTry it out!" ); - textArea.setBorder( new LineBorder( Color.blue, 3 ) ); - PSwing swing = new PSwing( pCanvas, textArea ); - swing.translate( 150, 150 ); - pCanvas.getLayer().addChild( swing ); - - // A Slider - JSlider slider = new JSlider(); - PSwing pSlider = new PSwing( pCanvas, slider ); - pSlider.translate( 200, 200 ); - pCanvas.getLayer().addChild( pSlider ); - - // A Scrollable JTree - JTree tree = new JTree(); - tree.setEditable( true ); - JScrollPane p = new JScrollPane( tree ); - p.setPreferredSize( new Dimension( 150, 150 ) ); - PSwing pTree = new PSwing( pCanvas, p ); - pCanvas.getLayer().addChild( pTree ); - pTree.translate( 0, 250 ); - - // A JColorChooser - also demonstrates JTabbedPane - JColorChooser chooser = new JColorChooser(); - PSwing pChooser = new PSwing( pCanvas, chooser ); - pCanvas.getLayer().addChild( pChooser ); - pChooser.translate( 100, 300 ); - - JPanel myPanel = new JPanel(); - myPanel.setBorder( BorderFactory.createTitledBorder( "Titled Border" ) ); - myPanel.add( new JCheckBox( "CheckBox" ) ); - PSwing panelSwing = new PSwing( pCanvas, myPanel ); - pCanvas.getLayer().addChild( panelSwing ); - panelSwing.translate( 400, 50 ); - - // A Slider - JSlider slider2 = new JSlider(); - PSwing pSlider2 = new PSwing( pCanvas, slider2 ); - pSlider2.translate( 200, 200 ); - PNode root = new PNode(); - root.addChild( pSlider2 ); - root.scale( 1.5 ); - root.rotate( Math.PI / 4 ); - root.translate( 300, 200 ); - pCanvas.getLayer().addChild( root ); - - String[] listItems = {"Summer Teeth", "Mermaid Avenue", "Being There", "A.M."}; - PComboBox box = new PComboBox( listItems ); - swing = new PSwing( pCanvas, box ); - swing.translate( 200, 250 ); - pCanvas.getLayer().addChild( swing ); - box.setEnvironment( swing, pCanvas );//has to be done manually at present - - // Revalidate and repaint - pCanvas.revalidate(); - pCanvas.repaint(); - } - -} +package edu.umd.cs.piccolox.pswing.tests; + +import edu.umd.cs.piccolo.PNode; +import edu.umd.cs.piccolo.event.PZoomEventHandler; +import edu.umd.cs.piccolo.nodes.PText; +import edu.umd.cs.piccolox.pswing.PComboBox; +import edu.umd.cs.piccolox.pswing.PSwing; +import edu.umd.cs.piccolox.pswing.PSwingCanvas; + +import javax.swing.*; +import javax.swing.border.LineBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * User: Sam Reid + * Date: Jul 11, 2005 + * Time: 12:15:55 PM + * Copyright (c) Jul 11, 2005 by Sam Reid + */ + +public class TestPSwing { + public static void main( String[] args ) { + PSwingCanvas pCanvas = new PSwingCanvas(); + final PText pText = new PText( "PText" ); + pCanvas.getLayer().addChild( pText ); + JFrame frame = new JFrame( "Test Piccolo" ); + + frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); + frame.setContentPane( pCanvas ); + frame.setSize( 600, 800 ); + frame.setVisible( true ); + + PText text2 = new PText( "Text2" ); + text2.setFont( new Font( "Lucida Sans", Font.BOLD, 18 ) ); + pCanvas.getLayer().addChild( text2 ); + text2.translate( 100, 100 ); + text2.addInputEventListener( new PZoomEventHandler() ); + + pCanvas.removeInputEventListener( pCanvas.getPanEventHandler() ); + + JButton jButton = new JButton( "MyButton!" ); + jButton.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e ) { + System.out.println( "TestZSwing.actionPerformed!!!!!!!!!!!!!!*********************" ); + } + } ); + final PSwing pSwing = new PSwing(jButton ); + pCanvas.getLayer().addChild( pSwing ); + pSwing.repaint(); + + JSpinner jSpinner = new JSpinner(); + jSpinner.setPreferredSize( new Dimension( 100, jSpinner.getPreferredSize().height ) ); + PSwing pSpinner = new PSwing(jSpinner ); + pCanvas.getLayer().addChild( pSpinner ); + pSpinner.translate( 0, 150 ); + + JCheckBox jcb = new JCheckBox( "CheckBox", true ); + jcb.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e ) { + System.out.println( "TestZSwing.JCheckBox.actionPerformed" ); + } + } ); + jcb.addChangeListener( new ChangeListener() { + public void stateChanged( ChangeEvent e ) { + System.out.println( "TestPSwing.JChekbox.stateChanged@" + System.currentTimeMillis() ); + } + } ); + PSwing pCheckBox = new PSwing(jcb ); + pCanvas.getLayer().addChild( pCheckBox ); + pCheckBox.translate( 100, 0 ); + + // Growable JTextArea + JTextArea textArea = new JTextArea( "This is a growable TextArea.\nTry it out!" ); + textArea.setBorder( new LineBorder( Color.blue, 3 ) ); + PSwing swing = new PSwing(textArea ); + swing.translate( 150, 150 ); + pCanvas.getLayer().addChild( swing ); + + // A Slider + JSlider slider = new JSlider(); + PSwing pSlider = new PSwing(slider ); + pSlider.translate( 200, 200 ); + pCanvas.getLayer().addChild( pSlider ); + + // A Scrollable JTree + JTree tree = new JTree(); + tree.setEditable( true ); + JScrollPane p = new JScrollPane( tree ); + p.setPreferredSize( new Dimension( 150, 150 ) ); + PSwing pTree = new PSwing(p ); + pCanvas.getLayer().addChild( pTree ); + pTree.translate( 0, 250 ); + + // A JColorChooser - also demonstrates JTabbedPane + JColorChooser chooser = new JColorChooser(); + PSwing pChooser = new PSwing(chooser ); + pCanvas.getLayer().addChild( pChooser ); + pChooser.translate( 100, 300 ); + + JPanel myPanel = new JPanel(); + myPanel.setBorder( BorderFactory.createTitledBorder( "Titled Border" ) ); + myPanel.add( new JCheckBox( "CheckBox" ) ); + PSwing panelSwing = new PSwing(myPanel ); + pCanvas.getLayer().addChild( panelSwing ); + panelSwing.translate( 400, 50 ); + + // A Slider + JSlider slider2 = new JSlider(); + PSwing pSlider2 = new PSwing(slider2 ); + pSlider2.translate( 200, 200 ); + PNode root = new PNode(); + root.addChild( pSlider2 ); + root.scale( 1.5 ); + root.rotate( Math.PI / 4 ); + root.translate( 300, 200 ); + pCanvas.getLayer().addChild( root ); + + String[] listItems = {"Summer Teeth", "Mermaid Avenue", "Being There", "A.M."}; + PComboBox box = new PComboBox( listItems ); + swing = new PSwing(box ); + swing.translate( 200, 250 ); + pCanvas.getLayer().addChild( swing ); + box.setEnvironment( swing, pCanvas );//has to be done manually at present + + // Revalidate and repaint + pCanvas.revalidate(); + pCanvas.repaint(); + } + +} diff --git a/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwingFull.java b/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwingFull.java index b13408c..81768e8 100644 --- a/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwingFull.java +++ b/extras/edu/umd/cs/piccolox/pswing/tests/TestPSwingFull.java @@ -1,416 +1,416 @@ -package edu.umd.cs.piccolox.pswing.tests; - -import edu.umd.cs.piccolo.PNode; -import edu.umd.cs.piccolox.pswing.PSwing; -import edu.umd.cs.piccolox.pswing.PSwingCanvas; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.border.EtchedBorder; -import javax.swing.border.LineBorder; -import javax.swing.border.TitledBorder; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; -import javax.swing.table.TableColumn; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.io.IOException; -import java.util.Vector; - -/** - * User: Sam Reid - * Date: Jul 11, 2005 - * Time: 12:15:55 PM - * Copyright (c) Jul 11, 2005 by Sam Reid - */ - -public class TestPSwingFull extends JFrame { - public TestPSwingFull() { - setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); - ClassLoader loader; - PSwingCanvas canvas; - - // Set up basic frame - setBounds( 50, 50, 750, 750 ); - setResizable( true ); - setBackground( null ); - setVisible( true ); - canvas = new PSwingCanvas(); - canvas.setPanEventHandler( null ); - getContentPane().add( canvas ); - validate(); - loader = getClass().getClassLoader(); - - ZVisualLeaf leaf; - PNode transform; - PSwing swing; - PSwing swing2; - - // JButton - JButton button = new JButton( "Button" ); - button.setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ) ); - swing = new PSwing( canvas, button ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -500, -500 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // JButton - JSpinner spinner = new JSpinner( new SpinnerNumberModel( 0, 0, 10, 1 ) ); - spinner.setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ) ); - swing = new PSwing( canvas, spinner ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -800, -500 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // 2nd Copy of JButton - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -450, -450 ); - transform.rotate( Math.PI / 2 ); - transform.scale( 0.5 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // Growable JTextArea - JTextArea textArea = new JTextArea( "This is a growable TextArea.\nTry it out!" ); - textArea.setBorder( new LineBorder( Color.blue, 3 ) ); - swing = new PSwing( canvas, textArea ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -250, -500 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // Growable JTextField - JTextField textField = new JTextField( "A growable text field" ); - swing = new PSwing( canvas, textField ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 0, -500 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // A Slider - JSlider slider = new JSlider(); - swing = new PSwing( canvas, slider ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 250, -500 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // A Scrollable JTree - JTree tree = new JTree(); - tree.setEditable( true ); - JScrollPane p = new JScrollPane( tree ); - p.setPreferredSize( new Dimension( 150, 150 ) ); - swing = new PSwing( canvas, p ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -500, -250 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // A Scrollable JTextArea - JScrollPane pane = new JScrollPane( new JTextArea( "A Scrollable Text Area\nTry it out!" ) ); - pane.setPreferredSize( new Dimension( 150, 150 ) ); - swing = new PSwing( canvas, pane ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -250, -250 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - swing2 = swing; - - // A non-scrollable JTextField - // A panel MUST be created with double buffering off - JPanel panel = new JPanel( false ); - textField = new JTextField( "A fixed-size text field" ); - panel.setLayout( new BorderLayout() ); - panel.add( textField ); - swing = new PSwing( canvas, panel ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 0, -250 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - -// // A JComboBox -// String[] listItems = {"Summer Teeth", "Mermaid Avenue", "Being There", "A.M."}; -// ZComboBox box = new ZComboBox( listItems ); -// swing = new PSwing( canvas, box ); -// leaf = new ZVisualLeaf( swing ); -// transform = new PNode(); -// transform.translate( 0, -150 ); -// transform.addChild( leaf ); -// canvas.getLayer().addChild( transform ); - - // A panel with TitledBorder and JList - panel = new JPanel( false ); - panel.setBackground( Color.lightGray ); - panel.setLayout( new BorderLayout() ); - panel.setBorder( new TitledBorder( new EtchedBorder( EtchedBorder.RAISED ), "A JList", TitledBorder.LEFT, TitledBorder.TOP ) ); - panel.setPreferredSize( new Dimension( 200, 200 ) ); - Vector data = new Vector(); - data.addElement( "Choice 1" ); - data.addElement( "Choice 2" ); - data.addElement( "Choice 3" ); - data.addElement( "Choice 4" ); - data.addElement( "Choice 5" ); - JList list = new JList( data ); - list.setBackground( Color.lightGray ); - panel.add( list ); - swing = new PSwing( canvas, panel ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 250, -250 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // A JLabel - JLabel label = new JLabel( "A JLabel", SwingConstants.CENTER ); - - swing = new PSwing( canvas, label ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -500, 0 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // Rotated copy of the Scrollable JTextArea - leaf = new ZVisualLeaf( swing2 ); - transform = new PNode(); - transform.translate( -100, 0 ); - transform.rotate( Math.PI / 2 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // A panel with layout - // A panel MUST be created with double buffering off - panel = new JPanel( false ); - panel.setLayout( new BorderLayout() ); - JButton button1 = new JButton( "Button 1" ); - JButton button2 = new JButton( "Button 2" ); - label = new JLabel( "A Panel with Layout" ); - label.setHorizontalAlignment( SwingConstants.CENTER ); - label.setForeground( Color.white ); - panel.setBackground( Color.red ); - panel.setPreferredSize( new Dimension( 150, 150 ) ); - panel.setBorder( new EmptyBorder( 5, 5, 5, 5 ) ); - panel.add( button1, "North" ); - panel.add( button2, "South" ); - panel.add( label, "Center" ); - panel.revalidate(); - swing = new PSwing( canvas, panel ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 0, 0 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // JTable Example - Vector columns = new Vector(); - columns.addElement( "Check Number" ); - columns.addElement( "Description" ); - columns.addElement( "Amount" ); - Vector rows = new Vector(); - Vector row = new Vector(); - row.addElement( "101" ); - row.addElement( "Sandwich" ); - row.addElement( "$20.00" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "102" ); - row.addElement( "Monkey Wrench" ); - row.addElement( "$100.00" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "214" ); - row.addElement( "Ant farm" ); - row.addElement( "$55.00" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "215" ); - row.addElement( "Self-esteem tapes" ); - row.addElement( "$37.99" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "216" ); - row.addElement( "Tube Socks" ); - row.addElement( "$7.45" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "220" ); - row.addElement( "Ab Excerciser" ); - row.addElement( "$56.95" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "319" ); - row.addElement( "Y2K Supplies" ); - row.addElement( "$4624.33" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "332" ); - row.addElement( "Tie Rack" ); - row.addElement( "$15.20" ); - rows.addElement( row ); - row = new Vector(); - row.addElement( "344" ); - row.addElement( "Swing Set" ); - row.addElement( "$146.59" ); - rows.addElement( row ); - JTable table = new JTable( rows, columns ); - table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF ); - table.setRowHeight( 30 ); - TableColumn c = table.getColumn( table.getColumnName( 0 ) ); - c.setPreferredWidth( 150 ); - c = table.getColumn( table.getColumnName( 1 ) ); - c.setPreferredWidth( 150 ); - c = table.getColumn( table.getColumnName( 2 ) ); - c.setPreferredWidth( 150 ); - pane = new JScrollPane( table ); - pane.setPreferredSize( new Dimension( 200, 200 ) ); - table.setDoubleBuffered( false ); - swing = new PSwing( canvas, pane ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 250, 0 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // JEditorPane - HTML example - try { - - - final JEditorPane editorPane = new JEditorPane( loader.getResource( "csdept.html" ) ); - editorPane.setDoubleBuffered( false ); - editorPane.setEditable( false ); - pane = new JScrollPane( editorPane ); - pane.setDoubleBuffered( false ); - pane.setPreferredSize( new Dimension( 400, 400 ) ); - editorPane.addHyperlinkListener( new HyperlinkListener() { - public void hyperlinkUpdate( HyperlinkEvent e ) { - if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) { - try { - editorPane.setPage( e.getURL() ); - } - catch( IOException ioe ) { - System.out.println( "Couldn't Load Web Page" ); - } - } - } - } ); - swing = new PSwing( canvas, pane ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -500, 250 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - } - catch( IOException ioe ) { - System.out.println( "Couldn't Load Web Page" ); - } - - // A JInternalFrame with a JSplitPane - a JOptionPane - and a - // JToolBar - JInternalFrame iframe = new JInternalFrame( "JInternalFrame" ); - iframe.getRootPane().setDoubleBuffered( false ); - ( (JComponent)iframe.getContentPane() ).setDoubleBuffered( false ); - iframe.setPreferredSize( new Dimension( 500, 500 ) ); - JTabbedPane tabby = new JTabbedPane(); - tabby.setDoubleBuffered( false ); - iframe.getContentPane().setLayout( new BorderLayout() ); - JOptionPane options = new JOptionPane( "This is a JOptionPane!", - JOptionPane.INFORMATION_MESSAGE, - JOptionPane.DEFAULT_OPTION ); - options.setDoubleBuffered( false ); - options.setMinimumSize( new Dimension( 50, 50 ) ); - options.setPreferredSize( new Dimension( 225, 225 ) ); - JPanel tools = new JPanel( false ); - tools.setMinimumSize( new Dimension( 150, 150 ) ); - tools.setPreferredSize( new Dimension( 225, 225 ) ); - JToolBar bar = new JToolBar(); - Action letter = new AbstractAction( "Big A!" ) { - - public void actionPerformed( ActionEvent e ) { - } - }; - - Action hand = new AbstractAction( "Hi!" ) { - public void actionPerformed( ActionEvent e ) { - } - }; - Action select = new AbstractAction( "There!" ) { - public void actionPerformed( ActionEvent e ) { - } - }; - - label = new JLabel( "A Panel with a JToolBar" ); - label.setHorizontalAlignment( SwingConstants.CENTER ); - bar.add( letter ); - bar.add( hand ); - bar.add( select ); - bar.setFloatable( false ); - bar.setBorder( new LineBorder( Color.black, 2 ) ); - tools.setLayout( new BorderLayout() ); - tools.add( bar, "North" ); - tools.add( label, "Center" ); - - JSplitPane split = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, options, tools ); - split.setDoubleBuffered( false ); - iframe.getContentPane().add( split ); - swing = new PSwing( canvas, iframe ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( 0, 250 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - -// JMenuBar menuBar = new JMenuBar(); -// ZMenu menu = new ZMenu( "File" ); -// ZMenu sub = new ZMenu( "Export" ); -// JMenuItem gif = new JMenuItem( "Funds" ); -// sub.add( gif ); -// menu.add( sub ); -// menuBar.add( menu ); -// iframe.setJMenuBar( menuBar ); - - iframe.setVisible( true ); - - // A JColorChooser - also demonstrates JTabbedPane -// JColorChooser chooser = new JColorChooser(); - JCheckBox chooser = new JCheckBox( "Check Box" ); - swing = new PSwing( canvas, chooser ); - leaf = new ZVisualLeaf( swing ); - transform = new PNode(); - transform.translate( -250, 850 ); - transform.addChild( leaf ); - canvas.getLayer().addChild( transform ); - - // Revalidate and repaint - canvas.revalidate(); - canvas.repaint(); - - PSwing message = new PSwing( canvas, new JTextArea( "Click-drag to zoom in and out." ) ); - message.translate( 0, -50 ); - canvas.getLayer().addChild( message ); - - canvas.getCamera().animateViewToCenterBounds( message.getFullBounds(), false, 1200 ); - } - - public static void main( String[] args ) { - new TestPSwingFull().setVisible( true ); - } - - public static class ZVisualLeaf extends PNode { - public ZVisualLeaf( PNode node ) { - addChild( node ); - } - } - -} +package edu.umd.cs.piccolox.pswing.tests; + +import edu.umd.cs.piccolo.PNode; +import edu.umd.cs.piccolox.pswing.PSwing; +import edu.umd.cs.piccolox.pswing.PSwingCanvas; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.border.LineBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.table.TableColumn; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.util.Vector; + +/** + * User: Sam Reid + * Date: Jul 11, 2005 + * Time: 12:15:55 PM + * Copyright (c) Jul 11, 2005 by Sam Reid + */ + +public class TestPSwingFull extends JFrame { + public TestPSwingFull() { + setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); + ClassLoader loader; + PSwingCanvas canvas; + + // Set up basic frame + setBounds( 50, 50, 750, 750 ); + setResizable( true ); + setBackground( null ); + setVisible( true ); + canvas = new PSwingCanvas(); + canvas.setPanEventHandler( null ); + getContentPane().add( canvas ); + validate(); + loader = getClass().getClassLoader(); + + ZVisualLeaf leaf; + PNode transform; + PSwing swing; + PSwing swing2; + + // JButton + JButton button = new JButton( "Button" ); + button.setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ) ); + swing = new PSwing(button ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -500, -500 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // JButton + JSpinner spinner = new JSpinner( new SpinnerNumberModel( 0, 0, 10, 1 ) ); + spinner.setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ) ); + swing = new PSwing(spinner ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -800, -500 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // 2nd Copy of JButton + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -450, -450 ); + transform.rotate( Math.PI / 2 ); + transform.scale( 0.5 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // Growable JTextArea + JTextArea textArea = new JTextArea( "This is a growable TextArea.\nTry it out!" ); + textArea.setBorder( new LineBorder( Color.blue, 3 ) ); + swing = new PSwing(textArea ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -250, -500 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // Growable JTextField + JTextField textField = new JTextField( "A growable text field" ); + swing = new PSwing(textField ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 0, -500 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // A Slider + JSlider slider = new JSlider(); + swing = new PSwing(slider ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 250, -500 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // A Scrollable JTree + JTree tree = new JTree(); + tree.setEditable( true ); + JScrollPane p = new JScrollPane( tree ); + p.setPreferredSize( new Dimension( 150, 150 ) ); + swing = new PSwing(p ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -500, -250 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // A Scrollable JTextArea + JScrollPane pane = new JScrollPane( new JTextArea( "A Scrollable Text Area\nTry it out!" ) ); + pane.setPreferredSize( new Dimension( 150, 150 ) ); + swing = new PSwing(pane ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -250, -250 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + swing2 = swing; + + // A non-scrollable JTextField + // A panel MUST be created with double buffering off + JPanel panel = new JPanel( false ); + textField = new JTextField( "A fixed-size text field" ); + panel.setLayout( new BorderLayout() ); + panel.add( textField ); + swing = new PSwing(panel ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 0, -250 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + +// // A JComboBox +// String[] listItems = {"Summer Teeth", "Mermaid Avenue", "Being There", "A.M."}; +// ZComboBox box = new ZComboBox( listItems ); +// swing = new PSwing( canvas, box ); +// leaf = new ZVisualLeaf( swing ); +// transform = new PNode(); +// transform.translate( 0, -150 ); +// transform.addChild( leaf ); +// canvas.getLayer().addChild( transform ); + + // A panel with TitledBorder and JList + panel = new JPanel( false ); + panel.setBackground( Color.lightGray ); + panel.setLayout( new BorderLayout() ); + panel.setBorder( new TitledBorder( new EtchedBorder( EtchedBorder.RAISED ), "A JList", TitledBorder.LEFT, TitledBorder.TOP ) ); + panel.setPreferredSize( new Dimension( 200, 200 ) ); + Vector data = new Vector(); + data.addElement( "Choice 1" ); + data.addElement( "Choice 2" ); + data.addElement( "Choice 3" ); + data.addElement( "Choice 4" ); + data.addElement( "Choice 5" ); + JList list = new JList( data ); + list.setBackground( Color.lightGray ); + panel.add( list ); + swing = new PSwing(panel ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 250, -250 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // A JLabel + JLabel label = new JLabel( "A JLabel", SwingConstants.CENTER ); + + swing = new PSwing(label ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -500, 0 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // Rotated copy of the Scrollable JTextArea + leaf = new ZVisualLeaf( swing2 ); + transform = new PNode(); + transform.translate( -100, 0 ); + transform.rotate( Math.PI / 2 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // A panel with layout + // A panel MUST be created with double buffering off + panel = new JPanel( false ); + panel.setLayout( new BorderLayout() ); + JButton button1 = new JButton( "Button 1" ); + JButton button2 = new JButton( "Button 2" ); + label = new JLabel( "A Panel with Layout" ); + label.setHorizontalAlignment( SwingConstants.CENTER ); + label.setForeground( Color.white ); + panel.setBackground( Color.red ); + panel.setPreferredSize( new Dimension( 150, 150 ) ); + panel.setBorder( new EmptyBorder( 5, 5, 5, 5 ) ); + panel.add( button1, "North" ); + panel.add( button2, "South" ); + panel.add( label, "Center" ); + panel.revalidate(); + swing = new PSwing(panel ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 0, 0 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // JTable Example + Vector columns = new Vector(); + columns.addElement( "Check Number" ); + columns.addElement( "Description" ); + columns.addElement( "Amount" ); + Vector rows = new Vector(); + Vector row = new Vector(); + row.addElement( "101" ); + row.addElement( "Sandwich" ); + row.addElement( "$20.00" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "102" ); + row.addElement( "Monkey Wrench" ); + row.addElement( "$100.00" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "214" ); + row.addElement( "Ant farm" ); + row.addElement( "$55.00" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "215" ); + row.addElement( "Self-esteem tapes" ); + row.addElement( "$37.99" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "216" ); + row.addElement( "Tube Socks" ); + row.addElement( "$7.45" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "220" ); + row.addElement( "Ab Excerciser" ); + row.addElement( "$56.95" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "319" ); + row.addElement( "Y2K Supplies" ); + row.addElement( "$4624.33" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "332" ); + row.addElement( "Tie Rack" ); + row.addElement( "$15.20" ); + rows.addElement( row ); + row = new Vector(); + row.addElement( "344" ); + row.addElement( "Swing Set" ); + row.addElement( "$146.59" ); + rows.addElement( row ); + JTable table = new JTable( rows, columns ); + table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF ); + table.setRowHeight( 30 ); + TableColumn c = table.getColumn( table.getColumnName( 0 ) ); + c.setPreferredWidth( 150 ); + c = table.getColumn( table.getColumnName( 1 ) ); + c.setPreferredWidth( 150 ); + c = table.getColumn( table.getColumnName( 2 ) ); + c.setPreferredWidth( 150 ); + pane = new JScrollPane( table ); + pane.setPreferredSize( new Dimension( 200, 200 ) ); + table.setDoubleBuffered( false ); + swing = new PSwing(pane ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 250, 0 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // JEditorPane - HTML example + try { + + + final JEditorPane editorPane = new JEditorPane( loader.getResource( "csdept.html" ) ); + editorPane.setDoubleBuffered( false ); + editorPane.setEditable( false ); + pane = new JScrollPane( editorPane ); + pane.setDoubleBuffered( false ); + pane.setPreferredSize( new Dimension( 400, 400 ) ); + editorPane.addHyperlinkListener( new HyperlinkListener() { + public void hyperlinkUpdate( HyperlinkEvent e ) { + if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) { + try { + editorPane.setPage( e.getURL() ); + } + catch( IOException ioe ) { + System.out.println( "Couldn't Load Web Page" ); + } + } + } + } ); + swing = new PSwing(pane ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -500, 250 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + } + catch( IOException ioe ) { + System.out.println( "Couldn't Load Web Page" ); + } + + // A JInternalFrame with a JSplitPane - a JOptionPane - and a + // JToolBar + JInternalFrame iframe = new JInternalFrame( "JInternalFrame" ); + iframe.getRootPane().setDoubleBuffered( false ); + ( (JComponent)iframe.getContentPane() ).setDoubleBuffered( false ); + iframe.setPreferredSize( new Dimension( 500, 500 ) ); + JTabbedPane tabby = new JTabbedPane(); + tabby.setDoubleBuffered( false ); + iframe.getContentPane().setLayout( new BorderLayout() ); + JOptionPane options = new JOptionPane( "This is a JOptionPane!", + JOptionPane.INFORMATION_MESSAGE, + JOptionPane.DEFAULT_OPTION ); + options.setDoubleBuffered( false ); + options.setMinimumSize( new Dimension( 50, 50 ) ); + options.setPreferredSize( new Dimension( 225, 225 ) ); + JPanel tools = new JPanel( false ); + tools.setMinimumSize( new Dimension( 150, 150 ) ); + tools.setPreferredSize( new Dimension( 225, 225 ) ); + JToolBar bar = new JToolBar(); + Action letter = new AbstractAction( "Big A!" ) { + + public void actionPerformed( ActionEvent e ) { + } + }; + + Action hand = new AbstractAction( "Hi!" ) { + public void actionPerformed( ActionEvent e ) { + } + }; + Action select = new AbstractAction( "There!" ) { + public void actionPerformed( ActionEvent e ) { + } + }; + + label = new JLabel( "A Panel with a JToolBar" ); + label.setHorizontalAlignment( SwingConstants.CENTER ); + bar.add( letter ); + bar.add( hand ); + bar.add( select ); + bar.setFloatable( false ); + bar.setBorder( new LineBorder( Color.black, 2 ) ); + tools.setLayout( new BorderLayout() ); + tools.add( bar, "North" ); + tools.add( label, "Center" ); + + JSplitPane split = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, options, tools ); + split.setDoubleBuffered( false ); + iframe.getContentPane().add( split ); + swing = new PSwing(iframe ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( 0, 250 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + +// JMenuBar menuBar = new JMenuBar(); +// ZMenu menu = new ZMenu( "File" ); +// ZMenu sub = new ZMenu( "Export" ); +// JMenuItem gif = new JMenuItem( "Funds" ); +// sub.add( gif ); +// menu.add( sub ); +// menuBar.add( menu ); +// iframe.setJMenuBar( menuBar ); + + iframe.setVisible( true ); + + // A JColorChooser - also demonstrates JTabbedPane +// JColorChooser chooser = new JColorChooser(); + JCheckBox chooser = new JCheckBox( "Check Box" ); + swing = new PSwing(chooser ); + leaf = new ZVisualLeaf( swing ); + transform = new PNode(); + transform.translate( -250, 850 ); + transform.addChild( leaf ); + canvas.getLayer().addChild( transform ); + + // Revalidate and repaint + canvas.revalidate(); + canvas.repaint(); + + PSwing message = new PSwing(new JTextArea( "Click-drag to zoom in and out." ) ); + message.translate( 0, -50 ); + canvas.getLayer().addChild( message ); + + canvas.getCamera().animateViewToCenterBounds( message.getFullBounds(), false, 1200 ); + } + + public static void main( String[] args ) { + new TestPSwingFull().setVisible( true ); + } + + public static class ZVisualLeaf extends PNode { + public ZVisualLeaf( PNode node ) { + addChild( node ); + } + } + +}