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 <[email protected]> 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 _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

