[sikuli] 319/385: completely revising observe (ongoing)
Gilles Filippini
pini at moszumanska.debian.org
Sun Jun 29 19:26:28 UTC 2014
This is an automated email from the git hooks/post-receive script.
pini pushed a commit to tag upstream/1.1.0_beta1
in repository sikuli.
commit 68b3354b5507275b2617b71bb07238303da40b3b
Author: Raimund Hocke <rmhdevelop at me.com>
Date: Mon Mar 3 08:33:30 2014 +0100
completely revising observe (ongoing)
---
.../main/java/org/sikuli/script/ObserveAppear.java | 4 +-
.../main/java/org/sikuli/script/ObserveChange.java | 4 +-
.../main/java/org/sikuli/script/ObserveEvent.java | 38 +-
.../main/java/org/sikuli/script/ObserveVanish.java | 4 +-
API/src/main/java/org/sikuli/script/Observer.java | 239 +++++++------
.../java/org/sikuli/script/ObserverCallBack.java | 2 +-
API/src/main/java/org/sikuli/script/Observing.java | 397 ++++++---------------
API/src/main/java/org/sikuli/script/Region.java | 106 ++++--
API/src/main/java/org/sikuli/script/SikuliX.java | 26 +-
9 files changed, 350 insertions(+), 470 deletions(-)
diff --git a/API/src/main/java/org/sikuli/script/ObserveAppear.java b/API/src/main/java/org/sikuli/script/ObserveAppear.java
index 6ff50a6..b6f8a5d 100755
--- a/API/src/main/java/org/sikuli/script/ObserveAppear.java
+++ b/API/src/main/java/org/sikuli/script/ObserveAppear.java
@@ -11,8 +11,8 @@ package org.sikuli.script;
*/
public class ObserveAppear extends ObserveEvent {
- public ObserveAppear(Object ptn, Match m, Region r){
- super(ptn, m, r);
+ public ObserveAppear(String name, Object ptn, Match m, Region r){
+ super(name, ptn, m, r);
type = Type.APPEAR;
}
diff --git a/API/src/main/java/org/sikuli/script/ObserveChange.java b/API/src/main/java/org/sikuli/script/ObserveChange.java
index 0c2ca74..812f654 100755
--- a/API/src/main/java/org/sikuli/script/ObserveChange.java
+++ b/API/src/main/java/org/sikuli/script/ObserveChange.java
@@ -12,10 +12,10 @@ import java.util.List;
* INTERNAL USE
*/
public class ObserveChange extends ObserveEvent {
- public ObserveChange(List<Match> results, Region r, int eventIndex){
+ public ObserveChange(String name, List<Match> results, Region r, int eventIndex){
+ super(name, null, null, r);
type = Type.CHANGE;
setChanges(results);
- setRegion(r);
setIndex(eventIndex);
}
diff --git a/API/src/main/java/org/sikuli/script/ObserveEvent.java b/API/src/main/java/org/sikuli/script/ObserveEvent.java
index 1713b4b..9b8e6a6 100755
--- a/API/src/main/java/org/sikuli/script/ObserveEvent.java
+++ b/API/src/main/java/org/sikuli/script/ObserveEvent.java
@@ -7,6 +7,7 @@
package org.sikuli.script;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
public class ObserveEvent {
@@ -25,22 +26,34 @@ public class ObserveEvent {
private Match match = null;
private int index = -1;
private List<Match> changes = null;
+ private long time;
+ private String name;
public ObserveEvent() {
}
-
+
/**
* INTERNAL USE ONLY: creates an observed event
*/
- public ObserveEvent(Object ptn, Match m, Region r) {
- init(ptn, m, r);
+ public ObserveEvent(String name, Object ptn, Match m, Region r) {
+ init(name, ptn, m, r);
}
- private void init(Object ptn, Match m, Region r) {
+ private void init(String name, Object ptn, Match m, Region r) {
+ this.name = name;
setRegion(r);
setMatch(m);
setPattern(ptn);
+ time = new Date().getTime();
}
+
+ /**
+ *
+ * @return the observer name of this event
+ */
+ public String getName() {
+ return name;
+ }
/**
*
@@ -134,17 +147,20 @@ public class ObserveEvent {
* @param secs
*/
public void repeat(long secs) {
- region.getObserver().repeat(type, pattern, match, secs);
+ region.getObserver().repeat(type, name, match, secs);
}
/**
* @return the number how often this event has already been triggered until now
*/
public int getCount() {
+ if (region.getObserver() == null) {
+ return 1;
+ }
if (type == Type.CHANGE) {
- return region.getObserver().getChangedCount(index);
+ return region.getObserver().getChangedCount(name);
} else {
- return region.getEvtMgr().getCount(pattern);
+ return region.getObserver().getCount(name);
}
}
@@ -162,11 +178,11 @@ public class ObserveEvent {
@Override
public String toString() {
if (type == Type.CHANGE) {
- return String.format("Event(%s) on: %s with: %d count: %d",
- type, region, index, getCount());
+ return String.format("Event(%s) %s on: %s with: %d count: %d",
+ type, name, region, index, getCount());
} else {
- return String.format("Event(%s) on: %s with: %s match: %s count: %d",
- type, region, pattern, match, getCount());
+ return String.format("Event(%s) %s on: %s with: %s match: %s count: %d",
+ type, name, region, pattern, match, getCount());
}
}
}
diff --git a/API/src/main/java/org/sikuli/script/ObserveVanish.java b/API/src/main/java/org/sikuli/script/ObserveVanish.java
index 2ed39aa..8a86805 100755
--- a/API/src/main/java/org/sikuli/script/ObserveVanish.java
+++ b/API/src/main/java/org/sikuli/script/ObserveVanish.java
@@ -10,8 +10,8 @@ package org.sikuli.script;
* INTERNAL USE
*/
public class ObserveVanish extends ObserveEvent {
- public ObserveVanish(Object ptn, Match m, Region r){
- super(ptn, m, r);
+ public ObserveVanish(String name, Object ptn, Match m, Region r){
+ super(name, ptn, m, r);
type = Type.VANISH;
}
}
diff --git a/API/src/main/java/org/sikuli/script/Observer.java b/API/src/main/java/org/sikuli/script/Observer.java
index ed907ad..65bfab5 100755
--- a/API/src/main/java/org/sikuli/script/Observer.java
+++ b/API/src/main/java/org/sikuli/script/Observer.java
@@ -6,10 +6,14 @@
*/
package org.sikuli.script;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import org.sikuli.basics.Settings;
import org.sikuli.basics.Debug;
-import java.awt.AWTException;
-import java.util.*;
import org.sikuli.natives.FindInput;
import org.sikuli.natives.FindResult;
import org.sikuli.natives.FindResults;
@@ -35,58 +39,67 @@ public class Observer {
private Region observedRegion;
private Mat lastImgMat = null;
private org.opencv.core.Mat lastImageMat = null;
- private Map<Object, State> eventStates;
- private Map<Object, Long> repeatWaitTimes;
- private Map<Object, Integer> happenedCount;
- private Map<Object, Match> lastMatches;
- private Map<Object, String> eventNames;
- private Map<Object, Object> appearCallBacks, vanishCallBacks;
- private Map<Integer, Object> changeCallBacks;
- private Map<Integer, Integer> changedCount;
- private Map<Integer, String> onChangeNames;
+ private final Map<String, State> eventStates;
+ private final Map<String, Long> repeatWaitTimes;
+ private final Map<String, Match> lastMatches;
+ private final Map<String, Object> eventNames;
+ private final Map<String, ObserveEvent.Type> eventTypes;
+ private final Map<String, Object> eventCallBacks;
+ private final Map<String, Integer> happenedCount;
+ private final Map<String, Integer> onChangeNames;
private int minChanges;
private boolean sthgLeft;
private boolean shouldCheckChanges;
public Observer(Region region) {
observedRegion = region;
- eventStates = new HashMap<Object, State>();
- repeatWaitTimes = new HashMap<Object, Long>();
- happenedCount = new HashMap<Object, Integer>();
- lastMatches = new HashMap<Object, Match>();
- eventNames = new HashMap<Object, String>();
- appearCallBacks = new HashMap<Object, Object>();
- vanishCallBacks = new HashMap<Object, Object>();
- changeCallBacks = new HashMap<Integer, Object>();
- changedCount = new HashMap<Integer, Integer>();
- onChangeNames = new HashMap<Integer, String>();
+ eventStates = Collections.synchronizedMap(new HashMap<String, State>());
+ repeatWaitTimes = Collections.synchronizedMap(new HashMap<String, Long>());
+ happenedCount = Collections.synchronizedMap(new HashMap<String, Integer>());
+ lastMatches = Collections.synchronizedMap(new HashMap<String, Match>());
+ eventNames = Collections.synchronizedMap(new HashMap<String, Object>());
+ eventTypes = Collections.synchronizedMap(new HashMap<String, ObserveEvent.Type>());
+ eventCallBacks = Collections.synchronizedMap(new HashMap<String, Object>());
+ onChangeNames = Collections.synchronizedMap(new HashMap<String, Integer>());
}
public void initialize() {
log(3, "resetting observe states for " + observedRegion.toStringShort());
sthgLeft = true;
shouldCheckChanges = true;
- for (Object ptn : eventStates.keySet()) {
- eventStates.put(ptn, State.FIRST);
- happenedCount.put(ptn, 0);
+ for (String name : eventNames.keySet()) {
+ eventStates.put(name, State.FIRST);
+ happenedCount.put(name, 0);
}
- for (int n : changeCallBacks.keySet()) {
- changedCount.put(n, 0);
+ for (String name : onChangeNames.keySet()) {
+ happenedCount.put(name, 0);
}
}
+ public String[] getNames() {
+ String[] names = new String[eventNames.size() + onChangeNames.size()];
+ int i = 0;
+ for (String n : eventNames.keySet()) {
+ names[i++] = n;
+ }
+ for (String n : onChangeNames.keySet()) {
+ names[i++] = n;
+ }
+ return names;
+ }
+
public void setRegion(Region reg) {
observedRegion = reg;
}
- public int getCount(Object ptn) {
- return happenedCount.get(ptn);
+ public int getCount(String name) {
+ return happenedCount.get(name);
}
- public int getChangedCount(int index) {
- return changedCount.get(index);
+ public int getChangedCount(String name) {
+ return happenedCount.get(name);
}
-
+
private <PSC> float getSimiliarity(PSC ptn) {
float similarity = -1f;
if (ptn instanceof Pattern) {
@@ -98,53 +111,54 @@ public class Observer {
return similarity;
}
- public <PSC> void addAppearObserver(PSC ptn, ObserverCallBack ob, String name) {
- appearCallBacks.put(ptn, ob);
- eventStates.put(ptn, State.FIRST);
- eventNames.put(ptn, name);
- }
-
- public <PSC> void removeAppearObserver(PSC ptn) {
- Observing.remove(eventNames.get(ptn));
- eventNames.remove(ptn);
- appearCallBacks.remove(ptn);
- eventStates.remove(ptn);
- }
-
- public <PSC> void addVanishObserver(PSC ptn, ObserverCallBack ob, String name) {
- vanishCallBacks.put(ptn, ob);
- eventStates.put(ptn, State.FIRST);
- eventNames.put(ptn, name);
+ public <PSC> void addObserver(PSC ptn, ObserverCallBack ob, String name, ObserveEvent.Type type) {
+ eventCallBacks.put(name, ob);
+ eventStates.put(name, State.FIRST);
+ eventNames.put(name, ptn);
}
- public <PSC> void removeVanishObserver(PSC ptn) {
- Observing.remove(eventNames.get(ptn));
- eventNames.remove(ptn);
- vanishCallBacks.remove(ptn);
- eventStates.remove(ptn);
+ public void removeObserver(String name) {
+ Observing.remove(name);
+ eventNames.remove(name);
+ eventCallBacks.remove(name);
+ eventStates.remove(name);
}
- private void callAppearObserver(Object ptn, Match m) {
- log(lvl, "appeared: %s with: %s\nat: %s", eventNames.get(ptn), ptn, m);
- ObserveAppear observeEvent = new ObserveAppear(ptn, m, observedRegion);
- Object callBack = appearCallBacks.get(ptn);
- Observing.addEvent(eventNames.get(ptn), observeEvent);
+ private void callAppearObserver(String name, Match m) {
+ Object ptn = eventNames.get(name);
+ log(lvl, "appeared: %s with: %s\nat: %s", name, ptn, m);
+ ObserveAppear observeEvent = new ObserveAppear(name, ptn, m, observedRegion);
+ Object callBack = eventCallBacks.get(name);
+ Observing.addEvent(observeEvent);
if (callBack != null && callBack instanceof ObserverCallBack) {
log(lvl, "running call back");
- ((ObserverCallBack) appearCallBacks.get(ptn)).appeared(observeEvent);
+ ((ObserverCallBack) callBack).appeared(observeEvent);
}
}
- private void callVanishObserver(Object ptn, Match m) {
- log(lvl, "vanished: %s with: %s\nat: %s", eventNames.get(ptn), ptn, m);
- ObserveVanish observeEvent = new ObserveVanish(ptn, m, observedRegion);
- Object callBack = vanishCallBacks.get(ptn);
- Observing.addEvent(eventNames.get(ptn), observeEvent);
+ private void callVanishObserver(String name, Match m) {
+ Object ptn = eventNames.get(name);
+ log(lvl, "vanished: %s with: %s\nat: %s", name, ptn, m);
+ ObserveVanish observeEvent = new ObserveVanish(name, ptn, m, observedRegion);
+ Object callBack = eventCallBacks.get(name);
+ Observing.addEvent(observeEvent);
if (callBack != null && callBack instanceof ObserverCallBack) {
log(lvl, "running call back");
- ((ObserverCallBack) vanishCallBacks.get(ptn)).vanished(observeEvent);
+ ((ObserverCallBack) callBack).vanished(observeEvent);
}
}
+
+ private void callEventObserver(String name, Match m) {
+ Object ptn = eventNames.get(name);
+ log(lvl, "appeared: %s with: %s\nat: %s", name, ptn, m);
+ ObserveAppear observeEvent = new ObserveAppear(name, ptn, m, observedRegion);
+ Object callBack = eventCallBacks.get(name);
+ Observing.addEvent(observeEvent);
+ if (callBack != null && callBack instanceof ObserverCallBack) {
+ log(lvl, "running call back");
+ ((ObserverCallBack) callBack).appeared(observeEvent);
+ }
+ }
private void checkPatterns(ScreenImage simg) {
Finder finder = null;
@@ -156,13 +170,14 @@ public class Observer {
}
String imgOK;
log(lvl + 1, "checkPatterns entry: sthgLeft: %s isObserving: %s", sthgLeft, observedRegion.isObserving());
- for (Object ptn : eventStates.keySet()) {
- if (eventStates.get(ptn) != State.FIRST
- && eventStates.get(ptn) != State.UNKNOWN
- && eventStates.get(ptn) != State.REPEAT) {
+ for (String name : eventStates.keySet()) {
+ if (eventStates.get(name) != State.FIRST
+ && eventStates.get(name) != State.UNKNOWN
+ && eventStates.get(name) != State.REPEAT) {
continue;
}
imgOK = null;
+ Object ptn = eventNames.get(name);
if (ptn instanceof String) {
imgOK = finder.find((String) ptn);
Image img = Image.create((String) ptn);
@@ -178,14 +193,14 @@ public class Observer {
}
if (null == imgOK) {
Debug.error("EventMgr: checkPatterns: Image not valid", ptn);
- eventStates.put(ptn, State.MISSING);
+ eventStates.put(name, State.MISSING);
continue;
}
- if (eventStates.get(ptn) == State.REPEAT) {
+ if (eventStates.get(name) == State.REPEAT) {
log(lvl, "repeat: checking");
- if (lastMatches.get(ptn).exists(ptn) != null) {
- if ((new Date()).getTime() > repeatWaitTimes.get(ptn)) {
- eventStates.put(ptn, State.APPEARED);
+ if (lastMatches.get(name).exists(ptn) != null) {
+ if ((new Date()).getTime() > repeatWaitTimes.get(name)) {
+ eventStates.put(name, State.APPEARED);
log(lvl, "repeat: vanish timeout");
// time out
} else {
@@ -193,7 +208,7 @@ public class Observer {
}
continue; // not vanished within given time or still there
} else {
- eventStates.put(ptn, State.UNKNOWN);
+ eventStates.put(name, State.UNKNOWN);
sthgLeft = true;
log(lvl, "repeat: has vanished");
continue; // has vanished, repeat
@@ -205,7 +220,7 @@ public class Observer {
m = finder.next();
if (m.getScore() >= getSimiliarity(ptn)) {
hasMatch = true;
- lastMatches.put(ptn, m);
+ lastMatches.put(name, m);
}
}
if (hasMatch) {
@@ -214,14 +229,14 @@ public class Observer {
} else if (eventStates.get(ptn) == State.FIRST) {
log(lvl + 1, "checkPatterns: " + ptn.toString() + " match: "
+ "NO" + " in " + observedRegion.toStringShort());
- eventStates.put(ptn, State.UNKNOWN);
+ eventStates.put(name, State.UNKNOWN);
}
- if (appearCallBacks.containsKey(ptn)) {
- if (eventStates.get(ptn) != State.APPEARED) {
+ if (appearCallBacks.containsKey(name)) {
+ if (eventStates.get(name) != State.APPEARED) {
if (hasMatch) {
- eventStates.put(ptn, State.APPEARED);
- happenedCount.put(ptn, happenedCount.get(ptn) + 1);
- callAppearObserver(ptn, m);
+ eventStates.put(name, State.APPEARED);
+ happenedCount.put(name, happenedCount.get(name) + 1);
+ callAppearObserver(name, m);
} else {
sthgLeft = true;
}
@@ -229,9 +244,9 @@ public class Observer {
} else if (vanishCallBacks.containsKey(ptn)) {
if (eventStates.get(ptn) != State.VANISHED) {
if (!hasMatch) {
- eventStates.put(ptn, State.VANISHED);
- happenedCount.put(ptn, happenedCount.get(ptn) + 1);
- callVanishObserver(ptn, lastMatches.get(ptn));
+ eventStates.put(name, State.VANISHED);
+ happenedCount.put(name, happenedCount.get(name) + 1);
+ callVanishObserver(name, lastMatches.get(name));
} else {
sthgLeft = true;
}
@@ -244,39 +259,41 @@ public class Observer {
log(lvl + 1, "checkPatterns exit: sthgLeft: %s isObserving: %s", sthgLeft, observedRegion.isObserving());
}
- public void repeat(ObserveEvent.Type type, Object pattern, Match match, long secs) {
+ public void repeat(ObserveEvent.Type type, String name, Match match, long secs) {
if (type == ObserveEvent.Type.CHANGE) {
Debug.error("EventMgr: repeat: CHANGE repeats automatically");
} else if (type == ObserveEvent.Type.VANISH) {
Debug.error("EventMgr: repeat: not supported for VANISH");
} else if (type == ObserveEvent.Type.APPEAR) {
- eventStates.put(pattern, State.REPEAT);
+ eventStates.put(name, State.REPEAT);
if (secs <= 0) {
secs = (long) observedRegion.getWaitForVanish();
}
- repeatWaitTimes.put(pattern, (new Date()).getTime() + 1000 * secs);
+ repeatWaitTimes.put(name, (new Date()).getTime() + 1000 * secs);
log(lvl, "repeat: requested for APPEAR: "
- + pattern.toString() + " at " + match.toStringShort() + " after " + secs + " seconds");
+ + eventNames.get(name).toString() + " at " + match.toStringShort() + " after " + secs + " seconds");
sthgLeft = true;
}
}
public void addChangeObserver(int threshold, ObserverCallBack ob, String name) {
- changeCallBacks.put(new Integer(threshold), ob);
- minChanges = getMinChanges();
- onChangeNames.put(threshold, name);
- }
-
- public void removeChangeObserver(int threshold) {
- Observing.remove(onChangeNames.get(threshold));
- eventNames.remove(threshold);
- changeCallBacks.remove(new Integer(threshold));
+ eventCallBacks.put(name, ob);
minChanges = getMinChanges();
+ onChangeNames.put(name, threshold);
}
+// public void removeChangeObserver(int threshold) {
+// Observing.remove(onChangeNames.get(threshold));
+// onChangeNames.remove(threshold);
+// changeCallBacks.remove(new Integer(threshold));
+// minChanges = getMinChanges();
+// }
+//
private int getMinChanges() {
int min = Integer.MAX_VALUE;
- for (Integer n : changeCallBacks.keySet()) {
+ int n;
+ for (String name : onChangeNames.keySet()) {
+ n = onChangeNames.get(name);
if (n < min) {
min = n;
}
@@ -286,9 +303,11 @@ public class Observer {
private int callChangeObserver(FindResults results) {
int activeChangeCallBacks = 0;
+ int n;
log(lvl, "changes: %d in: %s", results.size(), observedRegion);
- for (Integer n : changeCallBacks.keySet()) {
- if (changedCount.get(n) == -1) {
+ for (String name : onChangeNames.keySet()) {
+ n = onChangeNames.get(name);
+ if (happenedCount.get(name) == -1) {
continue;
}
activeChangeCallBacks++;
@@ -300,16 +319,16 @@ public class Observer {
}
}
if (changes.size() > 0) {
- changedCount.put(n, changedCount.get(n) + 1);
- ObserveChange observeEvent = new ObserveChange(changes, observedRegion, n);
- Object callBack = changeCallBacks.get(n);
- Observing.addEvent(onChangeNames.get(n), observeEvent);
+ happenedCount.put(name, happenedCount.get(name) + 1);
+ ObserveChange observeEvent = new ObserveChange(name, changes, observedRegion, n);
+ Object callBack = eventCallBacks.get(name);
+ Observing.addEvent(observeEvent);
if (callBack != null && callBack instanceof ObserverCallBack) {
log(lvl, "running call back");
- ((ObserverCallBack) changeCallBacks.get(n)).changed(observeEvent);
+ ((ObserverCallBack) callBack).changed(observeEvent);
} else {
// onChange only repeated if CallBack given
- changedCount.put(n, -1);
+ happenedCount.put(name, -1);
activeChangeCallBacks--;
}
}
@@ -348,7 +367,9 @@ public class Observer {
fin.setSimilarity(minChanges);
FindResults results = Vision.findChanges(fin);
if (results.size() > 0) {
- if (0 == callChangeObserver(results)) changesObserved = false;
+ if (0 == callChangeObserver(results)) {
+ changesObserved = false;
+ }
}
lastImgMat = target;
}
@@ -369,7 +390,7 @@ public class Observer {
}
if (observedRegion.isObserving()) {
ret = sthgLeft;
- if (shouldCheckChanges && changeCallBacks.size() > 0) {
+ if (shouldCheckChanges && onChangeNames.size() > 0) {
changesObserved = checkChanges(simg);
shouldCheckChanges = changesObserved;
if (!observedRegion.isObserving()) {
diff --git a/API/src/main/java/org/sikuli/script/ObserverCallBack.java b/API/src/main/java/org/sikuli/script/ObserverCallBack.java
index ae4362e..c328a73 100644
--- a/API/src/main/java/org/sikuli/script/ObserverCallBack.java
+++ b/API/src/main/java/org/sikuli/script/ObserverCallBack.java
@@ -37,6 +37,6 @@ public class ObserverCallBack implements EventListener {
public void changed(ObserveEvent e) {
}
- public void happened(Observing.Event e) {
+ public void happened(ObserveEvent e) {
}
}
diff --git a/API/src/main/java/org/sikuli/script/Observing.java b/API/src/main/java/org/sikuli/script/Observing.java
index 8023a77..e76383c 100644
--- a/API/src/main/java/org/sikuli/script/Observing.java
+++ b/API/src/main/java/org/sikuli/script/Observing.java
@@ -9,13 +9,14 @@ package org.sikuli.script;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
-import java.util.Iterator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.sikuli.basics.Debug;
/**
- * This class implements a container that globally collects
- * all running observations.<br />
+ * This class globally collects
+ * all running observations and tracks the created events.<br />
*/
public class Observing {
@@ -26,241 +27,114 @@ public class Observing {
Debug.logx(level, "", me + ": " + message, args);
}
- private static class Entry {
+ private Observing() {
+ }
+
+ private static class ObserverEntry {
private Region region;
- private String name;
private ObserveEvent.Type type;
private boolean isActive = true;
private ObserverCallBack obs;
- protected Entry(String name, Region reg, ObserverCallBack obs, ObserveEvent.Type type) {
- this.name = name;
+ protected ObserverEntry(Region reg, ObserverCallBack obs, ObserveEvent.Type type) {
region = reg;
this.obs = obs;
this.type = type;
}
-
- protected void destroy() {
- region = null;
- name = null;
- type = null;
- obs = null;
- }
}
- public static class Event extends ObserveEvent {
- private Entry observer = null;
- private long time = 0;
-
- protected Event() {
- }
-
- protected Event(Event evt) {
- observer = evt.observer;
- time = evt.time;
- setRegion(evt.getRegion());
- setMatch(evt.getMatch());
- setChanges(evt.getChanges());
- setPattern(evt.getPattern());
- setIndex(evt.getIndex());
- }
+ private static final Map<String, ObserverEntry> observers = Collections.synchronizedMap(new HashMap<String, ObserverEntry>());
+ private static final Map<String, ObserveEvent> events = Collections.synchronizedMap(new HashMap<String, ObserveEvent>());
+ private static final List<Region> runningObservers = Collections.synchronizedList(new ArrayList<Region>());
- public long getTime() {
- return time;
- }
-
- protected void destroy() {
- observer = null;
- time = 0;
- }
+ protected static void addRunningObserver(Region r) {
+ runningObservers.add(r);
+ log(lvl,"add observer: now running %d observer(s)", runningObservers.size());
}
- private static List<Entry> observers = Collections.synchronizedList(new ArrayList<Entry>());
- private static List<Event> events = Collections.synchronizedList(new ArrayList<Event>());
-
- /**
- * adds an observer with a callback to the list
- *
- * @param reg the observed region
- * @param obs the callback
- * @param type one off ObserveEvent.Type.APPEAR, VANISH, CHANGE, GENERIC
- * @return a unique name derived from time or null if not possible
- */
- public static synchronized String add(Region reg, ObserverCallBack obs, ObserveEvent.Type type) {
- String name = createName();
- if (add(name, reg, obs, type)) {
- return name;
- }
- return null;
+ protected static void removeRunningObserver(Region r) {
+ runningObservers.remove(r);
+ log(lvl, "remove observer: now running %d observer(s)", runningObservers.size());
}
-
- /**
- * adds an observer to the list having no callback
- *
- * @param reg the observed region
- * @param name a unique name
- * @param type one off Observing.Type.APPEAR, VANISH, CHANGE, GENERIC
- * @return the observers name or null if not possible (duplicate?)
- */
- public static synchronized String add(Region reg, String name, ObserveEvent.Type type) {
- if (add(name, reg, null, type)) {
- return name;
+
+ protected static void stopRunningObservers() {
+ if (runningObservers.size() > 0) {
+ log(lvl, "stopping %d running observer(s)", runningObservers.size());
+ synchronized (runningObservers) {
+ for (Region r : runningObservers) {
+ r.stopObserver();
+ }
+ runningObservers.clear();
+ }
}
- return null;
+ Observing.clear();
}
/**
- * adds an observer of type GENERIC to the list having no callback
+ * INTERNAL USE: adds an observer to the list
*
- * @param name a unique name
- * @return the observers name or null if not possible (duplicate?)
+ * @param reg the observed region
+ * @param obs the callback (might be null - observer without call back)
+ * @param type one off ObserveEvent.Type.APPEAR, VANISH, CHANGE, GENERIC
+ * @param target
+ * @return a unique name derived from time or null if not possible
*/
- public static synchronized String add(String name) {
- if (add(name, null, null, ObserveEvent.Type.GENERIC)) {
- return name;
- }
- return null;
- }
-
- private static boolean add(String name, Region reg, ObserverCallBack obs, ObserveEvent.Type type) {
- if (hasName(name, reg)) {
- return false;
- }
- Iterator<Entry> iter = observers.iterator();
- while (iter.hasNext()) {
- if (iter.next() == null) {
- iter.remove();
- }
- }
- return observers.add(new Entry(name, reg, obs, type));
- }
-
- private static String createName() {
+ public static String add(Region reg, ObserverCallBack obs, ObserveEvent.Type type, Object target) {
String name = null;
- while (null == name) {
- name = "" + new Date().getTime();
- if (!hasName(name, null)) {
- return name;
- } else {
- name = null;
+ long now = new Date().getTime();
+ while (true) {
+ name = "" + now++;
+ if (!hasName(name)) {
+ break;
}
- try {
- Thread.sleep(5);
- } catch(Exception ex) {}
}
- return null;
+ observers.put("" + now, new ObserverEntry(reg, obs, type));
+ reg.getObserver().addObserver(target, (ObserverCallBack) obs, name, type);
+ return name;
}
- private static boolean hasName(String name, Region reg) {
- for (Entry obs : observers) {
- if (obs.name == null) {
- continue;
- }
- if (name.equals(obs.name)) {
- if (reg != null && reg == obs.region) {
- return true;
- }
- }
- }
- return false;
+ private static boolean hasName(String name) {
+ return observers.containsKey(name);
}
/**
* remove the observer from the list, a region observer will be stopped <br>
- * registered events for that observer are removed as well
+ * events for that observer are removed as well
*
* @param name name of observer
* @return success
*/
- public static boolean remove(String name) {
- return remove(null, name);
+ public static void remove(String name) {
+ if (observers.containsKey(name)) {
+ observers.get(name).region.stopObserver();
+ observers.remove(name);
+ events.remove(name);
+ }
}
/**
* stop and remove all observers registered for this region from the list <br>
- * registered events for those observers are removed as well
- *
- * @return success
- */
- public static boolean remove(Region reg) {
- return remove(reg, null);
- }
-
- /**
- * stop and remove the observer registered for this region from the list <br>
- * registered events for that observer are removed as well
- *
- * @param reg the observed region
- * @param name name of observer
- * @return success
+ * events for those observers are removed as well
+ * @param reg
*/
- public static synchronized boolean remove(Region reg, String name) {
- for (Entry obs : observers) {
- if (name != null) {
- if (name.equals(obs.name)) {
- if (reg == null || reg == obs.region) {
- remove(obs);
- }
- }
- } else if (reg != null && reg == obs.region) {
- remove(obs);
- }
- }
- return true;
- }
-
- private static synchronized void remove(Entry obs) {
- if (obs.region != null) {
- obs.region.stopObserver();
- }
- for (Event ev:events) {
- if (ev.observer == obs) {
- ev.destroy();
- }
+ public static void remove(Region reg) {
+ for (String name : reg.getObserver().getNames()) {
+ remove(name);
}
- obs.destroy();
- }
-
- private static Entry get(Region reg, String name) {
- for (Entry obs : observers) {
- if (name != null) {
- if (name.equals(obs.name)) {
- if (reg == null || reg == obs.region) {
- return obs;
- }
- }
- } else if (reg != null && reg == obs.region) {
- return obs;
- }
- }
- return null;
}
/**
* stop and remove all observers and their registered events
*
- * @return success
*/
- public static synchronized boolean clear() {
- log(lvl, "*** requested ***: remove all observers");
- for (Entry e : observers) {
- remove(e);
- }
- Iterator<Entry> itero = observers.iterator();
- while (itero.hasNext()) {
- if (itero.next() == null) {
- itero.remove();
- }
- }
- Iterator<Event> itere = events.iterator();
- while (itere.hasNext()) {
- if (itere.next() == null) {
- itere.remove();
+ public static void clear() {
+ synchronized (observers) {
+ for (String name : observers.keySet()) {
+ remove(name);
}
}
log(lvl, "as requested: removed all observers");
- return true;
}
/**
@@ -268,146 +142,79 @@ public class Observing {
*
* @return true if yes
*/
- public static synchronized boolean hasEvents() {
+ public static boolean hasEvents() {
return events.size() > 0;
}
/**
- * are their any events registered for this region
- *
- * @return true if yes
- */
- public static synchronized boolean hasEvents(Region reg) {
- return hasEvent(reg, null);
- }
-
- /**
- * are their any events registered for the observer having this name
+ * are their any events registered for this region?
*
* @return true if yes
*/
- public static synchronized boolean hasEvent(String name) {
- return hasEvent(null, name);
- }
-
- /**
- * are their any events registered for the region's observer having this name
- *
- * @return true if yes
- */
- public static synchronized boolean hasEvent(Region reg, String name) {
- Entry obs = get(reg, name);
- if (obs == null) {
- return false;
- }
- for (Event ev:events) {
- if (ev.observer == obs) {
+ public static boolean hasEvents(Region reg) {
+ for (String name : reg.getObserver().getNames()) {
+ if (events.containsKey(name)) {
return true;
}
}
- return false;
+ return false;
}
/**
- * add a new event to the list
+ * are their any events registered for the observer having this name?
*
- * @param name name of event
- * @param pev the event object (ObserveEvent is copied)
- * @return the time of creation
+ * @return true if yes
*/
- public static synchronized long addEvent(String name, Object pev) {
- long t = 0;
- if (pev instanceof ObserveEvent) {
- ObserveEvent evt = (ObserveEvent) new Event();
- ObserveEvent event = (ObserveEvent) pev;
- evt.type = event.type;
- evt.setChanges(event.getChanges());
- evt.setMatch(event.getMatch());
- evt.setPattern(event.getPattern());
- evt.setRegion(event.getRegion());
- pev = evt;
- }
- Event ev = (Event) pev;
- ev.observer = get(null, name);
- ev.time = new Date().getTime();
- if (events.add(ev)) {
- t = ev.time;
- }
- Iterator<Event> iter = events.iterator();
- while (iter.hasNext()) {
- if (iter.next() == null) {
- iter.remove();
- }
- }
- return t;
+ public static boolean hasEvent(String name) {
+ return events.containsKey(name);
}
/**
- * remove and return the latest event for the named observer <br>
- * earlier events are removed
+ * add a new event to the list
*
- * @param name
- * @return the event or null if none registered
+ * @param name name of event
*/
- public static synchronized Event getEvent(String name) {
- return getEvent(name, true);
- }
-
- private static Event getEvent(String name, boolean remove) {
- Entry obs = get(null, name);
- Event event = null;
- if (obs != null) {
- for (Event ev:events) {
- if (ev.observer == null) {
- continue;
- }
- if (ev.observer.name.equals(obs.name)) {
- if (event == null) {
- event = ev;
- continue;
- }
- if (ev.time > event.time) {
- event.destroy();
- event = ev;
- }
- }
- }
- }
- if (null != event && remove) {
- Event ev = new Event(event);
- event.destroy();
- event = ev;
- }
- return event;
+ public static void addEvent(ObserveEvent evt) {
+ events.put(evt.getName(), evt);
}
/**
- * remove and return the latest events for that region <br>
- * earlier events are removed as well
+ * return the events for that region <br>
+ * events are removed from the list
*
* @return the array of events or size 0 array if none
*/
- public static synchronized Event[] getEvents(Region reg) {
- List<Event> evts = new ArrayList<Event>();
- for (Entry obs:observers) {
- if (reg == obs.region) evts.add(getEvent(obs.name));
+ public static ObserveEvent[] getEvents(Region reg) {
+ List<ObserveEvent> evts = new ArrayList<ObserveEvent>();
+ ObserveEvent evt;
+ for (String name : reg.getObserver().getNames()) {
+ evt = events.get(name);
+ if (evt != null) evts.add(evt);
+ events.remove(name);
}
- return evts.toArray(new Event[0]);
+ return evts.toArray(new ObserveEvent[0]);
}
/**
- * return the latest events (these are preserved) <br>
- * earlier events for the same observer are removed
+ * return the all events (they are preserved) <br>
*
* @return the array of events or size 0 array if none
*/
- public static synchronized Event[] getEvents() {
- List<Event> evts = new ArrayList<Event>();
- for (Entry obs:observers) {
- if (obs.name != null) {
- evts.add(getEvent(obs.name, false));
+ public static ObserveEvent[] getEvents() {
+ List<ObserveEvent> evts = new ArrayList<ObserveEvent>();
+ ObserveEvent evt;
+ synchronized (events) {
+ for (String name : events.keySet()) {
+ evt = events.get(name);
+ if (evt == null) {
+ evts.add(evt);
+ }
}
- }
- return evts.toArray(new Event[0]);
+ }
+ return evts.toArray(new ObserveEvent[0]);
+ }
+
+ public static void clearEvents() {
+ events.clear();
}
}
diff --git a/API/src/main/java/org/sikuli/script/Region.java b/API/src/main/java/org/sikuli/script/Region.java
index 9343f0e..c563d87 100755
--- a/API/src/main/java/org/sikuli/script/Region.java
+++ b/API/src/main/java/org/sikuli/script/Region.java
@@ -81,13 +81,6 @@ public class Region {
*/
private Observer regionObserver = null;
- public Observer getEvtMgr() {
- return regionObserver;
- }
-
- public void setEvtMgr(Observer em) {
- regionObserver = em;
- }
/**
* The last found {@link Match} in the Region
*/
@@ -175,6 +168,7 @@ public class Region {
}
*/
//</editor-fold>
+
//<editor-fold defaultstate="collapsed" desc="Initialization">
/**
* Detects on which Screen the Region is present. The region is cropped to the intersection with the given screen or
@@ -355,6 +349,7 @@ public class Region {
}
//</editor-fold>
+
//<editor-fold defaultstate="collapsed" desc="Quasi-Constructors to be used in Java">
/**
* internal use only, used for new Screen objects to get the Region behavior
@@ -534,6 +529,7 @@ public class Region {
}
//</editor-fold>
+
//<editor-fold defaultstate="collapsed" desc="handle coordinates">
/**
* check if current region contains given point
@@ -1217,6 +1213,7 @@ public class Region {
}
//</editor-fold>
+
//<editor-fold defaultstate="collapsed" desc="spatial operators - new regions">
/**
* check if current region contains given region
@@ -2474,12 +2471,24 @@ public class Region {
public boolean isObserving() {
return observing;
}
+
+ /**
+ *
+ * @return true if any events have been before, false otherwise
+ */
+ public boolean hasEvents() {
+ return Observing.hasEvents(this);
+ }
+
+ public ObserveEvent[] getEvents() {
+ return Observing.getEvents(this);
+ }
/**
* a subsequently started observer in this region should wait for target
- * and notify the given observer about this event
- * for details about the observe event handler: {@link ObserverCallBack}
- * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}
+ * and notify the given observer about this event<br />
+ * for details about the observe event handler: {@link ObserverCallBack}<br />
+ * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}<br />
* @param <PSI> Pattern, String or Image
* @param target
* @param observer
@@ -2490,6 +2499,19 @@ public class Region {
}
/**
+ * a subsequently started observer in this region should wait for target
+ * success and details about the event can be obtained using @{link Observing}<br />
+ * for details about the observe event handler: {@link ObserverCallBack}<br />
+ * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}<br />
+ * @param <PSI> Pattern, String or Image
+ * @param target
+ * @return the event's name
+ */
+ public <PSI> String onAppear(PSI target) {
+ return onAppearDo(target, null);
+ }
+
+ /**
*INTERNAL USE ONLY: for use with scripting API bridges
* @param <PSI> Pattern, String or Image
* @param target
@@ -2501,17 +2523,18 @@ public class Region {
}
private <PSI> String onAppearDo(PSI target, Object observer) {
- String name = Observing.add(this, (ObserverCallBack) observer, ObserveEvent.Type.APPEAR);
- getObserver().addAppearObserver(target, (ObserverCallBack) observer, name);
- log(lvl, "%s: onAppear: %s with: %s", toStringShort(), name, target);
+ String name = Observing.add(this,
+ (ObserverCallBack) observer, ObserveEvent.Type.APPEAR, target);
+ log(lvl, "%s: onAppear%s: %s with: %s", toStringShort(),
+ (observer == null ? "" : " with callback"), name, target);
return name;
}
/**
* a subsequently started observer in this region should wait for the target to vanish
- * and notify the given observer about this event
- * for details about the observe event handler: {@link ObserverCallBack}
- * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}
+ * and notify the given observer about this event<br />
+ * for details about the observe event handler: {@link ObserverCallBack}<br />
+ * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}<br />
* @param <PSI> Pattern, String or Image
* @param target
* @param observer
@@ -2522,6 +2545,19 @@ public class Region {
}
/**
+ * a subsequently started observer in this region should wait for the target to vanish
+ * success and details about the event can be obtained using @{link Observing}<br />
+ * for details about the observe event handler: {@link ObserverCallBack}<br />
+ * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}<br />
+ * @param <PSI> Pattern, String or Image
+ * @param target
+ * @return the event's name
+ */
+ public <PSI> String onVanish(PSI target) {
+ return onVanishDo(target, null);
+ }
+
+ /**
*INTERNAL USE ONLY: for use with scripting API bridges
* @param <PSI> Pattern, String or Image
* @param target
@@ -2533,9 +2569,10 @@ public class Region {
}
private <PSI> String onVanishDo(PSI target, Object observer) {
- String name = Observing.add(this, (ObserverCallBack) observer, ObserveEvent.Type.VANISH);
- getObserver().addVanishObserver(target, (ObserverCallBack) observer, name);
- log(lvl, "%s: onVanish: %s with: %s", toStringShort(), name, target);
+ String name = Observing.add(this,
+ (ObserverCallBack) observer, ObserveEvent.Type.VANISH, target);
+ log(lvl, "%s: onVanish%s: %s with: %s", toStringShort(),
+ (observer == null ? "" : " with callback"), name, target);
return name;
}
@@ -2554,6 +2591,18 @@ public class Region {
/**
* a subsequently started observer in this region should wait for changes in the region
+ * success and details about the event can be obtained using @{link Observing}<br />
+ * for details about the observe event handler: {@link ObserverCallBack}
+ * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}
+ * @param threshold minimum size of changes (rectangle threshhold x threshold)
+ * @return the event's name
+ */
+ public String onChange(int threshold) {
+ return onChangeDo(threshold, null);
+ }
+
+ /**
+ * a subsequently started observer in this region should wait for changes in the region
* and notify the given observer about this event <br />
* minimum size of changes used: Settings.ObserveMinChangedPixels
* for details about the observe event handler: {@link ObserverCallBack}
@@ -2566,6 +2615,18 @@ public class Region {
}
/**
+ * a subsequently started observer in this region should wait for changes in the region
+ * success and details about the event can be obtained using @{link Observing}<br />
+ * minimum size of changes used: Settings.ObserveMinChangedPixels
+ * for details about the observe event handler: {@link ObserverCallBack}
+ * for details about APPEAR/VANISH/CHANGE events: {@link ObserveEvent}
+ * @return the event's name
+ */
+ public String onChange() {
+ return onChangeDo(0, null);
+ }
+
+ /**
*INTERNAL USE ONLY: for use with scripting API bridges
* @param minSize
* @param observer
@@ -2582,7 +2643,8 @@ public class Region {
public String onChangeDo(int threshold, Object observer) {
String name = Observing.add(this, (ObserverCallBack) observer, ObserveEvent.Type.CHANGE);
getObserver().addChangeObserver(threshold, (ObserverCallBack) observer, name);
- log(lvl, "%s: onChange: %s minSize: %d", toStringShort(), name, threshold);
+ log(lvl, "%s: onChange%s: %s minSize: %d", toStringShort(),
+ (observer == null ? "" : " with callback"), name, threshold);
return name;
}
@@ -2626,7 +2688,6 @@ public class Region {
Debug.error("Region: observe: Nothing to observe (Region might be invalid): " + this.toStringShort());
return false;
}
- Observing.getEvents(this);
if (observing) {
Debug.error("Region: observe: already running for this region. Only one allowed!");
return false;
@@ -2642,7 +2703,7 @@ public class Region {
}
regionObserver.initialize();
observing = true;
- SikuliX.addRunningObserver(this);
+ Observing.addRunningObserver(this);
while (observing && stop_t > (new Date()).getTime()) {
long before_find = (new Date()).getTime();
ScreenImage simg = getScreen().capture(x, y, w, h);
@@ -2671,7 +2732,6 @@ public class Region {
log(lvl, "observe: ended successfully: " + this.toStringShort());
observeSuccess = Observing.hasEvents(this);
}
- SikuliX.removeRunningObserver(this);
return observeSuccess;
}
diff --git a/API/src/main/java/org/sikuli/script/SikuliX.java b/API/src/main/java/org/sikuli/script/SikuliX.java
index 25c0bcf..18b4589 100644
--- a/API/src/main/java/org/sikuli/script/SikuliX.java
+++ b/API/src/main/java/org/sikuli/script/SikuliX.java
@@ -6,8 +6,6 @@
*/
package org.sikuli.script;
-import java.util.ArrayList;
-import java.util.List;
import org.sikuli.basics.CommandArgs;
import org.sikuli.basics.Debug;
import org.sikuli.basics.SikuliScript;
@@ -19,28 +17,6 @@ import org.sikuli.basics.SikuliScript;
public class SikuliX {
private static final String me = "SikuliX: ";
- private static List<Region> runningObservers = new ArrayList<Region>();
-
- public static void addRunningObserver(Region r) {
- runningObservers.add(r);
- Debug.log(3, me + "add observer: now running %d observer(s)", runningObservers.size());
- }
-
- public static void removeRunningObserver(Region r) {
- runningObservers.remove(r);
- Debug.log(3, me + "remove observer: now running %d observer(s)", runningObservers.size());
- }
-
- public static void stopRunningObservers() {
- if (runningObservers.size() > 0) {
- Debug.log(3, me + "stopping %d running observer(s)", runningObservers.size());
- for (Region r : runningObservers) {
- r.stopObserver();
- }
- runningObservers.clear();
- }
- Observing.clear();
- }
public static void endNormal(int n) {
Debug.log(3, me + "endNormal: %d", n);
@@ -73,7 +49,7 @@ public class SikuliX {
public static void cleanUp(int n) {
Debug.log(3, me + "cleanUp: %d", n);
ScreenHighlighter.closeAll();
- stopRunningObservers();
+ Observing.stopRunningObservers();
if (CommandArgs.isIDE()) {
//TODO reset selected options to defaults
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/sikuli.git
More information about the pkg-java-commits
mailing list