package cn.com.jautoitx;
import org.apache.commons.lang3.StringUtils;
import com.sun.jna.platform.win32.WinDef.HWND;
/**
* Build control id base on Advanced Control Descriptions.
*
* @author zhengbo.wang
*/
public class ControlIdBuilder {
private ControlIdBuilder() {
// Do nothing
}
/**
* Build control id base on Advanced Control Descriptions.
*
* @param bys
* Selectors to build advanced control id.
* @return Returns advanced control id.
*/
public static String by(By... bys) {
StringBuilder controlId = new StringBuilder();
controlId.append('[');
String separator = "";
for (int i = 0; i < bys.length; i++) {
controlId.append(separator);
String strBy = bys[i].toAdvancedControlId();
if (StringUtils.isNotEmpty(strBy)) {
controlId.append(strBy);
separator = "; ";
}
}
controlId.append(']');
return controlId.toString();
}
/**
* Build control id base on the internal control ID.
*
* @param id
* The internal control ID. The Control ID is the internal
* numeric identifier that windows gives to each control. It is
* generally the best method of identifying controls. In addition
* to the AutoIt Window Info Tool, other applications such as
* screenreaders for the blind and Microsoft tools/APIs may allow
* you to get this Control ID.
* @return Returns advanced control id.
*/
public static String byId(int id) {
return by(By.id(id));
}
/**
* Build control id base on the text on a control.
*
* @param text
* The text on a control, for example "&Next" on a button.
* @return a By which locates control by the text on a control.
* @return Returns advanced control id.
*/
public static String byText(String text) {
return by(By.text(text));
}
/**
* Build control id base on the internal control classname.
*
* @param className
* The internal control classname such as "Edit" or "Button".
* @return Returns advanced control id.
*/
public static String byClassName(String className) {
return by(By.className(className));
}
/**
* Build control id base on the ClassnameNN.
*
* @param classNameNN
* The ClassnameNN value as used in previous versions of AutoIt,
* such as "Edit1".
* @return Returns advanced control id.
*/
public static String byClassNameNN(String classNameNN) {
return by(By.classNameNN(classNameNN));
}
/**
* Build control id base on the internal .NET Framework WinForms name.
*
* @param name
* The internal .NET Framework WinForms name (if available).
* @return Returns advanced control id.
*/
public static String byName(String name) {
return by(By.name(name));
}
/**
* Build control id base on the control classname using a regular
* expression.
*
* @param regexpClassName
* Control classname using a regular expression.
* @return Returns advanced control id.
*/
public static String byRegexpClassName(String regexpClassName) {
return by(By.regexpClassName(regexpClassName));
}
/**
* Build control id base on the the position and size of a control. All
* parameters are optional.
*
* @param x
* Optional, the X coordinate of the control.
* @param y
* Optional, the Y coordinate of the control.
* @param width
* Optional, the width of the control.
* @param height
* Optional, the height of the control.
* @return Returns advanced control id.
*/
public static String byBounds(Integer x, Integer y, Integer width,
Integer height) {
return by(By.bounds(x, y, width, height));
}
/**
* Build control id base on the the position of a control. All parameters
* are optional.
*
* @param x
* Optional, the X coordinate of the control.
* @param y
* Optional, the Y coordinate of the control.
* @return Returns advanced control id.
*/
public static String byPosition(Integer x, Integer y) {
return by(By.position(x, y));
}
/**
* Build control id base on the the size of a control. All parameters are
* optional.
*
* @param width
* Optional, the width of the control.
* @param height
* Optional, the height of the control.
* @return Returns advanced control id.
*/
public static String bySize(Integer width, Integer height) {
return by(By.size(width, height));
}
/**
* Build control id base on the 1-based instance when all given properties
* match.
*
* @param instance
* The 1-based instance when all given properties match.
* @return Returns advanced control id.
*/
public static String byInstance(int instance) {
return by(By.instance(instance));
}
/**
* Build control id base on the handle address as returned by a method like
* Control.getHandle.
*
* @param handle
* The handle address as returned by a method like
* Control.getHandle.
* @return Returns advanced control id.
*/
public static String byHandle(String handle) {
return by(By.handle(handle));
}
/**
* Build control id base on the handle address as returned by a method like
* Control.getHandle_.
*
* @param hCtrl
* The handle address as returned by a method like
* Control.getHandle_.
* @return Returns advanced control id.
*/
public static String byHandle(HWND hCtrl) {
return by(By.handle(hCtrl));
}
/**
* Selector to build advanced control id.
*
* @author zhengbo.wang
*/
public static abstract class By {
protected final String property;
protected final String value;
public By(final String property) {
this.property = property;
this.value = null;
}
public By(final String property, final String value) {
this.property = property;
this.value = StringUtils.defaultString(value);
}
/**
* @param id
* The internal control ID. The Control ID is the internal
* numeric identifier that windows gives to each control. It
* is generally the best method of identifying controls. In
* addition to the AutoIt Window Info Tool, other
* applications such as screenreaders for the blind and
* Microsoft tools/APIs may allow you to get this Control ID.
* @return a By which locates control by the internal control ID.
*/
public static By id(int id) {
return new ById(id);
}
/**
* @param text
* The text on a control, for example "&Next" on a button.
* @return a By which locates control by the text on a control.
*/
public static By text(String text) {
return new ByText(text);
}
/**
* @param className
* The internal control classname such as "Edit" or "Button".
* @return a By which locates control by the internal control classname.
*/
public static By className(String className) {
return new ByClass(className);
}
/**
* @param classNameNN
* The ClassnameNN value as used in previous versions of
* AutoIt, such as "Edit1".
* @return a By which locates control by the internal control
* ClassnameNN.
*/
public static By classNameNN(String classNameNN) {
return new ByClassNN(classNameNN);
}
/**
* @param name
* The internal .NET Framework WinForms name (if available).
* @return a By which locates control by the internal .NET Framework
* WinForms name.
*/
public static By name(String name) {
return new ByName(name);
}
/**
* @param regexpClassName
* Control classname using a regular expression.
* @return a By which locates control by the control classname using a
* regular expression.
*/
public static By regexpClassName(String regexpClassName) {
return new ByRegexpClass(regexpClassName);
}
/**
* All parameters are optional.
*
* @param x
* Optional, the X coordinate of the control.
* @param y
* Optional, the Y coordinate of the control.
* @param width
* Optional, the width of the control.
* @param height
* Optional, the height of the control.
* @return a By which locates control by the position and size of a
* control.
*/
public static By bounds(Integer x, Integer y, Integer width,
Integer height) {
return new ByBounds(x, y, width, height);
}
/**
* All parameters are optional.
*
* @param x
* Optional, the X coordinate of the control.
* @param y
* Optional, the Y coordinate of the control.
* @return a By which locates control by the position of a control.
*/
public static By position(Integer x, Integer y) {
return bounds(x, y, null, null);
}
/**
* All parameters are optional.
*
* @param width
* Optional, the width of the control.
* @param height
* Optional, the height of the control.
* @return a By which locates control by the size of a control.
*/
public static By size(Integer width, Integer height) {
return bounds(null, null, width, height);
}
/**
* @param instance
* The 1-based instance when all given properties match.
* @return a By which locates control by the 1-based instance when all
* given properties match.
*/
public static By instance(int instance) {
return new ByInstance(instance);
}
/**
* @param handle
* The handle address as returned by a method like
* Control.getHandle.
* @return a By which locates control by the handle address as returned
* by a method like Control.getHandle.
*/
public static By handle(String handle) {
return new ByHandle(handle);
}
/**
* @param hCtrl
* The handle address as returned by a method like
* Control.getHandle_.
* @return a By which locates control by the handle address as returned
* by a method like Control.getHandle.
*/
public static By handle(HWND hCtrl) {
return new ByHandle(hCtrl);
}
public String toAdvancedControlId() {
StringBuilder advancedTitle = new StringBuilder();
advancedTitle.append(property);
if (value != null) {
advancedTitle.append(':');
for (int i = 0; i < value.length(); i++) {
char ch = value.charAt(i);
advancedTitle.append(ch);
// Note: if a Value must contain a ";" it must be doubled.
if (ch == ';') {
advancedTitle.append(';');
}
}
}
return advancedTitle.toString();
}
@Override
public String toString() {
return "By." + property + ": " + value;
}
}
/**
* The internal control ID. The Control ID is the internal numeric
* identifier that windows gives to each control. It is generally the best
* method of identifying controls. In addition to the AutoIt Window Info
* Tool, other applications such as screenreaders for the blind and
* Microsoft tools/APIs may allow you to get this Control ID.
*
* @author zhengbo.wang
*/
public static class ById extends By {
public ById(int id) {
super("ID", String.valueOf(id));
}
}
/**
* The text on a control, for example "&Next" on a button.
*
* @author zhengbo.wang
*/
public static class ByText extends By {
public ByText(String text) {
super("TEXT", text);
}
}
/**
* The internal control classname such as "Edit" or "Button".
*
* @author zhengbo.wang
*/
public static class ByClass extends By {
public ByClass(String clazz) {
super("CLASS", clazz);
}
}
/**
* The ClassnameNN value as used in previous versions of AutoIt, such as
* "Edit1".
*
* @author zhengbo.wang
*/
public static class ByClassNN extends By {
public ByClassNN(String classNN) {
super("CLASSNN", classNN);
}
}
/**
* The internal .NET Framework WinForms name (if available).
*
* @author zhengbo.wang
*/
public static class ByName extends By {
public ByName(String name) {
super("NAME", name);
}
}
/**
* Control classname using a regular expression.
*
* @author zhengbo.wang
*/
public static class ByRegexpClass extends By {
public ByRegexpClass(String regexpClass) {
super("REGEXPCLASS", regexpClass);
}
}
/**
* The position and size of a control.
*
* @author zhengbo.wang
*/
public static class ByBounds extends By {
private final Integer x;
private final Integer y;
private final Integer width;
private final Integer height;
public ByBounds(Integer x, Integer y, Integer width, Integer height) {
super("POSITION AND SIZE", String.format("%s \\ %s \\ %s \\ %s",
String.valueOf(x), String.valueOf(y),
String.valueOf(width), String.valueOf(height)));
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
@Override
public String toAdvancedControlId() {
// see http://www.autoitscript.com/forum/topic/90848-x-y-w-h/
StringBuilder advancedTitle = new StringBuilder();
if (x != null) {
advancedTitle.append("X:").append(x);
}
if (y != null) {
if (StringUtils.isNotEmpty(advancedTitle.toString())) {
advancedTitle.append("\\");
}
advancedTitle.append("Y:").append(y);
}
if (width != null) {
if (StringUtils.isNotEmpty(advancedTitle.toString())) {
advancedTitle.append("\\");
}
advancedTitle.append("W:").append(width);
}
if (height != null) {
if (StringUtils.isNotEmpty(advancedTitle.toString())) {
advancedTitle.append("\\");
}
advancedTitle.append("H:").append(height);
}
return advancedTitle.toString();
}
}
/**
* The 1-based instance when all given properties match.
*
* @author zhengbo.wang
*/
public static class ByInstance extends By {
public ByInstance(int instance) {
super("INSTANCE", String.valueOf(instance));
}
}
/**
* The handle address as returned by a method like Control.getHandle or
* Control.getHandle_.
*
* @author zhengbo.wang
*/
public static class ByHandle extends By {
public ByHandle(String handle) {
super("HANDLE", handle);
}
public ByHandle(HWND hCtrl) {
this(AutoItX.hwndToHandle(hCtrl));
}
@Override
public String toAdvancedControlId() {
return new ById(Win32.getControlId(AutoItX.handleToHwnd(value)))
.toAdvancedControlId();
}
}
}