|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| ComponentLocation.java | 64.3% | 79.4% | 92.9% | 79% |
|
||||||||||||||
| 1 |
package abbot.tester;
|
|
| 2 |
|
|
| 3 |
import java.awt.*;
|
|
| 4 |
import java.util.StringTokenizer;
|
|
| 5 |
|
|
| 6 |
import abbot.i18n.Strings;
|
|
| 7 |
|
|
| 8 |
/** Provides encapsulation of a visible Component-relative location.
|
|
| 9 |
* "Visible" in this context means currently accessible by the pointer
|
|
| 10 |
* (possibly via scrolling). A hidden node in a collapsed tree path
|
|
| 11 |
* would <strong>not</strong> be considered visible.
|
|
| 12 |
* <p>
|
|
| 13 |
* This class the specifics of location so that {@link ComponentTester}
|
|
| 14 |
* primitives
|
|
| 15 |
* ({@link ComponentTester#actionClick(Component,ComponentLocation)},
|
|
| 16 |
* {@link ComponentTester#actionShowPopupMenu(Component,ComponentLocation)},
|
|
| 17 |
* etc) may be directed to specific elements of
|
|
| 18 |
* substructure on a <code>Component</code> (list rows, tree paths, table
|
|
| 19 |
* cells, substructure values, etc.).
|
|
| 20 |
* <p>
|
|
| 21 |
* Classes derived from <code>ComponentLocation</code> should provide
|
|
| 22 |
* constructors for each type of location indication, e.g. value, index, and
|
|
| 23 |
* {@link Point}. The {@link #toString()} method should provide an encoded
|
|
| 24 |
* {@link String} suitable for use by the {@link #parse(String)} method, which
|
|
| 25 |
* must convert the {@link String} encoding back into a proper
|
|
| 26 |
* <code>ComponentLocation</code>.
|
|
| 27 |
* <p>
|
|
| 28 |
* By convention, {@link Point} locations are specified with (x,y) notation.
|
|
| 29 |
* Indexed locations should use square brackets, e.g. [i] or [r,c] and
|
|
| 30 |
* value locations should use a quoted {@link String}, e.g.
|
|
| 31 |
* '"cuckoo for cocoa puffs"'. The specific syntax allowed will vary by
|
|
| 32 |
* specific <code>ComponentLocation</code> type. The base
|
|
| 33 |
* <code>ComponentLocation</code> implementation
|
|
| 34 |
* supports only the explicit (x,y) notation.
|
|
| 35 |
* <p>
|
|
| 36 |
* Recorders
|
|
| 37 |
* should use the {@link String} value by default for consistency. The
|
|
| 38 |
* special value {@link #CENTER} is provided to indicate the center of a
|
|
| 39 |
* {@link Component}.
|
|
| 40 |
* <p>
|
|
| 41 |
* The method {@link #badFormat(String)} should provide usage-like information
|
|
| 42 |
* indicating the acceptable forms of input for this class.
|
|
| 43 |
*
|
|
| 44 |
* @see JListLocation
|
|
| 45 |
* @see JTreeLocation
|
|
| 46 |
* @see JTableLocation
|
|
| 47 |
*/
|
|
| 48 |
public class ComponentLocation { |
|
| 49 |
|
|
| 50 |
/** Special <code>ComponentLocation</code> encoding which represents
|
|
| 51 |
the center of the component.
|
|
| 52 |
*/
|
|
| 53 |
public static final String CENTER = "(center)"; |
|
| 54 |
|
|
| 55 |
private Point where = null; |
|
| 56 |
|
|
| 57 |
/** Create a simple location which represents the center of a component. */
|
|
| 58 | 350 |
public ComponentLocation() { }
|
| 59 |
|
|
| 60 |
/** Create a simple location. */
|
|
| 61 | 113 |
public ComponentLocation(Point where) {
|
| 62 | 113 |
this.where = new Point(where); |
| 63 |
} |
|
| 64 |
|
|
| 65 |
/** Convert the abstract location into a concrete one. Returns
|
|
| 66 |
* a {@link Point} relative to the given {@link Component}.
|
|
| 67 |
*/
|
|
| 68 | 161 |
public Point getPoint(Component c)
|
| 69 |
throws LocationUnavailableException {
|
|
| 70 | 161 |
return where != null |
| 71 |
? new Point(where) : new Point(c.getWidth()/2, c.getHeight()/2); |
|
| 72 |
} |
|
| 73 |
|
|
| 74 |
/** Convert the abstract location into a concrete area, relative
|
|
| 75 |
* to the given <code>Component</code>. If a point has
|
|
| 76 |
* been specified, returns a 1x1 rectangle, otherwise returns the
|
|
| 77 |
* a rectangle at (0, 0) of the Component's size.
|
|
| 78 |
*/
|
|
| 79 | 117 |
public Rectangle getBounds(Component c)
|
| 80 |
throws LocationUnavailableException {
|
|
| 81 | 117 |
if (where == null) |
| 82 | 53 |
return new Rectangle(0, 0, c.getWidth(), c.getHeight()); |
| 83 | 64 |
return new Rectangle(where.x, where.y, 1, 1); |
| 84 |
} |
|
| 85 |
|
|
| 86 |
/** Returns whether the given object is an equivalent
|
|
| 87 |
* <code>ComponentLocation</code>.
|
|
| 88 |
*/
|
|
| 89 | 9 |
public boolean equals(Object o) { |
| 90 | 9 |
if (o instanceof ComponentLocation) { |
| 91 | 9 |
ComponentLocation loc = (ComponentLocation)o; |
| 92 | 9 |
return (where == null && loc.where == null) |
| 93 |
|| (where != null && where.equals(loc.where));
|
|
| 94 |
} |
|
| 95 | 0 |
return false; |
| 96 |
} |
|
| 97 |
|
|
| 98 | 13 |
public String toString() {
|
| 99 | 13 |
if (where != null) |
| 100 | 13 |
return "(" + where.x + "," + where.y + ")"; |
| 101 | 0 |
return CENTER;
|
| 102 |
} |
|
| 103 |
|
|
| 104 | 0 |
protected String badFormat(String encoded) {
|
| 105 | 0 |
return Strings.get("location.component.bad_format", |
| 106 |
new Object[] { encoded });
|
|
| 107 |
} |
|
| 108 |
|
|
| 109 | 4 |
protected String encodeIndex(int index) { |
| 110 | 4 |
return "[" + index + "]"; |
| 111 |
} |
|
| 112 |
|
|
| 113 |
/** Returns whether the given (trimmed) <code>String</code> is an encoded
|
|
| 114 |
index.
|
|
| 115 |
*/
|
|
| 116 | 19 |
protected boolean isIndex(String encoded) { |
| 117 | 19 |
return encoded.startsWith("[") && encoded.endsWith("]"); |
| 118 |
} |
|
| 119 |
|
|
| 120 |
/** Extract the encoded index. */
|
|
| 121 | 11 |
protected int parseIndex(String encoded) { |
| 122 | 11 |
try {
|
| 123 | 11 |
return Integer.parseInt(encoded.
|
| 124 |
substring(1, encoded.length()-1).trim()); |
|
| 125 |
} |
|
| 126 |
catch(NumberFormatException e) {
|
|
| 127 | 0 |
throw new IllegalArgumentException(badFormat(encoded)); |
| 128 |
} |
|
| 129 |
} |
|
| 130 |
|
|
| 131 | 44 |
protected String encodeValue(String value) {
|
| 132 | 44 |
return "\"" + value + "\""; |
| 133 |
} |
|
| 134 |
|
|
| 135 |
/** Returns whether the given (trimmed) <code>String</code> is an encoded
|
|
| 136 |
value.
|
|
| 137 |
*/
|
|
| 138 | 23 |
protected boolean isValue(String encoded) { |
| 139 | 23 |
return encoded.startsWith("\"") && encoded.endsWith("\""); |
| 140 |
} |
|
| 141 |
|
|
| 142 |
/** Extract the encoded value. */
|
|
| 143 | 7 |
protected String parseValue(String encoded) {
|
| 144 | 7 |
return encoded.substring(1, encoded.length()-1);
|
| 145 |
} |
|
| 146 |
|
|
| 147 |
/** Convert the given encoding into the proper location.
|
|
| 148 |
Allowed formats: (x, y)
|
|
| 149 |
<p>
|
|
| 150 |
*/
|
|
| 151 | 9 |
public ComponentLocation parse(String encoded) {
|
| 152 | 9 |
encoded = encoded.trim(); |
| 153 | 9 |
if (encoded.equals(CENTER)) {
|
| 154 | 0 |
where = null;
|
| 155 | 0 |
return this; |
| 156 |
} |
|
| 157 | 9 |
if (encoded.startsWith("(") && encoded.endsWith(")")) { |
| 158 | 9 |
StringTokenizer st = |
| 159 |
new StringTokenizer(encoded.substring(1, encoded.length()-1),
|
|
| 160 |
",");
|
|
| 161 | 9 |
if (st.countTokens() == 2) {
|
| 162 | 9 |
try {
|
| 163 | 9 |
int x = Integer.parseInt(st.nextToken().trim());
|
| 164 | 9 |
int y = Integer.parseInt(st.nextToken().trim());
|
| 165 | 9 |
where = new Point(x, y);
|
| 166 | 9 |
return this; |
| 167 |
} |
|
| 168 |
catch(NumberFormatException nfe) {
|
|
| 169 |
} |
|
| 170 |
} |
|
| 171 |
} |
|
| 172 | 0 |
throw new IllegalArgumentException(badFormat(encoded)); |
| 173 |
} |
|
| 174 |
} |
|
| 175 |
|
|
||||||||||