+ */
+public class Rectangle implements Serializable {
+
+ /**
+ * The X coordinate of the upper-left corner of the Rectangle
.
+ *
+ * @serial
+ * @see #setLocation(int, int)
+ * @see #getLocation()
+ */
+ public int x;
+
+ /**
+ * The Y coordinate of the upper-left corner of the Rectangle
.
+ *
+ * @serial
+ * @see #setLocation(int, int)
+ * @see #getLocation()
+ */
+ public int y;
+
+ /**
+ * The width of the Rectangle
.
+ * @serial
+ * @see #setSize(int, int)
+ * @see #getSize()
+ */
+ public int width;
+
+ /**
+ * The height of the Rectangle
.
+ *
+ * @serial
+ * @see #setSize(int, int)
+ * @see #getSize()
+ */
+ public int height;
+
+ /*
+ * JDK 1.1 serialVersionUID
+ */
+ private static final long serialVersionUID = -4345857070255674764L;
+
+
+ /**
+ * Constructs a new Rectangle
whose upper-left corner
+ * is at (0, 0) in the coordinate space, and whose width and
+ * height are both zero.
+ */
+ public Rectangle() {
+ this(0, 0, 0, 0);
+ }
+
+ /**
+ * Constructs a new Rectangle
, initialized to match
+ * the values of the specified Rectangle
.
+ * @param r the Rectangle
from which to copy initial values
+ * to a newly constructed Rectangle
+ */
+ public Rectangle(Rectangle r) {
+ this(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Constructs a new Rectangle
whose upper-left corner is
+ * specified as
+ * {@code (x,y)} and whose width and height
+ * are specified by the arguments of the same name.
+ * @param x the specified X coordinate
+ * @param y the specified Y coordinate
+ * @param width the width of the Rectangle
+ * @param height the height of the Rectangle
+ */
+ public Rectangle(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Constructs a new Rectangle
whose upper-left corner
+ * is at (0, 0) in the coordinate space, and whose width and
+ * height are specified by the arguments of the same name.
+ * @param width the width of the Rectangle
+ * @param height the height of the Rectangle
+ */
+ public Rectangle(int width, int height) {
+ this(0, 0, width, height);
+ }
+
+ /**
+ * Constructs a new Rectangle
whose upper-left corner is
+ * specified by the {@link Point} argument, and
+ * whose width and height are specified by the
+ * {@link Dimension} argument.
+ * @param p a Point
that is the upper-left corner of
+ * the Rectangle
+ * @param d a Dimension
, representing the
+ * width and height of the Rectangle
+ */
+ public Rectangle(Point p, Dimension d) {
+ this(p.x, p.y, d.width, d.height);
+ }
+
+ /**
+ * Constructs a new Rectangle
whose upper-left corner is the
+ * specified Point
, and whose width and height are both zero.
+ * @param p a Point
that is the top left corner
+ * of the Rectangle
+ */
+ public Rectangle(Point p) {
+ this(p.x, p.y, 0, 0);
+ }
+
+ /**
+ * Constructs a new Rectangle
whose top left corner is
+ * (0, 0) and whose width and height are specified
+ * by the Dimension
argument.
+ * @param d a Dimension
, specifying width and height
+ */
+ public Rectangle(Dimension d) {
+ this(0, 0, d.width, d.height);
+ }
+
+ /**
+ * Constructs a new Rectangle
whose upper-left corner is
+ * specified as {@code (x,y)} and whose width and height
+ * are specified by the arguments of the same name. All {@code double}
+ * values are rounded and stored as {@code int} values.
+ * @param x the specified X coordinate
+ * @param y the specified Y coordinate
+ * @param width the width of the Rectangle
+ * @param height the height of the Rectangle
+ */
+ public Rectangle(double x, double y, double width, double height) {
+ this((int) Math.round(x), (int) Math.round(y),
+ (int) Math.round(width), (int) Math.round(height));
+ }
+
+ /**
+ * Returns the X coordinate of the bounding Rectangle
in
+ * double
precision.
+ * @return the X coordinate of the bounding Rectangle
.
+ */
+ public double getX() {
+ return x;
+ }
+
+ /**
+ * Returns the Y coordinate of the bounding Rectangle
in
+ * double
precision.
+ * @return the Y coordinate of the bounding Rectangle
.
+ */
+ public double getY() {
+ return y;
+ }
+
+ /**
+ * Returns the width of the bounding Rectangle
in
+ * double
precision.
+ * @return the width of the bounding Rectangle
.
+ */
+ public double getWidth() {
+ return width;
+ }
+
+ /**
+ * Returns the height of the bounding Rectangle
in
+ * double
precision.
+ * @return the height of the bounding Rectangle
.
+ */
+ public double getHeight() {
+ return height;
+ }
+
+ /**
+ * Gets the bounding Rectangle
of this Rectangle
.
+ *
+ * @return a new Rectangle
, equal to the
+ * bounding Rectangle
for this Rectangle
.
+ * @see #setBounds(Rectangle)
+ * @see #setBounds(int, int, int, int)
+ */
+ public Rectangle getBounds() {
+ return new Rectangle(x, y, width, height);
+ }
+
+ /**
+ * Sets the bounding Rectangle
of this Rectangle
+ * to match the specified Rectangle
.
+ *
+ * @param r the specified Rectangle
+ * @see #getBounds
+ */
+ public void setBounds(Rectangle r) {
+ setBounds(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Sets the bounding Rectangle
of this
+ * Rectangle
to the specified
+ * x
, y
, width
,
+ * and height
.
+ *
+ * @param x the new X coordinate for the upper-left
+ * corner of this Rectangle
+ * @param y the new Y coordinate for the upper-left
+ * corner of this Rectangle
+ * @param width the new width for this Rectangle
+ * @param height the new height for this Rectangle
+ * @see #getBounds
+ */
+ public void setBounds(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Sets the bounds of this {@code Rectangle} to the integer bounds
+ * which encompass the specified {@code x}, {@code y}, {@code width},
+ * and {@code height}.
+ * If the parameters specify a {@code Rectangle} that exceeds the
+ * maximum range of integers, the result will be the best
+ * representation of the specified {@code Rectangle} intersected
+ * with the maximum integer bounds.
+ * @param x the X coordinate of the upper-left corner of
+ * the specified rectangle
+ * @param y the Y coordinate of the upper-left corner of
+ * the specified rectangle
+ * @param width the width of the specified rectangle
+ * @param height the new height of the specified rectangle
+ */
+ public void setRect(double x, double y, double width, double height) {
+ int newx, newy, neww, newh;
+
+ if (x > 2.0 * Integer.MAX_VALUE) {
+ // Too far in positive X direction to represent...
+ // We cannot even reach the left side of the specified
+ // rectangle even with both x & width set to MAX_VALUE.
+ // The intersection with the "maximal integer rectangle"
+ // is non-existant so we should use a width < 0.
+ // REMIND: Should we try to determine a more "meaningful"
+ // adjusted value for neww than just "-1"?
+ newx = Integer.MAX_VALUE;
+ neww = -1;
+ } else {
+ newx = clip(x, false);
+ if (width >= 0) width += x-newx;
+ neww = clip(width, width >= 0);
+ }
+
+ if (y > 2.0 * Integer.MAX_VALUE) {
+ // Too far in positive Y direction to represent...
+ newy = Integer.MAX_VALUE;
+ newh = -1;
+ } else {
+ newy = clip(y, false);
+ if (height >= 0) height += y-newy;
+ newh = clip(height, height >= 0);
+ }
+
+ setBounds(newx, newy, neww, newh);
+ }
+ // Return best integer representation for v, clipped to integer
+ // range and floor-ed or ceiling-ed, depending on the boolean.
+ private static int clip(double v, boolean doceil) {
+ if (v <= Integer.MIN_VALUE) {
+ return Integer.MIN_VALUE;
+ }
+ if (v >= Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ return (int) (doceil ? Math.ceil(v) : Math.floor(v));
+ }
+
+ /**
+ * Returns the location of this Rectangle
.
+ *
+ * @return the Point
that is the upper-left corner of
+ * this Rectangle
.
+ * @see #setLocation(Point)
+ * @see #setLocation(int, int)
+ */
+ public Point getLocation() {
+ return new Point(x, y);
+ }
+
+ /**
+ * Moves this Rectangle
to the specified location.
+ *
+ * @param p the Point
specifying the new location
+ * for this Rectangle
+ * @see #getLocation
+ */
+ public void setLocation(Point p) {
+ setLocation(p.x, p.y);
+ }
+
+ /**
+ * Moves this Rectangle
to the specified location.
+ *
+ * @param x the X coordinate of the new location
+ * @param y the Y coordinate of the new location
+ * @see #getLocation
+ */
+ public void setLocation(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Translates this Rectangle
the indicated distance,
+ * to the right along the X coordinate axis, and
+ * downward along the Y coordinate axis.
+ * @param dx the distance to move this Rectangle
+ * along the X axis
+ * @param dy the distance to move this Rectangle
+ * along the Y axis
+ * @see #setLocation(int, int)
+ * @see #setLocation(org.jemmy.Point)
+ */
+ public void translate(int dx, int dy) {
+ int oldv = this.x;
+ int newv = oldv + dx;
+ if (dx < 0) {
+ // moving leftward
+ if (newv > oldv) {
+ // negative overflow
+ // Only adjust width if it was valid (>= 0).
+ if (width >= 0) {
+ // The right edge is now conceptually at
+ // newv+width, but we may move newv to prevent
+ // overflow. But we want the right edge to
+ // remain at its new location in spite of the
+ // clipping. Think of the following adjustment
+ // conceptually the same as:
+ // width += newv; newv = MIN_VALUE; width -= newv;
+ width += newv - Integer.MIN_VALUE;
+ // width may go negative if the right edge went past
+ // MIN_VALUE, but it cannot overflow since it cannot
+ // have moved more than MIN_VALUE and any non-negative
+ // number + MIN_VALUE does not overflow.
+ }
+ newv = Integer.MIN_VALUE;
+ }
+ } else {
+ // moving rightward (or staying still)
+ if (newv < oldv) {
+ // positive overflow
+ if (width >= 0) {
+ // Conceptually the same as:
+ // width += newv; newv = MAX_VALUE; width -= newv;
+ width += newv - Integer.MAX_VALUE;
+ // With large widths and large displacements
+ // we may overflow so we need to check it.
+ if (width < 0) width = Integer.MAX_VALUE;
+ }
+ newv = Integer.MAX_VALUE;
+ }
+ }
+ this.x = newv;
+
+ oldv = this.y;
+ newv = oldv + dy;
+ if (dy < 0) {
+ // moving upward
+ if (newv > oldv) {
+ // negative overflow
+ if (height >= 0) {
+ height += newv - Integer.MIN_VALUE;
+ // See above comment about no overflow in this case
+ }
+ newv = Integer.MIN_VALUE;
+ }
+ } else {
+ // moving downward (or staying still)
+ if (newv < oldv) {
+ // positive overflow
+ if (height >= 0) {
+ height += newv - Integer.MAX_VALUE;
+ if (height < 0) height = Integer.MAX_VALUE;
+ }
+ newv = Integer.MAX_VALUE;
+ }
+ }
+ this.y = newv;
+ }
+
+ /**
+ * Gets the size of this Rectangle
, represented by
+ * the returned Dimension
.
+ *
+ * @return a Dimension
, representing the size of
+ * this Rectangle
.
+ * @see #setSize(Dimension)
+ * @see #setSize(int, int)
+ */
+ public Dimension getSize() {
+ return new Dimension(width, height);
+ }
+
+ /**
+ * Sets the size of this Rectangle
to match the
+ * specified Dimension
.
+ *
+ * @param d the new size for the Dimension
object
+ * @see #getSize
+ */
+ public void setSize(Dimension d) {
+ setSize(d.width, d.height);
+ }
+
+ /**
+ * Sets the size of this Rectangle
to the specified
+ * width and height.
+ *
+ * @param width the new width for this Rectangle
+ * @param height the new height for this Rectangle
+ * @see #getSize
+ */
+ public void setSize(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Checks whether or not this Rectangle
contains the
+ * specified Point
.
+ * @param p the Point
to test
+ * @return true
if the specified Point
+ * is inside this Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(Point p) {
+ return contains(p.x, p.y);
+ }
+
+ /**
+ * Checks whether or not this Rectangle
contains the
+ * point at the specified location {@code (x,y)}.
+ *
+ * @param x the specified X coordinate
+ * @param y the specified Y coordinate
+ * @return true
if the point
+ * {@code (x,y)} is inside this
+ * Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(int x, int y) {
+ return contains(x, y, 1, 1);
+ }
+
+ /**
+ * Checks whether or not this Rectangle
entirely contains
+ * the specified Rectangle
.
+ *
+ * @param r the specified Rectangle
+ * @return true
if the Rectangle
+ * is contained entirely inside this Rectangle
;
+ * false
otherwise
+ */
+ public boolean contains(Rectangle r) {
+ return contains(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Checks whether this Rectangle
entirely contains
+ * the Rectangle
+ * at the specified location {@code (X,Y)} with the
+ * specified dimensions {@code (W,H)}.
+ * @param X the specified X coordinate
+ * @param Y the specified Y coordinate
+ * @param W the width of the Rectangle
+ * @param H the height of the Rectangle
+ * @return true
if the Rectangle
specified by
+ * {@code (X, Y, W, H)}
+ * is entirely enclosed inside this Rectangle
;
+ * false
otherwise.
+ */
+ public boolean contains(int X, int Y, int W, int H) {
+ int w = this.width;
+ int h = this.height;
+ if ((w | h | W | H) < 0) {
+ // At least one of the dimensions is negative...
+ return false;
+ }
+ // Note: if any dimension is zero, tests below must return false...
+ int xx = this.x;
+ int yy = this.y;
+ if (X < xx || Y < yy) {
+ return false;
+ }
+ w += xx;
+ W += X;
+ if (W <= X) {
+ // X+W overflowed or W was zero, return false if...
+ // either original w or W was zero or
+ // x+w did not overflow or
+ // the overflowed x+w is smaller than the overflowed X+W
+ if (w >= xx || W > w) return false;
+ } else {
+ // X+W did not overflow and W was not zero, return false if...
+ // original w was zero or
+ // x+w did not overflow and x+w is smaller than X+W
+ if (w >= xx && W > w) return false;
+ }
+ h += yy;
+ H += Y;
+ if (H <= Y) {
+ if (h >= yy || H > h) return false;
+ } else {
+ if (h >= yy && H > h) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Determines whether or not this Rectangle
and the specified
+ * Rectangle
intersect. Two rectangles intersect if
+ * their intersection is nonempty.
+ *
+ * @param r the specified Rectangle
+ * @return true
if the specified Rectangle
+ * and this Rectangle
intersect;
+ * false
otherwise.
+ */
+ public boolean intersects(Rectangle r) {
+ int tw = this.width;
+ int th = this.height;
+ int rw = r.width;
+ int rh = r.height;
+ if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
+ return false;
+ }
+ int tx = this.x;
+ int ty = this.y;
+ int rx = r.x;
+ int ry = r.y;
+ rw += rx;
+ rh += ry;
+ tw += tx;
+ th += ty;
+ // overflow || intersect
+ return ((rw < rx || rw > tx) &&
+ (rh < ry || rh > ty) &&
+ (tw < tx || tw > rx) &&
+ (th < ty || th > ry));
+ }
+
+ /**
+ * Computes the intersection of this Rectangle
with the
+ * specified Rectangle
. Returns a new Rectangle
+ * that represents the intersection of the two rectangles.
+ * If the two rectangles do not intersect, the result will be
+ * an empty rectangle.
+ *
+ * @param r the specified Rectangle
+ * @return the largest Rectangle
contained in both the
+ * specified Rectangle
and in
+ * this Rectangle
; or if the rectangles
+ * do not intersect, an empty rectangle.
+ */
+ public Rectangle intersection(Rectangle r) {
+ int tx1 = this.x;
+ int ty1 = this.y;
+ int rx1 = r.x;
+ int ry1 = r.y;
+ long tx2 = tx1; tx2 += this.width;
+ long ty2 = ty1; ty2 += this.height;
+ long rx2 = rx1; rx2 += r.width;
+ long ry2 = ry1; ry2 += r.height;
+ if (tx1 < rx1) tx1 = rx1;
+ if (ty1 < ry1) ty1 = ry1;
+ if (tx2 > rx2) tx2 = rx2;
+ if (ty2 > ry2) ty2 = ry2;
+ tx2 -= tx1;
+ ty2 -= ty1;
+ // tx2,ty2 will never overflow (they will never be
+ // larger than the smallest of the two source w,h)
+ // they might underflow, though...
+ if (tx2 < Integer.MIN_VALUE) tx2 = Integer.MIN_VALUE;
+ if (ty2 < Integer.MIN_VALUE) ty2 = Integer.MIN_VALUE;
+ return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
+ }
+
+ /**
+ * Computes the union of this Rectangle
with the
+ * specified Rectangle
. Returns a new
+ * Rectangle
that
+ * represents the union of the two rectangles.
+ *
+ * If either {@code Rectangle} has any dimension less than zero
+ * the rules for non-existant rectangles
+ * apply.
+ * If only one has a dimension less than zero, then the result
+ * will be a copy of the other {@code Rectangle}.
+ * If both have dimension less than zero, then the result will
+ * have at least one dimension less than zero.
+ *
+ * If the resulting {@code Rectangle} would have a dimension
+ * too large to be expressed as an {@code int}, the result
+ * will have a dimension of {@code Integer.MAX_VALUE} along
+ * that dimension.
+ * @param r the specified Rectangle
+ * @return the smallest Rectangle
containing both
+ * the specified Rectangle
and this
+ * Rectangle
.
+ */
+ public Rectangle union(Rectangle r) {
+ long tx2 = this.width;
+ long ty2 = this.height;
+ if ((tx2 | ty2) < 0) {
+ // This rectangle has negative dimensions...
+ // If r has non-negative dimensions then it is the answer.
+ // If r is non-existant (has a negative dimension), then both
+ // are non-existant and we can return any non-existant rectangle
+ // as an answer. Thus, returning r meets that criterion.
+ // Either way, r is our answer.
+ return new Rectangle(r);
+ }
+ long rx2 = r.width;
+ long ry2 = r.height;
+ if ((rx2 | ry2) < 0) {
+ return new Rectangle(this);
+ }
+ int tx1 = this.x;
+ int ty1 = this.y;
+ tx2 += tx1;
+ ty2 += ty1;
+ int rx1 = r.x;
+ int ry1 = r.y;
+ rx2 += rx1;
+ ry2 += ry1;
+ if (tx1 > rx1) tx1 = rx1;
+ if (ty1 > ry1) ty1 = ry1;
+ if (tx2 < rx2) tx2 = rx2;
+ if (ty2 < ry2) ty2 = ry2;
+ tx2 -= tx1;
+ ty2 -= ty1;
+ // tx2,ty2 will never underflow since both original rectangles
+ // were already proven to be non-empty
+ // they might overflow, though...
+ if (tx2 > Integer.MAX_VALUE) tx2 = Integer.MAX_VALUE;
+ if (ty2 > Integer.MAX_VALUE) ty2 = Integer.MAX_VALUE;
+ return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
+ }
+
+ /**
+ * Adds a point, specified by the integer arguments {@code newx,newy}
+ * to the bounds of this {@code Rectangle}.
+ *
+ * If this {@code Rectangle} has any dimension less than zero,
+ * the rules for non-existant
+ * rectangles apply.
+ * In that case, the new bounds of this {@code Rectangle} will
+ * have a location equal to the specified coordinates and
+ * width and height equal to zero.
+ *
+ * After adding a point, a call to contains
with the
+ * added point as an argument does not necessarily return
+ * true
. The contains
method does not
+ * return true
for points on the right or bottom
+ * edges of a Rectangle
. Therefore, if the added point
+ * falls on the right or bottom edge of the enlarged
+ * Rectangle
, contains
returns
+ * false
for that point.
+ * If the specified point must be contained within the new
+ * {@code Rectangle}, a 1x1 rectangle should be added instead:
+ *
+ * r.add(newx, newy, 1, 1);
+ *
+ * @param newx the X coordinate of the new point
+ * @param newy the Y coordinate of the new point
+ */
+ public void add(int newx, int newy) {
+ if ((width | height) < 0) {
+ this.x = newx;
+ this.y = newy;
+ this.width = this.height = 0;
+ return;
+ }
+ int x1 = this.x;
+ int y1 = this.y;
+ long x2 = this.width;
+ long y2 = this.height;
+ x2 += x1;
+ y2 += y1;
+ if (x1 > newx) x1 = newx;
+ if (y1 > newy) y1 = newy;
+ if (x2 < newx) x2 = newx;
+ if (y2 < newy) y2 = newy;
+ x2 -= x1;
+ y2 -= y1;
+ if (x2 > Integer.MAX_VALUE) x2 = Integer.MAX_VALUE;
+ if (y2 > Integer.MAX_VALUE) y2 = Integer.MAX_VALUE;
+ setBounds(x1, y1, (int) x2, (int) y2);
+ }
+
+ /**
+ * Adds the specified {@code Point} to the bounds of this
+ * {@code Rectangle}.
+ *
+ * If this {@code Rectangle} has any dimension less than zero,
+ * the rules for non-existant
+ * rectangles apply.
+ * In that case, the new bounds of this {@code Rectangle} will
+ * have a location equal to the coordinates of the specified
+ * {@code Point} and width and height equal to zero.
+ *
+ * After adding a Point
, a call to contains
+ * with the added Point
as an argument does not
+ * necessarily return true
. The contains
+ * method does not return true
for points on the right
+ * or bottom edges of a Rectangle
. Therefore if the added
+ * Point
falls on the right or bottom edge of the
+ * enlarged Rectangle
, contains
returns
+ * false
for that Point
.
+ * If the specified point must be contained within the new
+ * {@code Rectangle}, a 1x1 rectangle should be added instead:
+ *
+ * r.add(pt.x, pt.y, 1, 1);
+ *
+ * @param pt the new Point
to add to this
+ * Rectangle
+ */
+ public void add(Point pt) {
+ add(pt.x, pt.y);
+ }
+
+ /**
+ * Adds a Rectangle
to this Rectangle
.
+ * The resulting Rectangle
is the union of the two
+ * rectangles.
+ *
+ * If either {@code Rectangle} has any dimension less than 0, the
+ * result will have the dimensions of the other {@code Rectangle}.
+ * If both {@code Rectangle}s have at least one dimension less
+ * than 0, the result will have at least one dimension less than 0.
+ *
+ * If either {@code Rectangle} has one or both dimensions equal
+ * to 0, the result along those axes with 0 dimensions will be
+ * equivalent to the results obtained by adding the corresponding
+ * origin coordinate to the result rectangle along that axis,
+ * similar to the operation of the {@link #add(Point)} method,
+ * but contribute no further dimension beyond that.
+ *
+ * If the resulting {@code Rectangle} would have a dimension
+ * too large to be expressed as an {@code int}, the result
+ * will have a dimension of {@code Integer.MAX_VALUE} along
+ * that dimension.
+ * @param r the specified Rectangle
+ */
+ public void add(Rectangle r) {
+ long tx2 = this.width;
+ long ty2 = this.height;
+ if ((tx2 | ty2) < 0) {
+ setBounds(r.x, r.y, r.width, r.height);
+ }
+ long rx2 = r.width;
+ long ry2 = r.height;
+ if ((rx2 | ry2) < 0) {
+ return;
+ }
+ int tx1 = this.x;
+ int ty1 = this.y;
+ tx2 += tx1;
+ ty2 += ty1;
+ int rx1 = r.x;
+ int ry1 = r.y;
+ rx2 += rx1;
+ ry2 += ry1;
+ if (tx1 > rx1) tx1 = rx1;
+ if (ty1 > ry1) ty1 = ry1;
+ if (tx2 < rx2) tx2 = rx2;
+ if (ty2 < ry2) ty2 = ry2;
+ tx2 -= tx1;
+ ty2 -= ty1;
+ // tx2,ty2 will never underflow since both original
+ // rectangles were non-empty
+ // they might overflow, though...
+ if (tx2 > Integer.MAX_VALUE) tx2 = Integer.MAX_VALUE;
+ if (ty2 > Integer.MAX_VALUE) ty2 = Integer.MAX_VALUE;
+ setBounds(tx1, ty1, (int) tx2, (int) ty2);
+ }
+
+ /**
+ * Resizes the Rectangle
both horizontally and vertically.
+ *
+ * This method modifies the Rectangle
so that it is
+ * h
units larger on both the left and right side,
+ * and v
units larger at both the top and bottom.
+ *
+ * The new Rectangle
has {@code (x - h, y - v)}
+ * as its upper-left corner,
+ * width of {@code (width + 2h)},
+ * and a height of {@code (height + 2v)}.
+ *
+ * If negative values are supplied for h
and
+ * v
, the size of the Rectangle
+ * decreases accordingly.
+ * The {@code grow} method will check for integer overflow
+ * and underflow, but does not check whether the resulting
+ * values of {@code width} and {@code height} grow
+ * from negative to non-negative or shrink from non-negative
+ * to negative.
+ * @param h the horizontal expansion
+ * @param v the vertical expansion
+ */
+ public void grow(int h, int v) {
+ long x0 = this.x;
+ long y0 = this.y;
+ long x1 = this.width;
+ long y1 = this.height;
+ x1 += x0;
+ y1 += y0;
+
+ x0 -= h;
+ y0 -= v;
+ x1 += h;
+ y1 += v;
+
+ if (x1 < x0) {
+ // Non-existant in X direction
+ // Final width must remain negative so subtract x0 before
+ // it is clipped so that we avoid the risk that the clipping
+ // of x0 will reverse the ordering of x0 and x1.
+ x1 -= x0;
+ if (x1 < Integer.MIN_VALUE) x1 = Integer.MIN_VALUE;
+ if (x0 < Integer.MIN_VALUE) x0 = Integer.MIN_VALUE;
+ else if (x0 > Integer.MAX_VALUE) x0 = Integer.MAX_VALUE;
+ } else { // (x1 >= x0)
+ // Clip x0 before we subtract it from x1 in case the clipping
+ // affects the representable area of the rectangle.
+ if (x0 < Integer.MIN_VALUE) x0 = Integer.MIN_VALUE;
+ else if (x0 > Integer.MAX_VALUE) x0 = Integer.MAX_VALUE;
+ x1 -= x0;
+ // The only way x1 can be negative now is if we clipped
+ // x0 against MIN and x1 is less than MIN - in which case
+ // we want to leave the width negative since the result
+ // did not intersect the representable area.
+ if (x1 < Integer.MIN_VALUE) x1 = Integer.MIN_VALUE;
+ else if (x1 > Integer.MAX_VALUE) x1 = Integer.MAX_VALUE;
+ }
+
+ if (y1 < y0) {
+ // Non-existant in Y direction
+ y1 -= y0;
+ if (y1 < Integer.MIN_VALUE) y1 = Integer.MIN_VALUE;
+ if (y0 < Integer.MIN_VALUE) y0 = Integer.MIN_VALUE;
+ else if (y0 > Integer.MAX_VALUE) y0 = Integer.MAX_VALUE;
+ } else { // (y1 >= y0)
+ if (y0 < Integer.MIN_VALUE) y0 = Integer.MIN_VALUE;
+ else if (y0 > Integer.MAX_VALUE) y0 = Integer.MAX_VALUE;
+ y1 -= y0;
+ if (y1 < Integer.MIN_VALUE) y1 = Integer.MIN_VALUE;
+ else if (y1 > Integer.MAX_VALUE) y1 = Integer.MAX_VALUE;
+ }
+
+ setBounds((int) x0, (int) y0, (int) x1, (int) y1);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return
+ */
+ public boolean isEmpty() {
+ return (width <= 0) || (height <= 0);
+ }
+
+ /**
+ * Checks whether two rectangles are equal.
+ *
+ * The result is true
if and only if the argument is not
+ * null
and is a Rectangle
object that has the
+ * same upper-left corner, width, and height as
+ * this Rectangle
.
+ * @param obj the Object
to compare with
+ * this Rectangle
+ * @return true
if the objects are equal;
+ * false
otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Rectangle) {
+ Rectangle r = (Rectangle)obj;
+ return ((x == r.x) &&
+ (y == r.y) &&
+ (width == r.width) &&
+ (height == r.height));
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * {@inheritDoc }
+ * @return
+ */
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 29 * hash + this.x;
+ hash = 29 * hash + this.y;
+ hash = 29 * hash + this.width;
+ hash = 29 * hash + this.height;
+ return hash;
+ }
+
+ /**
+ * Returns a String
representing this
+ * Rectangle
and its values.
+ * @return a String
representing this
+ * Rectangle
object's coordinate and size values.
+ */
+ @Override
+ public String toString() {
+ return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]";
+ }
+
+ /**
+ * Parses given string to restore Rectangle instance from the string.
+ * String assumed to be previously created using
+ * {@linkplain #toString() Rectangle.toString()} method.
+ * @param str String to parse.
+ * @return Recreated Rectangle instance.
+ */
+ public static Rectangle parseRectangle(String str) {
+ if (str != null && str.startsWith(Rectangle.class.getName())) {
+ try {
+ String[] t =
+ str.substring(Rectangle.class.getName().length() + 1)
+ .split("\\,|\\]");
+ Rectangle res = new Rectangle();
+ for(String pair : t) {
+ String[] p = pair.split("\\=");
+ String var = p[0];
+ int value = Integer.parseInt(p[1]);
+ res.getClass().getDeclaredField(var).setInt(res, value);
+ }
+ return res;
+ } catch (Exception ex) {
+ throw new JemmyException(
+ "Failed to parse Rectangle '" + str + "'", ex);
+ }
+ }
+ return null;
+ }
+}
--- /dev/null 2017-11-08 15:39:23.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/TimeoutExpiredException.java 2017-11-08 15:39:23.000000000 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy;
+
+/**
+ *
+ * Exception is supposed to be used to notice that some
+ * waiting was expired.
+ *
+ * @author Alexandre Iline (alexandre.iline@sun.com)
+ */
+
+public class TimeoutExpiredException extends JemmyException{
+
+ /**
+ * Constructor.
+ * @param description Waiting description.
+ */
+ public TimeoutExpiredException(String description) {
+ super(description);
+ }
+}
--- /dev/null 2017-11-08 15:39:23.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/Vector.java 2017-11-08 15:39:23.000000000 -0800
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy;
+
+/**
+ * The class for easy computations.
+ * @author shura
+ */
+public class Vector {
+
+ private double x;
+ private double y;
+
+ /**
+ *
+ * @param x
+ * @param y
+ */
+ public Vector(double x, double y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ *
+ * @param from
+ * @param to
+ */
+ public Vector(Point from, Point to) {
+ x = to.x - from.x;
+ y = to.y - from.y;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public double getX() {
+ return x;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public double getY() {
+ return y;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public double lenght() {
+ return Math.sqrt(x*x + y*y);
+ }
+
+ /**
+ *
+ * @param newLenght
+ * @return self
+ */
+ public Vector setLenght(double newLenght) {
+ double lenght = lenght();
+ x = x * newLenght / lenght;
+ y = y * newLenght / lenght;
+ return this;
+ }
+
+ /**
+ * @param multiplier
+ * @return self
+ */
+ public Vector multiply(double multiplier) {
+ x*=multiplier;
+ y*=multiplier;
+ return this;
+ }
+
+ /**
+ *
+ * @return a clone
+ */
+ @Override
+ public Vector clone() {
+ return new Vector(x, y);
+ }
+
+ /**
+ *
+ * @return
+ */
+ @Override
+ public String toString() {
+ return "(" + x + "," + y + ")";
+ }
+
+ /**
+ * Adds another vector (x1 + x2, y1 + y2)
+ * @param v
+ * @return self
+ */
+ public Vector add(Vector v) {
+ x+=v.x;
+ y+=v.y;
+ return this;
+ }
+
+
+}
--- /dev/null 2017-11-08 15:39:24.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/Version.java 2017-11-08 15:39:24.000000000 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ *
+ * @author shura
+ */
+public class Version {
+ /**
+ *
+ */
+ public static final Version VERSION = new Version();
+
+ private int major;
+ private int minor;
+ private int mini;
+ private String build;
+
+ /**
+ *
+ */
+ public Version() {
+ this(Version.class.getPackage().getName());
+ }
+
+ /**
+ *
+ * @param pkg
+ */
+ public Version(String pkg) {
+ try {
+ Properties props = new Properties();
+ String fileName = pkg.replace(".", "/") + "/jemmy.properties";
+ InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
+ if(in == null) {
+ throw new JemmyException("Can not get version - no " + fileName + " file");
+ }
+ props.load(in);
+ major = Integer.parseInt(props.getProperty("version.major"));
+ minor = Integer.parseInt(props.getProperty("version.minor"));
+ mini = Integer.parseInt(props.getProperty("version.mini"));
+ build = props.getProperty("build");
+ } catch (IOException ex) {
+ throw new JemmyException("Can not get version.", ex);
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public int getMajor() {
+ return major;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public int getMini() {
+ return mini;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public int getMinor() {
+ return minor;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getVersion() {
+ return major + "." + minor + "." + mini;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getBuild() {
+ return build;
+ }
+
+ /**
+ *
+ * @param old
+ * @return
+ */
+ public boolean newer(String old) {
+ StringTokenizer tn = new StringTokenizer(old, ".");
+ if(major >= Integer.parseInt(tn.nextToken())) {
+ if(minor >= Integer.parseInt(tn.nextToken())) {
+ if(mini >= Integer.parseInt(tn.nextToken())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @param args
+ */
+ public static void main(String[] args) {
+ System.out.println("JemmyCore version: " + VERSION.getVersion() + "." + VERSION.build);
+ }
+}
--- /dev/null 2017-11-08 15:39:24.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/AbstractExecutor.java 2017-11-08 15:39:24.000000000 -0800
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.action;
+
+import org.jemmy.env.Environment;
+import org.jemmy.env.TestOut;
+import org.jemmy.env.Timeout;
+import org.jemmy.timing.State;
+import org.jemmy.timing.Waiter;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class AbstractExecutor implements ActionExecutor {
+
+ /**
+ * Default timeout for action {@linkplain Action#run(java.lang.Object[])
+ * run()} method to be completed.
+ */
+ public static final Timeout MAX_ACTION_TIME = new Timeout("max.action.time", 60000);
+ /**
+ * Indentifies output which would be used to print information for all actions
+ * executed not on event queue.
+ * @see AbstractExecutor#execute(org.jemmy.env.Environment, boolean, org.jemmy.action.Action, java.lang.Object[])
+ * @see AbstractExecutor#executeDetached(org.jemmy.env.Environment, boolean, org.jemmy.action.Action, java.lang.Object[])
+ * @see Environment#getOutput(java.lang.String)
+ */
+ public static final String NON_QUEUE_ACTION_OUTPUT = "org.jemmy.action.AbstractExecutor.NON_QUEUE_ACTION_OUTPUT";
+ /**
+ * Indentifies output which would be used to print information for all actions
+ * executed on event queue.
+ * @see AbstractExecutor#execute(org.jemmy.env.Environment, boolean, org.jemmy.action.Action, java.lang.Object[])
+ * @see AbstractExecutor#executeDetached(org.jemmy.env.Environment, boolean, org.jemmy.action.Action, java.lang.Object[])
+ * @see Environment#getOutput(java.lang.String)
+ */
+ public static final String QUEUE_ACTION_OUTPUT = "org.jemmy.action.AbstractExecutor.QUEUE_ACTION_OUTPUT";
+ private ActionQueue queue;
+
+ /**
+ *
+ */
+ public AbstractExecutor() {
+ queue = new ActionQueue();
+ }
+
+ static {
+ Environment.getEnvironment().initTimeout(MAX_ACTION_TIME);
+ Environment.getEnvironment().initOutput(QUEUE_ACTION_OUTPUT, TestOut.getNullOutput());
+ Environment.getEnvironment().initOutput(NON_QUEUE_ACTION_OUTPUT, TestOut.getNullOutput());
+ }
+
+ /**
+ *
+ * @return
+ */
+ protected int actionsInQueue() {
+ return queue.actionsInQueue();
+ }
+
+ /**
+ * {@inheritDoc }
+ * Prints out what action is executed into output
+ * specified by either NON_QUEUE_ACTION_OUTPUT or QUEUE_ACTION_OUTPUT
+ * depending whether the action is called on queue or not. No output provided for
+ * nested actions - only the top level ones are printed.
+ * @see TestOut#getOutput(java.lang.String)
+ */
+ public final void execute(Environment env, boolean dispatch, final Action action, Object... parameters) {
+ printStrace(env, "Action: ", action);
+ action.setAllowedTime(env.getTimeout(MAX_ACTION_TIME.getName()).getValue());
+ if (dispatch) {
+ executeQueue(env, action, parameters);
+ } else {
+ if (isInAction()) {
+ action.execute(parameters);
+ } else {
+ queue.invokeAndWait(action, parameters);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc }
+ * Prints out what action is executed into output
+ * specified by either NON_QUEUE_ACTION_OUTPUT or QUEUE_ACTION_OUTPUT
+ * depending whether the action is called on queue or not. No output provided for
+ * nested actions - only the top level ones are printed.
+ * @see TestOut#getOutput(java.lang.String)
+ */
+ public final void executeDetached(Environment env, boolean dispatch, final Action action, final Object... parameters) {
+ printStrace(env, "Action detached: ", action);
+ if (dispatch) {
+ executeQueueDetached(env, action, parameters);
+ } else {
+ if (isInAction()) {
+ new Thread(new Runnable() {
+
+ public void run() {
+ action.execute(parameters);
+ }
+ }).start();
+ } else {
+ queue.invoke(action, parameters);
+ }
+ }
+ }
+
+ private void printStrace(Environment env, String text, Action action) {
+ String toString = action.toString();
+ if (toString != null && toString.length() > 0) {
+ if (!isInAction()) {
+ if (isOnQueue()) {
+ env.getOutput(QUEUE_ACTION_OUTPUT).println(text + action.toString());
+ } else {
+ env.getOutput(NON_QUEUE_ACTION_OUTPUT).println(text + action.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final boolean isInAction() {
+ return queue.getQueueThread() == Thread.currentThread() || isOnQueue();
+ }
+
+ /**
+ * Schedules to execute an action through the UI system's dispatch thread and
+ * waits for the action to be completed. This method is called from
+ * {@linkplain #execute(org.jemmy.env.Environment, boolean, org.jemmy.action.Action, java.lang.Object[]) execute()}
+ * method when it is invoked with dispatch argument set to true.
+ * @param env Environment.
+ * @param action action to execute.
+ * @param parameters parameters to pass to {@linkplain Action#run(java.lang.Object[]) action.run()} method.
+ */
+ public abstract void executeQueue(Environment env, Action action, Object... parameters);
+
+ /**
+ * Schedules to execute an action through the UI system's dispatch thread and
+ * exits immediately. This method is called from
+ * {@linkplain #executeDetached(org.jemmy.env.Environment, boolean, org.jemmy.action.Action, java.lang.Object[]) executeDetached()}
+ * method when it is invoked with dispatch argument set to true.
+ * @param env Environment.
+ * @param action action to execute.
+ * @param parameters parameters to pass to {@linkplain Action#run(java.lang.Object[]) action.run()} method.
+ */
+ public abstract void executeQueueDetached(Environment env, Action action, Object... parameters);
+
+ /**
+ * Checks whether this is invoked from the UI system event queue.
+ * @return true if invoked from the UI system event queue.
+ */
+ public abstract boolean isOnQueue();
+
+ /**
+ * Waits for UI to became quiet which is determined using
+ * {@linkplain #isQuiet() isQuiet()} method.
+ * @param waitTime maximum time for waiting.
+ */
+ public void waitQuiet(Timeout waitTime) {
+ new Waiter(waitTime).ensureState(new State() {
+
+ public Object reached() {
+ return isQuiet() ? true : null;
+ }
+ });
+ }
+
+ /**
+ * Tells whether the UI is quiet which usually means that all scheduled
+ * actions are dispatched and the queue is empty.
+ * @see #waitQuiet(org.jemmy.env.Timeout)
+ * @return true if the UI is quiet.
+ */
+ protected abstract boolean isQuiet();
+}
--- /dev/null 2017-11-08 15:39:25.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/Action.java 2017-11-08 15:39:24.000000000 -0800
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.action;
+
+import org.jemmy.JemmyException;
+
+
+/**
+ *
+ * @author shura, KAM
+ */
+public abstract class Action {
+
+ private boolean interrupted = false;
+ private long startTime = -1, endTime = 0, allowedTime = 0;
+ private Throwable throwable = null;
+
+ /**
+ * Executes {@linkplain #run(java.lang.Object[]) run()} method of this
+ * Action, saving the duration of its execution and storing any
+ * RuntimeException and Error which may occur during its work.
+ * @param parameters Parameters to pass to {@linkplain
+ * #run(java.lang.Object[]) run()} method
+ * @see #getThrowable()
+ * @see #failed()
+ */
+ public final void execute(Object... parameters) {
+ startTime = System.currentTimeMillis();
+ try {
+ run(parameters);
+ } catch (Error e) {
+ throwable = e;
+ throw e;
+ } catch (RuntimeException e) {
+ throwable = e;
+ throw e;
+ } catch (Exception e) {
+ throwable = e;
+ throw new JemmyException("Exception in action " + this.toString(), e);
+ } finally {
+ endTime = System.currentTimeMillis();
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public long getEndTime() {
+ return endTime;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /**
+ * Should be used from {@linkplain #run(java.lang.Object[]) run()) method
+ * to check whether execution time is withing allowed time
+ * @return true if difference between current time and start time is less
+ * then allowed time; false otherwice
+ */
+ protected boolean withinAllowedTime() {
+ return System.currentTimeMillis() - startTime < allowedTime;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public long getAllowedTime() {
+ return allowedTime;
+ }
+
+ /**
+ *
+ * @param allowedTime
+ */
+ public void setAllowedTime(long allowedTime) {
+ this.allowedTime = allowedTime;
+ }
+
+ /**
+ *
+ * @param parameters
+ */
+ public abstract void run(Object... parameters) throws Exception;
+
+ /**
+ *
+ * @return
+ */
+ public boolean isInterrupted() {
+ return interrupted;
+ }
+
+ /**
+ *
+ */
+ public void interrupt() {
+ this.interrupted = true;
+ }
+
+ /**
+ * Returns throwable that occurred during run() invocation.
+ * @return Error or RuntimeException.
+ */
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ /**
+ * Indicates whether action invocation failed.
+ * @return true if some exception occurred during run() invocation.
+ */
+ public boolean failed() {
+ return throwable != null;
+ }
+
+ /**
+ * Override this method to provide action description which
+ * will be printed into output.
+ * @return null If nothing should be printed into output.
+ */
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+}
--- /dev/null 2017-11-08 15:39:25.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/ActionExecutor.java 2017-11-08 15:39:25.000000000 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.action;
+
+
+import org.jemmy.env.Environment;
+import org.jemmy.env.Timeout;
+
+
+/**
+ * Interface to execute user's action at appropriate moment .
+ * @author shura
+ */
+public interface ActionExecutor {
+
+ /**
+ *
+ */
+ public static final String ACTION_EXECUTOR_PROPERTY = "action.executor";
+
+ /**
+ * Schedules to execute an action and waits for it to finish.
+ * @param env Environment.
+ * @param dispatch if true the action is executed on UI system dispatch
+ * thread. This is usually necessary to invoke methods of the UI to get
+ * the correct state or to update it.
+ * @param action Action to execute.
+ * @param parameters Parameters to pass to
+ * {@linkplain Action#run(java.lang.Object[]) action.run()} method.
+ */
+ public void execute(Environment env, boolean dispatch, Action action, Object... parameters);
+
+ /**
+ * Schedules to execute an action and exits immediately. Used to be called
+ * DoSomethingNoBlock operations in jemmy2.
+ * @param env Environment.
+ * @param dispatch if true the action is executed on UI system dispatch
+ * thread. This is usually necessary to invoke methods of the UI to get
+ * the correct state or to update it.
+ * @param action Action to execute.
+ * @param parameters Parameters to pass to
+ * {@linkplain Action#run(java.lang.Object[]) action.run()} method.
+ */
+ public void executeDetached(Environment env, boolean dispatch, Action action, Object... parameters);
+
+ /**
+ * Checks whether the current thread is already performing an action.
+ * @return true if the current thread is already performing an action.
+ * @see AbstractExecutor#isDispatchThread()
+ */
+ public boolean isInAction();
+
+ /**
+ * Waits for no activities to be going on. Implementation may be different
+ * for different mechanisms.
+ * @param waitTime maximum time for waiting.
+ * @see AbstractExecutor#isQuiet()
+ */
+ public void waitQuiet(Timeout waitTime);
+}
--- /dev/null 2017-11-08 15:39:25.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/ActionQueue.java 2017-11-08 15:39:25.000000000 -0800
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.action;
+
+
+import java.util.LinkedList;
+import org.jemmy.JemmyException;
+import org.jemmy.TimeoutExpiredException;
+
+
+/**
+ *
+ * @author shura, KAM
+ */
+class ActionQueue {
+
+ private Thread queueThread;
+ private final LinkedList queue;
+ private boolean stop = false;
+
+ public ActionQueue() {
+ queue = new LinkedList();
+ queueThread = new Thread(new Runnable() {
+
+ public void run() {
+ int size;
+ while (!stop) {
+ synchronized (queue) {
+ size = queue.size();
+ if (size == 0) {
+ try {
+ queue.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ if (size > 0) {
+ ActionRecord r;
+ synchronized (queue) {
+ r = queue.poll();
+ }
+ try {
+ r.execute();
+ } catch (Exception e) {
+ System.err.println("Action '" + r + "' failed with the following exception: ");
+ e.printStackTrace(System.err);
+ System.err.flush();
+ }
+ r.setCompleted(true);
+ }
+ }
+ }
+ }, "ActionQueue.queueThread");
+ queueThread.start();
+ }
+
+ public int actionsInQueue() {
+ synchronized(queue) {
+ return queue.size();
+ }
+ }
+
+ public void stop() {
+ stop = true;
+ }
+
+ /**
+ * Returns internal ActionQueue event dispatching thread
+ * @return queue dispatching thread of ActionQueue object
+ */
+ public Thread getQueueThread() {
+ return queueThread;
+ }
+
+ /**
+ * Schedules execution of an action throught the internal ActionQueue queue
+ * and exits immediately
+ * @param action action to execute
+ * @param parameters parameters to pass to action.run() method
+ */
+ public void invoke(Action action, Object... parameters) {
+ synchronized (queue) {
+ queue.add(new ActionRecord(action, parameters));
+ queue.notifyAll();
+ }
+ }
+
+ /**
+ * Schedules execution of an action through the internal ActionQueue queue
+ * and waits until it is completed
+ * @param action action to execute
+ * @param parameters parameters to pass to action.run() method
+ */
+ public void invokeAndWait(Action action, Object... parameters) {
+ ActionRecord r = new ActionRecord(action, parameters);
+ synchronized (queue) {
+ queue.add(r);
+ queue.notifyAll();
+ }
+ r.waitCompleted();
+
+ if (r.failed()) {
+ throw new JemmyException("Action '" + r + "' invoked through ActionQueue failed", r.getThrowable());
+ }
+ }
+
+ private class ActionRecord {
+
+ Action action;
+ Object[] parameters;
+ boolean completed;
+ boolean started;
+
+ public ActionRecord(Action action, Object[] parameters) {
+ this.action = action;
+ this.parameters = parameters;
+ }
+
+ public boolean failed() {
+ return action.failed();
+ }
+
+ public Throwable getThrowable() {
+ return action.getThrowable();
+ }
+
+ public Object[] getParameters() {
+ return parameters;
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ public synchronized void setCompleted(boolean completed) {
+ this.completed = completed;
+ notifyAll();
+ }
+
+ public void execute() {
+ synchronized (this) {
+ started = true;
+ notifyAll();
+ }
+ action.execute(parameters);
+ }
+
+ public synchronized void waitCompleted() {
+ try {
+ while (!started) {
+ wait();
+ }
+ if (!completed) {
+ wait(action.getAllowedTime());
+ if (!completed) {
+ action.interrupt();
+ throw new TimeoutExpiredException("Action did not finish in " + action.getAllowedTime() + " ms: " + action);
+ }
+ }
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ @Override
+ public String toString() {
+ return action.toString();
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:25.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/DefaultExecutor.java 2017-11-08 15:39:25.000000000 -0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.action;
+
+
+import org.jemmy.env.Environment;
+
+
+/**
+ *
+ * @author shura
+ */
+public class DefaultExecutor extends AbstractExecutor {
+
+ /**
+ *
+ */
+ public DefaultExecutor() {
+ }
+
+ /**
+ * Executes through the ActionQueue as there is no system dispatch thread.
+ * @param env {@inheritDoc }
+ * @param action {@inheritDoc }
+ * @param parameters {@inheritDoc }
+ * @see Action#run(java.lang.Object[])
+ */
+ public void executeQueue(Environment env, Action action, Object... parameters) {
+ execute(env, false, action, parameters);
+ }
+
+ /**
+ * Executes through the ActionQueue as there is no system dispatch thread.
+ * @param env {@inheritDoc }
+ * @param action {@inheritDoc }
+ * @param parameters {@inheritDoc }
+ * @see Action#run(java.lang.Object[])
+ */
+ public void executeQueueDetached(Environment env, Action action, Object... parameters) {
+ executeDetached(env, false, action, parameters);
+ }
+
+ /**
+ * Always returns false as there is no system dispatch thread.
+ * @return always false.
+ */
+ public boolean isOnQueue() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isQuiet() {
+ return actionsInQueue() == 0 && !isInAction();
+ }
+
+}
--- /dev/null 2017-11-08 15:39:26.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/FutureAction.java 2017-11-08 15:39:26.000000000 -0800
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.action;
+
+import org.jemmy.env.Environment;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+/**
+ * Created with IntelliJ IDEA. User: Andrey Nazarov Date: 14.05.13 Time: 20:49
+ */
+public class FutureAction extends Action {
+
+ final FutureTask task;
+
+ public FutureAction(Environment env, Callable callable) {
+ task = new FutureTask(callable);
+ env.getExecutor().execute(env, true, this);
+ }
+
+ public FutureAction(Environment env, Runnable runnable) {
+ task = new FutureTask(runnable, null);
+ env.getExecutor().execute(env, true, this);
+ }
+
+ @Override
+ public void run(Object... parameters) throws Exception {
+ task.run();
+ }
+
+ public T get() {
+ try {
+ return task.get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:26.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/action/GetAction.java 2017-11-08 15:39:26.000000000 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.action;
+
+
+import org.jemmy.env.Environment;
+
+
+/**
+ * An action to get some value.
+ * @param
+ * @author shura
+ */
+public abstract class GetAction extends Action {
+
+ private boolean finished = false;
+ private T result = null;
+
+ /**
+ *
+ */
+ public GetAction() {
+ }
+
+ /**
+ *
+ * @return
+ */
+ public boolean isFinished() {
+ return finished;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public T getResult() {
+ return result;
+ }
+
+ /**
+ *
+ * @param result
+ */
+ protected void setResult(T result) {
+ this.result = result;
+ finished = true;
+ }
+
+ /**
+ * Dispatches action through the system UI queue to get the result.
+ * @param env Environment to
+ * {@linkplain Environment#getExecutor() get} executor and to pass to
+ * {@linkplain ActionExecutor#execute(org.jemmy.env.Environment, boolean,
+ * org.jemmy.action.Action, java.lang.Object[]) execute()} method.
+ * @param parameters Parameters to pass to {@linkplain
+ * #run(java.lang.Object[]) run()} method.
+ * @return value returned by {@linkplain #getResult() getResult()} method.
+ */
+ public T dispatch(Environment env, Object... parameters) {
+ env.getExecutor().execute(env, true, this, parameters);
+ return getResult();
+ }
+
+}
--- /dev/null 2017-11-08 15:39:26.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/AbstractWrapper.java 2017-11-08 15:39:26.000000000 -0800
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.jemmy.env.Environment;
+
+
+/**
+ * This is an implementation of the {@code Wrapper} which instantiates a wrap
+ * of a class returned by {@code getWrapClass(Class)}.
+ * @author shura
+ */
+public abstract class AbstractWrapper implements Wrapper {
+
+ private Environment env;
+
+ /**
+ *
+ * @param env
+ */
+ @SuppressWarnings("unchecked")
+ public AbstractWrapper(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Environment getEnvironment() {
+ return env;
+ }
+
+ protected abstract Class getWrapClass(Class controlClass);
+
+ /**
+ *
+ * @param
+ * @param controlClass
+ * @param control
+ * @return Wrap
+ */
+ public Wrap extends T> wrap(Class controlClass, T control) {
+ Class cls = control.getClass();
+ Class wrp;
+ do {
+ wrp = getWrapClass(cls);
+ if (wrp != null) {
+ try {
+ return doWrap(control, cls, wrp);
+ } catch (InstantiationException ex) {
+ throw new WrapperException(cls, wrp, ex);
+ } catch (IllegalAccessException ex) {
+ throw new WrapperException(cls, wrp, ex);
+ } catch (IllegalArgumentException ex) {
+ throw new WrapperException(cls, wrp, ex);
+ } catch (InvocationTargetException ex) {
+ throw new WrapperException(cls, wrp, ex);
+ } catch (NoSuchMethodException ex) {
+ throw new WrapperException(cls, wrp, ex);
+ } catch (SecurityException ex) {
+ throw new WrapperException(cls, wrp, ex);
+ }
+ }
+ } while ((cls = cls.getSuperclass()) != null);
+ throw new WrapperException(control);
+ }
+
+ /**
+ *
+ * @param
+ * @param control
+ * @param controlClass
+ * @param wrapperClass
+ * @return Wrap
+ * @throws java.lang.NoSuchMethodException
+ * @throws java.lang.InstantiationException
+ * @throws java.lang.IllegalAccessException
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.reflect.InvocationTargetException
+ */
+ @SuppressWarnings("unchecked")
+ protected Wrap extends T> doWrap(T control, Class controlClass, Class wrapperClass) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ Constructor cns = null;
+ Class cls = controlClass;
+ do {
+ try {
+ cns = wrapperClass.getConstructor(Environment.class, cls);
+ } catch (NoSuchMethodException e) {
+ }
+ } while ((cls = cls.getSuperclass()) != null);
+ if (cns != null) {
+ return (Wrap) cns.newInstance(new Environment(env), control);
+ } else {
+ throw new WrapperException(controlClass, wrapperClass);
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:27.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/As.java 2017-11-08 15:39:27.000000000 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+import java.lang.annotation.*;
+import org.jemmy.interfaces.TypeControlInterface;
+
+/**
+ * This annotation should be used to annotate methods which turn a wrap
+ * into a control interface. It is, then, used in Wrap.as(*)
and
+ * Wrap.is(*)
methods and in *Dock.as*()
methods.
+ * @see Wrap#as(java.lang.Class)
+ * @see Wrap#as(java.lang.Class, java.lang.Class)
+ * @see Wrap#is(java.lang.Class)
+ * @see Wrap#is(java.lang.Class, java.lang.Class)
+ * @author shura
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Documented
+public @interface As {
+ /**
+ * This should point out what is the encapsulated type for
+ * TypeControlInterface
+ * @see TypeControlInterface
+ * @return
+ */
+ Class value() default Void.class;
+}
--- /dev/null 2017-11-08 15:39:27.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/ControlInterfaces.java 2017-11-08 15:39:27.000000000 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.jemmy.interfaces.ControlInterface;
+import org.jemmy.interfaces.TypeControlInterface;
+
+/**
+ * To be applied on classes - ancestors of Wrp
+ * class.
+ * @see Wrap
+ * @author shura
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+@Documented
+public @interface ControlInterfaces {
+ /**
+ * List of interfaces supported by this wrap.
+ * @see ControlInterface
+ */
+ Class extends ControlInterface>[] value();
+ /**
+ * List of encapsulated types for the TypeControlInterface
+ * interfaces listed in value
.
+ * Note that this list should be shorter that the value
to not
+ * provide anything for a ControlInterface
which is not a
+ * TypeControlInterface
+ * @see TypeControlInterface
+ */
+ Class[] encapsulates() default {};
+ /**
+ * This provides names for the dock methods which would be generated. If the array
+ * does not have enough elements, the method would be named as "as" + value[i].getName()
.
+ */
+ String[] name() default {};
+}
--- /dev/null 2017-11-08 15:39:27.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/ControlType.java 2017-11-08 15:39:27.000000000 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+import java.lang.annotation.*;
+
+/**
+ * TODO: JavaDoc
+ * @author shura
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Documented
+public @interface ControlType {
+ /**
+ *
+ * @return
+ */
+ Class[] value();
+}
--- /dev/null 2017-11-08 15:39:28.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/DefaultWrapper.java 2017-11-08 15:39:28.000000000 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+import org.jemmy.env.Environment;
+
+/**
+ *
+ * @author shura
+ */
+public class DefaultWrapper extends WrapperImpl {
+
+ /**
+ *
+ * @param env
+ * @param wrapList
+ */
+ @SuppressWarnings("unchecked")
+ public DefaultWrapper(Environment env, Class extends Wrap>... wrapList) {
+ super(env);
+ addAnnotated(wrapList);
+ }
+
+ /**
+ *
+ * @param env
+ */
+ @SuppressWarnings("unchecked")
+ public DefaultWrapper(Environment env) {
+ super(env);
+ }
+
+ /**
+ *
+ * @param list
+ */
+ @SuppressWarnings("unchecked")
+ public final void addAnnotated(Class extends Wrap>... list) {
+ for (Class cn : list) {
+ if (!cn.isAnnotationPresent(ControlType.class)) {
+ throw new IllegalStateException("\"" + cn.getName() + "\"" +
+ " must be annotated with @Control");
+ }
+ if (cn.isAnnotationPresent(ControlType.class)) {
+ ControlType cc = (ControlType) cn.getAnnotation(ControlType.class);
+ for(Class ccv : cc.value()) {
+ add(ccv, cn);
+ }
+ }
+ }
+ }
+
+
+}
--- /dev/null 2017-11-08 15:39:28.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/FieldProperties.java 2017-11-08 15:39:28.000000000 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This lists names of wrapped object's fields which could be accessed through
+ * Wrap.getProperty(String)
interface. Fields should be public.
+ * @see Wrap#getProperty(java.lang.String)
+ * @author shura
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+@Documented
+public @interface FieldProperties {
+ /**
+ * List of field names.
+ */
+ String[] value();
+ /**
+ * List of field types. In case this list is shorter, all the unmatched ones
+ * from value
are considered to be of type Object
.
+ */
+ Class[] types() default {};
+ /**
+ * Are the properties worth a waiter.
+ */
+ boolean[] waitable() default {};
+}
--- /dev/null 2017-11-08 15:39:28.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/JemmySupportWrapper.java 2017-11-08 15:39:28.000000000 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+import java.io.IOException;
+import java.io.InputStream;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.jemmy.env.Environment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * This loads information about the supported wrappers from an xml file which is
+ * generated by JemmySupport module.
+ * @author shura
+ */
+public class JemmySupportWrapper extends LazyWrapper {
+
+ public static final String CONTROL = "control";
+ public static final String WRAP = "wrap";
+
+ public JemmySupportWrapper(ClassLoader loader, InputStream in, Environment env) throws ParserConfigurationException, SAXException, IOException {
+ super(loader, env);
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document doc = builder.parse(in);
+ readAll(doc.getDocumentElement());
+ }
+
+ public JemmySupportWrapper(ClassLoader loader, String resource, Environment env) throws ParserConfigurationException, SAXException, IOException {
+ this(loader, loader.getResourceAsStream(resource), env);
+ }
+
+ private void readAll(Element element) {
+ NodeList cntrls = element.getElementsByTagName(CONTROL);
+ for(int i = 0; i < cntrls.getLength(); i++) {
+ readControl((Element)cntrls.item(i));
+ }
+ }
+
+ private void readControl(Element control) {
+ add(control.getAttribute(CONTROL), control.getAttribute(WRAP));
+ }
+
+}
--- /dev/null 2017-11-08 15:39:29.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/LazyWrapper.java 2017-11-08 15:39:29.000000000 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+
+import java.util.HashMap;
+import org.jemmy.JemmyException;
+import org.jemmy.env.Environment;
+
+
+/**
+ * This is an implementation of {@code Wrapper} which keeps a map between
+ * control class names and wrap class names. In only loads the wrap classes when
+ * first needed.
+ * @author shura
+ */
+public class LazyWrapper extends AbstractWrapper {
+
+ private final HashMap theWrappers = new HashMap();
+ private final ClassLoader loader;
+ /**
+ *
+ * @param env
+ */
+ @SuppressWarnings("unchecked")
+ public LazyWrapper(ClassLoader loader, Environment env) {
+ super(env);
+ this.loader = loader;
+ }
+
+ /**
+ *
+ * @param
+ * @param controlClass
+ * @param wrapperClass
+ */
+ public
void add(String controlClass, String wrapperClass) {
+ theWrappers.put(controlClass, wrapperClass);
+ }
+
+ @Override
+ protected Class getWrapClass(Class controlClass) {
+ String wrapClassName = theWrappers.get(controlClass.getName());
+ if(wrapClassName == null) {
+ return null;
+ }
+ try {
+ return (Class)loader.loadClass(wrapClassName);
+ } catch (ClassNotFoundException ex) {
+ throw new JemmyException("Unable to load wrap for " + controlClass.getName() +
+ " which is " + wrapClassName, ex);
+ }
+ }
+
+}
--- /dev/null 2017-11-08 15:39:29.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/MethodProperties.java 2017-11-08 15:39:29.000000000 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This lists names of wrapped object's methods which could be accessed through
+ * Wrap.getProperty(String)
interface. Methods should be public and
+ * should not have any parameters.
+ * @see Wrap#getProperty(java.lang.String)
+ * @author shura
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+@Documented
+public @interface MethodProperties {
+ /**
+ * List of method names
+ */
+ String[] value();
+ /**
+ * List of field types. In case this list is shorter, all the unmatched ones
+ * from value
are considered to be of type Object
.
+ */
+ Class[] types() default {};
+ /**
+ * Are the properties worth a waiter.
+ */
+ boolean[] waitable() default {};
+}
--- /dev/null 2017-11-08 15:39:29.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/Property.java 2017-11-08 15:39:29.000000000 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotates a method which provides a property value for the provided
+ * name of a wrapped control. To be used on public Wrap inheritors methods
+ * with no parameters. Property value is then accessible through
+ * Wrap.getProperty(String)
+ * @see Wrap#getProperty(java.lang.String)
+ * @author shura
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Documented
+public @interface Property {
+ /**
+ *
+ * @return a property name.
+ */
+ String value();
+ /**
+ * Are the properties worth a waiter.
+ */
+ boolean waitable() default false;
+}
--- /dev/null 2017-11-08 15:39:30.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/ScreenArea.java 2017-11-08 15:39:30.000000000 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+
+import org.jemmy.Rectangle;
+
+
+/**
+ *
+ * @author shura
+ */
+public interface ScreenArea {
+ /**
+ *
+ * @return
+ */
+ public abstract Rectangle getScreenBounds();
+}
--- /dev/null 2017-11-08 15:39:30.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/SelectorImpl.java 2017-11-08 15:39:30.000000000 -0800
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+import org.jemmy.JemmyException;
+import org.jemmy.interfaces.Selectable;
+import org.jemmy.interfaces.Selector;
+import org.jemmy.interfaces.Showable;
+import org.jemmy.timing.State;
+
+/**
+ *
+ * @param
+ * @param
+ * @author shura
+ */
+public class SelectorImpl implements Selector {
+
+ Wrap extends CONTROL> target;
+ Selectable selectable;
+
+ /**
+ *
+ * @param target
+ * @param selectable
+ */
+ public SelectorImpl(Wrap extends CONTROL> target, Selectable selectable) {
+ this.target = target;
+ this.selectable = selectable;
+ }
+
+ /**
+ *
+ * @param state
+ */
+ @SuppressWarnings("unchecked")
+ public void select(final STATE state) {
+ if (target.is(Showable.class)) {
+ target.as(Showable.class).shower().show();
+ }
+ int attempts = 0;
+ if (!selectable.getState().equals(state)) {
+ do {
+ final STATE currentState = selectable.getState();
+ if (attempts >= selectable.getStates().size()) {
+ throw new JemmyException("State is not reached in " + attempts + " attempts", state);
+ }
+ target.mouse().click(clickCount(state));
+ target.getEnvironment().getWaiter(Wrap.WAIT_STATE_TIMEOUT.getName()).ensureState(new State() {
+
+ public Object reached() {
+ return selectable.getState().equals(currentState) ? null : "";
+ }
+
+ @Override
+ public String toString() {
+ return "selectable state (" + selectable.getState() + ") equals '" + state + "'";
+ }
+
+ });
+ attempts++;
+ } while (!selectable.getState().equals(state));
+ }
+ }
+
+ private int clickCount(STATE state) {
+ int current = selectable.getStates().indexOf(selectable.getState());
+ int desired = selectable.getStates().indexOf(state);
+ if (desired >= current) {
+ return desired - current;
+ } else {
+ return selectable.getStates().size() - current + desired;
+ }
+ }
+
+ private class StateChangeState implements State {
+
+ Selectable source;
+ STATE original;
+
+ public StateChangeState(Selectable source) {
+ this.source = source;
+ this.original = source.getState();
+ }
+
+ public STATE reached() {
+ return (source.getState() != original) ? source.getState() : null;
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:30.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/Wrap.java 2017-11-08 15:39:30.000000000 -0800
@@ -0,0 +1,945 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import org.jemmy.JemmyException;
+import org.jemmy.Point;
+import org.jemmy.Rectangle;
+import org.jemmy.TimeoutExpiredException;
+import org.jemmy.action.GetAction;
+import org.jemmy.env.Environment;
+import org.jemmy.env.TestOut;
+import org.jemmy.env.Timeout;
+import org.jemmy.image.Image;
+import org.jemmy.interfaces.*;
+import org.jemmy.timing.State;
+
+/**
+ * This is a wrap which holds reference to a control without UI hierarchy. It
+ * also encapsulates all the logic to deal with the underlying control, in terms
+ * of implementations of ControlInterface.
+ *
+ * @see Wrap#as(java.lang.Class)
+ * @see Wrap#is(java.lang.Class)
+ * @param type of the encapsulated object.
+ * @author shura, erikgreijus
+ */
+@ControlType(Object.class)
+@ControlInterfaces({Mouse.class, Keyboard.class, Drag.class})
+public abstract class Wrap {
+
+ /**
+ *
+ */
+ public static final String BOUNDS_PROP_NAME = "bounds";
+ /**
+ *
+ */
+ public static final String CLICKPOINT_PROP_NAME = "clickPoint";
+ /**
+ *
+ */
+ public static final String CONTROL_CLASS_PROP_NAME = "control.class";
+ /**
+ *
+ */
+ public static final String CONTROL_PROP_NAME = "control";
+ /**
+ *
+ */
+ public static final String INPUT_FACTORY_PROPERTY = "input.control.interface.factory";
+ /**
+ *
+ */
+ public static final String IMAGE_LOADER_PROPERTY = "image.loader";
+ /**
+ *
+ */
+ public static final String IMAGE_CAPTURER_PROPERTY = "image.capturer";
+ /**
+ *
+ */
+ public static final String TEXT_PROP_NAME = "text";
+ /**
+ *
+ */
+ public static final String POSITION_PROP_NAME = "position";
+ /**
+ *
+ */
+ public static final String VALUE_PROP_NAME = "value";
+ /**
+ *
+ */
+ public static final String WRAPPER_CLASS_PROP_NAME = "wrapper.class";
+ /**
+ *
+ */
+ public static final String TOOLTIP_PROP_NAME = "tooltip";
+ /**
+ *
+ */
+ public static final String NAME_PROP_NAME = "name";
+ /**
+ *
+ */
+ public static final Timeout WAIT_STATE_TIMEOUT = new Timeout("wait.state", 1000);
+ /**
+ *
+ */
+ public static final String OUTPUT = Wrap.class.getName() + ".OUTPUT";
+ private static DefaultWrapper theWrapper = new DefaultWrapper(Environment.getEnvironment());
+
+ static {
+ Environment.getEnvironment().initTimeout(WAIT_STATE_TIMEOUT);
+ Environment.getEnvironment().initOutput(OUTPUT, TestOut.getNullOutput());
+ Environment.getEnvironment().initTimeout(Mouse.CLICK);
+ Environment.getEnvironment().initTimeout(Drag.BEFORE_DRAG_TIMEOUT);
+ Environment.getEnvironment().initTimeout(Drag.BEFORE_DROP_TIMEOUT);
+ Environment.getEnvironment().initTimeout(Drag.IN_DRAG_TIMEOUT);
+ Environment.getEnvironment().initTimeout(Keyboard.PUSH);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static DefaultWrapper getWrapper() {
+ return theWrapper;
+ }
+ CONTROL node;
+ Environment env;
+
+ /**
+ * Fur null source.
+ *
+ * @see org.jemmy.env.Environment
+ * @param env The environment
+ */
+ protected Wrap(Environment env) {
+ this.env = env;
+ node = null;
+ fillTheProps(false);
+ }
+
+ /**
+ *
+ * @see org.jemmy.env.Environment
+ * @param env The environment
+ * @param node The encapsulated object
+ */
+ protected Wrap(Environment env, CONTROL node) {
+ this.env = env;
+ this.node = node;
+ }
+
+ /**
+ *
+ * @see org.jemmy.env.Environment
+ * @return environment instance used by this
+ */
+ public Environment getEnvironment() {
+ return env;
+ }
+
+ public void setEnvironment(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ *
+ * @return The encapsulated object
+ */
+ @Property(CONTROL_PROP_NAME)
+ public CONTROL getControl() {
+ return node;
+ }
+
+ /**
+ * Return default point to click, drag. This implementation returns the
+ * center must be overriden if something different is desired.
+ *
+ * @return
+ */
+ @Property(CLICKPOINT_PROP_NAME)
+ public Point getClickPoint() {
+ return new Point(getScreenBounds().width / 2, (getScreenBounds().height / 2));
+ }
+
+ /**
+ * Returns control bounds in screen coordinates. These bounds could include
+ * parts that are covered by other controls or clipped out by parent
+ * components. If the control is not shown {@linkplain
+ * JemmyException JemmyException} will be thrown.
+ *
+ * @return control bounds in screen coordinates.
+ * @throws JemmyException if the control is not visible
+ */
+ @Property(BOUNDS_PROP_NAME)
+ public abstract Rectangle getScreenBounds();
+
+ /**
+ * Transforms point in local control coordinate system to screen
+ * coordinates.
+ *
+ * @param local
+ * @return
+ * @see #toLocal(org.jemmy.Point)
+ */
+ public Point toAbsolute(Point local) {
+ Rectangle bounds = getScreenBounds();
+ return local.translate(bounds.x, bounds.y);
+ }
+
+ /**
+ * Transforms point in screen coordinates to local control coordinate
+ * system.
+ *
+ * @param local
+ * @return coordinates which should be used for mouse operations.
+ * @see #toAbsolute(org.jemmy.Point)
+ */
+ public Point toLocal(Point local) {
+ Rectangle bounds = getScreenBounds();
+ return local.translate(-bounds.x, -bounds.y);
+ }
+
+ /**
+ * Captures the screen area held by the component. ImageFactory performs the
+ * actual capturing.
+ *
+ * @return TODO find a replacement
+ */
+ public Image getScreenImage() {
+ Rectangle bounds = getScreenBounds();
+ return getScreenImage(new Rectangle(0, 0, bounds.width, bounds.height));
+ }
+
+ /**
+ * Captures portion of the screen area held by the component. ImageFactory
+ * performs the actual capturing.
+ *
+ * @param rect Part of the control to capture
+ * @return TODO find a replacement
+ */
+ public Image getScreenImage(Rectangle rect) {
+ if (getEnvironment().getImageCapturer() == null) {
+ throw new JemmyException("Image capturer is not specified.");
+ }
+ return getEnvironment().getImageCapturer().capture(this, rect);
+ }
+
+ /**
+ * Waits for a portion of image to be exact the same as the parameter.
+ *
+ * @see Wrap#as(java.lang.Class)
+ * @param golden
+ * @param rect A portion of control to compare.
+ * @param resID ID of a result image to save in case of failure. No image
+ * saved if null.
+ * @param diffID ID of a diff image to save in case of failure. No image
+ * saved if null.
+ */
+ public void waitImage(final Image golden, final Rectangle rect, String resID, String diffID) {
+ try {
+ waitState(new State() {
+
+ public Object reached() {
+ return (getScreenImage(rect).compareTo(golden) == null) ? true : null;
+ }
+
+ @Override
+ public String toString() {
+ return "Control having expected image";
+ }
+ });
+ } catch (TimeoutExpiredException e) {
+ if (diffID != null) {
+ getEnvironment().getOutput(OUTPUT).println("Saving difference to " + diffID);
+ getScreenImage(rect).compareTo(golden).save(diffID);
+ }
+ throw e;
+ } finally {
+ if (resID != null) {
+ getEnvironment().getOutput(OUTPUT).println("Saving result to " + resID);
+ getScreenImage(rect).save(resID);
+ }
+ }
+ }
+
+ /**
+ * Waits for image to be exact the same as the parameter.
+ *
+ * @see Wrap#as(java.lang.Class)
+ * @param golden
+ * @param resID ID of a result image to save in case of failure. No image
+ * saved if null.
+ * @param diffID ID of a diff image to save in case of failure. No image
+ * saved if null.
+ */
+ public void waitImage(final Image golden, String resID, String diffID) {
+ Rectangle bounds = getScreenBounds();
+ waitImage(golden, new Rectangle(0, 0, bounds.width, bounds.height), resID, diffID);
+ }
+
+ /**
+ * TODO javadoc
+ *
+ * @param
+ * @param state
+ * @param value
+ * @return last returned State value
+ * @throws TimeoutExpiredException in case the wait is unsuccessful.
+ */
+ public V waitState(State state, V value) {
+ return getEnvironment().getWaiter(WAIT_STATE_TIMEOUT).ensureValue(value, state);
+ }
+
+ /**
+ * TODO javadoc
+ *
+ * @param
+ * @param state
+ * @return last returned State value
+ * @throws TimeoutExpiredException in case the wait is unsuccessful.
+ */
+ public V waitState(State state) {
+ return getEnvironment().getWaiter(WAIT_STATE_TIMEOUT).ensureState(state);
+ }
+
+ /**
+ * ***********************************************************************
+ */
+ /*
+ * INTERFACES
+ */
+ /**
+ * ***********************************************************************
+ */
+ private Method findAsMethod(Class extends ControlInterface> interfaceClass, Class type) {
+ while (type != null) {
+ for (Method m : getClass().getMethods()) {
+ As as = m.getAnnotation(As.class);
+ Class returnType = m.getReturnType();
+ if (as != null && interfaceClass.isAssignableFrom(returnType) && as.value().equals(type)) {
+ if (m.getParameterTypes().length > 0 && type.equals(Void.class)
+ || m.getParameterTypes().length > 1 && !type.equals(Void.class)) {
+ throw new IllegalStateException("wrong number of parameters in an @As method");
+ }
+ return m;
+ }
+ }
+ type = type.getSuperclass();
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the control could be treated as a ControlInterface. If it is,
+ * Wrap#as(java.lang.Class)
will be called. This implementation
+ * checks whether the class implements the necessary interface. It also
+ * works for root interfaces such as
+ * MouseTarget
and
+ * KeyTarget
, which implementations are encapsulated. If some
+ * other functionality is desired, must be overriden together with
+ * as(java.lang.Class)
+ *
+ * @see Wrap#is(java.lang.Class)
+ * @param
+ * @param interfaceClass
+ * @return
+ */
+ public boolean is(Class interfaceClass) {
+ if (interfaceClass.isInstance(this)) {
+ return true;
+ }
+ return findAsMethod(interfaceClass, Void.class) != null;
+ }
+
+ /**
+ * Checks if the control could be treated as a parametrized
+ * ControlInterface. If it is,
+ * Wrap#as(java.lang.Class, java.lang.Class)
will be called.
+ * This implementation checks whether the class implements the necessary
+ * interface. It also works for root interfaces such as
+ * MouseTarget
and
+ * KeyTarget
, which implementations are encapsulated. If some
+ * other functionality is desired, must be overriden together with
+ * as(java.lang.Class)
+ *
+ * @see Wrap#is(java.lang.Class)
+ * @param
+ * @param
+ * @param interfaceClass
+ * @param type The parameter class.
+ * @return
+ */
+ public > boolean is(Class interfaceClass, Class type) {
+ if (interfaceClass.isInstance(this)) {
+ if (interfaceClass.cast(this).getType().isAssignableFrom(type)) {
+ return true;
+ }
+ }
+ return findAsMethod(interfaceClass, type) != null;
+ }
+
+ private Object callAsMethod(Class extends ControlInterface> interfaceClass, Class type) {
+ Method m = findAsMethod(interfaceClass, type);
+ if (m != null) {
+ try {
+ if (m.getParameterTypes().length == 0) {
+ return m.invoke(this);
+ } else if (m.getParameterTypes().length == 1) {
+ return m.invoke(this, !type.equals(Void.class) ? type : Object.class);
+ } else {
+ throw new InterfaceException(this, interfaceClass);
+ }
+ } catch (IllegalAccessException ex) {
+ throw new JemmyException("Unable to call method \"" + m.getName() + "()\"", ex, this);
+ } catch (IllegalArgumentException ex) {
+ throw new JemmyException("Unable to call method \"" + m.getName() + "()\"", ex, this);
+ } catch (InvocationTargetException ex) {
+ throw new JemmyException("Unable to call method \"" + m.getName() + "()\"", ex, this);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns an implementation of interface associated with this object. First
+ * it checks
+ *
+ * @see Wrap#is(java.lang.Class)
+ * @param
+ * @param interfaceClass
+ * @return
+ */
+ public INTERFACE as(Class interfaceClass) {
+ if (interfaceClass.isInstance(this)) {
+ return interfaceClass.cast(this);
+ }
+
+ Object res = callAsMethod(interfaceClass, Void.class);
+ if (res != null) {
+ return (INTERFACE) res;
+ }
+
+ throw new InterfaceException(this, interfaceClass);
+ }
+
+ /**
+ * Returns an implementation of interface associated with the object.
+ *
+ * @see Wrap#is(java.lang.Class)
+ * @param
+ * @param
+ * @param interfaceClass
+ * @param type The parameter class.
+ * @return
+ */
+ public > INTERFACE as(Class interfaceClass, Class type) {
+ if (interfaceClass.isInstance(this)) {
+ if (interfaceClass.cast(this).getType().isAssignableFrom(type)) {
+ return interfaceClass.cast(this);
+ }
+ }
+
+ Object res = callAsMethod(interfaceClass, type);
+ if (res != null) {
+ return (INTERFACE) res;
+ }
+
+ throw new InterfaceException(this, interfaceClass);
+ }
+ /**
+ * ***********************************************************************
+ */
+ /*
+ * INPUT
+ */
+ /**
+ * ***********************************************************************
+ */
+ private Mouse mouse = null;
+ private Drag drag = null;
+ private Keyboard keyboard = null;
+
+ /**
+ * A shortcut to
+ * as(MouseTarget.class).mouse()
+ *
+ * @return
+ */
+ @As(Mouse.class)
+ public Mouse mouse() {
+ if (mouse == null) {
+ mouse = getEnvironment().getInputFactory().create(this, Mouse.class);
+ }
+ return mouse;
+ }
+
+ /**
+ * A shortcut to
+ * as(MouseTarget.class).drag()
+ *
+ * @return
+ */
+ @As(Drag.class)
+ public Drag drag() {
+ if (drag == null) {
+ drag = getEnvironment().getInputFactory().create(this, Drag.class);
+ }
+ return drag;
+ }
+
+ /**
+ * A shortcut to
+ * as(KeyTarget.class).wrap()
+ *
+ * @return
+ */
+ @As(Keyboard.class)
+ public Keyboard keyboard() {
+ if (keyboard == null) {
+ keyboard = getEnvironment().getInputFactory().create(this, Keyboard.class);
+ }
+ return keyboard;
+ }
+ /**
+ * ***********************************************************************
+ */
+ /*
+ * PROPERTIES
+ */
+ /**
+ * ***********************************************************************
+ */
+ private HashMap properties = new HashMap();
+
+ /**
+ *
+ * @return
+ */
+ @Property(CONTROL_CLASS_PROP_NAME)
+ public Class> getControlClass() {
+ return getControl().getClass();
+ }
+
+ private void fillTheProps(boolean quiet) {
+ properties.clear();
+ properties.put(WRAPPER_CLASS_PROP_NAME, getClass());
+ readAnnotationProps(quiet);
+ readControlProps(quiet);
+ }
+
+ private void readControlProps(boolean quiet) {
+ Class> cls = getClass();
+ do {
+ if (cls.isAnnotationPresent(FieldProperties.class)) {
+ for (String s : cls.getAnnotation(FieldProperties.class).value()) {
+ Object value;
+ try {
+ value = getFieldProperty(s);
+ } catch (Exception e) {
+ getEnvironment().getOutput().printStackTrace(e);
+ value = e.toString();
+ if (!(e instanceof JemmyException) && !quiet) {
+ throw new JemmyException("Exception while getting property \"" + s + "\"", e);
+ }
+ }
+ properties.put(s, value);
+ }
+ }
+ if (cls.isAnnotationPresent(MethodProperties.class)) {
+ for (String s : cls.getAnnotation(MethodProperties.class).value()) {
+ Object value;
+ try {
+ value = getMethodProperty(s);
+ } catch (Exception e) {
+ getEnvironment().getOutput().printStackTrace(e);
+ value = e.toString();
+ if (!(e instanceof JemmyException) && !quiet) {
+ throw new JemmyException("Exception while getting property \"" + s + "\"", e);
+ }
+ }
+ properties.put(s, value);
+ }
+ }
+ } while ((cls = cls.getSuperclass()) != null);
+ }
+
+ private void addAnnotationProps(Class cls, boolean quiet) {
+ for (Method m : cls.getMethods()) {
+ if (m.isAnnotationPresent(Property.class)) {
+ String name = m.getAnnotation(Property.class).value();
+ if (!properties.containsKey(name)) {
+ Object value;
+ try {
+ value = getProperty(this, m);
+ } catch (Exception e) {
+ if (quiet) {
+ getEnvironment().getOutput().printStackTrace(e);
+ value = e.toString();
+ } else {
+ throw new JemmyException("Exception while getting property \"" + name + "\"", e);
+ }
+ }
+ properties.put(name, value);
+ }
+ }
+ }
+ }
+
+ private void readAnnotationProps(boolean quiet) {
+ Class cls = getClass();
+ do {
+ addAnnotationProps(cls, quiet);
+ } while ((cls = cls.getSuperclass()) != null);
+ for (Class intf : getClass().getInterfaces()) {
+ addAnnotationProps(intf, quiet);
+ }
+ }
+
+ private void checkPropertyMethod(Method m) {
+ if (m.getParameterTypes().length > 0) {
+ throw new JemmyException("Method marked by @Property must not have parameters: "
+ + m.getDeclaringClass().getName() + "." + m.getName());
+ }
+ }
+
+ private Method getPropertyMethod(Class cls, String name) {
+ Class scls = cls;
+ do {
+ for (Method m : scls.getMethods()) {
+ if (m.isAnnotationPresent(Property.class) && m.getAnnotation(Property.class).value().equals(name)) {
+ checkPropertyMethod(m);
+ return m;
+ }
+ }
+ } while ((scls = scls.getSuperclass()) != null);
+ for (Class intf : cls.getInterfaces()) {
+ for (Method m : intf.getMethods()) {
+ if (m.isAnnotationPresent(Property.class) && m.getAnnotation(Property.class).value().equals(name)) {
+ checkPropertyMethod(m);
+ return m;
+ }
+ }
+ }
+ return null;
+ }
+
+ private Object getProperty(Object object, Method m) {
+ Property prop = m.getAnnotation(Property.class);
+ try {
+ return m.invoke(object);
+ } catch (IllegalAccessException ex) {
+ throw new JemmyException("Unable to obtain property \"" + ((prop != null) ? prop.value() : "null") + "\"", ex, this);
+ } catch (IllegalArgumentException ex) {
+ throw new JemmyException("Unable to obtain property \"" + ((prop != null) ? prop.value() : "null") + "\"", ex, this);
+ } catch (InvocationTargetException ex) {
+ throw new JemmyException("Unable to obtain property \"" + ((prop != null) ? prop.value() : "null") + "\"", ex, this);
+ }
+ }
+
+ /**
+ * Get property of the wrapped object. Uses first available from
+ * methods annotated by
+ * org.jemmy.control.Property
wrapped object methods
+ * listed in
+ * org.jemmy.control.MethodProperties
wrapped object
+ * fields listed in
+ * org.jemmy.control.FieldProperties
+ *
+ * @param name property name
+ * @throws JemmyException if no property found
+ * @see Property
+ * @see MethodProperties
+ * @see FieldProperties
+ * @return property value
+ */
+ public Object getProperty(String name) {
+ if (WRAPPER_CLASS_PROP_NAME.equals(name)) {
+ return getClass();
+ }
+ Method m = getPropertyMethod(this.getClass(), name);
+ if (m != null) {
+ return getProperty(this, m);
+ }
+ if (hasMethodProperty(name)) {
+ return getMethodProperty(name);
+ }
+ if (hasFieldProperty(name)) {
+ return getFieldProperty(name);
+ }
+ throw new JemmyException("No property \"" + name + "\"", this);
+ }
+
+ private Object getInterfaceProperty(Class cls, Object instance, String name) {
+ Method m = getPropertyMethod(cls, name);
+ if (m != null) {
+ return getProperty(instance, m);
+ }
+ throw new JemmyException("No property \"" + name + "\" in interface " + cls.getName(), instance);
+ }
+
+ /**
+ * Get property out of the control interface. Refer to the interface doc to
+ * find out what properties are provided.
+ *
+ * @param
+ * @param name
+ * @param intrfc
+ * @return
+ */
+ public Object getProperty(String name, Class intrfc) {
+ return getInterfaceProperty(intrfc, as(intrfc), name);
+ }
+
+ /**
+ * Get property out of the control interface. Refer to the interface doc to
+ * find out what properties are provided.
+ *
+ * @param
+ * @param
+ * @param name
+ * @param intrfc
+ * @param type
+ * @return
+ */
+ public > Object getProperty(String name, Class intrfc, Class type) {
+ return getInterfaceProperty(intrfc, as(intrfc, type), name);
+ }
+
+ /**
+ * Wait for the property
+ * property
to get the specified value.
+ * WAIT_STATE_TIMOUT
timeout is used
+ *
+ * @param property name of the property being waited for
+ * @param value property value to wait
+ */
+ public void waitProperty(final String property, final Object value) {
+ getEnvironment().getWaiter(WAIT_STATE_TIMEOUT).ensureValue(value, new State() {
+
+ public Object reached() {
+ return getProperty(property);
+ }
+
+ @Override
+ public String toString() {
+ return "Control having property " + property + " expected value '" + value + "' (Property = '" + getProperty(property) + "')";
+ }
+ });
+ }
+
+ /**
+ * Wait for the property
+ * property
of control interface to get the specified value.
+ * WAIT_STATE_TIMOUT
timeout is used
+ *
+ * @param
+ * @param property
+ * @param intrfc
+ * @param value
+ */
+ public void waitProperty(final String property, final Class intrfc, final Object value) {
+ Object instance = as(intrfc);
+ getEnvironment().getWaiter(WAIT_STATE_TIMEOUT).ensureValue(value, new State() {
+
+ public Object reached() {
+ return getProperty(property, intrfc);
+ }
+
+ @Override
+ public String toString() {
+ return "Interface " + intrfc.getName() + " having property " + property + " expected value '" + value + "' (Property = '" + getProperty(property, intrfc) + "')";
+ }
+ });
+ }
+
+ /**
+ * Wait for the property
+ * property
of control interface to get the specified value.
+ * WAIT_STATE_TIMOUT
timeout is used
+ *
+ * @param
+ * @param
+ * @param property
+ * @param intrfc
+ * @param type
+ * @param value
+ */
+ public > void waitProperty(final String property, final Class intrfc, final Class type, final Object value) {
+ getEnvironment().getWaiter(WAIT_STATE_TIMEOUT).ensureValue(value, new State() {
+
+ public Object reached() {
+ return getProperty(property, intrfc, type);
+ }
+
+ @Override
+ public String toString() {
+ return "Interface " + intrfc.getName() + " having property " + property + " expected value '" + value + "' (Property = '" + getProperty(property) + "')";
+ }
+ });
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public boolean hasFieldProperty(String name) {
+ Class> cls = getClass();
+ do {
+ if (cls.isAnnotationPresent(FieldProperties.class)) {
+ FieldProperties props = cls.getAnnotation(FieldProperties.class);
+ if (contains(props.value(), name)) {
+ return true;
+ }
+ }
+ } while ((cls = cls.getSuperclass()) != null);
+ return false;
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public boolean hasMethodProperty(String name) {
+ Class> cls = getClass();
+ do {
+ if (cls.isAnnotationPresent(MethodProperties.class)) {
+ MethodProperties props = cls.getAnnotation(MethodProperties.class);
+ if (contains(props.value(), name)) {
+ return true;
+ }
+ }
+ } while ((cls = cls.getSuperclass()) != null);
+ return false;
+ }
+
+ private boolean contains(String[] values, String name) {
+ for (int i = 0; i < values.length; i++) {
+ if (name.equals(values[i])) {
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public Object getFieldProperty(final String name) {
+ if (!hasFieldProperty(name)) {
+ throw new JemmyException("No \"" + name + "\" field property specified on " + getClass().getName());
+ }
+ GetAction action = new GetAction() {
+
+ @Override
+ public void run(Object... parameters) throws Exception {
+ setResult(getControl().getClass().getField(name).get(getControl()));
+ }
+ };
+ Object result = action.dispatch(env);
+ if (action.getThrowable() != null) {
+ throw new JemmyException("Unable to obtain property \"" + name + "\"", action.getThrowable(), this);
+ }
+ return result;
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public Object getMethodProperty(final String name) {
+ if (!hasMethodProperty(name)) {
+ throw new JemmyException("No \"" + name + "\" method property specified on " + getClass().getName());
+ }
+ GetAction action = new GetAction() {
+
+ @Override
+ public void run(Object... parameters) throws Exception {
+ setResult(getControl().getClass().getMethod(name).invoke(getControl()));
+ }
+
+ @Override
+ public String toString() {
+ return "Getting property \"" + name + "\" on " + getClass().getName();
+ }
+ };
+ Object result = action.dispatch(env);
+ if (action.getThrowable() != null) {
+ throw new JemmyException("Unable to obtain property \"" + name + "\"", action.getThrowable(), this);
+ }
+ return result;
+ }
+
+ /**
+ *
+ * @param
+ * @param valueClass
+ * @param name
+ * @return
+ */
+ public
P getProperty(Class
valueClass, String name) {
+ return valueClass.cast(getProperty(name));
+ }
+
+ /**
+ * Returns a a map of all known controls properties including values from
+ * methods marked by
+ * @Property
and values of methods/field from
+ * @MethodProperties
/
+ * FieldProperties
correspondingly.
+ *
+ * @return a map of properties
+ * @throws Runtime exception should there be an exception thrown while
+ * getting a property
+ */
+ public HashMap getProperties() {
+ fillTheProps(false);
+ return properties;
+ }
+
+ /**
+ * Returns a a map of all controls properties which is possible to obtain.
+ * Similar to
+ * getProperties()
only exception is swallowed should there be
+ * an exception thrown while getting a property.
+ *
+ * @return a map of properties which were possible to obtain.
+ */
+ public HashMap getPropertiesQiuet() {
+ fillTheProps(true);
+ return properties;
+ }
+}
--- /dev/null 2017-11-08 15:39:31.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/Wrapper.java 2017-11-08 15:39:31.000000000 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+/**
+ *
+ * @author shura
+ */
+public interface Wrapper {
+ /**
+ *
+ * @param
+ * @param controlClass
+ * @param control
+ * @return Wrap
+ */
+ public Wrap extends T> wrap(Class controlClass, T control);
+}
--- /dev/null 2017-11-08 15:39:31.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/WrapperDelegate.java 2017-11-08 15:39:31.000000000 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+import org.jemmy.env.Environment;
+
+/**
+ * This allows to reuse another {@code Wrapper} with a different environment
+ * @author shura
+ */
+public class WrapperDelegate implements Wrapper {
+ private final Wrapper real;
+ private final Environment env;
+
+ public WrapperDelegate(Wrapper real, Environment env) {
+ this.real = real;
+ this.env = env;
+ }
+
+ public Wrap extends T> wrap(Class controlClass, T control) {
+ Wrap extends T> res = real.wrap(controlClass, control);
+ res.setEnvironment(new Environment(env));
+ return res;
+ }
+}
--- /dev/null 2017-11-08 15:39:31.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/WrapperException.java 2017-11-08 15:39:31.000000000 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.control;
+
+import org.jemmy.JemmyException;
+
+/**
+ *
+ * @author shura
+ */
+public class WrapperException extends JemmyException {
+
+ /**
+ *
+ * @param
+ * @param controlClass
+ * @param wrapperClass
+ * @param e
+ */
+ public WrapperException(Class controlClass, Class wrapperClass, Exception e) {
+ super(controlClass.getName() + " is not accepted by " + wrapperClass.getName(), e);
+ }
+
+ /**
+ *
+ * @param
+ * @param controlClass
+ * @param wrapperClass
+ */
+ public WrapperException(Class controlClass, Class wrapperClass) {
+ super(controlClass.getName() + " is not accepted by " + wrapperClass.getName());
+ }
+
+ /**
+ *
+ * @param
+ * @param control
+ */
+ public WrapperException(Object control) {
+ super("Unable to find a wrapper", control);
+ }
+
+}
--- /dev/null 2017-11-08 15:39:32.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/control/WrapperImpl.java 2017-11-08 15:39:32.000000000 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.control;
+
+
+import java.util.HashMap;
+import org.jemmy.env.Environment;
+
+
+/**
+ * This is an implementation of {@code Wrapper} which keeps a map between
+ * control classes and wrap classes.
+ * @author shura
+ */
+public class WrapperImpl extends AbstractWrapper {
+
+ private HashMap> theWrappers;
+
+ /**
+ *
+ * @param env
+ */
+ @SuppressWarnings("unchecked")
+ public WrapperImpl(Environment env) {
+ super(env);
+ theWrappers = new HashMap>();
+ }
+
+ /**
+ *
+ * @param
+ * @param controlClass
+ * @param wrapperClass
+ */
+ public
void add(Class controlClass, Class wrapperClass) {
+ theWrappers.put(controlClass, wrapperClass);
+ // TODO: Improve output
+// getEnvironment().getOutput().println("Added \"" + wrapperClass.getName() + "\"" +
+// " wrapper for \"" + controlClass.getName() + "\" control type");
+ }
+
+ @Override
+ protected Class getWrapClass(Class controlClass) {
+ return theWrappers.get(controlClass);
+ }
+
+}
--- /dev/null 2017-11-08 15:39:32.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/DefaultParent.java 2017-11-08 15:39:32.000000000 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.dock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.jemmy.interfaces.Parent;
+
+/**
+ * Putting this on a public static method allows to generate constructors which
+ * do not take parent as a parameter, taking whatever is coming from this method
+ * instead. An annotated method should take one parameter - class of the controls
+ * to by looked for and should return parent for that type.
+ * @see Parent
+ * @author shura
+ */
+@Target(ElementType.METHOD)
+@Documented
+public @interface DefaultParent {
+ /**
+ * Description of a parent represented by the annotated method.
+ */
+ String value();
+}
--- /dev/null 2017-11-08 15:39:32.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/DefaultWrapper.java 2017-11-08 15:39:32.000000000 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.dock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Putting this on a public static method allows to generate constructors which
+ * do not take parent as a parameter, taking whatever is coming from this method
+ * instead. An annotated method should take one parameter - class of the controls
+ * to by looked for and should return parent for that type.
+ * @see Parent
+ * @author shura
+ */
+@Target(ElementType.METHOD)
+@Documented
+public @interface DefaultWrapper {
+}
--- /dev/null 2017-11-08 15:39:33.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/Dock.java 2017-11-08 15:39:33.000000000 -0800
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.dock;
+
+import org.jemmy.Rectangle;
+import org.jemmy.action.GetAction;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Drag;
+import org.jemmy.interfaces.Keyboard;
+import org.jemmy.interfaces.Mouse;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.lookup.Lookup;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * Superclass for all "docks" - classes which simple provide API for lookup, interfaces
+ * and properties.
+ * @author shura
+ */
+public class Dock {
+
+ /**
+ * Default suffix to construct result image name.
+ */
+ public static final String DEFAULT_RESULT_IMAGE_SUFFIX = "default.result.image.suffix";
+ /**
+ * Default suffix to construct diff image name.
+ */
+ public static final String DEFAULT_DIFF_IMAGE_SUFFIX = "default.diff.image.suffix";
+
+ static {
+ Environment.getEnvironment().setPropertyIfNotSet(DEFAULT_DIFF_IMAGE_SUFFIX, "-diff");
+ Environment.getEnvironment().setPropertyIfNotSet(DEFAULT_RESULT_IMAGE_SUFFIX, "-result");
+ }
+
+ private Wrap> wrap;
+
+ protected Dock(Wrap> wrap) {
+ this.wrap = wrap;
+ }
+
+ /**
+ * Method which at the end actually get called from all dock lookup
+ * constructors.
+ * @param
+ * @param parent
+ * @param controlType
+ * @param index
+ * @param criteria
+ * @return
+ */
+ protected static Wrap extends T> lookup(Parent super T> parent, Class controlType, int index, LookupCriteria... criteria) {
+ Lookup lookup;
+ if (criteria.length > 0) {
+ lookup = parent.lookup(controlType, criteria[0]);
+ for (int i = 1; i < criteria.length; i++) {
+ lookup = lookup.lookup(controlType, criteria[i]);
+ }
+ } else {
+ lookup = parent.lookup(controlType);
+ }
+ return lookup.wrap(index);
+ }
+
+ /**
+ *
+ * @return Wrap instance obtainer through lookup
+ */
+ public Wrap> wrap() {
+ return wrap;
+ }
+
+ /**
+ *
+ * @return Wrap instance obtainer through lookup
+ */
+ public Object control() {
+ return wrap.getControl();
+ }
+
+ /**
+ * Shortcut to wrap().mouse()
+ */
+ public Mouse mouse() {
+ return wrap.mouse();
+ }
+
+ /**
+ * Shortcut to wrap().keyboard()
+ */
+ public Keyboard keyboard() {
+ return wrap.keyboard();
+ }
+
+ /**
+ * Shortcut to wrap().drag()
+ */
+ public Drag drag() {
+ return wrap.drag();
+ }
+
+ /**
+ * Shortcut to wrap().getScreenBounds()
+ */
+ public Rectangle bounds() {
+ return wrap.getScreenBounds();
+ }
+
+ protected P getProperty(GetAction
action) {
+ action.execute();
+ return action.getResult();
+ }
+
+ /**
+ *
+ * @return wrap().getEnvironment()
.
+ */
+ public Environment environment() {
+ return wrap.getEnvironment();
+ }
+
+ /**
+ * Loads image with goldenId
id waits for the control to match it.
+ * @see Wrap#waitImage(org.jemmy.image.Image, org.jemmy.Rectangle, java.lang.String, java.lang.String)
+ */
+ public void waitImage(String goldenId, Rectangle rect, String resID, String diffID) {
+ wrap.waitImage(environment().getImageLoader().load(goldenId), rect, resID, diffID);
+ }
+
+ /**
+ * Constructs names for diff and result images and waits for the control to match it.
+ * Diff and result names
+ * constructed by adding suffixes. Suffixes are obtained from environment with
+ * default values being "-diff" and "-result"
+ * @see #waitImage(java.lang.String, org.jemmy.Rectangle, java.lang.String, java.lang.String)
+ * @see #DEFAULT_DIFF_IMAGE_SUFFIX
+ * @see #DEFAULT_RESULT_IMAGE_SUFFIX
+ */
+ public void waitImage(String goldenId, Rectangle rect) {
+ waitImage(goldenId,
+ rect,
+ goldenId + environment().getProperty(DEFAULT_RESULT_IMAGE_SUFFIX),
+ goldenId + environment().getProperty(DEFAULT_DIFF_IMAGE_SUFFIX));
+ }
+
+ /**
+ * Loads image with goldenId
id waits for the control to match it.
+ * @see Wrap#waitImage(org.jemmy.image.Image, java.lang.String, java.lang.String)
+ */
+ public void waitImage(String goldenId, String resID, String diffID) {
+ wrap.waitImage(environment().getImageLoader().load(goldenId), resID, diffID);
+ }
+
+ /**
+ * Constructs names for diff and result images and waits for the control to match it.
+ * Diff and result names
+ * constructed by adding suffixes. Suffixes are obtained from environment with
+ * default values being "-diff" and "-result"
+ * @see #waitImage(java.lang.String, java.lang.String, java.lang.String)
+ * @see #DEFAULT_DIFF_IMAGE_SUFFIX
+ * @see #DEFAULT_RESULT_IMAGE_SUFFIX
+ */
+ public void waitImage(String goldenId) {
+ waitImage(goldenId,
+ goldenId + environment().getProperty(DEFAULT_RESULT_IMAGE_SUFFIX),
+ goldenId + environment().getProperty(DEFAULT_DIFF_IMAGE_SUFFIX));
+ }
+ }
--- /dev/null 2017-11-08 15:39:33.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/DockInfo.java 2017-11-08 15:39:33.000000000 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.dock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.jemmy.control.Wrap;
+
+/**
+ * This should be used on classes - inheritors of Wrap
class to give
+ * annotation processor some information.
+ * @see Wrap
+ * @author shura
+ */
+@Target(ElementType.TYPE)
+@Documented
+public @interface DockInfo {
+ /**
+ * Desired name of the dock class, should one be generated.
+ * Usually empty ("", as nulls are not allowed) in which case the calculated value
+ * is taken whatever logic annotation processor decides to use.
+ */
+ String name() default "";
+
+ /**
+ * Should there be extra constructors which take another lookup criteria - a class
+ * of a desired control? That class must be a subtype of the one wrapped by the wrap
+ * class annotated with this annotation.
+ */
+ boolean generateSubtypeLookups() default false;
+
+ /**
+ * Should generated wrap()
method return this class or
+ * Wrap extends ...>
and also should there be a constructor with
+ * one parameter - the wrap.
+ */
+ boolean anonymous() default false;
+
+ /**
+ * Should the lookup constructors have LookupCriteria<Type>...
+ * parameter or the LookupCriteria<Type>
parameter.
+ */
+ boolean multipleCriteria() default true;
+}
--- /dev/null 2017-11-08 15:39:33.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/ObjectLookup.java 2017-11-08 15:39:33.000000000 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.dock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.jemmy.interfaces.Parent;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * This should be used to allow to build dock lookup constructors which take
+ * some values (such as text, value, orientation, etc) instead of lookup criteria.
+ * Methods annotated with this should take class of the looked up control as a
+ * first parameter and return parent around that type.
+ * @see Parent
+ * @see LookupCriteria
+ * @author shura
+ */
+@Target(ElementType.METHOD)
+@Documented
+public @interface ObjectLookup {
+ /**
+ * Description of the method parameters. To be used in the javadoc later.
+ */
+ String value();
+}
--- /dev/null 2017-11-08 15:39:34.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/PreferredParent.java 2017-11-08 15:39:34.000000000 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.dock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Parent;
+
+/**
+ * The annotation to be used on a child-type wrap (such as ListItemWrap), pointing
+ * to a parent type wrap (such as ListViewWrap).
+ */
+@Target(ElementType.TYPE)
+@Documented
+public @interface PreferredParent {
+ Class extends Wrap> value();
+}
--- /dev/null 2017-11-08 15:39:34.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/dock/Shortcut.java 2017-11-08 15:39:34.000000000 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.dock;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author Andrey Nazarov
+ */
+@Target(ElementType.METHOD)
+@Documented
+@Retention(RetentionPolicy.CLASS)
+public @interface Shortcut {
+ /**
+ * If name is not specified, then shortcut's name will same as name of interface method
+ */
+ String name() default "";
+}
--- /dev/null 2017-11-08 15:39:34.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/env/Environment.java 2017-11-08 15:39:34.000000000 -0800
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.env;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import org.jemmy.JemmyException;
+import org.jemmy.action.ActionExecutor;
+import org.jemmy.action.DefaultExecutor;
+import org.jemmy.control.Wrap;
+import org.jemmy.image.ImageCapturer;
+import org.jemmy.image.ImageLoader;
+import org.jemmy.input.CharBindingMap;
+import org.jemmy.interfaces.ControlInterfaceFactory;
+import org.jemmy.timing.Waiter;
+
+/**
+ *
+ * @author shura, mrkam, erikgreijus
+ */
+public class Environment {
+
+ /**
+ *
+ */
+ public static final String JEMMY_PROPERTIES_FILE_PROPERTY = "jemmy.properties";
+ public static final String TIMEOUTS_FILE_PROPERTY = "timeouts";
+ /**
+ * Information output for Environment class
+ */
+ public static final String OUTPUT = Environment.class.getName() + ".OUTPUT";
+ private final static Environment env = new Environment(null);
+
+ /**
+ *
+ * @return
+ */
+ public static Environment getEnvironment() {
+ return env;
+ }
+
+ static {
+ env.setOutput(new TestOut(System.in, System.out, System.err));
+ env.setExecutor(new DefaultExecutor());
+ }
+ private HashMap environment = new HashMap();
+ private Environment parent;
+
+ /**
+ *
+ * @param parent
+ */
+ public Environment(Environment parent) {
+ this.parent = parent;
+ environment = new HashMap();
+ if (parent == null) {
+ loadProperties(System.getProperty(JEMMY_PROPERTIES_FILE_PROPERTY));
+ }
+ }
+
+ /**
+ *
+ */
+ public Environment() {
+ this(getEnvironment());
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Environment getParentEnvironment() {
+ return parent;
+ }
+
+ /**
+ *
+ * @param parent
+ */
+ public void setParentEnvironment(Environment parent) {
+ this.parent = parent;
+ }
+
+ public void loadProperties(String propFileName) {
+ if (propFileName == null || propFileName.length() == 0) {
+ propFileName = System.getProperty("user.home") + File.separator + ".jemmy.properties";
+ }
+ File propFile = new File(propFileName);
+ System.out.println("Loading jemmy properties from " + propFile);
+ if (propFile.exists()) {
+ Properties props = new Properties();
+ try {
+ props.load(new FileInputStream(propFile));
+ } catch (IOException ex) {
+ throw new JemmyException("Unable to load properties", ex, propFileName);
+ }
+ for (String k : props.stringPropertyNames()) {
+ if (k.equals(TIMEOUTS_FILE_PROPERTY)) {
+ loadTimeouts(propFile.getParentFile(), props.getProperty(k));
+ } else {
+ setProperty(k, props.getProperty(k));
+ }
+ }
+ } else {
+ System.out.println("Property file " + propFile + " does not exists. Ignoring.");
+ }
+ }
+
+ private void loadTimeouts(File propDir, String file) {
+ File timeoutsFile = new File(file);
+ if (!timeoutsFile.isAbsolute()) {
+ timeoutsFile = new File(propDir.getAbsolutePath() + File.separator + file);
+ }
+ System.out.println("Loading timeouts from " + timeoutsFile.getAbsolutePath());
+ try {
+ Properties timeouts = new Properties();
+ timeouts.load(new FileInputStream(timeoutsFile));
+ for (String k : timeouts.stringPropertyNames()) {
+ setTimeout(k, Long.parseLong(timeouts.getProperty(k)));
+ }
+ } catch (IOException ex) {
+ throw new JemmyException("Unable to load timeouts", ex, timeoutsFile.getAbsolutePath());
+ }
+ }
+
+ /**
+ *
+ * @param cls
+ * @return
+ */
+ public List> get(Class cls) {
+ Set all = environment.keySet();
+ ArrayList result = new ArrayList();
+ for (PropertyKey key : all) {
+ if (key.getCls().equals(cls)) {
+ result.add(environment.get(key));
+ }
+ }
+ return result;
+ }
+
+ /**
+ *
+ * @param defaultExecutor
+ * @return
+ */
+ public ActionExecutor setExecutor(ActionExecutor defaultExecutor) {
+ return (ActionExecutor) setProperty(ActionExecutor.class, defaultExecutor);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public ActionExecutor getExecutor() {
+ ActionExecutor res = (ActionExecutor) getProperty(ActionExecutor.class);
+ if (res == null) {
+ String executorClassName = (String) getProperty(ActionExecutor.ACTION_EXECUTOR_PROPERTY);
+ try {
+ res = ActionExecutor.class.cast(Class.forName(executorClassName).newInstance());
+ setExecutor(res);
+ } catch (InstantiationException ex) {
+ throw new JemmyException("Unable to instantiate executor ", ex, executorClassName);
+ } catch (IllegalAccessException ex) {
+ throw new JemmyException("Unable to instantiate executor ", ex, executorClassName);
+ } catch (ClassNotFoundException ex) {
+ throw new JemmyException("No executorclass ", ex, executorClassName);
+ }
+ }
+ return res;
+ }
+
+ public T setProperty(Class cls, Object ref, T obj) {
+ return setProperty(new PropertyKey(cls, ref), obj);
+ }
+
+ private T setPropertyIfNotSet(Class cls, Object ref, T obj) {
+ return setPropertyIfNotSet(new PropertyKey(cls, ref), obj);
+ }
+
+ private T getProperty(Class cls, Object ref) {
+ return getProperty(cls, ref, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getProperty(Class cls, Object ref, T defaultValue) {
+ for (PropertyKey pk : environment.keySet()) {
+ if (pk.equals(new PropertyKey(cls, ref))) {
+ return (T) environment.get(pk);
+ }
+ }
+ if (getParentEnvironment() != null) {
+ return getParentEnvironment().getProperty(cls, ref, defaultValue);
+ } else {
+ return defaultValue;
+ }
+ }
+
+ /**
+ *
+ * @param
+ * @param cls
+ * @param obj if null then property is removed
+ * @return
+ */
+ public T setProperty(Class cls, T obj) {
+ return setProperty(cls, null, obj);
+ }
+
+ /**
+ *
+ * @param
+ * @param cls
+ * @param obj if null then property is removed
+ * @return
+ */
+ public T setPropertyIfNotSet(Class cls, T obj) {
+ return setPropertyIfNotSet(cls, null, obj);
+ }
+
+ /**
+ *
+ * @param
+ * @param cls
+ * @return
+ */
+ public T getProperty(Class cls) {
+ return getProperty(cls, null);
+ }
+
+ /**
+ *
+ * @param name
+ * @param obj if null then property is removed
+ * @return
+ */
+ public Object setProperty(String name, Object obj) {
+ return setProperty(Object.class, name, obj);
+ }
+
+ /**
+ *
+ * @param name
+ * @param obj
+ * @return
+ */
+ public Object setPropertyIfNotSet(String name, Object obj) {
+ return setPropertyIfNotSet(Object.class, name, obj);
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public Object getProperty(String name) {
+ return getProperty(Object.class, name);
+ }
+
+ /**
+ *
+ * @param name
+ * @param defaultValue
+ * @return
+ */
+ public Object getProperty(String name, Object defaultValue) {
+ return getProperty(Environment.class, name, defaultValue);
+ }
+
+ private T setProperty(PropertyKey key, Object value) {
+ if (value == null) {
+ return key.cls.cast(environment.remove(key));
+ } else {
+ return key.cls.cast(environment.put(key, value));
+ }
+ }
+
+ private T setPropertyIfNotSet(PropertyKey key, T value) {
+ if (getParentEnvironment() != null) {
+ T res = key.cls.cast(getParentEnvironment().getProperty(key));
+ if (res != null) {
+ return res;
+ }
+ }
+ T res = key.cls.cast(environment.get(key));
+ if (res == null) {
+ return key.cls.cast(environment.put(key, value));
+ } else {
+ return res;
+ }
+ }
+
+ private Object getProperty(PropertyKey key) {
+ return environment.get(key);
+ }
+
+ /**
+ *
+ * @param out
+ * @return
+ */
+ public TestOut setOutput(TestOut out) {
+ return (TestOut) setProperty(TestOut.class, out);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public TestOut getOutput() {
+ return (TestOut) getProperty(TestOut.class);
+ }
+
+ /**
+ * Set some specific output. All classes which provide output should use
+ * some specific outputs. Please consult javadoc for a class in question.
+ * Use null
to unset the property.
+ *
+ * @param outputName
+ * @param out
+ * @return
+ */
+ public TestOut setOutput(String outputName, TestOut out) {
+ return (TestOut) setProperty(TestOut.class, outputName, out);
+ }
+
+ /**
+ * Initializes some specific output only if it is not yet set.
+ *
+ * @param outputName
+ * @param out
+ * @return
+ */
+ public TestOut initOutput(String outputName, TestOut out) {
+ TestOut res = (TestOut) getProperty(TestOut.class, outputName);
+ if (res == null) {
+ return setOutput(outputName, out);
+ } else {
+ return res;
+ }
+ }
+
+ /**
+ * Get's a specific output. If nothing assigned, returns
+ * getOutput()
+ *
+ * @param outputName
+ * @return
+ */
+ public TestOut getOutput(String outputName) {
+ TestOut res = (TestOut) getProperty(TestOut.class, outputName);
+ return (res != null) ? res : getOutput();
+ }
+
+ /**
+ *
+ * @param timeout
+ * @return
+ */
+ public Waiter getWaiter(Timeout timeout) {
+ return getWaiter(timeout.getName());
+ }
+
+ /**
+ *
+ * @param timeoutName
+ * @return
+ */
+ public Waiter getWaiter(String timeoutName) {
+ return new Waiter(getTimeout(timeoutName));
+ }
+
+ /**
+ *
+ * @param timeout
+ * @return
+ */
+ public Timeout getTimeout(Timeout timeout) {
+ return getTimeout(timeout.getName());
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public Timeout getTimeout(String name) {
+ return (Timeout) getProperty(Timeout.class, name);
+ }
+
+ /**
+ * Sets timeout.
+ *
+ * @param timeout Timeout to set.
+ * @return replaced timeout if it was already set.
+ */
+ public Timeout setTimeout(Timeout timeout) {
+ return (Timeout) setProperty(Timeout.class, timeout.getName(), timeout);
+ }
+
+ /**
+ * Initializes timeout only if it is not set.
+ *
+ * @param timeout Timeout to set.
+ * @return replaced timeout if it was already set.
+ */
+ public Timeout initTimeout(Timeout timeout) {
+ if (getProperty(Timeout.class, timeout.getName()) == null) {
+ return setTimeout(timeout);
+ }
+ return getTimeout(timeout);
+ }
+
+ /**
+ * Sets new value for the timeout specified by Timeout object instance.
+ *
+ * @param timeout Timeout object instance which identifies the name of the
+ * timeout to set.
+ * @param value new value for the timout.
+ * @return replaced timeout if it was already set.
+ */
+ public Timeout setTimeout(Timeout timeout, long value) {
+ return setTimeout(timeout.getName(), value);
+ }
+
+ /**
+ * Sets new value for the timeout.
+ *
+ * @param name Name of the timeout.
+ * @param value Value of the timeout.
+ * @return replaced timeout if it was already set.
+ */
+ public Timeout setTimeout(String name, long value) {
+ return setTimeout(new Timeout(name, value));
+ }
+
+ /**
+ *
+ * @return
+ */
+ public CharBindingMap getBindingMap() {
+ return (CharBindingMap) getProperty(CharBindingMap.class);
+ }
+
+ /**
+ *
+ * @param map
+ * @return
+ */
+ public CharBindingMap setBindingMap(CharBindingMap map) {
+ return (CharBindingMap) setProperty(CharBindingMap.class, map);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public ImageLoader getImageLoader() {
+ ImageLoader res = (ImageLoader) getProperty(ImageLoader.class);
+ if (res == null) {
+ String loaderClass = (String) getProperty(Wrap.IMAGE_LOADER_PROPERTY);
+ if (loaderClass == null) {
+ throw new IllegalStateException("No image loader provided!");
+ }
+ try {
+ res = ImageLoader.class.cast(Class.forName(String.class.cast(loaderClass)).newInstance());
+ setImageLoader(res);
+ } catch (InstantiationException ex) {
+ throw new JemmyException("Unable to instantiate image loader ", ex, loaderClass);
+ } catch (IllegalAccessException ex) {
+ throw new JemmyException("Unable to instantiate image loader ", ex, loaderClass);
+ } catch (ClassNotFoundException ex) {
+ throw new JemmyException("No image loader class ", ex, loaderClass);
+ }
+ }
+ return res;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public ImageCapturer getImageCapturer() {
+ ImageCapturer res = (ImageCapturer) getProperty(ImageCapturer.class);
+ if (res == null) {
+ String capturerClass = (String) getProperty(Wrap.IMAGE_CAPTURER_PROPERTY);
+ if (capturerClass == null) {
+ throw new IllegalStateException("No image capturer provided!");
+ }
+ try {
+ res = ImageCapturer.class.cast(Class.forName(String.class.cast(capturerClass)).newInstance());
+ setImageCapturer(res);
+ } catch (InstantiationException ex) {
+ throw new JemmyException("Unable to instantiate image capturer ", ex, capturerClass);
+ } catch (IllegalAccessException ex) {
+ throw new JemmyException("Unable to instantiate image capturer ", ex, capturerClass);
+ } catch (ClassNotFoundException ex) {
+ throw new JemmyException("No image capturer class ", ex, capturerClass);
+ }
+ }
+ return res;
+ }
+
+ /**
+ *
+ * @param imageLoader
+ * @return
+ */
+ public ImageLoader setImageLoader(ImageLoader imageLoader) {
+ return (ImageLoader) setProperty(ImageLoader.class, imageLoader);
+ }
+
+ /**
+ *
+ * @param imageCapturer
+ * @return
+ */
+ public ImageCapturer setImageCapturer(ImageCapturer imageCapturer) {
+ getOutput(OUTPUT).println("ImageCapturer set to " + imageCapturer);
+ return (ImageCapturer) setProperty(ImageCapturer.class, imageCapturer);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public ControlInterfaceFactory getInputFactory() {
+ ControlInterfaceFactory res = (ControlInterfaceFactory) getProperty(ControlInterfaceFactory.class);
+ if (res == null) {
+ String factoryClass = (String) getProperty(Wrap.INPUT_FACTORY_PROPERTY);
+ if (factoryClass != null) {
+ try {
+ res = ControlInterfaceFactory.class.cast(Class.forName(String.class.cast(factoryClass)).newInstance());
+ setInputFactory(res);
+ } catch (InstantiationException ex) {
+ throw new JemmyException("Unable to instantiate input factory", ex, factoryClass);
+ } catch (IllegalAccessException ex) {
+ throw new JemmyException("Unable to instantiate input factory", ex, factoryClass);
+ } catch (ClassNotFoundException ex) {
+ throw new JemmyException("Unable to load input factory", ex, factoryClass);
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
+ *
+ * @param factory
+ * @return
+ */
+ public ControlInterfaceFactory setInputFactory(ControlInterfaceFactory factory) {
+ getOutput(OUTPUT).println("Input factory set to " + factory);
+ return (ControlInterfaceFactory) setProperty(ControlInterfaceFactory.class, factory);
+ }
+
+ private static class PropertyKey {
+
+ private Class cls;
+ private Object ref;
+
+ public PropertyKey(Class cls, Object ref) {
+ this.cls = cls;
+ this.ref = ref;
+ }
+
+ private PropertyKey(Class cls) {
+ this(cls, null);
+ }
+
+ public Class getCls() {
+ return cls;
+ }
+
+ public Object getRef() {
+ return ref;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final PropertyKey other = (PropertyKey) obj;
+ if (this.cls != other.cls && (this.cls == null || !this.cls.equals(other.cls))) {
+ return false;
+ }
+ if (this.ref != other.ref && (this.ref == null || !this.ref.equals(other.ref))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 41 * hash + (this.cls != null ? this.cls.hashCode() : 0);
+ hash = 41 * hash + (this.ref != null ? this.ref.hashCode() : 0);
+ return hash;
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:35.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/env/TestOut.java 2017-11-08 15:39:35.000000000 -0800
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.env;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ *
+ * Test output.
+ *
+ * @author Alexandre Iline (alexandre.iline@sun.com)
+ */
+public class TestOut {
+
+ private InputStream input;
+ private PrintWriter output;
+ private PrintWriter errput;
+ private BufferedReader buffInput;
+ private boolean autoFlushMode = true;
+
+ /**
+ * Constructor.
+ * @param in Input stream
+ * @param out Output stream
+ * @param err Errput stream
+ */
+ public TestOut(InputStream in, PrintStream out, PrintStream err) {
+ this(in, out, err, null);
+ }
+
+ /**
+ * Constructor.
+ * @param in Input stream
+ * @param out Output stream
+ * @param err Errput stream
+ * @param golden Golgen output stream
+ */
+ public TestOut(InputStream in, PrintStream out, PrintStream err, PrintStream golden) {
+ super();
+ PrintWriter tout = null;
+ if (out != null) {
+ tout = new PrintWriter(out);
+ }
+ PrintWriter terr = null;
+ if (err != null) {
+ terr = new PrintWriter(err);
+ }
+ initStreams(in, tout, terr);
+ }
+
+ /**
+ * Constructor.
+ * @param in Input stream
+ * @param out Output stream
+ * @param err Errput stream
+ */
+ public TestOut(InputStream in, PrintWriter out, PrintWriter err) {
+ super();
+ initStreams(in, out, err);
+ autoFlushMode = true;
+ }
+
+ /**
+ * Creates unstance using System.in, System.out and System.err streams.
+ */
+ public TestOut() {
+ this(System.in,
+ new PrintWriter(System.out),
+ new PrintWriter(System.err));
+ }
+
+ /**
+ * Creates output which does not print any message anywhere.
+ * @return a TestOut object which does not print any message anywhere.
+ */
+ public static TestOut getNullOutput() {
+ return (new TestOut((InputStream) null, (PrintWriter) null, (PrintWriter) null));
+ }
+
+ /**
+ * Specifies either flush is invoked after each output.
+ * @param autoFlushMode If true flush is invoking after each output.
+ * @return Old value of the auto flush mode.
+ * @see #getAutoFlushMode
+ */
+ public boolean setAutoFlushMode(boolean autoFlushMode) {
+ boolean oldValue = getAutoFlushMode();
+ this.autoFlushMode = autoFlushMode;
+ return (oldValue);
+ }
+
+ /**
+ * Says if flush is invoked after each output.
+ * @return Value of the auto flush mode.
+ * @see #setAutoFlushMode
+ */
+ public boolean getAutoFlushMode() {
+ return (autoFlushMode);
+ }
+
+ /**
+ * Read one byte from input.
+ * @return an int from input stream.
+ * @exception IOException
+ */
+ public int read() throws IOException {
+ if (input != null) {
+ return (input.read());
+ } else {
+ return (-1);
+ }
+ }
+
+ /**
+ * Read a line from input.
+ * @return a line from input stream.
+ * @exception IOException
+ */
+ public String readln() throws IOException {
+ if (buffInput != null) {
+ return (buffInput.readLine());
+ } else {
+ return (null);
+ }
+ }
+
+ /**
+ * Prints a line into output.
+ * @param line a string to print into output stream.
+ */
+ public void print(String line) {
+ if (output != null) {
+ output.print(line);
+ }
+ }
+
+ /**
+ * Prints a line and then terminate the line by writing the line separator string.
+ * @param line a string to print into output stream.
+ */
+ public void println(String line) {
+ if (output != null) {
+ output.println(line);
+ if (autoFlushMode) {
+ output.flush();
+ }
+ }
+ }
+
+ /**
+ * Prints a line into error output.
+ * @param line a string to print into error output stream.
+ */
+ public void printerrln(String line) {
+ if (errput != null) {
+ errput.println(line);
+ if (autoFlushMode) {
+ errput.flush();
+ }
+ }
+ }
+
+ /**
+ * Prints a line into either output or errput.
+ * @param toOut If true prints a line into output.
+ * @param line a string to print.
+ */
+ public void println(boolean toOut, String line) {
+ if (toOut) {
+ println(line);
+ } else {
+ printerrln(line);
+ }
+ }
+
+ /**
+ * Prints a error line.
+ * @param text a error text.
+ */
+ public void printerr(String text) {
+ printerrln("Error:");
+ printerrln(text);
+ }
+
+ /**
+ * Prints an exception stack trace into error stream.
+ * @param e exception
+ */
+ public void printStackTrace(Throwable e) {
+ if (errput != null) {
+ e.printStackTrace(errput);
+ if (autoFlushMode) {
+ errput.flush();
+ }
+ }
+ }
+
+ /**
+ * Returns input stream.
+ * @return an input stream
+ */
+ public InputStream getInput() {
+ return (input);
+ }
+
+ /**
+ * Returns output writer.
+ * @return an output stream
+ */
+ public PrintWriter getOutput() {
+ return (output);
+ }
+
+ /**
+ * Returns errput writer.
+ * @return a error stream
+ */
+ public PrintWriter getErrput() {
+ return (errput);
+ }
+
+ /**
+ * Creates an output which prints only error messages.
+ * @return a TestOut instance which has only error stream.
+ */
+ public TestOut createErrorOutput() {
+ return (new TestOut(null, null, getErrput()));
+ }
+
+ /**
+ * Flushes all output threads.
+ */
+ public void flush() {
+ if (output != null) {
+ output.flush();
+ }
+ if (errput != null) {
+ errput.flush();
+ }
+ }
+
+ private void initStreams(InputStream in, PrintWriter out, PrintWriter err) {
+ input = in;
+ output = out;
+ errput = err;
+ if (input != null) {
+ buffInput = new BufferedReader(new InputStreamReader(in));
+ } else {
+ buffInput = null;
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:35.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/env/Timeout.java 2017-11-08 15:39:35.000000000 -0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.env;
+
+import org.jemmy.TimeoutExpiredException;
+import org.jemmy.JemmyException;
+
+/**
+ * Represents one timeout.
+ * @author Alexandre Iline (alexandre.iline@sun.com)
+ */
+public class Timeout extends Object implements Cloneable {
+
+ private String name;
+ private long value;
+ private long startTime;
+
+ /**
+ * Constructor.
+ * @param name Timeout name.
+ * @param value Timeout value in milliseconds.
+ */
+ public Timeout(String name, long value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Returns timeout name.
+ * @return timeout name.
+ */
+ public String getName() {
+ return (name);
+ }
+
+ /**
+ * Returns timeout value.
+ * @return timeout value.
+ */
+ public long getValue() {
+ return (value);
+ }
+
+ public void setValue(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Sleeps for timeout value.
+ */
+ public void sleep() {
+ if (getValue() > 0) {
+ try {
+ Thread.sleep(getValue());
+ } catch (InterruptedException e) {
+ throw (new JemmyException("Sleep " +
+ getName() +
+ " was interrupted!",
+ e));
+ }
+ }
+ }
+
+ /**
+ * Starts timeout measuring.
+ */
+ public void start() {
+ startTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Checks if timeout has been expired after start() invocation.
+ * @return true if timeout has been expired.
+ */
+ public boolean expired() {
+ return (System.currentTimeMillis() - startTime > getValue());
+ }
+
+ /**
+ * Throws a TimeoutExpiredException exception if timeout has been expired.
+ * @throws TimeoutExpiredException if timeout has been expired after start() invocation.
+ */
+ public void check() {
+ if (expired()) {
+ throw (new TimeoutExpiredException(getName() +
+ " timeout expired!"));
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ @Override
+ public String toString() {
+ return "Timeout [" + name + ", " + value + "]";
+ }
+
+ @Override
+ public Timeout clone() {
+ return new Timeout(name, value);
+ }
+}
--- /dev/null 2017-11-08 15:39:35.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/Image.java 2017-11-08 15:39:35.000000000 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.image;
+
+/**
+ *
+ * @author shura
+ */
+public interface Image {
+ /**
+ * Compares the image with the other one.
+ *
+ * @param img
+ * @return difference of the images, null if identical
+ */
+ public Image compareTo(Image img);
+ /**
+ * Saves the image.
+ * @see ImageLoader#load(String)
+ * @param ID could be anything - depends on the implementation.
+ */
+ public void save(String ID);
+}
--- /dev/null 2017-11-08 15:39:36.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/ImageCapturer.java 2017-11-08 15:39:36.000000000 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.image;
+
+import org.jemmy.Rectangle;
+import org.jemmy.control.Wrap;
+
+/**
+ *
+ * @author mrkam
+ */
+public interface ImageCapturer {
+
+ /**
+ * Obtains a screen image for the control.
+ * @param control
+ * @param rect a control area to be captured
+ * @return
+ */
+ Image capture(Wrap> control, Rectangle rect);
+
+}
--- /dev/null 2017-11-08 15:39:36.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/ImageComparator.java 2017-11-08 15:39:36.000000000 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.image;
+
+/**
+ * Interface for all classes performing image comparison.
+ *
+ * @author Alexandre Iline (alexandre.iline@sun.com)
+ */
+public interface ImageComparator {
+
+ /**
+ * Checks if images are the same according to whatever comparison logic is used.
+ * @param image1 an image to compare.
+ * @param image2 an image to compare.
+ * @return null if images match each other; difference otherwise
+ */
+ public Image compare(Image image1, Image image2);
+
+ /**
+ * A string qualifying an image comparison algorithm. To be used in logs and
+ * tools.
+ * @return
+ */
+ public String getID();
+}
--- /dev/null 2017-11-08 15:39:36.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/ImageLoader.java 2017-11-08 15:39:36.000000000 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.image;
+
+/**
+ *
+ * @author mrkam
+ */
+public interface ImageLoader {
+
+ /**
+ * Loads image by ID. Depending on an implementation, ID could be file name,
+ * class name, image name, etc.
+ * @see Image#save(java.lang.String)
+ * @param ID
+ * @return
+ */
+ Image load(String ID);
+
+}
--- /dev/null 2017-11-08 15:39:37.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/ImageStore.java 2017-11-08 15:39:37.000000000 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image;
+
+/**
+ *
+ * @author shura
+ */
+public interface ImageStore {
+ public void save(Image image, String id) throws Exception;
+}
--- /dev/null 2017-11-08 15:39:37.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/AverageDistanceComparator.java 2017-11-08 15:39:37.000000000 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import org.jemmy.Dimension;
+
+/**
+ *
+ * @author shura
+ */
+public class AverageDistanceComparator extends ThresholdComparator {
+
+ /**
+ *
+ * @param threshold
+ */
+ public AverageDistanceComparator(double threshold) {
+ super(0, Math.sqrt(3));
+ setThreshold(threshold);
+ }
+
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public boolean compare(Raster image1, Raster image2) {
+ Dimension size = PixelImageComparator.computeDiffSize(image1, image2);
+ if (size == null) {
+ return false;
+ }
+ int totalPixels = size.width * size.height;
+ double distance = 0;
+ double[] colors1 = new double[image1.getSupported().length];
+ double[] colors2 = new double[image2.getSupported().length];
+ for (int x = 0; x < size.width; x++) {
+ for (int y = 0; y < size.height; y++) {
+ image1.getColors(x, y, colors1);
+ image2.getColors(x, y, colors2);
+ distance += distance(image1.getSupported(), colors1, image2.getSupported(), colors2) / totalPixels;
+ }
+ }
+ return distance < getThreshold();
+ }
+
+ public static final Raster.Component[] DISTANCE_COMPONENTS = {
+ Raster.Component.RED, Raster.Component.BLUE, Raster.Component.GREEN
+ };
+ static double distance(Raster.Component[] comps1, double[] colors1, Raster.Component[] comps2, double[] colors2) {
+ double res = 0;
+ double diff;
+ for (Raster.Component c : DISTANCE_COMPONENTS) {
+ diff = colors2[PixelImageComparator.arrayIndexOf(comps2, c)] -
+ colors1[PixelImageComparator.arrayIndexOf(comps1, c)];
+ res += diff * diff;
+ }
+ return Math.sqrt(res);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getID() {
+ return AverageDistanceComparator.class.getName() + ":" + getThreshold();
+ }
+}
--- /dev/null 2017-11-08 15:39:37.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/BaseCountingRasterComparator.java 2017-11-08 15:39:37.000000000 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.image.pixel;
+
+import org.jemmy.Dimension;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class BaseCountingRasterComparator extends ThresholdComparator {
+
+ /**
+ *
+ * @param threshold
+ */
+ public BaseCountingRasterComparator(double threshold) {
+ super(0, 1);
+ setThreshold(threshold);
+ }
+
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public boolean compare(Raster image1, Raster image2) {
+ Dimension size = PixelImageComparator.computeDiffSize(image1, image2);
+ if(size == null) {
+ return false;
+ }
+ int totalPixels = size.width * size.height;
+ int offPixels = 0;
+ double[] colors1 = new double[image1.getSupported().length];
+ double[] colors2 = new double[image2.getSupported().length];
+ for (int x = 0; x < size.width; x++) {
+ for (int y = 0; y < size.height; y++) {
+ image1.getColors(x, y, colors1);
+ image2.getColors(x, y, colors2);
+ if (!compare(image1.getSupported(), colors1,
+ image2.getSupported(), colors2)) {
+ offPixels++;
+ }
+ }
+ }
+ return (offPixels <= totalPixels * getThreshold());
+ }
+
+ /**
+ *
+ * @param comps1
+ * @param colors1
+ * @param comps2
+ * @param colors2
+ * @return
+ */
+ protected abstract boolean compare(Raster.Component[] comps1, double[] colors1, Raster.Component[] comps2, double[] colors2);
+
+}
--- /dev/null 2017-11-08 15:39:38.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/ColorMappingComparator.java 2017-11-08 15:39:38.000000000 -0800
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import java.util.List;
+import org.jemmy.Dimension;
+import org.jemmy.image.pixel.Raster.Component;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class ColorMappingComparator implements RasterComparator {
+
+ final private ColorMap left;
+ final private ColorMap right;
+ private RasterComparator subComparator;
+
+ /**
+ *
+ * @param left
+ * @param right
+ * @param subComparator
+ */
+ public ColorMappingComparator(ColorMap left, ColorMap right,
+ RasterComparator subComparator) {
+ this.subComparator = subComparator;
+ this.left = left;
+ this.right = right;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public RasterComparator getSubComparator() {
+ return subComparator;
+ }
+
+ /**
+ *
+ * @param subComparator
+ */
+ public void setSubComparator(RasterComparator subComparator) {
+ this.subComparator = subComparator;
+ }
+
+ /**
+ *
+ * @param both
+ * @param subComparator
+ */
+ public ColorMappingComparator(ColorMap both, RasterComparator subComparator) {
+ this(both, both, subComparator);
+ }
+
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public boolean compare(Raster image1, Raster image2) {
+ return subComparator.compare(map(image1, left), map(image2, right));
+ }
+
+ /**
+ *
+ * @param image
+ * @param map
+ * @return
+ */
+ public WriteableRaster map(Raster image, ColorMap map) {
+ WriteableRaster res = createView(image.getSize());
+ double[] colors = new double[image.getSupported().length];
+ double[] newColors = new double[image.getSupported().length];
+ for (int x = 0; x < image.getSize().width; x++) {
+ for (int y = 0; y < image.getSize().height; y++) {
+ image.getColors(x, y, colors);
+ map.map(image.getSupported(), colors, newColors);
+ res.setColors(x, y, newColors);
+ }
+ }
+ return res;
+ }
+
+ /**
+ *
+ * @param size
+ * @return
+ */
+ protected abstract WriteableRaster createView(Dimension size);
+
+ /**
+ *
+ * @return
+ */
+ public String getID() {
+ return ColorMappingComparator.class.getName() + ":" +
+ left.getID() + "," + right.getID() + "(" +
+ subComparator.getID() + ")";
+ }
+
+ /**
+ *
+ */
+ public interface ColorMap {
+
+ /**
+ *
+ * @param components
+ * @param values
+ * @param newValues
+ */
+ public void map(Component[] components, double[] values, double[] newValues);
+ /**
+ *
+ * @return
+ */
+ public String getID();
+ }
+}
--- /dev/null 2017-11-08 15:39:38.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/MaxDistanceComparator.java 2017-11-08 15:39:38.000000000 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import org.jemmy.Dimension;
+
+/**
+ *
+ * @author shura
+ */
+public class MaxDistanceComparator extends ThresholdComparator{
+
+ /**
+ *
+ * @param threshold
+ */
+ public MaxDistanceComparator(double threshold) {
+ super(0, Math.sqrt(3));
+ setThreshold(threshold);
+ }
+
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public boolean compare(Raster image1, Raster image2) {
+ Dimension size = PixelImageComparator.computeDiffSize(image1, image2);
+ if (size == null) {
+ return false;
+ }
+ double[] colors1 = new double[image1.getSupported().length];
+ double[] colors2 = new double[image2.getSupported().length];
+ double distance = 0;
+ for (int x = 0; x < size.width; x++) {
+ for (int y = 0; y < size.height; y++) {
+ image1.getColors(x, y, colors1);
+ image2.getColors(x, y, colors2);
+ distance = Math.max(distance, AverageDistanceComparator.distance(image1.getSupported(), colors1, image2.getSupported(), colors2));
+ }
+ }
+ return distance <= getThreshold();
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getID() {
+ return MaxDistanceComparator.class.getName() + ":" + getThreshold();
+ }
+}
--- /dev/null 2017-11-08 15:39:38.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/PNGFileImageStore.java 2017-11-08 15:39:38.000000000 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import java.io.File;
+import java.io.IOException;
+import org.jemmy.image.Image;
+import org.jemmy.image.ImageStore;
+
+/**
+ *
+ * @author shura
+ */
+public class PNGFileImageStore implements ImageStore {
+
+ private final File root;
+
+ public PNGFileImageStore(File root) {
+ this.root = root;
+ }
+
+ public PNGFileImageStore() {
+ this(null);
+ }
+
+ @Override
+ public void save(Image image, String id) throws IOException {
+ if (!(image instanceof Raster)) {
+ throw new IllegalArgumentException("This implementation only takes rasters");
+ }
+ if (root != null) {
+ id = root.getAbsolutePath() + File.separator + id;
+ }
+ File file = new File(id);
+ File parentDir = file.getParentFile();
+ if (parentDir != null) {
+ parentDir.mkdirs();
+ }
+ new PNGSaver(file).encode((Raster) image);
+ }
+
+ public File getRoot() {
+ return root;
+ }
+}
--- /dev/null 2017-11-08 15:39:39.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/PNGLoader.java 2017-11-08 15:39:39.000000000 -0800
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.image.pixel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+import org.jemmy.JemmyException;
+import org.jemmy.image.pixel.Raster.Component;
+
+/**
+ * Allows to load PNG graphical file.
+ * @author Alexandre Iline
+ */
+public abstract class PNGLoader {
+
+ InputStream in;
+
+ /**
+ * Constructs a PNGDecoder object.
+ * @param in input stream to read PNG image from.
+ */
+ public PNGLoader(InputStream in) {
+ this.in = in;
+ }
+
+ byte read() throws IOException {
+ byte b = (byte)in.read();
+ return(b);
+ }
+
+ int readInt() throws IOException {
+ byte b[] = read(4);
+ return(((b[0]&0xff)<<24) +
+ ((b[1]&0xff)<<16) +
+ ((b[2]&0xff)<<8) +
+ ((b[3]&0xff)));
+ }
+
+ byte[] read(int count) throws IOException {
+ byte[] result = new byte[count];
+ for(int i = 0; i < count; i++) {
+ result[i] = read();
+ }
+ return(result);
+ }
+
+ void checkEquality(byte[] b1, byte[] b2) {
+ if(!Arrays.equals(b1, b2)) {
+ throw(new JemmyException("Format error"));
+ }
+ }
+
+ /**
+ * Decodes image from an input stream passed into constructor.
+ * @return a BufferedImage object
+ * @throws IOException
+ */
+ public Raster decode() throws IOException {
+ return decode(true);
+ }
+
+ protected abstract WriteableRaster createRaster(int width, int height);
+
+ /**
+ * Decodes image from an input stream passed into constructor.
+ * @return a BufferedImage object
+ * @param closeStream requests method to close the stream after the image is read
+ * @throws IOException
+ */
+ public Raster decode(boolean closeStream) throws IOException {
+
+ byte[] id = read(12);
+ checkEquality(id, new byte[] {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13});
+
+ byte[] ihdr = read(4);
+ checkEquality(ihdr, "IHDR".getBytes());
+
+ int width = readInt();
+ int height = readInt();
+
+ WriteableRaster result = createRaster(width, height);
+
+ byte[] head = read(5);
+ int mode;
+ if(Arrays.equals(head, new byte[]{1, 0, 0, 0, 0})) {
+ mode = PNGSaver.BW_MODE;
+ } else if(Arrays.equals(head, new byte[]{8, 0, 0, 0, 0})) {
+ mode = PNGSaver.GREYSCALE_MODE;
+ } else if(Arrays.equals(head, new byte[]{8, 2, 0, 0, 0})) {
+ mode = PNGSaver.COLOR_MODE;
+ } else {
+ throw(new JemmyException("Format error"));
+ }
+
+ readInt();//!!crc
+
+ int size = readInt();
+
+ byte[] idat = read(4);
+ checkEquality(idat, "IDAT".getBytes());
+
+ byte[] data = read(size);
+
+
+ Inflater inflater = new Inflater();
+ inflater.setInput(data, 0, size);
+
+ int[] colors = new int[3];
+ int[] black = new int[] {0, 0, 0};
+ int[] white = new int[] {1, 1, 1};
+
+ try {
+ switch (mode) {
+ case PNGSaver.BW_MODE:
+ {
+ int bytes = (int)(width / 8);
+ if((width % 8) != 0) {
+ bytes++;
+ }
+ byte colorset;
+ byte[] row = new byte[bytes];
+ for (int y = 0; y < height; y++) {
+ inflater.inflate(new byte[1]);
+ inflater.inflate(row);
+ for (int x = 0; x < bytes; x++) {
+ colorset = row[x];
+ for (int sh = 0; sh < 8; sh++) {
+ if(x * 8 + sh >= width) {
+ break;
+ }
+ if((colorset & 0x80) == 0x80) {
+ setColors(result, x * 8 + sh, y, white);
+ } else {
+ setColors(result, x * 8 + sh, y, black);
+ }
+ colorset <<= 1;
+ }
+ }
+ }
+ }
+ break;
+ case PNGSaver.GREYSCALE_MODE:
+ {
+ byte[] row = new byte[width];
+ for (int y = 0; y < height; y++) {
+ inflater.inflate(new byte[1]);
+ inflater.inflate(row);
+ for (int x = 0; x < width; x++) {
+ colors[0] = row[x];
+ colors[1] = colors[0];
+ colors[2] = colors[0];
+ setColors(result, x, y, colors);
+ }
+ }
+ }
+ break;
+ case PNGSaver.COLOR_MODE:
+ {
+ byte[] row = new byte[width * 3];
+ for (int y = 0; y < height; y++) {
+ inflater.inflate(new byte[1]);
+ inflater.inflate(row);
+ for (int x = 0; x < width; x++) {
+ colors[0] = (row[x * 3 + 0]&0xff);
+ colors[1] = (row[x * 3 + 1]&0xff);
+ colors[2] = (row[x * 3 + 2]&0xff);
+ setColors(result, x, y, colors);
+ }
+ }
+ }
+ }
+ } catch(DataFormatException e) {
+ throw(new JemmyException("ZIP error", e));
+ }
+
+ readInt();//!!crc
+ readInt();//0
+
+ byte[] iend = read(4);
+ checkEquality(iend, "IEND".getBytes());
+
+ readInt();//!!crc
+ if (closeStream) {
+ in.close();
+ }
+
+ return(result);
+ }
+
+ private void setColors(WriteableRaster raster, int x, int y, int[] colors) {
+ Component[] supported = raster.getSupported();
+ double[] imageColors = new double[supported.length];
+ for (int i = 0; i < supported.length; i++) {
+ if(supported[i] == Component.ALPHA) {
+ imageColors[i] = 1;
+ } else {
+ imageColors[i] = (double)colors[
+ PixelImageComparator.arrayIndexOf(PNGSaver.RGB, supported[i])]/0xFF;
+ }
+ }
+ raster.setColors(x, y, imageColors);
+ }
+
+}
--- /dev/null 2017-11-08 15:39:39.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/PNGSaver.java 2017-11-08 15:39:39.000000000 -0800
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import java.io.*;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import org.jemmy.image.pixel.Raster.Component;
+
+/**
+ *
+ * @author shura
+ */
+public class PNGSaver {
+
+ /**
+ * black and white image mode.
+ */
+ public static final byte BW_MODE = 0;
+ /**
+ * grey scale image mode.
+ */
+ public static final byte GREYSCALE_MODE = 1;
+ /**
+ * full color image mode.
+ */
+ public static final byte COLOR_MODE = 2;
+ OutputStream out;
+ CRC32 crc;
+ byte mode;
+
+ /**
+ *
+ * @param file
+ * @throws java.io.FileNotFoundException
+ */
+ public PNGSaver(File file) throws FileNotFoundException {
+ this(new FileOutputStream(file));
+ }
+
+ /**
+ * public constructor of PNGEncoder class with greyscale mode by default.
+ *
+ * @param out output stream for PNG image format to write into
+ */
+ public PNGSaver(OutputStream out) {
+ this(out, COLOR_MODE);
+ }
+
+ /**
+ * public constructor of PNGEncoder class.
+ *
+ * @param out output stream for PNG image format to write into
+ * @param mode BW_MODE, GREYSCALE_MODE or COLOR_MODE
+ */
+ public PNGSaver(OutputStream out, byte mode) {
+ crc = new CRC32();
+ this.out = out;
+ if (mode < 0 || mode > 2) {
+ throw new IllegalArgumentException("Unknown color mode");
+ }
+ this.mode = mode;
+ }
+
+ void write(int i) throws IOException {
+ byte b[] = {(byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff), (byte) (i & 0xff)};
+ write(b);
+ }
+
+ void write(byte b[]) throws IOException {
+ out.write(b);
+ crc.update(b);
+ }
+
+ /**
+ * main encoding method (stays blocked till encoding is finished).
+ *
+ * @param image BufferedImage to encode
+ * @throws IOException IOException
+ */
+ public void encode(Raster image) throws IOException {
+ encode(image, true);
+ }
+
+ /**
+ * main encoding method (stays blocked till encoding is finished).
+ *
+ * @param image BufferedImage to encode
+ * @param closeStream requests method to close the stream after the image is
+ * written
+ * @throws IOException IOException
+ */
+ private void encode(Raster image, boolean closeStream) throws IOException {
+ int width = image.getSize().width;
+ int height = image.getSize().height;
+ final byte id[] = {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13};
+ write(id);
+ crc.reset();
+ write("IHDR".getBytes());
+ write(width);
+ write(height);
+ byte head[] = null;
+ switch (mode) {
+ case BW_MODE:
+ head = new byte[]{1, 0, 0, 0, 0};
+ break;
+ case GREYSCALE_MODE:
+ head = new byte[]{8, 0, 0, 0, 0};
+ break;
+ case COLOR_MODE:
+ head = new byte[]{8, 2, 0, 0, 0};
+ break;
+ }
+ write(head);
+ write((int) crc.getValue());
+ ByteArrayOutputStream compressed = new ByteArrayOutputStream(65536);
+ BufferedOutputStream bos = new BufferedOutputStream(new DeflaterOutputStream(compressed, new Deflater(9)));
+ int pixel;
+ int color;
+ int colorset;
+ switch (mode) {
+ case BW_MODE:
+ int rest = width % 8;
+ int bytes = width / 8;
+ for (int y = 0; y < height; y++) {
+ bos.write(0);
+ for (int x = 0; x < bytes; x++) {
+ colorset = 0;
+ for (int sh = 0; sh < 8; sh++) {
+ pixel = getRGB(image, x * 8 + sh, y);
+ color = ((pixel >> 16) & 0xff);
+ color += ((pixel >> 8) & 0xff);
+ color += (pixel & 0xff);
+ colorset <<= 1;
+ if (color >= 3 * 128) {
+ colorset |= 1;
+ }
+ }
+ bos.write((byte) colorset);
+ }
+ if (rest > 0) {
+ colorset = 0;
+ for (int sh = 0; sh < width % 8; sh++) {
+ pixel = getRGB(image, bytes * 8 + sh, y);
+ color = ((pixel >> 16) & 0xff);
+ color += ((pixel >> 8) & 0xff);
+ color += (pixel & 0xff);
+ colorset <<= 1;
+ if (color >= 3 * 128) {
+ colorset |= 1;
+ }
+ }
+ colorset <<= 8 - rest;
+ bos.write((byte) colorset);
+ }
+ }
+ break;
+ case GREYSCALE_MODE:
+ for (int y = 0; y < height; y++) {
+ bos.write(0);
+ for (int x = 0; x < width; x++) {
+ pixel = getRGB(image, x, y);
+ color = ((pixel >> 16) & 0xff);
+ color += ((pixel >> 8) & 0xff);
+ color += (pixel & 0xff);
+ bos.write((byte) (color / 3));
+ }
+ }
+ break;
+ case COLOR_MODE:
+ for (int y = 0; y < height; y++) {
+ bos.write(0);
+ for (int x = 0; x < width; x++) {
+ pixel = getRGB(image, x, y);
+ bos.write((byte) ((pixel >> 16) & 0xff));
+ bos.write((byte) ((pixel >> 8) & 0xff));
+ bos.write((byte) (pixel & 0xff));
+ }
+ }
+ break;
+ }
+ bos.close();
+ write(compressed.size());
+ crc.reset();
+ write("IDAT".getBytes());
+ write(compressed.toByteArray());
+ write((int) crc.getValue());
+ write(0);
+ crc.reset();
+ write("IEND".getBytes());
+ write((int) crc.getValue());
+ out.flush();
+ if (closeStream) {
+ out.close();
+ }
+ }
+ static final Component[] RGB = new Component[]{
+ Component.RED, Component.GREEN, Component.BLUE};
+
+ private int getRGB(Raster image, int x, int y) {
+ int res = 0;
+ double[] colors = new double[image.getSupported().length];
+ image.getColors(x, y, colors);
+ for (Component c : RGB) {
+ res <<= 8;
+ res |= (int)(colors[PixelImageComparator.arrayIndexOf(image.getSupported(), c)] * 0xFF);
+ }
+ return res;
+ }
+}
--- /dev/null 2017-11-08 15:39:39.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/PeakSignalNoiseRatioComparator.java 2017-11-08 15:39:39.000000000 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+/**
+ * Comparator, that implements peak signal to noise ratio, popular and reliable method of measuring
+ * image compression quality or image distortion.
+ * PSNR is used to measure the quality of reconstruction of lossy compression codecs. The signal is
+ * the reference (golden) image, and the noise is actual image. Higher PSNR indicates lesser
+ * difference between images for the most cases.
+ * Comparator is intended to compare images with large amount of very minor differences and one
+ * has to be extremely careful with the range of validity of this metric; it is only conclusively
+ * valid when it is used to compare results from the same content.
+ *
+ * @author andrey.rusakov@oracle.com
+ */
+public class PeakSignalNoiseRatioComparator implements RasterComparator {
+
+ public static final String OUTPUT = PeakSignalNoiseRatioComparator.class.getName() + ".OUTPUT";
+
+ private static final double MAX_CHANNEL = 1.0;
+ private final double minRatio;
+
+ private static double getMeanSquareError(Raster image, Raster original) {
+ double result = 0;
+ double[] colors1 = new double[image.getSupported().length];
+ double[] colors2 = new double[original.getSupported().length];
+
+ int w = Math.min(image.getSize().width, original.getSize().width);
+ int h = Math.min(image.getSize().height, original.getSize().height);
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ image.getColors(i, j, colors1);
+ original.getColors(i, j, colors2);
+ double distance = AverageDistanceComparator.distance(image.getSupported(), colors1,
+ original.getSupported(), colors2);
+ result += distance * distance / (AverageDistanceComparator.DISTANCE_COMPONENTS.length * w * h);
+ }
+ }
+ return result;
+ }
+
+ private static double getPeakSignalNoiseRatio(Raster image, Raster original) {
+ double mse = getMeanSquareError(image, original);
+ return 20 * Math.log10(MAX_CHANNEL) - 10 * Math.log10(mse);
+ }
+
+ public PeakSignalNoiseRatioComparator(double minRatio) {
+ this.minRatio = minRatio;
+ }
+
+ @Override
+ public boolean compare(Raster image1, Raster image2) {
+ return getPeakSignalNoiseRatio(image1, image2) > minRatio;
+ }
+
+ @Override
+ public String getID() {
+ return getClass().getName() + ":" + minRatio;
+ }
+
+}
--- /dev/null 2017-11-08 15:39:40.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/PixelEqualityRasterComparator.java 2017-11-08 15:39:40.000000000 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import org.jemmy.Dimension;
+import org.jemmy.image.Image;
+import org.jemmy.image.pixel.Raster.Component;
+
+/**
+ *
+ * @author shura
+ */
+public class PixelEqualityRasterComparator extends BaseCountingRasterComparator {
+
+ /**
+ *
+ * @param treshold
+ */
+ public PixelEqualityRasterComparator(double treshold) {
+ super(treshold);
+ }
+
+ /**
+ *
+ * @param comps1
+ * @param colors1
+ * @param comps2
+ * @param colors2
+ * @return
+ */
+ @Override
+ protected boolean compare(Raster.Component[] comps1, double[] colors1,
+ Raster.Component[] comps2, double[] colors2) {
+ if (colors1.length == colors2.length) {
+ for (int i = 0; i < colors1.length; i++) {
+ if (colors1[i] != colors2[PixelImageComparator.arrayIndexOf(comps2, comps1[i])]) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getID() {
+ return PixelEqualityRasterComparator.class.getName() + ":" + getThreshold();
+ }
+}
--- /dev/null 2017-11-08 15:39:40.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/PixelImageComparator.java 2017-11-08 15:39:40.000000000 -0800
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import java.util.Arrays;
+import org.jemmy.Dimension;
+import org.jemmy.env.Environment;
+import org.jemmy.image.Image;
+import org.jemmy.image.ImageComparator;
+import org.jemmy.image.pixel.Raster.Component;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class PixelImageComparator implements ImageComparator {
+
+ static {
+ Environment.getEnvironment().setPropertyIfNotSet(RasterComparator.class,
+ new PixelEqualityRasterComparator(0));
+// new MaxDistanceComparator((double)1/0x8f));
+ }
+
+ private RasterComparator comparator = null;
+ private Environment env = null;
+
+ /**
+ *
+ * @param comparator
+ */
+ public PixelImageComparator(RasterComparator comparator) {
+ this.comparator = comparator;
+ }
+
+ public PixelImageComparator(Environment env) {
+ this.env = env;
+ }
+
+ public synchronized RasterComparator getRasterComparator() {
+ if(comparator == null) {
+ return env.getProperty(RasterComparator.class);
+ } else {
+ return comparator;
+ }
+ }
+
+ /**
+ *
+ * @param one
+ * @param two
+ * @return
+ */
+ public static Dimension computeDiffSize(Raster one, Raster two) {
+ if (one.getSize().equals(two.getSize())) {
+ return one.getSize();
+ } else {
+ return null;
+ }
+ }
+
+ public Image compare(Image image1, Image image2) {
+ Raster pi1 = toRaster(image1);
+ Raster pi2 = toRaster(image2);
+ if (!getRasterComparator().compare(pi1, pi2)) {
+ return toImage(computeDifference(pi1, pi2));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public WriteableRaster computeDifference(Raster image1, Raster image2) {
+ Dimension size = computeDiffSize(image1, image2);
+ if (size == null) {
+ size = new Dimension(Math.max(image1.getSize().width, image2.getSize().width),
+ Math.max(image1.getSize().height, image2.getSize().height));
+ }
+ WriteableRaster res = createDiffRaster(image1, image2);
+ double[] colors1 = new double[image1.getSupported().length];
+ double[] colors2 = new double[image2.getSupported().length];
+ double[] colorsRes = new double[res.getSupported().length];
+ for (int x = 0; x < size.width; x++) {
+ for (int y = 0; y < size.height; y++) {
+ if (x < image1.getSize().width && y < image1.getSize().height) {
+ image1.getColors(x, y, colors1);
+ } else {
+ Arrays.fill(colors1, 0);
+ }
+ if (x < image2.getSize().width && y < image2.getSize().height) {
+ image2.getColors(x, y, colors2);
+ } else {
+ Arrays.fill(colors2, 1);
+ }
+ calcDiffColor(image1.getSupported(), colors1, image2.getSupported(), colors2,
+ res.getSupported(), colorsRes);
+ res.setColors(x, y, colorsRes);
+ }
+ }
+ return res;
+ }
+
+ private static final Component[] diffComponents = {
+ Component.RED, Component.BLUE, Component.GREEN
+ };
+ /**
+ *
+ * @param comps1
+ * @param colors1
+ * @param comps2
+ * @param colors2
+ * @param compsRes
+ * @param colorsRes
+ */
+ protected void calcDiffColor(Raster.Component[] comps1, double[] colors1,
+ Raster.Component[] comps2, double[] colors2, Raster.Component[] compsRes, double[] colorsRes) {
+ double square1, square2;
+ double dist = 0;
+
+ for (Component c : diffComponents) {
+ square1 = getComponentValue(comps1, colors1, c);
+ square2 = getComponentValue(comps2, colors2, c);
+ dist += (square2 - square1) * (square2 - square1);
+ }
+ for (Component c : diffComponents) {
+ colorsRes[arrayIndexOf(compsRes, c)] = Math.sqrt(dist) / Math.sqrt(3);
+ }
+ colorsRes[arrayIndexOf(compsRes, Component.ALPHA)] = 1;
+ }
+
+ public String getID() {
+ return getRasterComparator().getID();
+ }
+
+ /**
+ *
+ * @param image
+ * @return
+ */
+ protected abstract Image toImage(Raster image);
+
+ /**
+ *
+ * @param image
+ * @return
+ */
+ protected abstract Raster toRaster(Image image);
+
+ /**
+ *
+ * @param r1
+ * @param r2
+ * @return
+ */
+ protected abstract WriteableRaster createDiffRaster(Raster r1, Raster r2);
+
+ /**
+ *
+ * @param comps
+ * @param comp
+ * @return
+ */
+ public static int arrayIndexOf(Raster.Component[] comps, Raster.Component comp) {
+ for (int i = 0; i < comps.length; i++) {
+ if (comp == comps[i]) {
+ return i;
+ }
+ }
+ throw new IllegalArgumentException("Unknown component " + comp);
+ }
+
+ /**
+ * Returns color component value using its alpha information
+ *
+ * @param components available color components
+ * @param colors color components values
+ * @param comp required color component
+ *
+ * @return value of the required color component.
+ * If pixel is not opaque, then it is blended with white
+ * opaque background
+ */
+ protected double getComponentValue(Component[] components, double[] colors, Component comp) {
+
+ double result = colors[arrayIndexOf(components, comp)];
+
+ if(result < 0.0 || result > 1.0) throw new IllegalStateException("Component value = " + result);
+
+ //Find alpha index if exists
+ int idxAlpha = -1;
+ try {
+ idxAlpha = arrayIndexOf(components, Component.ALPHA);
+ } catch (IllegalArgumentException ex) {
+ }
+
+ //If alpha component is available
+ if (idxAlpha != -1) {
+ double alpha = colors[idxAlpha];
+
+ if(alpha < 0.0 || alpha > 1.0) throw new IllegalStateException("Alpha value = " + alpha);
+
+ //If not opaque
+ if (alpha < 1.0) {
+ //Blend with opaque white
+ result = Math.min(1.0, alpha * result + 1 - alpha);
+ }
+ }
+
+ return result;
+ }
+}
--- /dev/null 2017-11-08 15:39:40.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/Raster.java 2017-11-08 15:39:40.000000000 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import org.jemmy.Dimension;
+
+/**
+ *
+ * @author shura
+ */
+public interface Raster {
+
+ /**
+ *
+ */
+ public enum Component {
+
+ /**
+ *
+ */
+ RED,
+ /**
+ *
+ */
+ GREEN,
+ /**
+ *
+ */
+ BLUE,
+ /**
+ *
+ */
+ ALPHA;
+ };
+
+ /**
+ *
+ * @return
+ */
+ public Dimension getSize();
+
+ /**
+ * Supposed to write pixel component value in the RGBA order.
+ * @param x
+ * @param y
+ * @param colors
+ */
+ public void getColors(int x, int y, double[] colors);
+
+ /**
+ * Returns a list of supported components.
+ *
+ * @return
+ */
+ public Component[] getSupported();
+
+}
--- /dev/null 2017-11-08 15:39:41.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/RasterComparator.java 2017-11-08 15:39:41.000000000 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import java.util.List;
+
+/**
+ *
+ * @author shura
+ */
+public interface RasterComparator {
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public boolean compare(Raster image1, Raster image2);
+ /**
+ *
+ * @return
+ */
+ public String getID();
+}
--- /dev/null 2017-11-08 15:39:41.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/ResizeComparator.java 2017-11-08 15:39:41.000000000 -0800
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+import org.jemmy.Dimension;
+import org.jemmy.image.Image;
+import org.jemmy.image.ImageComparator;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class ResizeComparator implements ImageComparator {
+
+ private ImageComparator subComparator;
+ private Mode mode;
+
+ /**
+ *
+ */
+ public enum Mode {
+
+ /**
+ *
+ */
+ LEFT,
+ /**
+ *
+ */
+ RIGTH,
+ /**
+ *
+ */
+ MAX
+ };
+
+ /**
+ *
+ * @param subComparator
+ * @param mode
+ */
+ public ResizeComparator(ImageComparator subComparator, Mode mode) {
+ this.subComparator = subComparator;
+ this.mode = mode;
+ }
+
+ /**
+ *
+ * @param subComparator
+ */
+ public ResizeComparator(ImageComparator subComparator) {
+ this(subComparator, Mode.MAX);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public ImageComparator getSubComparator() {
+ return subComparator;
+ }
+
+ /**
+ *
+ * @param subComparator
+ */
+ public void setSubComparator(ImageComparator subComparator) {
+ this.subComparator = subComparator;
+ }
+
+ /**
+ *
+ * @param image1
+ * @param image2
+ * @return
+ */
+ public Image compare(Image image1, Image image2) {
+ if(image1 == null || image2 == null) {
+ return (image1 == null) ? image2 : image1;
+ }
+ Dimension size;
+ switch (mode) {
+ case LEFT:
+ size = getSize(image1);
+ break;
+ case RIGTH:
+ size = getSize(image2);
+ break;
+ case MAX:
+ Dimension size1 = getSize(image1);
+ Dimension size2 = getSize(image2);
+ size = new Dimension(Math.max(size1.width, size2.width),
+ Math.max(size1.height, size2.height));
+ break;
+ default:
+ throw new IllegalStateException("mode is not recognized");
+ }
+ Image r1 = resize(image1, size);
+ Image r2 = resize(image2, size);
+ if(r1 == null) {
+ return image1;
+ }
+ if(r2 == null) {
+ return image2;
+ }
+ return subComparator.compare(r1, r2);
+ }
+
+ /**
+ *
+ * @param image
+ * @param size
+ * @return
+ */
+ abstract public Image resize(Image image, Dimension size);
+
+ /**
+ *
+ * @param image
+ * @return
+ */
+ abstract public Dimension getSize(Image image);
+
+ /**
+ *
+ * @return
+ */
+ public String getID() {
+ return ResizeComparator.class.getName() + "(" + subComparator.getID() + ")";
+ }
+}
--- /dev/null 2017-11-08 15:39:41.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/ThresholdComparator.java 2017-11-08 15:39:41.000000000 -0800
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+/**
+ *
+ * @author shura
+ */
+abstract class ThresholdComparator implements RasterComparator {
+
+ private double min;
+ private double threshold;
+ private double max;
+
+ public ThresholdComparator(double min, double max) {
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ *
+ * @param threshold
+ */
+ public final void setThreshold(double threshold) {
+ if (threshold < min || threshold > max) {
+ throw new IllegalArgumentException("Treshold expected to be withing ("
+ + min + ", " + max + "1). Got: " + threshold);
+ }
+ this.threshold = threshold;
+ }
+
+ public double getThreshold() {
+ return threshold;
+ }
+}
--- /dev/null 2017-11-08 15:39:42.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/image/pixel/WriteableRaster.java 2017-11-08 15:39:42.000000000 -0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.image.pixel;
+
+/**
+ *
+ * @author shura
+ */
+public interface WriteableRaster extends Raster {
+ /**
+ *
+ * @param x
+ * @param y
+ * @param values
+ */
+ public void setColors(int x, int y, double[] values);
+}
--- /dev/null 2017-11-08 15:39:42.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/AbstractCaretOwner.java 2017-11-08 15:39:42.000000000 -0800
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+import org.jemmy.interfaces.*;
+import org.jemmy.interfaces.Caret.Direction;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class AbstractCaretOwner implements CaretOwner {
+ private double error;
+
+ public double allowedError() {
+ return error;
+ }
+
+ public void allowError(double error) {
+ if(error < 0) {
+ throw new IllegalArgumentException("Precision could not be less than 0");
+ }
+ this.error = error;
+ }
+
+ public void to(double position) {
+ caret().to(new ToPosition(this, position, error));
+ }
+
+ public static class ToPosition implements Direction {
+
+ private double error;
+ private double value;
+ private CaretOwner caret;
+
+ public ToPosition(CaretOwner caret, double value, double allowedError) {
+ this.caret = caret;
+ this.value = value;
+ this.error = allowedError;
+ }
+
+ public ToPosition(CaretOwner caret, double value) {
+ this(caret, value, 0);
+ }
+
+ public int to() {
+ double diff = diff();
+ return (Math.abs(diff) <= error) ? 0 : ((diff > 0) ? 1 : -1);
+ }
+
+ @Override
+ public String toString() {
+ return "value == " + position() + " with " + error + " error";
+ }
+
+ protected double diff() {
+ return position() - caret.position();
+ }
+
+ public CaretOwner getCaret() {
+ return caret;
+ }
+
+ /**
+ *
+ * @return
+ */
+ protected double position() {
+ return value;
+ }
+ }
+
+}
--- /dev/null 2017-11-08 15:39:42.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/AbstractScroll.java 2017-11-08 15:39:42.000000000 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.interfaces.Scroll;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class AbstractScroll extends AbstractCaretOwner implements Scroll {
+
+}
--- /dev/null 2017-11-08 15:39:43.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/CaretImpl.java 2017-11-08 15:39:43.000000000 -0800
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import java.util.ArrayList;
+import org.jemmy.JemmyException;
+import org.jemmy.Point;
+import org.jemmy.action.Action;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.env.Timeout;
+import org.jemmy.interfaces.Caret;
+import org.jemmy.interfaces.CaretOwner;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardModifier;
+import org.jemmy.interfaces.Mouse.MouseButtons;
+
+/**
+ *
+ * @author shura
+ */
+public class CaretImpl implements Caret {
+
+ /**
+ * Time to sleep between scrolling actions
+ */
+ public static final Timeout SCROLL_TIMEOUT =
+ new Timeout("ScrollerImpl.scroll", 1);
+
+ static {
+ Environment.getEnvironment().initTimeout(SCROLL_TIMEOUT);
+ }
+ private Wrap> wrap;
+ private CaretOwner caretOwner;
+ private ArrayList actions;
+
+ /**
+ *
+ * @param wrap
+ * @param caretOwner only position() is used
+ */
+ public CaretImpl(Wrap> wrap, CaretOwner caretOwner) {
+ this.wrap = wrap;
+ this.caretOwner = caretOwner;
+ actions = new ArrayList();
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Wrap> getWrap() {
+ return wrap;
+ }
+
+ /**
+ *
+ * @param action
+ */
+ protected void addScrollAction(ScrollAction action) {
+ actions.add(0, action);
+ }
+
+ public void to(final double value) {
+ to(new DirectionToPosition(caretOwner, value));
+ }
+
+ public void to(final Caret.Direction direction) {
+ wrap.getEnvironment().getExecutor().execute(wrap.getEnvironment(), false, new Action() {
+
+ @Override
+ public void run(Object... parameters) {
+ if (direction.to() == 0) {
+ return;
+ }
+ if (wrap.is(Focusable.class)) {
+ wrap.as(Focusable.class).focuser().focus();
+ }
+ int orig = direction.to();
+ if (orig == 0) {
+ return;
+ }
+ double prevPos = caretOwner.position();
+ double prevDist = Double.MAX_VALUE;
+ for (int i = 0; i < actions.size(); i++) {
+ while (!isInterrupted() && (direction.to() * orig) >= 0) {
+ actions.get(i).scrollTo(orig);
+ wrap.getEnvironment().getTimeout(SCROLL_TIMEOUT).sleep();
+ //if didn't move - use the smaller adjustment
+ //like, puching up when in the first line
+ if(caretOwner.position() == prevPos) {
+ //if did not move and there are more - move to next
+ if(i < actions.size() - 1) {
+ break;
+ } else {
+ //try more and finally fail by timeout
+ //throw new JemmyException("Unable to scoll.", wrap);
+ }
+ }
+ prevPos = caretOwner.position();
+ if (direction.to() == 0) {
+ return;
+ }
+ }
+ orig = direction.to();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Scrolling to " + direction.toString() + " condition";
+ }
+ });
+ }
+
+ /**
+ * @deprecated Use ApproximateCaretOwner.ToPosition or PreciseCaretOwner.ToPosition
+ */
+ public static class DirectionToPosition implements Direction {
+
+ private double value;
+ private CaretOwner caret;
+ private double precision;
+
+ /**
+ *
+ * @param caret
+ * @param value
+ */
+ public DirectionToPosition(CaretOwner caret, double value, double precision) {
+ this.value = value;
+ this.caret = caret;
+ this.precision = precision;
+ }
+
+ public DirectionToPosition(CaretOwner caret, double value) {
+ this(caret, value, 0);
+ }
+
+ public int to() {
+ double diff = position() - caret.position();
+ return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
+ }
+
+ /**
+ *
+ * @return
+ */
+ @Override
+ public String toString() {
+ return "value == " + position();
+ }
+
+ /**
+ *
+ * @return
+ */
+ protected double position() {
+ return value;
+ }
+ }
+
+ /**
+ *
+ */
+ protected static interface ScrollAction {
+
+ /**
+ *
+ * @param direction
+ */
+ public void scrollTo(int direction);
+ }
+
+ /**
+ *
+ */
+ protected class MouseScrollAction implements ScrollAction {
+
+ Point up, down;
+ KeyboardModifier[] upMods, downMods;
+
+ /**
+ *
+ * @param down
+ * @param downMods
+ * @param up
+ * @param upMods
+ */
+ public MouseScrollAction(Point down, KeyboardModifier[] downMods, Point up, KeyboardModifier[] upMods) {
+ this.up = up;
+ this.down = down;
+ this.upMods = upMods;
+ this.downMods = downMods;
+ }
+
+ /**
+ *
+ * @param down
+ * @param up
+ */
+ public MouseScrollAction(Point down, Point up) {
+ this(up, new KeyboardModifier[0], up, new KeyboardModifier[0]);
+ }
+
+ /**
+ *
+ * @param direction
+ */
+ public void scrollTo(int direction) {
+ wrap.mouse().click(1, (direction > 0) ? up : down, MouseButtons.BUTTON1,
+ (direction > 0) ? upMods : downMods);
+ }
+ }
+
+ /**
+ *
+ */
+ protected class KeyboardScrollAction implements ScrollAction {
+
+ KeyboardButton down, up;
+ KeyboardModifier[] downMods, upMods;
+
+ /**
+ *
+ * @param down
+ * @param downMods
+ * @param up
+ * @param upMods
+ */
+ public KeyboardScrollAction(KeyboardButton down, KeyboardModifier[] downMods, KeyboardButton up, KeyboardModifier[] upMods) {
+ this.down = down;
+ this.up = up;
+ this.downMods = downMods;
+ this.upMods = upMods;
+ }
+
+ /**
+ *
+ * @param down
+ * @param up
+ */
+ public KeyboardScrollAction(KeyboardButton down, KeyboardButton up) {
+ this(down, new KeyboardModifier[0], up, new KeyboardModifier[0]);
+ }
+
+ /**
+ *
+ * @param direction
+ */
+ public void scrollTo(int direction) {
+ wrap.keyboard().pushKey((direction > 0) ? up : down,
+ (direction > 0) ? upMods : downMods);
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:43.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/CaretText.java 2017-11-08 15:39:43.000000000 -0800
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardModifier;
+import org.jemmy.interfaces.Text;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class CaretText extends AbstractCaretOwner implements Text {
+
+ static {
+ Environment.getEnvironment().setPropertyIfNotSet(RegexCaretDirection.REGEX_FLAGS, 0);
+ }
+
+ TextCaret caret;
+ TextImpl text;
+ Wrap> wrap;
+
+ /**
+ *
+ * @param wrap
+ */
+ public CaretText(Wrap> wrap) {
+ this.wrap = wrap;
+ text = new TextImpl(wrap) {
+ public String text() {
+ return CaretText.this.text();
+ }
+ };
+ }
+
+ public TextCaret caret() {
+ if (caret == null) {
+ initCaret();
+ }
+ return caret;
+ }
+
+ protected void initCaret() {
+ caret = new TextCaret(wrap, this);
+ }
+
+ /**
+ *
+ * @return
+ */
+ protected int getFlags() {
+ return (Integer)wrap.getEnvironment().
+ getProperty(RegexCaretDirection.REGEX_FLAGS, 0);
+ }
+
+ public void type(String newText) {
+ text.type(newText);
+ }
+
+ public void clear() {
+ text.clear();
+ }
+
+ /**
+ * Moves caret to a beginning/end of an index
'th occurance of the regex.
+ * @param regex
+ * @param front
+ * @param index
+ */
+ public void to(String regex, boolean front, int index) {
+ caret().to(new RegexCaretDirection(this, this, regex, getFlags(), front, index));
+ }
+
+ /**
+ * Moves caret to a beginning/end of the first occurance of the regex.
+ * @param regex
+ * @param front
+ */
+ public void to(String regex, boolean front) {
+ to(regex, front, 0);
+ }
+
+ /**
+ * Moves caret to a beginning the first occurance of the regex.
+ * @param regex
+ */
+ public void to(String regex) {
+ to(regex, true);
+ }
+
+ /**
+ *
+ * @param left
+ * @param leftMods
+ * @param right
+ * @param rightMods
+ */
+ public void addNavKeys(KeyboardButton left, KeyboardModifier[] leftMods,
+ KeyboardButton right, KeyboardModifier[] rightMods) {
+ caret().addNavKeys(left, leftMods, right, rightMods);
+ }
+
+ /**
+ *
+ * @param left
+ * @param right
+ */
+ public void addNavKeys(KeyboardButton left, KeyboardButton right) {
+ addNavKeys(left, new KeyboardModifier[0], right, new KeyboardModifier[0]);
+ }
+}
--- /dev/null 2017-11-08 15:39:43.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/CharBindingMap.java 2017-11-08 15:39:43.000000000 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+import org.jemmy.interfaces.Button;
+import org.jemmy.interfaces.Modifier;
+
+/**
+ *
+ * Defines char-to-key binding. The generation of a symbol will,
+ * in general, require modifier keys to be pressed prior to pressing
+ * a primary key. Classes that implement CharBindingMap
+ * communicate what modifiers and primary key are required to generate
+ * a given symbol.
+ *
+ * @param
+ * @param
+ * @author Alexandre Iline (alexandre.iline@sun.com)
+ */
+
+public interface CharBindingMap {
+
+ /**
+ * Returns the code of the primary key used to type a symbol.
+ * @param c Character.
+ * @return a Button constant.
+ */
+ public BUTTON getCharKey(char c);
+
+ /**
+ * Returns the modifiers that should be pressed to type a symbol.
+ * @param c Character.
+ * @return an array of Modifier constants.
+ */
+ public MODIFIER[] getCharModifiers(char c);
+}
--- /dev/null 2017-11-08 15:39:44.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/ClickFocus.java 2017-11-08 15:39:44.000000000 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Focus;
+
+/**
+ * Simple Focus implementation which clicks on a control to give focus.
+ * @author shura
+ */
+public class ClickFocus implements Focus {
+
+ Wrap extends CONTROL> topControl;
+ Point clickPoint;
+
+ /**
+ *
+ * @param topControl a control to click on. Node that this could be
+ * a control itself (the one we're giving the focus to) or a subcontrol
+ * of it.
+ */
+ public ClickFocus(Wrap extends CONTROL> topControl, Point clickPoint) {
+ this.topControl = topControl;
+ this.clickPoint = clickPoint;
+ }
+
+ public ClickFocus(Wrap extends CONTROL> topControl) {
+ this(topControl, null);
+ }
+
+ protected Wrap extends CONTROL> getTopControl() {
+ return topControl;
+ }
+
+ /**
+ * @{@inheritDoc}
+ */
+ public void focus() {
+ if (clickPoint == null) {
+ topControl.mouse().click();
+ } else {
+ topControl.mouse().click(1, clickPoint);
+ }
+ }
+}
--- /dev/null 2017-11-08 15:39:44.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/DefaultCharBindingMap.java 2017-11-08 15:39:44.000000000 -0800
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Keyboard.KeyboardModifier;
+import static org.jemmy.interfaces.Keyboard.KeyboardButtons.*;
+import static org.jemmy.interfaces.Keyboard.KeyboardModifiers.*;
+
+
+
+/**
+ *
+ * Default implementation of CharBindingMap interface.
+ * Provides a mapping for the following symbols:
+ * @see org.jemmy.CharBindingMap
+ *
+ * @author Alexandre Iline (alexandre.iline@sun.com)
+ */
+
+public class DefaultCharBindingMap implements CharBindingMap {
+
+ private Hashtable chars;
+
+ /**
+ * Constructor.
+ */
+ public DefaultCharBindingMap() {
+ initMap();
+ }
+
+ /**
+ * Returns the code of the primary key used to type a symbol.
+ * @param c Character.
+ * @return a KeyboardButton.
+ * @see CharBindingMap#getCharKey(char)
+ */
+ public KeyboardButton getCharKey(char c) {
+ CharKey charKey = (CharKey)chars.get(new Character(c));
+ if (charKey != null) {
+ return charKey.key;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the modifiers that should be pressed to type a symbol.
+ * @param c Character.
+ * @return an array of KeyboardModifier constants.
+ * @see CharBindingMap#getCharModifiers(char)
+ * @see KeyboardModifier
+ */
+ public KeyboardModifier[] getCharModifiers(char c) {
+ CharKey charKey = (CharKey)chars.get(new Character(c));
+ if(charKey != null) {
+ return charKey.modifiers;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an array of all supported chars.
+ * @return an array of chars representing the supported chars values.
+ */
+ public char[] getSupportedChars() {
+ char[] charArray = new char[chars.size()];
+ Enumeration keys = chars.keys();
+ int index = 0;
+ while(keys.hasMoreElements()) {
+ charArray[index] = ((Character)keys.nextElement()).charValue();
+ }
+ return(charArray);
+ }
+
+ /**
+ * Removes a char from supported.
+ * @param c Symbol code.
+ */
+ public void removeChar(char c) {
+ chars.remove(new Character(c));
+ }
+
+ /**
+ * Adds a char to supported.
+ * @param c Symbol code.
+ * @param key key code.
+ * @param modifiers a combination of InputEvent MASK fields.
+ */
+ public void addChar(char c, KeyboardButton key, KeyboardModifier... modifiers) {
+ chars.put(new Character(c), new CharKey(key, modifiers));
+ }
+
+ private void initMap() {
+ chars = new Hashtable();
+ //first add letters and digits represented by . fields
+ KeyboardButtons[] buttons = KeyboardButtons.values();
+ for(int i = 0; i < buttons.length; i++) {
+ String name = buttons[i].name();
+ String letter;
+ if (name.length() == 1 && Character.isLetter(name.charAt(0))) {
+ letter = name;
+ } else if (name.length() == 2 && name.startsWith("D") && Character.isDigit(name.charAt(1))) {
+ letter = name.substring(1);
+ } else {
+ continue;
+ }
+ addChar(letter.toLowerCase().charAt(0), buttons[i]);
+ if(!letter.toUpperCase().equals(letter.toLowerCase())) {
+ addChar(letter.toUpperCase().charAt(0), buttons[i], SHIFT_DOWN_MASK);
+ }
+ }
+ //add special simbols
+ addChar('\t', TAB);
+ addChar(' ', SPACE);
+ addChar('!', D1 , SHIFT_DOWN_MASK);
+ addChar('"', QUOTE , SHIFT_DOWN_MASK);
+ addChar('#', D3 , SHIFT_DOWN_MASK);
+ addChar('$', D4 , SHIFT_DOWN_MASK);
+ addChar('%', D5 , SHIFT_DOWN_MASK);
+ addChar('&', D7 , SHIFT_DOWN_MASK);
+ addChar('\'', QUOTE);
+ addChar('(', D9 , SHIFT_DOWN_MASK);
+ addChar(')', D0 , SHIFT_DOWN_MASK);
+ addChar('*', D8 , SHIFT_DOWN_MASK);
+ addChar(',', COMMA);
+ addChar('-', MINUS);
+ addChar('.', PERIOD);
+ addChar('/', SLASH);
+ addChar(';', SEMICOLON);
+ addChar('<', COMMA , SHIFT_DOWN_MASK);
+ addChar('>', PERIOD , SHIFT_DOWN_MASK);
+ addChar('?', SLASH , SHIFT_DOWN_MASK);
+ addChar('@', D2 , SHIFT_DOWN_MASK);
+ addChar('[', OPEN_BRACKET);
+ addChar(']', CLOSE_BRACKET);
+ addChar('^', D6 , SHIFT_DOWN_MASK);
+ addChar('_', MINUS , SHIFT_DOWN_MASK);
+ addChar('`', BACK_QUOTE);
+ addChar('{', OPEN_BRACKET , SHIFT_DOWN_MASK);
+ addChar('|', BACK_SLASH , SHIFT_DOWN_MASK);
+ addChar('}', CLOSE_BRACKET, SHIFT_DOWN_MASK);
+ addChar('\n', ENTER);
+
+ if ("sv".equals(Environment.getEnvironment().getProperty("LANG"))) {
+ addChar('+', PLUS);
+ addChar(':', PERIOD, SHIFT_DOWN_MASK);
+ addChar('\\', PLUS, CTRL_DOWN_MASK, ALT_DOWN_MASK);
+ addChar('~', DEAD_DIAERESIS, CTRL_DOWN_MASK, ALT_DOWN_MASK);
+ addChar('=', D0, SHIFT_DOWN_MASK);
+ } else {
+ addChar('+', EQUALS , SHIFT_DOWN_MASK);
+ addChar(':', SEMICOLON , SHIFT_DOWN_MASK);
+ addChar('\\', BACK_SLASH);
+ addChar('~', BACK_QUOTE , SHIFT_DOWN_MASK);
+ addChar('=', EQUALS);
+ }
+ }
+
+ private static class CharKey {
+ public KeyboardButton key;
+ public KeyboardModifier modifiers[];
+ public CharKey(KeyboardButton key, KeyboardModifier... modifiers) {
+ this.key = key;
+ this.modifiers = modifiers;
+ }
+ }
+
+}
--- /dev/null 2017-11-08 15:39:44.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/KnobDragScrollerImpl.java 2017-11-08 15:39:44.000000000 -0800
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.JemmyException;
+import org.jemmy.Point;
+import org.jemmy.Rectangle;
+import org.jemmy.Vector;
+import org.jemmy.env.Timeout;
+import org.jemmy.action.Action;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Caret;
+import org.jemmy.interfaces.Drag;
+import org.jemmy.interfaces.Scroll;
+
+/**
+ * Performs scrolling by doing d'n'd of a "knob" wrap. To be used for controls
+ * like scroll bars, sliders.
+ * @author shura
+ */
+public abstract class KnobDragScrollerImpl implements Caret {
+
+ public static final int MAX_SCROLL_ATTEMPTS = 5;
+
+ Wrap> wrap;
+ Scroll scroll;
+ float dragDelta = 1;
+ boolean reverse;
+
+ /**
+ *
+ * @param wrap
+ * @param scroll
+ */
+ public KnobDragScrollerImpl(Wrap> wrap, Scroll scroll) {
+ this.wrap = wrap;
+ this.scroll = scroll;
+ }
+
+ public KnobDragScrollerImpl(Wrap> wrap, Scroll scroll, boolean reverse) {
+ this(wrap, scroll);
+ this.reverse = reverse;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Wrap> getWrap() {
+ return wrap;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public abstract Vector getScrollVector();
+
+ /**
+ *
+ * @param dragDelta
+ */
+ public void setDragDelta(float dragDelta) {
+ this.dragDelta = dragDelta;
+ }
+
+ private void toKnob(Wrap> knob, Point inWrap) {
+ inWrap.translate(wrap.getScreenBounds().x, wrap.getScreenBounds().y);
+ inWrap.translate(-knob.getScreenBounds().x, -knob.getScreenBounds().y);
+ }
+
+ private void toWrap(Wrap> knob, Point inWrap) {
+ inWrap.translate(knob.getScreenBounds().x, knob.getScreenBounds().y);
+ inWrap.translate(-wrap.getScreenBounds().x, -wrap.getScreenBounds().y);
+ }
+
+ public void to(double value) {
+ scroll.to(value);
+ }
+
+ public void to(final Direction condition) {
+ wrap.getEnvironment().getExecutor().execute(wrap.getEnvironment(), false, new Action() {
+
+ @Override
+ public void run(Object... parameters) {
+ int toOrig;
+ int dragAttempt = 0;
+ Timeout moveTimeout = wrap.getEnvironment().getTimeout(Drag.IN_DRAG_TIMEOUT).clone();
+ while((toOrig = condition.to()) != 0) {
+ Vector axis = getScrollVector().
+ multiply(toOrig).setLenght(dragDelta);
+ if (reverse) {
+ axis.multiply(-1);
+ }
+ Vector shift = axis.clone();
+ Wrap> knob = getKnob();
+ Point orig = new Point(knob.getScreenBounds().getX() + knob.getScreenBounds().getWidth()/2, knob.getScreenBounds().getY() + knob.getScreenBounds().getHeight()/2);
+ knob.mouse().move(knob.toLocal(orig.getLocation()));
+ knob.mouse().press();
+ wrap.getEnvironment().getTimeout(Drag.BEFORE_DRAG_TIMEOUT).sleep();
+ try {
+ while (condition.to() == toOrig) {
+ wrap.getEnvironment().getTimeout(Drag.IN_DRAG_TIMEOUT).sleep();
+// Rectangle old_pos = knob.getScreenBounds();
+ knob.mouse().move(knob.toLocal(orig.getLocation().translate(shift)));
+// if (old_pos.equals(knob.getScreenBounds())) { // TODO: it would be better to check if we achieve maximum position
+// break;
+// }
+ if(scroll.position() == scroll.minimum() || scroll.position() == scroll.maximum()) {
+ break;
+ }
+ shift.add(axis);
+ }
+ } finally {
+ wrap.getEnvironment().getTimeout(Drag.BEFORE_DROP_TIMEOUT).sleep();
+ knob.mouse().release();
+ }
+ dragAttempt++;
+ if(dragAttempt >= MAX_SCROLL_ATTEMPTS) {
+ //did what we could
+ return;
+ }
+ //slow dow the scrolling
+ moveTimeout.setValue((long) (moveTimeout.getValue() * 1.5));
+ }
+ }
+ });
+ }
+
+ /*
+ * Create another class for this perhaps
+ private void initialDrag(double value) {
+ Point hp = getEndPoint(false);
+ Point lp = getEndPoint(true);
+ double xdiff = hp.x - lp.x;
+ double ydiff = hp.y - lp.y;
+ double ratio = value / (scroll.maximum() - scroll.minimum());
+ Wrap> knob = getKnob();
+ Point p = new Point(xdiff * ratio, ydiff * ratio);
+ toKnob(knob, p);
+ Point clickPoint = knob.getClickPoint();
+ p.translate(clickPoint.x, clickPoint.y);
+ knob.drag().dnd(clickPoint, knob, p);
+ }
+ *
+ */
+ /**
+ *
+ * @return
+ */
+ protected abstract Wrap> getKnob();
+}
--- /dev/null 2017-11-08 15:39:45.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/RegexCaretDirection.java 2017-11-08 15:39:45.000000000 -0800
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.jemmy.JemmyException;
+import org.jemmy.interfaces.CaretOwner;
+import org.jemmy.interfaces.Text;
+
+/**
+ *
+ * @author shura
+ */
+public class RegexCaretDirection extends CaretImpl.DirectionToPosition {
+
+ /**
+ *
+ */
+ public static final String REGEX_FLAGS = "";
+
+ String regex;
+ boolean front;
+ int index;
+ Text text;
+ int flags;
+
+ /**
+ *
+ * @param text
+ * @param caretOwner
+ * @param regex
+ * @param flags
+ * @param front
+ * @param index
+ */
+ public RegexCaretDirection(Text text, CaretOwner caretOwner, String regex, int flags, boolean front, int index) {
+ super(caretOwner, 0);
+ this.text = text;
+ this.regex = regex;
+ this.flags = flags;
+ this.front = front;
+ this.index = index;
+ if (index < 0) {
+ throw new JemmyException("Index must be >=0 but is " + index, regex);
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ @Override
+ protected double position() {
+ return position(text, regex, flags, front, index);
+ }
+
+ /**
+ *
+ * @param text
+ * @param regex
+ * @param flags
+ * @param front
+ * @param index
+ * @return
+ */
+ public static int position(Text text, String regex, int flags, boolean front, int index) {
+ Matcher matcher = Pattern.compile(regex, flags).matcher(text.text());
+ for (int i = 0; i <= index; i++) {
+ if (!matcher.find()) {
+ throw new JemmyException(index + "'s occurance of \"" + regex + "\" not found.", text);
+ }
+ }
+ return front ? matcher.start() : matcher.end();
+ }
+}
--- /dev/null 2017-11-08 15:39:45.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/ScrollerImpl.java 2017-11-08 15:39:45.000000000 -0800
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.Point;
+import org.jemmy.Rectangle;
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Timeout;
+import org.jemmy.interfaces.Caret;
+import org.jemmy.interfaces.CaretOwner;
+import org.jemmy.interfaces.Scroll;
+
+/**
+ * Performs scrolling by clicking at a certain position.
+ * @author shura
+ */
+public abstract class ScrollerImpl extends CaretImpl {
+
+ /**
+ * @deprecated Use AdvancedScroller.SCROLL_TIMEOUT
+ */
+ public static final Timeout SCROLL_TIMEOUT = CaretImpl.SCROLL_TIMEOUT;
+
+ Scroll scroll;
+
+ /**
+ *
+ * @param target
+ * @param caret
+ */
+ public ScrollerImpl(Wrap target, CaretOwner caret) {
+ super(target, caret);
+ scroll = new CaretScroll(caret);
+ addScrollAction(new ScrollAction() {
+
+ public void scrollTo(int direction) {
+ getWrap().mouse().click(1, getScrollClickPoint(direction > 0));
+ }
+ });
+ }
+
+ /**
+ * @param increase
+ * @return a point to click in order to decrease/increase the value
+ */
+ protected abstract Point getScrollClickPoint(boolean increase);
+
+ /**
+ * An auxiliary function to calculate click point, on the appropriate side
+ * of the control depending on the parameters.
+ * @param c
+ * @param horizontal - horizontal or vertical
+ * @param increase - increase or decrease
+ * @param offset distance from the border
+ * @return
+ */
+ public static Point createScrollPoint(Wrap c, boolean horizontal, boolean increase, int offset) {
+ return createScrollPoint(c.getScreenBounds(), horizontal, increase, offset);
+ }
+
+ /**
+ *
+ * @param bounds
+ * @param horizontal
+ * @param increase
+ * @param offset
+ * @return
+ */
+ public static Point createScrollPoint(Rectangle bounds, boolean horizontal, boolean increase, int offset) {
+ if(horizontal) {
+ return new Point(increase ? (bounds.width - 1 - offset) : offset, bounds.height / 2);
+ } else {
+ return new Point(bounds.width / 2, increase ? (bounds.height - 1 - offset) : offset);
+ }
+ }
+
+ //only the value is used from it
+ /**
+ *
+ */
+ public static class CaretScroll implements Scroll {
+
+ CaretOwner co;
+
+ /**
+ *
+ * @param co
+ */
+ public CaretScroll(CaretOwner co) {
+ this.co = co;
+ }
+
+ public double maximum() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public double minimum() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public double position() {
+ return co.position();
+ }
+
+ public Caret caret() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void to(double position) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+}
--- /dev/null 2017-11-08 15:39:45.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/SelectionText.java 2017-11-08 15:39:45.000000000 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Caret;
+import org.jemmy.interfaces.IntervalSelectable;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class SelectionText extends CaretText implements IntervalSelectable {
+
+ /**
+ *
+ * @param wrap
+ */
+ public SelectionText(Wrap> wrap) {
+ super(wrap);
+ }
+
+ /**
+ * Selects index
'th occurance of the regex.
+ * @param regex
+ * @param index
+ */
+ public void select(String regex, int index) {
+ to(regex, true, index);
+ caret().selectTo(new RegexCaretDirection(this, this, regex, getFlags(), false, index));
+ }
+
+ /**
+ * Selects first occurance of the regex.
+ * @param regex
+ */
+ public void select(String regex) {
+ select(regex, 0);
+ }
+
+ /**
+ * Retuns the selection portion of the text.
+ * @return
+ */
+ public String selection() {
+ int a = (int) anchor(); int p = (int) position();
+ int start = (a < p) ? a : p;
+ int end = (a < p) ? p : a;
+ return text().substring(start, end);
+ }
+
+ @Override
+ protected void initCaret() {
+ caret = new TextCaret(wrap, this) {
+ @Override
+ public void to(Caret.Direction direction) {
+ int orig = direction.to();
+ if (orig == 0) {
+ return;
+ }
+ if (anchor() - position() != 0) {
+ super.to(direction); // clear selection
+ }
+ super.to(direction);
+ }
+ };
+ }
+}
--- /dev/null 2017-11-08 15:39:46.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/StringCriteriaList.java 2017-11-08 15:39:46.000000000 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.env.Environment;
+import org.jemmy.lookup.LookupCriteria;
+import org.jemmy.resources.StringComparePolicy;
+
+/**
+ * Defines logic of converting a list of strings (aka titles, texts) into a list of
+ * LookupCriteria. It is to be extended for hierarchical data support
+ * where string identification is applicable (such as trees, menus).
+ * @author shura
+ */
+public abstract class StringCriteriaList {
+
+ private StringComparePolicy policy;
+
+ public final static String STRING_COMPARE_POLICY_PROP_NAME =
+ StringCriteriaList.class.getName() + ".string.compare.policy";
+
+ protected StringCriteriaList(Environment env) {
+ policy = (StringComparePolicy) env.getProperty(STRING_COMPARE_POLICY_PROP_NAME, StringComparePolicy.EXACT);
+ }
+
+ protected StringCriteriaList(StringComparePolicy policy) {
+ this.policy = policy;
+ }
+
+ public StringComparePolicy getPolicy() {
+ return policy;
+ }
+
+ public void setPolicy(StringComparePolicy policy) {
+ this.policy = policy;
+ }
+
+ protected LookupCriteria[] createCriteriaList(String[] texts) {
+ LookupCriteria[] criteria = new LookupCriteria[texts.length];
+ for(int i = 0; i < texts.length; i++) {
+ criteria[i] = createCriteria(texts[i], policy);
+ }
+ return criteria;
+ }
+
+ protected abstract LookupCriteria createCriteria(String text, StringComparePolicy policy);
+}
--- /dev/null 2017-11-08 15:39:46.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/StringMenuOwner.java 2017-11-08 15:39:46.000000000 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Menu;
+import org.jemmy.interfaces.MenuOwner;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * In most cases menu has a text associated with every menu item. This interface
+ * makes it easy to push the menu based on that text information.
+ * @author shura
+ */
+public abstract class StringMenuOwner extends StringCriteriaList
+ implements MenuOwner {
+
+ private static final String MENU_PATH_LENGTH_ERROR = "Menu path length should be greater than 0";
+
+ public StringMenuOwner(Wrap> menuOwner) {
+ super(menuOwner.getEnvironment());
+ }
+
+ /**
+ * Pushes the menu using one string for one level of the menu. Comparison
+ * is done according to the policy.
+ * @param texts
+ * @see #getPolicy()
+ */
+ public void push(String... texts) {
+ if(texts.length == 0) {
+ throw new IllegalArgumentException(MENU_PATH_LENGTH_ERROR);
+ }
+ menu().push(createCriteriaList(texts));
+ }
+
+ /**
+ * A shortcut to menu().push(LookupCriteria ...)
+ * @see #menu()
+ * @see Menu#push(org.jemmy.lookup.LookupCriteria[])
+ * @param criteria
+ */
+ public void push(LookupCriteria... criteria) {
+ menu().push(criteria);
+ }
+
+ /**
+ * Select a menu item using one string for one level of the menu. Comparison
+ * is done according to the policy.
+ * @param texts
+ * @return wrap for the last selected item
+ * @see #getPolicy()
+ */
+ public Wrap extends T> select(String... texts) {
+ if(texts.length == 0) {
+ throw new IllegalArgumentException(MENU_PATH_LENGTH_ERROR);
+ }
+ return menu().select(createCriteriaList(texts));
+ }
+
+ /**
+ * A shortcut to menu().select(LookupCriteria ...)
+ * @see #menu()
+ * @see Menu#select(org.jemmy.lookup.LookupCriteria[])
+ * @param criteria
+ */
+ public Wrap extends T> select(LookupCriteria... criteria) {
+ return menu().select(criteria);
+ }
+
+}
--- /dev/null 2017-11-08 15:39:46.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/StringMenuSelectableOwner.java 2017-11-08 15:39:46.000000000 -0800
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.MenuSelectableOwner;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ *
+ * @author erikgreijus
+ * @param
+ */
+public abstract class StringMenuSelectableOwner extends StringMenuOwner implements MenuSelectableOwner {
+
+ private static final String MENU_PATH_LENGTH_ERROR = "Menu path length should be greater than 0";
+
+ public StringMenuSelectableOwner(Wrap> menuOwner) {
+ super(menuOwner);
+ }
+
+ /**
+ * Ensures state of a menu item conforming to the criteria. That would mean
+ * that all intermediate items get expanded and the menus are shown.
+ * Selection depends on if the desired state matches the current state or
+ * not. I.e selection of the last criteria happens only if the state differs
+ * from desiredSelectionState
+ *
+ * @param desiredSelectionState The desired selection state of the leaf menu
+ * item.
+ * @param texts used one for one level. In case of a menu bar, for example,
+ * first string is to be used to find a top level menu, second to find a
+ * menu underneath, etc.
+ */
+ public void push(boolean desiredSelectionState, String... texts) {
+ if (texts.length == 0) {
+ throw new IllegalArgumentException(MENU_PATH_LENGTH_ERROR);
+ }
+ push(desiredSelectionState, createCriteriaList(texts));
+ }
+
+ /**
+ * Ensures state of a menu item conforming to the criteria. That would mean
+ * that all intermediate items get expanded and the menus are shown.
+ * Selection depends on if the desired state matches the current state or
+ * not. I.e selection of the last criteria happens only if the state differs
+ * from desiredSelectionState
+ *
+ * @param desiredSelectionState The desired selection state of the leaf menu
+ * item.
+ * @param criteria used one for one level. In case of a menu bar, for
+ * example, first criteria is to be used to find a top level menu, second to
+ * find a menu underneath, etc.
+ */
+ public void push(boolean desiredSelectionState, LookupCriteria... criteria) {
+ menu().push(desiredSelectionState, criteria);
+ }
+
+ /**
+ * Returns the current selection state of the menu item conforming to the
+ * criteria. That would mean that all intermediate items get expanded and
+ * the menus are shown.
+ *
+ * @param texts used one for one level. In case of a menu bar, for example,
+ * first criteria is to be used to find a top level menu, second to find a
+ * menu underneath, etc.
+ * @return True if the menu item is selected. Otherwise false.
+ */
+ public boolean getState(String... texts) {
+ if (texts.length == 0) {
+ throw new IllegalArgumentException(MENU_PATH_LENGTH_ERROR);
+ }
+ return getState(createCriteriaList(texts));
+ }
+
+ /**
+ * Returns the current selection state of the menu item conforming to the
+ * criteria. That would mean that all intermediate items get expanded and
+ * the menus are shown.
+ *
+ * @param criteria used one for one level. In case of a menu bar, for
+ * example, first criteria is to be used to find a top level menu, second to
+ * find a menu underneath, etc.
+ * @return True if the menu item is selected. Otherwise false.
+ */
+ public boolean getState(LookupCriteria... criteria) {
+ return menu().getState(criteria);
+ }
+
+}
--- /dev/null 2017-11-08 15:39:47.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/StringPopupOwner.java 2017-11-08 15:39:47.000000000 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.PopupOwner;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class StringPopupOwner extends StringCriteriaList
+ implements PopupOwner{
+
+ public StringPopupOwner(Wrap> menuOwner) {
+ super(menuOwner.getEnvironment());
+ }
+
+ public void push(Point p, String... texts) {
+ if(texts.length == 0) {
+ throw new IllegalArgumentException("Menu path length should be greater than 0");
+ }
+ menu(p).push(createCriteriaList(texts));
+ }
+
+ public void select(Point p, String... texts) {
+ if(texts.length == 0) {
+ throw new IllegalArgumentException("Menu path length should be greater than 0");
+ }
+ menu(p).select(createCriteriaList(texts));
+ }
+
+}
--- /dev/null 2017-11-08 15:39:47.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/StringPopupSelectableOwner.java 2017-11-08 15:39:47.000000000 -0800
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.PopupSelectableOwner;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ *
+ * @author erikgreijus
+ * @param
+ */
+public abstract class StringPopupSelectableOwner extends StringPopupOwner implements PopupSelectableOwner {
+
+ private static final String MENU_PATH_LENGTH_ERROR = "Menu path length should be greater than 0";
+
+ public StringPopupSelectableOwner(Wrap> menuOwner) {
+ super(menuOwner);
+ }
+
+ /**
+ * Ensures state of a menu item conforming to the criteria. That would mean
+ * that all intermediate items get expanded and the menus are shown.
+ * Selection depends on if the desired state matches the current state or
+ * not. I.e selection of the last criteria happens only if the state differs
+ * from desiredSelectionState
+ *
+ * @param desiredSelectionState The desired selection state of the leaf menu
+ * item.
+ * @param p The point where the popup menu is to be opened
+ * @param criteria used one for one level. In case of a menu bar, for
+ * example, first criteria is to be used to find a top level menu, second to
+ * find a menu underneath, etc.
+ */
+ public void push(boolean desiredSelectionState, Point p, LookupCriteria... criteria) {
+ menu(p).push(desiredSelectionState, criteria);
+ }
+
+ /**
+ * Ensures state of a menu item conforming to the criteria. That would mean
+ * that all intermediate items get expanded and the menus are shown.
+ * Selection depends on if the desired state matches the current state or
+ * not. I.e selection of the last criteria happens only if the state differs
+ * from desiredSelectionState
+ *
+ * @param desiredSelectionState The desired selection state of the leaf menu
+ * item.
+ * @param p The point where the popup menu is to be opened
+ * @param texts used one for one level. In case of a menu bar, for example,
+ * first string is to be used to find a top level menu, second to find a
+ * menu underneath, etc.
+ */
+ public void push(boolean desiredSelectionState, Point p, String... texts) {
+ if (texts.length == 0) {
+ throw new IllegalArgumentException(MENU_PATH_LENGTH_ERROR);
+ }
+ push(desiredSelectionState, p, createCriteriaList(texts));
+ }
+
+ /**
+ * Returns the current selection state of the menu item conforming to the
+ * criteria. That would mean that all intermediate items get expanded and
+ * the menus are shown.
+ *
+ * @param p The point where the popup menu is to be opened
+ * @param criteria used one for one level. In case of a menu bar, for
+ * example, first criteria is to be used to find a top level menu, second to
+ * find a menu underneath, etc.
+ * @return True if the menu item is selected. Otherwise false.
+ */
+ public boolean getState(Point p, LookupCriteria... criteria) {
+ return menu(p).getState(criteria);
+ }
+
+ /**
+ * Returns the current selection state of the menu item conforming to the
+ * criteria. That would mean that all intermediate items get expanded and
+ * the menus are shown.
+ *
+ * @param p The point where the popup menu is to be opened
+ * @param texts used one for one level. In case of a menu bar, for example,
+ * first string is to be used to find a top level menu, second to find a
+ * menu underneath, etc.
+ * @return True if the menu item is selected. Otherwise false.
+ */
+ public boolean getState(Point p, String... texts) {
+ if (texts.length == 0) {
+ throw new IllegalArgumentException(MENU_PATH_LENGTH_ERROR);
+ }
+ return getState(p, createCriteriaList(texts));
+ }
+
+}
--- /dev/null 2017-11-08 15:39:47.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/StringTree.java 2017-11-08 15:39:47.000000000 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.env.Environment;
+import org.jemmy.interfaces.Tree;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class StringTree extends StringCriteriaList implements Tree {
+
+ public StringTree(Environment env) {
+ super(env);
+ }
+
+ public Wrap extends T> select(String... texts) {
+ if(texts.length == 0) {
+ throw new IllegalArgumentException("Tree path length should be greater than 0");
+ }
+ return selector().select(createCriteriaList(texts));
+ }
+}
--- /dev/null 2017-11-08 15:39:48.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/TextCaret.java 2017-11-08 15:39:48.000000000 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.CaretOwner;
+import org.jemmy.interfaces.IntervalSelector;
+import org.jemmy.interfaces.Keyboard.KeyboardButton;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Keyboard.KeyboardModifier;
+
+/**
+ *
+ * @author shura
+ */
+public class TextCaret extends CaretImpl implements IntervalSelector {
+
+ /**
+ *
+ * @param wrap
+ * @param scroll
+ */
+ public TextCaret(Wrap> wrap, CaretOwner scroll) {
+ super(wrap, scroll);
+ addScrollAction(new KeyboardScrollAction(KeyboardButtons.LEFT, KeyboardButtons.RIGHT));
+ }
+
+ /**
+ *
+ * @param down
+ * @param downMods
+ * @param up
+ * @param upMods
+ */
+ public void addNavKeys(KeyboardButton down, KeyboardModifier[] downMods,
+ KeyboardButton up, KeyboardModifier[] upMods) {
+ addScrollAction(new CaretImpl.KeyboardScrollAction(down, downMods, up, upMods));
+ }
+
+ /**
+ *
+ * @param down
+ * @param up
+ */
+ public void addNavKeys(KeyboardButton down, KeyboardButton up) {
+ addNavKeys(down, new KeyboardModifier[0], up, new KeyboardModifier[0]);
+ }
+
+ public void selectTo(double value) {
+ getWrap().keyboard().pressKey(KeyboardButtons.SHIFT);
+ to(value);
+ getWrap().keyboard().releaseKey(KeyboardButtons.SHIFT);
+ }
+
+ public void selectTo(Direction condition) {
+ getWrap().keyboard().pressKey(KeyboardButtons.SHIFT);
+ to(condition);
+ getWrap().keyboard().releaseKey(KeyboardButtons.SHIFT);
+ }
+}
--- /dev/null 2017-11-08 15:39:48.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/TextImpl.java 2017-11-08 15:39:48.000000000 -0800
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.input;
+
+import org.jemmy.action.Action;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Focusable;
+import org.jemmy.interfaces.Keyboard;
+import org.jemmy.interfaces.Keyboard.KeyboardButtons;
+import org.jemmy.interfaces.Keyboard.KeyboardModifiers;
+import org.jemmy.interfaces.Text;
+import org.jemmy.timing.State;
+import static org.jemmy.interfaces.Keyboard.KeyboardButtons.*;
+
+/**
+ *
+ * @author shura
+ */
+public abstract class TextImpl implements Text {
+
+ private static final int DEFAULT_SELECT_ALL_CLICK_COUNT = 3;
+ private Wrap> target;
+ private int selectAllClickCount = DEFAULT_SELECT_ALL_CLICK_COUNT;
+ boolean keyboardSelection;
+
+ /**
+ *
+ * @param target
+ * @param keyboardSelection
+ */
+ protected TextImpl(Wrap> target, boolean keyboardSelection) {
+ this.target = target;
+ this.keyboardSelection = keyboardSelection;
+ }
+
+ /**
+ *
+ * @param target
+ */
+ protected TextImpl(Wrap> target) {
+ this(target, false);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Wrap> getWrap() {
+ return target;
+ }
+
+ /**
+ * Types text into the control. Wrap may implement Focusable.
+ *
+ * @see Focusable
+ * @param newText
+ */
+ public void type(final String newText) {
+ target.getEnvironment().getExecutor().execute(target.getEnvironment(), false, new Action() {
+ public void run(Object... parameters) {
+ if (target.is(Focusable.class)) {
+ target.as(Focusable.class).focuser().focus();
+ }
+ char[] chars = newText.toCharArray();
+ Keyboard kb = target.keyboard();
+ for (char c : chars) {
+ kb.typeChar(c);
+ }
+ target.getEnvironment().getWaiter(Wrap.WAIT_STATE_TIMEOUT.getName()).ensureState(new State() {
+ public Object reached() {
+ return text().contains(newText) ? "" : null;
+ }
+
+ @Override
+ public String toString() {
+ return "text() equals '" + newText + "', text() = '" + text() + "'";
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return "typing text \"" + newText + "\"";
+ }
+ });
+ }
+
+ /**
+ * Selects all text within component by clicking 3 times on it or using
+ * keyboard depending on the second argument passed to {@linkplain
+ * #TextImpl(org.jemmy.control.Wrap, boolean) constructor}. Override if
+ * needed.
+ *
+ * Warning! In Java keyboard selection doesn't work with NumLock
+ * turned On due to CR 4966137 'Robot presses Numpad del key instead of
+ * normal Del key'.
+ */
+ protected void selectAll() {
+ if (!keyboardSelection) {
+ target.mouse().click(selectAllClickCount, target.getClickPoint());
+ } else {
+ Keyboard kbrd = target.keyboard();
+ kbrd.pushKey(KeyboardButtons.HOME);
+ kbrd.pushKey(KeyboardButtons.END, KeyboardModifiers.SHIFT_DOWN_MASK);
+ kbrd.pushKey(KeyboardButtons.DELETE);
+ }
+ }
+
+ /**
+ * Clears text by pressing End and then Delete and Backspace until the text
+ * is cleared.
+ */
+ public void clear() {
+ target.getEnvironment().getExecutor().execute(target.getEnvironment(),
+ false, new Action() {
+ public void run(Object... parameters) {
+ if (target.is(Focusable.class)) {
+ target.as(Focusable.class).focuser().focus();
+ }
+ String text = text();
+ if (text == null) {
+ return;
+ }
+ target.keyboard().pushKey(END);
+ while (!text.isEmpty() && withinAllowedTime()) {
+ target.keyboard().pushKey(BACK_SPACE);
+ target.keyboard().pushKey(DELETE);
+ text = text();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "clearing text";
+ }
+ });
+ }
+}
--- /dev/null 2017-11-08 15:39:48.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/input/WindowImpl.java 2017-11-08 15:39:48.000000000 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.input;
+
+import org.jemmy.Dimension;
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.interfaces.Window;
+
+/**
+ *
+ * @author shura
+ */
+public class WindowImpl implements Window {
+
+ private Wrap control;
+ private int offset;
+
+ /**
+ *
+ * @param control
+ * @param offset
+ */
+ public WindowImpl(Wrap control, int offset) {
+ this.control = control;
+ this.offset = offset;
+ }
+
+ /**
+ *
+ * @param dest
+ */
+ public void move(Point dest) {
+ Point start = control.getClickPoint();
+ Point target = new Point(start.x + dest.x, start.y + dest.y);
+ control.drag().dnd(start, control, target);
+ }
+
+ /**
+ *
+ * @param size
+ * @param direction
+ */
+ public void resize(Dimension size, Direction direction) {
+ Point start = null, target = null;
+ Dimension sizeDiff = new Dimension(size.width - control.getScreenBounds().width, size.height - control.getScreenBounds().height);
+ switch(direction) {
+ case NORTHWEST:
+ start = new Point(offset, offset);
+ target = new Point(start.x - sizeDiff.width, start.y - sizeDiff.height);
+ break;
+ case NORTHEAST:
+ start = new Point(control.getScreenBounds().width - offset - 1, offset);
+ target = new Point(start.x + sizeDiff.width, start.y - sizeDiff.height);
+ break;
+ case SOUTHEAST:
+ start = new Point(control.getScreenBounds().width - offset - 1, control.getScreenBounds().height - offset - 1);
+ target = new Point(start.x + sizeDiff.width, start.y + sizeDiff.height);
+ break;
+ case SOUTHWEST:
+ start = new Point(offset, control.getScreenBounds().height - offset - 1);
+ target = new Point(start.x - sizeDiff.width, start.y + sizeDiff.height);
+ break;
+ }
+ control.drag().dnd(start, control, target);
+ }
+
+}
--- /dev/null 2017-11-08 15:39:49.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Button.java 2017-11-08 15:39:49.000000000 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+
+/**
+ * All Input Drivers should implement this interface for buttons
+ * We need this interface to be able to extend buttons set
+ */
+public interface Button {
+
+}
--- /dev/null 2017-11-08 15:39:49.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Caret.java 2017-11-08 15:39:49.000000000 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ * Responsible for "scrolling"
+ * @see Scroll
+ * @author shura
+ */
+public interface Caret {
+ /**
+ * @deprecated this is moved to CaretOwner
+ * @param value
+ */
+ public void to(double value);
+
+ /**
+ *
+ * @param condition
+ */
+ public void to(Direction condition);
+
+ /**
+ *
+ */
+ public interface Direction {
+ /**
+ * @return < 0 to scroll toward decreasing value, > 0 - vice versa
+ * 0 to stop scrolling
+ */
+ public int to();
+ }
+}
--- /dev/null 2017-11-08 15:39:49.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/CaretOwner.java 2017-11-08 15:39:49.000000000 -0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.jemmy.interfaces;
+
+
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+import org.jemmy.dock.Shortcut;
+
+
+/**
+ * Interface representing an object which represents an integer value which
+ * could be increased or decreased, such as scroll bar, slider, etc.
+ * @author shura
+ */
+public interface CaretOwner extends ControlInterface {
+ /**
+ *
+ * @return
+ */
+ @Property(Wrap.VALUE_PROP_NAME)
+ public double position();
+ /**
+ *
+ * @return
+ */
+ @Shortcut
+ public Caret caret();
+
+ /**
+ * Utility method that invokes caret().to(Direction) with correct
+ * direction.
+ * TODO: Remove this method.
+ * @param position
+ */
+ @Shortcut
+ public void to(double position);
+
+}
--- /dev/null 2017-11-08 15:39:50.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Collapsible.java 2017-11-08 15:39:50.000000000 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Collapsible extends ControlInterface {
+
+ @Shortcut
+ void collapse();
+}
--- /dev/null 2017-11-08 15:39:50.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/ControlInterface.java 2017-11-08 15:39:50.000000000 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author shura
+ */
+public interface ControlInterface {
+
+}
--- /dev/null 2017-11-08 15:39:50.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/ControlInterfaceFactory.java 2017-11-08 15:39:50.000000000 -0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+
+import org.jemmy.control.Wrap;
+
+/**
+ * This defines an interface to provide flexible way to control
+ * test execution from outside. Check Wrap sources code for use case.
+ * The interface is not intended to be used directly from test.
+ * @see org.jemmy.control.Wrap
+ * @author shura
+ */
+public interface ControlInterfaceFactory {
+ /**
+ * Instantiates interface.
+ * @param ControlInterface type
+ * @param control control to provide the interface for
+ * @param interfaceClass ControlInterface type
+ * @return ControlInterface instance or null for an unknown type
+ */
+ public INTERFACE create(Wrap> control, Class interfaceClass);
+ /**
+ *
+ * Instantiates interface.
+ * @param
+ * @param ControlInterface type
+ * @param control control to provide the interface for
+ * @param interfaceClass ControlInterface type
+ * @param type Incapsulated type
+ * @return ControlInterface instance or null for an unknown type
+ */
+ public > INTERFACE create(Wrap> control, Class interfaceClass, Class type);
+}
--- /dev/null 2017-11-08 15:39:51.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Drag.java 2017-11-08 15:39:51.000000000 -0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+
+import org.jemmy.Point;
+import org.jemmy.control.Wrap;
+import org.jemmy.dock.Shortcut;
+import org.jemmy.env.Timeout;
+import org.jemmy.interfaces.Mouse.MouseButton;
+
+
+/**
+ *
+ * @author shura
+ */
+public interface Drag extends ControlInterface {
+ /**
+ *
+ */
+ public static final Timeout BEFORE_DRAG_TIMEOUT = new Timeout("Control.before.drag", 500);
+ /**
+ *
+ */
+ public static final Timeout BEFORE_DROP_TIMEOUT = new Timeout("Control.after.drag", 500);
+ /**
+ *
+ */
+ public static final Timeout IN_DRAG_TIMEOUT = new Timeout("Control.in.drag", 10);
+
+ /**
+ *
+ * @param targetPoint target point specified in component local coordinates
+ */
+ @Shortcut
+ public void dnd(Point targetPoint);
+ /**
+ *
+ * @param target
+ * @param targetPoint target point specified in target component local coordinates
+ */
+ @Shortcut
+ public void dnd(Wrap target, Point targetPoint);
+ /**
+ *
+ * @param point source point specified in component local coordinates
+ * @param target
+ * @param targetPoint target point specified in target component local coordinates
+ */
+ @Shortcut
+ public void dnd(Point point, Wrap target, Point targetPoint);
+ /**
+ *
+ * @param point source point specified in component local coordinates
+ * @param target
+ * @param targetPoint target point specified in target component local coordinates
+ * @param button
+ */
+ @Shortcut
+ public void dnd(Point point, Wrap target, Point targetPoint, MouseButton button);
+ /**
+ *
+ * @param point source point specified in component local coordinates
+ * @param target
+ * @param targetPoint target point specified in target component local coordinates
+ * @param button
+ * @param modifiers
+ */
+ @Shortcut
+ public void dnd(Point point, Wrap target, Point targetPoint, MouseButton button, Modifier... modifiers);
+}
--- /dev/null 2017-11-08 15:39:51.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Expandable.java 2017-11-08 15:39:51.000000000 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Expandable extends ControlInterface {
+
+ @Shortcut
+ void expand();
+}
--- /dev/null 2017-11-08 15:39:51.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Focus.java 2017-11-08 15:39:51.000000000 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author shura
+ */
+public interface Focus {
+ /**
+ *
+ */
+ public void focus();
+}
--- /dev/null 2017-11-08 15:39:52.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Focusable.java 2017-11-08 15:39:52.000000000 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Focusable extends ControlInterface {
+ /**
+ *
+ * @return
+ */
+ @Shortcut
+ public Focus focuser();
+}
--- /dev/null 2017-11-08 15:39:52.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/InterfaceException.java 2017-11-08 15:39:52.000000000 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.JemmyException;
+import org.jemmy.control.Wrap;
+
+/**
+ *
+ * @author shura
+ */
+public class InterfaceException extends JemmyException {
+
+ /**
+ *
+ * @param
+ * @param object
+ * @param interfaceClass
+ */
+ public InterfaceException(Wrap object, Class interfaceClass) {
+ super(interfaceClass.getName() + " is not implemented for " + object.getControl().getClass().getName() +
+ " by " + object.getClass().getName(), object.getControl());
+ }
+
+ /**
+ *
+ * @param
+ * @param
+ * @param object
+ * @param interfaceClass
+ * @param type
+ */
+ public > InterfaceException(Wrap object, Class interfaceClass, Class type) {
+ super(interfaceClass.getName() + " is not implemented for " + object.getControl().getClass().getName() +
+ " by " + object.getClass().getName() +
+ " or " + type.getClass().getName() + " is not enclosed", object.getControl());
+ }
+
+}
--- /dev/null 2017-11-08 15:39:52.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/IntervalSelectable.java 2017-11-08 15:39:52.000000000 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.control.Property;
+
+/**
+ *
+ * @author shura
+ */
+public interface IntervalSelectable extends CaretOwner {
+ /**
+ *
+ */
+ public static final String SELECTION_ANCHOR_PROP_NAME="selection.anchor";
+ /**
+ *
+ * @return
+ */
+ @Property(SELECTION_ANCHOR_PROP_NAME)
+ public double anchor();
+ public IntervalSelector caret();
+}
--- /dev/null 2017-11-08 15:39:53.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/IntervalSelector.java 2017-11-08 15:39:53.000000000 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author shura
+ */
+public interface IntervalSelector extends Caret {
+ /**
+ *
+ * @param value
+ */
+ public void selectTo(double value);
+
+ /**
+ *
+ * @param condition
+ */
+ public void selectTo(Caret.Direction condition);
+}
--- /dev/null 2017-11-08 15:39:53.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Keyboard.java 2017-11-08 15:39:53.000000000 -0800
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+import org.jemmy.env.Timeout;
+
+
+/**
+ * Defines how to simulate keyboard operations.
+ */
+public interface Keyboard extends ControlInterface {
+
+ /**
+ *
+ */
+ public static final Timeout PUSH = new Timeout("keyboard.push", 100);
+
+ /**
+ *
+ * @param key
+ * @param modifiers
+ */
+ @Shortcut
+ public void pressKey(KeyboardButton key, Modifier... modifiers);
+ /**
+ *
+ * @param key
+ */
+ @Shortcut
+ public void pressKey(KeyboardButton key);
+
+ /**
+ *
+ * @param key
+ * @param modifiers
+ */
+ @Shortcut
+ public void releaseKey(KeyboardButton key, Modifier... modifiers);
+ /**
+ *
+ * @param key
+ */
+ @Shortcut
+ public void releaseKey(KeyboardButton key);
+
+ /**
+ *
+ * @param key
+ * @param modifiers
+ * @param pushTime
+ */
+ @Shortcut
+ public void pushKey(Timeout pushTime, KeyboardButton key, Modifier... modifiers);
+ /**
+ *
+ * @param key
+ * @param modifiers
+ */
+ @Shortcut
+ public void pushKey(KeyboardButton key, Modifier... modifiers);
+ /**
+ *
+ * @param key
+ */
+ @Shortcut
+ public void pushKey(KeyboardButton key);
+
+ /**
+ *
+ * @param keyChar
+ * @param pushTime
+ */
+ @Shortcut
+ public void typeChar(char keyChar, Timeout pushTime);
+ /**
+ *
+ * @param keyChar
+ */
+ @Shortcut
+ public void typeChar(char keyChar);
+
+ /**
+ * Detaches the implementation so that all actions of it will be ran detached.
+ * @see org.jemmy.action.ActionExecutor#executeDetached(org.jemmy.env.Environment, org.jemmy.action.Action, java.lang.Object[])
+ * @return
+ */
+ public Keyboard detached();
+
+ /**
+ * Keyboard button interface (i. e. Q, W, ENTER, LEFT, F1, etc.)
+ * created to left the possibility for extention as enums can't be extended
+ */
+ public static interface KeyboardButton extends Button {
+
+ }
+
+ /**
+ * Keyboard modifier interface (i. e. SHIFT_DOWN_MASK)
+ * created to left the possibility for extention as enums can't be extended
+ */
+ public static interface KeyboardModifier extends Modifier {
+
+ }
+
+ /**
+ * Keyboard modifiers enum (i. e. SHIFT_DOWN_MASK)
+ * to be used in Keyboard interface methods
+ */
+ public static enum KeyboardModifiers implements KeyboardModifier {
+ /**
+ *
+ */
+ SHIFT_DOWN_MASK,
+ /**
+ *
+ */
+ CTRL_DOWN_MASK,
+ /**
+ *
+ */
+ ALT_DOWN_MASK,
+ /**
+ *
+ */
+ META_DOWN_MASK
+ }
+
+ /**
+ * Keyboard buttons enum (i. e. Q, W, ENTER, LEFT, F1, etc.)
+ * to be used in Keyboard interface methods
+ */
+ public static enum KeyboardButtons implements KeyboardButton {
+
+ /**
+ *
+ */
+ ESCAPE,
+ /**
+ *
+ */
+ F1,
+ /**
+ *
+ */
+ F2,
+ /**
+ *
+ */
+ F3,
+ /**
+ *
+ */
+ F4,
+ /**
+ *
+ */
+ F5,
+ /**
+ *
+ */
+ F6,
+ /**
+ *
+ */
+ F7,
+ /**
+ *
+ */
+ F8,
+ /**
+ *
+ */
+ F9,
+ /**
+ *
+ */
+ F10,
+ /**
+ *
+ */
+ F11,
+ /**
+ *
+ */
+ F12,
+ /**
+ *
+ */
+ F13,
+ /**
+ *
+ */
+ PRINTSCREEN,
+ /**
+ *
+ */
+ SCROLL_LOCK,
+ /**
+ *
+ */
+ PAUSE,
+ /**
+ *
+ */
+ BACK_QUOTE,
+ /**
+ *
+ */
+ D1,
+ /**
+ *
+ */
+ D2,
+ /**
+ *
+ */
+ D3,
+ /**
+ *
+ */
+ D4,
+ /**
+ *
+ */
+ D5,
+ /**
+ *
+ */
+ D6,
+ /**
+ *
+ */
+ D7,
+ /**
+ *
+ */
+ D8,
+ /**
+ *
+ */
+ D9,
+ /**
+ *
+ */
+ D0,
+ /**
+ *
+ */
+ MINUS,
+ /**
+ *
+ */
+ EQUALS,
+ /**
+ *
+ */
+ BACK_SLASH,
+ /**
+ *
+ */
+ BACK_SPACE,
+ /**
+ *
+ */
+ INSERT,
+ /**
+ *
+ */
+ HOME,
+ /**
+ *
+ */
+ PAGE_UP,
+ /**
+ *
+ */
+ NUM_LOCK,
+ /**
+ *
+ */
+ DIVIDE,
+ /**
+ *
+ */
+ MULTIPLY,
+ /**
+ *
+ */
+ SUBTRACT,
+ /**
+ *
+ */
+ TAB,
+ /**
+ *
+ */
+ Q,
+ /**
+ *
+ */
+ W,
+ /**
+ *
+ */
+ E,
+ /**
+ *
+ */
+ R,
+ /**
+ *
+ */
+ T,
+ /**
+ *
+ */
+ Y,
+ /**
+ *
+ */
+ U,
+ /**
+ *
+ */
+ I,
+ /**
+ *
+ */
+ O,
+ /**
+ *
+ */
+ P,
+ /**
+ *
+ */
+ OPEN_BRACKET,
+ /**
+ *
+ */
+ CLOSE_BRACKET,
+ /**
+ *
+ */
+ DELETE,
+ /**
+ *
+ */
+ END,
+ /**
+ *
+ */
+ PAGE_DOWN,
+ /**
+ *
+ */
+ NUMPAD7,
+ /**
+ *
+ */
+ NUMPAD8,
+ /**
+ *
+ */
+ NUMPAD9,
+ /**
+ *
+ */
+ ADD,
+ /**
+ *
+ */
+ CAPS_LOCK,
+ /**
+ *
+ */
+ A,
+ /**
+ *
+ */
+ S,
+ /**
+ *
+ */
+ D,
+ /**
+ *
+ */
+ F,
+ /**
+ *
+ */
+ G,
+ /**
+ *
+ */
+ H,
+ /**
+ *
+ */
+ J,
+ /**
+ *
+ */
+ K,
+ /**
+ *
+ */
+ L,
+ /**
+ *
+ */
+ SEMICOLON,
+ /**
+ *
+ */
+ QUOTE,
+ /**
+ *
+ */
+ ENTER,
+ /**
+ *
+ */
+ NUMPAD4,
+ /**
+ *
+ */
+ NUMPAD5,
+ /**
+ *
+ */
+ NUMPAD6,
+ /**
+ *
+ */
+ SHIFT,
+ /**
+ *
+ */
+ Z,
+ /**
+ *
+ */
+ X,
+ /**
+ *
+ */
+ C,
+ /**
+ *
+ */
+ V,
+ /**
+ *
+ */
+ B,
+ /**
+ *
+ */
+ N,
+ /**
+ *
+ */
+ M,
+ /**
+ *
+ */
+ COMMA,
+ /**
+ *
+ */
+ PERIOD,
+ /**
+ *
+ */
+ SLASH,
+ /**
+ *
+ */
+ UP,
+ /**
+ *
+ */
+ NUMPAD1,
+ /**
+ *
+ */
+ NUMPAD2,
+ /**
+ *
+ */
+ NUMPAD3,
+ /**
+ *
+ */
+ CONTROL,
+ /**
+ *
+ */
+ WINDOWS,
+ /**
+ *
+ */
+ ALT,
+ /**
+ * Represents meta key on some platforms (eg Command key on MacOS X)
+ */
+ META,
+ /**
+ *
+ */
+ SPACE,
+ /**
+ *
+ */
+ CONTEXT_MENU,
+ /**
+ *
+ */
+ LEFT,
+ /**
+ *
+ */
+ DOWN,
+ /**
+ *
+ */
+ RIGHT,
+ /**
+ *
+ */
+ NUMPAD0,
+ /**
+ *
+ */
+ DECIMAL,
+ /**
+ *
+ */
+ DEAD_DIAERESIS,
+ /**
+ *
+ */
+ PLUS
+ }
+
+}
--- /dev/null 2017-11-08 15:39:53.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Label.java 2017-11-08 15:39:53.000000000 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+
+/**
+ * Read only text component.
+ * @author shura
+ */
+
+public interface Label extends ControlInterface {
+ /**
+ * Returns the currently displayed text.
+ * TODO: Wrap.waitText
+ * @return
+ */
+ @Property(Wrap.TEXT_PROP_NAME)
+ public String text();
+}
--- /dev/null 2017-11-08 15:39:54.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Menu.java 2017-11-08 15:39:54.000000000 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * Represents a hierarchical structure (hence extending TreeSelector) in which
+ * elements not only could be selected but also "pushes", which is an action
+ * typically performed with menu.
+ * @author shura
+ * @see MenuOwner
+ */
+public interface Menu extends TreeSelector{
+
+ /**
+ * Pushes a menu item conforming to the criteria. That would mean that all
+ * intermediate items get expanded and the menus are shown, etc., etc. It is
+ * up to implementation whether to call select first or to do it somehow
+ * differently.
+ * @param criteria used one for one level. In case of a menu bar,
+ * for example, first criteria is to be used to find a top level menu, second -
+ * to find a menu underneath, etc
+ */
+ public abstract void push(LookupCriteria... criteria);
+
+}
--- /dev/null 2017-11-08 15:39:54.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/MenuOwner.java 2017-11-08 15:39:54.000000000 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ * The interface gives an access to a menu, such as menu bar or a popup menu.
+ * Things like windows or menu bars may support such control interface.
+ * @author shura
+ */
+public interface MenuOwner extends TypeControlInterface {
+ /**
+ * Actual menu.
+ * @return
+ */
+ @Shortcut
+ public Menu menu();
+}
--- /dev/null 2017-11-08 15:39:54.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/MenuSelectable.java 2017-11-08 15:39:54.000000000 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * Represents a hierarchical structure in which elements not only could be
+ * selected but also "pushes", which is an action typically performed with
+ * menu.
+ *
+ * @author erikgreijus
+ * @param
+ */
+public interface MenuSelectable extends Menu {
+
+ /**
+ * Ensures state of a menu item conforming to the criteria. That would mean
+ * that all intermediate items get expanded and the menus are shown.
+ * Selection depends on if the desired state matches the current state or
+ * not. I.e selection of the last criteria happens only if the state differs
+ * from desiredSelectionState
+ *
+ * @param desiredSelectionState The desired selection state of the leaf menu
+ * item.
+ * @param criteria used one for one level. In case of a menu bar, for
+ * example, first criteria is to be used to find a top level menu, second to
+ * - find a menu underneath, etc.
+ */
+ public void push(boolean desiredSelectionState, LookupCriteria... criteria);
+
+ /**
+ * Returns the current selection state of the menu item conforming to the
+ * criteria. That would mean that all intermediate items get expanded and
+ * the menus are shown.
+ *
+ * @param criteria used one for one level. In case of a menu bar, for
+ * example, first criteria is to be used to find a top level menu, second to
+ * - find a menu underneath, etc.
+ * @return True if the menu item is selected. Otherwise false.
+ */
+ public boolean getState(LookupCriteria... criteria);
+}
--- /dev/null 2017-11-08 15:39:55.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/MenuSelectableOwner.java 2017-11-08 15:39:55.000000000 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author erikgreijus
+ * @param
+ */
+public interface MenuSelectableOwner extends MenuOwner {
+
+ @Override
+ public MenuSelectable menu();
+}
--- /dev/null 2017-11-08 15:39:55.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Modifier.java 2017-11-08 15:39:55.000000000 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+
+/**
+ *
+ * @author Alexander Kouznetsov
+ */
+public interface Modifier extends Button {
+
+}
--- /dev/null 2017-11-08 15:39:55.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Mouse.java 2017-11-08 15:39:55.000000000 -0800
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+
+import org.jemmy.Point;
+import org.jemmy.dock.Shortcut;
+import org.jemmy.env.Timeout;
+
+/**
+ *
+ * @author shura
+ */
+public interface Mouse extends ControlInterface {
+ /**
+ *
+ */
+ public static final Timeout CLICK = new Timeout("mouse.click", 100);
+ /**
+ *
+ */
+ @Shortcut
+ public void press();
+ /**
+ *
+ * @param button
+ */
+ @Shortcut
+ public void press(MouseButton button);
+ /**
+ *
+ * @param button
+ * @param modifiers
+ */
+ @Shortcut
+ public void press(MouseButton button, Modifier... modifiers);
+ /**
+ *
+ */
+ @Shortcut
+ public void release();
+ /**
+ *
+ * @param button
+ */
+ @Shortcut
+ public void release(MouseButton button);
+ /**
+ *
+ * @param button
+ * @param modifiers
+ */
+ @Shortcut
+ public void release(MouseButton button, Modifier... modifiers);
+ /**
+ *
+ */
+ @Shortcut
+ public void move();
+ /**
+ *
+ * @param p
+ */
+ @Shortcut
+ public void move(Point p);
+ /**
+ *
+ */
+ @Shortcut
+ public void click();
+ /**
+ *
+ * @param count
+ */
+ @Shortcut
+ public void click(int count);
+ /**
+ *
+ * @param count
+ * @param p
+ */
+ @Shortcut
+ public void click(int count, Point p);
+ /**
+ *
+ * @param count
+ * @param p
+ * @param button
+ */
+ @Shortcut
+ public void click(int count, Point p, MouseButton button);
+ /**
+ *
+ * @param count
+ * @param p
+ * @param button
+ * @param modifiers
+ */
+ @Shortcut
+ public void click(int count, Point p, MouseButton button, Modifier... modifiers);
+
+ /*
+ * This method turns mouse wheel.
+ * @parem amount Positive or negative
+ */
+ @Shortcut
+ public void turnWheel(int amount);
+
+ /*
+ * This method turns mouse wheel.
+ * @parem amount Positive or negative
+ */
+ @Shortcut
+ public void turnWheel(Point point, int amount);
+
+ /*
+ * This method turns mouse wheel.
+ * @parem amount Positive or negative
+ */
+ @Shortcut
+ public void turnWheel(Point point, int amount, Modifier... modifiers);
+
+ /**
+ * Detaches the implementation so that all actions of it will be ran detached.
+ * @see org.jemmy.action.ActionExecutor#executeDetached(org.jemmy.env.Environment, org.jemmy.action.Action, java.lang.Object[])
+ * @return
+ */
+ public Mouse detached();
+
+ /**
+ * Mouse button interface (i. e. BUTTON1, BUTTON2, etc.)
+ * created to left the possibility for extention as enums can't be extended
+ */
+ public static interface MouseButton extends Button {
+
+ }
+
+ /**
+ * Mouse modifier interface (i. e. BUTTON1_DOWN_MASK)
+ * created to left the possibility for extention as enums can't be extended
+ */
+ public static interface MouseModifier extends Modifier {
+
+ }
+
+ /**
+ * Mouse modifiers enum (i. e. BUTTON1_DOWN_MASK)
+ * to be used in Keyboard interface methods
+ */
+ public static enum MouseModifiers implements MouseModifier {
+
+ /**
+ *
+ */
+ BUTTON1_DOWN_MASK,
+ /**
+ *
+ */
+ BUTTON2_DOWN_MASK,
+ /**
+ *
+ */
+ BUTTON3_DOWN_MASK
+ }
+
+ /**
+ * Mouse Buttons
+ */
+ public static enum MouseButtons implements MouseButton {
+ /**
+ *
+ */
+ BUTTON1,
+ /**
+ *
+ */
+ BUTTON2,
+ /**
+ *
+ */
+ BUTTON3
+ }
+
+}
--- /dev/null 2017-11-08 15:39:56.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Parent.java 2017-11-08 15:39:56.000000000 -0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.lookup.Lookup;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * Represents a container for UI controls.
+ * @param type of the control.
+ * @author shura
+ */
+public interface Parent extends TypeControlInterface {
+ /**
+ * Searcher the hierarchy for objects extending ST
which fit
+ * the criteria.
+ * @see Lookup
+ * @see LookupCriteria
+ * @param
+ * @param controlClass
+ * @param criteria
+ * @return an instance of Lookup, which holds found controls.
+ */
+ public Lookup lookup(Class controlClass, LookupCriteria criteria);
+ /**
+ * Same as lookup(controlClass, new Any())
+ * @see #lookup(java.lang.Class, org.jemmy.lookup.LookupCriteria)
+ * @param
+ * @param controlClass
+ * @return an instance of Lookup, which holds found controls.
+ */
+ public Lookup lookup(Class controlClass);
+ /**
+ * Searcher the hierarchy for objects extending T
which fit
+ * the criteria.
+ * @see Lookup
+ * @see LookupCriteria
+ * @param criteria
+ * @return an instance of Lookup, which holds found controls.
+ */
+ public Lookup lookup(LookupCriteria criteria);
+ /**
+ * Same as lookup(new Any())
+ * @see #lookup(org.jemmy.lookup.LookupCriteria)
+ * @return an instance of Lookup, which holds found controls.
+ */
+ public Lookup lookup();
+}
--- /dev/null 2017-11-08 15:39:56.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/PopupOwner.java 2017-11-08 15:39:56.000000000 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.jemmy.interfaces;
+
+import org.jemmy.Point;
+import org.jemmy.dock.Shortcut;
+
+
+/**
+ *
+ * @author shura
+ */
+public interface PopupOwner extends TypeControlInterface {
+ public static final Point CENTER = null;
+ @Shortcut
+ public Menu menu(Point p);
+}
--- /dev/null 2017-11-08 15:39:56.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/PopupSelectableOwner.java 2017-11-08 15:39:56.000000000 -0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.Point;
+
+/**
+ *
+ * @author erikgreijus
+ * @param
+ */
+public interface PopupSelectableOwner extends PopupOwner {
+
+ @Override
+ public MenuSelectable menu(Point p);
+}
--- /dev/null 2017-11-08 15:39:57.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Scroll.java 2017-11-08 15:39:57.000000000 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.jemmy.interfaces;
+
+import org.jemmy.control.Property;
+import org.jemmy.control.Wrap;
+
+/**
+ * Interface representing an object which represents an integer value which
+ * could be increased or decreased, such as scroll bar, slider, etc.
+ * @author shura
+ */
+public interface Scroll extends CaretOwner {
+ /**
+ *
+ */
+ public static final String VERTICAL_PROP_NAME = "vertical";
+ /**
+ *
+ */
+ public static final String MAXIMUM_PROP_NAME = "maximum";
+ /**
+ *
+ */
+ public static final String MINIMUM_PROP_NAME = "minimum";
+ /**
+ * TODO javadoc
+ * @return
+ */
+ @Property(MAXIMUM_PROP_NAME)
+ public double maximum();
+ /**
+ *
+ * @return
+ */
+ @Property(MINIMUM_PROP_NAME)
+ public double minimum();
+}
--- /dev/null 2017-11-08 15:39:57.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Selectable.java 2017-11-08 15:39:57.000000000 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import java.util.List;
+import org.jemmy.control.Property;
+import org.jemmy.dock.Shortcut;
+
+/**
+ * Interface for a control with one selected state among the number of them.
+ * @param
+ * @author shura, KAM
+ */
+public interface Selectable extends TypeControlInterface {
+
+ /**
+ *
+ */
+ public static final String STATES_PROP_NAME = "states";
+ public static final String STATE_PROP_NAME = "state";
+
+ /**
+ * Returns all available states.
+ * @return List of all states.
+ */
+ @Property(STATES_PROP_NAME)
+ public List getStates();
+
+ /**
+ * Returns currently selected state.
+ * @return Selected state.
+ */
+ @Property(STATE_PROP_NAME)
+ public STATE getState();
+
+ /**
+ * Returns Selector class instance that has methods to select state.
+ * @return Selector class instance for the control.
+ */
+ @Shortcut
+ public Selector selector();
+
+}
--- /dev/null 2017-11-08 15:39:57.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Selector.java 2017-11-08 15:39:57.000000000 -0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @param
+ * @author shura
+ */
+public interface Selector {
+ /**
+ *
+ * @param state
+ */
+ public void select(STATE state);
+}
--- /dev/null 2017-11-08 15:39:58.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Show.java 2017-11-08 15:39:58.000000000 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author shura
+ */
+public interface Show {
+ /**
+ *
+ */
+ public void show();
+}
--- /dev/null 2017-11-08 15:39:58.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Showable.java 2017-11-08 15:39:58.000000000 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Showable extends ControlInterface {
+ /**
+ *
+ * @return
+ */
+ @Shortcut
+ public Show shower();
+}
--- /dev/null 2017-11-08 15:39:58.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Text.java 2017-11-08 15:39:58.000000000 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Text extends Label {
+ /**
+ * Supposed to type a new value from current position.
+ * @param newText
+ */
+ @Shortcut
+ public void type(String newText);
+ /**
+ * Clears all the text content.
+ */
+ @Shortcut
+ public void clear();
+}
--- /dev/null 2017-11-08 15:39:59.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/TextInput.java 2017-11-08 15:39:59.000000000 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author shura
+ */
+public interface TextInput {
+ /**
+ *
+ */
+ public void clear();
+ /**
+ *
+ * @param text
+ */
+ public void type(String text);
+}
--- /dev/null 2017-11-08 15:39:59.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Tree.java 2017-11-08 15:39:59.000000000 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Tree extends TypeControlInterface {
+ @Shortcut
+ public TreeSelector selector();
+}
--- /dev/null 2017-11-08 15:39:59.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/TreeItem.java 2017-11-08 15:39:59.000000000 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+/**
+ *
+ * @author shura
+ */
+public interface TreeItem extends TypeControlInterface, Expandable, Collapsible {
+}
--- /dev/null 2017-11-08 15:40:00.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/TreeSelector.java 2017-11-08 15:40:00.000000000 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.control.Wrap;
+import org.jemmy.lookup.LookupCriteria;
+
+/**
+ * Represents a way to select an item within a hierarchy. Could be applied to
+ * anything from tree to menu.
+ * @author shura
+ */
+public interface TreeSelector {
+ /**
+ * Selects an item. All implementations are assumed to perform all necessary
+ * waiting for nodes to be expanded and the sub nodes shown, etc.
+ * @param criteria used one per level.
+ * @return a wrap for the last item, whatever it is
+ */
+ public abstract Wrap extends T> select(LookupCriteria... criteria);
+}
--- /dev/null 2017-11-08 15:40:00.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/TypeControlInterface.java 2017-11-08 15:40:00.000000000 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.interfaces;
+
+import org.jemmy.dock.Shortcut;
+
+/**
+ * TODO: JavaDoc
+ * @param
+ * @author shura
+ */
+public interface TypeControlInterface extends ControlInterface {
+ /**
+ *
+ * @return
+ */
+ public Class getType();
+}
--- /dev/null 2017-11-08 15:40:00.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/interfaces/Window.java 2017-11-08 15:40:00.000000000 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.jemmy.interfaces;
+
+import org.jemmy.Dimension;
+import org.jemmy.Point;
+import org.jemmy.dock.Shortcut;
+
+/**
+ *
+ * @author shura
+ */
+public interface Window extends ControlInterface {
+
+ /**
+ *
+ */
+ public enum Direction {
+
+ /**
+ *
+ */
+ NORTHEAST,
+ /**
+ *
+ */
+ SOUTHEAST,
+ /**
+ *
+ */
+ SOUTHWEST,
+ /**
+ *
+ */
+ NORTHWEST
+ };
+ /**
+ *
+ * @param dest
+ */
+ @Shortcut
+ public void move(Point dest);
+ /**
+ *
+ * @param size
+ * @param direction
+ */
+ @Shortcut
+ public void resize(Dimension size, Direction direction);
+}
--- /dev/null 2017-11-08 15:40:01.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/jemmy.properties 2017-11-08 15:40:01.000000000 -0800
@@ -0,0 +1,3 @@
+version.major=1
+version.minor=0
+version.mini=0
--- /dev/null 2017-11-08 15:40:01.000000000 -0800
+++ new/core/JemmyCore/src/org/jemmy/lookup/AbstractLookup.java 2017-11-08 15:40:01.000000000 -0800
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy.lookup;
+
+import java.io.PrintStream;
+import java.util.List;
+import org.jemmy.interfaces.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import org.jemmy.control.Wrap;
+import org.jemmy.control.Wrapper;
+import org.jemmy.env.Environment;
+import org.jemmy.env.TestOut;
+import org.jemmy.timing.State;
+
+/**
+ * Default implementation of Lookup. Regularly, it is enough just override this
+ * implementation and allow it to handle sub-lookups creation.
+ * @see AbstractLookup#lookup(org.jemmy.lookup.LookupCriteria)
+ * @see AbstractLookup#lookup(java.lang.Class, org.jemmy.lookup.LookupCriteria)
+ * @param
+ * @author shura
+ */
+public abstract class AbstractLookup extends AbstractParent implements Lookup {
+
+ static final String PREFIX_DELTA = "| ";
+ private ArrayList found;
+ Environment env;
+ private Class clss;
+ private LookupCriteria