All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sikuli.api.DefaultScreenRegion Maven / Gradle / Ivy

The newest version!
package org.sikuli.api;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.swing.Timer;

import org.sikuli.api.event.StateChangeListener;
import org.sikuli.api.event.TargetEventListener;
import org.sikuli.api.event.VisualEventManager;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
 * This class provides manipulation methods that can be used by the default screen region.
 *
 */
public class DefaultScreenRegion extends AbstractScreenRegion implements ScreenRegion {

	private BufferedImage lastCapturedImage;
	private Map states = new ConcurrentHashMap();

	/**
	 * Constructs a new DefaultScreenRegion on the specified Screen object whose 
	 * upper-left corner is at (0, 0) in the coordinate space.
	 *  
	 * @param screen The Screen to create a region from.
	 */
	public DefaultScreenRegion(Screen screen){
		super(screen);
	}
	/**
	 * Constructs a new DefaultScreenRegion object whose Screen is the same as the parent
	 * ScreenRegion with the specified region values.
	 * 
	 * @param parent the parent of this ScreenRegion
	 * @param x The X coordinate of the upper-left corner of the rectangular screen region.
	 * @param y The Y coordinate of the upper-left corner of the rectangular screen region.
	 * @param width The width of the rectangular screen region.
	 * @param height The height of the rectangular screen region.
	 */
	public DefaultScreenRegion(ScreenRegion parent, int x, int y, int width, int height) {
		super(parent.getScreen());
		setX(parent.getBounds().x + x);
		setY(parent.getBounds().y + y);
		setWidth(width);
		setHeight(height);
	}
	/**
	 * Constructs a new DefaultScreenRegion object on the specified Screen and region values.
	 * 
	 * @param screen The Screen to create a region from.
	 * @param x The X coordinate of the upper-left corner of the rectangular screen region.
	 * @param y The Y coordinate of the upper-left corner of the rectangular screen region.
	 * @param width The width of the rectangular screen region.
	 * @param height The height of the rectangular screen region.
	 */
	public DefaultScreenRegion(Screen screen, int x, int y, int width, int height) {
		super(screen, x, y, width, height);
	}

	@Override
	public List findAll(Target target){
		List rs = target.doFindAll(this);
		return rs;
	}

	@Override
	public ScreenRegion find(Target target){
		ScreenRegion result = _find(target);		
		return result;
	}	

	private ScreenRegion _find(Target target){
		// temporary override the limit to ONE
		int oldLimit = target.getLimit();
		target.setLimit(1);
		List results = target.doFindAll(this);
		target.setLimit(oldLimit);

		ScreenRegion result;
		if (results.size() == 0){
			result = null;
		}else{
			result = results.get(0);
		}
		return result;
	}


	static private int POLL_INTERVAL = 500;

	class RepeatFind{

		private volatile boolean timeout = false;		

		private Target target;
		private int duration;

		private ScreenRegion r = null;

		RepeatFind(Target target, int duration){		
			this.target = target;
			this.duration = duration;
		}

		public ScreenRegion run(){
			Timer t = new Timer(duration, new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent e) {
					timeout = true;
				}				
			});
			t.start();
			t.setRepeats(false);

