package org.rsbot.script.wrappers; import org.rsbot.client.Client; import org.rsbot.script.methods.MethodContext; import org.rsbot.script.methods.MethodProvider; import java.awt.*; import java.util.Arrays; import java.util.Iterator; /** * Represents an interface. Each interface consists * of a group of components. * * @author Qauters */ public class RSInterface extends MethodProvider implements Iterable<RSComponent> { /** * Cache of this interface's children. */ private RSComponent[] childCache = new RSComponent[0]; private final Object childLock = new Object(); /** * The index of this interface. */ private final int index; public RSInterface(final MethodContext ctx, final int iface) { super(ctx); index = iface; } /** * Searches all it's actions, to find your phrase * * @param phrase Text to search for * @return true if found */ public boolean containsAction(final String phrase) { for (final RSComponent child : getComponents()) { if (child == null) { continue; } if (child.getActions() == null) { return false; } for (final String action : child.getActions()) { if (action == null) { continue; } if (action.toLowerCase().contains(phrase.toLowerCase())) { return true; } } } return false; } /** * Searches all components' text. * * @param phrase Text to search for * @return true if found, false if null */ public boolean containsText(final String phrase) { return getText().contains(phrase); } /** * Gets the amount of child components. * * @return the amount of children, or 0 if null */ public int getChildCount() { final org.rsbot.client.RSInterface[] children = getChildrenInternal(); if (children != null) { return children.length; } return 0; } /** * Gets the child component at the given index. * * @param id The index of the child. * @return The child component. */ public RSComponent getComponent(final int id) { // TODO sparseMap synchronized (childCache) { final org.rsbot.client.RSInterface[] children = getChildrenInternal(); final int ensureLen = Math.max(children != null ? children.length : 0, id + 1); if (childCache.length < ensureLen) { // extend if necessary final int prevLen = childCache.length; childCache = Arrays.copyOf(childCache, ensureLen); for (int i = prevLen; i < ensureLen; i++) { childCache[i] = new RSComponent(methods, this, i); } } return childCache[id]; } } /** * Gets all child components of this interface. * * @return the component array */ public RSComponent[] getComponents() { synchronized (childLock) { final org.rsbot.client.RSInterface[] children = getChildrenInternal(); if (children == null) { return childCache.clone(); // return as is } else { if (childCache.length < children.length) { // extend if necessary final int prevLen = childCache.length; childCache = Arrays.copyOf(childCache, children.length); for (int i = prevLen; i < childCache.length; i++) { childCache[i] = new RSComponent(methods, this, i); } } return childCache.clone(); } } } /** * Gets the index of this interface. * * @return The index of this interface. */ public int getIndex() { return index; } /** * Gets the screen location of the interface. * * @return the exact location of the interface, return (-1, -1) if * interface was null. */ public Point getLocation() { final org.rsbot.client.RSInterface[] children = getChildrenInternal(); if (children != null) { for (final org.rsbot.client.RSInterface child : children) { if (child != null) { if (child.getMasterX() != -1 && child.getMasterY() != -1) { return new Point(child.getMasterX(), child.getMasterY()); } } } } return new Point(-1, -1); } /** * Finds all the text in it, searches all his children for it. * * @return all the text found separated by newlines, empty if null */ public String getText() { final StringBuilder sb = new StringBuilder(); final org.rsbot.client.RSInterface[] children = getChildrenInternal(); if (children != null) { for (final org.rsbot.client.RSInterface child : children) { String string; if (child != null && (string = child.getText()) != null) { sb.append(string); sb.append("\r\n"); } } } if (sb.length() > 2) { sb.setLength(sb.length() - 2); } return sb.toString(); } /** * Checks whether or not this interface is valid * * @return <tt>true</tt> if it's valid */ public boolean isValid() { if (getChildrenInternal() == null) { return false; } final int idx = getIndex(); final boolean[] validArray = methods.client.getValidRSInterfaceArray(); if (idx >= 0 && validArray != null && idx < validArray.length && validArray[idx]) { final org.rsbot.client.RSInterface[][] inters = methods.client.getRSInterfaceCache(); if (idx < inters.length && inters[idx] != null) { final RSComponent[] children = getComponents(); int count = 0; for (final RSComponent child : children) { if (child.getBoundsArrayIndex() == -1) { ++count; } } return count != children.length; } } return false; } /** * Iterates over the children of the interface. Will never return null even * if the underlying interface is null. */ public Iterator<RSComponent> iterator() { return new Iterator<RSComponent>() { private int nextIdx = 0; public boolean hasNext() { return !isValid() && getChildCount() >= nextIdx; } public RSComponent next() { final RSComponent child = getComponent(nextIdx); nextIdx++; return child; } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Safely gets the array of children. * * @return The child interfaces of the client. */ org.rsbot.client.RSInterface[] getChildrenInternal() { final Client c = methods.client; if (c == null) { return null; } final org.rsbot.client.RSInterface[][] inters = c.getRSInterfaceCache(); if (inters != null && index < inters.length) { return inters[index]; } return null; } void setChild(final RSComponent child) { synchronized (childLock) { // safe that the index isn't excessive since it comes from child final int idx = child.getIndex(); if (idx >= childCache.length) { getComponent(idx); childCache[idx] = child; } } } /** * @inheritDoc java/lang/Object#equals(java/lang/Object) */ @Override public boolean equals(final Object obj) { if (obj == this) { return true; } if (obj instanceof RSInterface) { final RSInterface inter = (RSInterface) obj; return inter.index == index; } return false; } /** * @inheritDoc java/lang/Object#hashCode() */ @Override public int hashCode() { return index; } }