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 a0037d5..1fad05a 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 @@ -52,119 +52,120 @@ import java.util.Arrays; /* - This message was sent to Sun on August 27, 1999 + 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. + 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 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.) + 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. + 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. + 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. + 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);
+ * 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.
+ * 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);
- *
+ * 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.
@@ -174,28 +175,27 @@
* 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.
+ * 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
+ *
+ * 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.
+ * 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();
/**
@@ -205,26 +205,28 @@
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 Font defaultFont = new Font("Serif", Font.PLAIN, 12);
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*/
+ // //////////////////////////////////////////////////////////
+ // /////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*/
+ /* The parent listener for camera/canvas changes */
private PropertyChangeListener parentListener = new PropertyChangeListener() {
- public void propertyChange( PropertyChangeEvent evt ) {
+ public void propertyChange(PropertyChangeEvent evt) {
PNode parent = (PNode) evt.getNewValue();
clearListeners((PNode) evt.getOldValue());
- if( parent != null ) {
- listenForCanvas( parent );
- } else {
- updateCanvas( null );
+ if (parent != null) {
+ listenForCanvas(parent);
+ }
+ else {
+ updateCanvas(null);
}
}
@@ -232,21 +234,21 @@
/**
* 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.putClientProperty(PSWING_PROPERTY, this);
+ init(component);
component.revalidate();
-
- component.addPropertyChangeListener( new PropertyChangeListener() {
- public void propertyChange( PropertyChangeEvent evt ) {
+
+ component.addPropertyChangeListener(new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
reshape();
}
- } );
-
+ });
+
component.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
System.out.println("Hiding component");
@@ -258,110 +260,115 @@
setVisible(true);
}
});
-
+
reshape();
- listenForCanvas( this );
+ listenForCanvas(this);
}
/**
- * Deprecated constructor for application code still depending on this signature.
+ * Deprecated constructor for application code still depending on this
+ * signature.
+ *
* @param pSwingCanvas
* @param component
- * @deprecated
+ * @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.
+ * 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 );
+ 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.
+ * 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.
- *
+ * 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 ) {
+ public void paint(PPaintContext renderContext) {
Graphics2D g2 = renderContext.getGraphics();
- if( defaultStroke == null ) {
+ if (defaultStroke == null) {
defaultStroke = new BasicStroke();
}
- g2.setStroke( defaultStroke );
+ g2.setStroke(defaultStroke);
- if( defaultFont == null ) {
- defaultFont = new Font( "Serif", Font.PLAIN, 12 );
+ if (defaultFont == null) {
+ defaultFont = new Font("Serif", Font.PLAIN, 12);
}
- g2.setFont( defaultFont );
+ g2.setFont(defaultFont);
- if( component.getParent() == null ) {
-// pSwingCanvas.getSwingWrapper().add( component );
+ if (component.getParent() == null) {
+ // pSwingCanvas.getSwingWrapper().add( component );
component.revalidate();
}
- if( shouldRenderGreek( renderContext ) ) {
- paintAsGreek( g2 );
+ if (shouldRenderGreek(renderContext)) {
+ paintAsGreek(g2);
}
else {
- paint( g2 );
+ paint(g2);
}
}
- protected boolean shouldRenderGreek( PPaintContext renderContext ) {
- return ( renderContext.getScale() < renderCutoff
-// && pSwingCanvas.getInteracting()
- ) ||
- minFontSize * renderContext.getScale() < 0.5;
+ 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 ) {
+ public void paintAsGreek(Graphics2D g2) {
Color background = component.getBackground();
Color foreground = component.getForeground();
Rectangle2D rect = getBounds();
- if( background != null ) {
- g2.setColor( background );
+ if (background != null) {
+ g2.setColor(background);
}
- g2.fill( rect );
+ g2.fill(rect);
- if( foreground != null ) {
- g2.setColor( foreground );
+ if (foreground != null) {
+ g2.setColor(foreground);
}
- g2.draw( rect );
+ g2.draw(rect);
}
/**
- * Remove from the SwingWrapper; throws an exception if no canvas is associated with this PSwing.
+ * 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 );
+ 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).
- *
+ * 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) {
@@ -372,64 +379,53 @@
PSwingRepaintManager manager = (PSwingRepaintManager) RepaintManager.currentManager(component);
manager.lockRepaint(component);
-
+
RenderingHints oldHints = g2.getRenderingHints();
-
- g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
- RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
+
+ g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
component.paint(g2);
-
+
g2.setRenderingHints(oldHints);
manager.unlockRepaint(component);
}
-
+
public void setVisible(boolean visible) {
super.setVisible(visible);
component.setVisible(visible);
- }
+ }
/**
- * 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.
- *
+ * 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 );
+ 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
+ * 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() );
-// }
-// }
+ // 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() {
@@ -437,26 +433,26 @@
}
/**
- * 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.
- *
+ * 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 ) {
- if( c.getFont() != null ) {
- minFontSize = Math.min( minFontSize, c.getFont().getSize() );
+ void init(Component c) {
+ if (c.getFont() != null) {
+ minFontSize = Math.min(minFontSize, c.getFont().getSize());
}
if (c instanceof Container) {
Component[] children = ((Container) c).getComponents();
- if(children != null) {
- for(int j = 0; j < children.length; j++) {
+ if (children != null) {
+ for (int j = 0; j < children.length; j++) {
init(children[j]);
}
}
@@ -467,66 +463,69 @@
}
});
}
- if( c instanceof JComponent ) {
- ( (JComponent)c ).setDoubleBuffered( false );
- c.addPropertyChangeListener( "font", this );
- c.addComponentListener( new ComponentAdapter() {
- public void componentResized( ComponentEvent e ) {
+ 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 ) {
+ 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() );
+ 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 {
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
- init( component );
+ init(component);
}
- ////////////////////////////////////////////////////////////
- ///////Start methods for automatic canvas detection
- ////////////////////////////////////////////////////////////
+ // //////////////////////////////////////////////////////////
+ // /////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.
+ * 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
+ private void listenForCanvas(PNode node) {
+ // need to get the full tree for this node
PNode p = node;
- while( p != null ) {
- listenToNode( p );
+ while (p != null) {
+ listenToNode(p);
PNode parent = p;
-// System.out.println( "parent = " + parent.getClass() );
- if( parent instanceof PCamera) {
+ // System.out.println( "parent = " + parent.getClass() );
+ if (parent instanceof PCamera) {
PCamera cam = (PCamera) parent;
- if( cam.getComponent() instanceof PSwingCanvas ) {
- updateCanvas( (PSwingCanvas)cam.getComponent() );
+ if (cam.getComponent() instanceof PSwingCanvas) {
+ updateCanvas((PSwingCanvas) cam.getComponent());
}
- } else if( parent instanceof PLayer ) {
- PLayer player = (PLayer)parent;
-// System.out.println( "Found player: with " + player.getCameraCount() + " cameras" );
- for( int i = 0; i < player.getCameraCount(); i++ ) {
- PCamera cam = player.getCamera( i );
- if( cam.getComponent() instanceof PSwingCanvas ) {
- updateCanvas( (PSwingCanvas)cam.getComponent() );
+ }
+ else if (parent instanceof PLayer) {
+ PLayer player = (PLayer) parent;
+ // System.out.println( "Found player: with " +
+ // player.getCameraCount() + " cameras" );
+ for (int i = 0; i < player.getCameraCount(); i++) {
+ PCamera cam = player.getCamera(i);
+ if (cam.getComponent() instanceof PSwingCanvas) {
+ updateCanvas((PSwingCanvas) cam.getComponent());
break;
}
}
@@ -536,26 +535,31 @@
}
/**
- * Attach a listener to the specified node, if one has not already been attached.
+ * 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 );
+ 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.
+ * 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
+ * @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 ) {
+ private boolean listeningTo(PNode node) {
+ for (int i = 0; i < listeningTo.size(); i++) {
+ PNode pNode = (PNode) listeningTo.get(i);
+ if (pNode == node) {
return true;
}
}
@@ -563,8 +567,9 @@
}
/**
- * Clear out all the listeners registered to make sure there are no stray references
- *
+ * Clear out all the listeners registered to make sure there are no stray
+ * references
+ *
* @param fromParent Parent to start with for clearing listeners
*/
private void clearListeners(PNode fromParent) {
@@ -572,32 +577,32 @@
return;
}
if (listeningTo(fromParent)) {
- fromParent.removePropertyChangeListener( PNode.PROPERTY_PARENT, parentListener );
+ fromParent.removePropertyChangeListener(PNode.PROPERTY_PARENT, parentListener);
listeningTo.remove(fromParent);
clearListeners(fromParent.getParent());
}
}
/**
- * Removes this PSwing from previous PSwingCanvas (if any), and ensure that this
- * PSwing is attached to the new PSwingCanvas.
+ * 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 );
+ private void updateCanvas(PSwingCanvas newCanvas) {
+ if (newCanvas != canvas) {
+ if (canvas != null) {
+ canvas.removePSwing(this);
}
canvas = newCanvas;
- if( newCanvas != null ) {
- canvas.addPSwing( this );
+ if (newCanvas != null) {
+ canvas.addPSwing(this);
reshape();
repaint();
}
}
}
- ////////////////////////////////////////////////////////////
- ///////End methods for automatic canvas detection
- ////////////////////////////////////////////////////////////
+ // //////////////////////////////////////////////////////////
+ // /////End methods for automatic canvas detection
+ // //////////////////////////////////////////////////////////
}