diff --git a/extras/pom.xml b/extras/pom.xml
index 8c4204f..213c43d 100644
--- a/extras/pom.xml
+++ b/extras/pom.xml
@@ -1,53 +1,53 @@
* Knots are used to determine when in time the activity should move from state * to state. Knot values should be increasing in value from 0 to 1 inclusive. * This class is based on the Java 3D PathInterpolator object, see that class * documentation for more information on the basic concepts used in this classes * design. + *
** See PPositionPathActivity for a concrete path activity that will animate * through a list of points. - *
- * @version 1.0 + *
+ * + * @version 1.0 * @author Jesse Grosjean */ public abstract class PPathActivity extends PInterpolatingActivity { - - protected float[] knots; - public PPathActivity(long duration, long stepRate, float[] knots) { - this(duration, stepRate, 0, PInterpolatingActivity.SOURCE_TO_DESTINATION, knots); - } - - public PPathActivity(long duration, long stepRate, int loopCount, int mode, float[] knots) { - super(duration, stepRate, loopCount, mode); - setKnots(knots); - } - - public int getKnotsLength() { - return knots.length; - } - - public void setKnots(float[] knots) { - this.knots = knots; - } - - public float[] getKnots() { - return knots; - } + protected float[] knots; - public void setKnot(int index, float knot) { - knots[index] = knot; - } - - public float getKnot(int index) { - return knots[index]; - } - - public void setRelativeTargetValue(float zeroToOne) { - int currentKnotIndex = 0; - - while (zeroToOne > knots[currentKnotIndex]) { - currentKnotIndex++; - } + public PPathActivity(long duration, long stepRate, float[] knots) { + this(duration, stepRate, 0, PInterpolatingActivity.SOURCE_TO_DESTINATION, knots); + } - int startKnot = currentKnotIndex - 1; - int endKnot = currentKnotIndex; - - if (startKnot < 0) startKnot = 0; - if (endKnot > getKnotsLength() - 1) endKnot = getKnotsLength() - 1; - - float currentRange = knots[endKnot] - knots[startKnot]; - float currentPointOnRange = zeroToOne - knots[startKnot]; - float normalizedPointOnRange = currentPointOnRange; - - if (currentRange != 0) { - normalizedPointOnRange = currentPointOnRange / currentRange; - } - - setRelativeTargetValue(normalizedPointOnRange, startKnot, endKnot); - } - - public abstract void setRelativeTargetValue(float zeroToOne, int startKnot, int endKnot); + public PPathActivity(long duration, long stepRate, int loopCount, int mode, float[] knots) { + super(duration, stepRate, loopCount, mode); + setKnots(knots); + } + + public int getKnotsLength() { + return knots.length; + } + + public void setKnots(float[] knots) { + this.knots = knots; + } + + public float[] getKnots() { + return knots; + } + + public void setKnot(int index, float knot) { + knots[index] = knot; + } + + public float getKnot(int index) { + return knots[index]; + } + + public void setRelativeTargetValue(float zeroToOne) { + int currentKnotIndex = 0; + + while (zeroToOne > knots[currentKnotIndex]) { + currentKnotIndex++; + } + + int startKnot = currentKnotIndex - 1; + int endKnot = currentKnotIndex; + + if (startKnot < 0) + startKnot = 0; + if (endKnot > getKnotsLength() - 1) + endKnot = getKnotsLength() - 1; + + float currentRange = knots[endKnot] - knots[startKnot]; + float currentPointOnRange = zeroToOne - knots[startKnot]; + float normalizedPointOnRange = currentPointOnRange; + + if (currentRange != 0) { + normalizedPointOnRange = currentPointOnRange / currentRange; + } + + setRelativeTargetValue(normalizedPointOnRange, startKnot, endKnot); + } + + public abstract void setRelativeTargetValue(float zeroToOne, int startKnot, int endKnot); } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java b/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java index f476913..bc63b24 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/activities/PPositionPathActivity.java @@ -38,113 +38,114 @@ /** * PPositionPathActivity animates through a sequence of points. - *- * @version 1.0 + * + * @version 1.0 * @author Jesse Grosjean */ public class PPositionPathActivity extends PPathActivity { - protected Point2D[] positions; - protected Target target; + protected Point2D[] positions; + protected Target target; - public interface Target { - public void setPosition(double x, double y); - } + public interface Target { + public void setPosition(double x, double y); + } - public PPositionPathActivity(long duration, long stepRate, Target aTarget) { - this(duration, stepRate, aTarget, null, null); - } + public PPositionPathActivity(long duration, long stepRate, Target aTarget) { + this(duration, stepRate, aTarget, null, null); + } - public PPositionPathActivity(long duration, long stepRate, Target aTarget, float[] knots, Point2D[] positions) { - this(duration, stepRate, 1, PInterpolatingActivity.SOURCE_TO_DESTINATION, aTarget, knots, positions); - } + public PPositionPathActivity(long duration, long stepRate, Target aTarget, float[] knots, Point2D[] positions) { + this(duration, stepRate, 1, PInterpolatingActivity.SOURCE_TO_DESTINATION, aTarget, knots, positions); + } - public PPositionPathActivity(long duration, long stepRate, int loopCount, int mode, Target aTarget, float[] knots, Point2D[] positions) { - super(duration, stepRate, loopCount, mode, knots); - target = aTarget; - this.positions = positions; - } + public PPositionPathActivity(long duration, long stepRate, int loopCount, int mode, Target aTarget, float[] knots, + Point2D[] positions) { + super(duration, stepRate, loopCount, mode, knots); + target = aTarget; + this.positions = positions; + } - protected boolean isAnimation() { - return true; - } + protected boolean isAnimation() { + return true; + } - public Point2D[] getPositions() { - return positions; - } + public Point2D[] getPositions() { + return positions; + } - public Point2D getPosition(int index) { - return positions[index]; - } + public Point2D getPosition(int index) { + return positions[index]; + } - public void setPositions(Point2D[] positions) { - this.positions = positions; - } + public void setPositions(Point2D[] positions) { + this.positions = positions; + } - public void setPosition(int index, Point2D position) { - positions[index] = position; - } + public void setPosition(int index, Point2D position) { + positions[index] = position; + } - public void setPositions(GeneralPath path) { - PathIterator pi = path.getPathIterator(null, 1); - ArrayList points = new ArrayList(); - float point[] = new float[6]; - float distanceSum = 0; - float lastMoveToX = 0; - float lastMoveToY = 0; - - while (!pi.isDone()) { - int type = pi.currentSegment(point); - - switch (type) { - case PathIterator.SEG_MOVETO: - points.add(new Point2D.Float(point[0], point[1])); - lastMoveToX = point[0]; - lastMoveToY = point[1]; - break; + public void setPositions(GeneralPath path) { + PathIterator pi = path.getPathIterator(null, 1); + ArrayList points = new ArrayList(); + float point[] = new float[6]; + float distanceSum = 0; + float lastMoveToX = 0; + float lastMoveToY = 0; - case PathIterator.SEG_LINETO: - points.add(new Point2D.Float(point[0], point[1])); - break; + while (!pi.isDone()) { + int type = pi.currentSegment(point); - case PathIterator.SEG_CLOSE: - points.add(new Point2D.Float(lastMoveToX, lastMoveToY)); - break; - - case PathIterator.SEG_QUADTO: - case PathIterator.SEG_CUBICTO: - throw new RuntimeException(); - } - - if (points.size() > 1) { - Point2D last = (Point2D) points.get(points.size() - 2); - Point2D current = (Point2D) points.get(points.size() - 1); - distanceSum += last.distance(current); - } - - pi.next(); - } - - int size = points.size(); - Point2D newPositions[] = new Point2D[size]; - float newKnots[] = new float[size]; - - for (int i = 0; i < size; i++) { - newPositions[i] = (Point2D) points.get(i); - if (i > 0) { - float dist = (float) newPositions[i - 1].distance(newPositions[i]); - newKnots[i] = newKnots[i - 1] + (dist / distanceSum); - } - } - - setPositions(newPositions); - setKnots(newKnots); - } - - public void setRelativeTargetValue(float zeroToOne, int startKnot, int endKnot) { - Point2D start = getPosition(startKnot); - Point2D end = getPosition(endKnot); - target.setPosition(start.getX() + (zeroToOne * (end.getX() - start.getX())), - start.getY() + (zeroToOne * (end.getY() - start.getY()))); - } + switch (type) { + case PathIterator.SEG_MOVETO: + points.add(new Point2D.Float(point[0], point[1])); + lastMoveToX = point[0]; + lastMoveToY = point[1]; + break; + + case PathIterator.SEG_LINETO: + points.add(new Point2D.Float(point[0], point[1])); + break; + + case PathIterator.SEG_CLOSE: + points.add(new Point2D.Float(lastMoveToX, lastMoveToY)); + break; + + case PathIterator.SEG_QUADTO: + case PathIterator.SEG_CUBICTO: + throw new RuntimeException(); + } + + if (points.size() > 1) { + Point2D last = (Point2D) points.get(points.size() - 2); + Point2D current = (Point2D) points.get(points.size() - 1); + distanceSum += last.distance(current); + } + + pi.next(); + } + + int size = points.size(); + Point2D newPositions[] = new Point2D[size]; + float newKnots[] = new float[size]; + + for (int i = 0; i < size; i++) { + newPositions[i] = (Point2D) points.get(i); + if (i > 0) { + float dist = (float) newPositions[i - 1].distance(newPositions[i]); + newKnots[i] = newKnots[i - 1] + (dist / distanceSum); + } + } + + setPositions(newPositions); + setKnots(newKnots); + } + + public void setRelativeTargetValue(float zeroToOne, int startKnot, int endKnot) { + Point2D start = getPosition(startKnot); + Point2D end = getPosition(endKnot); + target.setPosition(start.getX() + (zeroToOne * (end.getX() - start.getX())), start.getY() + + (zeroToOne * (end.getY() - start.getY()))); + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java index 38ed096..fa21ba0 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PNavigationEventHandler.java @@ -51,367 +51,376 @@ import edu.umd.cs.piccolo.util.PDimension; /** - * PNavigationEventHandler implements simple focus based navigation. Uses + * PNavigationEventHandler implements simple focus based navigation. Uses * mouse button one or the arrow keys to set a new focus. Animates the canvas - * view to keep the focus node on the screen and at 100 percent scale with minimal - * view movement. - *
+ * view to keep the focus node on the screen and at 100 percent scale with + * minimal view movement. + * * @version 1.0 * @author Jesse Grosjean */ public class PNavigationEventHandler extends PBasicInputEventHandler { - public static final int NORTH = 0; - public static final int SOUTH = 1; - public static final int EAST = 2; - public static final int WEST = 3; - public static final int IN = 4; - public static final int OUT = 5; - - private static Hashtable NODE_TO_GLOBAL_NODE_CENTER_MAPPING = new Hashtable(); - - private PNode focusNode; - private PActivity navigationActivity; - - public PNavigationEventHandler() { - super(); - setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK)); - } + public static final int NORTH = 0; + public static final int SOUTH = 1; + public static final int EAST = 2; + public static final int WEST = 3; + public static final int IN = 4; + public static final int OUT = 5; - //**************************************************************** - // Focus Change Events. - //**************************************************************** - - public void keyPressed(PInputEvent e) { - PNode oldLocation = focusNode; - - switch (e.getKeyCode()) { - case KeyEvent.VK_LEFT: - moveFocusLeft(e); - break; + private static Hashtable NODE_TO_GLOBAL_NODE_CENTER_MAPPING = new Hashtable(); - case KeyEvent.VK_RIGHT: - moveFocusRight(e); - break; + private PNode focusNode; + private PActivity navigationActivity; - case KeyEvent.VK_UP: - case KeyEvent.VK_PAGE_UP: - if (e.isAltDown()) { - moveFocusOut(e); - } else { - moveFocusUp(e); - } - break; + public PNavigationEventHandler() { + super(); + setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK)); + } - case KeyEvent.VK_DOWN: - case KeyEvent.VK_PAGE_DOWN: - if (e.isAltDown()) { - moveFocusIn(e); - } else { - moveFocusDown(e); - } - break; - } + // **************************************************************** + // Focus Change Events. + // **************************************************************** - if (focusNode != null && oldLocation != focusNode) { - directCameraViewToFocus(e.getCamera(), focusNode, 500); - } - } - - public void mousePressed(PInputEvent aEvent) { - moveFocusToMouseOver(aEvent); - - if (focusNode != null) { - directCameraViewToFocus(aEvent.getCamera(), focusNode, 500); - aEvent.getInputManager().setKeyboardFocus(aEvent.getPath()); - } - } - - //**************************************************************** - // Focus Movement - Moves the focus the specified direction. Left, - // right, up, down mean move the focus to the closest sibling of the - // current focus node that exists in that direction. Move in means - // move the focus to a child of the current focus, move out means - // move the focus to the parent of the current focus. - //**************************************************************** - - public void moveFocusDown(PInputEvent e) { - PNode n = getNeighborInDirection(SOUTH); + public void keyPressed(PInputEvent e) { + PNode oldLocation = focusNode; - if (n != null) { - focusNode = n; - } - } - - public void moveFocusIn(PInputEvent e) { - PNode n = getNeighborInDirection(IN); + switch (e.getKeyCode()) { + case KeyEvent.VK_LEFT: + moveFocusLeft(e); + break; - if (n != null) { - focusNode = n; - } - } - - public void moveFocusLeft(PInputEvent e) { - PNode n = getNeighborInDirection(WEST); + case KeyEvent.VK_RIGHT: + moveFocusRight(e); + break; - if (n != null) { - focusNode = n; - } - } - - public void moveFocusOut(PInputEvent e) { - PNode n = getNeighborInDirection(OUT); + case KeyEvent.VK_UP: + case KeyEvent.VK_PAGE_UP: + if (e.isAltDown()) { + moveFocusOut(e); + } + else { + moveFocusUp(e); + } + break; - if (n != null) { - focusNode = n; - } - } - - public void moveFocusRight(PInputEvent e) { - PNode n = getNeighborInDirection(EAST); + case KeyEvent.VK_DOWN: + case KeyEvent.VK_PAGE_DOWN: + if (e.isAltDown()) { + moveFocusIn(e); + } + else { + moveFocusDown(e); + } + break; + } - if (n != null) { - focusNode = n; - } - } - - public void moveFocusUp(PInputEvent e) { - PNode n = getNeighborInDirection(NORTH); + if (focusNode != null && oldLocation != focusNode) { + directCameraViewToFocus(e.getCamera(), focusNode, 500); + } + } - if (n != null) { - focusNode = n; - } - } + public void mousePressed(PInputEvent aEvent) { + moveFocusToMouseOver(aEvent); - public void moveFocusToMouseOver(PInputEvent e) { - PNode focus = e.getPickedNode(); - if (!(focus instanceof PCamera)) { - focusNode = focus; - } - } - - public PNode getNeighborInDirection(int aDirection) { - if (focusNode == null) return null; + if (focusNode != null) { + directCameraViewToFocus(aEvent.getCamera(), focusNode, 500); + aEvent.getInputManager().setKeyboardFocus(aEvent.getPath()); + } + } - NODE_TO_GLOBAL_NODE_CENTER_MAPPING.clear(); + // **************************************************************** + // Focus Movement - Moves the focus the specified direction. Left, + // right, up, down mean move the focus to the closest sibling of the + // current focus node that exists in that direction. Move in means + // move the focus to a child of the current focus, move out means + // move the focus to the parent of the current focus. + // **************************************************************** - Point2D highlightCenter = focusNode.getGlobalFullBounds().getCenter2D(); - NODE_TO_GLOBAL_NODE_CENTER_MAPPING.put(focusNode, highlightCenter); + public void moveFocusDown(PInputEvent e) { + PNode n = getNeighborInDirection(SOUTH); - List l = getNeighbors(); - sortNodesByDistanceFromPoint(l, highlightCenter); + if (n != null) { + focusNode = n; + } + } - Iterator i = l.iterator(); - while (i.hasNext()) { - PNode each = (PNode) i.next(); - if (nodeIsNeighborInDirection(each, aDirection)) { - return each; - } - } + public void moveFocusIn(PInputEvent e) { + PNode n = getNeighborInDirection(IN); - return null; - } - - public List getNeighbors() { - ArrayList result = new ArrayList(); - - if (focusNode == null) return result; - if (focusNode.getParent() == null) return result; + if (n != null) { + focusNode = n; + } + } - PNode focusParent = focusNode.getParent(); + public void moveFocusLeft(PInputEvent e) { + PNode n = getNeighborInDirection(WEST); - Iterator i = focusParent.getChildrenIterator(); + if (n != null) { + focusNode = n; + } + } - while (i.hasNext()) { - PNode each = (PNode) i.next(); - if (each != focusNode && each.getPickable()) { - result.add(each); - } - } + public void moveFocusOut(PInputEvent e) { + PNode n = getNeighborInDirection(OUT); - result.add(focusParent); + if (n != null) { + focusNode = n; + } + } - i = focusNode.getChildrenIterator(); - while (i.hasNext()) { - result.add(i.next()); - } + public void moveFocusRight(PInputEvent e) { + PNode n = getNeighborInDirection(EAST); - return result; - } + if (n != null) { + focusNode = n; + } + } - public boolean nodeIsNeighborInDirection(PNode aNode, int aDirection) { - switch (aDirection) { - case IN: { - return aNode.isDescendentOf(focusNode); - } + public void moveFocusUp(PInputEvent e) { + PNode n = getNeighborInDirection(NORTH); - case OUT: { - return aNode.isAncestorOf(focusNode); - } - - default: { - if (aNode.isAncestorOf(focusNode) || aNode.isDescendentOf(focusNode)) { - return false; - } - } - } + if (n != null) { + focusNode = n; + } + } - Point2D highlightCenter = (Point2D) NODE_TO_GLOBAL_NODE_CENTER_MAPPING.get(focusNode); - Point2D nodeCenter = (Point2D) NODE_TO_GLOBAL_NODE_CENTER_MAPPING.get(aNode); + public void moveFocusToMouseOver(PInputEvent e) { + PNode focus = e.getPickedNode(); + if (!(focus instanceof PCamera)) { + focusNode = focus; + } + } - double ytest1 = nodeCenter.getX() - highlightCenter.getX() + highlightCenter.getY(); - double ytest2 = -nodeCenter.getX() + highlightCenter.getX() + highlightCenter.getY(); + public PNode getNeighborInDirection(int aDirection) { + if (focusNode == null) + return null; - switch (aDirection) { - case NORTH: { - if (nodeCenter.getY() < highlightCenter.getY()) { - if (nodeCenter.getY() < ytest1 && nodeCenter.getY() < ytest2) { - return true; - } - } - break; - } + NODE_TO_GLOBAL_NODE_CENTER_MAPPING.clear(); - case EAST: { - if (nodeCenter.getX() > highlightCenter.getX()) { - if (nodeCenter.getY() < ytest1 && nodeCenter.getY() > ytest2) { - return true; - } - } - break; - } + Point2D highlightCenter = focusNode.getGlobalFullBounds().getCenter2D(); + NODE_TO_GLOBAL_NODE_CENTER_MAPPING.put(focusNode, highlightCenter); - case SOUTH: { - if (nodeCenter.getY() > highlightCenter.getY()) { - if (nodeCenter.getY() > ytest1 && nodeCenter.getY() > ytest2) { - return true; - } - } - break; - } - case WEST: { - if (nodeCenter.getX() < highlightCenter.getX()) { - if (nodeCenter.getY() > ytest1 && nodeCenter.getY() < ytest2) { - return true; - } - } - break; - } - } - return false; - } - - public void sortNodesByDistanceFromPoint(List aNodesList, final Point2D aPoint) { - Collections.sort(aNodesList, new Comparator() { - public int compare(Object o1, Object o2) { - PNode each1 = (PNode) o1; - PNode each2 = (PNode) o2; - Point2D each1Center = each1.getGlobalFullBounds().getCenter2D(); - Point2D each2Center = each2.getGlobalFullBounds().getCenter2D(); + List l = getNeighbors(); + sortNodesByDistanceFromPoint(l, highlightCenter); - NODE_TO_GLOBAL_NODE_CENTER_MAPPING.put(each1, each1Center); - NODE_TO_GLOBAL_NODE_CENTER_MAPPING.put(each2, each2Center); + Iterator i = l.iterator(); + while (i.hasNext()) { + PNode each = (PNode) i.next(); + if (nodeIsNeighborInDirection(each, aDirection)) { + return each; + } + } - double distance1 = aPoint.distance(each1Center); - double distance2 = aPoint.distance(each2Center); + return null; + } - if (distance1 < distance2) { - return -1; - } else if (distance1 == distance2) { - return 0; - } else { - return 1; - } - } - }); - } - - //**************************************************************** - // Canvas Movement - The canvas view is updated so that the current - // focus remains visible on the screen at 100 percent scale. - //**************************************************************** + public List getNeighbors() { + ArrayList result = new ArrayList(); - protected PActivity animateCameraViewTransformTo(final PCamera aCamera, AffineTransform aTransform, int duration) { - boolean wasOldAnimation = false; - - // first stop any old animations. - if (navigationActivity != null) { - navigationActivity.terminate(); - wasOldAnimation = true; - } - - if (duration == 0) { - aCamera.setViewTransform(aTransform); - return null; - } + if (focusNode == null) + return result; + if (focusNode.getParent() == null) + return result; - AffineTransform source = aCamera.getViewTransformReference(); + PNode focusParent = focusNode.getParent(); - if (!source.equals(aTransform)) { - navigationActivity = aCamera.animateViewToTransform(aTransform, duration); - ((PTransformActivity)navigationActivity).setSlowInSlowOut(!wasOldAnimation); - return navigationActivity; - } - - return null; - } + Iterator i = focusParent.getChildrenIterator(); - public PActivity directCameraViewToFocus(PCamera aCamera, PNode aFocusNode, int duration) { - focusNode = aFocusNode; - AffineTransform originalViewTransform = aCamera.getViewTransform(); + while (i.hasNext()) { + PNode each = (PNode) i.next(); + if (each != focusNode && each.getPickable()) { + result.add(each); + } + } - // Scale the canvas to include - PDimension d = new PDimension(1, 0); - focusNode.globalToLocal(d); - - double scaleFactor = d.getWidth() / aCamera.getViewScale(); - Point2D scalePoint = focusNode.getGlobalFullBounds().getCenter2D(); - if (scaleFactor != 1) { - aCamera.scaleViewAboutPoint(scaleFactor, scalePoint.getX(), scalePoint.getY()); - } - - // Pan the canvas to include the view bounds with minimal canvas - // movement. - aCamera.animateViewToPanToBounds(focusNode.getGlobalFullBounds(), 0); + result.add(focusParent); - // Get rid of any white space. The canvas may be panned and - // zoomed in to do this. But make sure not stay constrained by max - // magnification. - //fillViewWhiteSpace(aCamera); + i = focusNode.getChildrenIterator(); + while (i.hasNext()) { + result.add(i.next()); + } - AffineTransform resultingTransform = aCamera.getViewTransform(); - aCamera.setViewTransform(originalViewTransform); + return result; + } - // Animate the canvas so that it ends up with the given - // view transform. - return animateCameraViewTransformTo(aCamera, resultingTransform, duration); - } + public boolean nodeIsNeighborInDirection(PNode aNode, int aDirection) { + switch (aDirection) { + case IN: { + return aNode.isDescendentOf(focusNode); + } - protected void fillViewWhiteSpace(PCamera aCamera) { - PBounds rootBounds = aCamera.getRoot().getFullBoundsReference(); - PBounds viewBounds = aCamera.getViewBounds(); + case OUT: { + return aNode.isAncestorOf(focusNode); + } - if (!rootBounds.contains(aCamera.getViewBounds())) { - aCamera.animateViewToPanToBounds(rootBounds, 0); - aCamera.animateViewToPanToBounds(focusNode.getGlobalFullBounds(), 0); + default: { + if (aNode.isAncestorOf(focusNode) || aNode.isDescendentOf(focusNode)) { + return false; + } + } + } - // center content. - double dx = 0; - double dy = 0; - viewBounds = aCamera.getViewBounds(); + Point2D highlightCenter = (Point2D) NODE_TO_GLOBAL_NODE_CENTER_MAPPING.get(focusNode); + Point2D nodeCenter = (Point2D) NODE_TO_GLOBAL_NODE_CENTER_MAPPING.get(aNode); - if (viewBounds.getWidth() > rootBounds.getWidth()) { // then center along x axis. - double boundsCenterX = rootBounds.getMinX() + (rootBounds.getWidth() / 2); - double viewBoundsCenterX = viewBounds.getMinX() + (viewBounds.getWidth() / 2); - dx = viewBoundsCenterX - boundsCenterX; - } + double ytest1 = nodeCenter.getX() - highlightCenter.getX() + highlightCenter.getY(); + double ytest2 = -nodeCenter.getX() + highlightCenter.getX() + highlightCenter.getY(); - if (viewBounds.getHeight() > rootBounds.getHeight()) { // then center along y axis. - double boundsCenterY = rootBounds.getMinY() + (rootBounds.getHeight() / 2); - double viewBoundsCenterY = viewBounds.getMinY() + (viewBounds.getHeight() / 2); - dy = viewBoundsCenterY - boundsCenterY; - } - aCamera.translateView(dx, dy); - } - } + switch (aDirection) { + case NORTH: { + if (nodeCenter.getY() < highlightCenter.getY()) { + if (nodeCenter.getY() < ytest1 && nodeCenter.getY() < ytest2) { + return true; + } + } + break; + } + + case EAST: { + if (nodeCenter.getX() > highlightCenter.getX()) { + if (nodeCenter.getY() < ytest1 && nodeCenter.getY() > ytest2) { + return true; + } + } + break; + } + + case SOUTH: { + if (nodeCenter.getY() > highlightCenter.getY()) { + if (nodeCenter.getY() > ytest1 && nodeCenter.getY() > ytest2) { + return true; + } + } + break; + } + case WEST: { + if (nodeCenter.getX() < highlightCenter.getX()) { + if (nodeCenter.getY() > ytest1 && nodeCenter.getY() < ytest2) { + return true; + } + } + break; + } + } + return false; + } + + public void sortNodesByDistanceFromPoint(List aNodesList, final Point2D aPoint) { + Collections.sort(aNodesList, new Comparator() { + public int compare(Object o1, Object o2) { + PNode each1 = (PNode) o1; + PNode each2 = (PNode) o2; + Point2D each1Center = each1.getGlobalFullBounds().getCenter2D(); + Point2D each2Center = each2.getGlobalFullBounds().getCenter2D(); + + NODE_TO_GLOBAL_NODE_CENTER_MAPPING.put(each1, each1Center); + NODE_TO_GLOBAL_NODE_CENTER_MAPPING.put(each2, each2Center); + + double distance1 = aPoint.distance(each1Center); + double distance2 = aPoint.distance(each2Center); + + if (distance1 < distance2) { + return -1; + } + else if (distance1 == distance2) { + return 0; + } + else { + return 1; + } + } + }); + } + + // **************************************************************** + // Canvas Movement - The canvas view is updated so that the current + // focus remains visible on the screen at 100 percent scale. + // **************************************************************** + + protected PActivity animateCameraViewTransformTo(final PCamera aCamera, AffineTransform aTransform, int duration) { + boolean wasOldAnimation = false; + + // first stop any old animations. + if (navigationActivity != null) { + navigationActivity.terminate(); + wasOldAnimation = true; + } + + if (duration == 0) { + aCamera.setViewTransform(aTransform); + return null; + } + + AffineTransform source = aCamera.getViewTransformReference(); + + if (!source.equals(aTransform)) { + navigationActivity = aCamera.animateViewToTransform(aTransform, duration); + ((PTransformActivity) navigationActivity).setSlowInSlowOut(!wasOldAnimation); + return navigationActivity; + } + + return null; + } + + public PActivity directCameraViewToFocus(PCamera aCamera, PNode aFocusNode, int duration) { + focusNode = aFocusNode; + AffineTransform originalViewTransform = aCamera.getViewTransform(); + + // Scale the canvas to include + PDimension d = new PDimension(1, 0); + focusNode.globalToLocal(d); + + double scaleFactor = d.getWidth() / aCamera.getViewScale(); + Point2D scalePoint = focusNode.getGlobalFullBounds().getCenter2D(); + if (scaleFactor != 1) { + aCamera.scaleViewAboutPoint(scaleFactor, scalePoint.getX(), scalePoint.getY()); + } + + // Pan the canvas to include the view bounds with minimal canvas + // movement. + aCamera.animateViewToPanToBounds(focusNode.getGlobalFullBounds(), 0); + + // Get rid of any white space. The canvas may be panned and + // zoomed in to do this. But make sure not stay constrained by max + // magnification. + // fillViewWhiteSpace(aCamera); + + AffineTransform resultingTransform = aCamera.getViewTransform(); + aCamera.setViewTransform(originalViewTransform); + + // Animate the canvas so that it ends up with the given + // view transform. + return animateCameraViewTransformTo(aCamera, resultingTransform, duration); + } + + protected void fillViewWhiteSpace(PCamera aCamera) { + PBounds rootBounds = aCamera.getRoot().getFullBoundsReference(); + PBounds viewBounds = aCamera.getViewBounds(); + + if (!rootBounds.contains(aCamera.getViewBounds())) { + aCamera.animateViewToPanToBounds(rootBounds, 0); + aCamera.animateViewToPanToBounds(focusNode.getGlobalFullBounds(), 0); + + // center content. + double dx = 0; + double dy = 0; + viewBounds = aCamera.getViewBounds(); + + if (viewBounds.getWidth() > rootBounds.getWidth()) { + // then center along x axis. + double boundsCenterX = rootBounds.getMinX() + (rootBounds.getWidth() / 2); + double viewBoundsCenterX = viewBounds.getMinX() + (viewBounds.getWidth() / 2); + dx = viewBoundsCenterX - boundsCenterX; + } + + if (viewBounds.getHeight() > rootBounds.getHeight()) { + // then center along y axis. + double boundsCenterY = rootBounds.getMinY() + (rootBounds.getHeight() / 2); + double viewBoundsCenterY = viewBounds.getMinY() + (viewBounds.getHeight() / 2); + dy = viewBoundsCenterY - boundsCenterY; + } + aCamera.translateView(dx, dy); + } + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PNotification.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PNotification.java index 0fa8e4e..1f3acff 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/event/PNotification.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PNotification.java @@ -39,54 +39,55 @@ /** * PNotification objects encapsulate information so that it can be - * broadcast to other objects by a PNotificationCenter. A PNotification contains a - * name, an object, and an optional properties map. The name is a tag + * broadcast to other objects by a PNotificationCenter. A PNotification contains + * a name, an object, and an optional properties map. The name is a tag * identifying the notification. The object is any object that the poster of the * notification wants to send to observers of that notification (typically, it * is the object that posted the notification). The properties map stores other * related objects, if any. - *
+ *
* You don't usually create your own notifications directly. The - * PNotificationCenter method postNotification() allow you to conveniently post a - * notification without creating it first. - *
+ * PNotificationCenter method postNotification() allow you to conveniently post + * a notification without creating it first. + *
+ * * @author Jesse Grosjean */ public class PNotification { - - protected String name; - protected Object source; - protected Map properties; - public PNotification(String name, Object source, Map properties) { - this.name = name; - this.source = source; - this.properties = properties; - } + protected String name; + protected Object source; + protected Map properties; - /** - * Return the name of the notification. This is the same as the name used to - * register with the notfication center. - */ - public String getName() { - return name; - } + public PNotification(String name, Object source, Map properties) { + this.name = name; + this.source = source; + this.properties = properties; + } - /** - * Return the object associated with this notification. This is most often - * the same object that posted the notfication. It may be null. - */ - public Object getObject() { - return source; - } + /** + * Return the name of the notification. This is the same as the name used to + * register with the notfication center. + */ + public String getName() { + return name; + } - /** - * Return a property associated with the notfication. - */ - public Object getProperty(Object key) { - if (properties != null) { - return properties.get(key); - } - return null; - } + /** + * Return the object associated with this notification. This is most often + * the same object that posted the notfication. It may be null. + */ + public Object getObject() { + return source; + } + + /** + * Return a property associated with the notfication. + */ + public Object getProperty(Object key) { + if (properties != null) { + return properties.get(key); + } + return null; + } } 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 f9a6325..9b7d9bd 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 @@ -52,325 +52,337 @@ * them to all interested listeners. Unlike standard Java events, the event * listeners don't need to know about the event source, and the event source * doesn't need to maintain the list of listeners. - *+ *
* Listeners of the notfications center are held by weak references. So the * notfication center will not create garbage collection problems as standard * java event listeners do. - *
+ *
+ * * @author Jesse Grosjean */ public class PNotificationCenter { - public static final Object NULL_MARKER = new Object(); + public static final Object NULL_MARKER = new Object(); - protected static PNotificationCenter DEFAULT_CENTER; + protected static PNotificationCenter DEFAULT_CENTER; - protected HashMap listenersMap; - protected ReferenceQueue keyQueue; + protected HashMap listenersMap; + protected ReferenceQueue keyQueue; - public static PNotificationCenter defaultCenter() { - if (DEFAULT_CENTER == null) { - DEFAULT_CENTER = new PNotificationCenter(); - } - return DEFAULT_CENTER; - } + public static PNotificationCenter defaultCenter() { + if (DEFAULT_CENTER == null) { + DEFAULT_CENTER = new PNotificationCenter(); + } + return DEFAULT_CENTER; + } - private PNotificationCenter() { - listenersMap = new HashMap(); - keyQueue = new ReferenceQueue(); - } + private PNotificationCenter() { + listenersMap = new HashMap(); + keyQueue = new ReferenceQueue(); + } - //**************************************************************** - // Add Listener Methods - //**************************************************************** + // **************************************************************** + // Add Listener Methods + // **************************************************************** - /** - * Registers the 'listener' to receive notifications with the name - * 'notificationName' and/or containing 'object'. When a matching - * notification is posted the callBackMethodName message will be sent to the - * listener with a single PNotification argument. If notificationName is null - * then the listener will receive all notifications with an object matching - * 'object'. If 'object' is null the listener will receive all notifications - * with the name 'notificationName'. - */ - public void addListener(Object listener, String callbackMethodName, String notificationName, Object object) { - processKeyQueue(); + /** + * Registers the 'listener' to receive notifications with the name + * 'notificationName' and/or containing 'object'. When a matching + * notification is posted the callBackMethodName message will be sent to the + * listener with a single PNotification argument. If notificationName is + * null then the listener will receive all notifications with an object + * matching 'object'. If 'object' is null the listener will receive all + * notifications with the name 'notificationName'. + */ + public void addListener(Object listener, String callbackMethodName, String notificationName, Object object) { + processKeyQueue(); - Object name = notificationName; - Method method = null; + Object name = notificationName; + Method method = null; - try { - method = listener.getClass().getMethod(callbackMethodName, new Class[] { PNotification.class }); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - return; - } - - if (name == null) name = NULL_MARKER; - if (object == null) object = NULL_MARKER; + try { + method = listener.getClass().getMethod(callbackMethodName, new Class[] { PNotification.class }); + } + catch (NoSuchMethodException e) { + e.printStackTrace(); + return; + } - Object key = new CompoundKey(name, object); - Object value = new CompoundValue(listener, method); + if (name == null) + name = NULL_MARKER; + if (object == null) + object = NULL_MARKER; - List list = (List) listenersMap.get(key); - if (list == null) { - list = new ArrayList(); - listenersMap.put(new CompoundKey(name, object, keyQueue), list); - } + Object key = new CompoundKey(name, object); + Object value = new CompoundValue(listener, method); - if (!list.contains(value)) { - list.add(value); - } - } + List list = (List) listenersMap.get(key); + if (list == null) { + list = new ArrayList(); + listenersMap.put(new CompoundKey(name, object, keyQueue), list); + } - //**************************************************************** - // Remove Listener Methods - //**************************************************************** + if (!list.contains(value)) { + list.add(value); + } + } - /** - * Removes the listener so that it no longer recives notfications from this - * notfication center. - */ - public void removeListener(Object listener) { - processKeyQueue(); + // **************************************************************** + // Remove Listener Methods + // **************************************************************** - Iterator i = new LinkedList(listenersMap.keySet()).iterator(); - while (i.hasNext()) { - removeListener(listener, i.next()); - } - } + /** + * Removes the listener so that it no longer recives notfications from this + * notfication center. + */ + public void removeListener(Object listener) { + processKeyQueue(); - /** - * Removes the listeners as the listener of notifications matching - * notificationName and object. If listener is null all listeners matching - * notificationName and object are removed. If notificationName is null the - * listener will be removed from all notifications containing the object. If - * the object is null then the listener will be removed from all - * notifications matching notficationName. - */ - public void removeListener(Object listener, String notificationName, Object object) { - processKeyQueue(); + Iterator i = new LinkedList(listenersMap.keySet()).iterator(); + while (i.hasNext()) { + removeListener(listener, i.next()); + } + } - List keys = matchingKeys(notificationName, object); - Iterator it = keys.iterator(); - while (it.hasNext()) { - removeListener(listener, it.next()); - } - } + /** + * Removes the listeners as the listener of notifications matching + * notificationName and object. If listener is null all listeners matching + * notificationName and object are removed. If notificationName is null the + * listener will be removed from all notifications containing the object. If + * the object is null then the listener will be removed from all + * notifications matching notficationName. + */ + public void removeListener(Object listener, String notificationName, Object object) { + processKeyQueue(); - //**************************************************************** - // Post PNotification Methods - //**************************************************************** + List keys = matchingKeys(notificationName, object); + Iterator it = keys.iterator(); + while (it.hasNext()) { + removeListener(listener, it.next()); + } + } - /** - * Post a new notfication with notificationName and object. The object is - * typically the object posting the notification. The object may be null. - */ - public void postNotification(String notificationName, Object object) { - postNotification(notificationName, object, null); - } + // **************************************************************** + // Post PNotification Methods + // **************************************************************** - /** - * Creates a notification with the name notificationName, associates it with - * the object, and posts it to this notification center. The object is - * typically the object posting the notification. It may be nil. - */ - public void postNotification(String notificationName, Object object, Map userInfo) { - postNotification(new PNotification(notificationName, object, userInfo)); - } + /** + * Post a new notfication with notificationName and object. The object is + * typically the object posting the notification. The object may be null. + */ + public void postNotification(String notificationName, Object object) { + postNotification(notificationName, object, null); + } - /** - * Post the notification to this notification center. Most often clients will - * instead use one of this classes convenience postNotifcations methods. - */ - public void postNotification(PNotification aNotification) { - List mergedListeners = new LinkedList(); - List listenersList; - - Object name = aNotification.getName(); - Object object = aNotification.getObject(); + /** + * Creates a notification with the name notificationName, associates it with + * the object, and posts it to this notification center. The object is + * typically the object posting the notification. It may be nil. + */ + public void postNotification(String notificationName, Object object, Map userInfo) { + postNotification(new PNotification(notificationName, object, userInfo)); + } - if (name != null) { - if (object != null) { // both are specified - listenersList = (List) listenersMap.get(new CompoundKey(name, object)); - if (listenersList != null) { - mergedListeners.addAll(listenersList); - } - listenersList = (List) listenersMap.get(new CompoundKey(name, NULL_MARKER)); - if (listenersList != null) { - mergedListeners.addAll(listenersList); - } - listenersList = (List) listenersMap.get(new CompoundKey(NULL_MARKER, object)); - if (listenersList != null) { - mergedListeners.addAll(listenersList); - } - } else { // object is null - listenersList = (List) listenersMap.get(new CompoundKey(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)); - if (listenersList != null) { - mergedListeners.addAll(listenersList); - } - } + /** + * Post the notification to this notification center. Most often clients + * will instead use one of this classes convenience postNotifcations + * methods. + */ + public void postNotification(PNotification aNotification) { + List mergedListeners = new LinkedList(); + List listenersList; - Object key = new CompoundKey(NULL_MARKER, NULL_MARKER); - listenersList = (List) listenersMap.get(key); - if (listenersList != null) { - mergedListeners.addAll(listenersList); - } + Object name = aNotification.getName(); + Object object = aNotification.getObject(); - CompoundValue value; - Iterator it = mergedListeners.iterator(); + if (name != null) { + if (object != null) { // both are specified + listenersList = (List) listenersMap.get(new CompoundKey(name, object)); + if (listenersList != null) { + mergedListeners.addAll(listenersList); + } + listenersList = (List) listenersMap.get(new CompoundKey(name, NULL_MARKER)); + if (listenersList != null) { + mergedListeners.addAll(listenersList); + } + listenersList = (List) listenersMap.get(new CompoundKey(NULL_MARKER, object)); + if (listenersList != null) { + mergedListeners.addAll(listenersList); + } + } + else { // object is null + listenersList = (List) listenersMap.get(new CompoundKey(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)); + if (listenersList != null) { + mergedListeners.addAll(listenersList); + } + } - while (it.hasNext()) { - value = (CompoundValue) it.next(); - if (value.get() == null) { - it.remove(); - } else { - try { - value.getMethod().invoke(value.get(), new Object[] { aNotification }); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - } - } + Object key = new CompoundKey(NULL_MARKER, NULL_MARKER); + listenersList = (List) listenersMap.get(key); + if (listenersList != null) { + mergedListeners.addAll(listenersList); + } - //**************************************************************** - // Implementation classes and methods - //**************************************************************** + CompoundValue value; + Iterator it = mergedListeners.iterator(); - protected List matchingKeys(String name, Object object) { - List result = new LinkedList(); + while (it.hasNext()) { + value = (CompoundValue) it.next(); + if (value.get() == null) { + it.remove(); + } + else { + try { + value.getMethod().invoke(value.get(), new Object[] { aNotification }); + } + catch (IllegalAccessException e) { + e.printStackTrace(); + } + catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } - Iterator it = listenersMap.keySet().iterator(); - while (it.hasNext()) { - CompoundKey key = (CompoundKey) it.next(); - if ((name == null) || (name == key.name())) { - if ((object == null) || (object == key.get())) { - result.add(key); - } - } - } + // **************************************************************** + // Implementation classes and methods + // **************************************************************** - return result; - } - - protected void removeListener(Object listener, Object key) { - if (listener == null) { - listenersMap.remove(key); - return; - } + protected List matchingKeys(String name, Object object) { + List result = new LinkedList(); - List list = (List) listenersMap.get(key); - if (list == null) - return; + Iterator it = listenersMap.keySet().iterator(); + while (it.hasNext()) { + CompoundKey key = (CompoundKey) it.next(); + if ((name == null) || (name == key.name())) { + if ((object == null) || (object == key.get())) { + result.add(key); + } + } + } - Iterator it = list.iterator(); - while (it.hasNext()) { - Object observer = ((CompoundValue) it.next()).get(); - if ((observer == null) || (listener == observer)) { - it.remove(); - } - } - - if (list.size() == 0) { - listenersMap.remove(key); - } - } - - protected void processKeyQueue() { - CompoundKey key; - while ((key = (CompoundKey) keyQueue.poll()) != null) { - listenersMap.remove(key); - } - } - - protected static class CompoundKey extends WeakReference { + return result; + } - private Object name; - private int hashCode; + protected void removeListener(Object listener, Object key) { + if (listener == null) { + listenersMap.remove(key); + return; + } - public CompoundKey(Object aName, Object anObject) { - super(anObject); - name = aName; - hashCode = aName.hashCode() + anObject.hashCode(); - } + List list = (List) listenersMap.get(key); + if (list == null) + return; - public CompoundKey(Object aName, Object anObject, ReferenceQueue aQueue) { - super(anObject, aQueue); - name = aName; - hashCode = aName.hashCode() + anObject.hashCode(); - } + Iterator it = list.iterator(); + while (it.hasNext()) { + Object observer = ((CompoundValue) it.next()).get(); + if ((observer == null) || (listener == observer)) { + it.remove(); + } + } - public Object name() { - return name; - } + if (list.size() == 0) { + listenersMap.remove(key); + } + } - public int hashCode() { - return hashCode; - } + protected void processKeyQueue() { + CompoundKey key; + while ((key = (CompoundKey) keyQueue.poll()) != null) { + listenersMap.remove(key); + } + } - public boolean equals(Object anObject) { - if (this == anObject) return true; - CompoundKey key = (CompoundKey) anObject; - if (name == key.name || (name != null && name.equals(key.name))) { - Object object = get(); - if (object != null) { - if ( object == (key.get())) { - return true; - } - } - } - return false; - } + protected static class CompoundKey extends WeakReference { - public String toString() { - return "[CompoundKey:" + name() + ":" + get() + "]"; - } - } + private Object name; + private int hashCode; - protected static class CompoundValue extends WeakReference { + public CompoundKey(Object aName, Object anObject) { + super(anObject); + name = aName; + hashCode = aName.hashCode() + anObject.hashCode(); + } - protected int hashCode; - protected Method method; + public CompoundKey(Object aName, Object anObject, ReferenceQueue aQueue) { + super(anObject, aQueue); + name = aName; + hashCode = aName.hashCode() + anObject.hashCode(); + } - public CompoundValue(Object object, Method method) { - super(object); - hashCode = object.hashCode(); - this.method = method; - } + public Object name() { + return name; + } - public Method getMethod() { - return method; - } + public int hashCode() { + return hashCode; + } - public int hashCode() { - return hashCode; - } + public boolean equals(Object anObject) { + if (this == anObject) + return true; + CompoundKey key = (CompoundKey) anObject; + if (name == key.name || (name != null && name.equals(key.name))) { + Object object = get(); + if (object != null) { + if (object == (key.get())) { + return true; + } + } + } + return false; + } - public boolean equals(Object object) { - if (this == object) return true; - CompoundValue value = (CompoundValue) object; - if (method == value.method || (method != null && method.equals(value.method))) { - Object o = get(); - if (o != null) { - if (o == value.get()) { - return true; - } - } - } - return false; - } + public String toString() { + return "[CompoundKey:" + name() + ":" + get() + "]"; + } + } - public String toString() { - return "[CompoundValue:" + get() + ":" + getMethod().getName() + "]"; - } - } + protected static class CompoundValue extends WeakReference { + + protected int hashCode; + protected Method method; + + public CompoundValue(Object object, Method method) { + super(object); + hashCode = object.hashCode(); + this.method = method; + } + + public Method getMethod() { + return method; + } + + public int hashCode() { + return hashCode; + } + + public boolean equals(Object object) { + if (this == object) + return true; + CompoundValue value = (CompoundValue) object; + if (method == value.method || (method != null && method.equals(value.method))) { + Object o = get(); + if (o != null) { + if (o == value.get()) { + return true; + } + } + } + return false; + } + + public String toString() { + return "[CompoundValue:" + get() + ":" + getMethod().getName() + "]"; + } + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PSelectionEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PSelectionEventHandler.java index 8383eb6..901080c 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/event/PSelectionEventHandler.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PSelectionEventHandler.java @@ -55,607 +55,625 @@ import edu.umd.cs.piccolox.handles.PBoundsHandle; /** - *PSelectionEventHandler
provides standard interaction for selection. Clicking
- * selects the object under the cursor. Shift-clicking allows multiple objects to be
- * selected. Dragging offers marquee selection. Pressing the delete key deletes
- * the selection by default.
+ * PSelectionEventHandler
provides standard interaction for
+ * selection. Clicking selects the object under the cursor. Shift-clicking
+ * allows multiple objects to be selected. Dragging offers marquee selection.
+ * Pressing the delete key deletes the selection by default.
+ *
* @version 1.0
* @author Ben Bederson
- */
+ */
public class PSelectionEventHandler extends PDragSequenceEventHandler {
- public static final String SELECTION_CHANGED_NOTIFICATION = "SELECTION_CHANGED_NOTIFICATION";
+ public static final String SELECTION_CHANGED_NOTIFICATION = "SELECTION_CHANGED_NOTIFICATION";
- final static int DASH_WIDTH = 5;
- final static int NUM_STROKES = 10;
-
- private HashMap selection = null; // The current selection
- private List selectableParents = null; // List of nodes whose children can be selected
- private PPath marquee = null;
- private PNode marqueeParent = null; // Node that marquee is added to as a child
- private Point2D presspt = null;
- private Point2D canvasPressPt = null;
- private float strokeNum = 0;
- private Stroke[] strokes = null;
- private HashMap allItems = null; // Used within drag handler temporarily
- private ArrayList unselectList = null; // Used within drag handler temporarily
- private HashMap marqueeMap = null;
- private PNode pressNode = null; // Node pressed on (or null if none)
- private boolean deleteKeyActive = true; // True if DELETE key should delete selection
- private Paint marqueePaint;
- private float marqueePaintTransparency = 1.0f;
-
- /**
- * Creates a selection event handler.
- * @param marqueeParent The node to which the event handler dynamically adds a marquee
- * (temporarily) to represent the area being selected.
- * @param selectableParent The node whose children will be selected
- * by this event handler.
- */
- public PSelectionEventHandler(PNode marqueeParent, PNode selectableParent) {
- this.marqueeParent = marqueeParent;
- this.selectableParents = new ArrayList();
- this.selectableParents.add(selectableParent);
- init();
- }
+ final static int DASH_WIDTH = 5;
+ final static int NUM_STROKES = 10;
- /**
- * Creates a selection event handler.
- * @param marqueeParent The node to which the event handler dynamically adds a marquee
- * (temporarily) to represent the area being selected.
- * @param selectableParents A list of nodes whose children will be selected
- * by this event handler.
- */
- public PSelectionEventHandler(PNode marqueeParent, List selectableParents) {
- this.marqueeParent = marqueeParent;
- this.selectableParents = selectableParents;
- init();
- }
+ // The current selection
+ private HashMap selection = null;
+ // List of nodes whose children can be selected
+ private List selectableParents = null;
+ private PPath marquee = null;
+ // Node that marquee is added to as a child
+ private PNode marqueeParent = null;
+ private Point2D presspt = null;
+ private Point2D canvasPressPt = null;
+ private float strokeNum = 0;
+ private Stroke[] strokes = null;
+ // Used within drag handler temporarily
+ private HashMap allItems = null;
+ // Used within drag handler temporarily
+ private ArrayList unselectList = null;
+ private HashMap marqueeMap = null;
+ // Node pressed on (or null if none)
+ private PNode pressNode = null;
+ // True if DELETE key should delete selection
+ private boolean deleteKeyActive = true;
+ private Paint marqueePaint;
+ private float marqueePaintTransparency = 1.0f;
- protected void init() {
- float[] dash = { DASH_WIDTH, DASH_WIDTH };
- strokes = new Stroke[NUM_STROKES];
- for (int i = 0; i < NUM_STROKES; i++) {
- strokes[i] = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, dash, i);
- }
-
- selection = new HashMap();
- allItems = new HashMap();
- unselectList = new ArrayList();
- marqueeMap = new HashMap();
- }
+ /**
+ * Creates a selection event handler.
+ *
+ * @param marqueeParent The node to which the event handler dynamically adds
+ * a marquee (temporarily) to represent the area being selected.
+ * @param selectableParent The node whose children will be selected by this
+ * event handler.
+ */
+ public PSelectionEventHandler(PNode marqueeParent, PNode selectableParent) {
+ this.marqueeParent = marqueeParent;
+ this.selectableParents = new ArrayList();
+ this.selectableParents.add(selectableParent);
+ init();
+ }
- ///////////////////////////////////////////////////////
- // Public static methods for manipulating the selection
- ///////////////////////////////////////////////////////
-
- public void select(Collection items) {
- boolean changes = false;
- Iterator itemIt = items.iterator();
- while (itemIt.hasNext()) {
- PNode node = (PNode)itemIt.next();
- changes |= internalSelect(node);
- }
- if (changes) {
- postSelectionChanged();
- }
- }
+ /**
+ * Creates a selection event handler.
+ *
+ * @param marqueeParent The node to which the event handler dynamically adds
+ * a marquee (temporarily) to represent the area being selected.
+ * @param selectableParents A list of nodes whose children will be selected
+ * by this event handler.
+ */
+ public PSelectionEventHandler(PNode marqueeParent, List selectableParents) {
+ this.marqueeParent = marqueeParent;
+ this.selectableParents = selectableParents;
+ init();
+ }
- public void select(Map items) {
- select( items.keySet() );
- }
+ protected void init() {
+ float[] dash = { DASH_WIDTH, DASH_WIDTH };
+ strokes = new Stroke[NUM_STROKES];
+ for (int i = 0; i < NUM_STROKES; i++) {
+ strokes[i] = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, dash, i);
+ }
- private boolean internalSelect( PNode node ) {
- if (isSelected(node)) {
- return false;
- }
+ selection = new HashMap();
+ allItems = new HashMap();
+ unselectList = new ArrayList();
+ marqueeMap = new HashMap();
+ }
- selection.put(node, Boolean.TRUE);
- decorateSelectedNode(node);
- return true;
- }
+ // /////////////////////////////////////////////////////
+ // Public static methods for manipulating the selection
+ // /////////////////////////////////////////////////////
- private void postSelectionChanged()
- {
- PNotificationCenter.defaultCenter().postNotification(SELECTION_CHANGED_NOTIFICATION, this);
- }
+ public void select(Collection items) {
+ boolean changes = false;
+ Iterator itemIt = items.iterator();
+ while (itemIt.hasNext()) {
+ PNode node = (PNode) itemIt.next();
+ changes |= internalSelect(node);
+ }
+ if (changes) {
+ postSelectionChanged();
+ }
+ }
- public void select(PNode node) {
- if (internalSelect(node)) {
- postSelectionChanged();
- }
- }
+ public void select(Map items) {
+ select(items.keySet());
+ }
- public void decorateSelectedNode(PNode node) {
- PBoundsHandle.addBoundsHandlesTo(node);
- }
-
- public void unselect(Collection items) {
- boolean changes = false;
- Iterator itemIt = items.iterator();
- while (itemIt.hasNext()) {
- PNode node = (PNode)itemIt.next();
- changes |= internalUnselect(node);
- }
- if (changes) {
- postSelectionChanged();
- }
- }
+ private boolean internalSelect(PNode node) {
+ if (isSelected(node)) {
+ return false;
+ }
- private boolean internalUnselect( PNode node ) {
- if (!isSelected(node)) {
- return false;
- }
+ selection.put(node, Boolean.TRUE);
+ decorateSelectedNode(node);
+ return true;
+ }
- undecorateSelectedNode(node);
- selection.remove(node);
- return true;
- }
+ private void postSelectionChanged() {
+ PNotificationCenter.defaultCenter().postNotification(SELECTION_CHANGED_NOTIFICATION, this);
+ }
- public void unselect(PNode node) {
- if( internalUnselect(node) ) {
- postSelectionChanged();
- }
- }
+ public void select(PNode node) {
+ if (internalSelect(node)) {
+ postSelectionChanged();
+ }
+ }
- public void undecorateSelectedNode(PNode node) {
- PBoundsHandle.removeBoundsHandlesFrom(node);
- }
+ public void decorateSelectedNode(PNode node) {
+ PBoundsHandle.addBoundsHandlesTo(node);
+ }
- public void unselectAll() {
- // Because unselect() removes from selection, we need to
- // take a copy of it first so it isn't changed while we're iterating
- ArrayList sel = new ArrayList(selection.keySet());
- unselect( sel );
- }
+ public void unselect(Collection items) {
+ boolean changes = false;
+ Iterator itemIt = items.iterator();
+ while (itemIt.hasNext()) {
+ PNode node = (PNode) itemIt.next();
+ changes |= internalUnselect(node);
+ }
+ if (changes) {
+ postSelectionChanged();
+ }
+ }
- public boolean isSelected(PNode node) {
- if ((node != null) && (selection.containsKey(node))) {
- return true;
- } else {
- return false;
- }
- }
+ private boolean internalUnselect(PNode node) {
+ if (!isSelected(node)) {
+ return false;
+ }
- /**
- * Returns a copy of the currently selected nodes.
- */
- public Collection getSelection() {
- ArrayList sel = new ArrayList(selection.keySet());
- return sel;
- }
+ undecorateSelectedNode(node);
+ selection.remove(node);
+ return true;
+ }
- /**
- * Gets a reference to the currently selected nodes. You should not modify or store
- * this collection.
- */
- public Collection getSelectionReference()
- {
- return Collections.unmodifiableCollection( selection.keySet() );
- }
+ public void unselect(PNode node) {
+ if (internalUnselect(node)) {
+ postSelectionChanged();
+ }
+ }
- /**
- * Determine if the specified node is selectable (i.e., if it is a child
- * of the one the list of selectable parents.
- */
- protected boolean isSelectable(PNode node) {
- boolean selectable = false;
+ public void undecorateSelectedNode(PNode node) {
+ PBoundsHandle.removeBoundsHandlesFrom(node);
+ }
- Iterator parentsIt = selectableParents.iterator();
- while (parentsIt.hasNext()) {
- PNode parent = (PNode)parentsIt.next();
- if (parent.getChildrenReference().contains(node)) {
- selectable = true;
- break;
- }
- else if (parent instanceof PCamera) {
- for(int i=0; i<((PCamera)parent).getLayerCount(); i++) {
- PLayer layer = ((PCamera)parent).getLayer(i);
- if (layer.getChildrenReference().contains(node)) {
- selectable = true;
- break;
- }
- }
- }
- }
-
- return selectable;
- }
+ public void unselectAll() {
+ // Because unselect() removes from selection, we need to
+ // take a copy of it first so it isn't changed while we're iterating
+ ArrayList sel = new ArrayList(selection.keySet());
+ unselect(sel);
+ }
- //////////////////////////////////////////////////////
- // Methods for modifying the set of selectable parents
- //////////////////////////////////////////////////////
+ public boolean isSelected(PNode node) {
+ if ((node != null) && (selection.containsKey(node))) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
- public void addSelectableParent(PNode node) {
- selectableParents.add(node);
- }
-
- public void removeSelectableParent(PNode node) {
- selectableParents.remove(node);
- }
-
- public void setSelectableParent(PNode node) {
- selectableParents.clear();
- selectableParents.add(node);
- }
-
- public void setSelectableParents(Collection c) {
- selectableParents.clear();
- selectableParents.addAll(c);
- }
+ /**
+ * Returns a copy of the currently selected nodes.
+ */
+ public Collection getSelection() {
+ ArrayList sel = new ArrayList(selection.keySet());
+ return sel;
+ }
- public Collection getSelectableParents() {
- return new ArrayList(selectableParents);
- }
+ /**
+ * Gets a reference to the currently selected nodes. You should not modify
+ * or store this collection.
+ */
+ public Collection getSelectionReference() {
+ return Collections.unmodifiableCollection(selection.keySet());
+ }
- ////////////////////////////////////////////////////////
- // The overridden methods from PDragSequenceEventHandler
- ////////////////////////////////////////////////////////
-
- protected void startDrag(PInputEvent e) {
- super.startDrag(e);
+ /**
+ * Determine if the specified node is selectable (i.e., if it is a child of
+ * the one the list of selectable parents.
+ */
+ protected boolean isSelectable(PNode node) {
+ boolean selectable = false;
- initializeSelection(e);
+ Iterator parentsIt = selectableParents.iterator();
+ while (parentsIt.hasNext()) {
+ PNode parent = (PNode) parentsIt.next();
+ if (parent.getChildrenReference().contains(node)) {
+ selectable = true;
+ break;
+ }
+ else if (parent instanceof PCamera) {
+ for (int i = 0; i < ((PCamera) parent).getLayerCount(); i++) {
+ PLayer layer = ((PCamera) parent).getLayer(i);
+ if (layer.getChildrenReference().contains(node)) {
+ selectable = true;
+ break;
+ }
+ }
+ }
+ }
- if (isMarqueeSelection(e)) {
- initializeMarquee(e);
+ return selectable;
+ }
- if (!isOptionSelection(e)) {
- startMarqueeSelection(e);
- }
- else {
- startOptionMarqueeSelection(e);
- }
- }
- else {
- if (!isOptionSelection(e)) {
- startStandardSelection(e);
- } else {
- startStandardOptionSelection(e);
- }
- }
- }
+ // ////////////////////////////////////////////////////
+ // Methods for modifying the set of selectable parents
+ // ////////////////////////////////////////////////////
- protected void drag(PInputEvent e) {
- super.drag(e);
+ public void addSelectableParent(PNode node) {
+ selectableParents.add(node);
+ }
- if (isMarqueeSelection(e)) {
- updateMarquee(e);
+ public void removeSelectableParent(PNode node) {
+ selectableParents.remove(node);
+ }
- if (!isOptionSelection(e)) {
- computeMarqueeSelection(e);
- }
- else {
- computeOptionMarqueeSelection(e);
- }
- } else {
- dragStandardSelection(e);
- }
- }
+ public void setSelectableParent(PNode node) {
+ selectableParents.clear();
+ selectableParents.add(node);
+ }
- protected void endDrag(PInputEvent e) {
- super.endDrag(e);
+ public void setSelectableParents(Collection c) {
+ selectableParents.clear();
+ selectableParents.addAll(c);
+ }
+
+ public Collection getSelectableParents() {
+ return new ArrayList(selectableParents);
+ }
+
+ // //////////////////////////////////////////////////////
+ // The overridden methods from PDragSequenceEventHandler
+ // //////////////////////////////////////////////////////
+
+ protected void startDrag(PInputEvent e) {
+ super.startDrag(e);
+
+ initializeSelection(e);
+
+ if (isMarqueeSelection(e)) {
+ initializeMarquee(e);
+
+ if (!isOptionSelection(e)) {
+ startMarqueeSelection(e);
+ }
+ else {
+ startOptionMarqueeSelection(e);
+ }
+ }
+ else {
+ if (!isOptionSelection(e)) {
+ startStandardSelection(e);
+ }
+ else {
+ startStandardOptionSelection(e);
+ }
+ }
+ }
+
+ protected void drag(PInputEvent e) {
+ super.drag(e);
+
+ if (isMarqueeSelection(e)) {
+ updateMarquee(e);
+
+ if (!isOptionSelection(e)) {
+ computeMarqueeSelection(e);
+ }
+ else {
+ computeOptionMarqueeSelection(e);
+ }
+ }
+ else {
+ dragStandardSelection(e);
+ }
+ }
+
+ protected void endDrag(PInputEvent e) {
+ super.endDrag(e);
+
+ if (isMarqueeSelection(e)) {
+ endMarqueeSelection(e);
+ }
+ else {
+ endStandardSelection(e);
+ }
+ }
+
+ // //////////////////////////
+ // Additional methods
+ // //////////////////////////
+
+ public boolean isOptionSelection(PInputEvent pie) {
+ return pie.isShiftDown();
+ }
+
+ protected boolean isMarqueeSelection(PInputEvent pie) {
+ return (pressNode == null);
+ }
+
+ protected void initializeSelection(PInputEvent pie) {
+ canvasPressPt = pie.getCanvasPosition();
+ presspt = pie.getPosition();
+ pressNode = pie.getPath().getPickedNode();
+ if (pressNode instanceof PCamera) {
+ pressNode = null;
+ }
+ }
+
+ protected void initializeMarquee(PInputEvent e) {
+ marquee = PPath.createRectangle((float) presspt.getX(), (float) presspt.getY(), 0, 0);
+ marquee.setPaint(marqueePaint);
+ marquee.setTransparency(marqueePaintTransparency);
+ marquee.setStrokePaint(Color.black);
+ marquee.setStroke(strokes[0]);
+ marqueeParent.addChild(marquee);
+
+ marqueeMap.clear();
+ }
+
+ protected void startOptionMarqueeSelection(PInputEvent e) {
+ }
+
+ protected void startMarqueeSelection(PInputEvent e) {
+ unselectAll();
+ }
- if (isMarqueeSelection(e)) {
- endMarqueeSelection(e);
- }
- else {
- endStandardSelection(e);
- }
- }
+ protected void startStandardSelection(PInputEvent pie) {
+ // Option indicator not down - clear selection, and start fresh
+ if (!isSelected(pressNode)) {
+ unselectAll();
- ////////////////////////////
- // Additional methods
- ////////////////////////////
+ if (isSelectable(pressNode)) {
+ select(pressNode);
+ }
+ }
+ }
- public boolean isOptionSelection(PInputEvent pie) {
- return pie.isShiftDown();
- }
+ protected void startStandardOptionSelection(PInputEvent pie) {
+ // Option indicator is down, toggle selection
+ if (isSelectable(pressNode)) {
+ if (isSelected(pressNode)) {
+ unselect(pressNode);
+ }
+ else {
+ select(pressNode);
+ }
+ }
+ }
- protected boolean isMarqueeSelection(PInputEvent pie) {
- return (pressNode == null);
- }
+ protected void updateMarquee(PInputEvent pie) {
+ PBounds b = new PBounds();
- protected void initializeSelection(PInputEvent pie) {
- canvasPressPt = pie.getCanvasPosition();
- presspt = pie.getPosition();
- pressNode = pie.getPath().getPickedNode();
- if (pressNode instanceof PCamera) {
- pressNode = null;
- }
- }
+ if (marqueeParent instanceof PCamera) {
+ b.add(canvasPressPt);
+ b.add(pie.getCanvasPosition());
+ }
+ else {
+ b.add(presspt);
+ b.add(pie.getPosition());
+ }
- protected void initializeMarquee(PInputEvent e) {
- marquee = PPath.createRectangle((float)presspt.getX(), (float)presspt.getY(), 0, 0);
- marquee.setPaint(marqueePaint);
- marquee.setTransparency(marqueePaintTransparency);
- marquee.setStrokePaint(Color.black);
- marquee.setStroke(strokes[0]);
- marqueeParent.addChild(marquee);
+ marquee.globalToLocal(b);
+ marquee.setPathToRectangle((float) b.x, (float) b.y, (float) b.width, (float) b.height);
+ b.reset();
+ b.add(presspt);
+ b.add(pie.getPosition());
- marqueeMap.clear();
- }
+ allItems.clear();
+ PNodeFilter filter = createNodeFilter(b);
+ Iterator parentsIt = selectableParents.iterator();
+ while (parentsIt.hasNext()) {
+ PNode parent = (PNode) parentsIt.next();
- protected void startOptionMarqueeSelection(PInputEvent e) {
- }
+ Collection items;
+ if (parent instanceof PCamera) {
+ items = new ArrayList();
+ for (int i = 0; i < ((PCamera) parent).getLayerCount(); i++) {
+ ((PCamera) parent).getLayer(i).getAllNodes(filter, items);
+ }
+ }
+ else {
+ items = parent.getAllNodes(filter, null);
+ }
- protected void startMarqueeSelection(PInputEvent e) {
- unselectAll();
- }
-
- protected void startStandardSelection(PInputEvent pie) {
- // Option indicator not down - clear selection, and start fresh
- if (!isSelected(pressNode)) {
- unselectAll();
-
- if (isSelectable(pressNode)) {
- select(pressNode);
- }
- }
- }
+ Iterator itemsIt = items.iterator();
+ while (itemsIt.hasNext()) {
+ allItems.put(itemsIt.next(), Boolean.TRUE);
+ }
+ }
+ }
- protected void startStandardOptionSelection(PInputEvent pie) {
- // Option indicator is down, toggle selection
- if (isSelectable(pressNode)) {
- if (isSelected(pressNode)) {
- unselect(pressNode);
- } else {
- select(pressNode);
- }
- }
- }
+ protected void computeMarqueeSelection(PInputEvent pie) {
+ unselectList.clear();
+ // Make just the items in the list selected
+ // Do this efficiently by first unselecting things not in the list
+ Iterator selectionEn = selection.keySet().iterator();
+ while (selectionEn.hasNext()) {
+ PNode node = (PNode) selectionEn.next();
+ if (!allItems.containsKey(node)) {
+ unselectList.add(node);
+ }
+ }
+ unselect(unselectList);
- protected void updateMarquee(PInputEvent pie) {
- PBounds b = new PBounds();
+ // Then select the rest
+ selectionEn = allItems.keySet().iterator();
+ while (selectionEn.hasNext()) {
+ PNode node = (PNode) selectionEn.next();
+ if (!selection.containsKey(node) && !marqueeMap.containsKey(node) && isSelectable(node)) {
+ marqueeMap.put(node, Boolean.TRUE);
+ }
+ else if (!isSelectable(node)) {
+ selectionEn.remove();
+ }
+ }
- if (marqueeParent instanceof PCamera) {
- b.add(canvasPressPt);
- b.add(pie.getCanvasPosition());
- }
- else {
- b.add(presspt);
- b.add(pie.getPosition());
- }
+ select(allItems);
+ }
- marquee.globalToLocal(b);
- marquee.setPathToRectangle((float) b.x, (float) b.y, (float) b.width, (float) b.height);
- b.reset();
- b.add(presspt);
- b.add(pie.getPosition());
+ protected void computeOptionMarqueeSelection(PInputEvent pie) {
+ unselectList.clear();
+ Iterator selectionEn = selection.keySet().iterator();
+ while (selectionEn.hasNext()) {
+ PNode node = (PNode) selectionEn.next();
+ if (!allItems.containsKey(node) && marqueeMap.containsKey(node)) {
+ marqueeMap.remove(node);
+ unselectList.add(node);
+ }
+ }
+ unselect(unselectList);
- allItems.clear();
- PNodeFilter filter = createNodeFilter(b);
- Iterator parentsIt = selectableParents.iterator();
- while (parentsIt.hasNext()) {
- PNode parent = (PNode) parentsIt.next();
-
- Collection items;
- if (parent instanceof PCamera) {
- items = new ArrayList();
- for(int i=0; i<((PCamera)parent).getLayerCount(); i++) {
- ((PCamera)parent).getLayer(i).getAllNodes(filter,items);
- }
- }
- else {
- items = parent.getAllNodes(filter, null);
- }
-
- Iterator itemsIt = items.iterator();
- while (itemsIt.hasNext()) {
- allItems.put(itemsIt.next(), Boolean.TRUE);
- }
- }
- }
+ // Then select the rest
+ selectionEn = allItems.keySet().iterator();
+ while (selectionEn.hasNext()) {
+ PNode node = (PNode) selectionEn.next();
+ if (!selection.containsKey(node) && !marqueeMap.containsKey(node) && isSelectable(node)) {
+ marqueeMap.put(node, Boolean.TRUE);
+ }
+ else if (!isSelectable(node)) {
+ selectionEn.remove();
+ }
+ }
- protected void computeMarqueeSelection(PInputEvent pie) {
- unselectList.clear();
- // Make just the items in the list selected
- // Do this efficiently by first unselecting things not in the list
- Iterator selectionEn = selection.keySet().iterator();
- while (selectionEn.hasNext()) {
- PNode node = (PNode) selectionEn.next();
- if (!allItems.containsKey(node)) {
- unselectList.add(node);
- }
- }
- unselect(unselectList);
-
- // Then select the rest
- selectionEn = allItems.keySet().iterator();
- while (selectionEn.hasNext()) {
- PNode node = (PNode) selectionEn.next();
- if (!selection.containsKey(node) && !marqueeMap.containsKey(node) && isSelectable(node)) {
- marqueeMap.put(node,Boolean.TRUE);
- }
- else if (!isSelectable(node)) {
- selectionEn.remove();
- }
- }
-
- select(allItems);
- }
+ select(allItems);
+ }
- protected void computeOptionMarqueeSelection(PInputEvent pie) {
- unselectList.clear();
- Iterator selectionEn = selection.keySet().iterator();
- while (selectionEn.hasNext()) {
- PNode node = (PNode) selectionEn.next();
- if (!allItems.containsKey(node) && marqueeMap.containsKey(node)) {
- marqueeMap.remove(node);
- unselectList.add(node);
- }
- }
- unselect(unselectList);
-
+ protected PNodeFilter createNodeFilter(PBounds bounds) {
+ return new BoundsFilter(bounds);
+ }
- // Then select the rest
- selectionEn = allItems.keySet().iterator();
- while (selectionEn.hasNext()) {
- PNode node = (PNode) selectionEn.next();
- if (!selection.containsKey(node) && !marqueeMap.containsKey(node) && isSelectable(node)) {
- marqueeMap.put(node,Boolean.TRUE);
- }
- else if (!isSelectable(node)) {
- selectionEn.remove();
- }
- }
+ protected PBounds getMarqueeBounds() {
+ if (marquee != null) {
+ return marquee.getBounds();
+ }
+ return new PBounds();
+ }
- select(allItems);
- }
+ protected void dragStandardSelection(PInputEvent e) {
+ // There was a press node, so drag selection
+ PDimension d = e.getCanvasDelta();
+ e.getTopCamera().localToView(d);
- protected PNodeFilter createNodeFilter(PBounds bounds) {
- return new BoundsFilter(bounds);
- }
+ PDimension gDist = new PDimension();
+ Iterator selectionEn = getSelection().iterator();
+ while (selectionEn.hasNext()) {
+ PNode node = (PNode) selectionEn.next();
- protected PBounds getMarqueeBounds() {
- if (marquee != null) {
- return marquee.getBounds();
- }
- return new PBounds();
- }
+ gDist.setSize(d);
+ node.getParent().globalToLocal(gDist);
+ node.offset(gDist.getWidth(), gDist.getHeight());
+ }
+ }
- protected void dragStandardSelection(PInputEvent e) {
- // There was a press node, so drag selection
- PDimension d = e.getCanvasDelta();
- e.getTopCamera().localToView(d);
+ protected void endMarqueeSelection(PInputEvent e) {
+ // Remove marquee
+ allItems.clear();
+ marqueeMap.clear();
+ marquee.removeFromParent();
+ marquee = null;
+ }
- PDimension gDist = new PDimension();
- Iterator selectionEn = getSelection().iterator();
- while (selectionEn.hasNext()) {
- PNode node = (PNode) selectionEn.next();
+ protected void endStandardSelection(PInputEvent e) {
+ pressNode = null;
+ }
- gDist.setSize(d);
- node.getParent().globalToLocal(gDist);
- node.offset(gDist.getWidth(), gDist.getHeight());
- }
- }
+ /**
+ * This gets called continuously during the drag, and is used to animate the
+ * marquee
+ */
+ protected void dragActivityStep(PInputEvent aEvent) {
+ if (marquee != null) {
+ float origStrokeNum = strokeNum;
+ strokeNum = (strokeNum + 0.5f) % NUM_STROKES; // Increment by
+ // partial steps to
+ // slow down animation
+ if ((int) strokeNum != (int) origStrokeNum) {
+ marquee.setStroke(strokes[(int) strokeNum]);
+ }
+ }
+ }
- protected void endMarqueeSelection(PInputEvent e) {
- // Remove marquee
- allItems.clear();
- marqueeMap.clear();
- marquee.removeFromParent();
- marquee = null;
- }
+ /**
+ * Delete selection when delete key is pressed (if enabled)
+ */
+ public void keyPressed(PInputEvent e) {
+ switch (e.getKeyCode()) {
+ case KeyEvent.VK_DELETE:
+ if (deleteKeyActive) {
+ Iterator selectionEn = selection.keySet().iterator();
+ while (selectionEn.hasNext()) {
+ PNode node = (PNode) selectionEn.next();
+ node.removeFromParent();
+ }
+ selection.clear();
+ }
+ }
+ }
- protected void endStandardSelection(PInputEvent e) {
- pressNode = null;
- }
+ public boolean getSupportDeleteKey() {
+ return deleteKeyActive;
+ }
- /**
- * This gets called continuously during the drag, and is used to animate the marquee
- */
- protected void dragActivityStep(PInputEvent aEvent) {
- if (marquee != null) {
- float origStrokeNum = strokeNum;
- strokeNum = (strokeNum + 0.5f) % NUM_STROKES; // Increment by partial steps to slow down animation
- if ((int)strokeNum != (int)origStrokeNum) {
- marquee.setStroke(strokes[(int)strokeNum]);
- }
- }
- }
+ public boolean isDeleteKeyActive() {
+ return deleteKeyActive;
+ }
- /**
- * Delete selection when delete key is pressed (if enabled)
- */
- public void keyPressed(PInputEvent e) {
- switch (e.getKeyCode()) {
- case KeyEvent.VK_DELETE:
- if (deleteKeyActive) {
- Iterator selectionEn = selection.keySet().iterator();
- while (selectionEn.hasNext()) {
- PNode node = (PNode) selectionEn.next();
- node.removeFromParent();
- }
- selection.clear();
- }
- }
- }
+ /**
+ * Specifies if the DELETE key should delete the selection
+ */
+ public void setDeleteKeyActive(boolean deleteKeyActive) {
+ this.deleteKeyActive = deleteKeyActive;
+ }
- public boolean getSupportDeleteKey() {
- return deleteKeyActive;
- }
+ // ////////////////////
+ // Inner classes
+ // ////////////////////
- public boolean isDeleteKeyActive() {
- return deleteKeyActive;
- }
+ protected class BoundsFilter implements PNodeFilter {
+ PBounds localBounds = new PBounds();
+ PBounds bounds;
- /**
- * Specifies if the DELETE key should delete the selection
- */
- public void setDeleteKeyActive(boolean deleteKeyActive) {
- this.deleteKeyActive = deleteKeyActive;
- }
+ protected BoundsFilter(PBounds bounds) {
+ this.bounds = bounds;
+ }
- //////////////////////
- // Inner classes
- //////////////////////
+ public boolean accept(PNode node) {
+ localBounds.setRect(bounds);
+ node.globalToLocal(localBounds);
- protected class BoundsFilter implements PNodeFilter {
- PBounds localBounds = new PBounds();
- PBounds bounds;
-
- protected BoundsFilter(PBounds bounds) {
- this.bounds = bounds;
- }
+ boolean boundsIntersects = node.intersects(localBounds);
+ boolean isMarquee = (node == marquee);
+ return (node.getPickable() && boundsIntersects && !isMarquee && !selectableParents.contains(node) && !isCameraLayer(node));
+ }
- public boolean accept(PNode node) {
- localBounds.setRect(bounds);
- node.globalToLocal(localBounds);
-
- boolean boundsIntersects = node.intersects(localBounds);
- boolean isMarquee = (node == marquee);
- return (node.getPickable() && boundsIntersects && !isMarquee && !selectableParents.contains(node) && !isCameraLayer(node));
- }
+ public boolean acceptChildrenOf(PNode node) {
+ return selectableParents.contains(node) || isCameraLayer(node);
+ }
- public boolean acceptChildrenOf(PNode node) {
- return selectableParents.contains(node) || isCameraLayer(node);
- }
-
- public boolean isCameraLayer(PNode node) {
- if (node instanceof PLayer) {
- for(Iterator i=selectableParents.iterator(); i.hasNext();) {
- PNode parent = (PNode)i.next();
- if (parent instanceof PCamera) {
- if (((PCamera)parent).indexOfLayer((PLayer)node) != -1) {
- return true;
- }
- }
- }
- }
- return false;
- }
- }
+ public boolean isCameraLayer(PNode node) {
+ if (node instanceof PLayer) {
+ for (Iterator i = selectableParents.iterator(); i.hasNext();) {
+ PNode parent = (PNode) i.next();
+ if (parent instanceof PCamera) {
+ if (((PCamera) parent).indexOfLayer((PLayer) node) != -1) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ }
- /**
- * Indicates the color used to paint the marquee.
- * @return the paint for interior of the marquee
- */
- public Paint getMarqueePaint() {
- return marqueePaint;
- }
+ /**
+ * Indicates the color used to paint the marquee.
+ *
+ * @return the paint for interior of the marquee
+ */
+ public Paint getMarqueePaint() {
+ return marqueePaint;
+ }
- /**
- * Sets the color used to paint the marquee.
- * @param paint the paint color
- */
- public void setMarqueePaint(Paint paint) {
- this.marqueePaint = paint;
- }
+ /**
+ * Sets the color used to paint the marquee.
+ *
+ * @param paint the paint color
+ */
+ public void setMarqueePaint(Paint paint) {
+ this.marqueePaint = paint;
+ }
- /**
- * Indicates the transparency level for the interior of the marquee.
- * @return Returns the marquee paint transparency, zero to one
- */
- public float getMarqueePaintTransparency() {
- return marqueePaintTransparency;
- }
+ /**
+ * Indicates the transparency level for the interior of the marquee.
+ *
+ * @return Returns the marquee paint transparency, zero to one
+ */
+ public float getMarqueePaintTransparency() {
+ return marqueePaintTransparency;
+ }
- /**
- * Sets the transparency level for the interior of the marquee.
- * @param marqueePaintTransparency The marquee paint transparency to set.
- */
- public void setMarqueePaintTransparency(float marqueePaintTransparency) {
- this.marqueePaintTransparency = marqueePaintTransparency;
- }
+ /**
+ * Sets the transparency level for the interior of the marquee.
+ *
+ * @param marqueePaintTransparency The marquee paint transparency to set.
+ */
+ public void setMarqueePaintTransparency(float marqueePaintTransparency) {
+ this.marqueePaintTransparency = marqueePaintTransparency;
+ }
}
\ No newline at end of file
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PStyledTextEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PStyledTextEventHandler.java
index 64af73c..6d5ee8d 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/event/PStyledTextEventHandler.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PStyledTextEventHandler.java
@@ -27,7 +27,7 @@
* Piccolo was written at the Human-Computer Interaction Laboratory www.cs.umd.edu/hcil by Jesse Grosjean
* under the supervision of Ben Bederson. The Piccolo website is www.cs.umd.edu/hcil/piccolo.
*/
- package edu.umd.cs.piccolox.event;
+package edu.umd.cs.piccolox.event;
import java.awt.Color;
import java.awt.Dimension;
@@ -65,217 +65,217 @@
*/
public class PStyledTextEventHandler extends PBasicInputEventHandler {
- protected PCanvas canvas;
+ protected PCanvas canvas;
- protected JTextComponent editor;
+ protected JTextComponent editor;
- protected DocumentListener docListener;
+ protected DocumentListener docListener;
- protected PStyledText editedText;
+ protected PStyledText editedText;
- /**
- * Basic constructor for PStyledTextEventHandler
- */
- public PStyledTextEventHandler(PCanvas canvas) {
- super();
+ /**
+ * Basic constructor for PStyledTextEventHandler
+ */
+ public PStyledTextEventHandler(PCanvas canvas) {
+ super();
- this.canvas = canvas;
- initEditor(createDefaultEditor());
- }
+ this.canvas = canvas;
+ initEditor(createDefaultEditor());
+ }
- /**
- * Constructor for PStyledTextEventHandler that allows an editor to be specified
- */
- public PStyledTextEventHandler(PCanvas canvas, JTextComponent editor) {
- super();
+ /**
+ * Constructor for PStyledTextEventHandler that allows an editor to be
+ * specified
+ */
+ public PStyledTextEventHandler(PCanvas canvas, JTextComponent editor) {
+ super();
- this.canvas = canvas;
- initEditor(editor);
- }
+ this.canvas = canvas;
+ initEditor(editor);
+ }
- protected void initEditor(JTextComponent newEditor) {
- editor = newEditor;
-
- canvas.setLayout(null);
- canvas.add(editor);
- editor.setVisible(false);
-
- docListener = createDocumentListener();
- }
+ protected void initEditor(JTextComponent newEditor) {
+ editor = newEditor;
- protected JTextComponent createDefaultEditor() {
- JTextPane tComp = new JTextPane() {
+ canvas.setLayout(null);
+ canvas.add(editor);
+ editor.setVisible(false);
- /**
- * Set some rendering hints - if we don't then the rendering can be inconsistent. Also,
- * Swing doesn't work correctly with fractional metrics.
- */
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
-
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
- g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
-
- super.paint(g);
- }
- };
- tComp.setBorder(new CompoundBorder(new LineBorder(Color.black),new EmptyBorder(3,3,3,3)));
- return tComp;
- }
+ docListener = createDocumentListener();
+ }
- protected DocumentListener createDocumentListener() {
- return new DocumentListener() {
- public void removeUpdate(DocumentEvent e) {
- reshapeEditorLater();
- }
-
- public void insertUpdate(DocumentEvent e) {
- reshapeEditorLater();
- }
-
- public void changedUpdate(DocumentEvent e) {
- reshapeEditorLater();
- }
- };
- }
+ protected JTextComponent createDefaultEditor() {
+ JTextPane tComp = new JTextPane() {
- public PStyledText createText() {
- PStyledText newText = new PStyledText();
-
- Document doc = editor.getUI().getEditorKit(editor).createDefaultDocument();
- if (doc instanceof StyledDocument) {
- if (!doc.getDefaultRootElement().getAttributes().isDefined(StyleConstants.FontFamily)
- || !doc.getDefaultRootElement().getAttributes().isDefined(StyleConstants.FontSize)) {
+ /**
+ * Set some rendering hints - if we don't then the rendering can be
+ * inconsistent. Also, Swing doesn't work correctly with fractional
+ * metrics.
+ */
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
- Font eFont = editor.getFont();
- SimpleAttributeSet sas = new SimpleAttributeSet();
- sas.addAttribute(StyleConstants.FontFamily, eFont.getFamily());
- sas.addAttribute(StyleConstants.FontSize, new Integer(eFont.getSize()));
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
- ((StyledDocument) doc).setParagraphAttributes(0, doc.getLength(), sas, false);
- }
- }
- newText.setDocument(doc);
-
- return newText;
- }
+ super.paint(g);
+ }
+ };
+ tComp.setBorder(new CompoundBorder(new LineBorder(Color.black), new EmptyBorder(3, 3, 3, 3)));
+ return tComp;
+ }
- public void mousePressed(PInputEvent inputEvent) {
- PNode pickedNode = inputEvent.getPickedNode();
-
- stopEditing();
-
- if (pickedNode instanceof PStyledText) {
- startEditing(inputEvent,(PStyledText)pickedNode);
- }
- else if (pickedNode instanceof PCamera) {
- PStyledText newText = createText();
- Insets pInsets = newText.getInsets();
- canvas.getLayer().addChild(newText);
- newText.translate(inputEvent.getPosition().getX()-pInsets.left,inputEvent.getPosition().getY()-pInsets.top);
- startEditing(inputEvent, newText);
- }
- }
-
- public void startEditing(PInputEvent event, PStyledText text) {
- // Get the node's top right hand corner
- Insets pInsets = text.getInsets();
- Point2D nodePt = new Point2D.Double(text.getX()+pInsets.left,text.getY()+pInsets.top);
- text.localToGlobal(nodePt);
- event.getTopCamera().viewToLocal(nodePt);
+ protected DocumentListener createDocumentListener() {
+ return new DocumentListener() {
+ public void removeUpdate(DocumentEvent e) {
+ reshapeEditorLater();
+ }
- // Update the editor to edit the specified node
- editor.setDocument(text.getDocument());
- editor.setVisible(true);
+ public void insertUpdate(DocumentEvent e) {
+ reshapeEditorLater();
+ }
- Insets bInsets = editor.getBorder().getBorderInsets(editor);
- editor.setLocation((int)nodePt.getX()-bInsets.left,(int)nodePt.getY()-bInsets.top);
- reshapeEditorLater();
+ public void changedUpdate(DocumentEvent e) {
+ reshapeEditorLater();
+ }
+ };
+ }
- dispatchEventToEditor(event);
- canvas.repaint();
+ public PStyledText createText() {
+ PStyledText newText = new PStyledText();
- text.setEditing(true);
- text.getDocument().addDocumentListener(docListener);
- editedText = text;
- }
-
- public void stopEditing() {
- if (editedText != null) {
- editedText.getDocument().removeDocumentListener(docListener);
- editedText.setEditing(false);
+ Document doc = editor.getUI().getEditorKit(editor).createDefaultDocument();
+ if (doc instanceof StyledDocument) {
+ if (!doc.getDefaultRootElement().getAttributes().isDefined(StyleConstants.FontFamily)
+ || !doc.getDefaultRootElement().getAttributes().isDefined(StyleConstants.FontSize)) {
- if (editedText.getDocument().getLength() == 0) {
- editedText.removeFromParent();
- }
- else {
- editedText.syncWithDocument();
- }
+ Font eFont = editor.getFont();
+ SimpleAttributeSet sas = new SimpleAttributeSet();
+ sas.addAttribute(StyleConstants.FontFamily, eFont.getFamily());
+ sas.addAttribute(StyleConstants.FontSize, new Integer(eFont.getSize()));
- editor.setVisible(false);
- canvas.repaint();
-
- editedText = null;
- }
- }
+ ((StyledDocument) doc).setParagraphAttributes(0, doc.getLength(), sas, false);
+ }
+ }
+ newText.setDocument(doc);
- public void dispatchEventToEditor(final PInputEvent e) {
- // We have to nest the mouse press in two invoke laters so that it is
- // fired so that the component has been completely validated at the new size
- // and the mouse event has the correct offset
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- MouseEvent me =
- new MouseEvent(
- editor,
- MouseEvent.MOUSE_PRESSED,
- e.getWhen(),
- e.getModifiers() | InputEvent.BUTTON1_MASK,
- (int) (e.getCanvasPosition().getX() - editor.getX()),
- (int) (e.getCanvasPosition().getY() - editor.getY()),
- 1,
- false);
- editor.dispatchEvent(me);
- }
- });
- }
- });
- }
+ return newText;
+ }
-
- public void reshapeEditor() {
- if (editedText != null) {
- // Update the size to fit the new document - note that it is a 2 stage process
- Dimension prefSize = editor.getPreferredSize();
-
- Insets pInsets = editedText.getInsets();
- Insets jInsets = editor.getInsets();
-
- int width = (editedText.getConstrainWidthToTextWidth()) ? (int)prefSize.getWidth() : (int)(editedText.getWidth()-pInsets.left-pInsets.right+jInsets.left+jInsets.right+3.0);
- prefSize.setSize(width,prefSize.getHeight());
- editor.setSize(prefSize);
+ public void mousePressed(PInputEvent inputEvent) {
+ PNode pickedNode = inputEvent.getPickedNode();
- prefSize = editor.getPreferredSize();
- int height = (editedText.getConstrainHeightToTextHeight()) ? (int)prefSize.getHeight() : (int)(editedText.getHeight()-pInsets.top-pInsets.bottom+jInsets.top+jInsets.bottom+3.0);
- prefSize.setSize(width,height);
- editor.setSize(prefSize);
- }
- }
+ stopEditing();
- /**
- * Sometimes we need to invoke this later because the document events seem to get fired
- * before the text is actually incorporated into the document
- */
- protected void reshapeEditorLater() {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- reshapeEditor();
- }
- });
- }
-
+ if (pickedNode instanceof PStyledText) {
+ startEditing(inputEvent, (PStyledText) pickedNode);
+ }
+ else if (pickedNode instanceof PCamera) {
+ PStyledText newText = createText();
+ Insets pInsets = newText.getInsets();
+ canvas.getLayer().addChild(newText);
+ newText.translate(inputEvent.getPosition().getX() - pInsets.left, inputEvent.getPosition().getY()
+ - pInsets.top);
+ startEditing(inputEvent, newText);
+ }
+ }
+
+ public void startEditing(PInputEvent event, PStyledText text) {
+ // Get the node's top right hand corner
+ Insets pInsets = text.getInsets();
+ Point2D nodePt = new Point2D.Double(text.getX() + pInsets.left, text.getY() + pInsets.top);
+ text.localToGlobal(nodePt);
+ event.getTopCamera().viewToLocal(nodePt);
+
+ // Update the editor to edit the specified node
+ editor.setDocument(text.getDocument());
+ editor.setVisible(true);
+
+ Insets bInsets = editor.getBorder().getBorderInsets(editor);
+ editor.setLocation((int) nodePt.getX() - bInsets.left, (int) nodePt.getY() - bInsets.top);
+ reshapeEditorLater();
+
+ dispatchEventToEditor(event);
+ canvas.repaint();
+
+ text.setEditing(true);
+ text.getDocument().addDocumentListener(docListener);
+ editedText = text;
+ }
+
+ public void stopEditing() {
+ if (editedText != null) {
+ editedText.getDocument().removeDocumentListener(docListener);
+ editedText.setEditing(false);
+
+ if (editedText.getDocument().getLength() == 0) {
+ editedText.removeFromParent();
+ }
+ else {
+ editedText.syncWithDocument();
+ }
+
+ editor.setVisible(false);
+ canvas.repaint();
+
+ editedText = null;
+ }
+ }
+
+ public void dispatchEventToEditor(final PInputEvent e) {
+ // We have to nest the mouse press in two invoke laters so that it is
+ // fired so that the component has been completely validated at the new
+ // size and the mouse event has the correct offset
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ MouseEvent me = new MouseEvent(editor, MouseEvent.MOUSE_PRESSED, e.getWhen(), e.getModifiers()
+ | InputEvent.BUTTON1_MASK, (int) (e.getCanvasPosition().getX() - editor.getX()),
+ (int) (e.getCanvasPosition().getY() - editor.getY()), 1, false);
+ editor.dispatchEvent(me);
+ }
+ });
+ }
+ });
+ }
+
+ public void reshapeEditor() {
+ if (editedText != null) {
+ // Update the size to fit the new document - note that it is a 2
+ // stage process
+ Dimension prefSize = editor.getPreferredSize();
+
+ Insets pInsets = editedText.getInsets();
+ Insets jInsets = editor.getInsets();
+
+ int width = (editedText.getConstrainWidthToTextWidth()) ? (int) prefSize.getWidth() : (int) (editedText
+ .getWidth()
+ - pInsets.left - pInsets.right + jInsets.left + jInsets.right + 3.0);
+ prefSize.setSize(width, prefSize.getHeight());
+ editor.setSize(prefSize);
+
+ prefSize = editor.getPreferredSize();
+ int height = (editedText.getConstrainHeightToTextHeight()) ? (int) prefSize.getHeight() : (int) (editedText
+ .getHeight()
+ - pInsets.top - pInsets.bottom + jInsets.top + jInsets.bottom + 3.0);
+ prefSize.setSize(width, height);
+ editor.setSize(prefSize);
+ }
+ }
+
+ /**
+ * Sometimes we need to invoke this later because the document events seem
+ * to get fired before the text is actually incorporated into the document
+ */
+ protected void reshapeEditorLater() {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ reshapeEditor();
+ }
+ });
+ }
+
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/event/PZoomToEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/event/PZoomToEventHandler.java
index 9a07a14..b3edc7d 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/event/PZoomToEventHandler.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/event/PZoomToEventHandler.java
@@ -41,31 +41,32 @@
/**
* PZoomToEventHandler is used to zoom the camera view to the node
* clicked on with button one.
- * + * * @version 1.0 * @author Jesse Grosjean */ public class PZoomToEventHandler extends PBasicInputEventHandler { - public PZoomToEventHandler() { - setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK)); - } + public PZoomToEventHandler() { + setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK)); + } - public void mousePressed(PInputEvent aEvent) { - zoomTo(aEvent); - } + public void mousePressed(PInputEvent aEvent) { + zoomTo(aEvent); + } - protected void zoomTo(final PInputEvent aEvent) { - PBounds zoomToBounds; - PNode picked = aEvent.getPickedNode(); - - if (picked instanceof PCamera) { - PCamera c = (PCamera) picked; - zoomToBounds = c.getUnionOfLayerFullBounds(); - } else { - zoomToBounds = picked.getGlobalFullBounds(); - } - - aEvent.getCamera().animateViewToCenterBounds(zoomToBounds, true, 500); - } + protected void zoomTo(final PInputEvent aEvent) { + PBounds zoomToBounds; + PNode picked = aEvent.getPickedNode(); + + if (picked instanceof PCamera) { + PCamera c = (PCamera) picked; + zoomToBounds = c.getUnionOfLayerFullBounds(); + } + else { + zoomToBounds = picked.getGlobalFullBounds(); + } + + aEvent.getCamera().animateViewToCenterBounds(zoomToBounds, true, 500); + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/handles/PBoundsHandle.java b/extras/src/main/java/edu/umd/cs/piccolox/handles/PBoundsHandle.java index 14d536f..300cb2d 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/handles/PBoundsHandle.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/handles/PBoundsHandle.java @@ -48,296 +48,307 @@ /** * PBoundsHandle a handle for resizing the bounds of another node. If a * bounds handle is dragged such that the other node's width or height becomes - * negative then the each drag handle's locator assciated with that - * other node is "flipped" so that they are attached to and dragging a different - * corner of the nodes bounds. - *
+ * negative then the each drag handle's locator assciated with that other node + * is "flipped" so that they are attached to and dragging a different corner of + * the nodes bounds. + * * @version 1.0 * @author Jesse Grosjean */ public class PBoundsHandle extends PHandle { - - private transient PBasicInputEventHandler handleCursorHandler; - - public static void addBoundsHandlesTo(PNode aNode) { - aNode.addChild(new PBoundsHandle(PBoundsLocator.createEastLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createWestLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createNorthLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createSouthLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode))); - aNode.addChild(new PBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode))); - } - public static void addStickyBoundsHandlesTo(PNode aNode, PCamera camera) { - camera.addChild(new PBoundsHandle(PBoundsLocator.createEastLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createWestLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createNorthLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createSouthLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode))); - camera.addChild(new PBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode))); - } - - public static void removeBoundsHandlesFrom(PNode aNode) { - ArrayList handles = new ArrayList(); + private transient PBasicInputEventHandler handleCursorHandler; - Iterator i = aNode.getChildrenIterator(); - while (i.hasNext()) { - PNode each = (PNode) i.next(); - if (each instanceof PBoundsHandle) { - handles.add(each); - } - } - aNode.removeChildren(handles); - } - - public PBoundsHandle(PBoundsLocator aLocator) { - super(aLocator); - } - - protected void installHandleEventHandlers() { - super.installHandleEventHandlers(); - handleCursorHandler = new PBasicInputEventHandler() { - boolean cursorPushed = false; - public void mouseEntered(PInputEvent aEvent) { - if (!cursorPushed) { - aEvent.pushCursor(getCursorFor(((PBoundsLocator)getLocator()).getSide())); - cursorPushed = true; - } - } - public void mouseExited(PInputEvent aEvent) { - PPickPath focus = aEvent.getInputManager().getMouseFocus(); - if (cursorPushed) { - if (focus == null || focus.getPickedNode() != PBoundsHandle.this) { - aEvent.popCursor(); - cursorPushed = false; - } - } - } - public void mouseReleased(PInputEvent event) { - if (cursorPushed) { - event.popCursor(); - cursorPushed = false; - } - } - }; - addInputEventListener(handleCursorHandler); - } + public static void addBoundsHandlesTo(PNode aNode) { + aNode.addChild(new PBoundsHandle(PBoundsLocator.createEastLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createWestLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createNorthLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createSouthLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode))); + aNode.addChild(new PBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode))); + } - /** - * Return the event handler that is responsible for setting the mouse - * cursor when it enters/exits this handle. - */ - public PBasicInputEventHandler getHandleCursorEventHandler() { - return handleCursorHandler; - } + public static void addStickyBoundsHandlesTo(PNode aNode, PCamera camera) { + camera.addChild(new PBoundsHandle(PBoundsLocator.createEastLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createWestLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createNorthLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createSouthLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode))); + camera.addChild(new PBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode))); + } - public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { - PBoundsLocator l = (PBoundsLocator) getLocator(); - l.getNode().startResizeBounds(); - } - - public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) { - PBoundsLocator l = (PBoundsLocator) getLocator(); - - PNode n = l.getNode(); - PBounds b = n.getBounds(); + public static void removeBoundsHandlesFrom(PNode aNode) { + ArrayList handles = new ArrayList(); - PNode parent = getParent(); - if (parent != n && parent instanceof PCamera) { - ((PCamera)parent).localToView(aLocalDimension); - } + Iterator i = aNode.getChildrenIterator(); + while (i.hasNext()) { + PNode each = (PNode) i.next(); + if (each instanceof PBoundsHandle) { + handles.add(each); + } + } + aNode.removeChildren(handles); + } - localToGlobal(aLocalDimension); - n.globalToLocal(aLocalDimension); - - double dx = aLocalDimension.getWidth(); - double dy = aLocalDimension.getHeight(); - - switch (l.getSide()) { - case SwingConstants.NORTH: - b.setRect(b.x, b.y + dy, b.width, b.height - dy); - break; - - case SwingConstants.SOUTH: - b.setRect(b.x, b.y, b.width, b.height + dy); - break; - - case SwingConstants.EAST: - b.setRect(b.x, b.y, b.width + dx, b.height); - break; - - case SwingConstants.WEST: - b.setRect(b.x + dx, b.y, b.width - dx, b.height); - break; - - case SwingConstants.NORTH_WEST: - b.setRect(b.x + dx, b.y + dy, b.width - dx, b.height - dy); - break; - - case SwingConstants.SOUTH_WEST: - b.setRect(b.x + dx, b.y, b.width - dx, b.height + dy); - break; - - case SwingConstants.NORTH_EAST: - b.setRect(b.x, b.y + dy, b.width + dx, b.height - dy); - break; - - case SwingConstants.SOUTH_EAST: - b.setRect(b.x, b.y, b.width + dx, b.height + dy); - break; - } + public PBoundsHandle(PBoundsLocator aLocator) { + super(aLocator); + } - boolean flipX = false; - boolean flipY = false; - - if (b.width < 0) { - flipX = true; - b.width = -b.width; - b.x -= b.width; - } - - if (b.height < 0) { - flipY = true; - b.height = -b.height; - b.y -= b.height; - } - - if (flipX || flipY) { - flipSiblingBoundsHandles(flipX, flipY); - } - - n.setBounds(b); - } - - public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { - PBoundsLocator l = (PBoundsLocator) getLocator(); - l.getNode().endResizeBounds(); - } - - public void flipSiblingBoundsHandles(boolean flipX, boolean flipY) { - Iterator i = getParent().getChildrenIterator(); - while (i.hasNext()) { - Object each = i.next(); - if (each instanceof PBoundsHandle) { - ((PBoundsHandle)each).flipHandleIfNeeded(flipX, flipY); - } - } - } - - public void flipHandleIfNeeded(boolean flipX, boolean flipY) { - PBoundsLocator l = (PBoundsLocator) getLocator(); - - if (flipX || flipY) { - switch (l.getSide()) { - case SwingConstants.NORTH: { - if (flipY) { - l.setSide(SwingConstants.SOUTH); - } - break; - } - - case SwingConstants.SOUTH: { - if (flipY) { - l.setSide(SwingConstants.NORTH); - } - break; - } - - case SwingConstants.EAST: { - if (flipX) { - l.setSide(SwingConstants.WEST); - } - break; - } - - case SwingConstants.WEST: { - if (flipX) { - l.setSide(SwingConstants.EAST); - } - break; - } - - case SwingConstants.NORTH_WEST: { - if (flipX && flipY) { - l.setSide(SwingConstants.SOUTH_EAST); - } else if (flipX) { - l.setSide(SwingConstants.NORTH_EAST); - } else if (flipY) { - l.setSide(SwingConstants.SOUTH_WEST); - } - - break; - } - - case SwingConstants.SOUTH_WEST: { - if (flipX && flipY) { - l.setSide(SwingConstants.NORTH_EAST); - } else if (flipX) { - l.setSide(SwingConstants.SOUTH_EAST); - } else if (flipY) { - l.setSide(SwingConstants.NORTH_WEST); - } - break; - } - - case SwingConstants.NORTH_EAST: { - if (flipX && flipY) { - l.setSide(SwingConstants.SOUTH_WEST); - } else if (flipX) { - l.setSide(SwingConstants.NORTH_WEST); - } else if (flipY) { - l.setSide(SwingConstants.SOUTH_EAST); - } - break; - } - - case SwingConstants.SOUTH_EAST: { - if (flipX && flipY) { - l.setSide(SwingConstants.NORTH_WEST); - } else if (flipX) { - l.setSide(SwingConstants.SOUTH_WEST); - } else if (flipY) { - l.setSide(SwingConstants.NORTH_EAST); - } - break; - } - } - } - - // reset locator to update layout - setLocator(l); - } - - public Cursor getCursorFor(int side) { - switch (side) { - case SwingConstants.NORTH: - return new Cursor(Cursor.N_RESIZE_CURSOR); + protected void installHandleEventHandlers() { + super.installHandleEventHandlers(); + handleCursorHandler = new PBasicInputEventHandler() { + boolean cursorPushed = false; - case SwingConstants.SOUTH: - return new Cursor(Cursor.S_RESIZE_CURSOR); - - case SwingConstants.EAST: - return new Cursor(Cursor.E_RESIZE_CURSOR); - - case SwingConstants.WEST: - return new Cursor(Cursor.W_RESIZE_CURSOR); - - case SwingConstants.NORTH_WEST: - return new Cursor(Cursor.NW_RESIZE_CURSOR); - - case SwingConstants.SOUTH_WEST: - return new Cursor(Cursor.SW_RESIZE_CURSOR); - - case SwingConstants.NORTH_EAST: - return new Cursor(Cursor.NE_RESIZE_CURSOR); - - case SwingConstants.SOUTH_EAST: - return new Cursor(Cursor.SE_RESIZE_CURSOR); - } - return null; - } + public void mouseEntered(PInputEvent aEvent) { + if (!cursorPushed) { + aEvent.pushCursor(getCursorFor(((PBoundsLocator) getLocator()).getSide())); + cursorPushed = true; + } + } + + public void mouseExited(PInputEvent aEvent) { + PPickPath focus = aEvent.getInputManager().getMouseFocus(); + if (cursorPushed) { + if (focus == null || focus.getPickedNode() != PBoundsHandle.this) { + aEvent.popCursor(); + cursorPushed = false; + } + } + } + + public void mouseReleased(PInputEvent event) { + if (cursorPushed) { + event.popCursor(); + cursorPushed = false; + } + } + }; + addInputEventListener(handleCursorHandler); + } + + /** + * Return the event handler that is responsible for setting the mouse cursor + * when it enters/exits this handle. + */ + public PBasicInputEventHandler getHandleCursorEventHandler() { + return handleCursorHandler; + } + + public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { + PBoundsLocator l = (PBoundsLocator) getLocator(); + l.getNode().startResizeBounds(); + } + + public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) { + PBoundsLocator l = (PBoundsLocator) getLocator(); + + PNode n = l.getNode(); + PBounds b = n.getBounds(); + + PNode parent = getParent(); + if (parent != n && parent instanceof PCamera) { + ((PCamera) parent).localToView(aLocalDimension); + } + + localToGlobal(aLocalDimension); + n.globalToLocal(aLocalDimension); + + double dx = aLocalDimension.getWidth(); + double dy = aLocalDimension.getHeight(); + + switch (l.getSide()) { + case SwingConstants.NORTH: + b.setRect(b.x, b.y + dy, b.width, b.height - dy); + break; + + case SwingConstants.SOUTH: + b.setRect(b.x, b.y, b.width, b.height + dy); + break; + + case SwingConstants.EAST: + b.setRect(b.x, b.y, b.width + dx, b.height); + break; + + case SwingConstants.WEST: + b.setRect(b.x + dx, b.y, b.width - dx, b.height); + break; + + case SwingConstants.NORTH_WEST: + b.setRect(b.x + dx, b.y + dy, b.width - dx, b.height - dy); + break; + + case SwingConstants.SOUTH_WEST: + b.setRect(b.x + dx, b.y, b.width - dx, b.height + dy); + break; + + case SwingConstants.NORTH_EAST: + b.setRect(b.x, b.y + dy, b.width + dx, b.height - dy); + break; + + case SwingConstants.SOUTH_EAST: + b.setRect(b.x, b.y, b.width + dx, b.height + dy); + break; + } + + boolean flipX = false; + boolean flipY = false; + + if (b.width < 0) { + flipX = true; + b.width = -b.width; + b.x -= b.width; + } + + if (b.height < 0) { + flipY = true; + b.height = -b.height; + b.y -= b.height; + } + + if (flipX || flipY) { + flipSiblingBoundsHandles(flipX, flipY); + } + + n.setBounds(b); + } + + public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { + PBoundsLocator l = (PBoundsLocator) getLocator(); + l.getNode().endResizeBounds(); + } + + public void flipSiblingBoundsHandles(boolean flipX, boolean flipY) { + Iterator i = getParent().getChildrenIterator(); + while (i.hasNext()) { + Object each = i.next(); + if (each instanceof PBoundsHandle) { + ((PBoundsHandle) each).flipHandleIfNeeded(flipX, flipY); + } + } + } + + public void flipHandleIfNeeded(boolean flipX, boolean flipY) { + PBoundsLocator l = (PBoundsLocator) getLocator(); + + if (flipX || flipY) { + switch (l.getSide()) { + case SwingConstants.NORTH: { + if (flipY) { + l.setSide(SwingConstants.SOUTH); + } + break; + } + + case SwingConstants.SOUTH: { + if (flipY) { + l.setSide(SwingConstants.NORTH); + } + break; + } + + case SwingConstants.EAST: { + if (flipX) { + l.setSide(SwingConstants.WEST); + } + break; + } + + case SwingConstants.WEST: { + if (flipX) { + l.setSide(SwingConstants.EAST); + } + break; + } + + case SwingConstants.NORTH_WEST: { + if (flipX && flipY) { + l.setSide(SwingConstants.SOUTH_EAST); + } + else if (flipX) { + l.setSide(SwingConstants.NORTH_EAST); + } + else if (flipY) { + l.setSide(SwingConstants.SOUTH_WEST); + } + + break; + } + + case SwingConstants.SOUTH_WEST: { + if (flipX && flipY) { + l.setSide(SwingConstants.NORTH_EAST); + } + else if (flipX) { + l.setSide(SwingConstants.SOUTH_EAST); + } + else if (flipY) { + l.setSide(SwingConstants.NORTH_WEST); + } + break; + } + + case SwingConstants.NORTH_EAST: { + if (flipX && flipY) { + l.setSide(SwingConstants.SOUTH_WEST); + } + else if (flipX) { + l.setSide(SwingConstants.NORTH_WEST); + } + else if (flipY) { + l.setSide(SwingConstants.SOUTH_EAST); + } + break; + } + + case SwingConstants.SOUTH_EAST: { + if (flipX && flipY) { + l.setSide(SwingConstants.NORTH_WEST); + } + else if (flipX) { + l.setSide(SwingConstants.SOUTH_WEST); + } + else if (flipY) { + l.setSide(SwingConstants.NORTH_EAST); + } + break; + } + } + } + + // reset locator to update layout + setLocator(l); + } + + public Cursor getCursorFor(int side) { + switch (side) { + case SwingConstants.NORTH: + return new Cursor(Cursor.N_RESIZE_CURSOR); + + case SwingConstants.SOUTH: + return new Cursor(Cursor.S_RESIZE_CURSOR); + + case SwingConstants.EAST: + return new Cursor(Cursor.E_RESIZE_CURSOR); + + case SwingConstants.WEST: + return new Cursor(Cursor.W_RESIZE_CURSOR); + + case SwingConstants.NORTH_WEST: + return new Cursor(Cursor.NW_RESIZE_CURSOR); + + case SwingConstants.SOUTH_WEST: + return new Cursor(Cursor.SW_RESIZE_CURSOR); + + case SwingConstants.NORTH_EAST: + return new Cursor(Cursor.NE_RESIZE_CURSOR); + + case SwingConstants.SOUTH_EAST: + return new Cursor(Cursor.SE_RESIZE_CURSOR); + } + return null; + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/handles/PHandle.java b/extras/src/main/java/edu/umd/cs/piccolox/handles/PHandle.java index 8f2a2c7..a42fba6 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/handles/PHandle.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/handles/PHandle.java @@ -51,170 +51,174 @@ import edu.umd.cs.piccolox.util.PNodeLocator; /** - * PHandle is used to modify some aspect of Piccolo when it - * is dragged. Each handle has a PLocator that it uses to automatically position - * itself. See PBoundsHandle for an example of a handle that resizes the bounds - * of another node. - *
+ * PHandle is used to modify some aspect of Piccolo when it is dragged. + * Each handle has a PLocator that it uses to automatically position itself. See + * PBoundsHandle for an example of a handle that resizes the bounds of another + * node. + * * @version 1.0 * @author Jesse Grosjean */ public class PHandle extends PPath { - public static float DEFAULT_HANDLE_SIZE = 8; - public static Shape DEFAULT_HANDLE_SHAPE = new Ellipse2D.Float(0f, 0f, DEFAULT_HANDLE_SIZE, DEFAULT_HANDLE_SIZE); - public static Color DEFAULT_COLOR = Color.white; - - private PLocator locator; - private transient PDragSequenceEventHandler handleDragger; + public static float DEFAULT_HANDLE_SIZE = 8; + public static Shape DEFAULT_HANDLE_SHAPE = new Ellipse2D.Float(0f, 0f, DEFAULT_HANDLE_SIZE, DEFAULT_HANDLE_SIZE); + public static Color DEFAULT_COLOR = Color.white; - /** - * Construct a new handle that will use the given locator - * to locate itself on its parent node. - */ - public PHandle(PLocator aLocator) { - super(DEFAULT_HANDLE_SHAPE); - locator = aLocator; - setPaint(DEFAULT_COLOR); - installHandleEventHandlers(); - } + private PLocator locator; + private transient PDragSequenceEventHandler handleDragger; - protected void installHandleEventHandlers() { - handleDragger = new PDragSequenceEventHandler() { - protected void startDrag(PInputEvent event) { - super.startDrag(event); - startHandleDrag(event.getPositionRelativeTo(PHandle.this), event); - } - protected void drag(PInputEvent event) { - super.drag(event); - PDimension aDelta = event.getDeltaRelativeTo(PHandle.this); - if (aDelta.getWidth() != 0 || aDelta.getHeight() != 0) { - dragHandle(aDelta, event); - } - } - protected void endDrag(PInputEvent event) { - super.endDrag(event); - endHandleDrag(event.getPositionRelativeTo(PHandle.this), event); - } - }; + /** + * Construct a new handle that will use the given locator to locate itself + * on its parent node. + */ + public PHandle(PLocator aLocator) { + super(DEFAULT_HANDLE_SHAPE); + locator = aLocator; + setPaint(DEFAULT_COLOR); + installHandleEventHandlers(); + } - addPropertyChangeListener(PNode.PROPERTY_TRANSFORM, new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - relocateHandle(); - } - }); - - handleDragger.setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK)); - handleDragger.getEventFilter().setMarksAcceptedEventsAsHandled(true); - handleDragger.getEventFilter().setAcceptsMouseEntered(false); - handleDragger.getEventFilter().setAcceptsMouseExited(false); - handleDragger.getEventFilter().setAcceptsMouseMoved(false); // no need for moved events for handle interaction, - // so reject them so we don't consume them - addInputEventListener(handleDragger); - } - - /** - * Return the event handler that is responsible for the drag handle - * interaction. - */ - public PDragSequenceEventHandler getHandleDraggerHandler() { - return handleDragger; - } + protected void installHandleEventHandlers() { + handleDragger = new PDragSequenceEventHandler() { + protected void startDrag(PInputEvent event) { + super.startDrag(event); + startHandleDrag(event.getPositionRelativeTo(PHandle.this), event); + } - /** - * Get the locator that this handle uses to position itself on its - * parent node. - */ - public PLocator getLocator() { - return locator; - } - - /** - * Set the locator that this handle uses to position itself on its - * parent node. - */ - public void setLocator(PLocator aLocator) { - locator = aLocator; - invalidatePaint(); - relocateHandle(); - } - - //**************************************************************** - // Handle Dragging - These are the methods the subclasses should - // normally override to give a handle unique behavior. - //**************************************************************** - - /** - * Override this method to get notified when the handle starts to get dragged. - */ - public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { - } - - /** - * Override this method to get notified as the handle is dragged. - */ - public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) { - } - - /** - * Override this method to get notified when the handle stops getting dragged. - */ - public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { - } - - //**************************************************************** - // Layout - When a handle's parent's layout changes the handle - // invalidates its own layout and then repositions itself on its - // parents bounds using its locator to determine that new - // position. - //**************************************************************** - - public void setParent(PNode newParent) { - super.setParent(newParent); - relocateHandle(); - } - - public void parentBoundsChanged() { - relocateHandle(); - } - - /** - * Force this handle to relocate itself using its locator. - */ - public void relocateHandle() { - if (locator != null) { - PBounds b = getBoundsReference(); - Point2D aPoint = locator.locatePoint(null); - - if (locator instanceof PNodeLocator) { - PNode located = ((PNodeLocator)locator).getNode(); - PNode parent = getParent(); - - located.localToGlobal(aPoint); - globalToLocal(aPoint); - - if (parent != located && parent instanceof PCamera) { - ((PCamera)parent).viewToLocal(aPoint); - } - } - - double newCenterX = aPoint.getX(); - double newCenterY = aPoint.getY(); + protected void drag(PInputEvent event) { + super.drag(event); + PDimension aDelta = event.getDeltaRelativeTo(PHandle.this); + if (aDelta.getWidth() != 0 || aDelta.getHeight() != 0) { + dragHandle(aDelta, event); + } + } - if (newCenterX != b.getCenterX() || - newCenterY != b.getCenterY()) { - - centerBoundsOnPoint(newCenterX, newCenterY); - } - } - } - - //**************************************************************** - // Serialization - //**************************************************************** - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - installHandleEventHandlers(); - } + protected void endDrag(PInputEvent event) { + super.endDrag(event); + endHandleDrag(event.getPositionRelativeTo(PHandle.this), event); + } + }; + + addPropertyChangeListener(PNode.PROPERTY_TRANSFORM, new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + relocateHandle(); + } + }); + + handleDragger.setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK)); + handleDragger.getEventFilter().setMarksAcceptedEventsAsHandled(true); + handleDragger.getEventFilter().setAcceptsMouseEntered(false); + handleDragger.getEventFilter().setAcceptsMouseExited(false); + // no need for moved events for handle interaction, + handleDragger.getEventFilter().setAcceptsMouseMoved(false); + // so reject them so we don't consume them + addInputEventListener(handleDragger); + } + + /** + * Return the event handler that is responsible for the drag handle + * interaction. + */ + public PDragSequenceEventHandler getHandleDraggerHandler() { + return handleDragger; + } + + /** + * Get the locator that this handle uses to position itself on its parent + * node. + */ + public PLocator getLocator() { + return locator; + } + + /** + * Set the locator that this handle uses to position itself on its parent + * node. + */ + public void setLocator(PLocator aLocator) { + locator = aLocator; + invalidatePaint(); + relocateHandle(); + } + + // **************************************************************** + // Handle Dragging - These are the methods the subclasses should + // normally override to give a handle unique behavior. + // **************************************************************** + + /** + * Override this method to get notified when the handle starts to get + * dragged. + */ + public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { + } + + /** + * Override this method to get notified as the handle is dragged. + */ + public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) { + } + + /** + * Override this method to get notified when the handle stops getting + * dragged. + */ + public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) { + } + + // **************************************************************** + // Layout - When a handle's parent's layout changes the handle + // invalidates its own layout and then repositions itself on its + // parents bounds using its locator to determine that new + // position. + // **************************************************************** + + public void setParent(PNode newParent) { + super.setParent(newParent); + relocateHandle(); + } + + public void parentBoundsChanged() { + relocateHandle(); + } + + /** + * Force this handle to relocate itself using its locator. + */ + public void relocateHandle() { + if (locator != null) { + PBounds b = getBoundsReference(); + Point2D aPoint = locator.locatePoint(null); + + if (locator instanceof PNodeLocator) { + PNode located = ((PNodeLocator) locator).getNode(); + PNode parent = getParent(); + + located.localToGlobal(aPoint); + globalToLocal(aPoint); + + if (parent != located && parent instanceof PCamera) { + ((PCamera) parent).viewToLocal(aPoint); + } + } + + double newCenterX = aPoint.getX(); + double newCenterY = aPoint.getY(); + + if (newCenterX != b.getCenterX() || newCenterY != b.getCenterY()) { + + centerBoundsOnPoint(newCenterX, newCenterY); + } + } + } + + // **************************************************************** + // Serialization + // **************************************************************** + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + installHandleEventHandlers(); + } } \ No newline at end of file diff --git a/extras/src/main/java/edu/umd/cs/piccolox/handles/PStickyHandleManager.java b/extras/src/main/java/edu/umd/cs/piccolox/handles/PStickyHandleManager.java index a74c6be..8ff8774 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/handles/PStickyHandleManager.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/handles/PStickyHandleManager.java @@ -35,54 +35,54 @@ import edu.umd.cs.piccolo.util.PPickPath; public class PStickyHandleManager extends PNode { - - private PNode target; - private PCamera camera; - - public PStickyHandleManager(PCamera newCamera, PNode newTarget) { - setCameraTarget(newCamera, newTarget); - PBoundsHandle.addBoundsHandlesTo(this); - } - public void setCameraTarget(PCamera newCamera, PNode newTarget) { - camera = newCamera; - camera.addChild(this); - target = newTarget; - } - - public boolean setBounds(double x, double y, double width, double height) { - PBounds b = new PBounds(x, y, width, height); - camera.localToGlobal(b); - camera.localToView(b); - target.globalToLocal(b); - target.setBounds(b); - return super.setBounds(x, y, width, height); - } - - protected boolean getBoundsVolatile() { - return true; - } + private PNode target; + private PCamera camera; - public PBounds getBoundsReference() { - PBounds targetBounds = target.getFullBounds(); - camera.viewToLocal(targetBounds); - camera.globalToLocal(targetBounds); - PBounds bounds = super.getBoundsReference(); - bounds.setRect(targetBounds); - return super.getBoundsReference(); - } + public PStickyHandleManager(PCamera newCamera, PNode newTarget) { + setCameraTarget(newCamera, newTarget); + PBoundsHandle.addBoundsHandlesTo(this); + } - public void startResizeBounds() { - super.startResizeBounds(); - target.startResizeBounds(); - } + public void setCameraTarget(PCamera newCamera, PNode newTarget) { + camera = newCamera; + camera.addChild(this); + target = newTarget; + } - public void endResizeBounds() { - super.endResizeBounds(); - target.endResizeBounds(); - } + public boolean setBounds(double x, double y, double width, double height) { + PBounds b = new PBounds(x, y, width, height); + camera.localToGlobal(b); + camera.localToView(b); + target.globalToLocal(b); + target.setBounds(b); + return super.setBounds(x, y, width, height); + } - public boolean pickAfterChildren(PPickPath pickPath) { - return false; - } + protected boolean getBoundsVolatile() { + return true; + } + + public PBounds getBoundsReference() { + PBounds targetBounds = target.getFullBounds(); + camera.viewToLocal(targetBounds); + camera.globalToLocal(targetBounds); + PBounds bounds = super.getBoundsReference(); + bounds.setRect(targetBounds); + return super.getBoundsReference(); + } + + public void startResizeBounds() { + super.startResizeBounds(); + target.startResizeBounds(); + } + + public void endResizeBounds() { + super.endResizeBounds(); + target.endResizeBounds(); + } + + public boolean pickAfterChildren(PPickPath pickPath) { + return false; + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/P3DRect.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/P3DRect.java index b810656..37e6c18 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/P3DRect.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/P3DRect.java @@ -36,134 +36,137 @@ import edu.umd.cs.piccolox.*; /** - * This is a simple node that draws a "3D" rectangle within the bounds of the node. - * Drawing a 3D rectangle in a zooming environment is a little tricky because - * if you just use the regular (Java2D) 3D rectangle, the 3D borders get scaled, - * and that is ugly. This version always draws the 3D border at fixed 2 pixel width. + * This is a simple node that draws a "3D" rectangle within the bounds of the + * node. Drawing a 3D rectangle in a zooming environment is a little tricky + * because if you just use the regular (Java2D) 3D rectangle, the 3D borders get + * scaled, and that is ugly. This version always draws the 3D border at fixed 2 + * pixel width. * * @author Ben Bederson */ public class P3DRect extends PNode { - private Color topLeftOuterColor; - private Color topLeftInnerColor; - private Color bottomRightInnerColor; - private Color bottomRightOuterColor; - private GeneralPath path; - private Stroke stroke; - private boolean raised; - - public P3DRect() { - raised = true; - stroke = new BasicStroke(0); - path = new GeneralPath(); - } - - public P3DRect(Rectangle2D bounds) { - this(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); - } - - public P3DRect(double x, double y, double width, double height) { - this(); - setBounds(x, y, width, height); - } - - public void setRaised(boolean raised) { - this.raised = raised; - setPaint(getPaint()); - } - - public boolean getRaised() { - return raised; - } - - protected void paint(PPaintContext paintContext) { - Graphics2D g2 = paintContext.getGraphics(); - - double x = getX(); - double y = getY(); - double width = getWidth(); - double height = getHeight(); - double magX = g2.getTransform().getScaleX(); - double magY = g2.getTransform().getScaleY(); - double dx = (float)(1.0 / magX); - double dy = (float)(1.0 / magY); - PBounds bounds = getBounds(); - - g2.setPaint(getPaint()); - g2.fill(bounds); - g2.setStroke(stroke); + private Color topLeftOuterColor; + private Color topLeftInnerColor; + private Color bottomRightInnerColor; + private Color bottomRightOuterColor; + private GeneralPath path; + private Stroke stroke; + private boolean raised; - path.reset(); - path.moveTo((float)(x+width), (float)y); - path.lineTo((float)x, (float)y); - path.lineTo((float)x, (float)(y+height)); - g2.setPaint(topLeftOuterColor); - g2.draw(path); + public P3DRect() { + raised = true; + stroke = new BasicStroke(0); + path = new GeneralPath(); + } - path.reset(); - path.moveTo((float)(x+width), (float)(y+dy)); - path.lineTo((float)(x+dx), (float)(y+dy)); - path.lineTo((float)(x+dx), (float)(y+height)); - g2.setPaint(topLeftInnerColor); - g2.draw(path); + public P3DRect(Rectangle2D bounds) { + this(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); + } - path.reset(); - path.moveTo((float)(x+width), (float)(y)); - path.lineTo((float)(x+width), (float)(y+height)); - path.lineTo((float)(x), (float)(y+height)); - g2.setPaint(bottomRightOuterColor); - g2.draw(path); + public P3DRect(double x, double y, double width, double height) { + this(); + setBounds(x, y, width, height); + } - path.reset(); - path.moveTo((float)(x+width-dx), (float)(y+dy)); - path.lineTo((float)(x+width-dx), (float)(y+height-dy)); - path.lineTo((float)(x), (float)(y+height-dy)); - g2.setPaint(bottomRightInnerColor); - g2.draw(path); - } + public void setRaised(boolean raised) { + this.raised = raised; + setPaint(getPaint()); + } - public void setPaint(Paint newPaint) { - super.setPaint(newPaint); - - if (newPaint instanceof Color) { - Color color = (Color)newPaint; - - if (raised) { - topLeftOuterColor = color.brighter(); - topLeftInnerColor = topLeftOuterColor.brighter(); - bottomRightInnerColor = color.darker(); - bottomRightOuterColor = bottomRightInnerColor.darker(); - } else { - topLeftOuterColor = color.darker(); - topLeftInnerColor = topLeftOuterColor.darker(); - bottomRightInnerColor = color.brighter(); - bottomRightOuterColor = bottomRightInnerColor.brighter(); - } - } else { - topLeftOuterColor = null; - topLeftInnerColor = null; - bottomRightInnerColor = null; - bottomRightOuterColor = null; - } - } + public boolean getRaised() { + return raised; + } - public static void main(String[] args) { - new PFrame() { - public void initialize() { - getCanvas().setDefaultRenderQuality(PPaintContext.LOW_QUALITY_RENDERING); + protected void paint(PPaintContext paintContext) { + Graphics2D g2 = paintContext.getGraphics(); - P3DRect rect1 = new P3DRect(50, 50, 100, 100); - rect1.setPaint(new Color(239, 235, 222)); + double x = getX(); + double y = getY(); + double width = getWidth(); + double height = getHeight(); + double magX = g2.getTransform().getScaleX(); + double magY = g2.getTransform().getScaleY(); + double dx = (float) (1.0 / magX); + double dy = (float) (1.0 / magY); + PBounds bounds = getBounds(); - P3DRect rect2 = new P3DRect(50, 50, 100, 100); - rect2.setPaint(new Color(239, 235, 222)); - rect2.translate(110, 0); - rect2.setRaised(false); - - getCanvas().getLayer().addChild(rect1); - getCanvas().getLayer().addChild(rect2); - } - }; - } + g2.setPaint(getPaint()); + g2.fill(bounds); + g2.setStroke(stroke); + + path.reset(); + path.moveTo((float) (x + width), (float) y); + path.lineTo((float) x, (float) y); + path.lineTo((float) x, (float) (y + height)); + g2.setPaint(topLeftOuterColor); + g2.draw(path); + + path.reset(); + path.moveTo((float) (x + width), (float) (y + dy)); + path.lineTo((float) (x + dx), (float) (y + dy)); + path.lineTo((float) (x + dx), (float) (y + height)); + g2.setPaint(topLeftInnerColor); + g2.draw(path); + + path.reset(); + path.moveTo((float) (x + width), (float) (y)); + path.lineTo((float) (x + width), (float) (y + height)); + path.lineTo((float) (x), (float) (y + height)); + g2.setPaint(bottomRightOuterColor); + g2.draw(path); + + path.reset(); + path.moveTo((float) (x + width - dx), (float) (y + dy)); + path.lineTo((float) (x + width - dx), (float) (y + height - dy)); + path.lineTo((float) (x), (float) (y + height - dy)); + g2.setPaint(bottomRightInnerColor); + g2.draw(path); + } + + public void setPaint(Paint newPaint) { + super.setPaint(newPaint); + + if (newPaint instanceof Color) { + Color color = (Color) newPaint; + + if (raised) { + topLeftOuterColor = color.brighter(); + topLeftInnerColor = topLeftOuterColor.brighter(); + bottomRightInnerColor = color.darker(); + bottomRightOuterColor = bottomRightInnerColor.darker(); + } + else { + topLeftOuterColor = color.darker(); + topLeftInnerColor = topLeftOuterColor.darker(); + bottomRightInnerColor = color.brighter(); + bottomRightOuterColor = bottomRightInnerColor.brighter(); + } + } + else { + topLeftOuterColor = null; + topLeftInnerColor = null; + bottomRightInnerColor = null; + bottomRightOuterColor = null; + } + } + + public static void main(String[] args) { + new PFrame() { + public void initialize() { + getCanvas().setDefaultRenderQuality(PPaintContext.LOW_QUALITY_RENDERING); + + P3DRect rect1 = new P3DRect(50, 50, 100, 100); + rect1.setPaint(new Color(239, 235, 222)); + + P3DRect rect2 = new P3DRect(50, 50, 100, 100); + rect2.setPaint(new Color(239, 235, 222)); + rect2.translate(110, 0); + rect2.setRaised(false); + + getCanvas().getLayer().addChild(rect1); + getCanvas().getLayer().addChild(rect2); + } + }; + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PCacheCamera.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PCacheCamera.java index 5697cb7..e741475 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PCacheCamera.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PCacheCamera.java @@ -20,146 +20,157 @@ import edu.umd.cs.piccolo.util.PUtil; /** - * An extension to PCamera that provides a fast image based animationToCenterBounds method + * An extension to PCamera that provides a fast image based + * animationToCenterBounds method * * @author Lance Good */ public class PCacheCamera extends PCamera { - - private BufferedImage paintBuffer; - private boolean imageAnimate; - private PBounds imageAnimateBounds; - - /** - * Get the buffer used to provide fast image based animation - */ - protected BufferedImage getPaintBuffer() { - PBounds fRef = getFullBoundsReference(); - if (paintBuffer == null || paintBuffer.getWidth() < fRef.getWidth() || paintBuffer.getHeight() < fRef.getHeight()) { - paintBuffer = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage((int)Math.ceil(fRef.getWidth()),(int)Math.ceil(fRef.getHeight())); - } - return paintBuffer; - } - - /** - * Caches the information necessary to animate from the current view bounds to the - * specified centerBounds - */ - private AffineTransform cacheViewBounds(Rectangle2D centerBounds, boolean scaleToFit) { - PBounds viewBounds = getViewBounds(); - - // Initialize the image to the union of the current and destination bounds - PBounds imageBounds = new PBounds(viewBounds); - imageBounds.add(centerBounds); - animateViewToCenterBounds(imageBounds,scaleToFit,0); + private BufferedImage paintBuffer; + private boolean imageAnimate; + private PBounds imageAnimateBounds; + + /** + * Get the buffer used to provide fast image based animation + */ + protected BufferedImage getPaintBuffer() { + PBounds fRef = getFullBoundsReference(); + // TODO eclipse formatting made this ugly + if (paintBuffer == null || paintBuffer.getWidth() < fRef.getWidth() + || paintBuffer.getHeight() < fRef.getHeight()) { + paintBuffer = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() + .getDefaultConfiguration().createCompatibleImage((int) Math.ceil(fRef.getWidth()), + (int) Math.ceil(fRef.getHeight())); + } + return paintBuffer; + } + + /** + * Caches the information necessary to animate from the current view bounds + * to the specified centerBounds + */ + private AffineTransform cacheViewBounds(Rectangle2D centerBounds, boolean scaleToFit) { + PBounds viewBounds = getViewBounds(); + + // Initialize the image to the union of the current and destination + // bounds + PBounds imageBounds = new PBounds(viewBounds); + imageBounds.add(centerBounds); + + animateViewToCenterBounds(imageBounds, scaleToFit, 0); imageAnimateBounds = getViewBounds(); - // Now create the actual cache image that we will use to animate fast - - BufferedImage buffer = getPaintBuffer(); - Paint fPaint = Color.white; - if (getPaint() != null) { - fPaint = getPaint(); - } - toImage(buffer,fPaint); + // Now create the actual cache image that we will use to animate fast - // Do this after the painting above! - imageAnimate = true; - - // Return the bounds to the previous viewbounds - animateViewToCenterBounds(viewBounds,scaleToFit,0); - - // The code below is just copied from animateViewToCenterBounds to create the - // correct transform to center the specified bounds - - PDimension delta = viewBounds.deltaRequiredToCenter(centerBounds); - PAffineTransform newTransform = getViewTransform(); - newTransform.translate(delta.width, delta.height); - - if (scaleToFit) { - double s = Math.min(viewBounds.getWidth() / centerBounds.getWidth(), viewBounds.getHeight() / centerBounds.getHeight()); - newTransform.scaleAboutPoint(s, centerBounds.getCenterX(), centerBounds.getCenterY()); - } - - return newTransform; - } - - /** - * Turns off the fast image animation and does any other applicable cleanup - */ - private void clearViewCache() { - imageAnimate = false; - imageAnimateBounds = null; - } - - /** - * Mimics the standard animateViewToCenterBounds but uses a cached image for performance - * rather than re-rendering the scene at each step - */ - public PTransformActivity animateStaticViewToCenterBoundsFast(Rectangle2D centerBounds, boolean shouldScaleToFit, long duration) { - if (duration == 0) { - return animateViewToCenterBounds(centerBounds,shouldScaleToFit,duration); - } - - AffineTransform newViewTransform = cacheViewBounds(centerBounds,shouldScaleToFit); + BufferedImage buffer = getPaintBuffer(); + Paint fPaint = Color.white; + if (getPaint() != null) { + fPaint = getPaint(); + } + toImage(buffer, fPaint); - return animateStaticViewToTransformFast(newViewTransform, duration); - } + // Do this after the painting above! + imageAnimate = true; - /** - * This copies the behavior of the standard animateViewToTransform but clears the cache - * when it is done - */ - protected PTransformActivity animateStaticViewToTransformFast(AffineTransform destination, long duration) { - if (duration == 0) { - setViewTransform(destination); - return null; - } - - PTransformActivity.Target t = new PTransformActivity.Target() { - public void setTransform(AffineTransform aTransform) { - PCacheCamera.this.setViewTransform(aTransform); - } - public void getSourceMatrix(double[] aSource) { - getViewTransformReference().getMatrix(aSource); - } - }; - - PTransformActivity ta = new PTransformActivity(duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE, t, destination) { + // Return the bounds to the previous viewbounds + animateViewToCenterBounds(viewBounds, scaleToFit, 0); + + // The code below is just copied from animateViewToCenterBounds to + // create the correct transform to center the specified bounds + + PDimension delta = viewBounds.deltaRequiredToCenter(centerBounds); + PAffineTransform newTransform = getViewTransform(); + newTransform.translate(delta.width, delta.height); + + if (scaleToFit) { + double s = Math.min(viewBounds.getWidth() / centerBounds.getWidth(), viewBounds.getHeight() + / centerBounds.getHeight()); + newTransform.scaleAboutPoint(s, centerBounds.getCenterX(), centerBounds.getCenterY()); + } + + return newTransform; + } + + /** + * Turns off the fast image animation and does any other applicable cleanup + */ + private void clearViewCache() { + imageAnimate = false; + imageAnimateBounds = null; + } + + /** + * Mimics the standard animateViewToCenterBounds but uses a cached image for + * performance rather than re-rendering the scene at each step + */ + public PTransformActivity animateStaticViewToCenterBoundsFast(Rectangle2D centerBounds, boolean shouldScaleToFit, + long duration) { + if (duration == 0) { + return animateViewToCenterBounds(centerBounds, shouldScaleToFit, duration); + } + + AffineTransform newViewTransform = cacheViewBounds(centerBounds, shouldScaleToFit); + + return animateStaticViewToTransformFast(newViewTransform, duration); + } + + /** + * This copies the behavior of the standard animateViewToTransform but + * clears the cache when it is done + */ + protected PTransformActivity animateStaticViewToTransformFast(AffineTransform destination, long duration) { + if (duration == 0) { + setViewTransform(destination); + return null; + } + + PTransformActivity.Target t = new PTransformActivity.Target() { + public void setTransform(AffineTransform aTransform) { + PCacheCamera.this.setViewTransform(aTransform); + } + + public void getSourceMatrix(double[] aSource) { + getViewTransformReference().getMatrix(aSource); + } + }; + + PTransformActivity ta = new PTransformActivity(duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE, t, destination) { protected void activityFinished() { clearViewCache(); repaint(); super.activityFinished(); } - }; - - PRoot r = getRoot(); - if (r != null) { - r.getActivityScheduler().addActivity(ta); - } - - return ta; - } - - /** - * Overrides the camera's full paint method to do the fast rendering when possible - */ + }; + + PRoot r = getRoot(); + if (r != null) { + r.getActivityScheduler().addActivity(ta); + } + + return ta; + } + + /** + * Overrides the camera's full paint method to do the fast rendering when + * possible + */ public void fullPaint(PPaintContext paintContext) { - if (imageAnimate) { - PBounds fRef = getFullBoundsReference(); - PBounds viewBounds = getViewBounds(); - double scale = getFullBoundsReference().getWidth()/imageAnimateBounds.getWidth(); - double xOffset = (viewBounds.getX()-imageAnimateBounds.getX())*scale; - double yOffset = (viewBounds.getY()-imageAnimateBounds.getY())*scale; - double scaleW = viewBounds.getWidth()*scale; - double scaleH = viewBounds.getHeight()*scale; - paintContext.getGraphics().drawImage(paintBuffer,0,0,(int)Math.ceil(fRef.getWidth()),(int)Math.ceil(fRef.getHeight()), - (int)Math.floor(xOffset),(int)Math.floor(yOffset),(int)Math.ceil(xOffset+scaleW),(int)Math.ceil(yOffset+scaleH),null); - } - else { - super.fullPaint(paintContext); - } + if (imageAnimate) { + PBounds fRef = getFullBoundsReference(); + PBounds viewBounds = getViewBounds(); + double scale = getFullBoundsReference().getWidth() / imageAnimateBounds.getWidth(); + double xOffset = (viewBounds.getX() - imageAnimateBounds.getX()) * scale; + double yOffset = (viewBounds.getY() - imageAnimateBounds.getY()) * scale; + double scaleW = viewBounds.getWidth() * scale; + double scaleH = viewBounds.getHeight() * scale; + paintContext.getGraphics().drawImage(paintBuffer, 0, 0, (int) Math.ceil(fRef.getWidth()), + (int) Math.ceil(fRef.getHeight()), (int) Math.floor(xOffset), (int) Math.floor(yOffset), + (int) Math.ceil(xOffset + scaleW), (int) Math.ceil(yOffset + scaleH), null); + } + else { + super.fullPaint(paintContext); + } } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PClip.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PClip.java index 37300a3..f077b80 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PClip.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PClip.java @@ -40,78 +40,80 @@ import edu.umd.cs.piccolo.util.PPickPath; /** - * PClip is a simple node that applies a clip before rendering or picking its - * children. PClip is a subclass of PPath, the clip applies is the GeneralPath wrapped - * by its super class. See piccolo/examples ClipExample. - *
+ * PClip is a simple node that applies a clip before rendering or picking + * its children. PClip is a subclass of PPath, the clip applies is the + * GeneralPath wrapped by its super class. See piccolo/examples ClipExample. + * * @version 1.0 - * @author Jesse Grosjean + * @author Jesse Grosjean */ public class PClip extends PPath { - public PBounds computeFullBounds(PBounds dstBounds) { - if (dstBounds == null) dstBounds = new PBounds(); - dstBounds.reset(); - dstBounds.add(getBoundsReference()); - localToParent(dstBounds); - return dstBounds; - } + public PBounds computeFullBounds(PBounds dstBounds) { + if (dstBounds == null) + dstBounds = new PBounds(); + dstBounds.reset(); + dstBounds.add(getBoundsReference()); + localToParent(dstBounds); + return dstBounds; + } - public void repaintFrom(PBounds localBounds, PNode childOrThis) { - if (childOrThis != this) { - Rectangle2D.intersect(getBoundsReference(), localBounds, localBounds); - super.repaintFrom(localBounds, childOrThis); - } else { - super.repaintFrom(localBounds, childOrThis); - } - } + public void repaintFrom(PBounds localBounds, PNode childOrThis) { + if (childOrThis != this) { + Rectangle2D.intersect(getBoundsReference(), localBounds, localBounds); + super.repaintFrom(localBounds, childOrThis); + } + else { + super.repaintFrom(localBounds, childOrThis); + } + } - protected void paint(PPaintContext paintContext) { - Paint p = getPaint(); - if (p != null) { - Graphics2D g2 = paintContext.getGraphics(); - g2.setPaint(p); - g2.fill(getPathReference()); - } - paintContext.pushClip(getPathReference()); - } - - protected void paintAfterChildren(PPaintContext paintContext) { - paintContext.popClip(getPathReference()); - if (getStroke() != null && getStrokePaint() != null) { - Graphics2D g2 = paintContext.getGraphics(); - g2.setPaint(getStrokePaint()); - g2.setStroke(getStroke()); - g2.draw(getPathReference()); - } - } - - public boolean fullPick(PPickPath pickPath) { - if (getPickable() && fullIntersects(pickPath.getPickBounds())) { - pickPath.pushNode(this); - pickPath.pushTransform(getTransformReference(false)); - - if (pick(pickPath)) { - return true; - } - - if (getChildrenPickable() && getPathReference().intersects(pickPath.getPickBounds())) { - int count = getChildrenCount(); - for (int i = count - 1; i >= 0; i--) { - PNode each = getChild(i); - if (each.fullPick(pickPath)) - return true; - } - } + protected void paint(PPaintContext paintContext) { + Paint p = getPaint(); + if (p != null) { + Graphics2D g2 = paintContext.getGraphics(); + g2.setPaint(p); + g2.fill(getPathReference()); + } + paintContext.pushClip(getPathReference()); + } - if (pickAfterChildren(pickPath)) { - return true; - } + protected void paintAfterChildren(PPaintContext paintContext) { + paintContext.popClip(getPathReference()); + if (getStroke() != null && getStrokePaint() != null) { + Graphics2D g2 = paintContext.getGraphics(); + g2.setPaint(getStrokePaint()); + g2.setStroke(getStroke()); + g2.draw(getPathReference()); + } + } - pickPath.popTransform(getTransformReference(false)); - pickPath.popNode(this); - } + public boolean fullPick(PPickPath pickPath) { + if (getPickable() && fullIntersects(pickPath.getPickBounds())) { + pickPath.pushNode(this); + pickPath.pushTransform(getTransformReference(false)); - return false; - } + if (pick(pickPath)) { + return true; + } + + if (getChildrenPickable() && getPathReference().intersects(pickPath.getPickBounds())) { + int count = getChildrenCount(); + for (int i = count - 1; i >= 0; i--) { + PNode each = getChild(i); + if (each.fullPick(pickPath)) + return true; + } + } + + if (pickAfterChildren(pickPath)) { + return true; + } + + pickPath.popTransform(getTransformReference(false)); + pickPath.popNode(this); + } + + return false; + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PComposite.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PComposite.java index 6079c2e..a9f616b 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PComposite.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PComposite.java @@ -33,61 +33,54 @@ import edu.umd.cs.piccolo.util.PPickPath; /** - * PComposite is a simple node that makes a group of nodes appear to - * be a single node when picking and interacting. There is also partial - * (commented out) support for resizing the child node to fit when this - * nodes bounds are set. - *
+ * PComposite is a simple node that makes a group of nodes appear to be a + * single node when picking and interacting. There is also partial (commented + * out) support for resizing the child node to fit when this nodes bounds are + * set. + * * @version 1.0 * @author Jesse Grosjean */ public class PComposite extends PNode { - /* - public boolean setBounds(double x, double y, double width, double height) { - PBounds childBounds = getUnionOfChildrenBounds(null); - - double dx = x - childBounds.x; - double dy = y - childBounds.y; - double sx = width / childBounds.width; - double sy = height / childBounds.height; - double scale = sx > sy ? sx : sy; - - Iterator i = getChildrenIterator(); - while (i.hasNext()) { - PNode each = (PNode) i.next(); - each.offset(dx, dy); - each.scaleAboutPoint(scale, each.getBoundsReference().x, each.getBoundsReference().y); - } - - return super.setBounds(x, y, width, height); - } - - protected void layoutChildren() { - getBoundsReference().setRect(getUnionOfChildrenBounds(null)); - } - */ - - /** - * Return true if this node or any pickable descendends are picked. If - * a pick occurs the pickPath is modified so that this node is always returned - * as the picked node, event if it was a decendent node that initialy reported the - * pick. - */ - public boolean fullPick(PPickPath pickPath) { - if (super.fullPick(pickPath)) { - PNode picked = pickPath.getPickedNode(); - - // this code won't work with internal cameras, because it doesn't pop - // the cameras view transform. - while (picked != this) { - pickPath.popTransform(picked.getTransformReference(false)); - pickPath.popNode(picked); - picked = pickPath.getPickedNode(); - } - - return true; - } - return false; - } + /* + * public boolean setBounds(double x, double y, double width, double height) + * { PBounds childBounds = getUnionOfChildrenBounds(null); + * + * double dx = x - childBounds.x; double dy = y - childBounds.y; double sx = + * width / childBounds.width; double sy = height / childBounds.height; + * double scale = sx > sy ? sx : sy; + * + * Iterator i = getChildrenIterator(); while (i.hasNext()) { PNode each = + * (PNode) i.next(); each.offset(dx, dy); each.scaleAboutPoint(scale, + * each.getBoundsReference().x, each.getBoundsReference().y); } + * + * return super.setBounds(x, y, width, height); } + * + * protected void layoutChildren() { + * getBoundsReference().setRect(getUnionOfChildrenBounds(null)); } + */ + + /** + * Return true if this node or any pickable descendends are picked. If a + * pick occurs the pickPath is modified so that this node is always returned + * as the picked node, event if it was a decendent node that initialy + * reported the pick. + */ + public boolean fullPick(PPickPath pickPath) { + if (super.fullPick(pickPath)) { + PNode picked = pickPath.getPickedNode(); + + // this code won't work with internal cameras, because it doesn't + // pop the cameras view transform. + while (picked != this) { + pickPath.popTransform(picked.getTransformReference(false)); + pickPath.popNode(picked); + picked = pickPath.getPickedNode(); + } + + return true; + } + return false; + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLens.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLens.java index 249d7ea..5ae630a 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLens.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLens.java @@ -41,88 +41,94 @@ import edu.umd.cs.piccolo.nodes.PPath; /** - * PLens is a simple default lens implementation for Piccolo. See piccolo/examples - * LensExample for one possible use of this lens. Lens's are often application - * specific, it may be easiest to study this code, and then implement your own custom - * lens using the general principles illustrated here. - *
- * The basic design here is to add a PCamera as the child of a Pnode (the lens node). The camera is - * the viewing part of the lens, and the node is the title bar that can be used to - * move the lens around. Users of this lens will probably want to set up some lens - * specific event handler and attach it to the camera. - *
- * A lens also needs a layer that it will look at (it should not be the same as the layer - * that it's added to because then it will draw itself in a recursive loop. Last of all - * the PLens will need to be added to the PCanvas layer (so that it can be seen - * by the main camera). - *
+ * PLens is a simple default lens implementation for Piccolo. See + * piccolo/examples LensExample for one possible use of this lens. Lens's are + * often application specific, it may be easiest to study this code, and then + * implement your own custom lens using the general principles illustrated here. + *
+ * The basic design here is to add a PCamera as the child of a Pnode (the lens + * node). The camera is the viewing part of the lens, and the node is the title + * bar that can be used to move the lens around. Users of this lens will + * probably want to set up some lens specific event handler and attach it to the + * camera. + *
+ *+ * A lens also needs a layer that it will look at (it should not be the same as + * the layer that it's added to because then it will draw itself in a recursive + * loop. Last of all the PLens will need to be added to the PCanvas layer (so + * that it can be seen by the main camera). + *
+ * * @version 1.0 * @author Jesse Grosjean */ public class PLens extends PNode { - public static double LENS_DRAGBAR_HEIGHT = 20; - public static Paint DEFAULT_DRAGBAR_PAINT = Color.DARK_GRAY; - public static Paint DEFAULT_LENS_PAINT = Color.LIGHT_GRAY; - - private PPath dragBar; - private PCamera camera; - private PDragEventHandler lensDragger; - - public PLens() { - dragBar = PPath.createRectangle(0, 0, 100, 100); // Drag bar gets resized to fit the available space, so any rectangle will do here - dragBar.setPaint(DEFAULT_DRAGBAR_PAINT); - dragBar.setPickable(false); // This forces drag events to percolate up to PLens object - addChild(dragBar); - - camera = new PCamera(); - camera.setPaint(DEFAULT_LENS_PAINT); - addChild(camera); - - // create an event handler to drag the lens around. Note that this event - // handler consumes events in case another conflicting event handler has been - // installed higher up in the heirarchy. - lensDragger = new PDragEventHandler(); - lensDragger.getEventFilter().setMarksAcceptedEventsAsHandled(true); - addInputEventListener(lensDragger); + public static double LENS_DRAGBAR_HEIGHT = 20; + public static Paint DEFAULT_DRAGBAR_PAINT = Color.DARK_GRAY; + public static Paint DEFAULT_LENS_PAINT = Color.LIGHT_GRAY; - // When this PLens is dragged around adjust the cameras view transform. - addPropertyChangeListener(PNode.PROPERTY_TRANSFORM, new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - camera.setViewTransform(getInverseTransform()); - } - }); - } - - public PLens(PLayer layer) { - this(); - addLayer(0, layer); - } - - public PCamera getCamera() { - return camera; - } - - public PPath getDragBar() { - return dragBar; - } + private PPath dragBar; + private PCamera camera; + private PDragEventHandler lensDragger; - public PDragEventHandler getLensDraggerHandler() { - return lensDragger; - } - - public void addLayer(int index, PLayer layer) { - camera.addLayer(index, layer); - } - - public void removeLayer(PLayer layer) { - camera.removeLayer(layer); - } - - // when the lens is resized this method gives us a chance to layout the lenses - // camera child appropriately. - protected void layoutChildren() { - dragBar.setPathToRectangle((float)getX(), (float)getY(), (float)getWidth(), (float)LENS_DRAGBAR_HEIGHT); - camera.setBounds(getX(), getY() + LENS_DRAGBAR_HEIGHT, getWidth(), getHeight() - LENS_DRAGBAR_HEIGHT); - } + public PLens() { + // Drag bar gets resized to fit the available space, so any rectangle + // will do here + dragBar = PPath.createRectangle(0, 0, 100, 100); + dragBar.setPaint(DEFAULT_DRAGBAR_PAINT); + // This forces drag events to percolate up to PLens object + dragBar.setPickable(false); + addChild(dragBar); + + camera = new PCamera(); + camera.setPaint(DEFAULT_LENS_PAINT); + addChild(camera); + + // create an event handler to drag the lens around. Note that this event + // handler consumes events in case another conflicting event handler has + // been installed higher up in the heirarchy. + lensDragger = new PDragEventHandler(); + lensDragger.getEventFilter().setMarksAcceptedEventsAsHandled(true); + addInputEventListener(lensDragger); + + // When this PLens is dragged around adjust the cameras view transform. + addPropertyChangeListener(PNode.PROPERTY_TRANSFORM, new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + camera.setViewTransform(getInverseTransform()); + } + }); + } + + public PLens(PLayer layer) { + this(); + addLayer(0, layer); + } + + public PCamera getCamera() { + return camera; + } + + public PPath getDragBar() { + return dragBar; + } + + public PDragEventHandler getLensDraggerHandler() { + return lensDragger; + } + + public void addLayer(int index, PLayer layer) { + camera.addLayer(index, layer); + } + + public void removeLayer(PLayer layer) { + camera.removeLayer(layer); + } + + // when the lens is resized this method gives us a chance to layout the + // lenses camera child appropriately. + protected void layoutChildren() { + dragBar.setPathToRectangle((float) getX(), (float) getY(), (float) getWidth(), (float) LENS_DRAGBAR_HEIGHT); + camera.setBounds(getX(), getY() + LENS_DRAGBAR_HEIGHT, getWidth(), getHeight() - LENS_DRAGBAR_HEIGHT); + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLine.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLine.java index 8e682c3..efdfa85 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLine.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PLine.java @@ -18,138 +18,142 @@ import edu.umd.cs.piccolo.util.PUtil; import edu.umd.cs.piccolox.util.LineShape; -/** - * PLine a class for drawing multisegment lines. - * Submitted by Hallvard Traetteberg. +/** + * PLine a class for drawing multisegment lines. Submitted by Hallvard + * Traetteberg. */ -public class PLine extends PNode { - - private static final PAffineTransform TEMP_TRANSFORM = new PAffineTransform(); - private static final BasicStroke DEFAULT_STROKE = new BasicStroke(1.0f); - private static final Color DEFAULT_STROKE_PAINT = Color.black; - - private transient LineShape line; - private transient Stroke stroke; - private Paint strokePaint; +public class PLine extends PNode { - public PLine(LineShape line) { - strokePaint = DEFAULT_STROKE_PAINT; - stroke = DEFAULT_STROKE; + private static final PAffineTransform TEMP_TRANSFORM = new PAffineTransform(); + private static final BasicStroke DEFAULT_STROKE = new BasicStroke(1.0f); + private static final Color DEFAULT_STROKE_PAINT = Color.black; + + private transient LineShape line; + private transient Stroke stroke; + private Paint strokePaint; + + public PLine(LineShape line) { + strokePaint = DEFAULT_STROKE_PAINT; + stroke = DEFAULT_STROKE; if (line == null) { line = new LineShape(null); } - this.line = line; - } + this.line = line; + } public PLine() { this(null); } - public PLine(LineShape line, Stroke aStroke) { - this(line); - stroke = aStroke; - } - - //**************************************************************** - // Stroke - //**************************************************************** - - public Paint getStrokePaint() { - return strokePaint; - } + public PLine(LineShape line, Stroke aStroke) { + this(line); + stroke = aStroke; + } - public void setStrokePaint(Paint aPaint) { - Paint old = strokePaint; - strokePaint = aPaint; - invalidatePaint(); - firePropertyChange(PPath.PROPERTY_CODE_STROKE_PAINT, PPath.PROPERTY_STROKE_PAINT, old, strokePaint); - } - - public Stroke getStroke() { - return stroke; - } + // **************************************************************** + // Stroke + // **************************************************************** - public void setStroke(Stroke aStroke) { - Stroke old = stroke; - stroke = aStroke; - updateBoundsFromLine(); - invalidatePaint(); - firePropertyChange(PPath.PROPERTY_CODE_STROKE, PPath.PROPERTY_STROKE, old, stroke); - } - - //**************************************************************** - // Bounds - //**************************************************************** + public Paint getStrokePaint() { + return strokePaint; + } - public boolean setBounds(double x, double y, double width, double height) { - if (line == null || !super.setBounds(x, y, width, height)) { - return false; - } + public void setStrokePaint(Paint aPaint) { + Paint old = strokePaint; + strokePaint = aPaint; + invalidatePaint(); + firePropertyChange(PPath.PROPERTY_CODE_STROKE_PAINT, PPath.PROPERTY_STROKE_PAINT, old, strokePaint); + } - Rectangle2D lineBounds = line.getBounds2D(); - Rectangle2D lineStrokeBounds = getLineBoundsWithStroke(); - double strokeOutset = Math.max(lineStrokeBounds.getWidth() - lineBounds.getWidth(), - lineStrokeBounds.getHeight() - lineBounds.getHeight()); - - x += strokeOutset / 2; - y += strokeOutset / 2; - width -= strokeOutset; - height -= strokeOutset; - - TEMP_TRANSFORM.setToIdentity(); - TEMP_TRANSFORM.translate(x, y); - TEMP_TRANSFORM.scale(width / lineBounds.getWidth(), height / lineBounds.getHeight()); - TEMP_TRANSFORM.translate(-lineBounds.getX(), -lineBounds.getY()); + public Stroke getStroke() { + return stroke; + } + + public void setStroke(Stroke aStroke) { + Stroke old = stroke; + stroke = aStroke; + updateBoundsFromLine(); + invalidatePaint(); + firePropertyChange(PPath.PROPERTY_CODE_STROKE, PPath.PROPERTY_STROKE, old, stroke); + } + + // **************************************************************** + // Bounds + // **************************************************************** + + public boolean setBounds(double x, double y, double width, double height) { + if (line == null || !super.setBounds(x, y, width, height)) { + return false; + } + + Rectangle2D lineBounds = line.getBounds2D(); + Rectangle2D lineStrokeBounds = getLineBoundsWithStroke(); + double strokeOutset = Math.max(lineStrokeBounds.getWidth() - lineBounds.getWidth(), lineStrokeBounds + .getHeight() + - lineBounds.getHeight()); + + x += strokeOutset / 2; + y += strokeOutset / 2; + width -= strokeOutset; + height -= strokeOutset; + + TEMP_TRANSFORM.setToIdentity(); + TEMP_TRANSFORM.translate(x, y); + TEMP_TRANSFORM.scale(width / lineBounds.getWidth(), height / lineBounds.getHeight()); + TEMP_TRANSFORM.translate(-lineBounds.getX(), -lineBounds.getY()); line.transformPoints(TEMP_TRANSFORM); - - return true; - } - public boolean intersects(Rectangle2D aBounds) { - if (super.intersects(aBounds)) { - if (line.intersects(aBounds)) { - return true; - } else if (stroke != null && strokePaint != null) { - return stroke.createStrokedShape(line).intersects(aBounds); - } - } - return false; - } - - public Rectangle2D getLineBoundsWithStroke() { - if (stroke != null) { - return stroke.createStrokedShape(line).getBounds2D(); - } else { - return line.getBounds2D(); - } - } - - public void updateBoundsFromLine() { - if (line.getPointCount() == 0) { - resetBounds(); - } else { - Rectangle2D b = getLineBoundsWithStroke(); - super.setBounds(b.getX(), b.getY(), b.getWidth(), b.getHeight()); - } - } - - //**************************************************************** - // Painting - //**************************************************************** - - protected void paint(PPaintContext paintContext) { - Graphics2D g2 = paintContext.getGraphics(); - - if (stroke != null && strokePaint != null) { - g2.setPaint(strokePaint); - g2.setStroke(stroke); - g2.draw(line); - } - } + return true; + } - public LineShape getLineReference() { - return line; - } + public boolean intersects(Rectangle2D aBounds) { + if (super.intersects(aBounds)) { + if (line.intersects(aBounds)) { + return true; + } + else if (stroke != null && strokePaint != null) { + return stroke.createStrokedShape(line).intersects(aBounds); + } + } + return false; + } + + public Rectangle2D getLineBoundsWithStroke() { + if (stroke != null) { + return stroke.createStrokedShape(line).getBounds2D(); + } + else { + return line.getBounds2D(); + } + } + + public void updateBoundsFromLine() { + if (line.getPointCount() == 0) { + resetBounds(); + } + else { + Rectangle2D b = getLineBoundsWithStroke(); + super.setBounds(b.getX(), b.getY(), b.getWidth(), b.getHeight()); + } + } + + // **************************************************************** + // Painting + // **************************************************************** + + protected void paint(PPaintContext paintContext) { + Graphics2D g2 = paintContext.getGraphics(); + + if (stroke != null && strokePaint != null) { + g2.setPaint(strokePaint); + g2.setStroke(stroke); + g2.draw(line); + } + } + + public LineShape getLineReference() { + return line; + } public int getPointCount() { return line.getPointCount(); @@ -167,11 +171,11 @@ updateBoundsFromLine(); invalidatePaint(); } - - public void setPoint(int i, double x, double y) { + + public void setPoint(int i, double x, double y) { line.setPoint(i, x, y); lineChanged(); - } + } public void addPoint(int i, double x, double y) { line.addPoint(i, x, y); @@ -183,22 +187,22 @@ lineChanged(); } - public void removeAllPoints() { + public void removeAllPoints() { line.removePoints(0, line.getPointCount()); lineChanged(); - } - - //**************************************************************** - // Serialization - //**************************************************************** - - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - PUtil.writeStroke(stroke, out); - } + } - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - stroke = PUtil.readStroke(in); - } + // **************************************************************** + // Serialization + // **************************************************************** + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + PUtil.writeStroke(stroke, out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + stroke = PUtil.readStroke(in); + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PNodeCache.java b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PNodeCache.java index 8304aba..1cd34a4 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/nodes/PNodeCache.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/nodes/PNodeCache.java @@ -40,81 +40,81 @@ import edu.umd.cs.piccolo.util.PPickPath; /** - * PNodeCache caches a visual representation of it's children - * into an image and uses this cached image for painting instead of - * painting it's children directly. This is intended to be used in - * two ways. - *- * First it can be used as a simple optimization technique. If a node - * has many descendents it may be faster to paint the cached image - * representation instead of painting each node. - *
- * Second PNodeCache provides a place where "image" effects such as - * blurring and drop shadows can be added to the Piccolo scene graph. - * This can be done by overriding the method createImageCache and - * returing an image with the desired effect applied. - *
+ * PNodeCache caches a visual representation of it's children into an + * image and uses this cached image for painting instead of painting it's + * children directly. This is intended to be used in two ways. + *
+ * First it can be used as a simple optimization technique. If a node has many + * descendents it may be faster to paint the cached image representation instead + * of painting each node. + *
+ *+ * Second PNodeCache provides a place where "image" effects such as blurring and + * drop shadows can be added to the Piccolo scene graph. This can be done by + * overriding the method createImageCache and returing an image with the desired + * effect applied. + *
+ * * @version 1.0 * @author Jesse Grosjean */ public class PNodeCache extends PNode { - - private transient Image imageCache; - private boolean validatingCache; - - /** - * Override this method to customize the image cache creation process. For - * example if you want to create a shadow effect you would do that here. Fill - * in the cacheOffsetRef if needed to make your image cache line up with the - * nodes children. - */ - public Image createImageCache(Dimension2D cacheOffsetRef) { - return toImage(); - } - - public Image getImageCache() { - if (imageCache == null) { - PDimension cacheOffsetRef = new PDimension(); - validatingCache = true; - resetBounds(); - imageCache = createImageCache(cacheOffsetRef); - PBounds b = getFullBoundsReference(); - setBounds(b.getX() + cacheOffsetRef.getWidth(), - b.getY() + cacheOffsetRef.getHeight(), - imageCache.getWidth(null), - imageCache.getHeight(null)); - validatingCache = false; - } - return imageCache; - } - - public void invalidateCache() { - imageCache = null; - } - - public void invalidatePaint() { - if (!validatingCache) { - super.invalidatePaint(); - } - } - - public void repaintFrom(PBounds localBounds, PNode childOrThis) { - if (!validatingCache) { - super.repaintFrom(localBounds, childOrThis); - invalidateCache(); - } - } - - public void fullPaint(PPaintContext paintContext) { - if (validatingCache) { - super.fullPaint(paintContext); - } else { - Graphics2D g2 = paintContext.getGraphics(); - g2.drawImage(getImageCache(), (int) getX(), (int) getY(), null); - } - } - - protected boolean pickAfterChildren(PPickPath pickPath) { - return false; - } + + private transient Image imageCache; + private boolean validatingCache; + + /** + * Override this method to customize the image cache creation process. For + * example if you want to create a shadow effect you would do that here. + * Fill in the cacheOffsetRef if needed to make your image cache line up + * with the nodes children. + */ + public Image createImageCache(Dimension2D cacheOffsetRef) { + return toImage(); + } + + public Image getImageCache() { + if (imageCache == null) { + PDimension cacheOffsetRef = new PDimension(); + validatingCache = true; + resetBounds(); + imageCache = createImageCache(cacheOffsetRef); + PBounds b = getFullBoundsReference(); + setBounds(b.getX() + cacheOffsetRef.getWidth(), b.getY() + cacheOffsetRef.getHeight(), imageCache + .getWidth(null), imageCache.getHeight(null)); + validatingCache = false; + } + return imageCache; + } + + public void invalidateCache() { + imageCache = null; + } + + public void invalidatePaint() { + if (!validatingCache) { + super.invalidatePaint(); + } + } + + public void repaintFrom(PBounds localBounds, PNode childOrThis) { + if (!validatingCache) { + super.repaintFrom(localBounds, childOrThis); + invalidateCache(); + } + } + + public void fullPaint(PPaintContext paintContext) { + if (validatingCache) { + super.fullPaint(paintContext); + } + else { + Graphics2D g2 = paintContext.getGraphics(); + g2.drawImage(getImageCache(), (int) getX(), (int) getY(), null); + } + } + + protected boolean pickAfterChildren(PPickPath pickPath) { + return false; + } } 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 b222041..31d6622 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 @@ -61,620 +61,619 @@ */ public class PStyledText extends PNode { - protected static FontRenderContext SWING_FRC = new FontRenderContext(null,true,false); - protected static Line2D paintLine = new Line2D.Double(); + protected static FontRenderContext SWING_FRC = new FontRenderContext(null, true, false); + protected static Line2D paintLine = new Line2D.Double(); - protected Document document; - protected transient ArrayList stringContents; - protected transient LineInfo[] lines; + protected Document document; + protected transient ArrayList stringContents; + protected transient LineInfo[] lines; - protected boolean editing; - protected Insets insets = new Insets(0,0,0,0); - protected boolean constrainHeightToTextHeight = true; - protected boolean constrainWidthToTextWidth = true; + protected boolean editing; + protected Insets insets = new Insets(0, 0, 0, 0); + protected boolean constrainHeightToTextHeight = true; + protected boolean constrainWidthToTextWidth = true; - /** - * Constructor for PStyledText. - */ - public PStyledText() { - super(); - } + /** + * Constructor for PStyledText. + */ + public PStyledText() { + super(); + } - /** - * Controls whether this node changes its width to fit the width - * of its text. If flag is true it does; if flag is false it doesn't - */ - public void setConstrainWidthToTextWidth(boolean constrainWidthToTextWidth) { - this.constrainWidthToTextWidth = constrainWidthToTextWidth; - recomputeLayout(); - } + /** + * Controls whether this node changes its width to fit the width of its + * text. If flag is true it does; if flag is false it doesn't + */ + public void setConstrainWidthToTextWidth(boolean constrainWidthToTextWidth) { + this.constrainWidthToTextWidth = constrainWidthToTextWidth; + recomputeLayout(); + } - /** - * Controls whether this node changes its height to fit the height - * of its text. If flag is true it does; if flag is false it doesn't - */ - public void setConstrainHeightToTextHeight(boolean constrainHeightToTextHeight) { - this.constrainHeightToTextHeight = constrainHeightToTextHeight; - recomputeLayout(); - } + /** + * Controls whether this node changes its height to fit the height of its + * text. If flag is true it does; if flag is false it doesn't + */ + public void setConstrainHeightToTextHeight(boolean constrainHeightToTextHeight) { + this.constrainHeightToTextHeight = constrainHeightToTextHeight; + recomputeLayout(); + } - /** - * Controls whether this node changes its width to fit the width - * of its text. If flag is true it does; if flag is false it doesn't - */ - public boolean getConstrainWidthToTextWidth() { - return constrainWidthToTextWidth; - } + /** + * Controls whether this node changes its width to fit the width of its + * text. If flag is true it does; if flag is false it doesn't + */ + public boolean getConstrainWidthToTextWidth() { + return constrainWidthToTextWidth; + } - /** - * Controls whether this node changes its height to fit the height - * of its text. If flag is true it does; if flag is false it doesn't - */ - public boolean getConstrainHeightToTextHeight() { - return constrainHeightToTextHeight; - } + /** + * Controls whether this node changes its height to fit the height of its + * text. If flag is true it does; if flag is false it doesn't + */ + public boolean getConstrainHeightToTextHeight() { + return constrainHeightToTextHeight; + } - /** - * Get the document for this PStyledText - */ - public Document getDocument() { - return document; - } - - /** - * Set the document on this PStyledText - */ - public void setDocument(Document document) { - // Save the document - this.document = document; - - syncWithDocument(); - } - - - public void syncWithDocument() { - // The paragraph start and end indices - ArrayList pEnds = null; - - // The current position in the specified range - int pos = 0; - - // First get the actual text and stick it in an Attributed String - try { + /** + * Get the document for this PStyledText + */ + public Document getDocument() { + return document; + } - stringContents = new ArrayList(); - pEnds = new ArrayList(); - - 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; + /** + * Set the document on this PStyledText + */ + public void setDocument(Document document) { + // Save the document + this.document = document; - 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("")) { - stringContents.add(new AttributedString(" ")); - pEnds.add(new RunInfo(pos,pos)); + syncWithDocument(); + } - 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())); + public void syncWithDocument() { + // The paragraph start and end indices + ArrayList pEnds = null; - // Increment the position - pos = pos+token.length(); - - lastNewLine = false; - } - } - - // 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; - } - } - catch (Exception e) { - e.printStackTrace(); - } + // The current position in the specified range + int pos = 0; - // The default style context - which will be reused - StyleContext style = StyleContext.getDefaultStyleContext(); + // First get the actual text and stick it in an Attributed String + try { - RunInfo pEnd = null; - for (int i = 0; i < stringContents.size(); i++) { - pEnd = (RunInfo)pEnds.get(i); - pos = pEnd.runStart; + stringContents = new ArrayList(); + pEnds = new ArrayList(); - // The current element will be used as a temp variable while searching - // for the leaf element at the current position - Element curElement = null; + String s = document.getText(0, document.getLength()); + StringTokenizer tokenizer = new StringTokenizer(s, "\n", true); - // Small assumption here that there is one root element - can fix - // for more general support later - Element rootElement = document.getDefaultRootElement(); + // 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 string is length 0 then we just need to add the attributes once - if (pEnd.runStart != pEnd.runLimit) { - // OK, now we loop until we find all the leaf elements in the range - while (pos < pEnd.runLimit) { - - // Before each pass, start at the root - curElement = rootElement; - - // Now we descend the hierarchy until we get to a leaf - while (!curElement.isLeaf()) { - curElement = - curElement.getElement(curElement.getElementIndex(pos)); - } + // If the token + if (token.equals("\n")) { + if (lastNewLine) { + stringContents.add(new AttributedString(" ")); + pEnds.add(new RunInfo(pos, pos + 1)); - // These are the mandatory attributes + pos = pos + 1; - AttributeSet attributes = curElement.getAttributes(); - Color foreground = style.getForeground(attributes); + lastNewLine = true; + } + else { + pos = pos + 1; - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.FOREGROUND, - foreground, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - - Font font = (attributes.isDefined(StyleConstants.FontSize) || attributes.isDefined(StyleConstants.FontFamily)) ? style.getFont(attributes) : null; - if (font == null) { - if (document instanceof DefaultStyledDocument) { - font = style.getFont(((DefaultStyledDocument)document).getCharacterElement(pos).getAttributes()); - if (font == null) { - font = style.getFont(((DefaultStyledDocument)document).getParagraphElement(pos).getAttributes()); - } - if (font == null) { - font = style.getFont(rootElement.getAttributes()); - } - } - else { - font = style.getFont(rootElement.getAttributes()); - } - } - if (font != null) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.FONT, - font, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - // These are the optional attributes - - Color background = (attributes.isDefined(StyleConstants.Background)) ? style.getBackground(attributes) : null; - if (background != null) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.BACKGROUND, - background, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - boolean underline = StyleConstants.isUnderline(attributes); - if (underline) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.UNDERLINE, - Boolean.TRUE, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - boolean strikethrough = StyleConstants.isStrikeThrough(attributes); - if (strikethrough) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.STRIKETHROUGH, - Boolean.TRUE, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - // And set the position to the end of the given attribute - pos = curElement.getEndOffset(); - } - } - else { - // Before each pass, start at the root - curElement = rootElement; + 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("")) { + stringContents.add(new AttributedString(" ")); + pEnds.add(new RunInfo(pos, pos)); - // Now we descend the hierarchy until we get to a leaf - while (!curElement.isLeaf()) { - curElement = - curElement.getElement(curElement.getElementIndex(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())); - // These are the mandatory attributes - - AttributeSet attributes = curElement.getAttributes(); - Color foreground = style.getForeground(attributes); + // Increment the position + pos = pos + token.length(); - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.FOREGROUND, - foreground, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); + lastNewLine = false; + } + } - // These are the optional attributes + // Add one more newline if the last character was a newline + if (lastNewLine) { + stringContents.add(new AttributedString(" ")); + pEnds.add(new RunInfo(pos, pos + 1)); - Font font = (attributes.isDefined(StyleConstants.FontSize) || attributes.isDefined(StyleConstants.FontFamily)) ? style.getFont(attributes) : null; - if (font == null) { - if (document instanceof DefaultStyledDocument) { - font = style.getFont(((DefaultStyledDocument)document).getCharacterElement(pos).getAttributes()); - if (font == null) { - font = style.getFont(((DefaultStyledDocument)document).getParagraphElement(pos).getAttributes()); - } - if (font == null) { - font = style.getFont(rootElement.getAttributes()); - } - } - else { - font = style.getFont(rootElement.getAttributes()); - } - } - if (font != null) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.FONT, - font, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - Color background = (attributes.isDefined(StyleConstants.Background)) ? style.getBackground(attributes) : null; - if (background != null) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.BACKGROUND, - background, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - boolean underline = StyleConstants.isUnderline(attributes); - if (underline) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.UNDERLINE, - Boolean.TRUE, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - - boolean strikethrough = StyleConstants.isStrikeThrough(attributes); - if (strikethrough) { - ((AttributedString)stringContents.get(i)).addAttribute( - TextAttribute.STRIKETHROUGH, - Boolean.TRUE, - (int)Math.max(0,curElement.getStartOffset()-pEnd.runStart), - (int)Math.min(pEnd.runLimit-pEnd.runStart,curElement.getEndOffset()-pEnd.runStart)); - } - } - } + lastNewLine = false; + } + } + catch (Exception e) { + e.printStackTrace(); + } - recomputeLayout(); - } + // The default style context - which will be reused + StyleContext style = StyleContext.getDefaultStyleContext(); - /** - * Compute the bounds of the text wrapped by this node. The text layout - * is wrapped based on the bounds of this node. If the shrinkBoundsToFit parameter - * is true then after the text has been laid out the bounds of this node are shrunk - * to fit around those text bounds. - */ - public void recomputeLayout() { - if (stringContents == null) return; + RunInfo pEnd = null; + for (int i = 0; i < stringContents.size(); i++) { + pEnd = (RunInfo) pEnds.get(i); + pos = pEnd.runStart; - ArrayList linesList = new ArrayList(); + // The current element will be used as a temp variable while + // searching + // for the leaf element at the current position + Element curElement = null; - double textWidth = 0; - double textHeight = 0; - - for(int i=0; i+ * A ComboBox for use in Piccolo. This still has an associated JPopupMenu (which + * is always potentially heavyweight depending on component location relative to + * containing window borders.) However, this ComboBox places the PopupMenu + * component of the ComboBox in the appropriate position relative to the + * permanent part of the ComboBox. The PopupMenu is never transformed. + *
+ *+ * This class was not designed for subclassing. If different behavior is + * required, it seems more appropriate to subclass JComboBox directly using this + * class as a model. + *
+ *+ * NOTE: There is currently a known bug, namely, if the ComboBox receives focus + * through 'tab' focus traversal and the keyboard is used to interact with the + * ComboBox, there may be unexpected results. + *
+ *+ * 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 Lance Good */ public class PComboBox extends JComboBox implements Serializable { @@ -51,31 +53,31 @@ /** * Creates a PComboBox that takes its items from an existing ComboBoxModel. - * + * * @param model The ComboBoxModel from which the list will be created */ - public PComboBox( ComboBoxModel model ) { - super( model ); + public PComboBox(ComboBoxModel model) { + super(model); init(); } /** * Creates a PComboBox that contains the elements in the specified array. - * + * * @param items The items to populate the PComboBox list */ - public PComboBox( final Object items[] ) { - super( items ); + public PComboBox(final Object items[]) { + super(items); init(); } /** * Creates a PComboBox that contains the elements in the specified Vector. - * + * * @param items The items to populate the PComboBox list */ - public PComboBox( Vector items ) { - super( items ); + public PComboBox(Vector items) { + super(items); init(); } @@ -91,24 +93,25 @@ * Substitue our UI for the default */ private void init() { - setUI( new PBasicComboBoxUI() ); + setUI(new PBasicComboBoxUI()); } /** - * Clients must set the PSwing and PSwingCanvas environment for this PComboBox to work properly. - * + * Clients must set the PSwing and PSwingCanvas environment for this + * PComboBox to work properly. + * * @param pSwing * @param canvas */ - public void setEnvironment( PSwing pSwing, PSwingCanvas canvas ) { + public void setEnvironment(PSwing pSwing, PSwingCanvas canvas) { this.pSwing = pSwing; this.canvas = canvas; } /** - * The substitute look and feel - used to capture the mouse - * events on the arrowButton and the component itself and - * to create our PopupMenu rather than the default + * The substitute look and feel - used to capture the mouse events on the + * arrowButton and the component itself and to create our PopupMenu rather + * than the default */ protected class PBasicComboBoxUI extends BasicComboBoxUI { @@ -116,66 +119,52 @@ * Create our Popup instead of theirs */ protected ComboPopup createPopup() { - PBasicComboPopup popup = new PBasicComboPopup( comboBox ); - popup.getAccessibleContext().setAccessibleParent( comboBox ); + PBasicComboPopup popup = new PBasicComboPopup(comboBox); + popup.getAccessibleContext().setAccessibleParent(comboBox); return popup; } } /** - * The substitute ComboPopupMenu that places itself correctly - * in Piccolo. + * The substitute ComboPopupMenu that places itself correctly in Piccolo. */ protected class PBasicComboPopup extends BasicComboPopup { /** * @param combo The parent ComboBox */ - public PBasicComboPopup( JComboBox combo ) { - super( combo ); + public PBasicComboPopup(JComboBox combo) { + super(combo); } - /** - * Computes the bounds for the Popup in Piccolo if a - * PMouseEvent has been received. Otherwise, it uses the - * default algorithm for placing the popup. - * + * Computes the bounds for the Popup in Piccolo if a PMouseEvent has + * been received. Otherwise, it uses the default algorithm for placing + * the popup. + * * @param px corresponds to the x coordinate of the popup * @param py corresponds to the y coordinate of the popup * @param pw corresponds to the width of the popup * @param ph corresponds to the height of the popup * @return The bounds for the PopupMenu */ - protected Rectangle computePopupBounds( int px, int py, int pw, int ph ) { + protected Rectangle computePopupBounds(int px, int py, int pw, int ph) { Rectangle2D r = getNodeBoundsInCanvas(); - Rectangle sup = super.computePopupBounds( px, py, pw, ph ); - return new Rectangle( (int)r.getX(), (int)r.getMaxY(), (int)sup.getWidth(), (int)sup.getHeight() ); + Rectangle sup = super.computePopupBounds(px, py, pw, ph); + return new Rectangle((int) r.getX(), (int) r.getMaxY(), (int) sup.getWidth(), (int) sup.getHeight()); } } private Rectangle2D getNodeBoundsInCanvas() { - if( pSwing == null || canvas == null ) { - throw new RuntimeException( "PComboBox.setEnvironment( swing, pCanvas );//has to be done manually at present" ); + if (pSwing == null || canvas == null) { + throw new RuntimeException( + "PComboBox.setEnvironment( swing, pCanvas );//has to be done manually at present"); } Rectangle2D r1c = pSwing.getBounds(); - pSwing.localToGlobal( r1c ); - canvas.getCamera().globalToLocal( r1c ); - r1c = canvas.getCamera().getViewTransform().createTransformedShape( r1c ).getBounds2D(); + pSwing.localToGlobal(r1c); + canvas.getCamera().globalToLocal(r1c); + r1c = canvas.getCamera().getViewTransform().createTransformedShape(r1c).getBounds2D(); return r1c; } } - - - - - - - - - - - - - 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 3bd2e74..096ce79 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 @@ -112,7 +112,7 @@ /** * PSwing is used to add Swing Components to a Piccolo canvas. - * + ** Example: adding a swing JButton to a PCanvas: *
* PSwingCanvas canvas = new PSwingCanvas(); @@ -120,14 +120,16 @@ * 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: *
@@ -137,17 +139,21 @@ * 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 diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java index d7263f8..b050aae 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingCanvas.java @@ -16,8 +16,9 @@ import java.awt.*; /** - * The PSwingCanvas is a PCanvas that can display Swing components with the PSwing adapter. - * + * 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 @@ -34,35 +35,36 @@ * Construct a new PSwingCanvas. */ public PSwingCanvas() { - swingWrapper = new SwingWrapper( this ); - add( swingWrapper ); - RepaintManager.setCurrentManager( pSwingRepaintManager ); - pSwingRepaintManager.addPSwingCanvas( this ); + 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 ); + // todo or maybe getCameraLayer() or getRoot()? + swingEventHandler = new PSwingEventHandler(this, getCamera()); + swingEventHandler.setActive(true); } JComponent getSwingWrapper() { return swingWrapper; } - public void addPSwing( PSwing pSwing ) { - swingWrapper.add( pSwing.getComponent() ); + public void addPSwing(PSwing pSwing) { + swingWrapper.add(pSwing.getComponent()); } - public void removePSwing( PSwing pSwing ) { - swingWrapper.remove( pSwing.getComponent() ); + public void removePSwing(PSwing pSwing) { + swingWrapper.remove(pSwing.getComponent()); } private static class SwingWrapper extends JComponent { private PSwingCanvas pSwingCanvas; - public SwingWrapper( 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 ); + setSize(new Dimension(0, 0)); + setPreferredSize(new Dimension(0, 0)); + putClientProperty(SWING_WRAPPER_KEY, SWING_WRAPPER_KEY); } public PSwingCanvas getpSwingCanvas() { 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 ee777c9..8d2123b 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 @@ -19,18 +19,17 @@ import java.awt.geom.Point2D; /** - * Event handler to send MousePressed, MouseReleased, MouseMoved, - * MouseClicked, and MouseDragged events on Swing components within - * a PCanvas. - * + * Event handler to send MousePressed, MouseReleased, MouseMoved, MouseClicked, + * and MouseDragged events on Swing components within a PCanvas. + * * @author Ben Bederson * @author Lance Good * @author Sam Reid */ public class PSwingEventHandler implements PInputEventListener { - private PNode listenNode = null; //used to listen to for events - private boolean active = false; //True when event handlers are set active. + private PNode listenNode = null; // used to listen to for events + private boolean active = false; // True when event handlers are set active. // The previous component - used to generate mouseEntered and // mouseExited events @@ -40,7 +39,7 @@ private Point2D prevPoint = null; private Point2D prevOff = null; - private boolean recursing = false;//to avoid accidental recursive handling + private boolean recursing = false;// to avoid accidental recursive handling private ButtonData leftButtonData = new ButtonData(); private ButtonData rightButtonData = new ButtonData(); @@ -49,13 +48,13 @@ private PSwingCanvas canvas; /** - * Constructs a new PSwingEventHandler for the given canvas, - * and a node that will recieve the mouse events. - * + * Constructs a new PSwingEventHandler for the given canvas, and a node that + * will recieve the mouse events. + * * @param canvas the canvas associated with this PSwingEventHandler. - * @param node the node the mouse listeners will be attached to. + * @param node the node the mouse listeners will be attached to. */ - public PSwingEventHandler( PSwingCanvas canvas, PNode node ) { + public PSwingEventHandler(PSwingCanvas canvas, PNode node) { this.canvas = canvas; listenNode = node; } @@ -63,33 +62,33 @@ /** * Constructs a new PSwingEventHandler for the given canvas. */ - public PSwingEventHandler( PSwingCanvas canvas ) { + public PSwingEventHandler(PSwingCanvas canvas) { this.canvas = canvas; } /** * Sets whether this event handler can fire events. - * + * * @param active */ - void setActive( boolean active ) { - if( this.active && !active ) { - if( listenNode != null ) { + void setActive(boolean active) { + if (this.active && !active) { + if (listenNode != null) { this.active = false; - listenNode.removeInputEventListener( this ); + listenNode.removeInputEventListener(this); } } - else if( !this.active && active ) { - if( listenNode != null ) { + else if (!this.active && active) { + if (listenNode != null) { this.active = true; - listenNode.addInputEventListener( this ); + listenNode.addInputEventListener(this); } } } /** * Determines if this event handler is active. - * + * * @return True if active */ public boolean isActive() { @@ -98,33 +97,33 @@ /** * Finds the component at the specified location (must be showing). - * + * * @param c * @param x * @param y * @return the component at the specified location. */ - private Component findShowingComponentAt( Component c, int x, int y ) { - if( !c.contains( x, y ) ) { + private Component findShowingComponentAt(Component c, int x, int y) { + if (!c.contains(x, y)) { return null; } - if( c instanceof Container ) { - Container contain = ( (Container)c ); + if (c instanceof Container) { + Container contain = ((Container) c); int ncomponents = contain.getComponentCount(); Component component[] = contain.getComponents(); - for( int i = 0; i < ncomponents; i++ ) { + for (int i = 0; i < ncomponents; i++) { Component comp = component[i]; - if( comp != null ) { + if (comp != null) { Point p = comp.getLocation(); - if( comp instanceof Container ) { - comp = findShowingComponentAt( comp, x - (int)p.getX(), y - (int)p.getY() ); + if (comp instanceof Container) { + comp = findShowingComponentAt(comp, x - (int) p.getX(), y - (int) p.getY()); } else { - comp = comp.getComponentAt( x - (int)p.getX(), y - (int)p.getY() ); + comp = comp.getComponentAt(x - (int) p.getX(), y - (int) p.getY()); } - if( comp != null && comp.isShowing() ) { + if (comp != null && comp.isShowing()) { return comp; } } @@ -134,16 +133,15 @@ } /** - * Determines if any Swing components in Piccolo - * should receive the given MouseEvent and - * forwards the event to that component. - * However, mouseEntered and mouseExited are independent of the buttons. - * Also, notice the notes on mouseEntered and mouseExited. - * + * Determines if any Swing components in Piccolo should receive the given + * MouseEvent and forwards the event to that component. However, + * mouseEntered and mouseExited are independent of the buttons. Also, notice + * the notes on mouseEntered and mouseExited. + * * @param pSwingMouseEvent * @param aEvent */ - void dispatchEvent( PSwingMouseEvent pSwingMouseEvent, PInputEvent aEvent ) { + void dispatchEvent(PSwingMouseEvent pSwingMouseEvent, PInputEvent aEvent) { Component comp = null; Point2D pt = null; PNode pickedNode = pSwingMouseEvent.getPath().getPickedNode(); @@ -154,27 +152,27 @@ PNode currentNode = pSwingMouseEvent.getCurrentNode(); - if( currentNode instanceof PSwing ) { + if (currentNode instanceof PSwing) { - PSwing swing = (PSwing)currentNode; + PSwing swing = (PSwing) currentNode; PNode grabNode = pickedNode; - if( grabNode.isDescendentOf( canvas.getRoot() ) ) { - pt = new Point2D.Double( pSwingMouseEvent.getX(), pSwingMouseEvent.getY() ); - cameraToLocal( pSwingMouseEvent.getPath().getTopCamera(), pt, grabNode ); - prevPoint = new Point2D.Double( pt.getX(), pt.getY() ); + if (grabNode.isDescendentOf(canvas.getRoot())) { + pt = new Point2D.Double(pSwingMouseEvent.getX(), pSwingMouseEvent.getY()); + cameraToLocal(pSwingMouseEvent.getPath().getTopCamera(), pt, grabNode); + prevPoint = new Point2D.Double(pt.getX(), pt.getY()); // This is only partially fixed to find the deepest - // component at pt. It needs to do something like + // component at pt. It needs to do something like // package private method: // Container.getMouseEventTarget(int,int,boolean) - comp = findShowingComponentAt( swing.getComponent(), (int)pt.getX(), (int)pt.getY() ); + comp = findShowingComponentAt(swing.getComponent(), (int) pt.getX(), (int) pt.getY()); // We found the right component - but we need to // get the offset to put the event in the component's // coordinates - if( comp != null && comp != swing.getComponent() ) { - for( Component c = comp; c != swing.getComponent(); c = c.getParent() ) { + if (comp != null && comp != swing.getComponent()) { + for (Component c = comp; c != swing.getComponent(); c = c.getParent()) { offX += c.getLocation().getX(); offY += c.getLocation().getY(); } @@ -182,15 +180,15 @@ // Mouse Pressed gives focus - effects Mouse Drags and // Mouse Releases - if( comp != null && pSwingMouseEvent.getID() == MouseEvent.MOUSE_PRESSED ) { - if( SwingUtilities.isLeftMouseButton( pSwingMouseEvent ) ) { - leftButtonData.setState( swing, pickedNode, comp, offX, offY ); + if (comp != null && pSwingMouseEvent.getID() == MouseEvent.MOUSE_PRESSED) { + if (SwingUtilities.isLeftMouseButton(pSwingMouseEvent)) { + leftButtonData.setState(swing, pickedNode, comp, offX, offY); } - else if( SwingUtilities.isMiddleMouseButton( pSwingMouseEvent ) ) { - middleButtonData.setState( swing, pickedNode, comp, offX, offY ); + else if (SwingUtilities.isMiddleMouseButton(pSwingMouseEvent)) { + middleButtonData.setState(swing, pickedNode, comp, offX, offY); } - else if( SwingUtilities.isRightMouseButton( pSwingMouseEvent ) ) { - rightButtonData.setState( swing, pickedNode, comp, offX, offY ); + else if (SwingUtilities.isRightMouseButton(pSwingMouseEvent)) { + rightButtonData.setState(swing, pickedNode, comp, offX, offY); } } } @@ -199,219 +197,216 @@ // This first case we don't want to give events to just // any Swing component - but to the one that got the // original mousePressed - if( pSwingMouseEvent.getID() == MouseEvent.MOUSE_DRAGGED || - pSwingMouseEvent.getID() == MouseEvent.MOUSE_RELEASED ) { + if (pSwingMouseEvent.getID() == MouseEvent.MOUSE_DRAGGED + || pSwingMouseEvent.getID() == MouseEvent.MOUSE_RELEASED) { // LEFT MOUSE BUTTON - if( SwingUtilities.isLeftMouseButton( pSwingMouseEvent ) && leftButtonData.getFocusedComponent() != null ) { - handleButton( pSwingMouseEvent, aEvent, leftButtonData ); + if (SwingUtilities.isLeftMouseButton(pSwingMouseEvent) && leftButtonData.getFocusedComponent() != null) { + handleButton(pSwingMouseEvent, aEvent, leftButtonData); } // MIDDLE MOUSE BUTTON - if( SwingUtilities.isMiddleMouseButton( pSwingMouseEvent ) && middleButtonData.getFocusedComponent() != null ) - { - handleButton( pSwingMouseEvent, aEvent, middleButtonData ); + if (SwingUtilities.isMiddleMouseButton(pSwingMouseEvent) && middleButtonData.getFocusedComponent() != null) { + handleButton(pSwingMouseEvent, aEvent, middleButtonData); } // RIGHT MOUSE BUTTON - if( SwingUtilities.isRightMouseButton( pSwingMouseEvent ) && rightButtonData.getFocusedComponent() != null ) - { - handleButton( pSwingMouseEvent, aEvent, rightButtonData ); + if (SwingUtilities.isRightMouseButton(pSwingMouseEvent) && rightButtonData.getFocusedComponent() != null) { + handleButton(pSwingMouseEvent, aEvent, rightButtonData); } } // This case covers the cases mousePressed, mouseClicked, // and mouseMoved events - else if( ( pSwingMouseEvent.getID() == MouseEvent.MOUSE_PRESSED || - pSwingMouseEvent.getID() == MouseEvent.MOUSE_CLICKED || - pSwingMouseEvent.getID() == MouseEvent.MOUSE_MOVED ) && - ( comp != null ) ) { + else if ((pSwingMouseEvent.getID() == MouseEvent.MOUSE_PRESSED + || pSwingMouseEvent.getID() == MouseEvent.MOUSE_CLICKED || pSwingMouseEvent.getID() == MouseEvent.MOUSE_MOVED) + && (comp != null)) { - MouseEvent e_temp = new MouseEvent( comp, - pSwingMouseEvent.getID(), - pSwingMouseEvent.getWhen(), - pSwingMouseEvent.getModifiers(), - (int)pt.getX() - offX, - (int)pt.getY() - offY, - pSwingMouseEvent.getClickCount(), - pSwingMouseEvent.isPopupTrigger() ); + MouseEvent e_temp = new MouseEvent(comp, pSwingMouseEvent.getID(), pSwingMouseEvent.getWhen(), + pSwingMouseEvent.getModifiers(), (int) pt.getX() - offX, (int) pt.getY() - offY, pSwingMouseEvent + .getClickCount(), pSwingMouseEvent.isPopupTrigger()); - PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(), e_temp, aEvent ); - dispatchEvent( comp, e2 ); + PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent); + dispatchEvent(comp, e2); pSwingMouseEvent.consume(); } // Now we need to check if an exit or enter event needs to // be dispatched - this code is independent of the mouseButtons. // I tested in normal Swing to see the correct behavior. - if( prevComponent != null ) { + if (prevComponent != null) { // This means mouseExited // This shouldn't happen - since we're only getting node events - if( comp == null || pSwingMouseEvent.getID() == MouseEvent.MOUSE_EXITED ) { - MouseEvent e_temp = createExitEvent( pSwingMouseEvent ); + if (comp == null || pSwingMouseEvent.getID() == MouseEvent.MOUSE_EXITED) { + MouseEvent e_temp = createExitEvent(pSwingMouseEvent); - PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(), e_temp, aEvent ); + PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent); - dispatchEvent( prevComponent, e2 ); + dispatchEvent(prevComponent, e2); prevComponent = null; - if( pSwingMouseEvent.getID() == MouseEvent.MOUSE_EXITED ) { + if (pSwingMouseEvent.getID() == MouseEvent.MOUSE_EXITED) { pSwingMouseEvent.consume(); } } // This means mouseExited prevComponent and mouseEntered comp - else if( prevComponent != comp ) { - MouseEvent e_temp = createExitEvent( pSwingMouseEvent ); - PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(), e_temp, aEvent ); - dispatchEvent( prevComponent, e2 ); + else if (prevComponent != comp) { + MouseEvent e_temp = createExitEvent(pSwingMouseEvent); + PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent); + dispatchEvent(prevComponent, e2); - e_temp = createEnterEvent( comp, pSwingMouseEvent, offX, offY ); - e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(), e_temp, aEvent ); - comp.dispatchEvent( e2 ); + e_temp = createEnterEvent(comp, pSwingMouseEvent, offX, offY); + e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent); + comp.dispatchEvent(e2); } } else { // This means mouseEntered - if( comp != null ) { - MouseEvent e_temp = createEnterEvent( comp, pSwingMouseEvent, offX, offY ); - PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(), e_temp, aEvent ); - dispatchEvent( comp, e2 ); + if (comp != null) { + MouseEvent e_temp = createEnterEvent(comp, pSwingMouseEvent, offX, offY); + PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent); + dispatchEvent(comp, e2); } } - //todo add cursors -// // We have to manager our own Cursors since this is normally -// // done on the native side -// if( comp != cursorComponent && -// focusNodeLeft == null && -// focusNodeMiddle == null && -// focusNodeRight == null ) { -// if( comp != null ) { -// cursorComponent = comp; -// canvas.setCursor( comp.getCursor(), false ); -// } -// else { -// cursorComponent = null; -// canvas.resetCursor(); -// } -// } + // todo add cursors + // // We have to manager our own Cursors since this is normally + // // done on the native side + // if( comp != cursorComponent && + // focusNodeLeft == null && + // focusNodeMiddle == null && + // focusNodeRight == null ) { + // if( comp != null ) { + // cursorComponent = comp; + // canvas.setCursor( comp.getCursor(), false ); + // } + // else { + // cursorComponent = null; + // canvas.resetCursor(); + // } + // } // Set the previous variables for next time prevComponent = comp; - if( comp != null ) { - prevOff = new Point2D.Double( offX, offY ); + if (comp != null) { + prevOff = new Point2D.Double(offX, offY); } } - private MouseEvent createEnterEvent( Component comp, PSwingMouseEvent e1, int offX, int offY ) { - return new MouseEvent( comp, MouseEvent.MOUSE_ENTERED, - e1.getWhen(), 0, - (int)prevPoint.getX() - offX, (int)prevPoint.getY() - offY, - e1.getClickCount(), e1.isPopupTrigger() ); + private MouseEvent createEnterEvent(Component comp, PSwingMouseEvent e1, int offX, int offY) { + return new MouseEvent(comp, MouseEvent.MOUSE_ENTERED, e1.getWhen(), 0, (int) prevPoint.getX() - offX, + (int) prevPoint.getY() - offY, e1.getClickCount(), e1.isPopupTrigger()); } - private MouseEvent createExitEvent( PSwingMouseEvent e1 ) { - return new MouseEvent( prevComponent, MouseEvent.MOUSE_EXITED, - e1.getWhen(), 0, - (int)prevPoint.getX() - (int)prevOff.getX(), (int)prevPoint.getY() - (int)prevOff.getY(), - e1.getClickCount(), e1.isPopupTrigger() ); + private MouseEvent createExitEvent(PSwingMouseEvent e1) { + return new MouseEvent(prevComponent, MouseEvent.MOUSE_EXITED, e1.getWhen(), 0, (int) prevPoint.getX() + - (int) prevOff.getX(), (int) prevPoint.getY() - (int) prevOff.getY(), e1.getClickCount(), e1 + .isPopupTrigger()); } - private void handleButton( PSwingMouseEvent e1, PInputEvent aEvent, ButtonData buttonData ) { + private void handleButton(PSwingMouseEvent e1, PInputEvent aEvent, ButtonData buttonData) { Point2D pt; - if( buttonData.getPNode().isDescendentOf( canvas.getRoot() ) ) { - pt = new Point2D.Double( e1.getX(), e1.getY() ); - cameraToLocal( e1.getPath().getTopCamera(), pt, buttonData.getPNode() ); - //todo this probably won't handle viewing through multiple cameras. - MouseEvent e_temp = new MouseEvent( buttonData.getFocusedComponent(), - e1.getID(), e1.getWhen(), e1.getModifiers(), - (int)pt.getX() - buttonData.getOffsetX(), - (int)pt.getY() - buttonData.getOffsetY(), - e1.getClickCount(), e1.isPopupTrigger() ); + if (buttonData.getPNode().isDescendentOf(canvas.getRoot())) { + pt = new Point2D.Double(e1.getX(), e1.getY()); + cameraToLocal(e1.getPath().getTopCamera(), pt, buttonData.getPNode()); + // todo this probably won't handle viewing through multiple cameras. + MouseEvent e_temp = new MouseEvent(buttonData.getFocusedComponent(), e1.getID(), e1.getWhen(), e1 + .getModifiers(), (int) pt.getX() - buttonData.getOffsetX(), (int) pt.getY() + - buttonData.getOffsetY(), e1.getClickCount(), e1.isPopupTrigger()); - PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent( e_temp.getID(), e_temp, aEvent ); - dispatchEvent( buttonData.getFocusedComponent(), e2 ); + PSwingMouseEvent e2 = PSwingMouseEvent.createMouseEvent(e_temp.getID(), e_temp, aEvent); + dispatchEvent(buttonData.getFocusedComponent(), e2); } else { - dispatchEvent( buttonData.getFocusedComponent(), e1 ); + dispatchEvent(buttonData.getFocusedComponent(), e1); } - //buttonData.getPSwing().repaint(); //Experiment with SliderExample (from Martin) suggests this line is unnecessary, and a serious problem in performance. + // buttonData.getPSwing().repaint(); //Experiment with SliderExample + // (from Martin) suggests this line is unnecessary, and a serious + // problem in performance. e1.consume(); - if( e1.getID() == MouseEvent.MOUSE_RELEASED ) { + if (e1.getID() == MouseEvent.MOUSE_RELEASED) { buttonData.mouseReleased(); } } - private void dispatchEvent( final Component target, final PSwingMouseEvent event ) { - SwingUtilities.invokeLater( new Runnable() { + private void dispatchEvent(final Component target, final PSwingMouseEvent event) { + SwingUtilities.invokeLater(new Runnable() { public void run() { - target.dispatchEvent( event ); + target.dispatchEvent(event); } - } ); + }); } - private void cameraToLocal( PCamera topCamera, Point2D pt, PNode node ) { + private void cameraToLocal(PCamera topCamera, Point2D pt, PNode node) { AffineTransform inverse = null; try { inverse = topCamera.getViewTransform().createInverse(); } - catch( NoninvertibleTransformException e ) { + catch (NoninvertibleTransformException e) { e.printStackTrace(); } - - /* Only apply the camera's view transform when this node is a descendant of PLayer */ + + /* + * Only apply the camera's view transform when this node is a descendant + * of PLayer + */ PNode searchNode = node; do { - searchNode = searchNode.getParent(); - if (searchNode instanceof PLayer) { - inverse.transform( pt, pt ); - break; - } - } while(searchNode != null); - - if( node != null ) { - node.globalToLocal( pt ); + searchNode = searchNode.getParent(); + if (searchNode instanceof PLayer) { + inverse.transform(pt, pt); + break; + } + } while (searchNode != null); + + if (node != null) { + node.globalToLocal(pt); } return; } /** - * Process a piccolo event and (if active) dispatch the corresponding Swing event. - * + * Process a piccolo event and (if active) dispatch the corresponding Swing + * event. + * * @param aEvent * @param type */ - public void processEvent( PInputEvent aEvent, int type ) { - if(aEvent.isMouseEvent()) { + public void processEvent(PInputEvent aEvent, int type) { + if (aEvent.isMouseEvent()) { InputEvent sourceSwingEvent = aEvent.getSourceSwingEvent(); if (sourceSwingEvent instanceof MouseEvent) { - MouseEvent swingMouseEvent = (MouseEvent) sourceSwingEvent; - PSwingMouseEvent pSwingMouseEvent = PSwingMouseEvent.createMouseEvent( swingMouseEvent.getID(), swingMouseEvent, aEvent ); - if( !recursing ) { + MouseEvent swingMouseEvent = (MouseEvent) sourceSwingEvent; + PSwingMouseEvent pSwingMouseEvent = PSwingMouseEvent.createMouseEvent(swingMouseEvent.getID(), + swingMouseEvent, aEvent); + if (!recursing) { recursing = true; - dispatchEvent( pSwingMouseEvent, aEvent ); + dispatchEvent(pSwingMouseEvent, aEvent); recursing = false; } - } else { - new Exception("PInputEvent.getSourceSwingEvent was not a MouseEvent. Actual event: " + sourceSwingEvent + ", class=" + sourceSwingEvent.getClass().getName() ).printStackTrace(); + } + else { + 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; - } - } -*/ + + /* + * 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; } } + */ } /** @@ -424,7 +419,7 @@ private int focusOffX = 0; private int focusOffY = 0; - public void setState( PSwing swing, PNode visualNode, Component comp, int offX, int offY ) { + public void setState(PSwing swing, PNode visualNode, Component comp, int offX, int offY) { focusPSwing = swing; focusComponent = comp; focusNode = visualNode; diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java index e9a49fc..be69302 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseEvent.java @@ -16,8 +16,9 @@ import java.io.Serializable; /** - * PMouseEvent is an event which indicates that a mouse action occurred in a node. - * + * PMouseEvent is an event which indicates that a mouse action occurred + * in a node. + ** This low-level event is generated by a node object for: *
PMouseListener
- * or PMouseAdapter
object which registered to receive
- * the "interesting" mouse events using the component's
- * addMouseListener
method.
- * (PMouseAdapter
objects implement the
- * PMouseListener
interface.) Each such listener object
- * gets a PMouseEvent
containing the mouse event.
- *
- * 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.
- *
+ *
+ *
+ * A PMouseEvent object is passed to every PMouseListener
or
+ * PMouseAdapter
object which registered to receive the
+ * "interesting" mouse events using the component's
+ * addMouseListener
method. (PMouseAdapter
objects
+ * implement the PMouseListener
interface.) Each such listener
+ * object gets a PMouseEvent
containing the mouse event.
+ *
+ * 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 Benjamin B. Bederson * @author Sam R. Reid * @author Lance E. Good @@ -53,50 +56,50 @@ /** * Constructs a new PMouse event from a Java MouseEvent. - * - * @param id The event type (MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_CLICKED, MOUSE_ENTERED, MOUSE_EXITED) - * @param e The original Java mouse event - * when in MOUSE_RELEASED events. + * + * @param id The event type (MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_CLICKED, + * MOUSE_ENTERED, MOUSE_EXITED) + * @param e The original Java mouse event when in MOUSE_RELEASED events. */ - protected PSwingMouseEvent( int id, MouseEvent e, PInputEvent event ) { - super( (Component)e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger() ); + protected PSwingMouseEvent(int id, MouseEvent e, PInputEvent event) { + super((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e + .getClickCount(), e.isPopupTrigger()); this.id = id; this.event = event; } /** * Creates and returns a new PMouse event from a Java MouseEvent. - * - * @param id The event type (MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_CLICKED, MOUSE_ENTERED, MOUSE_EXITED, MOUSE_MOVED, MOUSE_DRAGGED) - * @param e The original Java mouse event - * when in MOUSE_DRAGGED and MOUSE_RELEASED events. + * + * @param id The event type (MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_CLICKED, + * MOUSE_ENTERED, MOUSE_EXITED, MOUSE_MOVED, MOUSE_DRAGGED) + * @param e The original Java mouse event when in MOUSE_DRAGGED and + * MOUSE_RELEASED events. */ - public static PSwingMouseEvent createMouseEvent( int id, - MouseEvent e, - PInputEvent pEvent ) { - if( id == PSwingMouseEvent.MOUSE_MOVED || - id == PSwingMouseEvent.MOUSE_DRAGGED ) { - return new PSwingMouseMotionEvent( id, e, pEvent ); + public static PSwingMouseEvent createMouseEvent(int id, MouseEvent e, PInputEvent pEvent) { + if (id == PSwingMouseEvent.MOUSE_MOVED || id == PSwingMouseEvent.MOUSE_DRAGGED) { + return new PSwingMouseMotionEvent(id, e, pEvent); } else { - return new PSwingMouseEvent( id, e, pEvent ); + return new PSwingMouseEvent(id, e, pEvent); } } /** - * Returns the x,y position of the event in the local coordinate system of the node - * the event occurred on. - * - * @return a Point2D object containing the x and y coordinates local to the node. + * Returns the x,y position of the event in the local coordinate system of + * the node the event occurred on. + * + * @return a Point2D object containing the x and y coordinates local to the + * node. */ public Point2D getLocalPoint() { - return new Point2D.Double( getX(), getY() ); + return new Point2D.Double(getX(), getY()); } /** - * Returns the horizontal x position of the event in the local coordinate system - * of the node the event occurred on. - * + * Returns the horizontal x position of the event in the local coordinate + * system of the node the event occurred on. + * * @return x a double indicating horizontal position local to the node. */ public double getLocalX() { @@ -104,9 +107,9 @@ } /** - * Returns the vertical y position of the event in the local coordinate system - * of the node the event occurred on. - * + * Returns the vertical y position of the event in the local coordinate + * system of the node the event occurred on. + * * @return y a double indicating vertical position local to the node. */ public double getLocalY() { @@ -115,7 +118,7 @@ /** * Determine the event type. - * + * * @return the id */ public int getID() { @@ -123,13 +126,13 @@ } /** - * Determine the node the event originated at. If an event percolates - * up the tree and is handled by an event listener higher up in the - * tree than the original node that generated the event, this returns - * the original node. For mouse drag and release events, this is the - * node that the original matching press event went to - in other words, - * the event is 'grabbed' by the originating node. - * + * Determine the node the event originated at. If an event percolates up the + * tree and is handled by an event listener higher up in the tree than the + * original node that generated the event, this returns the original node. + * For mouse drag and release events, this is the node that the original + * matching press event went to - in other words, the event is 'grabbed' by + * the originating node. + * * @return the node */ public PNode getNode() { @@ -137,8 +140,9 @@ } /** - * Determine the path the event took from the PCanvas down to the visual component. - * + * Determine the path the event took from the PCanvas down to the visual + * component. + * * @return the path */ public PPickPath getPath() { @@ -146,13 +150,13 @@ } /** - * Determine the node the event originated at. If an event percolates - * up the tree and is handled by an event listener higher up in the - * tree than the original node that generated the event, this returns - * the original node. For mouse drag and release events, this is the - * node that the original matching press event went to - in other words, - * the event is 'grabbed' by the originating node. - * + * Determine the node the event originated at. If an event percolates up the + * tree and is handled by an event listener higher up in the tree than the + * original node that generated the event, this returns the original node. + * For mouse drag and release events, this is the node that the original + * matching press event went to - in other words, the event is 'grabbed' by + * the originating node. + * * @return the node */ public PNode getGrabNode() { @@ -161,7 +165,7 @@ /** * Return the path from the PCanvas down to the currently grabbed object. - * + * * @return the path */ public PPickPath getGrabPath() { @@ -169,9 +173,10 @@ } /** - * Get the current node that is under the cursor. This may return a different result then getGrabNode() when - * in a MOUSE_RELEASED or MOUSE_DRAGGED event. - * + * Get the current node that is under the cursor. This may return a + * different result then getGrabNode() when in a MOUSE_RELEASED or + * MOUSE_DRAGGED event. + * * @return the current node. */ public PNode getCurrentNode() { @@ -179,9 +184,10 @@ } /** - * Get the path from the PCanvas down to the visual component currently under the mouse.This may - * give a different result then getGrabPath() durring a MOUSE_DRAGGED or MOUSE_RELEASED operation. - * + * Get the path from the PCanvas down to the visual component currently + * under the mouse.This may give a different result then getGrabPath() + * durring a MOUSE_DRAGGED or MOUSE_RELEASED operation. + * * @return the current path. */ public PPickPath getCurrentPath() { @@ -190,54 +196,55 @@ /** * Calls appropriate method on the listener based on this events ID. - * + * * @param listener the MouseListener or MouseMotionListener to dispatch to. */ - public void dispatchTo( Object listener ) { - if( listener instanceof MouseListener ) { - MouseListener mouseListener = (MouseListener)listener; - switch( getID() ) { + public void dispatchTo(Object listener) { + if (listener instanceof MouseListener) { + MouseListener mouseListener = (MouseListener) listener; + switch (getID()) { case PSwingMouseEvent.MOUSE_CLICKED: - mouseListener.mouseClicked( this ); + mouseListener.mouseClicked(this); break; case PSwingMouseEvent.MOUSE_ENTERED: - mouseListener.mouseEntered( this ); + mouseListener.mouseEntered(this); break; case PSwingMouseEvent.MOUSE_EXITED: - mouseListener.mouseExited( this ); + mouseListener.mouseExited(this); break; case PSwingMouseEvent.MOUSE_PRESSED: - mouseListener.mousePressed( this ); + mouseListener.mousePressed(this); break; case PSwingMouseEvent.MOUSE_RELEASED: - mouseListener.mouseReleased( this ); + mouseListener.mouseReleased(this); break; default: - throw new RuntimeException( "PMouseEvent with bad ID" ); + throw new RuntimeException("PMouseEvent with bad ID"); } } else { - MouseMotionListener mouseMotionListener = (MouseMotionListener)listener; - switch( getID() ) { + MouseMotionListener mouseMotionListener = (MouseMotionListener) listener; + switch (getID()) { case PSwingMouseEvent.MOUSE_DRAGGED: - mouseMotionListener.mouseDragged( this ); + mouseMotionListener.mouseDragged(this); break; case PSwingMouseEvent.MOUSE_MOVED: - mouseMotionListener.mouseMoved( this ); + mouseMotionListener.mouseMoved(this); break; default: - throw new RuntimeException( "PMouseMotionEvent with bad ID" ); + throw new RuntimeException("PMouseMotionEvent with bad ID"); } } } /** - * Set the souce of this event. As the event is fired up the tree the source of the - * event will keep changing to reflect the scenegraph object that is firing the event. - * + * Set the souce of this event. As the event is fired up the tree the source + * of the event will keep changing to reflect the scenegraph object that is + * firing the event. + * * @param aSource */ - public void setSource( Object aSource ) { + public void setSource(Object aSource) { source = aSource; } } \ No newline at end of file diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseMotionEvent.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseMotionEvent.java index ac48daa..93cb2b1 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseMotionEvent.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingMouseMotionEvent.java @@ -10,31 +10,34 @@ import java.awt.event.MouseMotionListener; /** - * PMouseMotionEvent is an event which indicates that a mouse motion action occurred in a node. - * + * PMouseMotionEvent is an event which indicates that a mouse motion + * action occurred in a node. + ** This low-level event is generated by a node object for: *
PMouseMotionListener
- * or PMouseMotionAdapter
object which registered to receive
- * mouse motion events using the component's addMouseMotionListener
+ *
+ *
+ * A PMouseEvent object is passed to every PMouseMotionListener
or
+ * PMouseMotionAdapter
object which registered to receive mouse
+ * motion events using the component's addMouseMotionListener
* method. (PMouseMotionAdapter
objects implement the
- * PMouseMotionListener
interface.) Each such listener object
- * gets a PMouseEvent
containing the mouse motion event.
- *
PMouseMotionListener
interface.) Each such listener object gets
+ * a PMouseEvent
containing the mouse motion event.
+ *
+ * + * 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 Benjamin B. Bederson * @author Sam R. Reid * @author Lance E. Good @@ -43,31 +46,30 @@ /** * Constructs a new PMouse event from a Java MouseEvent. - * + * * @param id The event type (MOUSE_MOVED, MOUSE_DRAGGED) - * @param e The original Java mouse event - * when in MOUSE_DRAGGED events. + * @param e The original Java mouse event when in MOUSE_DRAGGED events. */ - protected PSwingMouseMotionEvent( int id, MouseEvent e, PInputEvent event ) { - super( id, e, event ); + protected PSwingMouseMotionEvent(int id, MouseEvent e, PInputEvent event) { + super(id, e, event); } /** * Calls appropriate method on the listener based on this events ID. - * + * * @param listener the target for dispatch. */ - public void dispatchTo( Object listener ) { - MouseMotionListener mouseMotionListener = (MouseMotionListener)listener; - switch( getID() ) { + public void dispatchTo(Object listener) { + MouseMotionListener mouseMotionListener = (MouseMotionListener) listener; + switch (getID()) { case PSwingMouseEvent.MOUSE_DRAGGED: - mouseMotionListener.mouseDragged( this ); + mouseMotionListener.mouseDragged(this); break; case PSwingMouseEvent.MOUSE_MOVED: - mouseMotionListener.mouseMoved( this ); + mouseMotionListener.mouseMoved(this); break; default: - throw new RuntimeException( "PMouseMotionEvent with bad ID" ); + throw new RuntimeException("PMouseMotionEvent with bad ID"); } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingRepaintManager.java b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingRepaintManager.java index 7b9a823..132f670 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingRepaintManager.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/pswing/PSwingRepaintManager.java @@ -18,33 +18,35 @@ import java.util.Vector; /** - * This RepaintManager replaces the default Swing implementation, and - * is used to intercept and repaint dirty regions of PSwing components. - * - * 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 javax.swing.RepaintManager may still be called and - * perform in the expected manner. - * - * 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 component hierarchy as - * usually happens. - * - * Also traps revalidate calls made by the Swing components added - * to the PCanvas to reshape the applicable Visual Component. - * - * Also keeps a list of PSwings that are painting. This - * disables repaint until the component has finished painting. This is - * to address a problem introduced 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 + * This RepaintManager replaces the default Swing implementation, and is used to + * intercept and repaint dirty regions of PSwing components. + *+ * 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 + * javax.swing.RepaintManager may still be called and perform in the expected + * manner. + *
+ *+ * 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 + * component hierarchy as usually happens. + *
+ *+ * Also traps revalidate calls made by the Swing components added to the PCanvas + * to reshape the applicable Visual Component. + *
+ *+ * Also keeps a list of PSwings that are painting. This disables repaint until + * the component has finished painting. This is to address a problem introduced + * 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. - * + *
+ * * @author Benjamin B. Bederson * @author Lance E. Good * @author Sam R. Reid @@ -57,67 +59,64 @@ private Vector paintingComponents = new Vector(); /** - * Locks repaint for a particular (Swing) component displayed by - * PCanvas - * + * Locks repaint for a particular (Swing) component displayed by PCanvas + * * @param c The component for which the repaint is to be locked */ - public void lockRepaint( JComponent c ) { - paintingComponents.addElement( c ); + public void lockRepaint(JComponent c) { + paintingComponents.addElement(c); } /** - * Unlocks repaint for a particular (Swing) component displayed by - * PCanvas - * + * Unlocks repaint for a particular (Swing) component displayed by PCanvas + * * @param c The component for which the repaint is to be unlocked */ - public void unlockRepaint( JComponent c ) { - synchronized( paintingComponents ) { - paintingComponents.removeElementAt( paintingComponents.lastIndexOf( c ) ); + public void unlockRepaint(JComponent c) { + synchronized (paintingComponents) { + paintingComponents.removeElementAt(paintingComponents.lastIndexOf(c)); } } /** - * Returns true if repaint is currently locked for a component and - * false otherwise - * + * Returns true if repaint is currently locked for a component and false + * otherwise + * * @param c The component for which the repaint status is desired * @return Whether the component is currently painting */ - public boolean isPainting( JComponent c ) { - return paintingComponents.contains( c ); + public boolean isPainting(JComponent c) { + return paintingComponents.contains(c); } /** * This is the method "repaint" now calls in the Swing components. - * Overridden to capture repaint calls from those Swing components - * which are being used as Piccolo visual components and to call the Piccolo - * repaint mechanism rather than the traditional Component hierarchy - * repaint mechanism. Otherwise, behaves like the superclass. - * + * Overridden to capture repaint calls from those Swing components which are + * being used as Piccolo visual components and to call the Piccolo repaint + * mechanism rather than the traditional Component hierarchy repaint + * mechanism. Otherwise, behaves like the superclass. + * * @param c Component to be repainted * @param x X coordinate of the dirty region in the component * @param y Y coordinate of the dirty region in the component * @param w Width of the dirty region in the component * @param h Height of the dirty region in the component */ - public synchronized void addDirtyRegion( JComponent c, int x, int y, final int w, final int h ) { -// System.out.println( "PSwingCanvas$PBasicRepaintManager.addDirtyRegion, c="+c.getClass()+", rect=["+x+", "+y+", "+w+", " +", "+h+"], c="+c); + public synchronized void addDirtyRegion(JComponent c, int x, int y, final int w, final int h) { boolean captureRepaint = false; JComponent capturedComponent = null; int captureX = x, 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 + // (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 = c; comp != null && comp.isLightweight() && !captureRepaint; comp = comp.getParent() ) { - if( swingWrappers.contains( comp.getParent() ) ) { - if( comp instanceof JComponent ) { + for (Component comp = c; comp != null && comp.isLightweight() && !captureRepaint; comp = comp.getParent()) { + if (swingWrappers.contains(comp.getParent())) { + if (comp instanceof JComponent) { captureRepaint = true; - capturedComponent = (JComponent)comp; + capturedComponent = (JComponent) comp; } } else { @@ -129,58 +128,57 @@ // Now we check to see if we should capture the repaint and act // accordingly - if( captureRepaint ) { - if( !isPainting( capturedComponent ) ) { - final PSwing vis = (PSwing)capturedComponent.getClientProperty( PSwing.PSWING_PROPERTY ); - if( vis != null ) { + if (captureRepaint) { + if (!isPainting(capturedComponent)) { + final PSwing vis = (PSwing) capturedComponent.getClientProperty(PSwing.PSWING_PROPERTY); + if (vis != null) { final int repaintX = captureX; final int repaintY = captureY; Runnable repainter = new Runnable() { public void run() { - vis.repaint( new PBounds( (double)repaintX, (double)repaintY, (double)w, (double)h ) ); + vis.repaint(new PBounds((double) repaintX, (double) repaintY, (double) w, (double) h)); } }; - SwingUtilities.invokeLater( repainter ); + SwingUtilities.invokeLater(repainter); } } } else { - super.addDirtyRegion( c, x, y, w, h ); + super.addDirtyRegion(c, x, y, w, h); } } /** - * This is the method "revalidate" calls in the Swing components. - * Overridden to capture revalidate 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. - * + * This is the method "revalidate" calls in the Swing components. Overridden + * to capture revalidate 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. + * * @param invalidComponent The Swing component that needs validation */ - public synchronized void addInvalidComponent( JComponent invalidComponent ) { + public synchronized void addInvalidComponent(JComponent invalidComponent) { final JComponent capturedComponent = invalidComponent; - if( capturedComponent.getParent() != null && - capturedComponent.getParent() instanceof JComponent && - ( (JComponent)capturedComponent.getParent() ).getClientProperty( PSwingCanvas.SWING_WRAPPER_KEY ) != null ) - { + if (capturedComponent.getParent() != null + && capturedComponent.getParent() instanceof JComponent + && ((JComponent) capturedComponent.getParent()).getClientProperty(PSwingCanvas.SWING_WRAPPER_KEY) != null) { Runnable validater = new Runnable() { public void run() { capturedComponent.validate(); - PSwing swing = (PSwing)capturedComponent.getClientProperty( PSwing.PSWING_PROPERTY ); + PSwing swing = (PSwing) capturedComponent.getClientProperty(PSwing.PSWING_PROPERTY); swing.reshape(); } }; - SwingUtilities.invokeLater( validater ); + SwingUtilities.invokeLater(validater); } else { - super.addInvalidComponent( invalidComponent ); + super.addInvalidComponent(invalidComponent); } } - void addPSwingCanvas( PSwingCanvas swingWrapper ) { - swingWrappers.add( swingWrapper.getSwingWrapper() ); + void addPSwingCanvas(PSwingCanvas swingWrapper) { + swingWrappers.add(swingWrapper.getSwingWrapper()); } } \ No newline at end of file diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PCacheCanvas.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PCacheCanvas.java index 8ab0bd1..9729f0b 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PCacheCanvas.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PCacheCanvas.java @@ -11,18 +11,19 @@ /** * An extension of PCanvas that automatically installs a PCacheCamera + * * @author Lance Good */ public class PCacheCanvas extends PCanvas { protected PCamera createDefaultCamera() { - PRoot r = new PRoot(); - PLayer l = new PLayer(); - PCamera c = new PCacheCamera(); - - r.addChild(c); - r.addChild(l); - c.addLayer(l); - - return c; + PRoot r = new PRoot(); + PLayer l = new PLayer(); + PCamera c = new PCacheCamera(); + + r.addChild(c); + r.addChild(l); + c.addLayer(l); + + return c; } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PDefaultScrollDirector.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PDefaultScrollDirector.java index e3c3177..1e7a89f 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PDefaultScrollDirector.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PDefaultScrollDirector.java @@ -32,255 +32,264 @@ * follows the widely accepted model of scrolling - namely the scrollbars * control the movement of the window over the document rather than the movement * of the document under the window. - * + * * @author Lance Good */ public class PDefaultScrollDirector implements PScrollDirector, PropertyChangeListener { - /** - * The viewport that signals this scroll director - */ - protected PViewport viewPort; + /** + * The viewport that signals this scroll director + */ + protected PViewport viewPort; - /** - * The scrollpane that contains the viewport - */ - protected PScrollPane scrollPane; + /** + * The scrollpane that contains the viewport + */ + protected PScrollPane scrollPane; - /** - * The canvas that this class directs - */ - protected PCanvas view; + /** + * The canvas that this class directs + */ + protected PCanvas view; - /** - * The canvas' camera - */ - protected PCamera camera; + /** + * The canvas' camera + */ + protected PCamera camera; - /** - * The canvas' root - */ - protected PRoot root; + /** + * The canvas' root + */ + protected PRoot root; - /** - * Flag to indicate when scrolling is currently in progress - */ - protected boolean scrollInProgress = false; + /** + * Flag to indicate when scrolling is currently in progress + */ + protected boolean scrollInProgress = false; - /** - * The default constructor - */ - public PDefaultScrollDirector() { - } + /** + * The default constructor + */ + public PDefaultScrollDirector() { + } - /** - * Installs the scroll director and adds the appropriate listeners - * @param viewPort The viewport on which this director directs - * @param view The ZCanvas that the viewport looks at - */ - public void install(PViewport viewPort, final PCanvas view) { - this.scrollPane = (PScrollPane) viewPort.getParent(); - this.viewPort = viewPort; - this.view = view; + /** + * Installs the scroll director and adds the appropriate listeners + * + * @param viewPort The viewport on which this director directs + * @param view The ZCanvas that the viewport looks at + */ + public void install(PViewport viewPort, final PCanvas view) { + this.scrollPane = (PScrollPane) viewPort.getParent(); + this.viewPort = viewPort; + this.view = view; - if (view != null) { - this.camera = view.getCamera(); - this.root = view.getRoot(); - } + if (view != null) { + this.camera = view.getCamera(); + this.root = view.getRoot(); + } - if (camera != null) { - camera.addPropertyChangeListener(this); - } - if (root != null) { - root.addPropertyChangeListener(this); - } + if (camera != null) { + camera.addPropertyChangeListener(this); + } + if (root != null) { + root.addPropertyChangeListener(this); + } - if (scrollPane != null) { - scrollPane.revalidate(); - } - } + if (scrollPane != null) { + scrollPane.revalidate(); + } + } - /** - * Uninstall the scroll director from the viewport - */ - public void unInstall() { - viewPort = null; - view = null; + /** + * Uninstall the scroll director from the viewport + */ + public void unInstall() { + viewPort = null; + view = null; - if (camera != null) { - camera.removePropertyChangeListener(this); - } - if (root != null) { - root.removePropertyChangeListener(this); - } + if (camera != null) { + camera.removePropertyChangeListener(this); + } + if (root != null) { + root.removePropertyChangeListener(this); + } - camera = null; - root = null; - } + camera = null; + root = null; + } - /** - * Get the View position given the specified camera bounds - * @param viewBounds The bounds for which the view position will be computed - * @return The view position - */ - public Point getViewPosition(Rectangle2D viewBounds) { - Point pos = new Point(); - if (camera != null) { - // First we compute the union of all the layers - PBounds layerBounds = new PBounds(); - List layers = camera.getLayersReference(); - for(Iterator i=layers.iterator(); i.hasNext();) { - PLayer layer = (PLayer)i.next(); - layerBounds.add(layer.getFullBoundsReference()); - } + /** + * Get the View position given the specified camera bounds + * + * @param viewBounds The bounds for which the view position will be computed + * @return The view position + */ + public Point getViewPosition(Rectangle2D viewBounds) { + Point pos = new Point(); + if (camera != null) { + // First we compute the union of all the layers + PBounds layerBounds = new PBounds(); + List layers = camera.getLayersReference(); + for (Iterator i = layers.iterator(); i.hasNext();) { + PLayer layer = (PLayer) i.next(); + layerBounds.add(layer.getFullBoundsReference()); + } - // Then we put the bounds into camera coordinates and - // union the camera bounds - camera.viewToLocal(layerBounds); - layerBounds.add(viewBounds); + // Then we put the bounds into camera coordinates and + // union the camera bounds + camera.viewToLocal(layerBounds); + layerBounds.add(viewBounds); - pos.setLocation((int) (viewBounds.getX() - layerBounds.getX() + 0.5), (int) (viewBounds.getY() - layerBounds.getY() + 0.5)); - } + pos.setLocation((int) (viewBounds.getX() - layerBounds.getX() + 0.5), (int) (viewBounds.getY() + - layerBounds.getY() + 0.5)); + } - return pos; - } + return pos; + } - /** - * Get the size of the view based on the specified camera bounds - * @param viewBounds The view bounds for which the view size will be computed - * @return The view size - */ - public Dimension getViewSize(Rectangle2D viewBounds) { - Dimension size = new Dimension(); - if (camera != null) { - // First we compute the union of all the layers - PBounds bounds = new PBounds(); - List layers = camera.getLayersReference(); - for(Iterator i=layers.iterator(); i.hasNext();) { - PLayer layer = (PLayer)i.next(); - bounds.add(layer.getFullBoundsReference()); - } + /** + * Get the size of the view based on the specified camera bounds + * + * @param viewBounds The view bounds for which the view size will be + * computed + * @return The view size + */ + public Dimension getViewSize(Rectangle2D viewBounds) { + Dimension size = new Dimension(); + if (camera != null) { + // First we compute the union of all the layers + PBounds bounds = new PBounds(); + List layers = camera.getLayersReference(); + for (Iterator i = layers.iterator(); i.hasNext();) { + PLayer layer = (PLayer) i.next(); + bounds.add(layer.getFullBoundsReference()); + } - // Then we put the bounds into camera coordinates and - // union the camera bounds - if (!bounds.isEmpty()) { - camera.viewToLocal(bounds); - } - bounds.add(viewBounds); + // Then we put the bounds into camera coordinates and + // union the camera bounds + if (!bounds.isEmpty()) { + camera.viewToLocal(bounds); + } + bounds.add(viewBounds); - size.setSize((int) (bounds.getWidth() + 0.5), (int) (bounds.getHeight() + 0.5)); - } + size.setSize((int) (bounds.getWidth() + 0.5), (int) (bounds.getHeight() + 0.5)); + } - return size; - } + return size; + } - /** - * Set the view position in a manner consistent with standardized scrolling - * @param x The new x position - * @param y The new y position - */ - public void setViewPosition(double x, double y) { - if (camera != null) { - // If a scroll is in progress - we ignore new scrolls - - // if we didn't, since the scrollbars depend on the camera location - // we can end up with an infinite loop - if (!scrollInProgress) { - scrollInProgress = true; + /** + * Set the view position in a manner consistent with standardized scrolling + * + * @param x The new x position + * @param y The new y position + */ + public void setViewPosition(double x, double y) { + if (camera != null) { + // If a scroll is in progress - we ignore new scrolls - + // if we didn't, since the scrollbars depend on the camera location + // we can end up with an infinite loop + if (!scrollInProgress) { + scrollInProgress = true; - // Get the union of all the layers' bounds - PBounds layerBounds = new PBounds(); - List layers = camera.getLayersReference(); - for(Iterator i=layers.iterator(); i.hasNext();) { - PLayer layer = (PLayer)i.next(); - layerBounds.add(layer.getFullBoundsReference()); - } - - PAffineTransform at = camera.getViewTransform(); - at.transform(layerBounds,layerBounds); + // Get the union of all the layers' bounds + PBounds layerBounds = new PBounds(); + List layers = camera.getLayersReference(); + for (Iterator i = layers.iterator(); i.hasNext();) { + PLayer layer = (PLayer) i.next(); + layerBounds.add(layer.getFullBoundsReference()); + } - // Union the camera bounds - PBounds viewBounds = camera.getBoundsReference(); - layerBounds.add(viewBounds); + PAffineTransform at = camera.getViewTransform(); + at.transform(layerBounds, layerBounds); - // Now find the new view position in view coordinates - Point2D newPoint = new Point2D.Double(layerBounds.getX() + x, layerBounds.getY() + y); + // Union the camera bounds + PBounds viewBounds = camera.getBoundsReference(); + layerBounds.add(viewBounds); - // Now transform the new view position into global coords - camera.localToView(newPoint); + // Now find the new view position in view coordinates + Point2D newPoint = new Point2D.Double(layerBounds.getX() + x, layerBounds.getY() + y); - // Compute the new matrix values to put the camera at the - // correct location - double newX = - (at.getScaleX() * newPoint.getX() + at.getShearX() * newPoint.getY()); - double newY = - (at.getShearY() * newPoint.getX() + at.getScaleY() * newPoint.getY()); + // Now transform the new view position into global coords + camera.localToView(newPoint); - at.setTransform(at.getScaleX(), at.getShearY(), at.getShearX(), at.getScaleY(), newX, newY); + // Compute the new matrix values to put the camera at the + // correct location + double newX = -(at.getScaleX() * newPoint.getX() + at.getShearX() * newPoint.getY()); + double newY = -(at.getShearY() * newPoint.getX() + at.getScaleY() * newPoint.getY()); - // Now actually set the camera's transform - camera.setViewTransform(at); - scrollInProgress = false; - } - } - } + at.setTransform(at.getScaleX(), at.getShearY(), at.getShearX(), at.getScaleY(), newX, newY); - /** - * Invoked when the camera's view changes, or the bounds of the root or camera changes - */ - public void propertyChange(PropertyChangeEvent pce) { - boolean isRelevantViewEvent = (PCamera.PROPERTY_VIEW_TRANSFORM == pce.getPropertyName()); - boolean isRelevantBoundsEvent = (PNode.PROPERTY_BOUNDS == pce.getPropertyName() || PNode.PROPERTY_FULL_BOUNDS == pce.getPropertyName()) && (pce.getSource() == camera || pce.getSource() == view.getRoot()); - if (isRelevantViewEvent || isRelevantBoundsEvent) { - if (shouldRevalidateScrollPane()) { - scrollPane.revalidate(); - } - else { - viewPort.fireStateChanged(); - } - } - } + // Now actually set the camera's transform + camera.setViewTransform(at); + scrollInProgress = false; + } + } + } - /** - * Should the ScrollPane be revalidated. This occurs when either the - * scrollbars are showing and should be remove or are not showing and should - * be added. - * - * @return Whether the scroll pane should be revalidated - */ - public boolean shouldRevalidateScrollPane() { - if (camera != null) { - if (scrollPane.getHorizontalScrollBarPolicy() != JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED - && scrollPane.getVerticalScrollBarPolicy() != JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) { - return false; - } - - // Get the union of all the layers' bounds - PBounds layerBounds = new PBounds(); - List layers = camera.getLayersReference(); - for(Iterator i=layers.iterator(); i.hasNext();) { - PLayer layer = (PLayer)i.next(); - layerBounds.add(layer.getFullBoundsReference()); - } + /** + * Invoked when the camera's view changes, or the bounds of the root or + * camera changes + */ + public void propertyChange(PropertyChangeEvent pce) { + boolean isRelevantViewEvent = (PCamera.PROPERTY_VIEW_TRANSFORM == pce.getPropertyName()); + boolean isRelevantBoundsEvent = (PNode.PROPERTY_BOUNDS == pce.getPropertyName() || PNode.PROPERTY_FULL_BOUNDS == pce + .getPropertyName()) + && (pce.getSource() == camera || pce.getSource() == view.getRoot()); + if (isRelevantViewEvent || isRelevantBoundsEvent) { + if (shouldRevalidateScrollPane()) { + scrollPane.revalidate(); + } + else { + viewPort.fireStateChanged(); + } + } + } - // Put into camera coordinates - camera.viewToLocal(layerBounds); + /** + * Should the ScrollPane be revalidated. This occurs when either the + * scrollbars are showing and should be remove or are not showing and should + * be added. + * + * @return Whether the scroll pane should be revalidated + */ + public boolean shouldRevalidateScrollPane() { + if (camera != null) { + if (scrollPane.getHorizontalScrollBarPolicy() != JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED + && scrollPane.getVerticalScrollBarPolicy() != JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) { + return false; + } - // And union with the camera bounds - PBounds cameraBounds = camera.getBoundsReference(); - layerBounds.add(cameraBounds); + // Get the union of all the layers' bounds + PBounds layerBounds = new PBounds(); + List layers = camera.getLayersReference(); + for (Iterator i = layers.iterator(); i.hasNext();) { + PLayer layer = (PLayer) i.next(); + layerBounds.add(layer.getFullBoundsReference()); + } - // Truncate these to ints before comparing since - // that's what the ScrollPane uses - int layerWidth = (int) (layerBounds.getWidth() + 0.5); - int layerHeight = (int) (layerBounds.getHeight() + 0.5); - int cameraWidth = (int) (cameraBounds.getWidth() + 0.5); - int cameraHeight = (int) (cameraBounds.getHeight() + 0.5); + // Put into camera coordinates + camera.viewToLocal(layerBounds); - if ((scrollPane.getHorizontalScrollBar().isShowing() && layerWidth <= cameraWidth) - || (!scrollPane.getHorizontalScrollBar().isShowing() && layerWidth > cameraWidth) - || (scrollPane.getVerticalScrollBar().isShowing() && layerHeight <= cameraHeight) - || (!scrollPane.getVerticalScrollBar().isShowing() && layerHeight > cameraHeight)) { - return true; - } - } - return false; - } + // And union with the camera bounds + PBounds cameraBounds = camera.getBoundsReference(); + layerBounds.add(cameraBounds); + + // Truncate these to ints before comparing since + // that's what the ScrollPane uses + int layerWidth = (int) (layerBounds.getWidth() + 0.5); + int layerHeight = (int) (layerBounds.getHeight() + 0.5); + int cameraWidth = (int) (cameraBounds.getWidth() + 0.5); + int cameraHeight = (int) (cameraBounds.getHeight() + 0.5); + + if ((scrollPane.getHorizontalScrollBar().isShowing() && layerWidth <= cameraWidth) + || (!scrollPane.getHorizontalScrollBar().isShowing() && layerWidth > cameraWidth) + || (scrollPane.getVerticalScrollBar().isShowing() && layerHeight <= cameraHeight) + || (!scrollPane.getVerticalScrollBar().isShowing() && layerHeight > cameraHeight)) { + return true; + } + } + return false; + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollDirector.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollDirector.java index 87c4f03..d31fa3a 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollDirector.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollDirector.java @@ -16,42 +16,47 @@ /** * The interface an application can implement to control scrolling in a * PScrollPane->PViewport->ZCanvas component hierarchy. + * * @see PDefaultScrollDirector * @author Lance Good */ public interface PScrollDirector { - /** - * Installs the scroll director - * @param viewport The viewport on which this director directs - * @param view The ZCanvas that the viewport looks at - */ - public void install(PViewport viewport, PCanvas view); + /** + * Installs the scroll director + * + * @param viewport The viewport on which this director directs + * @param view The ZCanvas that the viewport looks at + */ + public void install(PViewport viewport, PCanvas view); - /** - * Uninstall the scroll director - */ - public void unInstall(); + /** + * Uninstall the scroll director + */ + public void unInstall(); - /** - * Get the View position given the specified camera bounds - * @param viewBounds The bounds for which the view position will be computed - * @return The view position - */ - public Point getViewPosition(Rectangle2D viewBounds); + /** + * Get the View position given the specified camera bounds + * + * @param viewBounds The bounds for which the view position will be computed + * @return The view position + */ + public Point getViewPosition(Rectangle2D viewBounds); + /** + * Set the view position + * + * @param x The new x position + * @param y The new y position + */ + public void setViewPosition(double x, double y); - /** - * Set the view position - * @param x The new x position - * @param y The new y position - */ - public void setViewPosition(double x, double y); - - /** - * Get the size of the view based on the specified camera bounds - * @param viewBounds The view bounds for which the view size will be computed - * @return The view size - */ - public Dimension getViewSize(Rectangle2D viewBounds); + /** + * Get the size of the view based on the specified camera bounds + * + * @param viewBounds The view bounds for which the view size will be + * computed + * @return The view size + */ + public Dimension getViewSize(Rectangle2D viewBounds); } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPane.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPane.java index a14ba50..a4b1579 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPane.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPane.java @@ -23,277 +23,279 @@ import javax.swing.plaf.ScrollPaneUI; /** - * A simple extension to a standard scroll pane that uses the jazz version - * of the viewport by default. Also uses the jazz version of ScrollPaneLayout - * + * A simple extension to a standard scroll pane that uses the jazz version of + * the viewport by default. Also uses the jazz version of ScrollPaneLayout + * * @author Lance Good */ public class PScrollPane extends JScrollPane { - // A reusable null action - protected PNullAction nullAction = null; + // A reusable null action + protected PNullAction nullAction = null; - // Are key actions disabled on this component? - protected boolean disableKeyActions = false; + // Are key actions disabled on this component? + protected boolean disableKeyActions = false; - /** - * Pass on the constructor info to the super - */ - public PScrollPane(Component view, int vsbPolicy, int hsbPolicy) { - super(view, vsbPolicy, hsbPolicy); + /** + * Pass on the constructor info to the super + */ + public PScrollPane(Component view, int vsbPolicy, int hsbPolicy) { + super(view, vsbPolicy, hsbPolicy); - // Set the layout and sync it with the scroll pane - PScrollPaneLayout layout = new PScrollPaneLayout.UIResource(); - setLayout(layout); - layout.syncWithScrollPane(this); - } + // Set the layout and sync it with the scroll pane + PScrollPaneLayout layout = new PScrollPaneLayout.UIResource(); + setLayout(layout); + layout.syncWithScrollPane(this); + } - /** - * Pass on the constructor info to the super - */ - public PScrollPane(Component view) { - this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); - } + /** + * Pass on the constructor info to the super + */ + public PScrollPane(Component view) { + this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); + } - /** - * Pass on the constructor info to the super - */ - public PScrollPane(int vsbPolicy, int hsbPolicy) { - this(null, vsbPolicy, hsbPolicy); - } + /** + * Pass on the constructor info to the super + */ + public PScrollPane(int vsbPolicy, int hsbPolicy) { + this(null, vsbPolicy, hsbPolicy); + } - /** - * Pass on the constructor info to the super - */ - public PScrollPane() { - this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); - } + /** + * Pass on the constructor info to the super + */ + public PScrollPane() { + this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); + } - /** - * Disable or enable key actions on this PScrollPane - * @param disable true disables key actions, false enables key actions - */ - public void setKeyActionsDisabled(boolean disable) { - if (disable && this.disableKeyActions != disable) { - this.disableKeyActions = disable; - disableKeyActions(); - } - else if (!disable && this.disableKeyActions != disable) { - this.disableKeyActions = disable; - installCustomKeyActions(); - } - } + /** + * Disable or enable key actions on this PScrollPane + * + * @param disable true disables key actions, false enables key actions + */ + public void setKeyActionsDisabled(boolean disable) { + if (disable && this.disableKeyActions != disable) { + this.disableKeyActions = disable; + disableKeyActions(); + } + else if (!disable && this.disableKeyActions != disable) { + this.disableKeyActions = disable; + installCustomKeyActions(); + } + } - /** - * Sets the UI - */ - public void setUI(ScrollPaneUI ui) { - super.setUI(ui); + /** + * Sets the UI + */ + public void setUI(ScrollPaneUI ui) { + super.setUI(ui); - if (!disableKeyActions) { - installCustomKeyActions(); - } - else { - disableKeyActions(); - } - } + if (!disableKeyActions) { + installCustomKeyActions(); + } + else { + disableKeyActions(); + } + } - /** - * Install custom key actions (in place of the Swing defaults) to - * correctly scroll the view - */ - protected void installCustomKeyActions() { - ActionMap map = getActionMap(); + /** + * Install custom key actions (in place of the Swing defaults) to correctly + * scroll the view + */ + protected void installCustomKeyActions() { + ActionMap map = getActionMap(); - map.put("scrollUp", new PScrollAction("scrollUp", SwingConstants.VERTICAL, -1, true)); - map.put("scrollDown", new PScrollAction("scrollDown", SwingConstants.VERTICAL, 1, true)); - map.put("scrollLeft", new PScrollAction("scrollLeft", SwingConstants.HORIZONTAL, -1, true)); + map.put("scrollUp", new PScrollAction("scrollUp", SwingConstants.VERTICAL, -1, true)); + map.put("scrollDown", new PScrollAction("scrollDown", SwingConstants.VERTICAL, 1, true)); + map.put("scrollLeft", new PScrollAction("scrollLeft", SwingConstants.HORIZONTAL, -1, true)); - map.put("scrollRight", new PScrollAction("ScrollRight", SwingConstants.HORIZONTAL, 1, true)); - map.put("unitScrollRight", new PScrollAction("UnitScrollRight", SwingConstants.HORIZONTAL, 1, false)); - map.put("unitScrollLeft", new PScrollAction("UnitScrollLeft", SwingConstants.HORIZONTAL, -1, false)); - map.put("unitScrollUp", new PScrollAction("UnitScrollUp", SwingConstants.VERTICAL, -1, false)); - map.put("unitScrollDown", new PScrollAction("UnitScrollDown", SwingConstants.VERTICAL, 1, false)); + map.put("scrollRight", new PScrollAction("ScrollRight", SwingConstants.HORIZONTAL, 1, true)); + map.put("unitScrollRight", new PScrollAction("UnitScrollRight", SwingConstants.HORIZONTAL, 1, false)); + map.put("unitScrollLeft", new PScrollAction("UnitScrollLeft", SwingConstants.HORIZONTAL, -1, false)); + map.put("unitScrollUp", new PScrollAction("UnitScrollUp", SwingConstants.VERTICAL, -1, false)); + map.put("unitScrollDown", new PScrollAction("UnitScrollDown", SwingConstants.VERTICAL, 1, false)); - map.put("scrollEnd", new PScrollEndAction("ScrollEnd")); - map.put("scrollHome", new PScrollHomeAction("ScrollHome")); - } + map.put("scrollEnd", new PScrollEndAction("ScrollEnd")); + map.put("scrollHome", new PScrollHomeAction("ScrollHome")); + } - /** - * Disables key actions on this PScrollPane - */ - protected void disableKeyActions() { - ActionMap map = getActionMap(); + /** + * Disables key actions on this PScrollPane + */ + protected void disableKeyActions() { + ActionMap map = getActionMap(); - if (nullAction == null) { - nullAction = new PNullAction(); - } + if (nullAction == null) { + nullAction = new PNullAction(); + } - map.put("scrollUp", nullAction); - map.put("scrollDown", nullAction); - map.put("scrollLeft", nullAction); - map.put("scrollRight", nullAction); - map.put("unitScrollRight", nullAction); - map.put("unitScrollLeft", nullAction); - map.put("unitScrollUp", nullAction); - map.put("unitScrollDown", nullAction); - map.put("scrollEnd", nullAction); - map.put("scrollHome", nullAction); - } + map.put("scrollUp", nullAction); + map.put("scrollDown", nullAction); + map.put("scrollLeft", nullAction); + map.put("scrollRight", nullAction); + map.put("unitScrollRight", nullAction); + map.put("unitScrollLeft", nullAction); + map.put("unitScrollUp", nullAction); + map.put("unitScrollDown", nullAction); + map.put("scrollEnd", nullAction); + map.put("scrollHome", nullAction); + } - /** - * Overridden to create the Jazz viewport - * @return The jazz version of the viewport - */ - protected JViewport createViewport() { - return new PViewport(); - } + /** + * Overridden to create the Jazz viewport + * + * @return The jazz version of the viewport + */ + protected JViewport createViewport() { + return new PViewport(); + } - /** - * Action to scroll left/right/up/down. - * Modified from javax.swing.plaf.basic.BasicScrollPaneUI.ScrollAction - * - * Gets the view parameters (position and size) from the Viewport - * rather than directly from the view - also only performs its actions - * when the relevant scrollbar is visible - */ - protected static class PScrollAction extends AbstractAction { - /** Direction to scroll. */ - protected int orientation; - /** 1 indicates scroll down, -1 up. */ - protected int direction; - /** True indicates a block scroll, otherwise a unit scroll. */ - private boolean block; + /** + * Action to scroll left/right/up/down. Modified from + * javax.swing.plaf.basic.BasicScrollPaneUI.ScrollAction + * + * Gets the view parameters (position and size) from the Viewport rather + * than directly from the view - also only performs its actions when the + * relevant scrollbar is visible + */ + protected static class PScrollAction extends AbstractAction { + /** Direction to scroll. */ + protected int orientation; + /** 1 indicates scroll down, -1 up. */ + protected int direction; + /** True indicates a block scroll, otherwise a unit scroll. */ + private boolean block; - protected PScrollAction(String name, int orientation, int direction, boolean block) { - super(name); - this.orientation = orientation; - this.direction = direction; - this.block = block; - } + protected PScrollAction(String name, int orientation, int direction, boolean block) { + super(name); + this.orientation = orientation; + this.direction = direction; + this.block = block; + } - public void actionPerformed(ActionEvent e) { - JScrollPane scrollpane = (JScrollPane) e.getSource(); - // LEG: Modification to only perform these actions if the relevant - // scrollbar is actually showing - if ((orientation == SwingConstants.VERTICAL && scrollpane.getVerticalScrollBar().isShowing()) - || (orientation == SwingConstants.HORIZONTAL && scrollpane.getHorizontalScrollBar().isShowing())) { + public void actionPerformed(ActionEvent e) { + JScrollPane scrollpane = (JScrollPane) e.getSource(); + // LEG: Modification to only perform these actions if the relevant + // scrollbar is actually showing + if ((orientation == SwingConstants.VERTICAL && scrollpane.getVerticalScrollBar().isShowing()) + || (orientation == SwingConstants.HORIZONTAL && scrollpane.getHorizontalScrollBar().isShowing())) { - JViewport vp = scrollpane.getViewport(); - Component view; - if (vp != null && (view = vp.getView()) != null) { - Rectangle visRect = vp.getViewRect(); - // LEG: Modification to query the viewport for the - // view size rather than going directly to the view - Dimension vSize = vp.getViewSize(); - int amount; + JViewport vp = scrollpane.getViewport(); + Component view; + if (vp != null && (view = vp.getView()) != null) { + Rectangle visRect = vp.getViewRect(); + // LEG: Modification to query the viewport for the + // view size rather than going directly to the view + Dimension vSize = vp.getViewSize(); + int amount; - if (view instanceof Scrollable) { - if (block) { - amount = ((Scrollable) view).getScrollableBlockIncrement(visRect, orientation, direction); - } - else { - amount = ((Scrollable) view).getScrollableUnitIncrement(visRect, orientation, direction); - } - } - else { - if (block) { - if (orientation == SwingConstants.VERTICAL) { - amount = visRect.height; - } - else { - amount = visRect.width; - } - } - else { - amount = 10; - } - } - if (orientation == SwingConstants.VERTICAL) { - visRect.y += (amount * direction); - if ((visRect.y + visRect.height) > vSize.height) { - visRect.y = Math.max(0, vSize.height - visRect.height); - } - else if (visRect.y < 0) { - visRect.y = 0; - } - } - else { - visRect.x += (amount * direction); - if ((visRect.x + visRect.width) > vSize.width) { - visRect.x = Math.max(0, vSize.width - visRect.width); - } - else if (visRect.x < 0) { - visRect.x = 0; - } - } - vp.setViewPosition(visRect.getLocation()); - } - } - } - } + if (view instanceof Scrollable) { + if (block) { + amount = ((Scrollable) view).getScrollableBlockIncrement(visRect, orientation, direction); + } + else { + amount = ((Scrollable) view).getScrollableUnitIncrement(visRect, orientation, direction); + } + } + else { + if (block) { + if (orientation == SwingConstants.VERTICAL) { + amount = visRect.height; + } + else { + amount = visRect.width; + } + } + else { + amount = 10; + } + } + if (orientation == SwingConstants.VERTICAL) { + visRect.y += (amount * direction); + if ((visRect.y + visRect.height) > vSize.height) { + visRect.y = Math.max(0, vSize.height - visRect.height); + } + else if (visRect.y < 0) { + visRect.y = 0; + } + } + else { + visRect.x += (amount * direction); + if ((visRect.x + visRect.width) > vSize.width) { + visRect.x = Math.max(0, vSize.width - visRect.width); + } + else if (visRect.x < 0) { + visRect.x = 0; + } + } + vp.setViewPosition(visRect.getLocation()); + } + } + } + } - /** - * Action to scroll to x,y location of 0,0. - * Modified from javax.swing.plaf.basic.BasicScrollPaneUI.ScrollEndAction - * - * Only performs the event if a scrollbar is visible - */ - private static class PScrollHomeAction extends AbstractAction { - protected PScrollHomeAction(String name) { - super(name); - } + /** + * Action to scroll to x,y location of 0,0. Modified from + * javax.swing.plaf.basic.BasicScrollPaneUI.ScrollEndAction + * + * Only performs the event if a scrollbar is visible + */ + private static class PScrollHomeAction extends AbstractAction { + protected PScrollHomeAction(String name) { + super(name); + } - public void actionPerformed(ActionEvent e) { - JScrollPane scrollpane = (JScrollPane) e.getSource(); - // LEG: Modification to only perform these actions if one of the - // scrollbars is actually showing - if (scrollpane.getVerticalScrollBar().isShowing() || scrollpane.getHorizontalScrollBar().isShowing()) { - JViewport vp = scrollpane.getViewport(); - if (vp != null && vp.getView() != null) { - vp.setViewPosition(new Point(0, 0)); - } - } - } - } + public void actionPerformed(ActionEvent e) { + JScrollPane scrollpane = (JScrollPane) e.getSource(); + // LEG: Modification to only perform these actions if one of the + // scrollbars is actually showing + if (scrollpane.getVerticalScrollBar().isShowing() || scrollpane.getHorizontalScrollBar().isShowing()) { + JViewport vp = scrollpane.getViewport(); + if (vp != null && vp.getView() != null) { + vp.setViewPosition(new Point(0, 0)); + } + } + } + } - /** - * Action to scroll to last visible location. - * Modified from javax.swing.plaf.basic.BasicScrollPaneUI.ScrollEndAction - * - * Gets the view size from the viewport rather than directly from the view - * - also only performs the event if a scrollbar is visible - */ - protected static class PScrollEndAction extends AbstractAction { - protected PScrollEndAction(String name) { - super(name); - } + /** + * Action to scroll to last visible location. Modified from + * javax.swing.plaf.basic.BasicScrollPaneUI.ScrollEndAction + * + * Gets the view size from the viewport rather than directly from the view - + * also only performs the event if a scrollbar is visible + */ + protected static class PScrollEndAction extends AbstractAction { + protected PScrollEndAction(String name) { + super(name); + } - public void actionPerformed(ActionEvent e) { - JScrollPane scrollpane = (JScrollPane) e.getSource(); - // LEG: Modification to only perform these actions if one of the - // scrollbars is actually showing - if (scrollpane.getVerticalScrollBar().isShowing() || scrollpane.getHorizontalScrollBar().isShowing()) { + public void actionPerformed(ActionEvent e) { + JScrollPane scrollpane = (JScrollPane) e.getSource(); + // LEG: Modification to only perform these actions if one of the + // scrollbars is actually showing + if (scrollpane.getVerticalScrollBar().isShowing() || scrollpane.getHorizontalScrollBar().isShowing()) { - JViewport vp = scrollpane.getViewport(); - if (vp != null && vp.getView() != null) { + JViewport vp = scrollpane.getViewport(); + if (vp != null && vp.getView() != null) { - Rectangle visRect = vp.getViewRect(); - // LEG: Modification to query the viewport for the - // view size rather than going directly to the view - Dimension size = vp.getViewSize(); - vp.setViewPosition(new Point(size.width - visRect.width, size.height - visRect.height)); - } - } - } - } + Rectangle visRect = vp.getViewRect(); + // LEG: Modification to query the viewport for the + // view size rather than going directly to the view + Dimension size = vp.getViewSize(); + vp.setViewPosition(new Point(size.width - visRect.width, size.height - visRect.height)); + } + } + } + } - /** - * An action to do nothing - put into an action map to keep it - * from looking to its parent - */ - protected static class PNullAction extends AbstractAction { - public void actionPerformed(ActionEvent e) { - } - } + /** + * An action to do nothing - put into an action map to keep it from looking + * to its parent + */ + protected static class PNullAction extends AbstractAction { + public void actionPerformed(ActionEvent e) { + } + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java index 346add8..f513f73 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PScrollPaneLayout.java @@ -21,309 +21,314 @@ /** * A subclass of ScrollPaneLayout that looks at the Viewport for sizing - * information rather than View. Also queries the Viewport for sizing + * information rather than View. Also queries the Viewport for sizing * information after each decision about scrollbar visiblity - * + * * @author Lance Good */ public class PScrollPaneLayout extends ScrollPaneLayout { - /** - * MODIFIED FROM javax.swing.ScrollPaneLayout.layoutContainer - * - * This is largely the same as ScrollPaneLayout.layoutContainer but - * obtains the preferred view size from the viewport rather than directly - * from the view so the viewport can get the preferred size from the - * PScrollDirector - * @param parent the Container to lay out - */ - public void layoutContainer(Container parent) { - /* Sync the (now obsolete) policy fields with the - * JScrollPane. - */ - JScrollPane scrollPane = (JScrollPane) parent; - vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); - hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); + /** + * MODIFIED FROM javax.swing.ScrollPaneLayout.layoutContainer + * + * This is largely the same as ScrollPaneLayout.layoutContainer but obtains + * the preferred view size from the viewport rather than directly from the + * view so the viewport can get the preferred size from the PScrollDirector + * + * @param parent the Container to lay out + */ + public void layoutContainer(Container parent) { + /* + * Sync the (now obsolete) policy fields with the JScrollPane. + */ + JScrollPane scrollPane = (JScrollPane) parent; + vsbPolicy = scrollPane.getVerticalScrollBarPolicy(); + hsbPolicy = scrollPane.getHorizontalScrollBarPolicy(); - Rectangle availR = scrollPane.getBounds(); - availR.x = availR.y = 0; + Rectangle availR = scrollPane.getBounds(); + availR.x = availR.y = 0; - Insets insets = parent.getInsets(); - availR.x = insets.left; - availR.y = insets.top; - availR.width -= insets.left + insets.right; - availR.height -= insets.top + insets.bottom; + Insets insets = parent.getInsets(); + availR.x = insets.left; + availR.y = insets.top; + availR.width -= insets.left + insets.right; + availR.height -= insets.top + insets.bottom; - /* Get the scrollPane's orientation. - */ - boolean leftToRight = scrollPane.getComponentOrientation().isLeftToRight(); + /* + * Get the scrollPane's orientation. + */ + boolean leftToRight = scrollPane.getComponentOrientation().isLeftToRight(); - /* If there's a visible column header remove the space it - * needs from the top of availR. The column header is treated - * as if it were fixed height, arbitrary width. - */ + /* + * If there's a visible column header remove the space it needs from the + * top of availR. The column header is treated as if it were fixed + * height, arbitrary width. + */ + Rectangle colHeadR = new Rectangle(0, availR.y, 0, 0); - Rectangle colHeadR = new Rectangle(0, availR.y, 0, 0); + if ((colHead != null) && (colHead.isVisible())) { + int colHeadHeight = colHead.getPreferredSize().height; + colHeadR.height = colHeadHeight; + availR.y += colHeadHeight; + availR.height -= colHeadHeight; + } - if ((colHead != null) && (colHead.isVisible())) { - int colHeadHeight = colHead.getPreferredSize().height; - colHeadR.height = colHeadHeight; - availR.y += colHeadHeight; - availR.height -= colHeadHeight; - } + /* + * If there's a visible row header remove the space it needs from the + * left or right of availR. The row header is treated as if it were + * fixed width, arbitrary height. + */ + Rectangle rowHeadR = new Rectangle(0, 0, 0, 0); - /* If there's a visible row header remove the space it needs - * from the left or right of availR. The row header is treated - * as if it were fixed width, arbitrary height. - */ + if ((rowHead != null) && (rowHead.isVisible())) { + int rowHeadWidth = rowHead.getPreferredSize().width; + rowHeadR.width = rowHeadWidth; + availR.width -= rowHeadWidth; + if (leftToRight) { + rowHeadR.x = availR.x; + availR.x += rowHeadWidth; + } + else { + rowHeadR.x = availR.x + availR.width; + } + } - Rectangle rowHeadR = new Rectangle(0, 0, 0, 0); + /* + * If there's a JScrollPane.viewportBorder, remove the space it occupies + * for availR. + */ + Border viewportBorder = scrollPane.getViewportBorder(); + Insets vpbInsets; + if (viewportBorder != null) { + vpbInsets = viewportBorder.getBorderInsets(parent); + availR.x += vpbInsets.left; + availR.y += vpbInsets.top; + availR.width -= vpbInsets.left + vpbInsets.right; + availR.height -= vpbInsets.top + vpbInsets.bottom; + } + else { + vpbInsets = new Insets(0, 0, 0, 0); + } - if ((rowHead != null) && (rowHead.isVisible())) { - int rowHeadWidth = rowHead.getPreferredSize().width; - rowHeadR.width = rowHeadWidth; - availR.width -= rowHeadWidth; - if (leftToRight) { - rowHeadR.x = availR.x; - availR.x += rowHeadWidth; - } - else { - rowHeadR.x = availR.x + availR.width; - } - } + /* + * At this point availR is the space available for the viewport and + * scrollbars. rowHeadR is correct except for its height and y and + * colHeadR is correct except for its width and x. Once we're through + * computing the dimensions of these three parts we can go back and set + * the dimensions of rowHeadR.height, rowHeadR.y, colHeadR.width, + * colHeadR.x and the bounds for the corners. + * + * We'll decide about putting up scrollbars by comparing the viewport + * views preferred size with the viewports extent size (generally just + * its size). Using the preferredSize is reasonable because layout + * proceeds top down - so we expect the viewport to be layed out next. + * And we assume that the viewports layout manager will give the view + * it's preferred size. + */ + Dimension extentSize = (viewport != null) ? viewport.toViewCoordinates(availR.getSize()) : new Dimension(0, 0); - /* If there's a JScrollPane.viewportBorder, remove the - * space it occupies for availR. - */ + PBounds cameraBounds = new PBounds(0, 0, extentSize.getWidth(), extentSize.getHeight()); - Border viewportBorder = scrollPane.getViewportBorder(); - Insets vpbInsets; - if (viewportBorder != null) { - vpbInsets = viewportBorder.getBorderInsets(parent); - availR.x += vpbInsets.left; - availR.y += vpbInsets.top; - availR.width -= vpbInsets.left + vpbInsets.right; - availR.height -= vpbInsets.top + vpbInsets.bottom; - } - else { - vpbInsets = new Insets(0, 0, 0, 0); - } + // LEG: Modification to ask the viewport for the view size rather + // than asking the view directly + Dimension viewPrefSize = (viewport != null) ? ((PViewport) viewport).getViewSize(cameraBounds) : new Dimension( + 0, 0); - /* At this point availR is the space available for the viewport - * and scrollbars. rowHeadR is correct except for its height and y - * and colHeadR is correct except for its width and x. Once we're - * through computing the dimensions of these three parts we can - * go back and set the dimensions of rowHeadR.height, rowHeadR.y, - * colHeadR.width, colHeadR.x and the bounds for the corners. - * - * We'll decide about putting up scrollbars by comparing the - * viewport views preferred size with the viewports extent - * size (generally just its size). Using the preferredSize is - * reasonable because layout proceeds top down - so we expect - * the viewport to be layed out next. And we assume that the - * viewports layout manager will give the view it's preferred - * size. - */ + /* + * If there's a vertical scrollbar and we need one, allocate space for + * it (we'll make it visible later). A vertical scrollbar is considered + * to be fixed width, arbitrary height. + */ + Rectangle vsbR = new Rectangle(0, availR.y - vpbInsets.top, 0, 0); - Dimension extentSize = (viewport != null) ? viewport.toViewCoordinates(availR.getSize()) : new Dimension(0, 0); + boolean vsbNeeded; + if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) { + vsbNeeded = true; + } + else if (vsbPolicy == VERTICAL_SCROLLBAR_NEVER) { + vsbNeeded = false; + } + else { // vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED - PBounds cameraBounds = new PBounds(0, 0, extentSize.getWidth(), extentSize.getHeight()); + vsbNeeded = (viewPrefSize.height > extentSize.height); + } - // LEG: Modification to ask the viewport for the view size rather - // than asking the view directly - Dimension viewPrefSize = (viewport != null) ? ((PViewport) viewport).getViewSize(cameraBounds) : new Dimension(0, 0); + if ((vsb != null) && vsbNeeded) { + adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight); + extentSize = viewport.toViewCoordinates(availR.getSize()); - /* If there's a vertical scrollbar and we need one, allocate - * space for it (we'll make it visible later). A vertical - * scrollbar is considered to be fixed width, arbitrary height. - */ + // LEG: Modification because the view's preferred size needs to + // be recomputed because the extent may have changed + cameraBounds.setRect(0, 0, extentSize.getWidth(), extentSize.getHeight()); + viewPrefSize = ((PViewport) viewport).getViewSize(cameraBounds); + } - Rectangle vsbR = new Rectangle(0, availR.y - vpbInsets.top, 0, 0); + /* + * If there's a horizontal scrollbar and we need one, allocate space for + * it (we'll make it visible later). A horizontal scrollbar is + * considered to be fixed height, arbitrary width. + */ + Rectangle hsbR = new Rectangle(availR.x - vpbInsets.left, 0, 0, 0); + boolean hsbNeeded; + if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) { + hsbNeeded = true; + } + else if (hsbPolicy == HORIZONTAL_SCROLLBAR_NEVER) { + hsbNeeded = false; + } + else { // hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED + hsbNeeded = (viewPrefSize.width > extentSize.width); + } - boolean vsbNeeded; - if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) { - vsbNeeded = true; - } - else if (vsbPolicy == VERTICAL_SCROLLBAR_NEVER) { - vsbNeeded = false; - } - else { // vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED + if ((hsb != null) && hsbNeeded) { + adjustForHSB(true, availR, hsbR, vpbInsets); - vsbNeeded = (viewPrefSize.height > extentSize.height); - } + /* + * If we added the horizontal scrollbar then we've implicitly + * reduced the vertical space available to the viewport. As a + * consequence we may have to add the vertical scrollbar, if that + * hasn't been done so already. Ofcourse we don't bother with any of + * this if the vsbPolicy is NEVER. + */ + if ((vsb != null) && !vsbNeeded && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) { - if ((vsb != null) && vsbNeeded) { - adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight); - extentSize = viewport.toViewCoordinates(availR.getSize()); + extentSize = viewport.toViewCoordinates(availR.getSize()); - // LEG: Modification because the view's preferred size needs to - // be recomputed because the extent may have changed - cameraBounds.setRect(0, 0, extentSize.getWidth(), extentSize.getHeight()); - viewPrefSize = ((PViewport) viewport).getViewSize(cameraBounds); - } + // LEG: Modification because the view's preferred size needs to + // be recomputed because the extent may have changed + cameraBounds.setRect(0, 0, extentSize.getWidth(), extentSize.getHeight()); + viewPrefSize = ((PViewport) viewport).getViewSize(cameraBounds); - /* If there's a horizontal scrollbar and we need one, allocate - * space for it (we'll make it visible later). A horizontal - * scrollbar is considered to be fixed height, arbitrary width. - */ + vsbNeeded = viewPrefSize.height > extentSize.height; - Rectangle hsbR = new Rectangle(availR.x - vpbInsets.left, 0, 0, 0); - boolean hsbNeeded; - if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) { - hsbNeeded = true; - } - else if (hsbPolicy == HORIZONTAL_SCROLLBAR_NEVER) { - hsbNeeded = false; - } - else { // hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED - hsbNeeded = (viewPrefSize.width > extentSize.width); - } + if (vsbNeeded) { + adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight); + } + } + } - if ((hsb != null) && hsbNeeded) { - adjustForHSB(true, availR, hsbR, vpbInsets); + /* + * Set the size of the viewport first, and then recheck the Scrollable + * methods. Some components base their return values for the Scrollable + * methods on the size of the Viewport, so that if we don't ask after + * resetting the bounds we may have gotten the wrong answer. + */ + if (viewport != null) { + viewport.setBounds(availR); + } - /* If we added the horizontal scrollbar then we've implicitly - * reduced the vertical space available to the viewport. - * As a consequence we may have to add the vertical scrollbar, - * if that hasn't been done so already. Ofcourse we - * don't bother with any of this if the vsbPolicy is NEVER. - */ + /* + * We now have the final size of the viewport: availR. Now fixup the + * header and scrollbar widths/heights. + */ + vsbR.height = availR.height + vpbInsets.top + vpbInsets.bottom; + hsbR.width = availR.width + vpbInsets.left + vpbInsets.right; + rowHeadR.height = availR.height + vpbInsets.top + vpbInsets.bottom; + rowHeadR.y = availR.y - vpbInsets.top; + colHeadR.width = availR.width + vpbInsets.left + vpbInsets.right; + colHeadR.x = availR.x - vpbInsets.left; - if ((vsb != null) && !vsbNeeded && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) { + /* + * Set the bounds of the remaining components. The scrollbars are made + * invisible if they're not needed. + */ + if (rowHead != null) { + rowHead.setBounds(rowHeadR); + } - extentSize = viewport.toViewCoordinates(availR.getSize()); + if (colHead != null) { + colHead.setBounds(colHeadR); + } - // LEG: Modification because the view's preferred size needs to - // be recomputed because the extent may have changed - cameraBounds.setRect(0, 0, extentSize.getWidth(), extentSize.getHeight()); - viewPrefSize = ((PViewport) viewport).getViewSize(cameraBounds); + if (vsb != null) { + if (vsbNeeded) { + vsb.setVisible(true); + vsb.setBounds(vsbR); + } + else { + vsb.setVisible(false); + } + } - vsbNeeded = viewPrefSize.height > extentSize.height; + if (hsb != null) { + if (hsbNeeded) { + hsb.setVisible(true); + hsb.setBounds(hsbR); + } + else { + hsb.setVisible(false); + } + } - if (vsbNeeded) { - adjustForVSB(true, availR, vsbR, vpbInsets, leftToRight); - } - } - } + if (lowerLeft != null) { + lowerLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x, hsbR.y, leftToRight ? rowHeadR.width : vsbR.width, + hsbR.height); + } - /* Set the size of the viewport first, and then recheck the Scrollable - * methods. Some components base their return values for the Scrollable - * methods on the size of the Viewport, so that if we don't - * ask after resetting the bounds we may have gotten the wrong - * answer. - */ + if (lowerRight != null) { + lowerRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x, hsbR.y, leftToRight ? vsbR.width : rowHeadR.width, + hsbR.height); + } - if (viewport != null) { - viewport.setBounds(availR); - } + if (upperLeft != null) { + upperLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x, colHeadR.y, leftToRight ? rowHeadR.width + : vsbR.width, colHeadR.height); + } - /* We now have the final size of the viewport: availR. - * Now fixup the header and scrollbar widths/heights. - */ - vsbR.height = availR.height + vpbInsets.top + vpbInsets.bottom; - hsbR.width = availR.width + vpbInsets.left + vpbInsets.right; - rowHeadR.height = availR.height + vpbInsets.top + vpbInsets.bottom; - rowHeadR.y = availR.y - vpbInsets.top; - colHeadR.width = availR.width + vpbInsets.left + vpbInsets.right; - colHeadR.x = availR.x - vpbInsets.left; + if (upperRight != null) { + upperRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x, colHeadR.y, leftToRight ? vsbR.width + : rowHeadR.width, colHeadR.height); + } + } - /* Set the bounds of the remaining components. The scrollbars - * are made invisible if they're not needed. - */ + /** + * Copied FROM javax.swing.ScrollPaneLayout.adjustForVSB + * + * This method is called from ScrollPaneLayout.layoutContainer and is + * private in ScrollPaneLayout so it was copied here + */ + protected void adjustForVSB(boolean wantsVSB, Rectangle available, Rectangle vsbR, Insets vpbInsets, + boolean leftToRight) { + int vsbWidth = vsb.getPreferredSize().width; + if (wantsVSB) { + available.width -= vsbWidth; + vsbR.width = vsbWidth; - if (rowHead != null) { - rowHead.setBounds(rowHeadR); - } + if (leftToRight) { + vsbR.x = available.x + available.width + vpbInsets.right; + } + else { + vsbR.x = available.x - vpbInsets.left; + available.x += vsbWidth; + } + } + else { + available.width += vsbWidth; + } + } - if (colHead != null) { - colHead.setBounds(colHeadR); - } + /** + * Copied FROM javax.swing.ScrollPaneLayout.adjustForHSB + * + * This method is called from ScrollPaneLayout.layoutContainer and is + * private in ScrollPaneLayout so it was copied here + */ + protected void adjustForHSB(boolean wantsHSB, Rectangle available, Rectangle hsbR, Insets vpbInsets) { + int hsbHeight = hsb.getPreferredSize().height; + if (wantsHSB) { + available.height -= hsbHeight; + hsbR.y = available.y + available.height + vpbInsets.bottom; + hsbR.height = hsbHeight; + } + else { + available.height += hsbHeight; + } + } - if (vsb != null) { - if (vsbNeeded) { - vsb.setVisible(true); - vsb.setBounds(vsbR); - } - else { - vsb.setVisible(false); - } - } - - if (hsb != null) { - if (hsbNeeded) { - hsb.setVisible(true); - hsb.setBounds(hsbR); - } - else { - hsb.setVisible(false); - } - } - - if (lowerLeft != null) { - lowerLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x, hsbR.y, leftToRight ? rowHeadR.width : vsbR.width, hsbR.height); - } - - if (lowerRight != null) { - lowerRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x, hsbR.y, leftToRight ? vsbR.width : rowHeadR.width, hsbR.height); - } - - if (upperLeft != null) { - upperLeft.setBounds(leftToRight ? rowHeadR.x : vsbR.x, colHeadR.y, leftToRight ? rowHeadR.width : vsbR.width, colHeadR.height); - } - - if (upperRight != null) { - upperRight.setBounds(leftToRight ? vsbR.x : rowHeadR.x, colHeadR.y, leftToRight ? vsbR.width : rowHeadR.width, colHeadR.height); - } - } - - /** - * Copied FROM javax.swing.ScrollPaneLayout.adjustForVSB - * - * This method is called from ScrollPaneLayout.layoutContainer and is - * private in ScrollPaneLayout so it was copied here - */ - protected void adjustForVSB(boolean wantsVSB, Rectangle available, Rectangle vsbR, Insets vpbInsets, boolean leftToRight) { - int vsbWidth = vsb.getPreferredSize().width; - if (wantsVSB) { - available.width -= vsbWidth; - vsbR.width = vsbWidth; - - if (leftToRight) { - vsbR.x = available.x + available.width + vpbInsets.right; - } - else { - vsbR.x = available.x - vpbInsets.left; - available.x += vsbWidth; - } - } - else { - available.width += vsbWidth; - } - } - - /** - * Copied FROM javax.swing.ScrollPaneLayout.adjustForHSB - * - * This method is called from ScrollPaneLayout.layoutContainer and is - * private in ScrollPaneLayout so it was copied here - */ - protected void adjustForHSB(boolean wantsHSB, Rectangle available, Rectangle hsbR, Insets vpbInsets) { - int hsbHeight = hsb.getPreferredSize().height; - if (wantsHSB) { - available.height -= hsbHeight; - hsbR.y = available.y + available.height + vpbInsets.bottom; - hsbR.height = hsbHeight; - } - else { - available.height += hsbHeight; - } - } - - /** - * The UI resource version of PScrollPaneLayout. It isn't clear why - * Swing does this in ScrollPaneLayout but we'll do it here too just - * to be safe. - */ - public static class UIResource extends PScrollPaneLayout implements javax.swing.plaf.UIResource { - } + /** + * The UI resource version of PScrollPaneLayout. It isn't clear why Swing + * does this in ScrollPaneLayout but we'll do it here too just to be safe. + */ + public static class UIResource extends PScrollPaneLayout implements javax.swing.plaf.UIResource { + } } diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java b/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java index 0a735e8..d28469c 100644 --- a/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java +++ b/extras/src/main/java/edu/umd/cs/piccolox/swing/PViewport.java @@ -16,184 +16,188 @@ import edu.umd.cs.piccolo.util.PBounds; /** - * A subclass of JViewport that talks to the scroll director to negotiate - * the view positions and sizes. - * + * A subclass of JViewport that talks to the scroll director to negotiate the + * view positions and sizes. + * * @author Lance Good */ public class PViewport extends JViewport { - /** - * Controls what happens when scrolling occurs - */ - PScrollDirector scrollDirector; + /** + * Controls what happens when scrolling occurs + */ + PScrollDirector scrollDirector; - /** - * Pass constructor info to super - */ - public PViewport() { - super(); + /** + * Pass constructor info to super + */ + public PViewport() { + super(); - setScrollDirector(createScrollDirector()); - } + setScrollDirector(createScrollDirector()); + } - /** - * Subclassers can override this to install a different - * layout manager (ornull
) in the constructor. Returns
- * a new ViewportLayout
object.
- *
- * @return a LayoutManager
- */
- protected LayoutManager createLayoutManager() {
- return new PViewportLayout();
- }
+ /**
+ * Subclassers can override this to install a different layout manager (or
+ * null
) in the constructor. Returns a new
+ * ViewportLayout
object.
+ *
+ * @return a LayoutManager
+ */
+ protected LayoutManager createLayoutManager() {
+ return new PViewportLayout();
+ }
- /**
- * Subclassers can override this to install a different scroll director
- * in the constructor. Returns a new PScrollDirector
object.
- * @return a PScrollDirector
- */
- protected PScrollDirector createScrollDirector() {
- return new PDefaultScrollDirector();
- }
+ /**
+ * Subclassers can override this to install a different scroll director in
+ * the constructor. Returns a new PScrollDirector
object.
+ *
+ * @return a PScrollDirector
+ */
+ protected PScrollDirector createScrollDirector() {
+ return new PDefaultScrollDirector();
+ }
- /**
- * Set the scroll director on this viewport
- * @param scrollDirector The new scroll director
- */
- public void setScrollDirector(PScrollDirector scrollDirector) {
- if (this.scrollDirector != null) {
- this.scrollDirector.unInstall();
- }
- this.scrollDirector = scrollDirector;
- if (scrollDirector != null) {
- this.scrollDirector.install(this, (PCanvas) getView());
- }
- }
+ /**
+ * Set the scroll director on this viewport
+ *
+ * @param scrollDirector The new scroll director
+ */
+ public void setScrollDirector(PScrollDirector scrollDirector) {
+ if (this.scrollDirector != null) {
+ this.scrollDirector.unInstall();
+ }
+ this.scrollDirector = scrollDirector;
+ if (scrollDirector != null) {
+ this.scrollDirector.install(this, (PCanvas) getView());
+ }
+ }
- /**
- * @return The scroll director on this viewport
- */
- public PScrollDirector getScrollDirector() {
- return scrollDirector;
- }
+ /**
+ * @return The scroll director on this viewport
+ */
+ public PScrollDirector getScrollDirector() {
+ return scrollDirector;
+ }
- /**
- * Overridden to throw an exception if the view is not a ZCanvas
- * @param view The new view - it better be a ZCanvas!
- */
- public void setView(Component view) {
- if (!(view instanceof PCanvas)) {
- throw new UnsupportedOperationException("PViewport only supports ZCanvas");
- }
+ /**
+ * Overridden to throw an exception if the view is not a ZCanvas
+ *
+ * @param view The new view - it better be a ZCanvas!
+ */
+ public void setView(Component view) {
+ if (!(view instanceof PCanvas)) {
+ throw new UnsupportedOperationException("PViewport only supports ZCanvas");
+ }
- super.setView(view);
+ super.setView(view);
- if (scrollDirector != null) {
- scrollDirector.install(this, (PCanvas) view);
- }
- }
+ if (scrollDirector != null) {
+ scrollDirector.install(this, (PCanvas) view);
+ }
+ }
- /**
- * Sets the view coordinates that appear in the upper left
- * hand corner of the viewport, does nothing if there's no view.
- *
- * @param p a Point
object giving the upper left coordinates
- */
- public void setViewPosition(Point p) {
- if (getView() == null) {
- return;
- }
+ /**
+ * Sets the view coordinates that appear in the upper left hand corner of
+ * the viewport, does nothing if there's no view.
+ *
+ * @param p a Point
object giving the upper left coordinates
+ */
+ public void setViewPosition(Point p) {
+ if (getView() == null) {
+ return;
+ }
- double oldX = 0, oldY = 0, x = p.x, y = p.y;
+ double oldX = 0, oldY = 0, x = p.x, y = p.y;
- Point2D vp = getViewPosition();
- if (vp != null) {
- oldX = vp.getX();
- oldY = vp.getY();
- }
+ Point2D vp = getViewPosition();
+ if (vp != null) {
+ oldX = vp.getX();
+ oldY = vp.getY();
+ }
- /**
- * Send the scroll director the exact view position and let it
- * interpret it as needed
- */
- double newX = x;
- double newY = y;
+ /**
+ * Send the scroll director the exact view position and let it interpret
+ * it as needed
+ */
+ double newX = x;
+ double newY = y;
- if ((oldX != newX) || (oldY != newY)) {
- scrollUnderway = true;
+ if ((oldX != newX) || (oldY != newY)) {
+ scrollUnderway = true;
- scrollDirector.setViewPosition(newX, newY);
+ scrollDirector.setViewPosition(newX, newY);
- fireStateChanged();
- }
- }
+ fireStateChanged();
+ }
+ }
- /**
- * Gets the view position from the scroll director based on the current
- * extent size
- * @return The new view position
- */
- public Point getViewPosition() {
- if (scrollDirector != null) {
- Dimension extent = getExtentSize();
- return scrollDirector.getViewPosition(new PBounds(0, 0, extent.getWidth(), extent.getHeight()));
- }
- else {
- return null;
- }
- }
+ /**
+ * Gets the view position from the scroll director based on the current
+ * extent size
+ *
+ * @return The new view position
+ */
+ public Point getViewPosition() {
+ if (scrollDirector != null) {
+ Dimension extent = getExtentSize();
+ return scrollDirector.getViewPosition(new PBounds(0, 0, extent.getWidth(), extent.getHeight()));
+ }
+ else {
+ return null;
+ }
+ }
- /**
- * Gets the view size from the scroll director based on the current
- * extent size
- * @return The new view size
- */
- public Dimension getViewSize() {
- Dimension extent = getExtentSize();
- return scrollDirector.getViewSize(new PBounds(0, 0, extent.getWidth(), extent.getHeight()));
- }
+ /**
+ * Gets the view size from the scroll director based on the current extent
+ * size
+ *
+ * @return The new view size
+ */
+ public Dimension getViewSize() {
+ Dimension extent = getExtentSize();
+ return scrollDirector.getViewSize(new PBounds(0, 0, extent.getWidth(), extent.getHeight()));
+ }
- /**
- * Gets the view size from the scroll director based on the specified
- * extent size
- * @param r The extent size from which the view is computed
- * @return The new view size
- */
- public Dimension getViewSize(Rectangle2D r) {
- return scrollDirector.getViewSize(r);
- }
+ /**
+ * Gets the view size from the scroll director based on the specified extent
+ * size
+ *
+ * @param r The extent size from which the view is computed
+ * @return The new view size
+ */
+ public Dimension getViewSize(Rectangle2D r) {
+ return scrollDirector.getViewSize(r);
+ }
- /**
- * Notifies all ChangeListeners
when the views
- * size, position, or the viewports extent size has changed.
- */
- public void fireStateChanged() {
- super.fireStateChanged();
- }
+ /**
+ * Notifies all ChangeListeners
when the views size, position,
+ * or the viewports extent size has changed.
+ */
+ public void fireStateChanged() {
+ super.fireStateChanged();
+ }
- /**
- * A simple layout manager to give the ZCanvas the same size as the
- * Viewport
- */
- public static class PViewportLayout extends ViewportLayout {
- /**
- * Called when the specified container needs to be laid out.
- *
- * @param parent the container to lay out
- */
- public void layoutContainer(Container parent) {
- JViewport vp = (JViewport) parent;
- Component view = vp.getView();
+ /**
+ * A simple layout manager to give the ZCanvas the same size as the Viewport
+ */
+ public static class PViewportLayout extends ViewportLayout {
+ /**
+ * Called when the specified container needs to be laid out.
+ *
+ * @param parent the container to lay out
+ */
+ public void layoutContainer(Container parent) {
+ JViewport vp = (JViewport) parent;
+ Component view = vp.getView();
- if (view == null) {
- return;
- }
+ if (view == null) {
+ return;
+ }
- Dimension extentSize = vp.getSize();
+ Dimension extentSize = vp.getSize();
- vp.setViewSize(extentSize);
- }
-
- }
+ vp.setViewSize(extentSize);
+ }
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTBoundsHandle.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTBoundsHandle.java
index a901e31..fb074cd 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTBoundsHandle.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTBoundsHandle.java
@@ -48,296 +48,308 @@
/**
* PBoundsHandle a handle for resizing the bounds of another node. If a
* bounds handle is dragged such that the other node's width or height becomes
- * negative then the each drag handle's locator assciated with that
- * other node is "flipped" so that they are attached to and dragging a different
- * corner of the nodes bounds.
+ * negative then the each drag handle's locator assciated with that other node
+ * is "flipped" so that they are attached to and dragging a different corner of
+ * the nodes bounds.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PSWTBoundsHandle extends PSWTHandle {
-
- private PBasicInputEventHandler handleCursorHandler;
-
- public static void addBoundsHandlesTo(PNode aNode) {
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createEastLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createWestLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode)));
- aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode)));
- }
- public static void addStickyBoundsHandlesTo(PNode aNode, PCamera camera) {
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createEastLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createWestLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode)));
- camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode)));
- }
-
- public static void removeBoundsHandlesFrom(PNode aNode) {
- ArrayList handles = new ArrayList();
+ private PBasicInputEventHandler handleCursorHandler;
- Iterator i = aNode.getChildrenIterator();
- while (i.hasNext()) {
- PNode each = (PNode) i.next();
- if (each instanceof PSWTBoundsHandle) {
- handles.add(each);
- }
- }
- aNode.removeChildren(handles);
- }
-
- public PSWTBoundsHandle(PBoundsLocator aLocator) {
- super(aLocator);
- }
-
- protected void installHandleEventHandlers() {
- super.installHandleEventHandlers();
- handleCursorHandler = new PBasicInputEventHandler() {
- boolean cursorPushed = false;
- public void mouseEntered(PInputEvent aEvent) {
- if (!cursorPushed) {
- aEvent.pushCursor(getCursorFor(((PBoundsLocator)getLocator()).getSide()));
- cursorPushed = true;
- }
- }
- public void mouseExited(PInputEvent aEvent) {
- PPickPath focus = aEvent.getInputManager().getMouseFocus();
- if (cursorPushed) {
- if (focus == null || focus.getPickedNode() != PSWTBoundsHandle.this) {
- aEvent.popCursor();
- cursorPushed = false;
- }
- }
- }
- public void mouseReleased(PInputEvent event) {
- if (cursorPushed) {
- event.popCursor();
- cursorPushed = false;
- }
- }
- };
- addInputEventListener(handleCursorHandler);
- }
+ public static void addBoundsHandlesTo(PNode aNode) {
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createEastLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createWestLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode)));
+ aNode.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode)));
+ }
- /**
- * Return the event handler that is responsible for setting the mouse
- * cursor when it enters/exits this handle.
- */
- public PBasicInputEventHandler getHandleCursorEventHandler() {
- return handleCursorHandler;
- }
-
- public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
- PBoundsLocator l = (PBoundsLocator) getLocator();
- l.getNode().startResizeBounds();
- }
-
- public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) {
- PBoundsLocator l = (PBoundsLocator) getLocator();
-
- PNode n = l.getNode();
- PBounds b = n.getBounds();
+ public static void addStickyBoundsHandlesTo(PNode aNode, PCamera camera) {
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createEastLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createWestLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthEastLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createNorthWestLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthEastLocator(aNode)));
+ camera.addChild(new PSWTBoundsHandle(PBoundsLocator.createSouthWestLocator(aNode)));
+ }
- PNode parent = getParent();
- if (parent != n && parent instanceof PCamera) {
- ((PCamera)parent).localToView(aLocalDimension);
- }
+ public static void removeBoundsHandlesFrom(PNode aNode) {
+ ArrayList handles = new ArrayList();
- localToGlobal(aLocalDimension);
- n.globalToLocal(aLocalDimension);
-
- double dx = aLocalDimension.getWidth();
- double dy = aLocalDimension.getHeight();
-
- switch (l.getSide()) {
- case SwingConstants.NORTH:
- b.setRect(b.x, b.y + dy, b.width, b.height - dy);
- break;
-
- case SwingConstants.SOUTH:
- b.setRect(b.x, b.y, b.width, b.height + dy);
- break;
-
- case SwingConstants.EAST:
- b.setRect(b.x, b.y, b.width + dx, b.height);
- break;
-
- case SwingConstants.WEST:
- b.setRect(b.x + dx, b.y, b.width - dx, b.height);
- break;
-
- case SwingConstants.NORTH_WEST:
- b.setRect(b.x + dx, b.y + dy, b.width - dx, b.height - dy);
- break;
-
- case SwingConstants.SOUTH_WEST:
- b.setRect(b.x + dx, b.y, b.width - dx, b.height + dy);
- break;
-
- case SwingConstants.NORTH_EAST:
- b.setRect(b.x, b.y + dy, b.width + dx, b.height - dy);
- break;
-
- case SwingConstants.SOUTH_EAST:
- b.setRect(b.x, b.y, b.width + dx, b.height + dy);
- break;
- }
-
- boolean flipX = false;
- boolean flipY = false;
-
- if (b.width < 0) {
- flipX = true;
- b.width = -b.width;
- b.x -= b.width;
- }
-
- if (b.height < 0) {
- flipY = true;
- b.height = -b.height;
- b.y -= b.height;
- }
-
- if (flipX || flipY) {
- flipSiblingBoundsHandles(flipX, flipY);
- }
-
- n.setBounds(b);
- }
-
- public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
- PBoundsLocator l = (PBoundsLocator) getLocator();
- l.getNode().endResizeBounds();
- }
-
- public void flipSiblingBoundsHandles(boolean flipX, boolean flipY) {
- Iterator i = getParent().getChildrenIterator();
- while (i.hasNext()) {
- Object each = i.next();
- if (each instanceof PSWTBoundsHandle) {
- ((PSWTBoundsHandle)each).flipHandleIfNeeded(flipX, flipY);
- }
- }
- }
-
- public void flipHandleIfNeeded(boolean flipX, boolean flipY) {
- PBoundsLocator l = (PBoundsLocator) getLocator();
-
- if (flipX || flipY) {
- switch (l.getSide()) {
- case SwingConstants.NORTH: {
- if (flipY) {
- l.setSide(SwingConstants.SOUTH);
- }
- break;
- }
-
- case SwingConstants.SOUTH: {
- if (flipY) {
- l.setSide(SwingConstants.NORTH);
- }
- break;
- }
-
- case SwingConstants.EAST: {
- if (flipX) {
- l.setSide(SwingConstants.WEST);
- }
- break;
- }
-
- case SwingConstants.WEST: {
- if (flipX) {
- l.setSide(SwingConstants.EAST);
- }
- break;
- }
-
- case SwingConstants.NORTH_WEST: {
- if (flipX && flipY) {
- l.setSide(SwingConstants.SOUTH_EAST);
- } else if (flipX) {
- l.setSide(SwingConstants.NORTH_EAST);
- } else if (flipY) {
- l.setSide(SwingConstants.SOUTH_WEST);
- }
-
- break;
- }
-
- case SwingConstants.SOUTH_WEST: {
- if (flipX && flipY) {
- l.setSide(SwingConstants.NORTH_EAST);
- } else if (flipX) {
- l.setSide(SwingConstants.SOUTH_EAST);
- } else if (flipY) {
- l.setSide(SwingConstants.NORTH_WEST);
- }
- break;
- }
-
- case SwingConstants.NORTH_EAST: {
- if (flipX && flipY) {
- l.setSide(SwingConstants.SOUTH_WEST);
- } else if (flipX) {
- l.setSide(SwingConstants.NORTH_WEST);
- } else if (flipY) {
- l.setSide(SwingConstants.SOUTH_EAST);
- }
- break;
- }
-
- case SwingConstants.SOUTH_EAST: {
- if (flipX && flipY) {
- l.setSide(SwingConstants.NORTH_WEST);
- } else if (flipX) {
- l.setSide(SwingConstants.SOUTH_WEST);
- } else if (flipY) {
- l.setSide(SwingConstants.NORTH_EAST);
- }
- break;
- }
- }
- }
-
- // reset locator to update layout
- setLocator(l);
- }
-
- public Cursor getCursorFor(int side) {
- switch (side) {
- case SwingConstants.NORTH:
- return new Cursor(Cursor.N_RESIZE_CURSOR);
+ Iterator i = aNode.getChildrenIterator();
+ while (i.hasNext()) {
+ PNode each = (PNode) i.next();
+ if (each instanceof PSWTBoundsHandle) {
+ handles.add(each);
+ }
+ }
+ aNode.removeChildren(handles);
+ }
- case SwingConstants.SOUTH:
- return new Cursor(Cursor.S_RESIZE_CURSOR);
-
- case SwingConstants.EAST:
- return new Cursor(Cursor.E_RESIZE_CURSOR);
-
- case SwingConstants.WEST:
- return new Cursor(Cursor.W_RESIZE_CURSOR);
-
- case SwingConstants.NORTH_WEST:
- return new Cursor(Cursor.NW_RESIZE_CURSOR);
-
- case SwingConstants.SOUTH_WEST:
- return new Cursor(Cursor.SW_RESIZE_CURSOR);
-
- case SwingConstants.NORTH_EAST:
- return new Cursor(Cursor.NE_RESIZE_CURSOR);
-
- case SwingConstants.SOUTH_EAST:
- return new Cursor(Cursor.SE_RESIZE_CURSOR);
- }
- return null;
- }
+ public PSWTBoundsHandle(PBoundsLocator aLocator) {
+ super(aLocator);
+ }
+
+ protected void installHandleEventHandlers() {
+ super.installHandleEventHandlers();
+ handleCursorHandler = new PBasicInputEventHandler() {
+ boolean cursorPushed = false;
+
+ public void mouseEntered(PInputEvent aEvent) {
+ if (!cursorPushed) {
+ aEvent.pushCursor(getCursorFor(((PBoundsLocator) getLocator()).getSide()));
+ cursorPushed = true;
+ }
+ }
+
+ public void mouseExited(PInputEvent aEvent) {
+ PPickPath focus = aEvent.getInputManager().getMouseFocus();
+ if (cursorPushed) {
+ if (focus == null || focus.getPickedNode() != PSWTBoundsHandle.this) {
+ aEvent.popCursor();
+ cursorPushed = false;
+ }
+ }
+ }
+
+ public void mouseReleased(PInputEvent event) {
+ if (cursorPushed) {
+ event.popCursor();
+ cursorPushed = false;
+ }
+ }
+ };
+ addInputEventListener(handleCursorHandler);
+ }
+
+ /**
+ * Return the event handler that is responsible for setting the mouse cursor
+ * when it enters/exits this handle.
+ */
+ public PBasicInputEventHandler getHandleCursorEventHandler() {
+ return handleCursorHandler;
+ }
+
+ public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
+ PBoundsLocator l = (PBoundsLocator) getLocator();
+ l.getNode().startResizeBounds();
+ }
+
+ public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) {
+ PBoundsLocator l = (PBoundsLocator) getLocator();
+
+ PNode n = l.getNode();
+ PBounds b = n.getBounds();
+
+ PNode parent = getParent();
+ if (parent != n && parent instanceof PCamera) {
+ ((PCamera) parent).localToView(aLocalDimension);
+ }
+
+ localToGlobal(aLocalDimension);
+ n.globalToLocal(aLocalDimension);
+
+ double dx = aLocalDimension.getWidth();
+ double dy = aLocalDimension.getHeight();
+
+ switch (l.getSide()) {
+ case SwingConstants.NORTH:
+ b.setRect(b.x, b.y + dy, b.width, b.height - dy);
+ break;
+
+ case SwingConstants.SOUTH:
+ b.setRect(b.x, b.y, b.width, b.height + dy);
+ break;
+
+ case SwingConstants.EAST:
+ b.setRect(b.x, b.y, b.width + dx, b.height);
+ break;
+
+ case SwingConstants.WEST:
+ b.setRect(b.x + dx, b.y, b.width - dx, b.height);
+ break;
+
+ case SwingConstants.NORTH_WEST:
+ b.setRect(b.x + dx, b.y + dy, b.width - dx, b.height - dy);
+ break;
+
+ case SwingConstants.SOUTH_WEST:
+ b.setRect(b.x + dx, b.y, b.width - dx, b.height + dy);
+ break;
+
+ case SwingConstants.NORTH_EAST:
+ b.setRect(b.x, b.y + dy, b.width + dx, b.height - dy);
+ break;
+
+ case SwingConstants.SOUTH_EAST:
+ b.setRect(b.x, b.y, b.width + dx, b.height + dy);
+ break;
+ }
+
+ boolean flipX = false;
+ boolean flipY = false;
+
+ if (b.width < 0) {
+ flipX = true;
+ b.width = -b.width;
+ b.x -= b.width;
+ }
+
+ if (b.height < 0) {
+ flipY = true;
+ b.height = -b.height;
+ b.y -= b.height;
+ }
+
+ if (flipX || flipY) {
+ flipSiblingBoundsHandles(flipX, flipY);
+ }
+
+ n.setBounds(b);
+ }
+
+ public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
+ PBoundsLocator l = (PBoundsLocator) getLocator();
+ l.getNode().endResizeBounds();
+ }
+
+ public void flipSiblingBoundsHandles(boolean flipX, boolean flipY) {
+ Iterator i = getParent().getChildrenIterator();
+ while (i.hasNext()) {
+ Object each = i.next();
+ if (each instanceof PSWTBoundsHandle) {
+ ((PSWTBoundsHandle) each).flipHandleIfNeeded(flipX, flipY);
+ }
+ }
+ }
+
+ public void flipHandleIfNeeded(boolean flipX, boolean flipY) {
+ PBoundsLocator l = (PBoundsLocator) getLocator();
+
+ if (flipX || flipY) {
+ switch (l.getSide()) {
+ case SwingConstants.NORTH: {
+ if (flipY) {
+ l.setSide(SwingConstants.SOUTH);
+ }
+ break;
+ }
+
+ case SwingConstants.SOUTH: {
+ if (flipY) {
+ l.setSide(SwingConstants.NORTH);
+ }
+ break;
+ }
+
+ case SwingConstants.EAST: {
+ if (flipX) {
+ l.setSide(SwingConstants.WEST);
+ }
+ break;
+ }
+
+ case SwingConstants.WEST: {
+ if (flipX) {
+ l.setSide(SwingConstants.EAST);
+ }
+ break;
+ }
+
+ case SwingConstants.NORTH_WEST: {
+ if (flipX && flipY) {
+ l.setSide(SwingConstants.SOUTH_EAST);
+ }
+ else if (flipX) {
+ l.setSide(SwingConstants.NORTH_EAST);
+ }
+ else if (flipY) {
+ l.setSide(SwingConstants.SOUTH_WEST);
+ }
+
+ break;
+ }
+
+ case SwingConstants.SOUTH_WEST: {
+ if (flipX && flipY) {
+ l.setSide(SwingConstants.NORTH_EAST);
+ }
+ else if (flipX) {
+ l.setSide(SwingConstants.SOUTH_EAST);
+ }
+ else if (flipY) {
+ l.setSide(SwingConstants.NORTH_WEST);
+ }
+ break;
+ }
+
+ case SwingConstants.NORTH_EAST: {
+ if (flipX && flipY) {
+ l.setSide(SwingConstants.SOUTH_WEST);
+ }
+ else if (flipX) {
+ l.setSide(SwingConstants.NORTH_WEST);
+ }
+ else if (flipY) {
+ l.setSide(SwingConstants.SOUTH_EAST);
+ }
+ break;
+ }
+
+ case SwingConstants.SOUTH_EAST: {
+ if (flipX && flipY) {
+ l.setSide(SwingConstants.NORTH_WEST);
+ }
+ else if (flipX) {
+ l.setSide(SwingConstants.SOUTH_WEST);
+ }
+ else if (flipY) {
+ l.setSide(SwingConstants.NORTH_EAST);
+ }
+ break;
+ }
+ }
+ }
+
+ // reset locator to update layout
+ setLocator(l);
+ }
+
+ public Cursor getCursorFor(int side) {
+ switch (side) {
+ case SwingConstants.NORTH:
+ return new Cursor(Cursor.N_RESIZE_CURSOR);
+
+ case SwingConstants.SOUTH:
+ return new Cursor(Cursor.S_RESIZE_CURSOR);
+
+ case SwingConstants.EAST:
+ return new Cursor(Cursor.E_RESIZE_CURSOR);
+
+ case SwingConstants.WEST:
+ return new Cursor(Cursor.W_RESIZE_CURSOR);
+
+ case SwingConstants.NORTH_WEST:
+ return new Cursor(Cursor.NW_RESIZE_CURSOR);
+
+ case SwingConstants.SOUTH_WEST:
+ return new Cursor(Cursor.SW_RESIZE_CURSOR);
+
+ case SwingConstants.NORTH_EAST:
+ return new Cursor(Cursor.NE_RESIZE_CURSOR);
+
+ case SwingConstants.SOUTH_EAST:
+ return new Cursor(Cursor.SE_RESIZE_CURSOR);
+ }
+ return null;
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTCanvas.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTCanvas.java
index db8fcd2..f9fc22b 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTCanvas.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTCanvas.java
@@ -63,541 +63,559 @@
import edu.umd.cs.piccolo.util.PStack;
/**
- * PCanvas is a simple Swing component that can be used to embed
- * Piccolo into a Java Swing application. Canvas's view the Piccolo scene
- * graph through a camera. The canvas manages screen updates coming from
- * this camera, and forwards swing mouse and keyboard events to the camera.
+ * PCanvas is a simple Swing component that can be used to embed Piccolo
+ * into a Java Swing application. Canvas's view the Piccolo scene graph through
+ * a camera. The canvas manages screen updates coming from this camera, and
+ * forwards swing mouse and keyboard events to the camera.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PSWTCanvas extends Composite implements PComponent {
- public static PSWTCanvas CURRENT_CANVAS = null;
+ public static PSWTCanvas CURRENT_CANVAS = null;
- private Image backBuffer;
- private boolean doubleBuffered = true;
+ private Image backBuffer;
+ private boolean doubleBuffered = true;
- private PCamera camera;
- private PStack cursorStack;
- private Cursor curCursor;
- private int interacting;
- private int defaultRenderQuality;
- private int animatingRenderQuality;
- private int interactingRenderQuality;
- private PPanEventHandler panEventHandler;
- private PZoomEventHandler zoomEventHandler;
- private boolean paintingImmediately;
- private boolean animatingOnLastPaint;
-
- /**
- * Construct a canvas with the basic scene graph consisting of a
- * root, camera, and layer. Event handlers for zooming and panning
- * are automatically installed.
- */
- public PSWTCanvas(Composite parent, int style) {
- super(parent,style | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE);
-
- CURRENT_CANVAS = this;
- cursorStack = new PStack();
- setCamera(createBasicSceneGraph());
- installInputSources();
- setDefaultRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
- setAnimatingRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);
- setInteractingRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);
- panEventHandler = new PPanEventHandler();
- zoomEventHandler = new PZoomEventHandler();
- addInputEventListener(panEventHandler);
- addInputEventListener(zoomEventHandler);
-
- // Add a paint listener to call paint
- addPaintListener(new PaintListener() {
- public void paintControl(PaintEvent pe) {
- paintComponent(pe.gc,pe.x,pe.y,pe.width,pe.height);
- }
- });
-
- // Keep track of the references so we can dispose of the Fonts and Colors
- SWTGraphics2D.incrementGCCount();
- addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent de) {
- getRoot().getActivityScheduler().removeAllActivities();
- SWTGraphics2D.decrementGCCount();
- }
- });
- }
-
- //****************************************************************
- // Basic - Methods for accessing common piccolo nodes.
- //****************************************************************
+ private PCamera camera;
+ private PStack cursorStack;
+ private Cursor curCursor;
+ private int interacting;
+ private int defaultRenderQuality;
+ private int animatingRenderQuality;
+ private int interactingRenderQuality;
+ private PPanEventHandler panEventHandler;
+ private PZoomEventHandler zoomEventHandler;
+ private boolean paintingImmediately;
+ private boolean animatingOnLastPaint;
- /**
- * Get the pan event handler associated with this canvas. This event handler
- * is set up to get events from the camera associated with this canvas by
- * default.
- */
- public PPanEventHandler getPanEventHandler() {
- return panEventHandler;
- }
-
- /**
- * Get the zoom event handler associated with this canvas. This event handler
- * is set up to get events from the camera associated with this canvas by
- * default.
- */
- public PZoomEventHandler getZoomEventHandler() {
- return zoomEventHandler;
- }
+ /**
+ * Construct a canvas with the basic scene graph consisting of a root,
+ * camera, and layer. Event handlers for zooming and panning are
+ * automatically installed.
+ */
+ public PSWTCanvas(Composite parent, int style) {
+ super(parent, style | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE);
- /**
- * Return the camera associated with this canvas. All input events from this canvas
- * go through this camera. And this is the camera that paints this canvas.
- */
- public PCamera getCamera() {
- return camera;
- }
-
- /**
- * Set the camera associated with this canvas. All input events from this canvas
- * go through this camera. And this is the camera that paints this canvas.
- */
- public void setCamera(PCamera newCamera) {
- if (camera != null) {
- camera.setComponent(null);
- }
-
- camera = newCamera;
-
- if (camera != null) {
- camera.setComponent(this);
-
- Rectangle swtRect = getBounds();
-
- camera.setBounds(new Rectangle2D.Double(swtRect.x,swtRect.y,swtRect.width,swtRect.height));
- }
- }
+ CURRENT_CANVAS = this;
+ cursorStack = new PStack();
+ setCamera(createBasicSceneGraph());
+ installInputSources();
+ setDefaultRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
+ setAnimatingRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);
+ setInteractingRenderQuality(PPaintContext.LOW_QUALITY_RENDERING);
+ panEventHandler = new PPanEventHandler();
+ zoomEventHandler = new PZoomEventHandler();
+ addInputEventListener(panEventHandler);
+ addInputEventListener(zoomEventHandler);
- /**
- * Return root for this canvas.
- */
- public PRoot getRoot() {
- return camera.getRoot();
- }
-
- /**
- * Return layer for this canvas.
- */
- public PLayer getLayer() {
- return camera.getLayer(0);
- }
+ // Add a paint listener to call paint
+ addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent pe) {
+ paintComponent(pe.gc, pe.x, pe.y, pe.width, pe.height);
+ }
+ });
- /**
- * Add an input listener to the camera associated with this canvas.
- */
- public void addInputEventListener(PInputEventListener listener) {
- getCamera().addInputEventListener(listener);
- }
-
- /**
- * Remove an input listener to the camera associated with this canvas.
- */
- public void removeInputEventListener(PInputEventListener listener) {
- getCamera().removeInputEventListener(listener);
- }
-
- public PCamera createBasicSceneGraph() {
- PRoot r = new PSWTRoot(this);
- PLayer l = new PLayer();
- PCamera c = new PCamera();
+ // Keep track of the references so we can dispose of the Fonts and
+ // Colors
+ SWTGraphics2D.incrementGCCount();
+ addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent de) {
+ getRoot().getActivityScheduler().removeAllActivities();
+ SWTGraphics2D.decrementGCCount();
+ }
+ });
+ }
- r.addChild(c);
- r.addChild(l);
- c.addLayer(l);
-
- return c;
- }
-
- //****************************************************************
- // Painting
- //****************************************************************
+ // ****************************************************************
+ // Basic - Methods for accessing common piccolo nodes.
+ // ****************************************************************
- /**
- * Return true if this canvas has been marked as interacting. If so
- * the canvas will normally render at a lower quality that is faster.
- */
- public boolean getInteracting() {
- return interacting > 0;
- }
-
- /**
- * Return true if any activities that respond with true to the method
- * isAnimating were run in the last PRoot.processInputs() loop. This
- * values is used by this canvas to determine the render quality
- * to use for the next paint.
- */
- public boolean getAnimating() {
- return getRoot().getActivityScheduler().getAnimating();
- }
+ /**
+ * Get the pan event handler associated with this canvas. This event handler
+ * is set up to get events from the camera associated with this canvas by
+ * default.
+ */
+ public PPanEventHandler getPanEventHandler() {
+ return panEventHandler;
+ }
- /**
- * Set if this canvas is interacting. If so the canvas will normally
- * render at a lower quality that is faster.
- */
- public void setInteracting(boolean isInteracting) {
- if (isInteracting) {
- interacting++;
- } else {
- interacting--;
- }
-
- if (!getInteracting()) {
- repaint();
- }
- }
+ /**
+ * Get the zoom event handler associated with this canvas. This event
+ * handler is set up to get events from the camera associated with this
+ * canvas by default.
+ */
+ public PZoomEventHandler getZoomEventHandler() {
+ return zoomEventHandler;
+ }
- /**
- * Get whether this canvas should use double buffering - the default is no double buffering
- */
- public boolean getDoubleBuffered() {
- return doubleBuffered;
- }
+ /**
+ * Return the camera associated with this canvas. All input events from this
+ * canvas go through this camera. And this is the camera that paints this
+ * canvas.
+ */
+ public PCamera getCamera() {
+ return camera;
+ }
- /**
- * Set whether this canvas should use double buffering - the default is no double buffering
- */
- public void setDoubleBuffered(boolean dBuffered) {
- this.doubleBuffered = dBuffered;
- }
+ /**
+ * Set the camera associated with this canvas. All input events from this
+ * canvas go through this camera. And this is the camera that paints this
+ * canvas.
+ */
+ public void setCamera(PCamera newCamera) {
+ if (camera != null) {
+ camera.setComponent(null);
+ }
- /**
- * Set the render quality that should be used when rendering this canvas.
- * The default value is PPaintContext.HIGH_QUALITY_RENDERING.
- *
- * @param requestedQuality supports PPaintContext.HIGH_QUALITY_RENDERING or PPaintContext.LOW_QUALITY_RENDERING
- */
- public void setDefaultRenderQuality(int requestedQuality) {
- defaultRenderQuality = requestedQuality;
- repaint();
- }
+ camera = newCamera;
- /**
- * Set the render quality that should be used when rendering this canvas
- * when it is animating. The default value is PPaintContext.LOW_QUALITY_RENDERING.
- *
- * @param requestedQuality supports PPaintContext.HIGH_QUALITY_RENDERING or PPaintContext.LOW_QUALITY_RENDERING
- */
- public void setAnimatingRenderQuality(int requestedQuality) {
- animatingRenderQuality = requestedQuality;
- repaint();
- }
+ if (camera != null) {
+ camera.setComponent(this);
- /**
- * Set the render quality that should be used when rendering this canvas
- * when it is interacting. The default value is PPaintContext.LOW_QUALITY_RENDERING.
- *
- * @param requestedQuality supports PPaintContext.HIGH_QUALITY_RENDERING or PPaintContext.LOW_QUALITY_RENDERING
- */
- public void setInteractingRenderQuality(int requestedQuality) {
- interactingRenderQuality = requestedQuality;
- repaint();
- }
-
- /**
- * Set the canvas cursor, and remember the previous cursor on the
- * cursor stack.
- */
- public void pushCursor(java.awt.Cursor cursor) {
- Cursor aCursor = null;
- if (cursor.getType() == java.awt.Cursor.N_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZEN);
- }
- else if (cursor.getType() == java.awt.Cursor.NE_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZENE);
- }
- else if (cursor.getType() == java.awt.Cursor.NW_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZENW);
- }
- else if (cursor.getType() == java.awt.Cursor.S_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZES);
- }
- else if (cursor.getType() == java.awt.Cursor.SE_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZESE);
- }
- else if (cursor.getType() == java.awt.Cursor.SW_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZESW);
- }
- else if (cursor.getType() == java.awt.Cursor.E_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZEE);
- }
- else if (cursor.getType() == java.awt.Cursor.W_RESIZE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZEW);
- }
- else if (cursor.getType() == java.awt.Cursor.TEXT_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_IBEAM);
- }
- else if (cursor.getType() == java.awt.Cursor.HAND_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_HAND);
- }
- else if (cursor.getType() == java.awt.Cursor.MOVE_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_SIZEALL);
- }
- else if (cursor.getType() == java.awt.Cursor.CROSSHAIR_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_CROSS);
- }
- else if (cursor.getType() == java.awt.Cursor.WAIT_CURSOR) {
- aCursor = new Cursor(this.getDisplay(),SWT.CURSOR_WAIT);
- }
-
- if (aCursor != null) {
- if (curCursor != null) {
- cursorStack.push(curCursor);
- }
- curCursor = aCursor;
- setCursor(aCursor);
- }
- }
-
- /**
- * Pop the cursor on top of the cursorStack and set it as the
- * canvas cursor.
- */
- public void popCursor() {
- if (curCursor != null) {
- // We must manually dispose of cursors under SWT
- curCursor.dispose();
- }
-
- if (!cursorStack.isEmpty()) {
- curCursor = (Cursor)cursorStack.pop();
- }
- else {
- curCursor = null;
- }
-
- // This sets the cursor back to default
- setCursor(curCursor);
- }
-
- //****************************************************************
- // Code to manage connection to Swing. There appears to be a bug in
- // swing where it will occasionally send to many mouse pressed or mouse
- // released events. Below we attempt to filter out those cases before
- // they get delivered to the Piccolo framework.
- //****************************************************************
-
- private boolean isButton1Pressed;
- private boolean isButton2Pressed;
- private boolean isButton3Pressed;
-
- /**
- * This method installs mouse and key listeners on the canvas that forward
- * those events to piccolo.
- */
- protected void installInputSources() {
- this.addMouseListener(new MouseListener() {
- public void mouseDown(MouseEvent me) {
- boolean shouldBalanceEvent = false;
-
- switch (me.button) {
- case 1:
- if (isButton1Pressed) {
- shouldBalanceEvent = true;
- }
- isButton1Pressed = true;
- break;
- case 2:
- if (isButton2Pressed) {
- shouldBalanceEvent = true;
- }
- isButton2Pressed = true;
- break;
- case 3:
- if (isButton3Pressed) {
- shouldBalanceEvent = true;
- }
- isButton3Pressed = true;
- break;
- }
-
- if (shouldBalanceEvent) {
- java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_RELEASED,1);
- sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_RELEASED);
- }
-
- java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_PRESSED,1);
- sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_PRESSED);
- }
-
- public void mouseUp(MouseEvent me) {
- boolean shouldBalanceEvent = false;
-
- switch (me.button) {
- case 1:
- if (!isButton1Pressed) {
- shouldBalanceEvent = true;
- }
- isButton1Pressed = false;
- break;
- case 2:
- if (!isButton2Pressed) {
- shouldBalanceEvent = true;
- }
- isButton2Pressed = false;
- break;
- case 3:
- if (!isButton3Pressed) {
- shouldBalanceEvent = true;
- }
- isButton3Pressed = false;
- break;
- }
-
- if (shouldBalanceEvent) {
- java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_PRESSED,1);
- sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_PRESSED);
- }
-
- java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_RELEASED,1);
- sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_RELEASED);
- }
-
- public void mouseDoubleClick(final MouseEvent me) {
- // This doesn't work with click event types for some reason - it has to do with how
- // the click and release events are ordered, I think
- java.awt.event.MouseEvent inputEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_PRESSED,2);
- sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_PRESSED);
- inputEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_RELEASED,2);
- sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_RELEASED);
- }
- });
+ Rectangle swtRect = getBounds();
- this.addMouseMoveListener(new MouseMoveListener() {
- public void mouseMove(MouseEvent me) {
- if (isButton1Pressed || isButton2Pressed || isButton3Pressed) {
- java.awt.event.MouseEvent inputEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_DRAGGED,1);
- sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_DRAGGED);
- }
- else {
- java.awt.event.MouseEvent inputEvent = new PSWTMouseEvent(me,java.awt.event.MouseEvent.MOUSE_MOVED,1);
- sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_MOVED);
- }
- }
- });
-
- this.addKeyListener(new KeyListener() {
- public void keyPressed(KeyEvent ke) {
- java.awt.event.KeyEvent inputEvent = new PSWTKeyEvent(ke,java.awt.event.KeyEvent.KEY_PRESSED);
- sendInputEventToInputManager(inputEvent, java.awt.event.KeyEvent.KEY_PRESSED);
- }
-
- public void keyReleased(KeyEvent ke) {
- java.awt.event.KeyEvent inputEvent = new PSWTKeyEvent(ke,java.awt.event.KeyEvent.KEY_RELEASED);
- sendInputEventToInputManager(inputEvent, java.awt.event.KeyEvent.KEY_RELEASED);
- }
- });
+ camera.setBounds(new Rectangle2D.Double(swtRect.x, swtRect.y, swtRect.width, swtRect.height));
+ }
+ }
- }
+ /**
+ * Return root for this canvas.
+ */
+ public PRoot getRoot() {
+ return camera.getRoot();
+ }
- protected void sendInputEventToInputManager(InputEvent e, int type) {
- getRoot().getDefaultInputManager().processEventFromCamera(e, type, getCamera());
- }
-
- public void setBounds(int x, int y, final int w, final int h) {
- camera.setBounds(camera.getX(), camera.getY(), w, h);
+ /**
+ * Return layer for this canvas.
+ */
+ public PLayer getLayer() {
+ return camera.getLayer(0);
+ }
- if (backBuffer == null || backBuffer.getBounds().width < w || backBuffer.getBounds().height < h) {
- backBuffer = new Image(getDisplay(),w,h);
- }
+ /**
+ * Add an input listener to the camera associated with this canvas.
+ */
+ public void addInputEventListener(PInputEventListener listener) {
+ getCamera().addInputEventListener(listener);
+ }
- super.setBounds(x, y, w, h);
- }
+ /**
+ * Remove an input listener to the camera associated with this canvas.
+ */
+ public void removeInputEventListener(PInputEventListener listener) {
+ getCamera().removeInputEventListener(listener);
+ }
- public void repaint() {
- super.redraw();
- }
-
- public void repaint(PBounds bounds) {
- bounds.expandNearestIntegerDimensions();
- bounds.inset(-1, -1);
+ public PCamera createBasicSceneGraph() {
+ PRoot r = new PSWTRoot(this);
+ PLayer l = new PLayer();
+ PCamera c = new PCamera();
- redraw((int)bounds.x,
- (int)bounds.y,
- (int)bounds.width,
- (int)bounds.height,
- true);
- }
+ r.addChild(c);
+ r.addChild(l);
+ c.addLayer(l);
- public void paintComponent(GC gc, int x, int y, int w, int h) {
- PDebug.startProcessingOutput();
+ return c;
+ }
- GC imageGC = null;
- Graphics2D g2 = null;
- if (doubleBuffered) {
- imageGC = new GC(backBuffer);
- g2 = new SWTGraphics2D(imageGC,getDisplay());
- }
- else {
- g2 = new SWTGraphics2D(gc,getDisplay());
- }
+ // ****************************************************************
+ // Painting
+ // ****************************************************************
- g2.setColor(Color.white);
- g2.setBackground(Color.white);
-
- Rectangle rect = getBounds();
- g2.fillRect(0,0,rect.width,rect.height);
+ /**
+ * Return true if this canvas has been marked as interacting. If so the
+ * canvas will normally render at a lower quality that is faster.
+ */
+ public boolean getInteracting() {
+ return interacting > 0;
+ }
- // This fixes a problem with standard debugging of region management in SWT
- if (PDebug.debugRegionManagement) {
- Rectangle r = gc.getClipping();
- Rectangle2D r2 = new Rectangle2D.Double(r.x,r.y,r.width,r.height);
- g2.setBackground(PDebug.getDebugPaintColor());
- g2.fill(r2);
- }
-
- // create new paint context and set render quality
- PPaintContext paintContext = new PPaintContext(g2);
- if (getInteracting() || getAnimating()) {
- if (interactingRenderQuality > animatingRenderQuality) {
- paintContext.setRenderQuality(interactingRenderQuality);
- } else {
- paintContext.setRenderQuality(animatingRenderQuality);
- }
- } else {
- paintContext.setRenderQuality(defaultRenderQuality);
- }
-
- // paint piccolo
- camera.fullPaint(paintContext);
-
- // if switched state from animating to not animating invalidate the entire
- // screen so that it will be drawn with the default instead of animating
- // render quality.
- if (!getAnimating() && animatingOnLastPaint) {
- repaint();
- }
- animatingOnLastPaint = getAnimating();
+ /**
+ * Return true if any activities that respond with true to the method
+ * isAnimating were run in the last PRoot.processInputs() loop. This values
+ * is used by this canvas to determine the render quality to use for the
+ * next paint.
+ */
+ public boolean getAnimating() {
+ return getRoot().getActivityScheduler().getAnimating();
+ }
- boolean region = PDebug.debugRegionManagement;
- PDebug.debugRegionManagement = false;
- PDebug.endProcessingOutput(g2);
- PDebug.debugRegionManagement = region;
-
- if (doubleBuffered) {
- gc.drawImage(backBuffer,0,0);
-
- // Dispose of the allocated image gc
- imageGC.dispose();
- }
- }
-
- public void paintImmediately() {
- if (paintingImmediately) {
- return;
- }
-
- paintingImmediately = true;
- redraw();
- update();
- paintingImmediately = false;
- }
+ /**
+ * Set if this canvas is interacting. If so the canvas will normally render
+ * at a lower quality that is faster.
+ */
+ public void setInteracting(boolean isInteracting) {
+ if (isInteracting) {
+ interacting++;
+ }
+ else {
+ interacting--;
+ }
+
+ if (!getInteracting()) {
+ repaint();
+ }
+ }
+
+ /**
+ * Get whether this canvas should use double buffering - the default is no
+ * double buffering
+ */
+ public boolean getDoubleBuffered() {
+ return doubleBuffered;
+ }
+
+ /**
+ * Set whether this canvas should use double buffering - the default is no
+ * double buffering
+ */
+ public void setDoubleBuffered(boolean dBuffered) {
+ this.doubleBuffered = dBuffered;
+ }
+
+ /**
+ * Set the render quality that should be used when rendering this canvas.
+ * The default value is PPaintContext.HIGH_QUALITY_RENDERING.
+ *
+ * @param requestedQuality supports PPaintContext.HIGH_QUALITY_RENDERING or
+ * PPaintContext.LOW_QUALITY_RENDERING
+ */
+ public void setDefaultRenderQuality(int requestedQuality) {
+ defaultRenderQuality = requestedQuality;
+ repaint();
+ }
+
+ /**
+ * Set the render quality that should be used when rendering this canvas
+ * when it is animating. The default value is
+ * PPaintContext.LOW_QUALITY_RENDERING.
+ *
+ * @param requestedQuality supports PPaintContext.HIGH_QUALITY_RENDERING or
+ * PPaintContext.LOW_QUALITY_RENDERING
+ */
+ public void setAnimatingRenderQuality(int requestedQuality) {
+ animatingRenderQuality = requestedQuality;
+ repaint();
+ }
+
+ /**
+ * Set the render quality that should be used when rendering this canvas
+ * when it is interacting. The default value is
+ * PPaintContext.LOW_QUALITY_RENDERING.
+ *
+ * @param requestedQuality supports PPaintContext.HIGH_QUALITY_RENDERING or
+ * PPaintContext.LOW_QUALITY_RENDERING
+ */
+ public void setInteractingRenderQuality(int requestedQuality) {
+ interactingRenderQuality = requestedQuality;
+ repaint();
+ }
+
+ /**
+ * Set the canvas cursor, and remember the previous cursor on the cursor
+ * stack.
+ */
+ public void pushCursor(java.awt.Cursor cursor) {
+ Cursor aCursor = null;
+ if (cursor.getType() == java.awt.Cursor.N_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZEN);
+ }
+ else if (cursor.getType() == java.awt.Cursor.NE_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZENE);
+ }
+ else if (cursor.getType() == java.awt.Cursor.NW_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZENW);
+ }
+ else if (cursor.getType() == java.awt.Cursor.S_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZES);
+ }
+ else if (cursor.getType() == java.awt.Cursor.SE_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZESE);
+ }
+ else if (cursor.getType() == java.awt.Cursor.SW_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZESW);
+ }
+ else if (cursor.getType() == java.awt.Cursor.E_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZEE);
+ }
+ else if (cursor.getType() == java.awt.Cursor.W_RESIZE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZEW);
+ }
+ else if (cursor.getType() == java.awt.Cursor.TEXT_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_IBEAM);
+ }
+ else if (cursor.getType() == java.awt.Cursor.HAND_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_HAND);
+ }
+ else if (cursor.getType() == java.awt.Cursor.MOVE_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_SIZEALL);
+ }
+ else if (cursor.getType() == java.awt.Cursor.CROSSHAIR_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_CROSS);
+ }
+ else if (cursor.getType() == java.awt.Cursor.WAIT_CURSOR) {
+ aCursor = new Cursor(this.getDisplay(), SWT.CURSOR_WAIT);
+ }
+
+ if (aCursor != null) {
+ if (curCursor != null) {
+ cursorStack.push(curCursor);
+ }
+ curCursor = aCursor;
+ setCursor(aCursor);
+ }
+ }
+
+ /**
+ * Pop the cursor on top of the cursorStack and set it as the canvas cursor.
+ */
+ public void popCursor() {
+ if (curCursor != null) {
+ // We must manually dispose of cursors under SWT
+ curCursor.dispose();
+ }
+
+ if (!cursorStack.isEmpty()) {
+ curCursor = (Cursor) cursorStack.pop();
+ }
+ else {
+ curCursor = null;
+ }
+
+ // This sets the cursor back to default
+ setCursor(curCursor);
+ }
+
+ // ****************************************************************
+ // Code to manage connection to Swing. There appears to be a bug in
+ // swing where it will occasionally send to many mouse pressed or mouse
+ // released events. Below we attempt to filter out those cases before
+ // they get delivered to the Piccolo framework.
+ // ****************************************************************
+
+ private boolean isButton1Pressed;
+ private boolean isButton2Pressed;
+ private boolean isButton3Pressed;
+
+ /**
+ * This method installs mouse and key listeners on the canvas that forward
+ * those events to piccolo.
+ */
+ protected void installInputSources() {
+ this.addMouseListener(new MouseListener() {
+ public void mouseDown(MouseEvent me) {
+ boolean shouldBalanceEvent = false;
+
+ switch (me.button) {
+ case 1:
+ if (isButton1Pressed) {
+ shouldBalanceEvent = true;
+ }
+ isButton1Pressed = true;
+ break;
+ case 2:
+ if (isButton2Pressed) {
+ shouldBalanceEvent = true;
+ }
+ isButton2Pressed = true;
+ break;
+ case 3:
+ if (isButton3Pressed) {
+ shouldBalanceEvent = true;
+ }
+ isButton3Pressed = true;
+ break;
+ }
+
+ if (shouldBalanceEvent) {
+ java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,
+ java.awt.event.MouseEvent.MOUSE_RELEASED, 1);
+ sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_RELEASED);
+ }
+
+ java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,
+ java.awt.event.MouseEvent.MOUSE_PRESSED, 1);
+ sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_PRESSED);
+ }
+
+ public void mouseUp(MouseEvent me) {
+ boolean shouldBalanceEvent = false;
+
+ switch (me.button) {
+ case 1:
+ if (!isButton1Pressed) {
+ shouldBalanceEvent = true;
+ }
+ isButton1Pressed = false;
+ break;
+ case 2:
+ if (!isButton2Pressed) {
+ shouldBalanceEvent = true;
+ }
+ isButton2Pressed = false;
+ break;
+ case 3:
+ if (!isButton3Pressed) {
+ shouldBalanceEvent = true;
+ }
+ isButton3Pressed = false;
+ break;
+ }
+
+ if (shouldBalanceEvent) {
+ java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,
+ java.awt.event.MouseEvent.MOUSE_PRESSED, 1);
+ sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_PRESSED);
+ }
+
+ java.awt.event.MouseEvent balanceEvent = new PSWTMouseEvent(me,
+ java.awt.event.MouseEvent.MOUSE_RELEASED, 1);
+ sendInputEventToInputManager(balanceEvent, java.awt.event.MouseEvent.MOUSE_RELEASED);
+ }
+
+ public void mouseDoubleClick(final MouseEvent me) {
+ // This doesn't work with click event types for some reason - it
+ // has to do with how the click and release events are ordered,
+ // I think
+ java.awt.event.MouseEvent inputEvent = new PSWTMouseEvent(me, java.awt.event.MouseEvent.MOUSE_PRESSED,
+ 2);
+ sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_PRESSED);
+ inputEvent = new PSWTMouseEvent(me, java.awt.event.MouseEvent.MOUSE_RELEASED, 2);
+ sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_RELEASED);
+ }
+ });
+
+ this.addMouseMoveListener(new MouseMoveListener() {
+ public void mouseMove(MouseEvent me) {
+ if (isButton1Pressed || isButton2Pressed || isButton3Pressed) {
+ java.awt.event.MouseEvent inputEvent = new PSWTMouseEvent(me,
+ java.awt.event.MouseEvent.MOUSE_DRAGGED, 1);
+ sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_DRAGGED);
+ }
+ else {
+ java.awt.event.MouseEvent inputEvent = new PSWTMouseEvent(me,
+ java.awt.event.MouseEvent.MOUSE_MOVED, 1);
+ sendInputEventToInputManager(inputEvent, java.awt.event.MouseEvent.MOUSE_MOVED);
+ }
+ }
+ });
+
+ this.addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent ke) {
+ java.awt.event.KeyEvent inputEvent = new PSWTKeyEvent(ke, java.awt.event.KeyEvent.KEY_PRESSED);
+ sendInputEventToInputManager(inputEvent, java.awt.event.KeyEvent.KEY_PRESSED);
+ }
+
+ public void keyReleased(KeyEvent ke) {
+ java.awt.event.KeyEvent inputEvent = new PSWTKeyEvent(ke, java.awt.event.KeyEvent.KEY_RELEASED);
+ sendInputEventToInputManager(inputEvent, java.awt.event.KeyEvent.KEY_RELEASED);
+ }
+ });
+
+ }
+
+ protected void sendInputEventToInputManager(InputEvent e, int type) {
+ getRoot().getDefaultInputManager().processEventFromCamera(e, type, getCamera());
+ }
+
+ public void setBounds(int x, int y, final int w, final int h) {
+ camera.setBounds(camera.getX(), camera.getY(), w, h);
+
+ if (backBuffer == null || backBuffer.getBounds().width < w || backBuffer.getBounds().height < h) {
+ backBuffer = new Image(getDisplay(), w, h);
+ }
+
+ super.setBounds(x, y, w, h);
+ }
+
+ public void repaint() {
+ super.redraw();
+ }
+
+ public void repaint(PBounds bounds) {
+ bounds.expandNearestIntegerDimensions();
+ bounds.inset(-1, -1);
+
+ redraw((int) bounds.x, (int) bounds.y, (int) bounds.width, (int) bounds.height, true);
+ }
+
+ public void paintComponent(GC gc, int x, int y, int w, int h) {
+ PDebug.startProcessingOutput();
+
+ GC imageGC = null;
+ Graphics2D g2 = null;
+ if (doubleBuffered) {
+ imageGC = new GC(backBuffer);
+ g2 = new SWTGraphics2D(imageGC, getDisplay());
+ }
+ else {
+ g2 = new SWTGraphics2D(gc, getDisplay());
+ }
+
+ g2.setColor(Color.white);
+ g2.setBackground(Color.white);
+
+ Rectangle rect = getBounds();
+ g2.fillRect(0, 0, rect.width, rect.height);
+
+ // This fixes a problem with standard debugging of region management in
+ // SWT
+ if (PDebug.debugRegionManagement) {
+ Rectangle r = gc.getClipping();
+ Rectangle2D r2 = new Rectangle2D.Double(r.x, r.y, r.width, r.height);
+ g2.setBackground(PDebug.getDebugPaintColor());
+ g2.fill(r2);
+ }
+
+ // create new paint context and set render quality
+ PPaintContext paintContext = new PPaintContext(g2);
+ if (getInteracting() || getAnimating()) {
+ if (interactingRenderQuality > animatingRenderQuality) {
+ paintContext.setRenderQuality(interactingRenderQuality);
+ }
+ else {
+ paintContext.setRenderQuality(animatingRenderQuality);
+ }
+ }
+ else {
+ paintContext.setRenderQuality(defaultRenderQuality);
+ }
+
+ // paint piccolo
+ camera.fullPaint(paintContext);
+
+ // if switched state from animating to not animating invalidate
+ // the entire screen so that it will be drawn with the default instead
+ // of animating render quality.
+ if (!getAnimating() && animatingOnLastPaint) {
+ repaint();
+ }
+ animatingOnLastPaint = getAnimating();
+
+ boolean region = PDebug.debugRegionManagement;
+ PDebug.debugRegionManagement = false;
+ PDebug.endProcessingOutput(g2);
+ PDebug.debugRegionManagement = region;
+
+ if (doubleBuffered) {
+ gc.drawImage(backBuffer, 0, 0);
+
+ // Dispose of the allocated image gc
+ imageGC.dispose();
+ }
+ }
+
+ public void paintImmediately() {
+ if (paintingImmediately) {
+ return;
+ }
+
+ paintingImmediately = true;
+ redraw();
+ update();
+ paintingImmediately = false;
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTHandle.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTHandle.java
index 0704363..cb1c37b 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTHandle.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTHandle.java
@@ -50,169 +50,174 @@
import edu.umd.cs.piccolox.util.PNodeLocator;
/**
- * PHandle is used to modify some aspect of Piccolo when it
- * is dragged. Each handle has a PLocator that it uses to automatically position
- * itself. See PBoundsHandle for an example of a handle that resizes the bounds
- * of another node.
+ * PHandle is used to modify some aspect of Piccolo when it is dragged.
+ * Each handle has a PLocator that it uses to automatically position itself. See
+ * PBoundsHandle for an example of a handle that resizes the bounds of another
+ * node.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PSWTHandle extends PSWTPath {
- public static float DEFAULT_HANDLE_SIZE = 8;
- public static Shape DEFAULT_HANDLE_SHAPE = new Ellipse2D.Float(0f, 0f, DEFAULT_HANDLE_SIZE, DEFAULT_HANDLE_SIZE);
- public static Color DEFAULT_COLOR = Color.white;
-
- private PLocator locator;
- private PDragSequenceEventHandler handleDragger;
+ public static float DEFAULT_HANDLE_SIZE = 8;
+ public static Shape DEFAULT_HANDLE_SHAPE = new Ellipse2D.Float(0f, 0f, DEFAULT_HANDLE_SIZE, DEFAULT_HANDLE_SIZE);
+ public static Color DEFAULT_COLOR = Color.white;
- /**
- * Construct a new handle that will use the given locator
- * to locate itself on its parent node.
- */
- public PSWTHandle(PLocator aLocator) {
- super(DEFAULT_HANDLE_SHAPE);
- locator = aLocator;
- setPaint(DEFAULT_COLOR);
- installHandleEventHandlers();
- }
+ private PLocator locator;
+ private PDragSequenceEventHandler handleDragger;
- protected void installHandleEventHandlers() {
- handleDragger = new PDragSequenceEventHandler() {
- protected void startDrag(PInputEvent event) {
- super.startDrag(event);
- startHandleDrag(event.getPositionRelativeTo(PSWTHandle.this), event);
- }
- protected void drag(PInputEvent event) {
- super.drag(event);
- PDimension aDelta = event.getDeltaRelativeTo(PSWTHandle.this);
- if (aDelta.getWidth() != 0 || aDelta.getHeight() != 0) {
- dragHandle(aDelta, event);
- }
- }
- protected void endDrag(PInputEvent event) {
- super.endDrag(event);
- endHandleDrag(event.getPositionRelativeTo(PSWTHandle.this), event);
- }
- };
+ /**
+ * Construct a new handle that will use the given locator to locate itself
+ * on its parent node.
+ */
+ public PSWTHandle(PLocator aLocator) {
+ super(DEFAULT_HANDLE_SHAPE);
+ locator = aLocator;
+ setPaint(DEFAULT_COLOR);
+ installHandleEventHandlers();
+ }
- addPropertyChangeListener(PNode.PROPERTY_TRANSFORM, new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- relocateHandle();
- }
- });
-
- handleDragger.setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK));
- handleDragger.getEventFilter().setMarksAcceptedEventsAsHandled(true);
- handleDragger.getEventFilter().setAcceptsMouseEntered(false);
- handleDragger.getEventFilter().setAcceptsMouseExited(false);
- handleDragger.getEventFilter().setAcceptsMouseMoved(false); // no need for moved events for handle interaction,
- // so reject them so we don't consume them
- addInputEventListener(handleDragger);
- }
-
- /**
- * Return the event handler that is responsible for the drag handle
- * interaction.
- */
- public PDragSequenceEventHandler getHandleDraggerHandler() {
- return handleDragger;
- }
+ protected void installHandleEventHandlers() {
+ handleDragger = new PDragSequenceEventHandler() {
+ protected void startDrag(PInputEvent event) {
+ super.startDrag(event);
+ startHandleDrag(event.getPositionRelativeTo(PSWTHandle.this), event);
+ }
- /**
- * Get the locator that this handle uses to position itself on its
- * parent node.
- */
- public PLocator getLocator() {
- return locator;
- }
-
- /**
- * Set the locator that this handle uses to position itself on its
- * parent node.
- */
- public void setLocator(PLocator aLocator) {
- locator = aLocator;
- invalidatePaint();
- relocateHandle();
- }
-
- //****************************************************************
- // Handle Dragging - These are the methods the subclasses should
- // normally override to give a handle unique behavior.
- //****************************************************************
-
- /**
- * Override this method to get notified when the handle starts to get dragged.
- */
- public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
- }
-
- /**
- * Override this method to get notified as the handle is dragged.
- */
- public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) {
- }
-
- /**
- * Override this method to get notified when the handle stops getting dragged.
- */
- public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
- }
-
- //****************************************************************
- // Layout - When a handle's parent's layout changes the handle
- // invalidates its own layout and then repositions itself on its
- // parents bounds using its locator to determine that new
- // position.
- //****************************************************************
-
- public void setParent(PNode newParent) {
- super.setParent(newParent);
- relocateHandle();
- }
-
- public void parentBoundsChanged() {
- relocateHandle();
- }
-
- /**
- * Force this handle to relocate itself using its locator.
- */
- public void relocateHandle() {
- if (locator != null) {
- PBounds b = getBoundsReference();
- Point2D aPoint = locator.locatePoint(null);
-
- if (locator instanceof PNodeLocator) {
- PNode located = ((PNodeLocator)locator).getNode();
- PNode parent = getParent();
-
- located.localToGlobal(aPoint);
- globalToLocal(aPoint);
-
- if (parent != located && parent instanceof PCamera) {
- ((PCamera)parent).viewToLocal(aPoint);
- }
- }
-
- double newCenterX = aPoint.getX();
- double newCenterY = aPoint.getY();
+ protected void drag(PInputEvent event) {
+ super.drag(event);
+ PDimension aDelta = event.getDeltaRelativeTo(PSWTHandle.this);
+ if (aDelta.getWidth() != 0 || aDelta.getHeight() != 0) {
+ dragHandle(aDelta, event);
+ }
+ }
- if (newCenterX != b.getCenterX() ||
- newCenterY != b.getCenterY()) {
- centerBoundsOnPoint(newCenterX, newCenterY);
- }
- }
- }
-
- //****************************************************************
- // Serialization
- //****************************************************************
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- in.defaultReadObject();
- installHandleEventHandlers();
- }
+ protected void endDrag(PInputEvent event) {
+ super.endDrag(event);
+ endHandleDrag(event.getPositionRelativeTo(PSWTHandle.this), event);
+ }
+ };
+
+ addPropertyChangeListener(PNode.PROPERTY_TRANSFORM, new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
+ relocateHandle();
+ }
+ });
+
+ handleDragger.setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK));
+ handleDragger.getEventFilter().setMarksAcceptedEventsAsHandled(true);
+ handleDragger.getEventFilter().setAcceptsMouseEntered(false);
+ handleDragger.getEventFilter().setAcceptsMouseExited(false);
+ // no need for moved events for handle interaction,
+ handleDragger.getEventFilter().setAcceptsMouseMoved(false);
+ // so reject them so we don't consume them
+ addInputEventListener(handleDragger);
+ }
+
+ /**
+ * Return the event handler that is responsible for the drag handle
+ * interaction.
+ */
+ public PDragSequenceEventHandler getHandleDraggerHandler() {
+ return handleDragger;
+ }
+
+ /**
+ * Get the locator that this handle uses to position itself on its parent
+ * node.
+ */
+ public PLocator getLocator() {
+ return locator;
+ }
+
+ /**
+ * Set the locator that this handle uses to position itself on its parent
+ * node.
+ */
+ public void setLocator(PLocator aLocator) {
+ locator = aLocator;
+ invalidatePaint();
+ relocateHandle();
+ }
+
+ // ****************************************************************
+ // Handle Dragging - These are the methods the subclasses should
+ // normally override to give a handle unique behavior.
+ // ****************************************************************
+
+ /**
+ * Override this method to get notified when the handle starts to get
+ * dragged.
+ */
+ public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
+ }
+
+ /**
+ * Override this method to get notified as the handle is dragged.
+ */
+ public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) {
+ }
+
+ /**
+ * Override this method to get notified when the handle stops getting
+ * dragged.
+ */
+ public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
+ }
+
+ // ****************************************************************
+ // Layout - When a handle's parent's layout changes the handle
+ // invalidates its own layout and then repositions itself on its
+ // parents bounds using its locator to determine that new
+ // position.
+ // ****************************************************************
+
+ public void setParent(PNode newParent) {
+ super.setParent(newParent);
+ relocateHandle();
+ }
+
+ public void parentBoundsChanged() {
+ relocateHandle();
+ }
+
+ /**
+ * Force this handle to relocate itself using its locator.
+ */
+ public void relocateHandle() {
+ if (locator != null) {
+ PBounds b = getBoundsReference();
+ Point2D aPoint = locator.locatePoint(null);
+
+ if (locator instanceof PNodeLocator) {
+ PNode located = ((PNodeLocator) locator).getNode();
+ PNode parent = getParent();
+
+ located.localToGlobal(aPoint);
+ globalToLocal(aPoint);
+
+ if (parent != located && parent instanceof PCamera) {
+ ((PCamera) parent).viewToLocal(aPoint);
+ }
+ }
+
+ double newCenterX = aPoint.getX();
+ double newCenterY = aPoint.getY();
+
+ if (newCenterX != b.getCenterX() || newCenterY != b.getCenterY()) {
+ centerBoundsOnPoint(newCenterX, newCenterY);
+ }
+ }
+ }
+
+ // ****************************************************************
+ // Serialization
+ // ****************************************************************
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ installHandleEventHandlers();
+ }
}
\ No newline at end of file
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTImage.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTImage.java
index 2e5ee28..22f2f8c 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTImage.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTImage.java
@@ -40,124 +40,129 @@
import edu.umd.cs.piccolo.util.PPaintContext;
/**
- * PImage is a wrapper around a java.awt.Image. If this node is
- * copied or serialized that image will be converted into a BufferedImage if
- * it is not already one.
+ * PImage is a wrapper around a java.awt.Image. If this node is copied or
+ * serialized that image will be converted into a BufferedImage if it is not
+ * already one.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PSWTImage extends PNode {
-
- private transient PSWTCanvas canvas;
- private transient Image image;
+ private transient PSWTCanvas canvas;
- public PSWTImage(PSWTCanvas canvas) {
- super();
-
- this.canvas = canvas;
- canvas.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent de) {
- if (image != null) {
- image.dispose();
- }
- }
- });
- }
-
- public PSWTImage(PSWTCanvas canvas, Image newImage) {
- this(canvas);
- setImage(newImage);
- }
+ private transient Image image;
- public PSWTImage(PSWTCanvas canvas, String fileName) {
- this(canvas);
- setImage(fileName);
- }
-
- /**
- * Returns the image that is shown by this node.
- * @return the image that is shown by this node
- */
- public Image getImage() {
- return image;
- }
+ public PSWTImage(PSWTCanvas canvas) {
+ super();
- /**
- * Set the image that is wrapped by this PImage node. This method will also load
- * the image using a MediaTracker before returning. And if the this PImage is
- * accelerated that I'm will be copied into an accelerated image if needed. Note
- * that this may cause undesired results with images that have transparent regions,
- * for those cases you may want to set the PImage to be not accelerated.
- */
- public void setImage(String fileName) {
- setImage(new Image(canvas.getDisplay(),fileName));
- }
+ this.canvas = canvas;
+ canvas.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent de) {
+ if (image != null) {
+ image.dispose();
+ }
+ }
+ });
+ }
- /**
- * Set the image that is wrapped by this PImage node. This method will also load
- * the image using a MediaTracker before returning. And if the this PImage is
- * accelerated that I'm will be copied into an accelerated image if needed. Note
- * that this may cause undesired results with images that have transparent regions,
- * for those cases you may want to set the PImage to be not accelerated.
- */
- public void setImage(Image newImage) {
- Image old = image;
- image = newImage;
-
- if (image != null) {
- Rectangle bounds = getImage().getBounds();
- setBounds(0, 0, bounds.width, bounds.height);
- invalidatePaint();
- } else {
- image = null;
- }
-
- firePropertyChange(PImage.PROPERTY_CODE_IMAGE, PImage.PROPERTY_IMAGE, old, image);
- }
+ public PSWTImage(PSWTCanvas canvas, Image newImage) {
+ this(canvas);
+ setImage(newImage);
+ }
- protected void paint(PPaintContext paintContext) {
- if (getImage() != null) {
- Rectangle r = image.getBounds();
- double iw = r.width;
- double ih = r.height;
- PBounds b = getBoundsReference();
- SWTGraphics2D g2 = (SWTGraphics2D)paintContext.getGraphics();
+ public PSWTImage(PSWTCanvas canvas, String fileName) {
+ this(canvas);
+ setImage(fileName);
+ }
- if (b.x != 0 || b.y != 0 || b.width != iw || b.height != ih) {
- g2.translate(b.x, b.y);
- g2.scale(b.width / iw, b.height / ih);
- g2.drawImage(image, 0, 0);
- g2.scale(iw / b.width, ih / b.height);
- g2.translate(-b.x, -b.y);
- } else {
- g2.drawImage(image, 0, 0);
- }
- }
- }
-
-
- //****************************************************************
- // Debugging - methods for debugging
- //****************************************************************
+ /**
+ * Returns the image that is shown by this node.
+ *
+ * @return the image that is shown by this node
+ */
+ public Image getImage() {
+ return image;
+ }
- /**
- * Returns a string representing the state of this node. This method is
- * intended to be used only for debugging purposes, and the content and
- * format of the returned string may vary between implementations. The
- * returned string may be empty but may not be null
.
- *
- * @return a string representation of this node's state
- */
- protected String paramString() {
- StringBuffer result = new StringBuffer();
+ /**
+ * Set the image that is wrapped by this PImage node. This method will also
+ * load the image using a MediaTracker before returning. And if the this
+ * PImage is accelerated that I'm will be copied into an accelerated image
+ * if needed. Note that this may cause undesired results with images that
+ * have transparent regions, for those cases you may want to set the PImage
+ * to be not accelerated.
+ */
+ public void setImage(String fileName) {
+ setImage(new Image(canvas.getDisplay(), fileName));
+ }
- result.append("image=" + (image == null ? "null" : image.toString()));
-
- result.append(',');
- result.append(super.paramString());
+ /**
+ * Set the image that is wrapped by this PImage node. This method will also
+ * load the image using a MediaTracker before returning. And if the this
+ * PImage is accelerated that I'm will be copied into an accelerated image
+ * if needed. Note that this may cause undesired results with images that
+ * have transparent regions, for those cases you may want to set the PImage
+ * to be not accelerated.
+ */
+ public void setImage(Image newImage) {
+ Image old = image;
+ image = newImage;
- return result.toString();
- }
+ if (image != null) {
+ Rectangle bounds = getImage().getBounds();
+ setBounds(0, 0, bounds.width, bounds.height);
+ invalidatePaint();
+ }
+ else {
+ image = null;
+ }
+
+ firePropertyChange(PImage.PROPERTY_CODE_IMAGE, PImage.PROPERTY_IMAGE, old, image);
+ }
+
+ protected void paint(PPaintContext paintContext) {
+ if (getImage() != null) {
+ Rectangle r = image.getBounds();
+ double iw = r.width;
+ double ih = r.height;
+ PBounds b = getBoundsReference();
+ SWTGraphics2D g2 = (SWTGraphics2D) paintContext.getGraphics();
+
+ if (b.x != 0 || b.y != 0 || b.width != iw || b.height != ih) {
+ g2.translate(b.x, b.y);
+ g2.scale(b.width / iw, b.height / ih);
+ g2.drawImage(image, 0, 0);
+ g2.scale(iw / b.width, ih / b.height);
+ g2.translate(-b.x, -b.y);
+ }
+ else {
+ g2.drawImage(image, 0, 0);
+ }
+ }
+ }
+
+ // ****************************************************************
+ // Debugging - methods for debugging
+ // ****************************************************************
+
+ /**
+ * Returns a string representing the state of this node. This method is
+ * intended to be used only for debugging purposes, and the content and
+ * format of the returned string may vary between implementations. The
+ * returned string may be empty but may not be null
.
+ *
+ * @return a string representation of this node's state
+ */
+ protected String paramString() {
+ StringBuffer result = new StringBuffer();
+
+ result.append("image=" + (image == null ? "null" : image.toString()));
+
+ result.append(',');
+ result.append(super.paramString());
+
+ return result.toString();
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTKeyEvent.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTKeyEvent.java
index 6eedfe4..b36f381 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTKeyEvent.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTKeyEvent.java
@@ -15,85 +15,86 @@
*/
public class PSWTKeyEvent extends KeyEvent {
- static Component fakeSrc = new Component() {};
+ static Component fakeSrc = new Component() {
+ };
- org.eclipse.swt.events.KeyEvent swtEvent;
-
- public PSWTKeyEvent(org.eclipse.swt.events.KeyEvent ke, int eventType) {
- super(fakeSrc, eventType, ke.time, 0, ke.keyCode, ke.character, KeyEvent.KEY_LOCATION_STANDARD);
-
- swtEvent = ke;
- }
+ org.eclipse.swt.events.KeyEvent swtEvent;
- public Object getSource() {
- return swtEvent.getSource();
- }
+ public PSWTKeyEvent(org.eclipse.swt.events.KeyEvent ke, int eventType) {
+ super(fakeSrc, eventType, ke.time, 0, ke.keyCode, ke.character, KeyEvent.KEY_LOCATION_STANDARD);
- public boolean isShiftDown() {
- return (swtEvent.stateMask & SWT.SHIFT) != 0;
- }
+ swtEvent = ke;
+ }
- public boolean isControlDown() {
- return (swtEvent.stateMask & SWT.CONTROL) != 0;
- }
-
- public boolean isAltDown() {
- return (swtEvent.stateMask & SWT.ALT) != 0;
- }
-
- public int getModifiers() {
- int modifiers = 0;
-
- if (swtEvent != null) {
- if ((swtEvent.stateMask & SWT.ALT) != 0) {
- modifiers = modifiers | InputEvent.ALT_MASK;
- }
- if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
- modifiers = modifiers | InputEvent.CTRL_MASK;
- }
- if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
- modifiers = modifiers | InputEvent.SHIFT_MASK;
- }
- }
+ public Object getSource() {
+ return swtEvent.getSource();
+ }
- return modifiers;
- }
-
- public int getModifiersEx() {
- int modifiers = 0;
-
- if (swtEvent != null) {
- if ((swtEvent.stateMask & SWT.ALT) != 0) {
- modifiers = modifiers | InputEvent.ALT_DOWN_MASK;
- }
- if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
- modifiers = modifiers | InputEvent.CTRL_DOWN_MASK;
- }
- if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
- modifiers = modifiers | InputEvent.SHIFT_DOWN_MASK;
- }
- }
-
- return modifiers;
- }
+ public boolean isShiftDown() {
+ return (swtEvent.stateMask & SWT.SHIFT) != 0;
+ }
- public boolean isActionKey() {
- return false;
- }
+ public boolean isControlDown() {
+ return (swtEvent.stateMask & SWT.CONTROL) != 0;
+ }
- ///////////////////////////
- // THE SWT SPECIFIC EVENTS
- ///////////////////////////
+ public boolean isAltDown() {
+ return (swtEvent.stateMask & SWT.ALT) != 0;
+ }
- public Widget getWidget() {
- return swtEvent.widget;
- }
-
- public Display getDisplay() {
- return swtEvent.display;
- }
-
- public Object getData() {
- return swtEvent.data;
- }
+ public int getModifiers() {
+ int modifiers = 0;
+
+ if (swtEvent != null) {
+ if ((swtEvent.stateMask & SWT.ALT) != 0) {
+ modifiers = modifiers | InputEvent.ALT_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
+ modifiers = modifiers | InputEvent.CTRL_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
+ modifiers = modifiers | InputEvent.SHIFT_MASK;
+ }
+ }
+
+ return modifiers;
+ }
+
+ public int getModifiersEx() {
+ int modifiers = 0;
+
+ if (swtEvent != null) {
+ if ((swtEvent.stateMask & SWT.ALT) != 0) {
+ modifiers = modifiers | InputEvent.ALT_DOWN_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
+ modifiers = modifiers | InputEvent.CTRL_DOWN_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
+ modifiers = modifiers | InputEvent.SHIFT_DOWN_MASK;
+ }
+ }
+
+ return modifiers;
+ }
+
+ public boolean isActionKey() {
+ return false;
+ }
+
+ // /////////////////////////
+ // THE SWT SPECIFIC EVENTS
+ // /////////////////////////
+
+ public Widget getWidget() {
+ return swtEvent.widget;
+ }
+
+ public Display getDisplay() {
+ return swtEvent.display;
+ }
+
+ public Object getData() {
+ return swtEvent.data;
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTMouseEvent.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTMouseEvent.java
index 0117b25..8a31038 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTMouseEvent.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTMouseEvent.java
@@ -15,126 +15,120 @@
*/
public class PSWTMouseEvent extends MouseEvent {
- static Component fakeSrc = new Component() {};
+ static Component fakeSrc = new Component() {
+ };
- protected org.eclipse.swt.events.MouseEvent swtEvent;
-
- protected int clickCount;
+ protected org.eclipse.swt.events.MouseEvent swtEvent;
- public PSWTMouseEvent(org.eclipse.swt.events.MouseEvent me, int type, int clickCount) {
- super(fakeSrc,type, me.time, 0, me.x, me.y, clickCount, (me.button == 3), me.button);
-
- this.swtEvent = me;
- this.clickCount = clickCount;
- }
+ protected int clickCount;
- public Object getSource() {
- return swtEvent.getSource();
- }
+ public PSWTMouseEvent(org.eclipse.swt.events.MouseEvent me, int type, int clickCount) {
+ super(fakeSrc, type, me.time, 0, me.x, me.y, clickCount, (me.button == 3), me.button);
- public int getClickCount() {
- return clickCount;
- }
+ this.swtEvent = me;
+ this.clickCount = clickCount;
+ }
- public int getButton() {
- switch (swtEvent.button) {
- case 1:
- return MouseEvent.BUTTON1;
- case 2:
- return MouseEvent.BUTTON2;
- case 3:
- return MouseEvent.BUTTON3;
- default:
- return MouseEvent.NOBUTTON;
- }
- }
-
- public boolean isShiftDown() {
- return (swtEvent.stateMask & SWT.SHIFT) != 0;
- }
+ public Object getSource() {
+ return swtEvent.getSource();
+ }
- public boolean isControlDown() {
- return (swtEvent.stateMask & SWT.CONTROL) != 0;
- }
-
- public boolean isAltDown() {
- return (swtEvent.stateMask & SWT.ALT) != 0;
- }
-
- public int getModifiers() {
- int modifiers = 0;
-
- if (swtEvent != null) {
- if ((swtEvent.stateMask & SWT.ALT) != 0) {
- modifiers = modifiers | InputEvent.ALT_MASK;
- }
- if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
- modifiers = modifiers | InputEvent.CTRL_MASK;
- }
- if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
- modifiers = modifiers | InputEvent.SHIFT_MASK;
- }
- if (swtEvent.button == 1 ||
- (swtEvent.stateMask & SWT.BUTTON1) != 0) {
- modifiers = modifiers | InputEvent.BUTTON1_MASK;
- }
- if (swtEvent.button == 2 ||
- (swtEvent.stateMask & SWT.BUTTON2) != 0) {
- modifiers = modifiers | InputEvent.BUTTON2_MASK;
- }
- if (swtEvent.button == 3 ||
- (swtEvent.stateMask & SWT.BUTTON3) != 0) {
- modifiers = modifiers | InputEvent.BUTTON3_MASK;
- }
- }
-
- return modifiers;
- }
-
- public int getModifiersEx() {
- int modifiers = 0;
-
- if (swtEvent != null) {
- if ((swtEvent.stateMask & SWT.ALT) != 0) {
- modifiers = modifiers | InputEvent.ALT_DOWN_MASK;
- }
- if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
- modifiers = modifiers | InputEvent.CTRL_DOWN_MASK;
- }
- if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
- modifiers = modifiers | InputEvent.SHIFT_DOWN_MASK;
- }
- if (swtEvent.button == 1 ||
- (swtEvent.stateMask & SWT.BUTTON1) != 0) {
- modifiers = modifiers | InputEvent.BUTTON1_DOWN_MASK;
- }
- if (swtEvent.button == 2 ||
- (swtEvent.stateMask & SWT.BUTTON2) != 0) {
- modifiers = modifiers | InputEvent.BUTTON2_DOWN_MASK;
- }
- if (swtEvent.button == 3 ||
- (swtEvent.stateMask & SWT.BUTTON3) != 0) {
- modifiers = modifiers | InputEvent.BUTTON3_DOWN_MASK;
- }
- }
-
- return modifiers;
- }
+ public int getClickCount() {
+ return clickCount;
+ }
+ public int getButton() {
+ switch (swtEvent.button) {
+ case 1:
+ return MouseEvent.BUTTON1;
+ case 2:
+ return MouseEvent.BUTTON2;
+ case 3:
+ return MouseEvent.BUTTON3;
+ default:
+ return MouseEvent.NOBUTTON;
+ }
+ }
- ///////////////////////////
- // THE SWT SPECIFIC EVENTS
- ///////////////////////////
+ public boolean isShiftDown() {
+ return (swtEvent.stateMask & SWT.SHIFT) != 0;
+ }
- public Widget getWidget() {
- return swtEvent.widget;
- }
-
- public Display getDisplay() {
- return swtEvent.display;
- }
-
- public Object getData() {
- return swtEvent.data;
- }
+ public boolean isControlDown() {
+ return (swtEvent.stateMask & SWT.CONTROL) != 0;
+ }
+
+ public boolean isAltDown() {
+ return (swtEvent.stateMask & SWT.ALT) != 0;
+ }
+
+ public int getModifiers() {
+ int modifiers = 0;
+
+ if (swtEvent != null) {
+ if ((swtEvent.stateMask & SWT.ALT) != 0) {
+ modifiers = modifiers | InputEvent.ALT_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
+ modifiers = modifiers | InputEvent.CTRL_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
+ modifiers = modifiers | InputEvent.SHIFT_MASK;
+ }
+ if (swtEvent.button == 1 || (swtEvent.stateMask & SWT.BUTTON1) != 0) {
+ modifiers = modifiers | InputEvent.BUTTON1_MASK;
+ }
+ if (swtEvent.button == 2 || (swtEvent.stateMask & SWT.BUTTON2) != 0) {
+ modifiers = modifiers | InputEvent.BUTTON2_MASK;
+ }
+ if (swtEvent.button == 3 || (swtEvent.stateMask & SWT.BUTTON3) != 0) {
+ modifiers = modifiers | InputEvent.BUTTON3_MASK;
+ }
+ }
+
+ return modifiers;
+ }
+
+ public int getModifiersEx() {
+ int modifiers = 0;
+
+ if (swtEvent != null) {
+ if ((swtEvent.stateMask & SWT.ALT) != 0) {
+ modifiers = modifiers | InputEvent.ALT_DOWN_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.CONTROL) != 0) {
+ modifiers = modifiers | InputEvent.CTRL_DOWN_MASK;
+ }
+ if ((swtEvent.stateMask & SWT.SHIFT) != 0) {
+ modifiers = modifiers | InputEvent.SHIFT_DOWN_MASK;
+ }
+ if (swtEvent.button == 1 || (swtEvent.stateMask & SWT.BUTTON1) != 0) {
+ modifiers = modifiers | InputEvent.BUTTON1_DOWN_MASK;
+ }
+ if (swtEvent.button == 2 || (swtEvent.stateMask & SWT.BUTTON2) != 0) {
+ modifiers = modifiers | InputEvent.BUTTON2_DOWN_MASK;
+ }
+ if (swtEvent.button == 3 || (swtEvent.stateMask & SWT.BUTTON3) != 0) {
+ modifiers = modifiers | InputEvent.BUTTON3_DOWN_MASK;
+ }
+ }
+
+ return modifiers;
+ }
+
+ // /////////////////////////
+ // THE SWT SPECIFIC EVENTS
+ // /////////////////////////
+
+ public Widget getWidget() {
+ return swtEvent.widget;
+ }
+
+ public Display getDisplay() {
+ return swtEvent.display;
+ }
+
+ public Object getData() {
+ return swtEvent.data;
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTPath.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTPath.java
index 3b9f750..cb8a559 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTPath.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTPath.java
@@ -49,387 +49,403 @@
import edu.umd.cs.piccolo.util.PPaintContext;
/**
- * PPath is a wrapper around a java.awt.geom.GeneralPath. The
- * setBounds method works by scaling the path to fit into the specified
- * bounds. This normally works well, but if the specified base bounds
- * get too small then it is impossible to expand the path shape again since
- * all its numbers have tended to zero, so application code may need to take
- * this into consideration.
+ * PPath is a wrapper around a java.awt.geom.GeneralPath. The setBounds
+ * method works by scaling the path to fit into the specified bounds. This
+ * normally works well, but if the specified base bounds get too small then it
+ * is impossible to expand the path shape again since all its numbers have
+ * tended to zero, so application code may need to take this into consideration.
*
- * One option that applications have is to call startResizeBounds
before
- * starting an interaction that may make the bounds very small, and calling
- * endResizeBounds
when this interaction is finished. When this is done
- * PPath will use a copy of the original path to do the resizing so the numbers
- * in the path wont loose resolution.
+ * One option that applications have is to call startResizeBounds
+ * before starting an interaction that may make the bounds very small, and
+ * calling endResizeBounds
when this interaction is finished. When
+ * this is done PPath will use a copy of the original path to do the resizing so
+ * the numbers in the path wont loose resolution.
*
- * This class also provides methods for constructing common shapes using a
+ * This class also provides methods for constructing common shapes using a
* general path.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PSWTPath extends PNode {
-
- /**
- * The property name that identifies a change of this node's path.
- * In any property change event the new value will be a reference to
- * this node's path, but old value will always be null.
- */
- public static final String PROPERTY_SHAPE = "shape";
- private static final double BOUNDS_TOLERANCE = 0.01;
- private static final Rectangle2D.Float TEMP_RECTANGLE = new Rectangle2D.Float();
- private static final RoundRectangle2D.Float TEMP_ROUNDRECTANGLE = new RoundRectangle2D.Float();
- private static final Ellipse2D.Float TEMP_ELLIPSE = new Ellipse2D.Float();
- private static final Color DEFAULT_STROKE_PAINT = Color.black;
- private static final BasicStroke BASIC_STROKE = new BasicStroke();
- private static final float PEN_WIDTH = 1f;
-
- private Paint strokePaint;
+ /**
+ * The property name that identifies a change of this node's path. In any
+ * property change event the new value will be a reference to this node's
+ * path, but old value will always be null.
+ */
+ public static final String PROPERTY_SHAPE = "shape";
- boolean updatingBoundsFromPath;
- Shape origShape;
- Shape shape;
-
- PAffineTransform internalXForm;
- AffineTransform inverseXForm;
-
- double[] shapePts;
+ private static final double BOUNDS_TOLERANCE = 0.01;
+ private static final Rectangle2D.Float TEMP_RECTANGLE = new Rectangle2D.Float();
+ private static final RoundRectangle2D.Float TEMP_ROUNDRECTANGLE = new RoundRectangle2D.Float();
+ private static final Ellipse2D.Float TEMP_ELLIPSE = new Ellipse2D.Float();
+ private static final Color DEFAULT_STROKE_PAINT = Color.black;
+ private static final BasicStroke BASIC_STROKE = new BasicStroke();
+ private static final float PEN_WIDTH = 1f;
- public static PSWTPath createRectangle(float x, float y, float width, float height) {
- TEMP_RECTANGLE.setFrame(x, y, width, height);
- PSWTPath result = new PSWTPath(TEMP_RECTANGLE);
- result.setPaint(Color.white);
- return result;
- }
-
- public static PSWTPath createRoundRectangle(float x, float y, float width, float height, float arcWidth, float arcHeight) {
- TEMP_ROUNDRECTANGLE.setRoundRect(x, y, width, height, arcWidth, arcHeight);
- PSWTPath result = new PSWTPath(TEMP_ROUNDRECTANGLE);
- result.setPaint(Color.white);
- return result;
- }
-
- public static PSWTPath createEllipse(float x, float y, float width, float height) {
- TEMP_ELLIPSE.setFrame(x, y, width, height);
- PSWTPath result = new PSWTPath(TEMP_ELLIPSE);
- result.setPaint(Color.white);
- return result;
- }
-
- public static PSWTPath createPolyline(Point2D[] points) {
- PSWTPath result = new PSWTPath();
- result.setPathToPolyline(points);
- result.setPaint(Color.white);
- return result;
- }
+ private Paint strokePaint;
- public static PSWTPath createPolyline(float[] xp, float[] yp) {
- PSWTPath result = new PSWTPath();
- result.setPathToPolyline(xp, yp);
- result.setPaint(Color.white);
- return result;
- }
-
- public PSWTPath() {
- strokePaint = DEFAULT_STROKE_PAINT;
- }
+ boolean updatingBoundsFromPath;
+ Shape origShape;
+ Shape shape;
- public PSWTPath(Shape aShape) {
- this();
- setShape(aShape);
- }
-
- //****************************************************************
- // Stroke
- //****************************************************************
-
- public Paint getStrokePaint() {
- return strokePaint;
- }
+ PAffineTransform internalXForm;
+ AffineTransform inverseXForm;
- public void setStrokeColor(Paint aPaint) {
- Paint old = strokePaint;
- strokePaint = aPaint;
- invalidatePaint();
- firePropertyChange(PPath.PROPERTY_CODE_STROKE_PAINT, PPath.PROPERTY_STROKE_PAINT, old, strokePaint);
- }
-
- /**
- * Set the bounds of this path. This method works by scaling the path
- * to fit into the specified bounds. This normally works well, but if
- * the specified base bounds get too small then it is impossible to
- * expand the path shape again since all its numbers have tended to zero,
- * so application code may need to take this into consideration.
- */
- protected void internalUpdateBounds(double x, double y, double width, double height) {
- if (updatingBoundsFromPath) return;
- if (origShape == null) return;
-
- Rectangle2D pathBounds = origShape.getBounds2D();
+ double[] shapePts;
- if (Math.abs(x-pathBounds.getX())/x < BOUNDS_TOLERANCE &&
- Math.abs(y-pathBounds.getY())/y < BOUNDS_TOLERANCE &&
- Math.abs(width-pathBounds.getWidth())/width < BOUNDS_TOLERANCE &&
- Math.abs(height-pathBounds.getHeight())/height < BOUNDS_TOLERANCE) {
- return;
- }
-
- if (internalXForm == null) {
- internalXForm = new PAffineTransform();
- }
- internalXForm.setToIdentity();
- internalXForm.translate(x, y);
- internalXForm.scale(width / pathBounds.getWidth(), height / pathBounds.getHeight());
- internalXForm.translate(-pathBounds.getX(), -pathBounds.getY());
-
- try {
- inverseXForm = internalXForm.createInverse();
- }
- catch (Exception e) {
- }
- }
+ public static PSWTPath createRectangle(float x, float y, float width, float height) {
+ TEMP_RECTANGLE.setFrame(x, y, width, height);
+ PSWTPath result = new PSWTPath(TEMP_RECTANGLE);
+ result.setPaint(Color.white);
+ return result;
+ }
-
- public boolean intersects(Rectangle2D aBounds) {
- if (super.intersects(aBounds)) {
-
- if (internalXForm != null) {
- aBounds = new PBounds(aBounds);
- internalXForm.inverseTransform(aBounds,aBounds);
- }
-
- if (getPaint() != null && shape.intersects(aBounds)) {
- return true;
- } else if (strokePaint != null) {
- return BASIC_STROKE.createStrokedShape(shape).intersects(aBounds);
- }
- }
- return false;
- }
-
- public void updateBoundsFromPath() {
- updatingBoundsFromPath = true;
-
- if (origShape == null) {
- resetBounds();
- } else {
- Rectangle2D b = origShape.getBounds2D();
-
- // Note that this pen width code does not really work for SWT since it assumes
- // that the pen width scales - in actuality it does not. However, the fix would
- // be to have volatile bounds for all shapes which isn't a nice alternative
- super.setBounds(b.getX()-PEN_WIDTH,
- b.getY()-PEN_WIDTH,
- b.getWidth()+2*PEN_WIDTH,
- b.getHeight()+2*PEN_WIDTH);
- }
- updatingBoundsFromPath = false;
- }
-
- //****************************************************************
- // Painting
- //****************************************************************
-
- protected void paint(PPaintContext paintContext) {
- Paint p = getPaint();
- SWTGraphics2D g2 = (SWTGraphics2D)paintContext.getGraphics();
-
- if (internalXForm != null) {
- g2.transform(internalXForm);
- }
-
- if (p != null) {
- g2.setBackground((Color)p);
+ public static PSWTPath createRoundRectangle(float x, float y, float width, float height, float arcWidth,
+ float arcHeight) {
+ TEMP_ROUNDRECTANGLE.setRoundRect(x, y, width, height, arcWidth, arcHeight);
+ PSWTPath result = new PSWTPath(TEMP_ROUNDRECTANGLE);
+ result.setPaint(Color.white);
+ return result;
+ }
- double lineWidth = g2.getTransformedLineWidth();
- if (shape instanceof Rectangle2D) {
- g2.fillRect(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth);
- }
- else if (shape instanceof Ellipse2D) {
- g2.fillOval(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth);
- }
- else if (shape instanceof Arc2D) {
- g2.fillArc(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth,shapePts[4],shapePts[5]);
- }
- else if (shape instanceof RoundRectangle2D) {
- g2.fillRoundRect(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth,shapePts[4],shapePts[5]);
- }
- else {
- g2.fillPolygon(shapePts);
- }
- }
-
- if (strokePaint != null) {
- g2.setColor((Color)strokePaint);
-
- double lineWidth = g2.getTransformedLineWidth();
- if (shape instanceof Rectangle2D) {
- g2.drawRect(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth);
- }
- else if (shape instanceof Ellipse2D) {
- g2.drawOval(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth);
- }
- else if (shape instanceof Arc2D) {
- g2.drawArc(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth,shapePts[4],shapePts[5]);
- }
- else if (shape instanceof RoundRectangle2D) {
- g2.drawRoundRect(shapePts[0]+lineWidth/2,shapePts[1]+lineWidth/2,shapePts[2]-lineWidth,shapePts[3]-lineWidth,shapePts[4],shapePts[5]);
- }
- else {
- // TODO The bounds may be incorrect for polylines at the moment - resulting in graphics turds at some scales
- g2.drawPolyline(shapePts);
- }
- }
-
- if (inverseXForm != null) {
- g2.transform(inverseXForm);
- }
- }
-
- public void setShape(Shape aShape) {
- this.shape = cloneShape(aShape);
- this.origShape = shape;
- updateShapePoints(aShape);
-
- firePropertyChange(PPath.PROPERTY_CODE_PATH, PPath.PROPERTY_PATH, null, shape);
- updateBoundsFromPath();
- invalidatePaint();
- }
+ public static PSWTPath createEllipse(float x, float y, float width, float height) {
+ TEMP_ELLIPSE.setFrame(x, y, width, height);
+ PSWTPath result = new PSWTPath(TEMP_ELLIPSE);
+ result.setPaint(Color.white);
+ return result;
+ }
- public void updateShapePoints(Shape aShape) {
- if (aShape instanceof Rectangle2D) {
- if (shapePts == null || shapePts.length < 4) {
- shapePts = new double[4];
- }
-
- shapePts[0] = ((Rectangle2D)shape).getX();
- shapePts[1] = ((Rectangle2D)shape).getY();
- shapePts[2] = ((Rectangle2D)shape).getWidth();
- shapePts[3] = ((Rectangle2D)shape).getHeight();
- }
- else if (aShape instanceof Ellipse2D) {
- if (shapePts == null || shapePts.length < 4) {
- shapePts = new double[4];
- }
+ public static PSWTPath createPolyline(Point2D[] points) {
+ PSWTPath result = new PSWTPath();
+ result.setPathToPolyline(points);
+ result.setPaint(Color.white);
+ return result;
+ }
- shapePts[0] = ((Ellipse2D)shape).getX();
- shapePts[1] = ((Ellipse2D)shape).getY();
- shapePts[2] = ((Ellipse2D)shape).getWidth();
- shapePts[3] = ((Ellipse2D)shape).getHeight();
- }
- else if (aShape instanceof Arc2D) {
- if (shapePts == null || shapePts.length < 6) {
- shapePts = new double[6];
- }
-
- shapePts[0] = ((Arc2D)shape).getX();
- shapePts[1] = ((Arc2D)shape).getY();
- shapePts[2] = ((Arc2D)shape).getWidth();
- shapePts[3] = ((Arc2D)shape).getHeight();
- shapePts[4] = ((Arc2D)shape).getAngleStart();
- shapePts[5] = ((Arc2D)shape).getAngleExtent();
- }
- else if (aShape instanceof RoundRectangle2D) {
- if (shapePts == null || shapePts.length < 6) {
- shapePts = new double[6];
- }
+ public static PSWTPath createPolyline(float[] xp, float[] yp) {
+ PSWTPath result = new PSWTPath();
+ result.setPathToPolyline(xp, yp);
+ result.setPaint(Color.white);
+ return result;
+ }
- shapePts[0] = ((RoundRectangle2D)shape).getX();
- shapePts[1] = ((RoundRectangle2D)shape).getY();
- shapePts[2] = ((RoundRectangle2D)shape).getWidth();
- shapePts[3] = ((RoundRectangle2D)shape).getHeight();
- shapePts[4] = ((RoundRectangle2D)shape).getArcWidth();
- shapePts[5] = ((RoundRectangle2D)shape).getArcHeight();
- }
- else {
- shapePts = SWTShapeManager.shapeToPolyline(shape);
- }
- }
+ public PSWTPath() {
+ strokePaint = DEFAULT_STROKE_PAINT;
+ }
- public Shape cloneShape(Shape aShape) {
- if (aShape instanceof Rectangle2D) {
- return new PBounds((Rectangle2D)aShape);
- }
- else if (aShape instanceof Ellipse2D) {
- Ellipse2D e2 = (Ellipse2D)aShape;
- return new Ellipse2D.Double(e2.getX(),e2.getY(),e2.getWidth(),e2.getHeight());
- }
- else if (aShape instanceof Arc2D) {
- Arc2D a2 = (Arc2D)aShape;
- return new Arc2D.Double(a2.getX(),a2.getY(),a2.getWidth(),a2.getHeight(),a2.getAngleStart(),a2.getAngleExtent(),a2.getArcType());
- }
- else if (aShape instanceof RoundRectangle2D) {
- RoundRectangle2D r2 = (RoundRectangle2D)aShape;
- return new RoundRectangle2D.Double(r2.getX(),r2.getY(),r2.getWidth(),r2.getHeight(),r2.getArcWidth(),r2.getArcHeight());
- }
- else if (aShape instanceof Line2D) {
- Line2D l2 = (Line2D)aShape;
- return new Line2D.Double(l2.getP1(),l2.getP2());
- }
- else {
- new Exception().printStackTrace();
- GeneralPath aPath = new GeneralPath();
- aPath.append(aShape,false);
- return aPath;
- }
- }
-
- public void setPathToRectangle(float x, float y, float width, float height) {
- TEMP_RECTANGLE.setFrame(x, y, width, height);
- setShape(TEMP_RECTANGLE);
- }
-
- public void setPathToRoundRectangle(float x, float y, float width, float height, float arcWidth, float arcHeight){
- TEMP_ROUNDRECTANGLE.setRoundRect(x, y, width, height, arcWidth, arcHeight);
- setShape(TEMP_ROUNDRECTANGLE);
- }
+ public PSWTPath(Shape aShape) {
+ this();
+ setShape(aShape);
+ }
- public void setPathToEllipse(float x, float y, float width, float height) {
- TEMP_ELLIPSE.setFrame(x, y, width, height);
- setShape(TEMP_ELLIPSE);
- }
+ // ****************************************************************
+ // Stroke
+ // ****************************************************************
- public void setPathToPolyline(Point2D[] points) {
- GeneralPath path = new GeneralPath();
- path.reset();
- path.moveTo((float)points[0].getX(), (float)points[0].getY());
- for (int i = 1; i < points.length; i++) {
- path.lineTo((float)points[i].getX(), (float)points[i].getY());
- }
- setShape(path);
- }
+ public Paint getStrokePaint() {
+ return strokePaint;
+ }
- public void setPathToPolyline(float[] xp, float[] yp) {
- GeneralPath path = new GeneralPath();
- path.reset();
- path.moveTo(xp[0], yp[0]);
- for (int i = 1; i < xp.length; i++) {
- path.lineTo(xp[i], yp[i]);
- }
- setShape(path);
- }
-
- //****************************************************************
- // Debugging - methods for debugging
- //****************************************************************
-
- /**
- * Returns a string representing the state of this node. This method is
- * intended to be used only for debugging purposes, and the content and
- * format of the returned string may vary between implementations. The
- * returned string may be empty but may not be null
.
- *
- * @return a string representation of this node's state
- */
- protected String paramString() {
- StringBuffer result = new StringBuffer();
+ public void setStrokeColor(Paint aPaint) {
+ Paint old = strokePaint;
+ strokePaint = aPaint;
+ invalidatePaint();
+ firePropertyChange(PPath.PROPERTY_CODE_STROKE_PAINT, PPath.PROPERTY_STROKE_PAINT, old, strokePaint);
+ }
- result.append("path=" + (shape == null ? "null" : shape.toString()));
- result.append(",strokePaint=" + (strokePaint == null ? "null" : strokePaint.toString()));
- result.append(',');
- result.append(super.paramString());
+ /**
+ * Set the bounds of this path. This method works by scaling the path to fit
+ * into the specified bounds. This normally works well, but if the specified
+ * base bounds get too small then it is impossible to expand the path shape
+ * again since all its numbers have tended to zero, so application code may
+ * need to take this into consideration.
+ */
+ protected void internalUpdateBounds(double x, double y, double width, double height) {
+ if (updatingBoundsFromPath)
+ return;
+ if (origShape == null)
+ return;
- return result.toString();
- }
+ Rectangle2D pathBounds = origShape.getBounds2D();
+
+ if (Math.abs(x - pathBounds.getX()) / x < BOUNDS_TOLERANCE
+ && Math.abs(y - pathBounds.getY()) / y < BOUNDS_TOLERANCE
+ && Math.abs(width - pathBounds.getWidth()) / width < BOUNDS_TOLERANCE
+ && Math.abs(height - pathBounds.getHeight()) / height < BOUNDS_TOLERANCE) {
+ return;
+ }
+
+ if (internalXForm == null) {
+ internalXForm = new PAffineTransform();
+ }
+ internalXForm.setToIdentity();
+ internalXForm.translate(x, y);
+ internalXForm.scale(width / pathBounds.getWidth(), height / pathBounds.getHeight());
+ internalXForm.translate(-pathBounds.getX(), -pathBounds.getY());
+
+ try {
+ inverseXForm = internalXForm.createInverse();
+ }
+ catch (Exception e) {
+ }
+ }
+
+ public boolean intersects(Rectangle2D aBounds) {
+ if (super.intersects(aBounds)) {
+
+ if (internalXForm != null) {
+ aBounds = new PBounds(aBounds);
+ internalXForm.inverseTransform(aBounds, aBounds);
+ }
+
+ if (getPaint() != null && shape.intersects(aBounds)) {
+ return true;
+ }
+ else if (strokePaint != null) {
+ return BASIC_STROKE.createStrokedShape(shape).intersects(aBounds);
+ }
+ }
+ return false;
+ }
+
+ public void updateBoundsFromPath() {
+ updatingBoundsFromPath = true;
+
+ if (origShape == null) {
+ resetBounds();
+ }
+ else {
+ Rectangle2D b = origShape.getBounds2D();
+
+ // Note that this pen width code does not really work for SWT since
+ // it assumes
+ // that the pen width scales - in actuality it does not. However,
+ // the fix would
+ // be to have volatile bounds for all shapes which isn't a nice
+ // alternative
+ super.setBounds(b.getX() - PEN_WIDTH, b.getY() - PEN_WIDTH, b.getWidth() + 2 * PEN_WIDTH, b.getHeight() + 2
+ * PEN_WIDTH);
+ }
+ updatingBoundsFromPath = false;
+ }
+
+ // ****************************************************************
+ // Painting
+ // ****************************************************************
+
+ protected void paint(PPaintContext paintContext) {
+ Paint p = getPaint();
+ SWTGraphics2D g2 = (SWTGraphics2D) paintContext.getGraphics();
+
+ if (internalXForm != null) {
+ g2.transform(internalXForm);
+ }
+
+ if (p != null) {
+ g2.setBackground((Color) p);
+
+ double lineWidth = g2.getTransformedLineWidth();
+ if (shape instanceof Rectangle2D) {
+ g2.fillRect(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth);
+ }
+ else if (shape instanceof Ellipse2D) {
+ g2.fillOval(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth);
+ }
+ else if (shape instanceof Arc2D) {
+ g2.fillArc(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth, shapePts[4], shapePts[5]);
+ }
+ else if (shape instanceof RoundRectangle2D) {
+ g2.fillRoundRect(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth, shapePts[4], shapePts[5]);
+ }
+ else {
+ g2.fillPolygon(shapePts);
+ }
+ }
+
+ if (strokePaint != null) {
+ g2.setColor((Color) strokePaint);
+
+ double lineWidth = g2.getTransformedLineWidth();
+ if (shape instanceof Rectangle2D) {
+ g2.drawRect(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth);
+ }
+ else if (shape instanceof Ellipse2D) {
+ g2.drawOval(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth);
+ }
+ else if (shape instanceof Arc2D) {
+ g2.drawArc(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth, shapePts[4], shapePts[5]);
+ }
+ else if (shape instanceof RoundRectangle2D) {
+ g2.drawRoundRect(shapePts[0] + lineWidth / 2, shapePts[1] + lineWidth / 2, shapePts[2] - lineWidth,
+ shapePts[3] - lineWidth, shapePts[4], shapePts[5]);
+ }
+ else {
+ // TODO The bounds may be incorrect for polylines at the moment
+ // - resulting in graphics turds at some scales
+ g2.drawPolyline(shapePts);
+ }
+ }
+
+ if (inverseXForm != null) {
+ g2.transform(inverseXForm);
+ }
+ }
+
+ public void setShape(Shape aShape) {
+ this.shape = cloneShape(aShape);
+ this.origShape = shape;
+ updateShapePoints(aShape);
+
+ firePropertyChange(PPath.PROPERTY_CODE_PATH, PPath.PROPERTY_PATH, null, shape);
+ updateBoundsFromPath();
+ invalidatePaint();
+ }
+
+ public void updateShapePoints(Shape aShape) {
+ if (aShape instanceof Rectangle2D) {
+ if (shapePts == null || shapePts.length < 4) {
+ shapePts = new double[4];
+ }
+
+ shapePts[0] = ((Rectangle2D) shape).getX();
+ shapePts[1] = ((Rectangle2D) shape).getY();
+ shapePts[2] = ((Rectangle2D) shape).getWidth();
+ shapePts[3] = ((Rectangle2D) shape).getHeight();
+ }
+ else if (aShape instanceof Ellipse2D) {
+ if (shapePts == null || shapePts.length < 4) {
+ shapePts = new double[4];
+ }
+
+ shapePts[0] = ((Ellipse2D) shape).getX();
+ shapePts[1] = ((Ellipse2D) shape).getY();
+ shapePts[2] = ((Ellipse2D) shape).getWidth();
+ shapePts[3] = ((Ellipse2D) shape).getHeight();
+ }
+ else if (aShape instanceof Arc2D) {
+ if (shapePts == null || shapePts.length < 6) {
+ shapePts = new double[6];
+ }
+
+ shapePts[0] = ((Arc2D) shape).getX();
+ shapePts[1] = ((Arc2D) shape).getY();
+ shapePts[2] = ((Arc2D) shape).getWidth();
+ shapePts[3] = ((Arc2D) shape).getHeight();
+ shapePts[4] = ((Arc2D) shape).getAngleStart();
+ shapePts[5] = ((Arc2D) shape).getAngleExtent();
+ }
+ else if (aShape instanceof RoundRectangle2D) {
+ if (shapePts == null || shapePts.length < 6) {
+ shapePts = new double[6];
+ }
+
+ shapePts[0] = ((RoundRectangle2D) shape).getX();
+ shapePts[1] = ((RoundRectangle2D) shape).getY();
+ shapePts[2] = ((RoundRectangle2D) shape).getWidth();
+ shapePts[3] = ((RoundRectangle2D) shape).getHeight();
+ shapePts[4] = ((RoundRectangle2D) shape).getArcWidth();
+ shapePts[5] = ((RoundRectangle2D) shape).getArcHeight();
+ }
+ else {
+ shapePts = SWTShapeManager.shapeToPolyline(shape);
+ }
+ }
+
+ public Shape cloneShape(Shape aShape) {
+ if (aShape instanceof Rectangle2D) {
+ return new PBounds((Rectangle2D) aShape);
+ }
+ else if (aShape instanceof Ellipse2D) {
+ Ellipse2D e2 = (Ellipse2D) aShape;
+ return new Ellipse2D.Double(e2.getX(), e2.getY(), e2.getWidth(), e2.getHeight());
+ }
+ else if (aShape instanceof Arc2D) {
+ Arc2D a2 = (Arc2D) aShape;
+ return new Arc2D.Double(a2.getX(), a2.getY(), a2.getWidth(), a2.getHeight(), a2.getAngleStart(), a2
+ .getAngleExtent(), a2.getArcType());
+ }
+ else if (aShape instanceof RoundRectangle2D) {
+ RoundRectangle2D r2 = (RoundRectangle2D) aShape;
+ return new RoundRectangle2D.Double(r2.getX(), r2.getY(), r2.getWidth(), r2.getHeight(), r2.getArcWidth(),
+ r2.getArcHeight());
+ }
+ else if (aShape instanceof Line2D) {
+ Line2D l2 = (Line2D) aShape;
+ return new Line2D.Double(l2.getP1(), l2.getP2());
+ }
+ else {
+ new Exception().printStackTrace();
+ GeneralPath aPath = new GeneralPath();
+ aPath.append(aShape, false);
+ return aPath;
+ }
+ }
+
+ public void setPathToRectangle(float x, float y, float width, float height) {
+ TEMP_RECTANGLE.setFrame(x, y, width, height);
+ setShape(TEMP_RECTANGLE);
+ }
+
+ public void setPathToRoundRectangle(float x, float y, float width, float height, float arcWidth, float arcHeight) {
+ TEMP_ROUNDRECTANGLE.setRoundRect(x, y, width, height, arcWidth, arcHeight);
+ setShape(TEMP_ROUNDRECTANGLE);
+ }
+
+ public void setPathToEllipse(float x, float y, float width, float height) {
+ TEMP_ELLIPSE.setFrame(x, y, width, height);
+ setShape(TEMP_ELLIPSE);
+ }
+
+ public void setPathToPolyline(Point2D[] points) {
+ GeneralPath path = new GeneralPath();
+ path.reset();
+ path.moveTo((float) points[0].getX(), (float) points[0].getY());
+ for (int i = 1; i < points.length; i++) {
+ path.lineTo((float) points[i].getX(), (float) points[i].getY());
+ }
+ setShape(path);
+ }
+
+ public void setPathToPolyline(float[] xp, float[] yp) {
+ GeneralPath path = new GeneralPath();
+ path.reset();
+ path.moveTo(xp[0], yp[0]);
+ for (int i = 1; i < xp.length; i++) {
+ path.lineTo(xp[i], yp[i]);
+ }
+ setShape(path);
+ }
+
+ // ****************************************************************
+ // Debugging - methods for debugging
+ // ****************************************************************
+
+ /**
+ * Returns a string representing the state of this node. This method is
+ * intended to be used only for debugging purposes, and the content and
+ * format of the returned string may vary between implementations. The
+ * returned string may be empty but may not be null
.
+ *
+ * @return a string representation of this node's state
+ */
+ protected String paramString() {
+ StringBuffer result = new StringBuffer();
+
+ result.append("path=" + (shape == null ? "null" : shape.toString()));
+ result.append(",strokePaint=" + (strokePaint == null ? "null" : strokePaint.toString()));
+ result.append(',');
+ result.append(super.paramString());
+
+ return result.toString();
+ }
}
\ No newline at end of file
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTRoot.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTRoot.java
index cb5e279..d4899cd 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTRoot.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTRoot.java
@@ -21,36 +21,37 @@
* thread. With the current setup only a single PSWTCanvas is expected to be
* connected to a root.
*
+ *
* @version 1.1
* @author Jesse Grosjean
*/
public class PSWTRoot extends PRoot {
- private Composite composite;
-
- public PSWTRoot(Composite composite) {
- this.composite = composite;
- }
+ private Composite composite;
- public Timer createTimer(int delay, ActionListener listener) {
- return new SWTTimer(composite.getDisplay(),delay,listener);
- }
+ public PSWTRoot(Composite composite) {
+ this.composite = composite;
+ }
- public void scheduleProcessInputsIfNeeded() {
- if (!Thread.currentThread().equals(composite.getDisplay().getThread())) {
- return;
- }
+ public Timer createTimer(int delay, ActionListener listener) {
+ return new SWTTimer(composite.getDisplay(), delay, listener);
+ }
- if (!processInputsScheduled && !processingInputs &&
- (getFullBoundsInvalid() || getChildBoundsInvalid() || getPaintInvalid() || getChildPaintInvalid())) {
+ public void scheduleProcessInputsIfNeeded() {
+ if (!Thread.currentThread().equals(composite.getDisplay().getThread())) {
+ return;
+ }
- processInputsScheduled = true;
- composite.getDisplay().asyncExec(new Runnable() {
- public void run() {
- processInputs();
- processInputsScheduled = false;
- }
- });
- }
- }
+ if (!processInputsScheduled && !processingInputs
+ && (getFullBoundsInvalid() || getChildBoundsInvalid() || getPaintInvalid() || getChildPaintInvalid())) {
+
+ processInputsScheduled = true;
+ composite.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ processInputs();
+ processInputsScheduled = false;
+ }
+ });
+ }
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTSelectionEventHandler.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTSelectionEventHandler.java
index ccfbb95..7d6d269 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTSelectionEventHandler.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTSelectionEventHandler.java
@@ -44,109 +44,113 @@
import edu.umd.cs.piccolox.event.PSelectionEventHandler;
/**
- * Modified to use SWT paths instead of normal paths
+ * Modified to use SWT paths instead of normal paths
+ *
* @version 1.0
* @author Lance Good
- */
+ */
public class PSWTSelectionEventHandler extends PSelectionEventHandler {
PSWTPath marquee;
PNode marqueeParent;
Point2D pressPt;
Point2D canvasPressPt;
-
+
/**
- * Creates a selection event handler.
- * @param marqueeParent The node to which the event handler dynamically adds a marquee
- * (temporarily) to represent the area being selected.
- * @param selectableParent The node whose children will be selected
- * by this event handler.
- */
- public PSWTSelectionEventHandler(PNode marqueeParent, PNode selectableParent) {
- super(new PNode(),selectableParent);
- this.marqueeParent = marqueeParent;
- }
+ * Creates a selection event handler.
+ *
+ * @param marqueeParent The node to which the event handler dynamically adds
+ * a marquee (temporarily) to represent the area being selected.
+ * @param selectableParent The node whose children will be selected by this
+ * event handler.
+ */
+ public PSWTSelectionEventHandler(PNode marqueeParent, PNode selectableParent) {
+ super(new PNode(), selectableParent);
+ this.marqueeParent = marqueeParent;
+ }
- /**
- * Creates a selection event handler.
- * @param marqueeParent The node to which the event handler dynamically adds a marquee
- * (temporarily) to represent the area being selected.
- * @param selectableParents A list of nodes whose children will be selected
- * by this event handler.
- */
- public PSWTSelectionEventHandler(PNode marqueeParent, List selectableParents) {
- super(new PNode(),selectableParents);
- this.marqueeParent = marqueeParent;
- }
+ /**
+ * Creates a selection event handler.
+ *
+ * @param marqueeParent The node to which the event handler dynamically adds
+ * a marquee (temporarily) to represent the area being selected.
+ * @param selectableParents A list of nodes whose children will be selected
+ * by this event handler.
+ */
+ public PSWTSelectionEventHandler(PNode marqueeParent, List selectableParents) {
+ super(new PNode(), selectableParents);
+ this.marqueeParent = marqueeParent;
+ }
- public void decorateSelectedNode(PNode node) {
- PSWTBoundsHandle.addBoundsHandlesTo(node);
- }
+ public void decorateSelectedNode(PNode node) {
+ PSWTBoundsHandle.addBoundsHandlesTo(node);
+ }
- public void undecorateSelectedNode(PNode node) {
- PSWTBoundsHandle.removeBoundsHandlesFrom(node);
- }
+ public void undecorateSelectedNode(PNode node) {
+ PSWTBoundsHandle.removeBoundsHandlesFrom(node);
+ }
- protected void initializeSelection(PInputEvent pie) {
- super.initializeSelection(pie);
- pressPt = pie.getPosition();
- canvasPressPt = pie.getCanvasPosition();
- }
-
- protected void initializeMarquee(PInputEvent e) {
- super.initializeMarquee(e);
-
- marquee = new PSWTPath(new Rectangle2D.Float((float)pressPt.getX(), (float)pressPt.getY(), 0, 0)) {
+ protected void initializeSelection(PInputEvent pie) {
+ super.initializeSelection(pie);
+ pressPt = pie.getPosition();
+ canvasPressPt = pie.getCanvasPosition();
+ }
+
+ protected void initializeMarquee(PInputEvent e) {
+ super.initializeMarquee(e);
+
+ marquee = new PSWTPath(new Rectangle2D.Float((float) pressPt.getX(), (float) pressPt.getY(), 0, 0)) {
protected void paint(PPaintContext paintContext) {
- SWTGraphics2D s2g = (SWTGraphics2D)paintContext.getGraphics();
+ SWTGraphics2D s2g = (SWTGraphics2D) paintContext.getGraphics();
s2g.gc.setLineStyle(SWT.LINE_DASH);
super.paint(paintContext);
s2g.gc.setLineStyle(SWT.LINE_SOLID);
}
- };
- marquee.setStrokeColor(Color.black);
- marquee.setPaint(null);
- marqueeParent.addChild(marquee);
- }
+ };
+ marquee.setStrokeColor(Color.black);
+ marquee.setPaint(null);
+ marqueeParent.addChild(marquee);
+ }
- protected void updateMarquee(PInputEvent pie) {
- super.updateMarquee(pie);
-
- PBounds b = new PBounds();
+ protected void updateMarquee(PInputEvent pie) {
+ super.updateMarquee(pie);
- if (marqueeParent instanceof PCamera) {
- b.add(canvasPressPt);
- b.add(pie.getCanvasPosition());
- }
- else {
- b.add(pressPt);
- b.add(pie.getPosition());
- }
+ PBounds b = new PBounds();
- marquee.setPathToRectangle((float) b.x, (float) b.y, (float) b.width, (float) b.height);
- b.reset();
- b.add(pressPt);
- b.add(pie.getPosition());
- }
+ if (marqueeParent instanceof PCamera) {
+ b.add(canvasPressPt);
+ b.add(pie.getCanvasPosition());
+ }
+ else {
+ b.add(pressPt);
+ b.add(pie.getPosition());
+ }
- protected PBounds getMarqueeBounds() {
- if (marquee != null) {
- return marquee.getBounds();
- }
- return new PBounds();
- }
+ marquee.setPathToRectangle((float) b.x, (float) b.y, (float) b.width, (float) b.height);
+ b.reset();
+ b.add(pressPt);
+ b.add(pie.getPosition());
+ }
- protected void endMarqueeSelection(PInputEvent e) {
- super.endMarqueeSelection(e);
-
- // Remove marquee
- marquee.removeFromParent();
- marquee = null;
- }
+ protected PBounds getMarqueeBounds() {
+ if (marquee != null) {
+ return marquee.getBounds();
+ }
+ return new PBounds();
+ }
- /**
- * This gets called continuously during the drag, and is used to animate the marquee
- */
- protected void dragActivityStep(PInputEvent aEvent) {
- }
+ protected void endMarqueeSelection(PInputEvent e) {
+ super.endMarqueeSelection(e);
+
+ // Remove marquee
+ marquee.removeFromParent();
+ marquee = null;
+ }
+
+ /**
+ * This gets called continuously during the drag, and is used to animate the
+ * marquee
+ */
+ protected void dragActivityStep(PInputEvent aEvent) {
+ }
}
\ No newline at end of file
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTStickyHandleManager.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTStickyHandleManager.java
index 3740fbd..8c04056 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTStickyHandleManager.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTStickyHandleManager.java
@@ -35,54 +35,54 @@
import edu.umd.cs.piccolo.util.PPickPath;
public class PSWTStickyHandleManager extends PNode {
-
- private PNode target;
- private PCamera camera;
-
- public PSWTStickyHandleManager(PCamera newCamera, PNode newTarget) {
- setCameraTarget(newCamera, newTarget);
- PSWTBoundsHandle.addBoundsHandlesTo(this);
- }
- public void setCameraTarget(PCamera newCamera, PNode newTarget) {
- camera = newCamera;
- camera.addChild(this);
- target = newTarget;
- }
-
- public boolean setBounds(double x, double y, double width, double height) {
- PBounds b = new PBounds(x, y, width, height);
- camera.localToGlobal(b);
- camera.localToView(b);
- target.globalToLocal(b);
- target.setBounds(b);
- return super.setBounds(x, y, width, height);
- }
-
- protected boolean getBoundsVolatile() {
- return true;
- }
+ private PNode target;
+ private PCamera camera;
- public PBounds getBoundsReference() {
- PBounds targetBounds = target.getFullBounds();
- camera.viewToLocal(targetBounds);
- camera.globalToLocal(targetBounds);
- PBounds bounds = super.getBoundsReference();
- bounds.setRect(targetBounds);
- return super.getBoundsReference();
- }
+ public PSWTStickyHandleManager(PCamera newCamera, PNode newTarget) {
+ setCameraTarget(newCamera, newTarget);
+ PSWTBoundsHandle.addBoundsHandlesTo(this);
+ }
- public void startResizeBounds() {
- super.startResizeBounds();
- target.startResizeBounds();
- }
+ public void setCameraTarget(PCamera newCamera, PNode newTarget) {
+ camera = newCamera;
+ camera.addChild(this);
+ target = newTarget;
+ }
- public void endResizeBounds() {
- super.endResizeBounds();
- target.endResizeBounds();
- }
+ public boolean setBounds(double x, double y, double width, double height) {
+ PBounds b = new PBounds(x, y, width, height);
+ camera.localToGlobal(b);
+ camera.localToView(b);
+ target.globalToLocal(b);
+ target.setBounds(b);
+ return super.setBounds(x, y, width, height);
+ }
- public boolean pickAfterChildren(PPickPath pickPath) {
- return false;
- }
+ protected boolean getBoundsVolatile() {
+ return true;
+ }
+
+ public PBounds getBoundsReference() {
+ PBounds targetBounds = target.getFullBounds();
+ camera.viewToLocal(targetBounds);
+ camera.globalToLocal(targetBounds);
+ PBounds bounds = super.getBoundsReference();
+ bounds.setRect(targetBounds);
+ return super.getBoundsReference();
+ }
+
+ public void startResizeBounds() {
+ super.startResizeBounds();
+ target.startResizeBounds();
+ }
+
+ public void endResizeBounds() {
+ super.endResizeBounds();
+ target.endResizeBounds();
+ }
+
+ public boolean pickAfterChildren(PPickPath pickPath) {
+ return false;
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTText.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTText.java
index 81eee7a..6e1c0d2 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTText.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/PSWTText.java
@@ -20,11 +20,11 @@
import edu.umd.cs.piccolo.util.PPaintContext;
/**
- * PSWTText creates a visual component to support text. Multiple lines can
- * be entered, and basic editing is supported. A caret is drawn,
- * and can be repositioned with mouse clicks. The text object is positioned
- * so that its upper-left corner is at the origin, though this can be changed
- * with the translate methods.
+ * PSWTText creates a visual component to support text. Multiple lines
+ * can be entered, and basic editing is supported. A caret is drawn, and can be
+ * repositioned with mouse clicks. The text object is positioned so that its
+ * upper-left corner is at the origin, though this can be changed with the
+ * translate methods.
*
* Warning: Serialized and ZSerialized objects of this class will not be
* compatible with future Jazz releases. The current serialization support is
@@ -37,80 +37,78 @@
/**
* Below this magnification render text as 'greek'.
*/
- static protected final double DEFAULT_GREEK_THRESHOLD = 5.5;
+ static protected final double DEFAULT_GREEK_THRESHOLD = 5.5;
/**
* Default color of text rendered as 'greek'.
*/
- static protected final Color DEFAULT_GREEK_COLOR = Color.gray;
+ static protected final Color DEFAULT_GREEK_COLOR = Color.gray;
/**
* Default font name of text.
*/
- static protected final String DEFAULT_FONT_NAME = "Helvetica";
+ static protected final String DEFAULT_FONT_NAME = "Helvetica";
/**
* Default font style for text.
*/
- static protected final int DEFAULT_FONT_STYLE = Font.PLAIN;
+ static protected final int DEFAULT_FONT_STYLE = Font.PLAIN;
/**
* Default font size for text.
*/
- static protected final int DEFAULT_FONT_SIZE = 12;
+ static protected final int DEFAULT_FONT_SIZE = 12;
/**
* Default font for text.
*/
- static protected final Font DEFAULT_FONT = new Font(DEFAULT_FONT_NAME, DEFAULT_FONT_STYLE, DEFAULT_FONT_SIZE);
+ static protected final Font DEFAULT_FONT = new Font(DEFAULT_FONT_NAME, DEFAULT_FONT_STYLE, DEFAULT_FONT_SIZE);
/**
* Default color for text.
*/
- static protected final Color DEFAULT_PEN_COLOR = Color.black;
+ static protected final Color DEFAULT_PEN_COLOR = Color.black;
/**
* Default text when new text area is created.
*/
- static protected final String DEFAULT_TEXT = "";
+ static protected final String DEFAULT_TEXT = "";
/**
* Default padding
*/
- static protected final int DEFAULT_PADDING = 2;
-
+ static protected final int DEFAULT_PADDING = 2;
+
/**
* Below this magnification text is rendered as greek.
*/
- protected double greekThreshold = DEFAULT_GREEK_THRESHOLD;
+ protected double greekThreshold = DEFAULT_GREEK_THRESHOLD;
/**
* Color for greek text.
*/
- protected Color greekColor = DEFAULT_GREEK_COLOR;
+ protected Color greekColor = DEFAULT_GREEK_COLOR;
/**
* Current pen color.
*/
- protected Color penColor = DEFAULT_PEN_COLOR;
+ protected Color penColor = DEFAULT_PEN_COLOR;
/**
* Current text font.
*/
- protected Font font = DEFAULT_FONT;
+ protected Font font = DEFAULT_FONT;
/**
* The amount of padding on each side of the text
*/
- protected int padding = DEFAULT_PADDING;
+ protected int padding = DEFAULT_PADDING;
-
/**
* Each vector element is one line of text.
*/
- protected ArrayList lines = new ArrayList();
+ protected ArrayList lines = new ArrayList();
-
/**
* Translation offset X.
*/
@@ -130,6 +128,7 @@
/**
* PSWTTest constructor with initial text.
+ *
* @param str The initial text.
*/
public PSWTText(String str) {
@@ -138,6 +137,7 @@
/**
* PSWTTest constructor with initial text and font.
+ *
* @param str The initial text.
* @param font The font for this PSWTText component.
*/
@@ -148,19 +148,24 @@
recomputeBounds();
}
- //****************************************************************************
+ //**************************************************************************
+ // **
//
- // Get/Set and pairs
+ // Get/Set and pairs
//
- //***************************************************************************
+ //**************************************************************************
+ // *
/**
* Returns the current pen color.
*/
- public Color getPenColor() {return penColor;}
+ public Color getPenColor() {
+ return penColor;
+ }
/**
* Sets the current pen color.
+ *
* @param color use this color.
*/
public void setPenColor(Color color) {
@@ -177,36 +182,41 @@
/**
* Sets the current pen paint.
+ *
* @param aPaint use this paint.
*/
public void setPenPaint(Paint aPaint) {
- penColor = (Color)aPaint;
+ penColor = (Color) aPaint;
}
/**
* Returns the current background color.
*/
public Color getBackgroundColor() {
- return (Color)getPaint();
+ return (Color) getPaint();
}
/**
* Sets the current background color.
+ *
* @param color use this color.
*/
public void setBackgroundColor(Color color) {
- super.setPaint(color);
+ super.setPaint(color);
}
/**
- * Returns the current greek threshold. Below this magnification
- * text is rendered as 'greek'.
+ * Returns the current greek threshold. Below this magnification text is
+ * rendered as 'greek'.
*/
- public double getGreekThreshold() {return greekThreshold;}
+ public double getGreekThreshold() {
+ return greekThreshold;
+ }
/**
- * Sets the current greek threshold. Below this magnification
- * text is rendered as 'greek'.
+ * Sets the current greek threshold. Below this magnification text is
+ * rendered as 'greek'.
+ *
* @param threshold compared to renderContext magnification.
*/
public void setGreekThreshold(double threshold) {
@@ -217,12 +227,13 @@
/**
* Returns the current font.
*/
- public Font getFont() {return font;}
+ public Font getFont() {
+ return font;
+ }
/**
- * Return the text within this text component.
- * Multline text is returned as a single string
- * where each line is separated by a newline character.
+ * Return the text within this text component. Multline text is returned as
+ * a single string where each line is separated by a newline character.
* Single line text does not have any newline characters.
*/
public String getText() {
@@ -230,11 +241,11 @@
String result = new String();
int lineNum = 0;
- for (Iterator i = lines.iterator() ; i.hasNext() ; ) {
+ for (Iterator i = lines.iterator(); i.hasNext();) {
if (lineNum > 0) {
result += '\n';
}
- line = (String)i.next();
+ line = (String) i.next();
result += line;
lineNum++;
}
@@ -245,23 +256,26 @@
/**
* Sets the font for the text.
*
- * Warning: Java has a serious bug in that it does not support very small
- * fonts. In particular, fonts that are less than about a pixel high just don't work.
- * Since in Jazz, it is common to create objects of arbitrary sizes, and then scale them,
- * an application can easily create a text object with a very small font by accident.
- * The workaround for this bug is to create a larger font for the text object, and
- * then scale the node down correspondingly.
+ * Warning: Java has a serious bug in that it does not support very
+ * small fonts. In particular, fonts that are less than about a pixel high
+ * just don't work. Since in Jazz, it is common to create objects of
+ * arbitrary sizes, and then scale them, an application can easily create a
+ * text object with a very small font by accident. The workaround for this
+ * bug is to create a larger font for the text object, and then scale the
+ * node down correspondingly.
+ *
* @param aFont use this font.
*/
public void setFont(Font aFont) {
font = aFont;
- recomputeBounds();
+ recomputeBounds();
}
/**
- * Sets the text of this visual component to str. Multiple lines
- * of text are separated by a newline character.
+ * Sets the text of this visual component to str. Multiple lines of text are
+ * separated by a newline character.
+ *
* @param str use this string.
*/
public void setText(String str) {
@@ -274,17 +288,19 @@
if (index == -1) {
lines.add(str);
done = true;
- } else {
+ }
+ else {
lines.add(str.substring(0, index));
str = str.substring(index + 1);
}
} while (!done);
- recomputeBounds();
+ recomputeBounds();
}
/**
* Set text translation offset X.
+ *
* @param x the X translation.
*/
public void setTranslateX(double x) {
@@ -293,6 +309,7 @@
/**
* Get the X offset translation.
+ *
* @return the X translation.
*/
public double getTranslateX() {
@@ -301,6 +318,7 @@
/**
* Set text translation offset Y.
+ *
* @param y the Y translation.
*/
public void setTranslateY(double y) {
@@ -309,6 +327,7 @@
/**
* Get the Y offset translation.
+ *
* @return the Y translation.
*/
public double getTranslateY() {
@@ -317,6 +336,7 @@
/**
* Set the text translation offset to the specified position.
+ *
* @param x the X-coord of translation
* @param y the Y-coord of translation
*/
@@ -324,11 +344,12 @@
translateX = x;
translateY = y;
- recomputeBounds();
+ recomputeBounds();
}
/**
* Set the text translation offset to point p.
+ *
* @param p The translation offset.
*/
public void setTranslation(Point2D p) {
@@ -337,6 +358,7 @@
/**
* Get the text translation offset.
+ *
* @return The translation offset.
*/
public Point2D getTranslation() {
@@ -347,12 +369,13 @@
/**
* Renders the text object.
*
- * 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 Jazz. 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 Jazz. This object
+ * should set those things if they are used, but they do not need to be
+ * restored.
+ *
* @param ppc Contains information about current render.
*/
public void paint(PPaintContext ppc) {
@@ -367,17 +390,17 @@
translated = true;
}
- // If font too small and not antialiased, then greek
+ // If font too small and not antialiased, then greek
double renderedFontSize = font.getSize() * ppc.getScale();
- // BBB: HACK ALERT - July 30, 1999
- // This is a workaround for a bug in Sun JDK 1.2.2 where
- // fonts that are rendered at very small magnifications show up big!
- // So, we render as greek if requested (that's normal)
- // OR if the font is very small (that's the workaround)
- if ((renderedFontSize < 0.5) ||
- (renderedFontSize < greekThreshold)) {
+ // BBB: HACK ALERT - July 30, 1999
+ // This is a workaround for a bug in Sun JDK 1.2.2 where
+ // fonts that are rendered at very small magnifications show up big!
+ // So, we render as greek if requested (that's normal)
+ // OR if the font is very small (that's the workaround)
+ if ((renderedFontSize < 0.5) || (renderedFontSize < greekThreshold)) {
paintAsGreek(ppc);
- } else {
+ }
+ else {
paintAsText(ppc);
}
if (translated) {
@@ -388,47 +411,50 @@
/**
* Paints this object as greek.
+ *
* @param ppc The graphics context to paint into.
*/
public void paintAsGreek(PPaintContext ppc) {
- Graphics2D g2 = ppc.getGraphics();
+ Graphics2D g2 = ppc.getGraphics();
- if (greekColor != null) {
- g2.setBackground(greekColor);
- ((SWTGraphics2D)g2).fillRect(0,0,getWidth(),getHeight());
- }
+ if (greekColor != null) {
+ g2.setBackground(greekColor);
+ ((SWTGraphics2D) g2).fillRect(0, 0, getWidth(), getHeight());
+ }
}
/**
- * Paints this object normally (show it's text).
- * Note that the entire text gets rendered so that it's upper
- * left corner appears at the origin of this local object.
+ * Paints this object normally (show it's text). Note that the entire text
+ * gets rendered so that it's upper left corner appears at the origin of
+ * this local object.
+ *
* @param ppc The graphics context to paint into.
*/
public void paintAsText(PPaintContext ppc) {
- SWTGraphics2D sg2 = (SWTGraphics2D)ppc.getGraphics();
-
- if (getPaint() != null) {
- sg2.setBackground((Color)getPaint());
+ SWTGraphics2D sg2 = (SWTGraphics2D) ppc.getGraphics();
+
+ if (getPaint() != null) {
+ sg2.setBackground((Color) getPaint());
Rectangle2D rect = new Rectangle2D.Double(0.0, 0.0, getWidth(), getHeight());
- sg2.fillRect(rect.getX(),rect.getY(),rect.getWidth(),rect.getHeight());
+ sg2.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
}
+ sg2.translate(padding, padding);
- sg2.translate(padding,padding);
+ double scale = Math.min(sg2.getTransform().getScaleX(), sg2.getTransform().getScaleY());
+ double dSize = scale * font.getSize();
+ double fixupScale = Math.floor(dSize) / dSize;
- double scale = Math.min(sg2.getTransform().getScaleX(),sg2.getTransform().getScaleY());
- double dSize = scale*font.getSize();
- double fixupScale = Math.floor(dSize)/dSize;
-
- // This moves the text size down to the next closest integer size - to help it stay in
- // it's alloted bounds. This is because SWT only supports integer font metrics
- sg2.scale(fixupScale,fixupScale);
-
-
- // Render each line of text
- // Note that the entire text gets rendered so that it's upper left corner
- // appears at the origin of this local object.
+ // This moves the text size down to the next closest integer size - to
+ // help it stay in
+ // it's alloted bounds. This is because SWT only supports integer font
+ // metrics
+ sg2.scale(fixupScale, fixupScale);
+
+ // Render each line of text
+ // Note that the entire text gets rendered so that it's upper left
+ // corner
+ // appears at the origin of this local object.
sg2.setColor(penColor);
sg2.setFont(font);
@@ -436,88 +462,89 @@
String line;
double y;
- FontMetrics metrics = sg2.getSWTFontMetrics();
+ FontMetrics metrics = sg2.getSWTFontMetrics();
- for (Iterator i = lines.iterator() ; i.hasNext() ; ) {
- line = (String)i.next();
+ for (Iterator i = lines.iterator(); i.hasNext();) {
+ line = (String) i.next();
- // ADDED BY LEG ON 2/25/03 - BUG CAUSING PROBLEMS AT CERTAIN
- // SCALES WHEN LINE WAS EMPTY
- line = (line.equals("")) ? " " : line;
+ // ADDED BY LEG ON 2/25/03 - BUG CAUSING PROBLEMS AT CERTAIN
+ // SCALES WHEN LINE WAS EMPTY
+ line = (line.equals("")) ? " " : line;
y = (lineNum * metrics.getHeight());
- sg2.drawString(line, (double)0, (double)y);
+ sg2.drawString(line, (double) 0, (double) y);
lineNum++;
}
-
- sg2.scale(1/fixupScale,1/fixupScale);
-
- sg2.translate(-padding,-padding);
+
+ sg2.scale(1 / fixupScale, 1 / fixupScale);
+
+ sg2.translate(-padding, -padding);
}
/**
- * Notifies this object that it has changed and that it
- * should update its notion of its bounding box.
+ * Notifies this object that it has changed and that it should update its
+ * notion of its bounding box.
*/
protected void recomputeBounds() {
- Point bds;
+ Point bds;
double lineWidth;
double maxWidth = 0.0;
double height;
- height = 0.0;
+ height = 0.0;
boolean hasText = true;
- if ((lines.size() == 1) && (((String)lines.get(0)).equals(""))) {
+ if ((lines.size() == 1) && (((String) lines.get(0)).equals(""))) {
hasText = false;
}
- GC gc = new GC(Display.getDefault());
- SWTGraphics2D g2 = new SWTGraphics2D(gc,Display.getDefault());
- g2.setFont(font);
- FontMetrics fm = g2.getSWTFontMetrics();
-
+ GC gc = new GC(Display.getDefault());
+ SWTGraphics2D g2 = new SWTGraphics2D(gc, Display.getDefault());
+ g2.setFont(font);
+ FontMetrics fm = g2.getSWTFontMetrics();
+
if (!lines.isEmpty() && hasText) {
String line;
int lineNum = 0;
- for (Iterator i = lines.iterator() ; i.hasNext() ; ) {
- line = (String)i.next();
+ for (Iterator i = lines.iterator(); i.hasNext();) {
+ line = (String) i.next();
-
- // Find the longest line in the text
- bds = gc.stringExtent(line);
- lineWidth = bds.x;
+ // Find the longest line in the text
+ bds = gc.stringExtent(line);
+ lineWidth = bds.x;
if (lineWidth > maxWidth) {
maxWidth = lineWidth;
}
- // Find the heighest line in the text
+ // Find the heighest line in the text
if (lineNum == 0) {
- height += fm.getAscent()+fm.getDescent()+fm.getLeading();
- } else {
+ height += fm.getAscent() + fm.getDescent() + fm.getLeading();
+ }
+ else {
height += fm.getHeight();
}
lineNum++;
}
- } else {
- // If no text, then we want to have the bounds of a space character,
- // so get those bounds here
- bds = gc.stringExtent(" ");
+ }
+ else {
+ // If no text, then we want to have the bounds of a space character,
+ // so get those bounds here
+ bds = gc.stringExtent(" ");
maxWidth = bds.x;
height = bds.y;
}
- gc.dispose();
+ gc.dispose();
- // Finally, set the bounds of this text
- setBounds(translateX,translateY,maxWidth+2*DEFAULT_PADDING,height+2*DEFAULT_PADDING);
+ // Finally, set the bounds of this text
+ setBounds(translateX, translateY, maxWidth + 2 * DEFAULT_PADDING, height + 2 * DEFAULT_PADDING);
}
- protected void internalUpdateBounds(double x, double y, double width, double height) {
- recomputeBounds();
- }
-
+ protected void internalUpdateBounds(double x, double y, double width, double height) {
+ recomputeBounds();
+ }
+
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTGraphics2D.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTGraphics2D.java
index 821e236..0e7fef6 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTGraphics2D.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTGraphics2D.java
@@ -38,905 +38,924 @@
import org.eclipse.swt.graphics.GC;
/**
- * An extension to Graphics2D to support an SWT Piccolo Canvas with little modification to the current Piccolo architecture
+ * An extension to Graphics2D to support an SWT Piccolo Canvas with little
+ * modification to the current Piccolo architecture
*
- * There is an outstanding SWT bug request #33319 for more efficient polyline/polygon rendering methods. It also appears that
- * most of the code below could be made obselete by bug fix #6490
+ * There is an outstanding SWT bug request #33319 for more efficient
+ * polyline/polygon rendering methods. It also appears that most of the code
+ * below could be made obselete by bug fix #6490
*
- * A lot of this may also be duplicated in GEF - the eclipse Graphical Editor Framework
+ * A lot of this may also be duplicated in GEF - the eclipse Graphical Editor
+ * Framework
*
* @author Lance Good
*/
public class SWTGraphics2D extends Graphics2D {
- protected static int CACHE_COUNT = 0;
- protected static HashMap FONT_CACHE = new HashMap();
- protected static HashMap COLOR_CACHE = new HashMap();
- protected static HashMap SHAPE_CACHE = new HashMap();
- protected static BufferedImage BUFFER = new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB);
+ protected static int CACHE_COUNT = 0;
+ protected static HashMap FONT_CACHE = new HashMap();
+ protected static HashMap COLOR_CACHE = new HashMap();
+ protected static HashMap SHAPE_CACHE = new HashMap();
+ protected static BufferedImage BUFFER = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
- static Point PT = new Point();
- static Rectangle2D RECT = new Rectangle2D.Double();
- static Rectangle2D LINE_RECT = new Rectangle2D.Double();
- static org.eclipse.swt.graphics.Rectangle SWT_RECT = new org.eclipse.swt.graphics.Rectangle(0,0,0,0);
+ static Point PT = new Point();
+ static Rectangle2D RECT = new Rectangle2D.Double();
+ static Rectangle2D LINE_RECT = new Rectangle2D.Double();
+ static org.eclipse.swt.graphics.Rectangle SWT_RECT = new org.eclipse.swt.graphics.Rectangle(0, 0, 0, 0);
- protected GC gc;
- protected Device device;
- protected AffineTransform transform = new AffineTransform();
- protected org.eclipse.swt.graphics.Font curFont;
- protected double lineWidth = 1.0;
+ protected GC gc;
+ protected Device device;
+ protected AffineTransform transform = new AffineTransform();
+ protected org.eclipse.swt.graphics.Font curFont;
+ protected double lineWidth = 1.0;
- /**
- * Constructor for SWTGraphics2D.
- */
- public SWTGraphics2D(GC gc, Device device) {
- super();
-
- this.gc = gc;
- this.device = device;
- }
+ /**
+ * Constructor for SWTGraphics2D.
+ */
+ public SWTGraphics2D(GC gc, Device device) {
+ super();
- ////////////////////
- // GET CLIP
- ////////////////////
+ this.gc = gc;
+ this.device = device;
+ }
- /**
- * @see java.awt.Graphics#getClipBounds()
- */
- public Rectangle getClipBounds() {
- org.eclipse.swt.graphics.Rectangle rect = gc.getClipping();
- Rectangle aRect = new Rectangle(rect.x,rect.y,rect.width,rect.height);
- try {
- SWTShapeManager.transform(aRect,transform.createInverse());
- } catch (Exception e) {e.printStackTrace();}
- return aRect;
- }
+ // //////////////////
+ // GET CLIP
+ // //////////////////
- public void clipRect(int x, int y, int width, int height) {
- RECT.setRect(x,y,width,height);
- SWTShapeManager.transform(RECT,transform);
- SWTShapeManager.awtToSWT(RECT,SWT_RECT);
-
- org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
- clip = clip.intersection(SWT_RECT);
-
- gc.setClipping(clip);
- }
+ /**
+ * @see java.awt.Graphics#getClipBounds()
+ */
+ public Rectangle getClipBounds() {
+ org.eclipse.swt.graphics.Rectangle rect = gc.getClipping();
+ Rectangle aRect = new Rectangle(rect.x, rect.y, rect.width, rect.height);
+ try {
+ SWTShapeManager.transform(aRect, transform.createInverse());
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ return aRect;
+ }
- public void setClip(int x, int y, int width, int height) {
- RECT.setRect(x,y,width,height);
- SWTShapeManager.transform(RECT,transform);
- SWTShapeManager.awtToSWT(RECT,SWT_RECT);
-
- gc.setClipping(SWT_RECT);
- }
+ public void clipRect(int x, int y, int width, int height) {
+ RECT.setRect(x, y, width, height);
+ SWTShapeManager.transform(RECT, transform);
+ SWTShapeManager.awtToSWT(RECT, SWT_RECT);
- /**
- * This method isn't really supported by SWT - so will use the shape bounds
- */
- public void clip(Shape s) {
- Rectangle2D clipBds = s.getBounds2D();
- SWTShapeManager.transform(clipBds,transform);
- SWTShapeManager.awtToSWT(clipBds,SWT_RECT);
+ org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
+ clip = clip.intersection(SWT_RECT);
- org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
- clip = clip.intersection(SWT_RECT);
-
- gc.setClipping(SWT_RECT);
- }
+ gc.setClipping(clip);
+ }
- /**
- * This method isn't really supported by SWT - so will use the shape bounds
- */
- public void setClip(Shape clip) {
- if (clip == null) {
- gc.setClipping((org.eclipse.swt.graphics.Rectangle)null);
- }
- else {
- Rectangle2D clipBds = clip.getBounds2D();
- SWTShapeManager.transform(clipBds,transform);
- SWTShapeManager.awtToSWT(clipBds,SWT_RECT);
-
- gc.setClipping(SWT_RECT);
- }
- }
-
- public Shape getClip() {
- org.eclipse.swt.graphics.Rectangle rect = gc.getClipping();
- Rectangle2D aRect = new Rectangle2D.Double(rect.x,rect.y,rect.width,rect.height);
- try {
- SWTShapeManager.transform(aRect,transform.createInverse());
- } catch (Exception e) {e.printStackTrace();}
- return aRect;
- }
+ public void setClip(int x, int y, int width, int height) {
+ RECT.setRect(x, y, width, height);
+ SWTShapeManager.transform(RECT, transform);
+ SWTShapeManager.awtToSWT(RECT, SWT_RECT);
- /////////////////////
- // DEVICE SPECIFIC
- /////////////////////
-
+ gc.setClipping(SWT_RECT);
+ }
- public GraphicsConfiguration getDeviceConfiguration() {
- return ((Graphics2D)BUFFER.getGraphics()).getDeviceConfiguration();
- }
+ /**
+ * This method isn't really supported by SWT - so will use the shape bounds
+ */
+ public void clip(Shape s) {
+ Rectangle2D clipBds = s.getBounds2D();
+ SWTShapeManager.transform(clipBds, transform);
+ SWTShapeManager.awtToSWT(clipBds, SWT_RECT);
+ org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
+ clip = clip.intersection(SWT_RECT);
- ////////////////
- // COLOR METHODS
- ////////////////
+ gc.setClipping(SWT_RECT);
+ }
- public Paint getPaint() {
- return getColor();
- }
+ /**
+ * This method isn't really supported by SWT - so will use the shape bounds
+ */
+ public void setClip(Shape clip) {
+ if (clip == null) {
+ gc.setClipping((org.eclipse.swt.graphics.Rectangle) null);
+ }
+ else {
+ Rectangle2D clipBds = clip.getBounds2D();
+ SWTShapeManager.transform(clipBds, transform);
+ SWTShapeManager.awtToSWT(clipBds, SWT_RECT);
- public void setPaint(Paint paint) {
- if (paint instanceof Color) {
- setColor((Color)paint);
- }
- }
+ gc.setClipping(SWT_RECT);
+ }
+ }
- public Color getColor() {
- org.eclipse.swt.graphics.Color color = gc.getForeground();
- Color awtColor = new Color(color.getRed(),color.getGreen(),color.getBlue());
- return awtColor;
- }
+ public Shape getClip() {
+ org.eclipse.swt.graphics.Rectangle rect = gc.getClipping();
+ Rectangle2D aRect = new Rectangle2D.Double(rect.x, rect.y, rect.width, rect.height);
+ try {
+ SWTShapeManager.transform(aRect, transform.createInverse());
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ return aRect;
+ }
- public void setColor(Color c) {
- org.eclipse.swt.graphics.Color cachedColor = (org.eclipse.swt.graphics.Color)COLOR_CACHE.get(c);
- if (cachedColor == null) {
- cachedColor = new org.eclipse.swt.graphics.Color(device,c.getRed(),c.getGreen(),c.getBlue());
- COLOR_CACHE.put(c,cachedColor);
- }
- gc.setForeground(cachedColor);
- }
+ // ///////////////////
+ // DEVICE SPECIFIC
+ // ///////////////////
- public void setColor(org.eclipse.swt.graphics.Color c) {
- gc.setForeground(c);
- }
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return ((Graphics2D) BUFFER.getGraphics()).getDeviceConfiguration();
+ }
- public void setBackground(Color c) {
- org.eclipse.swt.graphics.Color cachedColor = (org.eclipse.swt.graphics.Color)COLOR_CACHE.get(c);
- if (cachedColor == null) {
- cachedColor = new org.eclipse.swt.graphics.Color(device,c.getRed(),c.getGreen(),c.getBlue());
- COLOR_CACHE.put(c,cachedColor);
- }
- gc.setBackground(cachedColor);
- }
+ // //////////////
+ // COLOR METHODS
+ // //////////////
- public void setBackground(org.eclipse.swt.graphics.Color c) {
- gc.setBackground(c);
- }
+ public Paint getPaint() {
+ return getColor();
+ }
- public Color getBackground() {
- org.eclipse.swt.graphics.Color color = gc.getBackground();
- Color awtColor = new Color(color.getRed(),color.getGreen(),color.getBlue());
- return awtColor;
- }
+ public void setPaint(Paint paint) {
+ if (paint instanceof Color) {
+ setColor((Color) paint);
+ }
+ }
- ////////////////
- // FONT METHODS
- ////////////////
+ public Color getColor() {
+ org.eclipse.swt.graphics.Color color = gc.getForeground();
+ Color awtColor = new Color(color.getRed(), color.getGreen(), color.getBlue());
+ return awtColor;
+ }
- public org.eclipse.swt.graphics.Font getSWTFont() {
- return curFont;
- }
-
- public org.eclipse.swt.graphics.FontMetrics getSWTFontMetrics() {
- gc.setFont(curFont);
- return gc.getFontMetrics();
- }
+ public void setColor(Color c) {
+ org.eclipse.swt.graphics.Color cachedColor = (org.eclipse.swt.graphics.Color) COLOR_CACHE.get(c);
+ if (cachedColor == null) {
+ cachedColor = new org.eclipse.swt.graphics.Color(device, c.getRed(), c.getGreen(), c.getBlue());
+ COLOR_CACHE.put(c, cachedColor);
+ }
+ gc.setForeground(cachedColor);
+ }
- public Font getFont() {
- if (curFont != null) {
- int style = Font.PLAIN;
-
- FontData[] fd = curFont.getFontData();
- if (fd.length > 0) {
- if ((fd[0].getStyle() & SWT.BOLD) != 0) {
- style = style | Font.BOLD;
- }
- if ((fd[0].getStyle() & SWT.ITALIC) != 0) {
- style = style | SWT.ITALIC;
- }
-
- return new Font(fd[0].getName(),style,fd[0].height);
- }
- return null;
- }
- else {
- return null;
- }
- }
+ public void setColor(org.eclipse.swt.graphics.Color c) {
+ gc.setForeground(c);
+ }
- public void setFont(Font font) {
- String fontString = "name="+font.getFamily()+";bold="+font.isBold()+";italic="+font.isItalic()+";size="+font.getSize();
-
- curFont = getFont(fontString);
- }
+ public void setBackground(Color c) {
+ org.eclipse.swt.graphics.Color cachedColor = (org.eclipse.swt.graphics.Color) COLOR_CACHE.get(c);
+ if (cachedColor == null) {
+ cachedColor = new org.eclipse.swt.graphics.Color(device, c.getRed(), c.getGreen(), c.getBlue());
+ COLOR_CACHE.put(c, cachedColor);
+ }
+ gc.setBackground(cachedColor);
+ }
- public void setFont(org.eclipse.swt.graphics.Font font) {
- curFont = font;
- }
+ public void setBackground(org.eclipse.swt.graphics.Color c) {
+ gc.setBackground(c);
+ }
- public org.eclipse.swt.graphics.Font getFont(String fontString) {
- org.eclipse.swt.graphics.Font cachedFont = (org.eclipse.swt.graphics.Font)FONT_CACHE.get(fontString);
- if (cachedFont == null) {
- int style = 0;
- if (fontString.indexOf("bold=true") != -1) {
- style = style | SWT.BOLD;
- }
- if (fontString.indexOf("italic=true") != -1) {
- style = style | SWT.ITALIC;
- }
-
- String name = fontString.substring(0,fontString.indexOf(";"));
- String size = fontString.substring(fontString.lastIndexOf(";")+1,fontString.length());
- int sizeInt = 12;
- try {
- sizeInt = Integer.parseInt(size.substring(size.indexOf("=")+1,size.length()));
- }
- catch (Exception e) {e.printStackTrace();}
-
- cachedFont = new org.eclipse.swt.graphics.Font(device,name.substring(name.indexOf("=")+1,name.length()),sizeInt,style);
- FONT_CACHE.put(fontString,cachedFont);
- }
- return cachedFont;
- }
+ public Color getBackground() {
+ org.eclipse.swt.graphics.Color color = gc.getBackground();
+ Color awtColor = new Color(color.getRed(), color.getGreen(), color.getBlue());
+ return awtColor;
+ }
- protected org.eclipse.swt.graphics.Font getTransformedFont() {
- if (curFont != null) {
- FontData fontData = curFont.getFontData()[0];
- int height = fontData.getHeight();
- RECT.setRect(0,0,height,height);
- SWTShapeManager.transform(RECT,transform);
- height = (int)(RECT.getHeight()+0.5);
-
- String fontString = "name="+fontData.getName()+";bold="+((fontData.getStyle() & SWT.BOLD) != 0)+";italic="+((fontData.getStyle() & SWT.ITALIC) != 0)+";size="+height;
- return getFont(fontString);
- }
- return null;
- }
+ // //////////////
+ // FONT METHODS
+ // //////////////
- ///////////////////////////
- // AFFINE TRANSFORM METHODS
- ///////////////////////////
+ public org.eclipse.swt.graphics.Font getSWTFont() {
+ return curFont;
+ }
- public void translate(int x, int y) {
- transform.translate(x,y);
- }
+ public org.eclipse.swt.graphics.FontMetrics getSWTFontMetrics() {
+ gc.setFont(curFont);
+ return gc.getFontMetrics();
+ }
- public void translate(double tx, double ty) {
- transform.translate(tx,ty);
- }
+ public Font getFont() {
+ if (curFont != null) {
+ int style = Font.PLAIN;
- public void rotate(double theta) {
- transform.rotate(theta);
- }
+ FontData[] fd = curFont.getFontData();
+ if (fd.length > 0) {
+ if ((fd[0].getStyle() & SWT.BOLD) != 0) {
+ style = style | Font.BOLD;
+ }
+ if ((fd[0].getStyle() & SWT.ITALIC) != 0) {
+ style = style | SWT.ITALIC;
+ }
- public void rotate(double theta, double x, double y) {
- transform.rotate(theta,x,y);
- }
+ return new Font(fd[0].getName(), style, fd[0].height);
+ }
+ return null;
+ }
+ else {
+ return null;
+ }
+ }
- public void scale(double sx, double sy) {
- transform.scale(sx,sy);
- }
+ public void setFont(Font font) {
+ String fontString = "name=" + font.getFamily() + ";bold=" + font.isBold() + ";italic=" + font.isItalic()
+ + ";size=" + font.getSize();
- public void shear(double shx, double shy) {
- transform.shear(shx,shy);
- }
+ curFont = getFont(fontString);
+ }
- public void transform(AffineTransform Tx) {
- transform.concatenate(Tx);
- }
+ public void setFont(org.eclipse.swt.graphics.Font font) {
+ curFont = font;
+ }
- public void setTransform(AffineTransform Tx) {
- transform = (AffineTransform)Tx.clone();
- }
+ public org.eclipse.swt.graphics.Font getFont(String fontString) {
+ org.eclipse.swt.graphics.Font cachedFont = (org.eclipse.swt.graphics.Font) FONT_CACHE.get(fontString);
+ if (cachedFont == null) {
+ int style = 0;
+ if (fontString.indexOf("bold=true") != -1) {
+ style = style | SWT.BOLD;
+ }
+ if (fontString.indexOf("italic=true") != -1) {
+ style = style | SWT.ITALIC;
+ }
- public AffineTransform getTransform() {
- return (AffineTransform)transform.clone();
- }
+ String name = fontString.substring(0, fontString.indexOf(";"));
+ String size = fontString.substring(fontString.lastIndexOf(";") + 1, fontString.length());
+ int sizeInt = 12;
+ try {
+ sizeInt = Integer.parseInt(size.substring(size.indexOf("=") + 1, size.length()));
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
- ///////////////////////////////
- // DRAWING AND FILLING METHODS
- ///////////////////////////////
-
- public void clearRect(int x, int y, int width, int height) {
- fillRect(x,y,width,height);
- }
-
- public void draw(Shape s) {
- if (s instanceof Rectangle2D) {
- Rectangle2D r2 = (Rectangle2D)s;
- drawRect(r2.getX(),r2.getY(),r2.getWidth(),r2.getHeight());
- }
- else if (s instanceof Ellipse2D) {
- Ellipse2D e2 = (Ellipse2D)s;
- drawOval(e2.getX(),e2.getY(),e2.getWidth(),e2.getHeight());
- }
- else if (s instanceof RoundRectangle2D) {
- RoundRectangle2D r2 = (RoundRectangle2D)s;
- drawRoundRect(r2.getX(),r2.getY(),r2.getWidth(),r2.getHeight(),r2.getArcWidth(),r2.getArcHeight());
- }
- else if (s instanceof Arc2D) {
- Arc2D a2 = (Arc2D)s;
- drawArc(a2.getX(),a2.getY(),a2.getWidth(),a2.getHeight(),a2.getAngleStart(),a2.getAngleExtent());
- }
- else {
- double[] pts = (double[])SHAPE_CACHE.get(s);
-
- if (pts == null) {
- pts = SWTShapeManager.shapeToPolyline(s);
- SHAPE_CACHE.put(s,pts);
- }
-
- drawPolyline(pts);
- }
- }
+ cachedFont = new org.eclipse.swt.graphics.Font(device,
+ name.substring(name.indexOf("=") + 1, name.length()), sizeInt, style);
+ FONT_CACHE.put(fontString, cachedFont);
+ }
+ return cachedFont;
+ }
- public void fill(Shape s) {
- if (s instanceof Rectangle2D) {
- Rectangle2D r2 = (Rectangle2D)s;
- fillRect(r2.getX(),r2.getY(),r2.getWidth(),r2.getHeight());
- }
- else if (s instanceof Ellipse2D) {
- Ellipse2D e2 = (Ellipse2D)s;
- fillOval(e2.getX(),e2.getY(),e2.getWidth(),e2.getHeight());
- }
- else if (s instanceof RoundRectangle2D) {
- RoundRectangle2D r2 = (RoundRectangle2D)s;
- fillRoundRect(r2.getX(),r2.getY(),r2.getWidth(),r2.getHeight(),r2.getArcWidth(),r2.getArcHeight());
- }
- else if (s instanceof Arc2D) {
- Arc2D a2 = (Arc2D)s;
- fillArc(a2.getX(),a2.getY(),a2.getWidth(),a2.getHeight(),a2.getAngleStart(),a2.getAngleExtent());
- }
- else {
- double[] pts = (double[])SHAPE_CACHE.get(s);
-
- if (pts == null) {
- pts = SWTShapeManager.shapeToPolyline(s);
- SHAPE_CACHE.put(s,pts);
- }
-
- fillPolygon(pts);
- }
- }
+ protected org.eclipse.swt.graphics.Font getTransformedFont() {
+ if (curFont != null) {
+ FontData fontData = curFont.getFontData()[0];
+ int height = fontData.getHeight();
+ RECT.setRect(0, 0, height, height);
+ SWTShapeManager.transform(RECT, transform);
+ height = (int) (RECT.getHeight() + 0.5);
- public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
- int[] ptArray = new int[2*nPoints];
- for(int i=0; i maxX) {
- maxX = pts[2*i];
+ if (pts[2 * i] > maxX) {
+ maxX = pts[2 * i];
}
- if (pts[2*i+1] > maxY) {
- maxY = pts[2*i+1];
+ if (pts[2 * i + 1] > maxY) {
+ maxY = pts[2 * i + 1];
}
}
rect.setRect(minX, minY, maxX - minX, maxY - minY);
}
- public static void awtToSWT(Rectangle2D aRect, Rectangle sRect) {
- sRect.x = (int)(aRect.getX()+0.5);
- sRect.y = (int)(aRect.getY()+0.5);
- sRect.width = (int)(aRect.getWidth()+0.5);
- sRect.height = (int)(aRect.getHeight()+0.5);
- }
-
- public static double[] shapeToPolyline(Shape s) {
- segList.clear();
- aPoint.setLocation(0,0);
-
- PathIterator pi = s.getPathIterator(IDENTITY_XFORM,0.000000001);
- while (!pi.isDone()) {
- int segType = pi.currentSegment(pts);
- switch (segType) {
- case PathIterator.SEG_MOVETO:
- aPoint.setLocation(pts[0],pts[1]);
- segList.add(new Point2D.Double(pts[0],pts[1]));
- break;
- case PathIterator.SEG_LINETO:
- segList.add(new Point2D.Double(pts[0],pts[1]));
- break;
- case PathIterator.SEG_CLOSE:
- segList.add(new Point2D.Double(aPoint.getX(),aPoint.getY()));
- break;
- }
- pi.next();
- }
-
- double[] polyObj = new double[2*segList.size()];
- for(int i=0; i=0; i-=2) {
- if (listeners[i]==ActionListener.class) {
- ((ActionListener)listeners[i+1]).actionPerformed(e);
- }
+ for (int i = listeners.length - 2; i >= 0; i -= 2) {
+ if (listeners[i] == ActionListener.class) {
+ ((ActionListener) listeners[i + 1]).actionPerformed(e);
+ }
}
}
-
/**
* Returns the timer queue.
*/
@@ -93,11 +91,10 @@
return SWTTimerQueue.sharedInstance(display);
}
-
/**
- * Sets the Timer
's delay, the number of milliseconds
- * between successive action events.
- *
+ * Sets the Timer
's delay, the number of milliseconds between
+ * successive action events.
+ *
* @param delay the delay in milliseconds
* @see #setInitialDelay
*/
@@ -110,11 +107,9 @@
}
}
-
/**
- * Returns the delay, in milliseconds,
- * between firings of action events.
- *
+ * Returns the delay, in milliseconds, between firings of action events.
+ *
* @see #setDelay
* @see #getInitialDelay
*/
@@ -122,35 +117,29 @@
return delay;
}
-
/**
- * Sets the Timer
's initial delay,
- * which by default is the same as the between-event delay.
- * This is used only for the first action event.
- * Subsequent action events are spaced
- * using the delay property.
+ * Sets the Timer
's initial delay, which by default is the same
+ * as the between-event delay. This is used only for the first action event.
+ * Subsequent action events are spaced using the delay property.
*
- * @param initialDelay the delay, in milliseconds,
- * between the invocation of the start
- * method and the first action event
- * fired by this timer
- *
+ * @param initialDelay the delay, in milliseconds, between the invocation of
+ * the start
method and the first action event fired
+ * by this timer
+ *
* @see #setDelay
*/
public void setInitialDelay(int initialDelay) {
if (initialDelay < 0) {
- throw new IllegalArgumentException("Invalid initial delay: " +
- initialDelay);
+ throw new IllegalArgumentException("Invalid initial delay: " + initialDelay);
}
else {
this.initialDelay = initialDelay;
}
}
-
/**
* Returns the Timer
's initial delay.
- *
+ *
* @see #setInitialDelay
* @see #setDelay
*/
@@ -158,47 +147,37 @@
return initialDelay;
}
-
/**
- * If flag
is false
,
- * instructs the Timer
to send only one
- * action event to its listeners.
- *
- * @param flag specify false
to make the timer
- * stop after sending its first action event
+ * If flag
is false
, instructs the
+ * Timer
to send only one action event to its listeners.
+ *
+ * @param flag specify false
to make the timer stop after
+ * sending its first action event
*/
public void setRepeats(boolean flag) {
repeats = flag;
}
-
/**
- * Returns true
(the default)
- * if the Timer
will send
- * an action event
- * to its listeners multiple times.
- *
+ * Returns true
(the default) if the Timer
will
+ * send an action event to its listeners multiple times.
+ *
* @see #setRepeats
*/
public boolean isRepeats() {
return repeats;
}
-
/**
* Sets whether the Timer
coalesces multiple pending
- * ActionEvent
firings.
- * A busy application may not be able
- * to keep up with a Timer
's event generation,
- * causing multiple
- * action events to be queued. When processed,
- * the application sends these events one after the other, causing the
- * Timer
's listeners to receive a sequence of
- * events with no delay between them. Coalescing avoids this situation
- * by reducing multiple pending events to a single event.
- * Timer
s
- * coalesce events by default.
- *
+ * ActionEvent
firings. A busy application may not be able to
+ * keep up with a Timer
's event generation, causing multiple
+ * action events to be queued. When processed, the application sends these
+ * events one after the other, causing the Timer
's listeners to
+ * receive a sequence of events with no delay between them. Coalescing
+ * avoids this situation by reducing multiple pending events to a single
+ * event. Timer
s coalesce events by default.
+ *
* @param flag specify false
to turn off coalescing
*/
public void setCoalesce(boolean flag) {
@@ -212,46 +191,39 @@
}
}
-
/**
- * Returns true
if the Timer
coalesces
- * multiple pending action events.
- *
+ * Returns true
if the Timer
coalesces multiple
+ * pending action events.
+ *
* @see #setCoalesce
*/
public boolean isCoalesce() {
return coalesce;
}
-
/**
- * Starts the Timer
,
- * causing it to start sending action events
+ * Starts the Timer
, causing it to start sending action events
* to its listeners.
- *
+ *
* @see #stop
*/
public void start() {
- timerQueue().addTimer(this,
- System.currentTimeMillis() + getInitialDelay());
+ timerQueue().addTimer(this, System.currentTimeMillis() + getInitialDelay());
}
-
/**
* Returns true
if the Timer
is running.
- *
+ *
* @see #start
*/
public boolean isRunning() {
return timerQueue().containsTimer(this);
}
-
/**
- * Stops the Timer
,
- * causing it to stop sending action events
- * to its listeners.
- *
+ * Stops the Timer
, causing it to stop sending action events to
+ * its listeners.
+ *
* @see #start
*/
public void stop() {
@@ -259,33 +231,29 @@
cancelEventOverride();
}
-
/**
- * Restarts the Timer
,
- * canceling any pending firings and causing
- * it to fire with its initial delay.
+ * Restarts the Timer
, canceling any pending firings and
+ * causing it to fire with its initial delay.
*/
public void restart() {
stop();
start();
}
-
/**
- * Resets the internal state to indicate this Timer shouldn't notify
- * any of its listeners. This does not stop a repeatable Timer from
- * firing again, use stop
for that.
+ * Resets the internal state to indicate this Timer shouldn't notify any of
+ * its listeners. This does not stop a repeatable Timer from firing again,
+ * use stop
for that.
*/
synchronized void cancelEventOverride() {
notify = false;
}
-
synchronized void postOverride() {
if (notify == false || !coalesce) {
notify = true;
- display.asyncExec(doPostEvent);
+ display.asyncExec(doPostEvent);
}
}
-
+
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTTimerQueue.java b/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTTimerQueue.java
index cc158b2..1abfbfe 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTTimerQueue.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/swt/SWTTimerQueue.java
@@ -6,11 +6,11 @@
* @author Lance Good
*/
public class SWTTimerQueue implements Runnable {
- static SWTTimerQueue instance;
+ static SWTTimerQueue instance;
- Display display = null;
+ Display display = null;
- SWTTimer firstTimer;
+ SWTTimer firstTimer;
boolean running;
/**
@@ -19,31 +19,27 @@
public SWTTimerQueue(Display display) {
super();
- this.display = display;
+ this.display = display;
// Now start the TimerQueue thread.
start();
}
-
public static SWTTimerQueue sharedInstance(Display display) {
- if (instance == null) {
- instance = new SWTTimerQueue(display);
+ if (instance == null) {
+ instance = new SWTTimerQueue(display);
}
return instance;
}
-
synchronized void start() {
if (running) {
- throw new RuntimeException("Can't start a TimerQueue " +
- "that is already running");
+ throw new RuntimeException("Can't start a TimerQueue " + "that is already running");
}
else {
- Display.getDefault().asyncExec(new Runnable() {
+ Display.getDefault().asyncExec(new Runnable() {
public void run() {
- Thread timerThread = new Thread(SWTTimerQueue.this,
- "TimerQueue");
+ Thread timerThread = new Thread(SWTTimerQueue.this, "TimerQueue");
timerThread.setDaemon(true);
timerThread.setPriority(Thread.NORM_PRIORITY);
timerThread.start();
@@ -53,13 +49,11 @@
}
}
-
synchronized void stop() {
running = false;
notify();
}
-
synchronized void addTimer(SWTTimer timer, long expirationTime) {
SWTTimer previousTimer;
SWTTimer nextTimer;
@@ -73,11 +67,12 @@
nextTimer = firstTimer;
// Insert the Timer into the linked list in the order they will
- // expire. If two timers expire at the same time, put the newer entry
+ // expire. If two timers expire at the same time, put the newer entry
// later so they expire in the order they came in.
while (nextTimer != null) {
- if (nextTimer.expirationTime > expirationTime) break;
+ if (nextTimer.expirationTime > expirationTime)
+ break;
previousTimer = nextTimer;
nextTimer = nextTimer.nextTimer;
@@ -96,13 +91,13 @@
notify();
}
-
synchronized void removeTimer(SWTTimer timer) {
- SWTTimer previousTimer;
- SWTTimer nextTimer;
+ SWTTimer previousTimer;
+ SWTTimer nextTimer;
boolean found;
- if (!timer.running) return;
+ if (!timer.running)
+ return;
previousTimer = null;
nextTimer = firstTimer;
@@ -118,7 +113,8 @@
nextTimer = nextTimer.nextTimer;
}
- if (!found) return;
+ if (!found)
+ return;
if (previousTimer == null) {
firstTimer = timer.nextTimer;
@@ -132,35 +128,34 @@
timer.running = false;
}
-
synchronized boolean containsTimer(SWTTimer timer) {
return timer.running;
}
-
/**
- * If there are a ton of timers, this method may never return. It loops
- * checking to see if the head of the Timer list has expired. If it has,
- * it posts the Timer and reschedules it if necessary.
+ * If there are a ton of timers, this method may never return. It loops
+ * checking to see if the head of the Timer list has expired. If it has, it
+ * posts the Timer and reschedules it if necessary.
*/
synchronized long postExpiredTimers() {
- SWTTimer timer;
- long currentTime;
- long timeToWait;
+ SWTTimer timer;
+ long currentTime;
+ long timeToWait;
// The timeToWait we return should never be negative and only be zero
// when we have no Timers to wait for.
do {
timer = firstTimer;
- if (timer == null) return 0;
+ if (timer == null)
+ return 0;
currentTime = System.currentTimeMillis();
timeToWait = timer.expirationTime - currentTime;
if (timeToWait <= 0) {
try {
- timer.postOverride(); // have timer post an event
+ timer.postOverride(); // have timer post an event
}
catch (SecurityException e) {
}
@@ -175,7 +170,7 @@
}
// Allow other threads to call addTimer() and removeTimer()
- // even when we are posting Timers like mad. Since the wait()
+ // even when we are posting Timers like mad. Since the wait()
// releases the lock, be sure not to maintain any state
// between iterations of the loop.
@@ -190,7 +185,6 @@
return timeToWait;
}
-
public synchronized void run() {
long timeToWait;
@@ -212,12 +206,11 @@
timer.cancelEventOverride();
timer = timer.nextTimer;
}
- display.asyncExec(new SWTTimerQueueRestart(display));
+ display.asyncExec(new SWTTimerQueueRestart(display));
throw td;
}
}
-
public synchronized String toString() {
StringBuffer buf;
SWTTimer nextTimer;
@@ -230,39 +223,39 @@
buf.append(nextTimer.toString());
nextTimer = nextTimer.nextTimer;
- if (nextTimer != null) buf.append(", ");
+ if (nextTimer != null)
+ buf.append(", ");
}
buf.append(")");
return buf.toString();
- }
-
+ }
/**
- * Runnable that will message the shared instance of the Timer Queue
- * to restart.
+ * Runnable that will message the shared instance of the Timer Queue to
+ * restart.
*/
protected static class SWTTimerQueueRestart implements Runnable {
- boolean attemptedStart;
-
- Display display = null;
-
- public SWTTimerQueueRestart(Display display) {
- this.display = display;
- }
-
- public synchronized void run() {
- // Only try and restart the q once.
- if(!attemptedStart) {
- SWTTimerQueue q = SWTTimerQueue.sharedInstance(display);
-
- synchronized(q) {
- if(!q.running)
- q.start();
- }
- attemptedStart = true;
- }
- }
+ boolean attemptedStart;
+
+ Display display = null;
+
+ public SWTTimerQueueRestart(Display display) {
+ this.display = display;
+ }
+
+ public synchronized void run() {
+ // Only try and restart the q once.
+ if (!attemptedStart) {
+ SWTTimerQueue q = SWTTimerQueue.sharedInstance(display);
+
+ synchronized (q) {
+ if (!q.running)
+ q.start();
+ }
+ attemptedStart = true;
+ }
+ }
}
-
+
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/LineShape.java b/extras/src/main/java/edu/umd/cs/piccolox/util/LineShape.java
index 272188f..c5b9538 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/LineShape.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/LineShape.java
@@ -8,15 +8,14 @@
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-public class LineShape implements Shape, MutablePoints
-{
+public class LineShape implements Shape, MutablePoints {
private MutablePoints points;
- private Rectangle2D bounds = new Rectangle2D.Double();
+ private Rectangle2D bounds = new Rectangle2D.Double();
public LineShape(MutablePoints points) {
setPoints(points);
}
-
+
public void setPoints(MutablePoints points) {
if (points == null) {
points = new XYArray();
@@ -25,13 +24,18 @@
}
// from Points
-
+
public int getPointCount() {
return points.getPointCount();
}
- public double getX(int i) { return points.getX(i); }
- public double getY(int i) { return points.getY(i); }
+ public double getX(int i) {
+ return points.getX(i);
+ }
+
+ public double getY(int i) {
+ return points.getY(i);
+ }
public Point2D getPoint(int i, Point2D dst) {
return points.getPoint(i, dst);
@@ -48,7 +52,7 @@
bounds.setRect(0.0d, 0.0d, 0.0d, 0.0d);
points.getBounds(bounds);
}
-
+
public void setPoint(int i, double x, double y) {
points.setPoint(i, x, y);
updateBounds();
@@ -70,21 +74,20 @@
newPoints.transformPoints(trans);
points = newPoints;
}
-
+
//
-
+
public Rectangle getBounds() {
- return new Rectangle((int)bounds.getX(), (int)bounds.getY(), (int)bounds.getWidth(), (int)bounds.getHeight());
+ return new Rectangle((int) bounds.getX(), (int) bounds.getY(), (int) bounds.getWidth(), (int) bounds
+ .getHeight());
}
public Rectangle2D getBounds2D() {
return bounds;
}
- public static boolean contains(double x, double y, double x1, double y1, double x2, double y2,
- boolean min, boolean max,
- double d)
- {
+ public static boolean contains(double x, double y, double x1, double y1, double x2, double y2, boolean min,
+ boolean max, double d) {
double dx = x2 - x1, dy = y2 - y1;
double dx2 = dx * dx, dy2 = dy * dy;
double p;
@@ -103,7 +106,8 @@
else if (min && p < 0.0) {
return false;
}
- dx = (p * dx) + x1 - x; dy = (p * dy) + y1 - y;
+ dx = (p * dx) + x1 - x;
+ dy = (p * dy) + y1 - y;
double len = dx * dx + dy * dy;
return (len < d);
}
@@ -126,6 +130,7 @@
}
return false;
}
+
public boolean contains(double x, double y) {
return contains(x, y, 2.0d);
}
@@ -134,11 +139,8 @@
return contains(p.getX(), p.getY());
}
- public static boolean intersects(double x1, double y1, double x2, double y2,
- double x3, double y3, double x4, double y4,
- boolean min1, boolean max1,
- boolean min2, boolean max2)
- {
+ public static boolean intersects(double x1, double y1, double x2, double y2, double x3, double y3, double x4,
+ double y4, boolean min1, boolean max1, boolean min2, boolean max2) {
double dx1 = x2 - x1, dy1 = y2 - y1, dx2 = x4 - x3, dy2 = y4 - y3;
double d, p2, p1;
@@ -165,8 +167,7 @@
else {
return false;
}
- return (((! min1) || (p1 >= 0.0)) && ((! max1) || (p1 <= 1.0)) &&
- ((! min2) || (p2 >= 0.0)) && ((! max2) || (p2 <= 1.0)));
+ return (((!min1) || (p1 >= 0.0)) && ((!max1) || (p1 <= 1.0)) && ((!min2) || (p2 >= 0.0)) && ((!max2) || (p2 <= 1.0)));
}
public boolean intersects(double x, double y, double w, double h) {
@@ -181,10 +182,10 @@
y1 = y2;
x2 = points.getX(i);
y2 = points.getY(i);
- if (intersects(x, y, x + w, y, x1, y1, x2, y2, true, true, true, true) ||
- intersects(x + w, y, x + w, y + h, x1, y1, x2, y2, true, true, true, true) ||
- intersects(x + w, y + h, x, y + h, x1, y1, x2, y2, true, true, true, true) ||
- intersects(x, y + h, x, y, x1, y1, x2, y2, true, true, true, true)) {
+ if (intersects(x, y, x + w, y, x1, y1, x2, y2, true, true, true, true)
+ || intersects(x + w, y, x + w, y + h, x1, y1, x2, y2, true, true, true, true)
+ || intersects(x + w, y + h, x, y + h, x1, y1, x2, y2, true, true, true, true)
+ || intersects(x, y + h, x, y, x1, y1, x2, y2, true, true, true, true)) {
return true;
}
}
@@ -204,9 +205,9 @@
}
//
-
+
//
-
+
public PathIterator getPathIterator(AffineTransform at) {
return new LinePathIterator(points, at);
}
@@ -214,13 +215,13 @@
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return new LinePathIterator(points, at);
}
-
+
private static class LinePathIterator implements PathIterator {
private Points points;
private AffineTransform trans;
private int i = 0;
-
+
public LinePathIterator(Points points, AffineTransform trans) {
this.points = points;
this.trans = trans;
@@ -239,7 +240,7 @@
}
private Point2D tempPoint = new Point2D.Double();
-
+
private void currentSegment() {
tempPoint.setLocation(points.getX(i), points.getY(i));
if (trans != null) {
@@ -249,8 +250,8 @@
public int currentSegment(float[] coords) {
currentSegment();
- coords[0] = (float)tempPoint.getX();
- coords[1] = (float)tempPoint.getY();
+ coords[0] = (float) tempPoint.getX();
+ coords[1] = (float) tempPoint.getY();
return (i == 0 ? PathIterator.SEG_MOVETO : PathIterator.SEG_LINETO);
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/MutablePoints.java b/extras/src/main/java/edu/umd/cs/piccolox/util/MutablePoints.java
index 42a6ed3..b14d97e 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/MutablePoints.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/MutablePoints.java
@@ -2,10 +2,12 @@
import java.awt.geom.AffineTransform;
-public interface MutablePoints extends Points
-{
+public interface MutablePoints extends Points {
public void setPoint(int i, double x, double y);
+
public void addPoint(int pos, double x, double y);
+
public void removePoints(int pos, int num);
+
public void transformPoints(AffineTransform t);
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/PBoundsLocator.java b/extras/src/main/java/edu/umd/cs/piccolox/util/PBoundsLocator.java
index a27bd4e..0d2659d 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/PBoundsLocator.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/PBoundsLocator.java
@@ -36,100 +36,101 @@
import edu.umd.cs.piccolo.PNode;
/**
- * PBoundsLocator is a locator that locates points on the
- * bounds of a node.
+ * PBoundsLocator is a locator that locates points on the bounds of a
+ * node.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PBoundsLocator extends PNodeLocator {
- private int side;
-
- public static PBoundsLocator createEastLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.EAST);
- }
+ private int side;
- public static PBoundsLocator createNorthEastLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.NORTH_EAST);
- }
+ public static PBoundsLocator createEastLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.EAST);
+ }
- public static PBoundsLocator createNorthWestLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.NORTH_WEST);
- }
+ public static PBoundsLocator createNorthEastLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.NORTH_EAST);
+ }
- public static PBoundsLocator createNorthLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.NORTH);
- }
+ public static PBoundsLocator createNorthWestLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.NORTH_WEST);
+ }
- public static PBoundsLocator createSouthLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.SOUTH);
- }
+ public static PBoundsLocator createNorthLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.NORTH);
+ }
- public static PBoundsLocator createWestLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.WEST);
- }
+ public static PBoundsLocator createSouthLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.SOUTH);
+ }
- public static PBoundsLocator createSouthWestLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.SOUTH_WEST);
- }
+ public static PBoundsLocator createWestLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.WEST);
+ }
- public static PBoundsLocator createSouthEastLocator(PNode node) {
- return new PBoundsLocator(node, SwingConstants.SOUTH_EAST);
- }
+ public static PBoundsLocator createSouthWestLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.SOUTH_WEST);
+ }
- public PBoundsLocator(PNode node, int aSide) {
- super(node);
- side = aSide;
- }
+ public static PBoundsLocator createSouthEastLocator(PNode node) {
+ return new PBoundsLocator(node, SwingConstants.SOUTH_EAST);
+ }
- public int getSide() {
- return side;
- }
-
- public void setSide(int side) {
- this.side = side;
- }
-
- public double locateX() {
- Rectangle2D aBounds = node.getBoundsReference();
+ public PBoundsLocator(PNode node, int aSide) {
+ super(node);
+ side = aSide;
+ }
- switch (side) {
- case SwingConstants.NORTH_WEST :
- case SwingConstants.SOUTH_WEST :
- case SwingConstants.WEST :
- return aBounds.getX();
+ public int getSide() {
+ return side;
+ }
- case SwingConstants.NORTH_EAST :
- case SwingConstants.SOUTH_EAST :
- case SwingConstants.EAST :
- return aBounds.getX() + aBounds.getWidth();
+ public void setSide(int side) {
+ this.side = side;
+ }
- case SwingConstants.NORTH :
- case SwingConstants.SOUTH :
- return aBounds.getX() + (aBounds.getWidth() / 2);
- }
- return -1;
- }
+ public double locateX() {
+ Rectangle2D aBounds = node.getBoundsReference();
- public double locateY() {
- Rectangle2D aBounds = node.getBoundsReference();
+ switch (side) {
+ case SwingConstants.NORTH_WEST:
+ case SwingConstants.SOUTH_WEST:
+ case SwingConstants.WEST:
+ return aBounds.getX();
- switch (side) {
- case SwingConstants.EAST :
- case SwingConstants.WEST :
- return aBounds.getY() + (aBounds.getHeight() / 2);
+ case SwingConstants.NORTH_EAST:
+ case SwingConstants.SOUTH_EAST:
+ case SwingConstants.EAST:
+ return aBounds.getX() + aBounds.getWidth();
- case SwingConstants.SOUTH :
- case SwingConstants.SOUTH_WEST :
- case SwingConstants.SOUTH_EAST :
- return aBounds.getY() + aBounds.getHeight();
+ case SwingConstants.NORTH:
+ case SwingConstants.SOUTH:
+ return aBounds.getX() + (aBounds.getWidth() / 2);
+ }
+ return -1;
+ }
- case SwingConstants.NORTH_WEST :
- case SwingConstants.NORTH_EAST :
- case SwingConstants.NORTH :
- return aBounds.getY();
- }
- return -1;
- }
+ public double locateY() {
+ Rectangle2D aBounds = node.getBoundsReference();
+
+ switch (side) {
+ case SwingConstants.EAST:
+ case SwingConstants.WEST:
+ return aBounds.getY() + (aBounds.getHeight() / 2);
+
+ case SwingConstants.SOUTH:
+ case SwingConstants.SOUTH_WEST:
+ case SwingConstants.SOUTH_EAST:
+ return aBounds.getY() + aBounds.getHeight();
+
+ case SwingConstants.NORTH_WEST:
+ case SwingConstants.NORTH_EAST:
+ case SwingConstants.NORTH:
+ return aBounds.getY();
+ }
+ return -1;
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/PFixedWidthStroke.java b/extras/src/main/java/edu/umd/cs/piccolox/util/PFixedWidthStroke.java
index d86ab8a..5df26ea 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/PFixedWidthStroke.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/PFixedWidthStroke.java
@@ -50,361 +50,363 @@
import edu.umd.cs.piccolo.util.PPickPath;
/**
- * PFixedWidthStroke is the same as {@link java.awt.BasicStroke} except that PFixedWidthStroke
- * has a fixed width on the screen so that even when the canvas view is zooming its
- * width stays the same in canvas coordinates. Note that this stroke draws in the inside of
- * the stroked shape, instead of the normal draw on center behavior.
+ * PFixedWidthStroke is the same as {@link java.awt.BasicStroke} except
+ * that PFixedWidthStroke has a fixed width on the screen so that even when the
+ * canvas view is zooming its width stays the same in canvas coordinates. Note
+ * that this stroke draws in the inside of the stroked shape, instead of the
+ * normal draw on center behavior.
*
+ *
* @see edu.umd.cs.piccolo.nodes.PPath
* @version 1.0
* @author Jesse Grosjean
*/
public class PFixedWidthStroke implements Stroke, Serializable {
-
- private static PAffineTransform TEMP_TRANSFORM = new PAffineTransform();
- private static GeneralPath TEMP_PATH = new GeneralPath(GeneralPath.WIND_NON_ZERO);
-
- final static int JOIN_MITER = BasicStroke.JOIN_MITER;
- final static int JOIN_ROUND = BasicStroke.JOIN_ROUND;
- final static int JOIN_BEVEL = BasicStroke.JOIN_BEVEL;
- final static int CAP_BUTT = BasicStroke.CAP_BUTT;
- final static int CAP_ROUND = BasicStroke.CAP_ROUND;
- final static int CAP_SQUARE = BasicStroke.CAP_SQUARE;
- private float width;
- private int join;
- private int cap;
- private float miterlimit;
- private float dash[];
- private float dash_phase;
+ private static PAffineTransform TEMP_TRANSFORM = new PAffineTransform();
+ private static GeneralPath TEMP_PATH = new GeneralPath(GeneralPath.WIND_NON_ZERO);
- private static final int RasterizerCaps[] = {
- Rasterizer.BUTT, Rasterizer.ROUND, Rasterizer.SQUARE
- };
+ final static int JOIN_MITER = BasicStroke.JOIN_MITER;
+ final static int JOIN_ROUND = BasicStroke.JOIN_ROUND;
+ final static int JOIN_BEVEL = BasicStroke.JOIN_BEVEL;
+ final static int CAP_BUTT = BasicStroke.CAP_BUTT;
+ final static int CAP_ROUND = BasicStroke.CAP_ROUND;
+ final static int CAP_SQUARE = BasicStroke.CAP_SQUARE;
- private static final int RasterizerCorners[] = {
- Rasterizer.MITER, Rasterizer.ROUND, Rasterizer.BEVEL
- };
+ private float width;
+ private int join;
+ private int cap;
+ private float miterlimit;
+ private float dash[];
+ private float dash_phase;
- private class FillAdapter implements PathConsumer {
- boolean closed;
- GeneralPath path;
+ private static final int RasterizerCaps[] = { Rasterizer.BUTT, Rasterizer.ROUND, Rasterizer.SQUARE };
- public FillAdapter() {
- path = TEMP_PATH;
- path.reset();
- }
+ private static final int RasterizerCorners[] = { Rasterizer.MITER, Rasterizer.ROUND, Rasterizer.BEVEL };
- public Shape getShape() {
- return path;
- }
+ private class FillAdapter implements PathConsumer {
+ boolean closed;
+ GeneralPath path;
- public void beginPath() {}
+ public FillAdapter() {
+ path = TEMP_PATH;
+ path.reset();
+ }
- public void beginSubpath(float x0, float y0) {
- if (closed) {
- path.closePath();
- closed = false;
- }
- path.moveTo(x0, y0);
- }
+ public Shape getShape() {
+ return path;
+ }
- public void appendLine(float x1, float y1) {
- path.lineTo(x1, y1);
- }
+ public void beginPath() {
+ }
- public void appendQuadratic(float xm, float ym, float x1, float y1) {
- path.quadTo(xm, ym, x1, y1);
- }
+ public void beginSubpath(float x0, float y0) {
+ if (closed) {
+ path.closePath();
+ closed = false;
+ }
+ path.moveTo(x0, y0);
+ }
- public void appendCubic(float xm, float ym,
- float xn, float yn,
- float x1, float y1) {
- path.curveTo(xm, ym, xn, yn, x1, y1);
- }
+ public void appendLine(float x1, float y1) {
+ path.lineTo(x1, y1);
+ }
- public void closedSubpath() {
- closed = true;
- }
+ public void appendQuadratic(float xm, float ym, float x1, float y1) {
+ path.quadTo(xm, ym, x1, y1);
+ }
- public void endPath() {
- if (closed) {
- path.closePath();
- closed = false;
- }
- }
+ public void appendCubic(float xm, float ym, float xn, float yn, float x1, float y1) {
+ path.curveTo(xm, ym, xn, yn, x1, y1);
+ }
- public void useProxy(FastPathProducer proxy)
- throws PathException {
- proxy.sendTo(this);
- }
+ public void closedSubpath() {
+ closed = true;
+ }
- public long getCPathConsumer() {
- return 0;
- }
-
- public void dispose() {
- }
+ public void endPath() {
+ if (closed) {
+ path.closePath();
+ closed = false;
+ }
+ }
- public PathConsumer getConsumer() {
- return null;
- }
- }
-
- public PFixedWidthStroke() {
- this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
- }
-
- public PFixedWidthStroke(float width) {
- this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
- }
-
- public PFixedWidthStroke(float width, int cap, int join) {
- this(width, cap, join, 10.0f, null, 0.0f);
- }
-
- public PFixedWidthStroke(float width, int cap, int join, float miterlimit) {
- this(width, cap, join, miterlimit, null, 0.0f);
- }
-
- public PFixedWidthStroke(float width, int cap, int join, float miterlimit, float dash[], float dash_phase) {
- if (width < 0.0f) {
- throw new IllegalArgumentException("negative width");
- }
- if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
- throw new IllegalArgumentException("illegal end cap value");
- }
- if (join == JOIN_MITER) {
- if (miterlimit < 1.0f) {
- throw new IllegalArgumentException("miter limit < 1");
- }
- } else if (join != JOIN_ROUND && join != JOIN_BEVEL) {
- throw new IllegalArgumentException("illegal line join value");
- }
- if (dash != null) {
- if (dash_phase < 0.0f) {
- throw new IllegalArgumentException("negative dash phase");
- }
- boolean allzero = true;
- for (int i = 0; i < dash.length; i++) {
- float d = dash[i];
- if (d > 0.0) {
- allzero = false;
- } else if (d < 0.0) {
- throw new IllegalArgumentException("negative dash length");
- }
- }
-
- if (allzero) {
- throw new IllegalArgumentException("dash lengths all zero");
- }
- }
- this.width = width;
- this.cap = cap;
- this.join = join;
- this.miterlimit = miterlimit;
- if (dash != null) {
- this.dash = (float []) dash.clone();
- }
- this.dash_phase = dash_phase;
- }
-
- public Object clone() {
- try {
- return super.clone();
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public Shape createStrokedShape(Shape s) {
- FillAdapter filler = new FillAdapter();
- PathStroker stroker = new PathStroker(filler);
- PathConsumer consumer;
+ public void useProxy(FastPathProducer proxy) throws PathException {
+ proxy.sendTo(this);
+ }
- // Fixed Width Additions, always stroke path inside shape.
- // Also keeps dashes fixed when zooming (thanks to Shawn Castrianni - Dec 2006)
- float fixedScale = 1.0f;
+ public long getCPathConsumer() {
+ return 0;
+ }
- if (PDebug.getProcessingOutput()) {
- if (PPaintContext.CURRENT_PAINT_CONTEXT != null) {
- fixedScale = 1.0f / (float)PPaintContext.CURRENT_PAINT_CONTEXT.getScale();
- }
- } else {
- if (PPickPath.CURRENT_PICK_PATH != null) {
- fixedScale = 1.0f / (float)PPickPath.CURRENT_PICK_PATH.getScale();
- }
- }
- float fixedWidth = width * fixedScale;
+ public void dispose() {
+ }
- Rectangle2D bounds = s.getBounds2D();
- double scale = 1.0;
+ public PathConsumer getConsumer() {
+ return null;
+ }
+ }
- if (bounds.getWidth() > bounds.getHeight()) {
- if (bounds.getWidth() != 0) {
- scale = (bounds.getWidth()-fixedWidth)/bounds.getWidth();
- }
- } else {
- if (bounds.getHeight() != 0) {
- scale = (bounds.getHeight()-fixedWidth)/bounds.getHeight();
- }
- }
+ public PFixedWidthStroke() {
+ this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
+ }
- TEMP_TRANSFORM.setToIdentity();
- TEMP_TRANSFORM.scaleAboutPoint(scale, bounds.getCenterX(), bounds.getCenterY());
- stroker.setPenDiameter(fixedWidth);
- PathIterator pi = s.getPathIterator(TEMP_TRANSFORM);
+ public PFixedWidthStroke(float width) {
+ this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
+ }
- stroker.setPenT4(null);
- stroker.setCaps(RasterizerCaps[cap]);
- stroker.setCorners(RasterizerCorners[join], miterlimit);
- if (dash != null) {
- //Fixed Width Additions
- float fixedDash[] = new float[dash.length];
- for (int i = 0; i < dash.length; i++) {
- fixedDash[i] = dash[i] * fixedScale;
- }
- float fixedDashPhase = dash_phase * fixedScale;
- PathDasher dasher = new PathDasher(stroker);
- dasher.setDash(fixedDash, fixedDashPhase);
- dasher.setDashT4(null);
- consumer = dasher;
- } else {
- consumer = stroker;
- }
+ public PFixedWidthStroke(float width, int cap, int join) {
+ this(width, cap, join, 10.0f, null, 0.0f);
+ }
- try {
- consumer.beginPath();
- boolean pathClosed = false;
- float mx = 0.0f;
- float my = 0.0f;
- float point[] = new float[6];
+ public PFixedWidthStroke(float width, int cap, int join, float miterlimit) {
+ this(width, cap, join, miterlimit, null, 0.0f);
+ }
- while (!pi.isDone()) {
- int type = pi.currentSegment(point);
- if (pathClosed == true) {
- pathClosed = false;
- if (type != PathIterator.SEG_MOVETO) {
- // Force current point back to last moveto point
- consumer.beginSubpath(mx, my);
- }
- }
- switch (type) {
- case PathIterator.SEG_MOVETO:
- mx = point[0];
- my = point[1];
- consumer.beginSubpath(point[0], point[1]);
- break;
- case PathIterator.SEG_LINETO:
- consumer.appendLine(point[0], point[1]);
- break;
- case PathIterator.SEG_QUADTO:
- // Quadratic curves take two points
- consumer.appendQuadratic(point[0], point[1],
- point[2], point[3]);
- break;
- case PathIterator.SEG_CUBICTO:
- // Cubic curves take three points
- consumer.appendCubic(point[0], point[1],
- point[2], point[3],
- point[4], point[5]);
- break;
- case PathIterator.SEG_CLOSE:
- consumer.closedSubpath();
- pathClosed = true;
- break;
- }
- pi.next();
- }
+ public PFixedWidthStroke(float width, int cap, int join, float miterlimit, float dash[], float dash_phase) {
+ if (width < 0.0f) {
+ throw new IllegalArgumentException("negative width");
+ }
+ if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
+ throw new IllegalArgumentException("illegal end cap value");
+ }
+ if (join == JOIN_MITER) {
+ if (miterlimit < 1.0f) {
+ throw new IllegalArgumentException("miter limit < 1");
+ }
+ }
+ else if (join != JOIN_ROUND && join != JOIN_BEVEL) {
+ throw new IllegalArgumentException("illegal line join value");
+ }
+ if (dash != null) {
+ if (dash_phase < 0.0f) {
+ throw new IllegalArgumentException("negative dash phase");
+ }
+ boolean allzero = true;
+ for (int i = 0; i < dash.length; i++) {
+ float d = dash[i];
+ if (d > 0.0) {
+ allzero = false;
+ }
+ else if (d < 0.0) {
+ throw new IllegalArgumentException("negative dash length");
+ }
+ }
- consumer.endPath();
+ if (allzero) {
+ throw new IllegalArgumentException("dash lengths all zero");
+ }
+ }
+ this.width = width;
+ this.cap = cap;
+ this.join = join;
+ this.miterlimit = miterlimit;
+ if (dash != null) {
+ this.dash = (float[]) dash.clone();
+ }
+ this.dash_phase = dash_phase;
+ }
- consumer.dispose(); // hack to fix memory leak, shouldn't be neccessary but is.
- } catch (PathException e) {
- throw new InternalError("Unable to Stroke shape ("+
- e.getMessage()+")");
- }
+ public Object clone() {
+ try {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
- return filler.getShape();
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof PFixedWidthStroke)) {
- return false;
- }
+ public Shape createStrokedShape(Shape s) {
+ FillAdapter filler = new FillAdapter();
+ PathStroker stroker = new PathStroker(filler);
+ PathConsumer consumer;
- PFixedWidthStroke bs = (PFixedWidthStroke) obj;
- if (width != bs.width) {
- return false;
- }
+ // Fixed Width Additions, always stroke path inside shape.
+ // Also keeps dashes fixed when zooming (thanks to Shawn Castrianni -
+ // Dec 2006)
+ float fixedScale = 1.0f;
- if (join != bs.join) {
- return false;
- }
+ if (PDebug.getProcessingOutput()) {
+ if (PPaintContext.CURRENT_PAINT_CONTEXT != null) {
+ fixedScale = 1.0f / (float) PPaintContext.CURRENT_PAINT_CONTEXT.getScale();
+ }
+ }
+ else {
+ if (PPickPath.CURRENT_PICK_PATH != null) {
+ fixedScale = 1.0f / (float) PPickPath.CURRENT_PICK_PATH.getScale();
+ }
+ }
+ float fixedWidth = width * fixedScale;
- if (cap != bs.cap) {
- return false;
- }
+ Rectangle2D bounds = s.getBounds2D();
+ double scale = 1.0;
- if (miterlimit != bs.miterlimit) {
- return false;
- }
+ if (bounds.getWidth() > bounds.getHeight()) {
+ if (bounds.getWidth() != 0) {
+ scale = (bounds.getWidth() - fixedWidth) / bounds.getWidth();
+ }
+ }
+ else {
+ if (bounds.getHeight() != 0) {
+ scale = (bounds.getHeight() - fixedWidth) / bounds.getHeight();
+ }
+ }
- if (dash != null) {
- if (dash_phase != bs.dash_phase) {
- return false;
- }
+ TEMP_TRANSFORM.setToIdentity();
+ TEMP_TRANSFORM.scaleAboutPoint(scale, bounds.getCenterX(), bounds.getCenterY());
+ stroker.setPenDiameter(fixedWidth);
+ PathIterator pi = s.getPathIterator(TEMP_TRANSFORM);
- if (!java.util.Arrays.equals(dash, bs.dash)) {
- return false;
- }
- } else if (bs.dash != null) {
- return false;
- }
+ stroker.setPenT4(null);
+ stroker.setCaps(RasterizerCaps[cap]);
+ stroker.setCorners(RasterizerCorners[join], miterlimit);
+ if (dash != null) {
+ // Fixed Width Additions
+ float fixedDash[] = new float[dash.length];
+ for (int i = 0; i < dash.length; i++) {
+ fixedDash[i] = dash[i] * fixedScale;
+ }
+ float fixedDashPhase = dash_phase * fixedScale;
+ PathDasher dasher = new PathDasher(stroker);
+ dasher.setDash(fixedDash, fixedDashPhase);
+ dasher.setDashT4(null);
+ consumer = dasher;
+ }
+ else {
+ consumer = stroker;
+ }
- return true;
- }
-
- private float[] getDashArray() {
- if (dash == null) {
- return null;
- }
+ try {
+ consumer.beginPath();
+ boolean pathClosed = false;
+ float mx = 0.0f;
+ float my = 0.0f;
+ float point[] = new float[6];
- return (float[]) dash.clone();
- }
-
- private float getDashPhase() {
- return dash_phase;
- }
-
- private int getEndCap() {
- return cap;
- }
-
- private int getLineJoin() {
- return join;
- }
-
- private float getLineWidth() {
- return width;
- }
-
- private float getMiterLimit() {
- return miterlimit;
- }
-
- public int hashCode() {
- int hash = Float.floatToIntBits(width);
- hash = hash * 31 + join;
- hash = hash * 31 + cap;
- hash = hash * 31 + Float.floatToIntBits(miterlimit);
- if (dash != null) {
- hash = hash * 31 + Float.floatToIntBits(dash_phase);
- for (int i = 0; i < dash.length; i++) {
- hash = hash * 31 + Float.floatToIntBits(dash[i]);
- }
- }
- return hash;
- }
+ while (!pi.isDone()) {
+ int type = pi.currentSegment(point);
+ if (pathClosed == true) {
+ pathClosed = false;
+ if (type != PathIterator.SEG_MOVETO) {
+ // Force current point back to last moveto point
+ consumer.beginSubpath(mx, my);
+ }
+ }
+ switch (type) {
+ case PathIterator.SEG_MOVETO:
+ mx = point[0];
+ my = point[1];
+ consumer.beginSubpath(point[0], point[1]);
+ break;
+ case PathIterator.SEG_LINETO:
+ consumer.appendLine(point[0], point[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ // Quadratic curves take two points
+ consumer.appendQuadratic(point[0], point[1], point[2], point[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ // Cubic curves take three points
+ consumer.appendCubic(point[0], point[1], point[2], point[3], point[4], point[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ consumer.closedSubpath();
+ pathClosed = true;
+ break;
+ }
+ pi.next();
+ }
+
+ consumer.endPath();
+
+ consumer.dispose(); // hack to fix memory leak, shouldn't be
+ // neccessary but is.
+ }
+ catch (PathException e) {
+ throw new InternalError("Unable to Stroke shape (" + e.getMessage() + ")");
+ }
+
+ return filler.getShape();
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof PFixedWidthStroke)) {
+ return false;
+ }
+
+ PFixedWidthStroke bs = (PFixedWidthStroke) obj;
+ if (width != bs.width) {
+ return false;
+ }
+
+ if (join != bs.join) {
+ return false;
+ }
+
+ if (cap != bs.cap) {
+ return false;
+ }
+
+ if (miterlimit != bs.miterlimit) {
+ return false;
+ }
+
+ if (dash != null) {
+ if (dash_phase != bs.dash_phase) {
+ return false;
+ }
+
+ if (!java.util.Arrays.equals(dash, bs.dash)) {
+ return false;
+ }
+ }
+ else if (bs.dash != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private float[] getDashArray() {
+ if (dash == null) {
+ return null;
+ }
+
+ return (float[]) dash.clone();
+ }
+
+ private float getDashPhase() {
+ return dash_phase;
+ }
+
+ private int getEndCap() {
+ return cap;
+ }
+
+ private int getLineJoin() {
+ return join;
+ }
+
+ private float getLineWidth() {
+ return width;
+ }
+
+ private float getMiterLimit() {
+ return miterlimit;
+ }
+
+ public int hashCode() {
+ int hash = Float.floatToIntBits(width);
+ hash = hash * 31 + join;
+ hash = hash * 31 + cap;
+ hash = hash * 31 + Float.floatToIntBits(miterlimit);
+ if (dash != null) {
+ hash = hash * 31 + Float.floatToIntBits(dash_phase);
+ for (int i = 0; i < dash.length; i++) {
+ hash = hash * 31 + Float.floatToIntBits(dash[i]);
+ }
+ }
+ return hash;
+ }
}
\ No newline at end of file
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/PLocator.java b/extras/src/main/java/edu/umd/cs/piccolox/util/PLocator.java
index ee51de8..5365ce3 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/PLocator.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/PLocator.java
@@ -37,23 +37,24 @@
* as PNodeLocator and PBoundsLocator specialize this behavior by locating
* points on nodes, or on the bounds of nodes.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public abstract class PLocator implements Serializable {
- public PLocator() {
- }
+ public PLocator() {
+ }
- public Point2D locatePoint(Point2D aDstPoint) {
- if (aDstPoint == null) {
- aDstPoint = new Point2D.Double();
- }
- aDstPoint.setLocation(locateX(), locateY());
- return aDstPoint;
- }
+ public Point2D locatePoint(Point2D aDstPoint) {
+ if (aDstPoint == null) {
+ aDstPoint = new Point2D.Double();
+ }
+ aDstPoint.setLocation(locateX(), locateY());
+ return aDstPoint;
+ }
- public abstract double locateX();
+ public abstract double locateX();
- public abstract double locateY();
+ public abstract double locateY();
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/PNodeLocator.java b/extras/src/main/java/edu/umd/cs/piccolox/util/PNodeLocator.java
index b1a89ec..0d79527 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/PNodeLocator.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/PNodeLocator.java
@@ -39,30 +39,31 @@
* many different nodes you will need to call setNode() before asking for each
* location.
*
+ *
* @version 1.0
* @author Jesse Grosjean
*/
public class PNodeLocator extends PLocator {
-
- protected PNode node;
- public PNodeLocator(PNode node) {
- setNode(node);
- }
+ protected PNode node;
- public PNode getNode() {
- return node;
- }
-
- public void setNode(PNode node) {
- this.node = node;
- }
+ public PNodeLocator(PNode node) {
+ setNode(node);
+ }
- public double locateX() {
- return node.getBoundsReference().getCenterX();
- }
+ public PNode getNode() {
+ return node;
+ }
- public double locateY() {
- return node.getBoundsReference().getCenterY();
- }
+ public void setNode(PNode node) {
+ this.node = node;
+ }
+
+ public double locateX() {
+ return node.getBoundsReference().getCenterX();
+ }
+
+ public double locateY() {
+ return node.getBoundsReference().getCenterY();
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/POcclusionDetection.java b/extras/src/main/java/edu/umd/cs/piccolox/util/POcclusionDetection.java
index e330740..1f96446 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/POcclusionDetection.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/POcclusionDetection.java
@@ -40,46 +40,47 @@
*/
public class POcclusionDetection {
- /**
- * Traverse from the bottom right of the scene graph (top visible node)
- * up the tree determining which parent nodes are occluded by their children
- * nodes. Note that this is only detecting a subset of occlusions (parent, child),
- * others such as overlapping siblings or cousins are not detected.
- */
- public void detectOccusions(PNode n, PBounds parentBounds) {
- detectOcclusions(n, new PPickPath(null, parentBounds));
- }
+ /**
+ * Traverse from the bottom right of the scene graph (top visible node) up
+ * the tree determining which parent nodes are occluded by their children
+ * nodes. Note that this is only detecting a subset of occlusions (parent,
+ * child), others such as overlapping siblings or cousins are not detected.
+ */
+ public void detectOccusions(PNode n, PBounds parentBounds) {
+ detectOcclusions(n, new PPickPath(null, parentBounds));
+ }
- public void detectOcclusions(PNode n, PPickPath pickPath) {
- if (n.fullIntersects(pickPath.getPickBounds())) {
- pickPath.pushTransform(n.getTransformReference(false));
-
- int count = n.getChildrenCount();
- for (int i = count - 1; i >= 0; i--) {
- PNode each = (PNode) n.getChild(i);
- if (n.getOccluded()) {
- // if n has been occuded by a previous decendent then
- // this child must also be occuded
- each.setOccluded(true);
- } else {
- // see if child each occludes n
- detectOcclusions(each, pickPath);
- }
- }
+ public void detectOcclusions(PNode n, PPickPath pickPath) {
+ if (n.fullIntersects(pickPath.getPickBounds())) {
+ pickPath.pushTransform(n.getTransformReference(false));
- // see if n occudes it's parents
- if (!n.getOccluded()) {
- if (n.intersects(pickPath.getPickBounds())) {
- if (n.isOpaque(pickPath.getPickBounds())) {
- PNode p = n.getParent();
- while (p != null && !p.getOccluded()) {
- p.setOccluded(true);
- }
- }
- }
- }
-
- pickPath.popTransform(n.getTransformReference(false));
- }
- }
+ int count = n.getChildrenCount();
+ for (int i = count - 1; i >= 0; i--) {
+ PNode each = (PNode) n.getChild(i);
+ if (n.getOccluded()) {
+ // if n has been occuded by a previous decendent then
+ // this child must also be occuded
+ each.setOccluded(true);
+ }
+ else {
+ // see if child each occludes n
+ detectOcclusions(each, pickPath);
+ }
+ }
+
+ // see if n occudes it's parents
+ if (!n.getOccluded()) {
+ if (n.intersects(pickPath.getPickBounds())) {
+ if (n.isOpaque(pickPath.getPickBounds())) {
+ PNode p = n.getParent();
+ while (p != null && !p.getOccluded()) {
+ p.setOccluded(true);
+ }
+ }
+ }
+ }
+
+ pickPath.popTransform(n.getTransformReference(false));
+ }
+ }
}
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/Points.java b/extras/src/main/java/edu/umd/cs/piccolox/util/Points.java
index 10180f7..0e8d9c8 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/Points.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/Points.java
@@ -1,13 +1,15 @@
package edu.umd.cs.piccolox.util;
+
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-public interface Points
-{
+public interface Points {
public int getPointCount();
public double getX(int i);
+
public double getY(int i);
+
public Point2D getPoint(int i, Point2D dst);
public Rectangle2D getBounds(Rectangle2D dst);
diff --git a/extras/src/main/java/edu/umd/cs/piccolox/util/XYArray.java b/extras/src/main/java/edu/umd/cs/piccolox/util/XYArray.java
index d8410d7..8bfa502 100644
--- a/extras/src/main/java/edu/umd/cs/piccolox/util/XYArray.java
+++ b/extras/src/main/java/edu/umd/cs/piccolox/util/XYArray.java
@@ -4,8 +4,7 @@
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-public class XYArray implements MutablePoints
-{
+public class XYArray implements MutablePoints {
// the coordinates are stored as alternating x and y pairs
private double[] points = null;
@@ -15,11 +14,13 @@
private int numPoints = 0;
- public int getPointCount() { return numPoints;}
+ public int getPointCount() {
+ return numPoints;
+ }
// normalize an index, negative counts from end
- private int i(int i) {
+ private int i(int i) {
if (i < 0) {
i = numPoints + i;
}
@@ -33,52 +34,47 @@
// from Points
- public double getX(int i)
- {
+ public double getX(int i) {
i = i(i);
- return points[i*2];
+ return points[i * 2];
}
- public double getY(int i)
- {
+
+ public double getY(int i) {
i = i(i);
- return points[i*2 + 1];
+ return points[i * 2 + 1];
}
+
public Point2D getPoint(int i, Point2D dst) {
i = i(i);
- dst.setLocation(points[i*2], points[i*2 + 1]);
+ dst.setLocation(points[i * 2], points[i * 2 + 1]);
return dst;
}
- public void setX(int i, double x)
- {
+ public void setX(int i, double x) {
i = i(i);
- points[i*2] = x;
- }
- public void setY(int i, double y)
- {
- i = i(i);
- points[i*2 + 1] = y;
+ points[i * 2] = x;
}
- public void setPoint(int i, double x, double y)
- {
+ public void setY(int i, double y) {
i = i(i);
- points[i*2] = x;
- points[i*2 + 1] = y;
+ points[i * 2 + 1] = y;
}
- public void setPoint(int i, Point2D pt)
- {
+ public void setPoint(int i, double x, double y) {
+ i = i(i);
+ points[i * 2] = x;
+ points[i * 2 + 1] = y;
+ }
+
+ public void setPoint(int i, Point2D pt) {
setPoint(i, pt.getX(), pt.getY());
}
- public void transformPoints(AffineTransform t)
- {
+ public void transformPoints(AffineTransform t) {
t.transform(points, 0, points, 0, numPoints);
}
- public Rectangle2D getBounds(Rectangle2D dst)
- {
+ public Rectangle2D getBounds(Rectangle2D dst) {
int i = 0;
if (dst.isEmpty() && getPointCount() > 0) {
dst.setRect(getX(i), getY(i), 1.0d, 1.0d);
@@ -95,19 +91,17 @@
// initialization of points array
- public static double[] initPoints(double[] points, int n, double[] old)
- {
+ public static double[] initPoints(double[] points, int n, double[] old) {
if (points == null || n * 2 > points.length) {
points = new double[n * 2];
}
if (old != null && points != old) {
System.arraycopy(old, 0, points, 0, Math.min(old.length, n * 2));
}
- return(points);
+ return (points);
}
- private void initPoints(double[] points, int n)
- {
+ private void initPoints(double[] points, int n) {
this.points = initPoints(points, n, this.points);
numPoints = (points != null ? points.length / 2 : 0);
}
@@ -117,17 +111,18 @@
public XYArray(double[] points) {
initPoints(points, points.length / 2);
}
+
public XYArray(int n) {
- initPoints(null, n);
+ initPoints(null, n);
}
+
public XYArray() {
this(0);
}
// adding points to points array
- public void addPoints(int pos, Points pts, int start, int end)
- {
+ public void addPoints(int pos, Points pts, int start, int end) {
if (end < 0) {
end = pts.getPointCount() + end + 1;
}
@@ -143,15 +138,16 @@
setPoint(pos + count, pts.getX(start), pts.getY(start));
}
}
+
public void addPoints(int pos, Points pts) {
addPoints(pos, pts, 0, pts.getPointCount());
}
- public void appendPoints(Points pts)
- { addPoints(numPoints, pts);}
+ public void appendPoints(Points pts) {
+ addPoints(numPoints, pts);
+ }
- public static XYArray copyPoints(Points pts)
- {
+ public static XYArray copyPoints(Points pts) {
XYArray newList = new XYArray(pts.getPointCount());
newList.appendPoints(pts);
return newList;
@@ -159,39 +155,40 @@
// from MutablePoints
- public void addPoint(int pos, double x, double y)
- {
+ public void addPoint(int pos, double x, double y) {
addPoints(pos, null, 0, 1);
setPoint(pos, x, y);
}
- public void addPoint(int pos, Point2D pt)
- {
+ public void addPoint(int pos, Point2D pt) {
addPoint(pos, pt.getX(), pt.getY());
}
- public void removePoints(int pos, int num)
- {
+ public void removePoints(int pos, int num) {
num = Math.min(num, numPoints - pos);
if (num <= 0)
return;
System.arraycopy(points, (pos + num) * 2, points, pos * 2, (numPoints - (pos + num)) * 2);
numPoints -= num;
}
- public void removeAllPoints()
- { removePoints(0, numPoints);}
+
+ public void removeAllPoints() {
+ removePoints(0, numPoints);
+ }
//
- public Object clone()
- {
- XYArray ps = null;
- try { ps = (XYArray)(super.clone());}
- catch (CloneNotSupportedException e) {}
- if (ps != null) {
- ps.points = initPoints(ps.points, numPoints, points);
- ps.numPoints = numPoints;
- }
- return(ps);
+ public Object clone() {
+ XYArray ps = null;
+ try {
+ ps = (XYArray) (super.clone());
+ }
+ catch (CloneNotSupportedException e) {
+ }
+ if (ps != null) {
+ ps.points = initPoints(ps.points, numPoints, points);
+ ps.numPoints = numPoints;
+ }
+ return (ps);
}
}
diff --git a/extras/src/test/java/edu/umd/cs/piccolox/PFrameTest.java b/extras/src/test/java/edu/umd/cs/piccolox/PFrameTest.java
index ee90198..1592423 100644
--- a/extras/src/test/java/edu/umd/cs/piccolox/PFrameTest.java
+++ b/extras/src/test/java/edu/umd/cs/piccolox/PFrameTest.java
@@ -1,4 +1,5 @@
package edu.umd.cs.piccolox;
+
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.lang.reflect.InvocationTargetException;
@@ -23,6 +24,7 @@
});
Rectangle bounds = frame.getCanvas().getBounds();
assertEquals("Canvas width should match width of content pane", frame.getContentPane().getWidth(), bounds.width);
- assertEquals("Canvas height should match height of content pane", frame.getContentPane().getHeight(), bounds.height);
+ assertEquals("Canvas height should match height of content pane", frame.getContentPane().getHeight(),
+ bounds.height);
}
}
diff --git a/extras/src/test/java/edu/umd/cs/piccolox/event/PNotificationCenterTest.java b/extras/src/test/java/edu/umd/cs/piccolox/event/PNotificationCenterTest.java
index bc0252f..cb8efa3 100644
--- a/extras/src/test/java/edu/umd/cs/piccolox/event/PNotificationCenterTest.java
+++ b/extras/src/test/java/edu/umd/cs/piccolox/event/PNotificationCenterTest.java
@@ -1,55 +1,56 @@
package edu.umd.cs.piccolox.event;
+
import junit.framework.TestCase;
public class PNotificationCenterTest extends TestCase {
- boolean changed1;
- boolean changed2;
- boolean changed3;
- boolean changed4;
+ boolean changed1;
+ boolean changed2;
+ boolean changed3;
+ boolean changed4;
- public PNotificationCenterTest(String name) {
- super(name);
- }
+ public PNotificationCenterTest(String name) {
+ super(name);
+ }
- public void testToString() {
- PNotificationCenter center = PNotificationCenter.defaultCenter();
-
- center.addListener(this, "changed1", "propertyChanged", this);
- center.addListener(this, "changed2", null, this);
- center.addListener(this, "changed3", "propertyChanged", null);
- center.addListener(this, "changed4", null, null);
-
- center.postNotification("propertyChanged", this);
- assertTrue(changed1 && changed2 && changed3 && changed4);
- changed1 = changed2 = changed3 = changed4 = false;
-
- center.postNotification("propertyChanged", new Object());
- assertTrue(!changed1 && !changed2 && changed3 && changed4);
- changed1 = changed2 = changed3 = changed4 = false;
+ public void testToString() {
+ PNotificationCenter center = PNotificationCenter.defaultCenter();
- center.postNotification("otherPropertyChanged", this);
- assertTrue(!changed1 && changed2 && !changed3 && changed4);
- changed1 = changed2 = changed3 = changed4 = false;
+ center.addListener(this, "changed1", "propertyChanged", this);
+ center.addListener(this, "changed2", null, this);
+ center.addListener(this, "changed3", "propertyChanged", null);
+ center.addListener(this, "changed4", null, null);
- center.postNotification("otherPropertyChanged", new Object());
- assertTrue(!changed1 && !changed2 && !changed3 && changed4);
- changed1 = changed2 = changed3 = changed4 = false;
- }
-
- public void changed1(PNotification notification) {
- changed1 = true;
- }
+ center.postNotification("propertyChanged", this);
+ assertTrue(changed1 && changed2 && changed3 && changed4);
+ changed1 = changed2 = changed3 = changed4 = false;
- public void changed2(PNotification notification) {
- changed2 = true;
- }
-
- public void changed3(PNotification notification) {
- changed3 = true;
- }
+ center.postNotification("propertyChanged", new Object());
+ assertTrue(!changed1 && !changed2 && changed3 && changed4);
+ changed1 = changed2 = changed3 = changed4 = false;
- public void changed4(PNotification notification) {
- changed4 = true;
- }
+ center.postNotification("otherPropertyChanged", this);
+ assertTrue(!changed1 && changed2 && !changed3 && changed4);
+ changed1 = changed2 = changed3 = changed4 = false;
+
+ center.postNotification("otherPropertyChanged", new Object());
+ assertTrue(!changed1 && !changed2 && !changed3 && changed4);
+ changed1 = changed2 = changed3 = changed4 = false;
+ }
+
+ public void changed1(PNotification notification) {
+ changed1 = true;
+ }
+
+ public void changed2(PNotification notification) {
+ changed2 = true;
+ }
+
+ public void changed3(PNotification notification) {
+ changed3 = true;
+ }
+
+ public void changed4(PNotification notification) {
+ changed4 = true;
+ }
}
diff --git a/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwing.java b/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwing.java
index 7a4362e..a926262 100644
--- a/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwing.java
+++ b/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwing.java
@@ -26,114 +26,112 @@
import edu.umd.cs.piccolo.nodes.PText;
/**
- * User: Sam Reid
- * Date: Jul 11, 2005
- * Time: 12:15:55 PM
+ * User: Sam Reid Date: Jul 11, 2005 Time: 12:15:55 PM
*/
public class TestPSwing {
- public static void main( String[] args ) {
+ 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" );
+ 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 );
+ 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() );
+ 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() );
+ pCanvas.removeInputEventListener(pCanvas.getPanEventHandler());
- JButton jButton = new JButton( "MyButton!" );
- jButton.addActionListener( new ActionListener() {
- public void actionPerformed( ActionEvent e ) {
- System.out.println( "TestZSwing.actionPerformed!!!!!!!!!!!!!!*********************" );
+ 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 );
+ });
+ 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 );
+ 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" );
+ 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() );
+ });
+ 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 );
+ });
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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
+ 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();
diff --git a/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwingFull.java b/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwingFull.java
index ccfd848..70ae13d 100644
--- a/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwingFull.java
+++ b/extras/src/test/java/edu/umd/cs/piccolox/pswing/TestPSwingFull.java
@@ -43,25 +43,23 @@
import edu.umd.cs.piccolo.PNode;
/**
- * User: Sam Reid
- * Date: Jul 11, 2005
- * Time: 12:15:55 PM
+ * User: Sam Reid Date: Jul 11, 2005 Time: 12:15:55 PM
*/
public class TestPSwingFull extends JFrame {
public TestPSwingFull() {
- setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ClassLoader loader;
PSwingCanvas canvas;
// Set up basic frame
- setBounds( 50, 50, 750, 750 );
- setResizable( true );
- setBackground( null );
- setVisible( true );
+ setBounds(50, 50, 750, 750);
+ setResizable(true);
+ setBackground(null);
+ setVisible(true);
canvas = new PSwingCanvas();
- canvas.setPanEventHandler( null );
- getContentPane().add( canvas );
+ canvas.setPanEventHandler(null);
+ getContentPane().add(canvas);
validate();
loader = getClass().getClassLoader();
@@ -71,369 +69,369 @@
PSwing swing2;
// JButton
- JButton button = new JButton( "Button" );
- button.setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ) );
- swing = new PSwing(button );
- leaf = new ZVisualLeaf( swing );
+ 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 );
+ 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 );
+ 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 );
+ transform.translate(-800, -500);
+ transform.addChild(leaf);
+ canvas.getLayer().addChild(transform);
// 2nd Copy of JButton
- leaf = new ZVisualLeaf( swing );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ swing = new PSwing(slider);
+ leaf = new ZVisualLeaf(swing);
transform = new PNode();
- transform.translate( 250, -500 );
- transform.addChild( leaf );
- canvas.getLayer().addChild( transform );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 );
+ 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 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 ) );
+ 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 );
+ 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 );
+ transform.translate(250, -250);
+ transform.addChild(leaf);
+ canvas.getLayer().addChild(transform);
// A JLabel
- JLabel label = new JLabel( "A JLabel", SwingConstants.CENTER );
+ JLabel label = new JLabel("A JLabel", SwingConstants.CENTER);
- swing = new PSwing(label );
- leaf = new ZVisualLeaf( swing );
+ swing = new PSwing(label);
+ leaf = new ZVisualLeaf(swing);
transform = new PNode();
- transform.translate( -500, 0 );
- transform.addChild( leaf );
- canvas.getLayer().addChild( transform );
+ transform.translate(-500, 0);
+ transform.addChild(leaf);
+ canvas.getLayer().addChild(transform);
// Rotated copy of the Scrollable JTextArea
- leaf = new ZVisualLeaf( swing2 );
+ leaf = new ZVisualLeaf(swing2);
transform = new PNode();
- transform.translate( -100, 0 );
- transform.rotate( Math.PI / 2 );
- transform.addChild( leaf );
- canvas.getLayer().addChild( transform );
+ 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 = 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 );
+ swing = new PSwing(panel);
+ leaf = new ZVisualLeaf(swing);
transform = new PNode();
- transform.translate( 0, 0 );
- transform.addChild( leaf );
- canvas.getLayer().addChild( transform );
+ 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" );
+ 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.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.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.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.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.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.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.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.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 );
+ 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 );
+ 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 ) {
+ 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() );
+ editorPane.setPage(e.getURL());
}
- catch( IOException ioe ) {
- System.out.println( "Couldn't Load Web Page" );
+ catch (IOException ioe) {
+ System.out.println("Couldn't Load Web Page");
}
}
}
- } );
- swing = new PSwing(pane );
- leaf = new ZVisualLeaf( swing );
+ });
+ swing = new PSwing(pane);
+ leaf = new ZVisualLeaf(swing);
transform = new PNode();
- transform.translate( -500, 250 );
- transform.addChild( leaf );
- canvas.getLayer().addChild( transform );
+ transform.translate(-500, 250);
+ transform.addChild(leaf);
+ canvas.getLayer().addChild(transform);
}
- catch( IOException ioe ) {
- System.out.println( "Couldn't Load Web Page" );
+ 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 ) );
+ 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 ) );
+ 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!" ) {
+ Action letter = new AbstractAction("Big A!") {
- public void actionPerformed( ActionEvent e ) {
+ public void actionPerformed(ActionEvent e) {
}
};
- Action hand = new AbstractAction( "Hi!" ) {
- 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 ) {
+ 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" );
+ 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 );
+ 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 );
+ 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 );
+ // 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 );
+ 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 );
+ // 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 );
+ 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 );
+ 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 );
+ canvas.getCamera().animateViewToCenterBounds(message.getFullBounds(), false, 1200);
}
- public static void main( String[] args ) {
- new TestPSwingFull().setVisible( true );
+ public static void main(String[] args) {
+ new TestPSwingFull().setVisible(true);
}
public static class ZVisualLeaf extends PNode {
- public ZVisualLeaf( PNode node ) {
- addChild( node );
+ public ZVisualLeaf(PNode node) {
+ addChild(node);
}
}
diff --git a/extras/src/test/java/edu/umd/cs/piccolox/util/PFixedWidthStrokeTest.java b/extras/src/test/java/edu/umd/cs/piccolox/util/PFixedWidthStrokeTest.java
index e9fd380..e21390c 100644
--- a/extras/src/test/java/edu/umd/cs/piccolox/util/PFixedWidthStrokeTest.java
+++ b/extras/src/test/java/edu/umd/cs/piccolox/util/PFixedWidthStrokeTest.java
@@ -5,12 +5,12 @@
import junit.framework.TestCase;
public class PFixedWidthStrokeTest extends TestCase {
- public void testContants() {
- assertEquals(PFixedWidthStroke.CAP_BUTT, BasicStroke.CAP_BUTT);
- assertEquals(PFixedWidthStroke.CAP_ROUND, BasicStroke.CAP_ROUND);
- assertEquals(PFixedWidthStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE);
- assertEquals(PFixedWidthStroke.JOIN_BEVEL, BasicStroke.JOIN_BEVEL);
- assertEquals(PFixedWidthStroke.JOIN_MITER, BasicStroke.JOIN_MITER);
- assertEquals(PFixedWidthStroke.JOIN_ROUND, BasicStroke.JOIN_ROUND);
- }
+ public void testContants() {
+ assertEquals(PFixedWidthStroke.CAP_BUTT, BasicStroke.CAP_BUTT);
+ assertEquals(PFixedWidthStroke.CAP_ROUND, BasicStroke.CAP_ROUND);
+ assertEquals(PFixedWidthStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE);
+ assertEquals(PFixedWidthStroke.JOIN_BEVEL, BasicStroke.JOIN_BEVEL);
+ assertEquals(PFixedWidthStroke.JOIN_MITER, BasicStroke.JOIN_MITER);
+ assertEquals(PFixedWidthStroke.JOIN_ROUND, BasicStroke.JOIN_ROUND);
+ }
}