			while (r == null && !timeout){
				r = _find(target);		
				try {
					Thread.sleep(POLL_INTERVAL);
				} catch (InterruptedException e1) {
				}
			}
			t.stop();
			return r;
		}
	}	

	@Override
	public ScreenRegion wait(final Target target, int mills){
		RepeatFind ru = new RepeatFind(target, mills);
		ScreenRegion result = ru.run();
		return result;
	}

	@Override
	public BufferedImage capture() {
		lastCapturedImage = getScreen().getScreenshot(getX(), getY(), getWidth(), getHeight());
		//lastCapturedImage = applyMask(lastCapturedImage);
		return lastCapturedImage;
	}

	/**
	 * Returns the last captured screenshot in this screen region.
	 * 
	 * @return a BufferedImage that holds the last captured screenshot in this screen region.
	 */
	public BufferedImage getLastCapturedImage(){
		if (lastCapturedImage == null)
			lastCapturedImage = capture();
		return lastCapturedImage;
	}
	
	@Override
	public ScreenLocation getUpperLeftCorner() {
		return new DefaultScreenLocation(getScreen(), getX(), getY());
	}
	
	@Override
	public ScreenLocation getLowerLeftCorner() {
		return new DefaultScreenLocation(getScreen(), getX(), getY() + getHeight());
	}
	
	@Override
	public ScreenLocation getUpperRightCorner() {
		return new DefaultScreenLocation(getScreen(), getX() + getWidth(), getY());
	}
	
	@Override
	public ScreenLocation getLowerRightCorner() {
		return new DefaultScreenLocation(getScreen(), getX() + getWidth(), getY() + getHeight());
	}

	@Override
	public ScreenLocation getCenter() {
		return new DefaultScreenLocation(getScreen(), getX() + getWidth()/2, getY() + getHeight()/2);
	}

	@Override
	public void addTargetEventListener(Target target, TargetEventListener listener) {	
		VisualEventManager.getSingleton().addTargetEventListener(this,  target, listener);
	}

	@Override
	public void removeTargetEventListener(Target target, TargetEventListener listener) {
		VisualEventManager.getSingleton().removeTargetEventListener(this,  target, listener);		
	}


	static class StaticScreen implements Screen {

		static private BufferedImage crop(BufferedImage src, int x, int y, int width, int height){
			BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
			Graphics g = dest.getGraphics();
			g.drawImage(src, 0, 0, width, height, x, y, x + width, y + height, null);
			g.dispose();
			return dest;
		}

		final BufferedImage fullScreenshot;
		final Dimension screenSize;

		StaticScreen(ScreenRegion screenRegion){
			screenSize = screenRegion.getScreen().getSize();
			fullScreenshot = screenRegion.getScreen().getScreenshot(0, 0, screenSize.width, screenSize.height);
		}

		@Override
		public BufferedImage getScreenshot(int x, int y, int width, int height) {
			return crop(fullScreenshot, x, y, width, height);
		}

		@Override
		public Dimension getSize() {
			return screenSize;
		}
	}

	@Override
	public ScreenRegion snapshot(){
		ScreenRegion r = new DefaultScreenRegion(new StaticScreen(this), getX(), getY(), getWidth(), getHeight());
		return r;
	}

	@Override
	public void addStateChangeEventListener(StateChangeListener listener) {
		VisualEventManager.getSingleton().addStateChangeEventListener(this, listener);		
	}

	// x, y are relative to the upper-left corner of this ScreenRegion
	// no boundary check is built in yet
	List rois = Lists.newArrayList(); 
	/* (non-Javadoc)
	 * @see org.sikuli.api.ScreenRegion#addROI(int, int, int, int)
	 */
	@Override
	public void addROI(int x, int y, int width, int height){
		rois.add(new Rectangle(x,y,width,height));
	}

	/* (non-Javadoc)
	 * @see org.sikuli.api.ScreenRegion#getROIs()
	 */
	@Override
	public List getROIs(){		
		return ImmutableList.copyOf(rois);
	}	

	/**
	 * Returns a map of {@link Target} objects and states, which can be any object, 
	 * of this DefaultScreenRegion.
	 * 
	 * @return a map of Target objects and their states.
	 */
	public Map getStates() {
		return states;
	}
	
	@Override
	public void addState(Target target, Object state) {
		states.put(target,  state);
	}

	@Override
	public void removeState(Target target) {
		states.remove(target);
	}

	@Override
	public Object getState() {

		Target topStateTarget = null;
		double topScore = 0;

		//Map states = screenRegion.getStates();		
		Set keySet = states.keySet();		
		for (Target target : keySet){	
			//System.out.println(this + ">" + target);			
			ScreenRegion match = _find(target);
			//System.out.println("m:" + match);
			if (match != null && match.getScore() > topScore){
				topStateTarget = target;
				topScore = match.getScore();
			}			
		}
		if (topStateTarget != null){
			return states.get(topStateTarget);
		}else{
			return null;
		}
	}


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy