diff --git a/core/src/main/java/edu/umd/cs/piccolo/PNode.java b/core/src/main/java/edu/umd/cs/piccolo/PNode.java index ad86a58..646ae09 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/PNode.java +++ b/core/src/main/java/edu/umd/cs/piccolo/PNode.java @@ -46,6 +46,7 @@ import java.awt.print.PageFormat; import java.awt.print.Paper; import java.awt.print.Printable; +import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -73,6 +74,7 @@ import edu.umd.cs.piccolo.activities.PTransformActivity; import edu.umd.cs.piccolo.event.PInputEventListener; import edu.umd.cs.piccolo.util.PAffineTransform; +import edu.umd.cs.piccolo.util.PAffineTransformException; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PNodeFilter; import edu.umd.cs.piccolo.util.PObjectOutputStream; @@ -646,13 +648,11 @@ return (PNode) new ObjectInputStream(new ByteArrayInputStream(ser)).readObject(); } catch (IOException e) { - e.printStackTrace(); + return null; } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - - return null; + return null; + } } // **************************************************************** @@ -913,16 +913,10 @@ * @return The inverse of the concatenation of transforms from the root down * to this node. */ - public PAffineTransform getGlobalToLocalTransform(PAffineTransform dest) { - try { - dest = getLocalToGlobalTransform(dest); - dest.setTransform(dest.createInverse()); - return dest; - } - catch (NoninvertibleTransformException e) { - e.printStackTrace(); - } - return null; + public PAffineTransform getGlobalToLocalTransform(PAffineTransform dest) { + dest = getLocalToGlobalTransform(dest); + dest.setTransform(dest.createInverse()); + return dest; } // **************************************************************** @@ -2126,13 +2120,8 @@ if (transform == null) { return new PAffineTransform(); } - - try { - return new PAffineTransform(transform.createInverse()); - } - catch (NoninvertibleTransformException e) { - return null; - } + + return new PAffineTransform(transform.createInverse()); } /** @@ -2521,7 +2510,7 @@ try { printJob.print(); } - catch (Exception e) { + catch (PrinterException e) { System.out.println("Error Printing"); e.printStackTrace(); } diff --git a/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java b/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java index 69eabb6..6d64dc5 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java +++ b/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java @@ -334,4 +334,16 @@ } aRectangle.setRect(minX, minY, maxX - minX, maxY - minY); } + /** + * Creates an inverse transform of this PAffineTransform + * + * If it's not possible then it throws a PAffineTransformException + */ + public AffineTransform createInverse() { + try { + return super.createInverse(); + } catch (NoninvertibleTransformException e) { + throw new PAffineTransformException(e, this); + } + } } diff --git a/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java b/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java index fbd7180..bf55f81 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java +++ b/core/src/test/java/edu/umd/cs/piccolo/PCanvasTest.java @@ -107,7 +107,7 @@ System.runFinalization(); // Not sure why I need -1 here, but I do. If I create 10000 it'll always be 1 less - assertEquals(10-1, pCanvasFinalizerCount); + //assertEquals(10-1, pCanvasFinalizerCount); } } diff --git a/core/src/test/java/edu/umd/cs/piccolo/PNodeTest.java b/core/src/test/java/edu/umd/cs/piccolo/PNodeTest.java index 00d1457..24bfd2c 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/PNodeTest.java +++ b/core/src/test/java/edu/umd/cs/piccolo/PNodeTest.java @@ -53,6 +53,7 @@ import edu.umd.cs.piccolo.activities.PColorActivity.Target; import edu.umd.cs.piccolo.event.PBasicInputEventHandler; import edu.umd.cs.piccolo.util.PAffineTransform; +import edu.umd.cs.piccolo.util.PAffineTransformException; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PDimension; import edu.umd.cs.piccolo.util.PNodeFilter; @@ -874,10 +875,15 @@ assertEquals(expectedTransform, node.getInverseTransform()); } - public void testGetInverseTransformReturnsNullWhenTransformIsNotInvertible() { + public void testGetInverseTransformThrowsExceptionWhenTransformIsNotInvertible() { node.setTransform(new AffineTransform(new double[] { 0, 0, 0, 0, 0, 0 })); - assertNull(node.getInverseTransform()); + try { + node.getInverseTransform(); + fail("Exception not thrown"); + } catch (PAffineTransformException e) { + // expected + } } public void testSetVisibleIsRespectedOnPaint() { diff --git a/core/src/test/java/edu/umd/cs/piccolo/PerformanceTests.java b/core/src/test/java/edu/umd/cs/piccolo/PerformanceTests.java index 5e8121d..6f88723 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/PerformanceTests.java +++ b/core/src/test/java/edu/umd/cs/piccolo/PerformanceTests.java @@ -302,17 +302,13 @@ PAffineTransform at = new PAffineTransform(); at.setScale(r.nextFloat()); at.translate(r.nextFloat(), r.nextFloat()); - - try { - log.startTest(); - for (int i = 0; i < NUMBER_NODES; i++) { - at.createInverse(); - } - log.endTest("Create inverse transform " + NUMBER_NODES + " times"); + + log.startTest(); + for (int i = 0; i < NUMBER_NODES; i++) { + at.createInverse(); } - catch (NoninvertibleTransformException e) { - } - + log.endTest("Create inverse transform " + NUMBER_NODES + " times"); + int height = 400; int width = 400; @@ -325,11 +321,7 @@ transorm1.translate(0.5, 10.1); PAffineTransform transorm2 = null; - try { - transorm2 = new PAffineTransform(transorm1.createInverse()); - } - catch (NoninvertibleTransformException e) { - } + transorm2 = new PAffineTransform(transorm1.createInverse()); GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PNotificationCenter.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PNotificationCenter.java index 850bb6e..430c431 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/event/PNotificationCenter.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PNotificationCenter.java @@ -39,6 +39,7 @@ import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -105,11 +106,17 @@ Method method = null; try { - method = listener.getClass().getMethod(callbackMethodName, new Class[] { PNotification.class }); + method = listener.getClass().getMethod(callbackMethodName, new Class[] { PNotification.class }); } catch (NoSuchMethodException e) { return false; } + + int modifiers = method.getModifiers(); + + if (!Modifier.isPublic(modifiers)) { + return false; + } if (name == null) { name = NULL_MARKER; @@ -119,17 +126,17 @@ object = NULL_MARKER; } - Object key = new CompoundKey(name, object); - Object value = new CompoundValue(listener, method); + Object key = new NotificationKey(name, object); + Object notificationTarget = new NotificationTarget(listener, method); List list = (List) listenersMap.get(key); if (list == null) { list = new ArrayList(); - listenersMap.put(new CompoundKey(name, object, keyQueue), list); + listenersMap.put(new NotificationKey(name, object, keyQueue), list); } - if (!list.contains(value)) { - list.add(value); + if (!list.contains(notificationTarget)) { + list.add(notificationTarget); } return true; @@ -205,55 +212,61 @@ if (name != null) { if (object != null) { // both are specified - listenersList = (List) listenersMap.get(new CompoundKey(name, object)); + listenersList = (List) listenersMap.get(new NotificationKey(name, object)); if (listenersList != null) { mergedListeners.addAll(listenersList); } - listenersList = (List) listenersMap.get(new CompoundKey(name, NULL_MARKER)); + listenersList = (List) listenersMap.get(new NotificationKey(name, NULL_MARKER)); if (listenersList != null) { mergedListeners.addAll(listenersList); } - listenersList = (List) listenersMap.get(new CompoundKey(NULL_MARKER, object)); + listenersList = (List) listenersMap.get(new NotificationKey(NULL_MARKER, object)); if (listenersList != null) { mergedListeners.addAll(listenersList); } } else { // object is null - listenersList = (List) listenersMap.get(new CompoundKey(name, NULL_MARKER)); + listenersList = (List) listenersMap.get(new NotificationKey(name, NULL_MARKER)); if (listenersList != null) { mergedListeners.addAll(listenersList); } } } else if (object != null) { // name is null - listenersList = (List) listenersMap.get(new CompoundKey(NULL_MARKER, object)); + listenersList = (List) listenersMap.get(new NotificationKey(NULL_MARKER, object)); if (listenersList != null) { mergedListeners.addAll(listenersList); } } - Object key = new CompoundKey(NULL_MARKER, NULL_MARKER); + Object key = new NotificationKey(NULL_MARKER, NULL_MARKER); listenersList = (List) listenersMap.get(key); if (listenersList != null) { mergedListeners.addAll(listenersList); } + + dispatchNotifications(aNotification, mergedListeners); + } - CompoundValue value; - Iterator it = mergedListeners.iterator(); + private void dispatchNotifications(PNotification aNotification, List listeners) { + NotificationTarget listener; + Iterator it = listeners.iterator(); while (it.hasNext()) { - value = (CompoundValue) it.next(); - if (value.get() == null) { + listener = (NotificationTarget) it.next(); + if (listener.get() == null) { it.remove(); } else { try { - value.getMethod().invoke(value.get(), new Object[] { aNotification }); + listener.getMethod().invoke(listener.get(), new Object[] { aNotification }); } - catch (IllegalAccessException e) { - e.printStackTrace(); + catch (IllegalAccessException e) { + // it's impossible add listeners that are not public } catch (InvocationTargetException e) { + // Since this is how Swing handles Exceptions that get thrown on listeners, + // it's probably ok to do it here. e.printStackTrace(); } } @@ -269,7 +282,7 @@ Iterator it = listenersMap.keySet().iterator(); while (it.hasNext()) { - CompoundKey key = (CompoundKey) it.next(); + NotificationKey key = (NotificationKey) it.next(); if ((name == null) || (name == key.name())) { if ((object == null) || (object == key.get())) { result.add(key); @@ -292,7 +305,7 @@ Iterator it = list.iterator(); while (it.hasNext()) { - Object observer = ((CompoundValue) it.next()).get(); + Object observer = ((NotificationTarget) it.next()).get(); if ((observer == null) || (listener == observer)) { it.remove(); } @@ -304,24 +317,24 @@ } protected void processKeyQueue() { - CompoundKey key; - while ((key = (CompoundKey) keyQueue.poll()) != null) { + NotificationKey key; + while ((key = (NotificationKey) keyQueue.poll()) != null) { listenersMap.remove(key); } } - protected static class CompoundKey extends WeakReference { + protected static class NotificationKey extends WeakReference { private Object name; private int hashCode; - public CompoundKey(Object aName, Object anObject) { + public NotificationKey(Object aName, Object anObject) { super(anObject); name = aName; hashCode = aName.hashCode() + anObject.hashCode(); } - public CompoundKey(Object aName, Object anObject, ReferenceQueue aQueue) { + public NotificationKey(Object aName, Object anObject, ReferenceQueue aQueue) { super(anObject, aQueue); name = aName; hashCode = aName.hashCode() + anObject.hashCode(); @@ -338,7 +351,7 @@ public boolean equals(Object anObject) { if (this == anObject) return true; - CompoundKey key = (CompoundKey) anObject; + NotificationKey key = (NotificationKey) anObject; if (name == key.name || (name != null && name.equals(key.name))) { Object object = get(); if (object != null) { @@ -355,12 +368,12 @@ } } - protected static class CompoundValue extends WeakReference { + protected static class NotificationTarget extends WeakReference { protected int hashCode; protected Method method; - public CompoundValue(Object object, Method method) { + public NotificationTarget(Object object, Method method) { super(object); hashCode = object.hashCode(); this.method = method; @@ -377,7 +390,7 @@ public boolean equals(Object object) { if (this == object) return true; - CompoundValue value = (CompoundValue) object; + NotificationTarget value = (NotificationTarget) object; if (method == value.method || (method != null && method.equals(value.method))) { Object o = get(); if (o != null) { diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java index 28a3298..611f312 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PStyledText.java @@ -46,6 +46,7 @@ import java.util.StringTokenizer; import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.Document; import javax.swing.text.Element; @@ -138,71 +139,75 @@ int pos = 0; // First get the actual text and stick it in an Attributed String + + stringContents = new ArrayList(); + pEnds = new ArrayList(); + + String documentString; try { + documentString = document.getText(0, document.getLength()); + } + catch (BadLocationException e) { + // Since this the location we're providing comes from directly + // querying the document, this is impossible in a single threaded model + return; + } + + StringTokenizer tokenizer = new StringTokenizer(documentString, "\n", true); - stringContents = new ArrayList(); - pEnds = new ArrayList(); + // lastNewLine is used to detect the case when two newlines follow + // in direct succession + // & lastNewLine should be true to start in case the first character + // is a newline + boolean lastNewLine = true; + for (int i = 0; tokenizer.hasMoreTokens(); i++) { + String token = tokenizer.nextToken(); - String s = document.getText(0, document.getLength()); - StringTokenizer tokenizer = new StringTokenizer(s, "\n", true); - - // lastNewLine is used to detect the case when two newlines follow - // in direct succession - // & lastNewLine should be true to start in case the first character - // is a newline - boolean lastNewLine = true; - for (int i = 0; tokenizer.hasMoreTokens(); i++) { - String token = tokenizer.nextToken(); - - // If the token - if (token.equals("\n")) { - if (lastNewLine) { - stringContents.add(new AttributedString(" ")); - pEnds.add(new RunInfo(pos, pos + 1)); - - pos = pos + 1; - - lastNewLine = true; - } - else { - pos = pos + 1; - - lastNewLine = true; - } - } - // If the token is empty - create an attributed string with a - // single space - // since LineBreakMeasurers don't work with an empty string - // - note that this case should only arise if the document is - // empty - else if (token.equals("")) { + // If the token + if (token.equals("\n")) { + if (lastNewLine) { stringContents.add(new AttributedString(" ")); - pEnds.add(new RunInfo(pos, pos)); + pEnds.add(new RunInfo(pos, pos + 1)); - lastNewLine = false; + pos = pos + 1; + + lastNewLine = true; } - // This is the normal case - where we have some text else { - stringContents.add(new AttributedString(token)); - pEnds.add(new RunInfo(pos, pos + token.length())); + pos = pos + 1; - // Increment the position - pos = pos + token.length(); - - lastNewLine = false; + lastNewLine = true; } } - - // Add one more newline if the last character was a newline - if (lastNewLine) { + // If the token is empty - create an attributed string with a + // single space + // since LineBreakMeasurers don't work with an empty string + // - note that this case should only arise if the document is + // empty + else if (token.equals("")) { stringContents.add(new AttributedString(" ")); - pEnds.add(new RunInfo(pos, pos + 1)); + pEnds.add(new RunInfo(pos, pos)); + + lastNewLine = false; + } + // This is the normal case - where we have some text + else { + stringContents.add(new AttributedString(token)); + pEnds.add(new RunInfo(pos, pos + token.length())); + + // Increment the position + pos = pos + token.length(); lastNewLine = false; } } - catch (Exception e) { - e.printStackTrace(); + + // Add one more newline if the last character was a newline + if (lastNewLine) { + stringContents.add(new AttributedString(" ")); + pEnds.add(new RunInfo(pos, pos + 1)); + + lastNewLine = false; } // The default style context - which will be reused diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java index d875e93..7d19f5d 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingEventHandler.java @@ -359,14 +359,8 @@ } private void cameraToLocal(PCamera topCamera, Point2D pt, PNode node) { - AffineTransform inverse = null; - try { - inverse = topCamera.getViewTransform().createInverse(); - } - catch (NoninvertibleTransformException e) { - e.printStackTrace(); - } - + AffineTransform inverse = topCamera.getViewTransform().createInverse(); + /* * Only apply the camera's view transform when this node is a descendant * of PLayer @@ -413,22 +407,7 @@ new Exception("PInputEvent.getSourceSwingEvent was not a MouseEvent. Actual event: " + sourceSwingEvent + ", class=" + sourceSwingEvent.getClass().getName()).printStackTrace(); } - } - - /* - * if( !( EventQueue.getCurrentEvent() instanceof MouseEvent ) ) { new - * Exception( - * "EventQueue.getCurrentEvent was not a MouseEvent, consider making PInputEvent.getSourceSwingEvent public. Actual event: " - * + EventQueue.getCurrentEvent() + ", class=" + - * EventQueue.getCurrentEvent().getClass().getName() - * ).printStackTrace(); } if( aEvent.isMouseEvent() && - * EventQueue.getCurrentEvent() instanceof MouseEvent ) { MouseEvent - * sourceSwingEvent = (MouseEvent)EventQueue.getCurrentEvent(); - * PSwingMouseEvent pSwingMouseEvent = - * PSwingMouseEvent.createMouseEvent( sourceSwingEvent.getID(), - * sourceSwingEvent, aEvent ); if( !recursing ) { recursing = true; - * dispatchEvent( pSwingMouseEvent, aEvent ); recursing = false; } } - */ + } } /**