Revision: 1112
Author: [email protected]
Date: Mon Mar 7 11:50:37 2011
Log: Applied fixes from the piccolo 1.3 branch to trunk, see issue 163
http://code.google.com/p/piccolo2d/source/detail?r=1112
Added:
/piccolo2d.java/trunk/extras/src/test/java/org/piccolo2d/extras/pswing/PSwingDynamicComponentExample.java
Modified:
/piccolo2d.java/trunk/extras/src/main/java/org/piccolo2d/extras/pswing/PSwing.java
/piccolo2d.java/trunk/extras/src/main/java/org/piccolo2d/extras/pswing/PSwingRepaintManager.java
=======================================
--- /dev/null
+++
/piccolo2d.java/trunk/extras/src/test/java/org/piccolo2d/extras/pswing/PSwingDynamicComponentExample.java
Mon Mar 7 11:50:37 2011
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2008-2010, Piccolo2D project, http://piccolo2d.org
+ * Copyright (c) 1998-2008, University of Maryland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
this list of conditions
+ * and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions
+ * and the following disclaimer in the documentation and/or other
materials provided with the
+ * distribution.
+ *
+ * None of the name of the University of Maryland, the name of the
Piccolo2D project, or the names of its
+ * contributors may be used to endorse or promote products derived from
this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.piccolo2d.extras.pswing;
+
+import javax.swing.*;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Demonstrates a PSwing problem with dynamic JComponents.
+ * <p>
+ * This example shows 2 identical JPanels.
+ * The panel on the left uses PSwing.
+ * The panel on the right uses pure Swing.
+ * <p>
+ * The JPanel contain various JComponents whose text can be updated by
+ * typing into JTextFields and pressing the "Update" button.
+ * The JPanel managed by PSwing is often rendered incorrectly.
+ * <p>
+ * Please see piccolo2d issue 163 for more information about this problem
and solution:
+ * http://code.google.com/p/piccolo2d/issues/detail?id=163
+ *
+ * @author Chris Malley ([email protected])
+ * @author Sam Reid
+ */
+public class PSwingDynamicComponentExample extends JFrame {
+
+ private static final Dimension FRAME_SIZE = new Dimension( 800, 400 );
+ private static final int TEXT_FIELD_COLUMNS = 30;
+
+ private final ComponentPanel swingPanel, piccoloPanel;
+ private final JTextField labelTextField, checkBoxTextField,
radioButtonTextField;
+
+ public PSwingDynamicComponentExample() {
+ super( PSwingDynamicComponentExample.class.getName() );
+ setSize( FRAME_SIZE );
+
+ // canvas
+ PSwingCanvas canvas = new PSwingCanvas();
+ canvas.setBackground( Color.RED );
+ canvas.removeInputEventListener( canvas.getZoomEventHandler() );
+ canvas.removeInputEventListener( canvas.getPanEventHandler() );
+
+ // panel that we'll display using Piccolo
+ piccoloPanel = new ComponentPanel();
+ final PSwing pswing = new PSwing( piccoloPanel );
+ canvas.getLayer().addChild( pswing );
+ pswing.setOffset( 10, 10 );
+
+ // panel that we're display using pure Swing
+ swingPanel = new ComponentPanel();
+ JPanel jpanel = new JPanel();
+ jpanel.setBorder( new LineBorder( Color.BLACK ) );
+ jpanel.add( swingPanel );
+
+ // text fields, for specifying dynamic text
+ labelTextField = new JTextField( swingPanel.label.getText(),
TEXT_FIELD_COLUMNS );
+ checkBoxTextField = new JTextField( swingPanel.checkBox.getText(),
TEXT_FIELD_COLUMNS );
+ radioButtonTextField = new JTextField(
swingPanel.radioButton.getText(), TEXT_FIELD_COLUMNS );
+
+ // Update button, for applying dynamic text
+ JButton updateButton = new JButton( "Update" );
+ updateButton.addActionListener( new ActionListener() {
+ public void actionPerformed( ActionEvent e ) {
+ updatePanels();
+ }
+ } );
+
+ //
+ JButton addComponentButton = new JButton( "add component" );
+ addComponentButton.addActionListener( new ActionListener() {
+
+ public void actionPerformed( ActionEvent e ) {
+ piccoloPanel.addComponent( new JLabel( "new" ) );
+ swingPanel.addComponent( new JLabel( "new" ) );
+ }
+
+ });
+
+ // control panel
+ JPanel controlPanel = new JPanel();
+ controlPanel.setBorder( new LineBorder( Color.BLACK ) );
+ controlPanel.setLayout( new GridBagLayout() );
+ GridBagConstraints c = new GridBagConstraints();
+ // JLabel
+ c.gridx = 0;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.EAST;
+ controlPanel.add( new JLabel( "JLabel text:" ), c );
+ c.gridx++;
+ c.anchor = GridBagConstraints.WEST;
+ controlPanel.add( labelTextField, c );
+ // JCheckBox
+ c.gridx = 0;
+ c.gridy++;
+ c.anchor = GridBagConstraints.EAST;
+ controlPanel.add( new JLabel( "JCheckBox text:" ), c );
+ c.gridx++;
+ c.anchor = GridBagConstraints.WEST;
+ controlPanel.add( checkBoxTextField, c );
+ // JRadioButton
+ c.gridx = 0;
+ c.gridy++;
+ c.anchor = GridBagConstraints.EAST;
+ controlPanel.add( new JLabel( "JRadioButton text:" ), c );
+ c.gridx++;
+ c.anchor = GridBagConstraints.WEST;
+ controlPanel.add( radioButtonTextField, c );
+ // Update button
+ c.gridx = 1;
+ c.gridy++;
+ c.anchor = GridBagConstraints.WEST;
+ controlPanel.add( updateButton, c );
+ // Add component buttons
+ c.gridx = 1;
+ c.gridy++;
+ c.anchor = GridBagConstraints.WEST;
+ controlPanel.add( addComponentButton, c );
+
+
+
+ // main panel
+ JPanel mainPanel = new JPanel( new BorderLayout() );
+ mainPanel.add( canvas, BorderLayout.CENTER );
+ mainPanel.add( jpanel, BorderLayout.EAST );
+ mainPanel.add( controlPanel, BorderLayout.SOUTH );
+ setContentPane( mainPanel );
+ }
+
+ // applies the text field values to the components in the panels
+ private void updatePanels() {
+
+ // Piccolo (PSwing) panel
+ piccoloPanel.label.setText( labelTextField.getText() );
+ piccoloPanel.checkBox.setText( checkBoxTextField.getText() );
+ piccoloPanel.radioButton.setText( radioButtonTextField.getText() );
+
+ // Swing panel
+ swingPanel.label.setText( labelTextField.getText() );
+ swingPanel.checkBox.setText( checkBoxTextField.getText() );
+ swingPanel.radioButton.setText( radioButtonTextField.getText() );
+ }
+
+ // A panel with a few different types of JComponent.
+ private static class ComponentPanel extends JPanel {
+
+ // allow public access to keep our example code short
+ public final JLabel label;
+ public final JCheckBox checkBox;
+ public final JRadioButton radioButton;
+ public final GridBagConstraints constraints;
+
+ public ComponentPanel() {
+ setBorder( new CompoundBorder( new LineBorder( Color.BLACK, 1
), new EmptyBorder( 5, 14, 5, 14 ) ) );
+ setBackground( new Color( 180, 205, 255 ) );
+
+ // components
+ label = new JLabel( "JLabel" );
+ checkBox = new JCheckBox( "JCheckBox" );
+ radioButton = new JRadioButton( "JRadioButton" );
+
+ // layout
+ setLayout( new GridBagLayout() );
+ constraints = new GridBagConstraints();
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.gridx = 0;
+ constraints.gridy = GridBagConstraints.RELATIVE;
+ addComponent( label );
+ addComponent( checkBox );
+ addComponent( radioButton );
+ }
+
+ public void addComponent( JComponent c ) {
+ add( c, constraints );
+ revalidate();
+ }
+ }
+
+ public static class SleepThread extends Thread {
+
+ public SleepThread( long millis ) {
+ super( new Runnable() {
+ public void run() {
+ while ( true ) {
+ try {
+ SwingUtilities.invokeAndWait( new Runnable() {
+ public void run() {
+ try {
+ Thread.sleep( 1000 );
+ }
+ catch ( InterruptedException e ) {
+ e.printStackTrace();
+ }
+ }
+ } );
+ }
+ catch ( InterruptedException e ) {
+ e.printStackTrace();
+ }
+ catch ( InvocationTargetException e ) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } );
+ }
+ }
+
+ public static void main( String[] args ) {
+ // This thread serves to make the problem more noticeable.
+// new SleepThread( 1000 ).start();
+ SwingUtilities.invokeLater( new Runnable() {
+ public void run() {
+ JFrame frame = new PSwingDynamicComponentExample();
+ frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE );
+ frame.setVisible( true );
+ }
+ } );
+ }
+}
=======================================
---
/piccolo2d.java/trunk/extras/src/main/java/org/piccolo2d/extras/pswing/PSwing.java
Mon May 10 20:10:56 2010
+++
/piccolo2d.java/trunk/extras/src/main/java/org/piccolo2d/extras/pswing/PSwing.java
Mon Mar 7 11:50:37 2011
@@ -37,12 +37,9 @@
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
-import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
@@ -60,7 +57,6 @@
import org.piccolo2d.util.PBounds;
import org.piccolo2d.util.PPaintContext;
-
/*
This message was sent to Sun on August 27, 1999
@@ -192,6 +188,7 @@
* </p>
*
* @author Sam R. Reid
+ * @author Chris Malley ([email protected])
* @author Benjamin B. Bederson
* @author Lance E. Good
*
@@ -220,7 +217,7 @@
/**
* Default stroke, <code>new BasicStroke()</code>. Cannot be made
static
- * because BasicStroke is not serializable.
+ * because BasicStroke is not serializable. Should not be null.
*/
private Stroke defaultStroke = new BasicStroke();
@@ -271,12 +268,6 @@
};
- private final PropertyChangeListener reshapeListener = new
PropertyChangeListener() {
- public void propertyChange(final PropertyChangeEvent evt) {
- repaint();
- }
- };
-
/**
* Listens to container nodes for changes to its contents. Any
additions
* will automatically have double buffering turned off.
@@ -296,9 +287,10 @@
* I'm assuming that the intent of the is method is that it should
be
* called explicitly by anyone making changes to the hierarchy of
the
* Swing component graph.
+ * @param targetComponent the component for which double buffering
should be removed
*/
private void disableDoubleBuffering(final JComponent
targetComponent) {
- targetComponent.setDoubleBuffered(false);
+ targetComponent.setDoubleBuffered( false );
for (int i = 0; i < targetComponent.getComponentCount(); i++) {
final Component c = targetComponent.getComponent(i);
if (c instanceof JComponent) {
@@ -319,41 +311,56 @@
initializeComponent(component);
component.revalidate();
- //TODO: this listener is suspicious, it's not listening for any
specific property
- component.addPropertyChangeListener(new PropertyChangeListener() {
- /** {@inheritDoc} */
- public void propertyChange(final PropertyChangeEvent evt) {
- updateBounds();
- }
- });
-
updateBounds();
listenForCanvas(this);
}
+
+ /**
+ * @deprecated by {@link #PSwing(JComponent)}
+ *
+ * @param swingCanvas canvas on which the PSwing node will be embedded
+ * @param component not used
+ */
+ public PSwing(final PSwingCanvas swingCanvas, final JComponent
component) {
+ this(component);
+ }
/**
* Ensures the bounds of the underlying component are accurate, and
sets the
* bounds of this PNode.
*/
public void updateBounds() {
- // Avoid setBounds if it is unnecessary
- // TODO: should we make sure this is called at least once
- // TODO: does this sometimes need to be called when size already
equals
- // preferred size, to relayout/update things?
+ /*
+ * Need to explicitly set the component's bounds because
+ * the component's parent (PSwingCanvas.ChildWrapper) has no
layout manager.
+ */
if (componentNeedsResizing()) {
- component.setBounds(0, 0, component.getPreferredSize().width,
component.getPreferredSize().height);
- }
- setBounds(0, 0, component.getPreferredSize().width,
component.getPreferredSize().height);
+ updateComponentSize();
+ }
+ setBounds( 0, 0, component.getPreferredSize().width,
component.getPreferredSize().height );
}
+ /**
+ * Since the parent ChildWrapper has no layout manager, it is the
responsibility of this PSwing
+ * to make sure the component has its bounds set properly, otherwise
it will not be drawn properly.
+ * This method sets the bounds of the component to be equal to its
preferred size.
+ */
+ private void updateComponentSize() {
+ component.setBounds( 0, 0, component.getPreferredSize().width,
component.getPreferredSize().height );
+ }
+
+ /**
+ * Determines whether the component should be resized, based on
whether its actual width and height
+ * differ from its preferred width and height.
+ * @return true if the component should be resized.
+ */
private boolean componentNeedsResizing() {
- return component.getWidth() != component.getPreferredSize().width
- || component.getHeight() !=
component.getPreferredSize().height;
+ return component.getWidth() != component.getPreferredSize().width |
| component.getHeight() != component.getPreferredSize().height;
}
/**
- * Determines if the Swing component should be rendered normally or as
a
- * filled rectangle.
+ * Paints the PSwing on the specified renderContext. Also determines
if
+ * the Swing component should be rendered normally or as a filled
rectangle (greeking).
* <p/>
* The transform, clip, and composite will be set appropriately when
this
* object is rendered. It is up to this object to restore the
transform,
@@ -365,25 +372,29 @@
* @param renderContext Contains information about current render.
*/
public void paint(final PPaintContext renderContext) {
+ if (componentNeedsResizing()) {
+ updateComponentSize();
+ component.validate();
+ }
final Graphics2D g2 = renderContext.getGraphics();
- if (defaultStroke == null) {
- defaultStroke = new BasicStroke();
- }
+ //Save Stroke and Font for restoring.
+ Stroke originalStroke = g2.getStroke();
+ Font originalFont = g2.getFont();
g2.setStroke(defaultStroke);
g2.setFont(DEFAULT_FONT);
-
- if (component.getParent() == null) {
- component.revalidate();
- }
-
+
if (shouldRenderGreek(renderContext)) {
paintAsGreek(g2);
}
else {
paint(g2);
}
+
+ //Restore the stroke and font on the Graphics2D
+ g2.setStroke(originalStroke);
+ g2.setFont(originalFont);
}
/**
@@ -399,24 +410,26 @@
}
/**
- * Paints the Swing component as greek.
+ * Paints the Swing component as greek. This method assumes that the
stroke has been set beforehand.
*
* @param g2 The graphics used to render the filled rectangle
*/
public void paintAsGreek(final Graphics2D g2) {
- final Color background = component.getBackground();
- final Color foreground = component.getForeground();
- final Rectangle2D rect = getBounds();
-
- if (background != null) {
- g2.setColor(background);
- }
- g2.fill(rect);
-
- if (foreground != null) {
- g2.setColor(foreground);
- }
- g2.draw(rect);
+ //Save original color for restoring painting as greek.
+ Color originalColor = g2.getColor();
+
+ if (component.getBackground() != null) {
+ g2.setColor(component.getBackground());
+ }
+ g2.fill(getBounds());
+
+ if (component.getForeground() != null) {
+ g2.setColor(component.getForeground());
+ }
+ g2.draw(getBounds());
+
+ //Restore original color on the Graphics2D
+ g2.setColor( originalColor );
}
/** {@inheritDoc} */
@@ -504,20 +517,7 @@
if (c.getFont() != null) {
minFontSize = Math.min(minFontSize, c.getFont().getSize());
}
- c.addPropertyChangeListener("font", this);
-
- // Update shape when any property (such as text or font) changes.
- c.addPropertyChangeListener(reshapeListener);
-
- c.addComponentListener(new ComponentAdapter() {
- public void componentResized(final ComponentEvent e) {
- updateBounds();
- }
-
- public void componentShown(final ComponentEvent e) {
- updateBounds();
- }
- });
+ c.addPropertyChangeListener( "font", this );
if (c instanceof Container) {
initializeChildren((Container) c);
@@ -654,7 +654,7 @@
* threshold the Swing component is rendered as 'Greek' instead of
painting
* the Swing component. Defaults to {@link #DEFAULT_GREEK_THRESHOLD}.
*
- * @see PSwing#paintGreek(PPaintContext)
+ * @see PSwing#paintAsGreek(Graphics2D)
* @return the current Greek threshold scale
*/
public double getGreekThreshold() {
@@ -666,7 +666,7 @@
* scale will be below this threshold the Swing component is rendered
as
* 'Greek' instead of painting the Swing component..
*
- * @see PSwing#paintGreek(PPaintContext)
+ * @see PSwing#paintAsGreek(Graphics2D)
* @param greekThreshold Greek threshold in scale
*/
public void setGreekThreshold(final double greekThreshold) {
=======================================
---
/piccolo2d.java/trunk/extras/src/main/java/org/piccolo2d/extras/pswing/PSwingRepaintManager.java
Mon May 10 20:10:56 2010
+++
/piccolo2d.java/trunk/extras/src/main/java/org/piccolo2d/extras/pswing/PSwingRepaintManager.java
Mon Mar 7 11:50:37 2011
@@ -33,14 +33,13 @@
import javax.swing.JComponent;
import javax.swing.RepaintManager;
-import javax.swing.SwingUtilities;
import org.piccolo2d.util.PBounds;
-
/**
* This RepaintManager replaces the default Swing implementation, and is
used to
- * intercept and repaint dirty regions of PSwing components.
+ * repaint dirty regions of PSwing components and make sure the PSwings
have
+ * the appropriate size.
* <p>
* This is an internal class used by Piccolo to support Swing components in
* Piccolo. This should not be instantiated, though all the public methods
of
@@ -50,12 +49,12 @@
* <p>
* PBasicRepaint Manager is an extension of RepaintManager that traps those
* repaints called by the Swing components that have been added to the
PCanvas
- * and passes these repaints to the SwingVisualComponent rather than up the
+ * and passes these repaints to the PSwing rather than up the
* component hierarchy as usually happens.
* </p>
* <p>
- * Also traps revalidate calls made by the Swing components added to the
PCanvas
- * to reshape the applicable Visual Component.
+ * Also traps invalidate calls made by the Swing components added to the
PCanvas
+ * to reshape the corresponding PSwing.
* </p>
* <p>
* Also keeps a list of PSwings that are painting. This disables repaint
until
@@ -63,14 +62,14 @@
* by Swing's CellRendererPane which is itself a work-around. The problem
is
* that JTable's, JTree's, and JList's cell renderers need to be validated
* before repaint. Since we have to repaint the entire Swing component
hierarchy
- * (in the case of a Swing component group used as a Piccolo visual
component).
- * This causes an infinite loop. So we introduce the restriction that no
- * repaints can be triggered by a call to paint.
+ * (in the case of a PSwing), this causes an infinite loop. So we
introduce the
+ * restriction that no repaints can be triggered by a call to paint.
* </p>
*
* @author Benjamin B. Bederson
* @author Lance E. Good
* @author Sam R. Reid
+ * @author Chris Malley ([email protected])
*/
public class PSwingRepaintManager extends RepaintManager {
@@ -120,19 +119,15 @@
* @param width Width of the dirty region in the component
* @param height Height of the dirty region in the component
*/
- public synchronized void addDirtyRegion(final JComponent component,
final int x, final int y, final int width,
- final int height) {
+ public synchronized void addDirtyRegion(final JComponent component,
final int x, final int y, final int width, final int height) {
boolean captureRepaint = false;
JComponent childComponent = null;
-
int captureX = x;
int captureY = y;
- // We have to check to see if the PCanvas
- // (ie. the SwingWrapper) is in the components ancestry. If so,
- // we will want to capture that repaint. However, we also will
- // need to translate the repaint request since the component may
- // be offset inside another component.
+ // We have to check to see if the PCanvas (ie. the SwingWrapper)
is in the components ancestry. If so, we will
+ // want to capture that repaint. However, we also will need to
translate the repaint request since the component
+ // may be offset inside another component.
for (Component comp = component; comp != null &&
comp.isLightweight(); comp = comp.getParent()) {
if (comp.getParent() instanceof PSwingCanvas.ChildWrapper) {
captureRepaint = true;
@@ -146,34 +141,24 @@
}
}
- // Now we check to see if we should capture the repaint and act
- // accordingly
+ // Now we check to see if we should capture the repaint and act
accordingly
if (captureRepaint) {
if (!isPainting(childComponent)) {
final double repaintW = Math.min(childComponent.getWidth()
- captureX, width);
final double repaintH =
Math.min(childComponent.getHeight() - captureY, height);
- dispatchRepaint(childComponent, new PBounds(captureX,
captureY, repaintW, repaintH));
+ //Schedule a repaint for the dirty part of the PSwing
+ getPSwing(childComponent).repaint( new PBounds( captureX,
captureY, repaintW, repaintH ) );
}
}
else {
super.addDirtyRegion(component, x, y, width, height);
}
}
-
- private void dispatchRepaint(final JComponent childComponent, final
PBounds repaintBounds) {
- final PSwing pSwing = (PSwing)
childComponent.getClientProperty(PSwing.PSWING_PROPERTY);
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- pSwing.repaint(repaintBounds);
- }
- });
- }
/**
- * This is the method "revalidate" calls in the Swing components.
Overridden
- * to capture revalidate calls from those Swing components being used
as
+ * This is the method "invalidate" calls in the Swing components.
Overridden
+ * to capture invalidation calls from those Swing components being
used as
* Piccolo visual components and to update Piccolo's visual component
* wrapper bounds (these are stored separately from the Swing
component).
* Otherwise, behaves like the superclass.
@@ -181,20 +166,21 @@
* @param invalidComponent The Swing component that needs validation
*/
public synchronized void addInvalidComponent(final JComponent
invalidComponent) {
- final JComponent capturedComponent = invalidComponent;
-
- if (capturedComponent.getParent() == null
- || !(capturedComponent.getParent() instanceof
PSwingCanvas.ChildWrapper)) {
+ if (invalidComponent.getParent() == null |
| !(invalidComponent.getParent() instanceof PSwingCanvas.ChildWrapper)) {
super.addInvalidComponent(invalidComponent);
}
else {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- capturedComponent.validate();
- final PSwing pSwing = (PSwing)
capturedComponent.getClientProperty(PSwing.PSWING_PROPERTY);
- pSwing.updateBounds();
- }
- });
+ invalidComponent.validate();
+ getPSwing(invalidComponent).updateBounds();
}
}
-}
+
+ /**
+ * Obtains the PSwing associated with the specified component.
+ * @param component the component for which to return the associated
PSwing
+ * @return the associated PSwing
+ */
+ private PSwing getPSwing(JComponent component) {
+ return (PSwing) component.getClientProperty(
PSwing.PSWING_PROPERTY );
+ }
+}
--
Piccolo2D Developers Group: http://groups.google.com/group/piccolo2d-dev?hl=en