uci-sdcl/CalicoClient — Issue #62: Drawing strokes quickly causes ArrayIndexOutOfBoundsException
Author: waynehuang3
Created: 2012-02-07 04:15:32+00:00
State: open

The cause for this has been found.

In calico.components.CStroke.finish()

path.setTransparency(0f);
SwingUtilities.invokeLater(
new Runnable() { public void run() { layer.removeChild(path); } }
);

It appears that the purpose of these lines is that the child will be removed later but we want to immediately remove the stroke from the canvas so its transparency is set to 0 first, and the layer will officially be removed later. However the Piccolo code pushes and pops the transparency onto a stack. Changing the transparency here causes the value to be changed in between the push and pop. Push and Pop are ignored if transparency = 1.0f. Since we are setting transparency to 0f here, Piccolo tries to pop when nothing was ever pushed.

The easy fix is to remove "path.setTransparency(0f)". It is possible this is not the source of the race condition, but by removing this line of code, all the push and pops appear to line up properly. It also does not appear to have any visible impact on the removal of strokes.

I will add this to my next commit unless further discussion warrants otherwise. Created this issue for documenting purposes.

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.remove(Unknown Source)
at edu.umd.cs.piccolo.util.PStack.pop(PStack.java:84)
at edu.umd.cs.piccolo.util.PPaintContext.popTransparency(PPaintContext.java:250)
at edu.umd.cs.piccolo.PNode.fullPaint(PNode.java:2837)
at edu.umd.cs.piccolo.PNode.fullPaint(PNode.java:2832)
at edu.umd.cs.piccolo.PCamera.paintCameraView(PCamera.java:374)
at edu.umd.cs.piccolo.PCamera.paint(PCamera.java:356)
at edu.umd.cs.piccolo.PNode.fullPaint(PNode.java:2826)
at edu.umd.cs.piccolo.PCamera.fullPaint(PCamera.java:448)
at edu.umd.cs.piccolo.PCanvas.paintComponent(PCanvas.java:608)
at calico.components.CCanvas$ContainedCanvas.paintComponent(CCanvas.java:1363)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)