/*
* Copyright (c) 2010-2016, Sikuli.org, sikulix.com
* Released under the MIT License.
*
*/
package org.sikuli.guide;
import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import org.sikuli.guide.SxAnchor.AnchorListener;
import org.sikuli.guide.Visual.Layout;
import org.sikuli.basics.Debug;
import org.sikuli.script.Env;
import org.sikuli.script.Location;
import org.sikuli.script.Pattern;
import org.sikuli.script.Region;
public class SxMagnet
implements Transition, GlobalMouseMotionListener {
Guide guide;
GlobalMouseMotionTracker mouseTracker;
private SxClickable lastClickedClickable;
public SxMagnet(Guide guide) {
this.guide = guide;
mouseTracker = GlobalMouseMotionTracker.getInstance();
mouseTracker.addListener(this);
// TOOD: fix this hack
// use this trick to engage clickablewindow
guide.addComponent(new SxClickable(), 0);
}
ArrayList<SxAnchor> targets = new ArrayList<SxAnchor>();
ArrayList<Link> links = new ArrayList<Link>();
// void flyTarget(SxAnchor a){
//
// Location mouseLocation = Env.getMouseLocation();
//
// try {
// Pattern pattern = a.getPattern();
// SxImage img = new SxImage(pattern.getBImage());
// img.setActualLocation(a.getActualLocation());
//
// Dimension currentSize = a.getActualSize();
// Dimension targetSize = new Dimension(currentSize);
// targetSize.width *= 1.5;
// targetSize.height *= 1.5;
//
// img.addResizeAnimation(currentSize, targetSize);
//
//
// Point currentLocation = new Point(a.getActualLocation());
// currentLocation.x += img.getActualWidth();
// currentLocation.y += img.getActualHeight();
//
// int dx = mouseLocation.x - currentLocation.x;
// int dy = mouseLocation.y - currentLocation.y;
//
// int radius = 50;
// double distance = mouseLocation.distance(currentLocation);
// double m = radius / distance;
//
// Point targetLocation = new Point();
// targetLocation.x = (int) (mouseLocation.x - dx*m) - img.getActualWidth()/2;
// targetLocation.y = (int) (mouseLocation.y - dy*m) - img.getActualHeight()/2;
//
//
// Rectangle desiredSpot = new Rectangle(targetLocation, targetSize);
// desiredSpot = getFreeSpot(desiredSpot);
// targetLocation = desiredSpot.getLocation();
//
//
// img.addMoveAnimation(currentLocation, targetLocation);
// guide.addToFront(img);
// img.startAnimation();
//
//
// Region r = new Region(mouseLocation.x-radius,mouseLocation.y-radius,radius*2,radius*2);
// SxCircle c = new SxCircle(r);
// guide.addComponent(c,1);
//
// guide.repaint();
//
//
// } catch (IOException e) {
// e.printStackTrace();
// }
class Link {
SxImage image;
SxAnchor anchor;
}
void attractTarget(SxAnchor a, Point targetLocation) {
try {
Pattern pattern = a.getPattern();
SxImage img = new SxImage(pattern.getBImage());
SxClickable clickable = new SxClickable();
clickable.setLocationRelativeToComponent(img, Layout.OVER);
guide.addToFront(clickable);
clickable.clickPoint = a.getCenter();
Link link = new Link();
link.image = img;
link.anchor = a;
links.add(link);
img.setShadowDefault();
img.setActualLocation(a.getActualLocation());
Dimension currentSize = a.getActualSize();
Dimension targetSize = new Dimension(currentSize);
targetSize.width *= 1.5;
targetSize.height *= 1.5;
img.addResizeAnimation(currentSize, targetSize);
Point currentLocation = new Point(a.getActualLocation());
targetLocation.x -= targetSize.width / 2;
targetLocation.y -= targetSize.height / 2;
img.addMoveAnimation(currentLocation, targetLocation);
guide.addToFront(img);
img.startAnimation();
guide.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
SxCircle selection;
public void allTargetAnchored() {
double theta = 0;
double dtheta = 2.0f * Math.PI / (double) targets.size();
Location mouseLocation = Env.getMouseLocation();
int x = mouseLocation.x;
int y = mouseLocation.y;
int radius = 50;
Region r = new Region(mouseLocation.x - radius, mouseLocation.y - radius, radius * 2, radius * 2);
SxCircle c = new SxCircle(r);
guide.addToFront(c);
selection = new SxCircle();
guide.addToFront(selection);
// sort targets along x-axis
Collections.sort(targets, new Comparator<SxAnchor>() {
@Override
public int compare(SxAnchor a, SxAnchor b) {
return b.getX() - a.getX();
}
});
for (SxAnchor target : targets) {
int px = (int) (x + radius * Math.cos(theta));
int py = (int) (y + radius * Math.sin(theta));
theta += dtheta;
attractTarget(target, new Point(px, py));
}
}
int anchoredCount = 0;
public void addTarget(final Pattern pattern) {
final SxAnchor a = new SxAnchor(pattern);
guide.addToFront(a);
targets.add(a);
SxFlag f = new SxFlag("Flag");
f.setLocationRelativeToComponent(a, Layout.LEFT);
guide.addToFront(f);
a.addListener(new AnchorListener() {
@Override
public void anchored() {
Debug.info("[Magnet] pattern anchored");
anchoredCount += 1;
if (anchoredCount == targets.size()) {
allTargetAnchored();
}
}
@Override
public void found(SxAnchor source) {
// TODO Auto-generated method stub
}
});
}
// ArrayList<Rectangle> occupiedSpots = new ArrayList<Rectangle>();
// Rectangle getFreeSpot(Rectangle desired){
//
// Rectangle freeSpot = new Rectangle(desired);
//
// for (Rectangle occupiedSpot : occupiedSpots){
//
// if (freeSpot.intersects(occupiedSpot)){
// freeSpot.x = occupiedSpot.x + occupiedSpot.width + 10;
// }
//
// }
//
// occupiedSpots.add(freeSpot);
//
// return freeSpot;
// }
TransitionListener token;
@Override
public String waitForTransition(TransitionListener token) {
this.token = token;
mouseTracker.start();
return "Next";
}
@Override
public void globalMouseMoved(int x, int y) {
// Debug.log("[SxMagnet] moved to " + x + "," + y);
Point p = new Point(x, y);
for (Link link : links) {
if (link.image.getActualBounds().contains(p)) {
//Debug.info("[SxMagnet] mouseover on a target");
if (selection != null) {
selection.setMargin(5, 5, 5, 5);
selection.setLocationRelativeToComponent(link.anchor, Layout.OVER);
guide.repaint();
}
}
}
}
@Override
public void globalMouseIdled(int x, int y) {
}
}