[Arakhnę-Dev] [404] * Add utility functions on zoomable contexts. |
[ Thread Index |
Date Index
| More arakhne.org/dev Archives
]
Revision: 404
Author: galland
Date: 2013-04-04 09:10:14 +0200 (Thu, 04 Apr 2013)
Log Message:
-----------
* Add utility functions on zoomable contexts.
Modified Paths:
--------------
trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContext.java
trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContextUtil.java
trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/actionmode/ActionModeManager.java
trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/event/PointerEvent.java
trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/InternalZoomablePanel.java
trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/ZoomableGraphics2D.java
Added Paths:
-----------
trunk/ui/ui-awt/src/main/java/org/arakhne/afc/ui/awt/ZoomableAwtContextUtil.java
Added: trunk/ui/ui-awt/src/main/java/org/arakhne/afc/ui/awt/ZoomableAwtContextUtil.java
===================================================================
--- trunk/ui/ui-awt/src/main/java/org/arakhne/afc/ui/awt/ZoomableAwtContextUtil.java (rev 0)
+++ trunk/ui/ui-awt/src/main/java/org/arakhne/afc/ui/awt/ZoomableAwtContextUtil.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -0,0 +1,695 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2005-09 Stephane GALLAND.
+ * Copyright (C) 2013 Stephane GALLAND.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.afc.ui.awt;
+
+import java.awt.Font;
+import java.awt.Polygon;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Area;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+
+import org.arakhne.afc.ui.CenteringTransform;
+
+/** Utilities for ZoomableContext with additional functions
+ * dedicated to AWT objects.
+ *
+ * @author $Author: sgalland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+public class ZoomableAwtContextUtil extends org.arakhne.afc.ui.ZoomableContextUtil {
+
+ private static void create(
+ PathIterator pathIterator,
+ CenteringTransform centeringTransform,
+ float zoom,
+ Path2D output) {
+ float[] coords = new float[8];
+ while (!pathIterator.isDone()) {
+ switch(pathIterator.currentSegment(coords)) {
+ case PathIterator.SEG_MOVETO:
+ output.moveTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_LINETO:
+ output.lineTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CUBICTO:
+ output.curveTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom),
+ logical2pixel_x(coords[2], centeringTransform, zoom),
+ logical2pixel_y(coords[3], centeringTransform, zoom),
+ logical2pixel_x(coords[4], centeringTransform, zoom),
+ logical2pixel_y(coords[5], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_QUADTO:
+ output.quadTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom),
+ logical2pixel_x(coords[2], centeringTransform, zoom),
+ logical2pixel_y(coords[3], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CLOSE:
+ output.closePath();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ pathIterator.next();
+ }
+ }
+
+ private static void create2(
+ Shape s,
+ CenteringTransform centeringTransform,
+ float zoom,
+ Path2D output) {
+ PathIterator it = s.getPathIterator(new AffineTransform());
+ float[] coords = new float[8];
+ while (!it.isDone()) {
+ switch(it.currentSegment(coords)) {
+ case PathIterator.SEG_MOVETO:
+ output.moveTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_LINETO:
+ output.lineTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CUBICTO:
+ output.curveTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom),
+ pixel2logical_x(coords[2], centeringTransform, zoom),
+ pixel2logical_y(coords[3], centeringTransform, zoom),
+ pixel2logical_x(coords[4], centeringTransform, zoom),
+ pixel2logical_y(coords[5], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_QUADTO:
+ output.quadTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom),
+ pixel2logical_x(coords[2], centeringTransform, zoom),
+ pixel2logical_y(coords[3], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CLOSE:
+ output.closePath();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ it.next();
+ }
+ }
+
+ /** Replies the transformation matrix which is corresponding to
+ * the given {@link CenteringTransform} and with a zooming
+ * factor.
+ * <p>
+ * <code>
+ * | transform.scaleX*zoom 0 transform.translationX*zoom |
+ * | 0 transform.scaleY*zoom transform.translationY*zoom |
+ * | 0 0 1 |
+ * </code>
+ *
+ * @param transform
+ * @param zoom
+ * @return the transformation matrix.
+ */
+ public static AffineTransform getMatrix(CenteringTransform transform, float zoom) {
+ return new AffineTransform(
+ transform.getScaleX()*zoom, 0,
+ 0, transform.getScaleY()*zoom,
+ transform.getTranslationX()*zoom,
+ transform.getTranslationY()*zoom);
+ }
+
+ /** Replies the transformation matrix which is corresponding to
+ * the given {@link CenteringTransform} but without a zoom.
+ * <p>
+ * <code>
+ * | transform.scaleX 0 transform.translationX*zoom |
+ * | 0 transform.scaleY transform.translationY*zoom |
+ * | 0 0 1 |
+ * </code>
+ *
+ * @param transform
+ * @param zoom
+ * @return the transformation matrix.
+ */
+ public static AffineTransform getMatrixNoScaling(CenteringTransform transform, float zoom) {
+ return new AffineTransform(
+ transform.getScaleX(), 0,
+ 0, transform.getScaleY(),
+ transform.getTranslationX()*zoom,
+ transform.getTranslationY()*zoom);
+ }
+
+ /** Translates the specified rectangle
+ * into the screen space.
+ *
+ * @param r is the rectangle in the logical space when input and the
+ * same rectangle in screen space when output.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ */
+ public static void logical2pixel(Rectangle2D r,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ assert(r!=null);
+ assert(centeringTransform!=null);
+ float x = (float)(centeringTransform.isXAxisFlipped() ? r.getMaxX() : r.getMinX());
+ float y = (float)(centeringTransform.isYAxisFlipped() ? r.getMaxY() : r.getMinY());
+ r.setFrame(
+ logical2pixel_x(x, centeringTransform, zoom),
+ logical2pixel_y(y, centeringTransform, zoom),
+ logical2pixel_size((float)r.getWidth(), zoom),
+ logical2pixel_size((float)r.getHeight(), zoom));
+ }
+
+ /** Translates the specified rectangle
+ * into the logical space.
+ *
+ * @param r is the rectangle in the screen space when input and the
+ * same rectangle in logical space when output.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ */
+ public static void pixel2logical(Rectangle2D r,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ assert(r!=null);
+ assert(centeringTransform!=null);
+ float x = (float)(centeringTransform.isXAxisFlipped() ? r.getMaxX() : r.getMinX());
+ float y = (float)(centeringTransform.isYAxisFlipped() ? r.getMaxY() : r.getMinY());
+ r.setFrame(
+ pixel2logical_x(x, centeringTransform, zoom),
+ pixel2logical_y(y, centeringTransform, zoom),
+ pixel2logical_size((float)r.getWidth(), zoom),
+ pixel2logical_size((float)r.getHeight(), zoom));
+ }
+
+ /** Translate the specified font from a logical length to a screen length.
+ *
+ * @param font is the font with a size in the logical coordinate system.
+ * @param zoom is the current zooming factor of the view.
+ * @return the font with a size suitable for the screen coordinate system.
+ */
+ public static Font logical2pixel(Font font, float zoom) {
+ float nSize = logical2pixel_size(font.getSize2D(), zoom);
+ return font.deriveFont(nSize);
+ }
+
+ /** Translate the specified font from a screen length to a logical length.
+ *
+ * @param font is the font with a size in the screen coordinate system.
+ * @param zoom is the current zooming factor of the view.
+ * @return the font with a size suitable for the logical coordinate system.
+ */
+ public static Font pixel2logical(Font font, float zoom) {
+ float nSize = pixel2logical_size(font.getSize2D(), zoom);
+ return font.deriveFont(nSize);
+ }
+
+ /** Translates the specified point
+ * into the screen space.
+ *
+ * @param p is the point in the logical space when input and the
+ * same point in screen space when output.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ */
+ public static void logical2pixel(Point2D p,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ assert(p!=null);
+ assert(centeringTransform!=null);
+ p.setLocation(
+ logical2pixel_x((float)p.getX(), centeringTransform, zoom),
+ logical2pixel_y((float)p.getY(), centeringTransform, zoom));
+ }
+
+ /** Translates the specified point
+ * into the logical space.
+ *
+ * @param p is the point in the screen space when input and the
+ * same point in logical space when output.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ */
+ public static void pixel2logical(Point2D p,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ assert(p!=null);
+ assert(centeringTransform!=null);
+ p.setLocation(
+ pixel2logical_x((float)p.getX(), centeringTransform, zoom),
+ pixel2logical_y((float)p.getY(), centeringTransform, zoom));
+ }
+
+ /** Translates the specified path
+ * into the screen space.
+ *
+ * @param p is the path in the logical.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ * @param the path is screen path.
+ */
+ public static Path2D logical2pixel(PathIterator p,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ Path2D path = new Path2D.Float();
+ float[] coords = new float[6];
+ while(!p.isDone()) {
+ switch(p.currentSegment(coords)) {
+ case PathIterator.SEG_MOVETO:
+ path.moveTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_LINETO:
+ path.lineTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_QUADTO:
+ path.quadTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom),
+ logical2pixel_x(coords[2], centeringTransform, zoom),
+ logical2pixel_y(coords[3], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CUBICTO:
+ path.curveTo(
+ logical2pixel_x(coords[0], centeringTransform, zoom),
+ logical2pixel_y(coords[1], centeringTransform, zoom),
+ logical2pixel_x(coords[2], centeringTransform, zoom),
+ logical2pixel_y(coords[3], centeringTransform, zoom),
+ logical2pixel_x(coords[4], centeringTransform, zoom),
+ logical2pixel_y(coords[5], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CLOSE:
+ path.closePath();
+ break;
+ default:
+ }
+ p.next();
+ }
+ return path;
+ }
+
+ /** Translates the specified path
+ * into the logical space.
+ *
+ * @param p is the path in the screen space.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ * @return the path in logical space.
+ */
+ public static Path2D pixel2logical(PathIterator p,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ Path2D path = new Path2D.Float();
+ float[] coords = new float[6];
+ while(!p.isDone()) {
+ switch(p.currentSegment(coords)) {
+ case PathIterator.SEG_MOVETO:
+ path.moveTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_LINETO:
+ path.lineTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_QUADTO:
+ path.quadTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom),
+ pixel2logical_x(coords[2], centeringTransform, zoom),
+ pixel2logical_y(coords[3], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CUBICTO:
+ path.curveTo(
+ pixel2logical_x(coords[0], centeringTransform, zoom),
+ pixel2logical_y(coords[1], centeringTransform, zoom),
+ pixel2logical_x(coords[2], centeringTransform, zoom),
+ pixel2logical_y(coords[3], centeringTransform, zoom),
+ pixel2logical_x(coords[4], centeringTransform, zoom),
+ pixel2logical_y(coords[5], centeringTransform, zoom));
+ break;
+ case PathIterator.SEG_CLOSE:
+ path.closePath();
+ break;
+ default:
+ }
+ p.next();
+ }
+ return path;
+ }
+
+ /** Translates the specified shape
+ * into the screen space.
+ *
+ * @param <T> is the type of shape to convert.
+ * @param s is the shape in the logical space.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ * @return a shape into the screen space.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Shape> T logical2pixel(
+ T s, CenteringTransform centeringTransform, float zoom) {
+ if (s==null) return null;
+ SupportedShape type = SupportedShape.getTypeOf(s.getClass());
+ try {
+ switch(type) {
+ case RECTANGLE2D:
+ {
+ Rectangle2D r = (Rectangle2D)s;
+ float x = (float)((centeringTransform.isXAxisFlipped()) ? r.getMaxX() : r.getMinX());
+ float y = (float)((centeringTransform.isYAxisFlipped()) ? r.getMaxY() : r.getMinY());
+ return (T)new Rectangle2D.Double(
+ logical2pixel_x(x, centeringTransform, zoom),
+ logical2pixel_y(y, centeringTransform, zoom),
+ logical2pixel_size((float)r.getWidth(), zoom),
+ logical2pixel_size((float)r.getHeight(), zoom));
+ }
+ case ROUND_RECTANGLE:
+ {
+ RoundRectangle2D r = (RoundRectangle2D)s;
+ float x = (float)((centeringTransform.isXAxisFlipped()) ? r.getMaxX() : r.getMinX());
+ float y = (float)((centeringTransform.isYAxisFlipped()) ? r.getMaxY() : r.getMinY());
+ return (T)new RoundRectangle2D.Double(
+ logical2pixel_x(x, centeringTransform, zoom),
+ logical2pixel_y(y, centeringTransform, zoom),
+ logical2pixel_size((float)r.getWidth(), zoom),
+ logical2pixel_size((float)r.getHeight(), zoom),
+ logical2pixel_size((float)r.getArcWidth(), zoom),
+ logical2pixel_size((float)r.getArcHeight(), zoom));
+ }
+ case ELLIPSE:
+ {
+ Ellipse2D e = (Ellipse2D)s;
+ float x = (float)((centeringTransform.isXAxisFlipped()) ? e.getMaxX() : e.getMinX());
+ float y = (float)((centeringTransform.isYAxisFlipped()) ? e.getMaxY() : e.getMinY());
+ return (T)new Ellipse2D.Double(
+ logical2pixel_x(x, centeringTransform, zoom),
+ logical2pixel_y(y, centeringTransform, zoom),
+ logical2pixel_size((float)e.getWidth(), zoom),
+ logical2pixel_size((float)e.getHeight(), zoom));
+ }
+ case LINE:
+ {
+ Line2D l = (Line2D)s;
+ return (T)new Line2D.Double(
+ logical2pixel_x((float)l.getX1(), centeringTransform, zoom),
+ logical2pixel_y((float)l.getY1(), centeringTransform, zoom),
+ logical2pixel_x((float)l.getX2(), centeringTransform, zoom),
+ logical2pixel_y((float)l.getY2(), centeringTransform, zoom));
+ }
+ case ARC:
+ {
+ Arc2D a = (Arc2D)s;
+ float x = (float)((centeringTransform.isXAxisFlipped()) ? a.getMaxX() : a.getMinX());
+ float y = (float)((centeringTransform.isYAxisFlipped()) ? a.getMaxY() : a.getMinY());
+ return (T)new Arc2D.Double(
+ logical2pixel_x(x, centeringTransform, zoom),
+ logical2pixel_y(y, centeringTransform, zoom),
+ logical2pixel_size((float)a.getWidth(), zoom),
+ logical2pixel_size((float)a.getHeight(), zoom),
+ a.getAngleStart(),
+ a.getAngleExtent(),
+ a.getArcType());
+ }
+ case POLYGON:
+ {
+ Polygon p = (Polygon)s ;
+ float x, y;
+ GeneralPath p2 = new GeneralPath() ;
+ for( int i=0; i < p.npoints; ++i ) {
+ x = logical2pixel_x(p.xpoints[i], centeringTransform, zoom);
+ y = logical2pixel_y(p.ypoints[i], centeringTransform, zoom);
+ if (i==0)
+ p2.moveTo(x, y);
+ else
+ p2.lineTo(x, y);
+ }
+ p2.closePath();
+ return (T)p2 ;
+ }
+ case CUBIC_CURVE:
+ {
+ CubicCurve2D c = (CubicCurve2D)s ;
+ return (T)new CubicCurve2D.Double(
+ logical2pixel_x((float)c.getX1(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getY1(), centeringTransform, zoom),
+ logical2pixel_x((float)c.getCtrlX1(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getCtrlY1(), centeringTransform, zoom),
+ logical2pixel_x((float)c.getCtrlX2(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getCtrlY2(), centeringTransform, zoom),
+ logical2pixel_x((float)c.getX2(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getY2(), centeringTransform, zoom));
+ }
+ case QUAD_CURVE:
+ {
+ QuadCurve2D c = (QuadCurve2D)s ;
+ return (T)new QuadCurve2D.Double(
+ logical2pixel_x((float)c.getX1(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getY1(), centeringTransform, zoom),
+ logical2pixel_x((float)c.getCtrlX(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getCtrlY(), centeringTransform, zoom),
+ logical2pixel_x((float)c.getX2(), centeringTransform, zoom),
+ logical2pixel_y((float)c.getY2(), centeringTransform, zoom));
+ }
+ case PATH:
+ {
+ Path2D p = (Path2D)s;
+ Path2D p2 = new GeneralPath(p.getWindingRule());
+ create(
+ p.getPathIterator(null), centeringTransform, zoom, p2);
+ return (T)p2;
+ }
+ case AREA:
+ {
+ Area a = (Area)s ;
+ GeneralPath p2 = new GeneralPath();
+ create(
+ a.getPathIterator(null),
+ centeringTransform, zoom, p2);
+ return (T)new Area(p2);
+ }
+ case VIRTUALIZABLE_SHAPE:
+ {
+ VirtualizableShape vs = (VirtualizableShape)s;
+ return (T)vs.toScreen(centeringTransform, zoom);
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ catch(ClassCastException _) {
+ //
+ }
+
+ throw new UnsupportedShapeException(type);
+ }
+
+ /** Translates the specified shape
+ * into the logical space.
+ *
+ * @param <T> is the type of shape to convert.
+ * @param s is the shape in the screen space.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ * @return a shape into the logical space.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Shape> T pixel2logical(
+ T s, CenteringTransform centeringTransform, float zoom) {
+ if (s==null) return null;
+ SupportedShape type = SupportedShape.getTypeOf(s.getClass());
+ try {
+ switch(type) {
+ case RECTANGLE2D:
+ {
+ Rectangle2D r = (Rectangle2D)s;
+ float x = (float)((centeringTransform.isXAxisFlipped()) ? r.getMaxX() : r.getMinX());
+ float y = (float)((centeringTransform.isYAxisFlipped()) ? r.getMaxY() : r.getMinY());
+ return (T)new Rectangle2D.Double(
+ pixel2logical_x(x, centeringTransform, zoom),
+ pixel2logical_y(y, centeringTransform, zoom),
+ pixel2logical_size((float)r.getWidth(), zoom),
+ pixel2logical_size((float)r.getHeight(), zoom));
+ }
+ case ROUND_RECTANGLE:
+ {
+ RoundRectangle2D r = (RoundRectangle2D)s;
+ float x = (float) ((centeringTransform.isXAxisFlipped()) ? r.getMaxX() : r.getMinX());
+ float y = (float) ((centeringTransform.isYAxisFlipped()) ? r.getMaxY() : r.getMinY());
+ return (T)new RoundRectangle2D.Double(
+ pixel2logical_x(x, centeringTransform, zoom),
+ pixel2logical_y(y, centeringTransform, zoom),
+ pixel2logical_size((float)r.getWidth(), zoom),
+ pixel2logical_size((float)r.getHeight(), zoom),
+ pixel2logical_size((float)r.getArcWidth(), zoom),
+ pixel2logical_size((float)r.getArcHeight(), zoom));
+ }
+ case ELLIPSE:
+ {
+ Ellipse2D e = (Ellipse2D)s;
+ float x = (float) ((centeringTransform.isXAxisFlipped()) ? e.getMaxX() : e.getMinX());
+ float y = (float) ((centeringTransform.isYAxisFlipped()) ? e.getMaxY() : e.getMinY());
+ return (T)new Ellipse2D.Double(
+ pixel2logical_x(x, centeringTransform, zoom),
+ pixel2logical_y(y, centeringTransform, zoom),
+ pixel2logical_size((float)e.getWidth(), zoom),
+ pixel2logical_size((float)e.getHeight(), zoom));
+ }
+ case LINE:
+ {
+ Line2D l = (Line2D)s;
+ return (T)new Line2D.Double(
+ pixel2logical_x((float)l.getX1(), centeringTransform, zoom),
+ pixel2logical_y((float)l.getY1(), centeringTransform, zoom),
+ pixel2logical_x((float)l.getX2(), centeringTransform, zoom),
+ pixel2logical_y((float)l.getY2(), centeringTransform, zoom));
+ }
+ case ARC:
+ {
+ Arc2D a = (Arc2D)s;
+ float x = (float) ((centeringTransform.isXAxisFlipped()) ? a.getMaxX() : a.getMinX());
+ float y = (float) ((centeringTransform.isYAxisFlipped()) ? a.getMaxY() : a.getMinY());
+ return (T)new Arc2D.Double(
+ pixel2logical_x(x, centeringTransform, zoom),
+ pixel2logical_y(y, centeringTransform, zoom),
+ pixel2logical_size((float)a.getWidth(), zoom),
+ pixel2logical_size((float)a.getHeight(), zoom),
+ a.getAngleStart(),
+ a.getAngleExtent(),
+ a.getArcType());
+ }
+ case POLYGON:
+ {
+ Polygon p = (Polygon)s ;
+ GeneralPath p2 = new GeneralPath() ;
+ float x, y;
+ for( int i=0; i < p.npoints; ++i ) {
+ x = pixel2logical_x(p.xpoints[i], centeringTransform, zoom);
+ y = pixel2logical_y(p.ypoints[i], centeringTransform, zoom);
+ if (i==0) p2.moveTo(x, y);
+ else p2.lineTo(x, y);
+ }
+ p2.closePath();
+ return (T)p2 ;
+ }
+ case CUBIC_CURVE:
+ {
+ CubicCurve2D c = (CubicCurve2D)s ;
+ return (T)new CubicCurve2D.Double(
+ pixel2logical_x((float)c.getX1(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getY1(), centeringTransform, zoom),
+ pixel2logical_x((float)c.getCtrlX1(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getCtrlY1(), centeringTransform, zoom),
+ pixel2logical_x((float)c.getCtrlX2(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getCtrlY2(), centeringTransform, zoom),
+ pixel2logical_x((float)c.getX2(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getY2(), centeringTransform, zoom));
+ }
+ case QUAD_CURVE:
+ {
+ QuadCurve2D c = (QuadCurve2D)s ;
+ return (T)new QuadCurve2D.Double(
+ pixel2logical_x((float)c.getX1(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getY1(), centeringTransform, zoom),
+ pixel2logical_x((float)c.getCtrlX(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getCtrlY(), centeringTransform, zoom),
+ pixel2logical_x((float)c.getX2(), centeringTransform, zoom),
+ pixel2logical_y((float)c.getY2(), centeringTransform, zoom));
+ }
+ case PATH:
+ {
+ Path2D p = (Path2D)s;
+ Path2D p2 = new GeneralPath(p.getWindingRule());
+ create2(p, centeringTransform, zoom, p2);
+ return (T)p2;
+ }
+ case AREA:
+ {
+ Area a = (Area)s ;
+ GeneralPath p2 = new GeneralPath();
+ create2(a, centeringTransform, zoom, p2);
+ return (T)new Area(p2);
+ }
+ case VIRTUALIZABLE_SHAPE:
+ {
+ VirtualizableShape vs = (VirtualizableShape)s;
+ return (T)vs.fromScreen(centeringTransform, zoom);
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ catch(ClassCastException _) {
+ //
+ }
+
+ throw new UnsupportedShapeException(type);
+ }
+
+}
\ No newline at end of file
Modified: trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContext.java
===================================================================
--- trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContext.java 2013-03-31 09:26:05 UTC (rev 403)
+++ trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContext.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -29,6 +29,7 @@
import org.arakhne.afc.math.continous.object2d.Rectangle2f;
import org.arakhne.afc.math.continous.object2d.RoundRectangle2f;
import org.arakhne.afc.math.continous.object2d.Segment2f;
+import org.arakhne.afc.math.continous.object2d.Shape2f;
/** This interface describes a zooming context and
* permits to make some operation in it.
@@ -200,6 +201,32 @@
*/
public void pixel2logical(Rectangle2f r);
+ /** Translates the specified shape
+ * into the screen space.
+ * <p>
+ * <strong>CAUTION:</strong> You must prefer to invoke
+ * one of the other functions of this ZoomableContext
+ * to run a faster translation algorithm than the
+ * algorithm implemented in this function.
+ *
+ * @param s is the shape in the logical space when input and the
+ * same shape in screen space when output.
+ */
+ public Shape2f logical2pixel(Shape2f s);
+
+ /** Translates the specified shape
+ * into the logical space.
+ * <p>
+ * <strong>CAUTION:</strong> You must prefer to invoke
+ * one of the other functions of this ZoomableContext
+ * to run a faster translation algorithm than the
+ * algorithm implemented in this function.
+ *
+ * @param s is the shape in the screen space when input and the
+ * same shape in logical space when output.
+ */
+ public Shape2f pixel2logical(Shape2f s);
+
/** Replies the graphical zoom factor.
*
* @return the scale factor.
Modified: trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContextUtil.java
===================================================================
--- trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContextUtil.java 2013-03-31 09:26:05 UTC (rev 403)
+++ trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/ZoomableContextUtil.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -24,12 +24,14 @@
import org.arakhne.afc.math.continous.object2d.Circle2f;
import org.arakhne.afc.math.continous.object2d.Ellipse2f;
+import org.arakhne.afc.math.continous.object2d.Path2f;
import org.arakhne.afc.math.continous.object2d.PathElement2f;
import org.arakhne.afc.math.continous.object2d.PathIterator2f;
import org.arakhne.afc.math.continous.object2d.Point2f;
import org.arakhne.afc.math.continous.object2d.Rectangle2f;
import org.arakhne.afc.math.continous.object2d.RoundRectangle2f;
import org.arakhne.afc.math.continous.object2d.Segment2f;
+import org.arakhne.afc.math.continous.object2d.Shape2f;
import org.arakhne.afc.math.generic.PathWindingRule;
/** Utilities for ZoomableContext.
@@ -347,6 +349,102 @@
pixel2logical_size(r.getHeight(), zoom));
}
+ /** Translates the specified shape
+ * into the screen space.
+ * <p>
+ * <strong>CAUTION:</strong> You must prefer to invoke
+ * one of the other functions of this ZoomableContext
+ * to run a faster translation algorithm than the
+ * algorithm implemented in this function.
+ *
+ * @param s is the shape in the logical space to translate.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ * @return the result of the translation.
+ */
+ public static Shape2f logical2pixel(Shape2f s,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ assert(s!=null);
+ assert(centeringTransform!=null);
+ if (s instanceof Rectangle2f) {
+ Rectangle2f r = ((Rectangle2f)s).clone();
+ logical2pixel(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof Circle2f) {
+ Circle2f r = ((Circle2f)s).clone();
+ logical2pixel(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof Ellipse2f) {
+ Ellipse2f r = ((Ellipse2f)s).clone();
+ logical2pixel(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof RoundRectangle2f) {
+ RoundRectangle2f r = ((RoundRectangle2f)s).clone();
+ logical2pixel(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof Segment2f) {
+ Segment2f r = ((Segment2f)s).clone();
+ logical2pixel(r, centeringTransform, zoom);
+ return r;
+ }
+ return new Path2f(logical2pixel(s.getPathIterator(), centeringTransform, zoom));
+ }
+
+ /** Translates the specified shape
+ * into the logical space.
+ * <p>
+ * <strong>CAUTION:</strong> You must prefer to invoke
+ * one of the other functions of this ZoomableContext
+ * to run a faster translation algorithm than the
+ * algorithm implemented in this function.
+ *
+ * @param s is the shape in the screen space to translate.
+ * @param centeringTransform is the transform to apply to the points to change from/to the coordinate
+ * system from the "global" logical coordinate system to/from the "centered" logical coordinate
+ * system.
+ * @param zoom is the current zooming factor of the view.
+ * @return the result of the translation.
+ */
+ public static Shape2f pixel2logical(Shape2f s,
+ CenteringTransform centeringTransform,
+ float zoom) {
+ assert(s!=null);
+ assert(centeringTransform!=null);
+ if (s instanceof Rectangle2f) {
+ Rectangle2f r = ((Rectangle2f)s).clone();
+ pixel2logical(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof Circle2f) {
+ Circle2f r = ((Circle2f)s).clone();
+ pixel2logical(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof Ellipse2f) {
+ Ellipse2f r = ((Ellipse2f)s).clone();
+ pixel2logical(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof RoundRectangle2f) {
+ RoundRectangle2f r = ((RoundRectangle2f)s).clone();
+ pixel2logical(r, centeringTransform, zoom);
+ return r;
+ }
+ if (s instanceof Segment2f) {
+ Segment2f r = ((Segment2f)s).clone();
+ pixel2logical(r, centeringTransform, zoom);
+ return r;
+ }
+ return new Path2f(logical2pixel(s.getPathIterator(), centeringTransform, zoom));
+ }
+
/** Translates the specified workspace location
* into the screen location.
*
Modified: trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/actionmode/ActionModeManager.java
===================================================================
--- trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/actionmode/ActionModeManager.java 2013-03-31 09:26:05 UTC (rev 403)
+++ trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/actionmode/ActionModeManager.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -32,6 +32,7 @@
import java.util.UUID;
import org.arakhne.afc.math.continous.object2d.Point2f;
+import org.arakhne.afc.math.continous.object2d.Shape2f;
import org.arakhne.afc.math.generic.Point2D;
import org.arakhne.afc.ui.ZoomableContext;
import org.arakhne.afc.ui.event.KeyEvent;
@@ -76,6 +77,7 @@
private float mouseX = Float.NaN;
private float mouseY = Float.NaN;
+ private Shape2f mouseArea = null;
private final ListenerCollection<EventListener> listeners = new ListenerCollection<EventListener>();
@@ -707,12 +709,19 @@
if (zc!=null) {
this.mouseX = zc.pixel2logical_x(e.getX());
this.mouseY = zc.pixel2logical_y(e.getY());
+ this.mouseArea = zc.pixel2logical(e.getToolArea(0));
}
else {
this.mouseX = e.getX();
this.mouseY = e.getY();
+ this.mouseArea = e.getToolArea(0);
}
}
+ else {
+ this.mouseX = e.getX();
+ this.mouseY = e.getY();
+ this.mouseArea = e.getToolArea(0);
+ }
}
/** Replies the current position of the mouse in the document.
@@ -742,4 +751,12 @@
return this.mouseY;
}
+ /** Replies the area covered by the pointer.
+ *
+ * @return the area covered by the pointer.
+ */
+ public Shape2f getMouseArea() {
+ return this.mouseArea;
+ }
+
}
Modified: trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/event/PointerEvent.java
===================================================================
--- trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/event/PointerEvent.java 2013-03-31 09:26:05 UTC (rev 403)
+++ trunk/ui/ui-base/src/main/java/org/arakhne/afc/ui/event/PointerEvent.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -113,7 +113,7 @@
*/
public int getPointerCount();
- /** Returns an ellipse that describes the size of the approaching
+ /** Returns a shape that describes the size of the approaching
* tool for the given pointer index. The tool area represents
* the estimated size of the finger or pen that is touching the
* device independent of its actual touch area at the point of contact.
Modified: trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/InternalZoomablePanel.java
===================================================================
--- trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/InternalZoomablePanel.java 2013-03-31 09:26:05 UTC (rev 403)
+++ trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/InternalZoomablePanel.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -47,6 +47,7 @@
import org.arakhne.afc.math.continous.object2d.Rectangle2f;
import org.arakhne.afc.math.continous.object2d.RoundRectangle2f;
import org.arakhne.afc.math.continous.object2d.Segment2f;
+import org.arakhne.afc.math.continous.object2d.Shape2f;
import org.arakhne.afc.ui.CenteringTransform;
import org.arakhne.afc.ui.Graphics2DLOD;
import org.arakhne.afc.ui.ZoomableContextUtil;
@@ -1009,4 +1010,16 @@
this.fitToWindowFactor * this.zoomFactor);
}
+ @Override
+ public Shape2f logical2pixel(Shape2f s) {
+ return ZoomableContextUtil.logical2pixel(s, this.centeringTransform,
+ this.fitToWindowFactor * this.zoomFactor);
+ }
+
+ @Override
+ public Shape2f pixel2logical(Shape2f s) {
+ return ZoomableContextUtil.pixel2logical(s, this.centeringTransform,
+ this.fitToWindowFactor * this.zoomFactor);
+ }
+
}
Modified: trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/ZoomableGraphics2D.java
===================================================================
--- trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/ZoomableGraphics2D.java 2013-03-31 09:26:05 UTC (rev 403)
+++ trunk/ui/ui-swing/src/main/java/org/arakhne/afc/ui/swing/zoompanel/ZoomableGraphics2D.java 2013-04-04 07:10:14 UTC (rev 404)
@@ -62,6 +62,7 @@
import org.arakhne.afc.math.continous.object2d.Rectangle2f;
import org.arakhne.afc.math.continous.object2d.RoundRectangle2f;
import org.arakhne.afc.math.continous.object2d.Segment2f;
+import org.arakhne.afc.math.continous.object2d.Shape2f;
import org.arakhne.afc.ui.CenteringTransform;
import org.arakhne.afc.ui.Graphics2DLOD;
import org.arakhne.afc.ui.StringAnchor;
@@ -1664,6 +1665,16 @@
ZoomableContextUtil.pixel2logical(r, this.centeringTransform, this.zoomFactor);
}
+ @Override
+ public Shape2f logical2pixel(Shape2f s) {
+ return ZoomableContextUtil.logical2pixel(s, this.centeringTransform, this.zoomFactor);
+ }
+
+ @Override
+ public Shape2f pixel2logical(Shape2f s) {
+ return ZoomableContextUtil.pixel2logical(s, this.centeringTransform, this.zoomFactor);
+ }
+
/**
* Return the rectangle that corresponds to the displayed
* area.