public void repeat(SikuliEvent.Type type, Object pattern, Match match, long secs) {
   if (type == SikuliEvent.Type.CHANGE) {
     Debug.error("EventMgr: repeat: CHANGE repeats automatically");
   } else if (type == SikuliEvent.Type.VANISH) {
     Debug.error("EventMgr: repeat: not supported for VANISH");
   } else if (type == SikuliEvent.Type.APPEAR) {
     _state.put(pattern, State.REPEAT);
     if (secs <= 0) {
       secs = (long) _region.getWaitForVanish();
     }
     _wait.put(pattern, (new Date()).getTime() + 1000 * secs);
     Debug.log(
         2,
         "EventMgr: repeat: requested for APPEAR: "
             + pattern.toString()
             + " at "
             + match.toStringShort()
             + " after "
             + secs
             + " seconds");
     sthgLeft = true;
   }
 }
 private void checkPatterns(ScreenImage simg) {
   Finder finder = null;
   if (Settings.UseImageFinder) {
     finder = new ImageFinder(_region);
     ((ImageFinder) finder).setIsMultiFinder();
   } else {
     finder = new Finder(simg, _region);
   }
   String imgOK;
   Debug.log(
       3,
       "observe: checkPatterns entry: sthgLeft: %s isObserving: %s",
       sthgLeft,
       _region.isObserving());
   for (Object ptn : _state.keySet()) {
     if (_state.get(ptn) != State.FIRST
         && _state.get(ptn) != State.UNKNOWN
         && _state.get(ptn) != State.REPEAT) {
       continue;
     }
     imgOK = null;
     if (ptn instanceof String) {
       imgOK = finder.find((String) ptn);
       Image img = Image.create((String) ptn);
       if (img.isValid()) {
         imgOK = finder.find(img);
       } else if (img.isText()) {
         imgOK = finder.findText((String) ptn);
       }
     } else if (ptn instanceof Pattern) {
       imgOK = finder.find((Pattern) ptn);
     } else if (ptn instanceof Image) {
       imgOK = finder.find((Image) ptn);
     }
     if (null == imgOK) {
       Debug.error("EventMgr: checkPatterns: Image not valid", ptn);
       _state.put(ptn, State.MISSING);
       continue;
     }
     if (_state.get(ptn) == State.REPEAT) {
       Debug.log(3, "repeat: checking");
       if (_lastMatch.get(ptn).exists(ptn) != null) {
         if ((new Date()).getTime() > _wait.get(ptn)) {
           _state.put(ptn, State.APPEARED);
           Debug.log(3, "repeat: vanish timeout");
           // time out
         } else {
           sthgLeft = true;
         }
         continue; // not vanished within given time or still there
       } else {
         _state.put(ptn, State.UNKNOWN);
         sthgLeft = true;
         Debug.log(3, "repeat: has vanished");
         continue; // has vanished, repeat
       }
     }
     Match m = null;
     boolean hasMatch = false;
     if (finder.hasNext()) {
       m = finder.next();
       if (m.getScore() >= getSimiliarity(ptn)) {
         hasMatch = true;
         _lastMatch.put(ptn, m);
       }
     }
     if (hasMatch) {
       Debug.log(
           2,
           "EventMgr: checkPatterns: "
               + ptn.toString()
               + " match: "
               + m.toStringShort()
               + " in "
               + _region.toStringShort());
     } else if (_state.get(ptn) == State.FIRST) {
       Debug.log(
           2,
           "EventMgr: checkPatterns: "
               + ptn.toString()
               + " match: "
               + "NO"
               + " in "
               + _region.toStringShort());
       _state.put(ptn, State.UNKNOWN);
     }
     if (_appearOb.containsKey(ptn)) {
       if (_state.get(ptn) != State.APPEARED) {
         if (hasMatch) {
           _state.put(ptn, State.APPEARED);
           _count.put(ptn, _count.get(ptn) + 1);
           callAppearObserver(ptn, m);
         } else {
           sthgLeft = true;
         }
       }
     } else if (_vanishOb.containsKey(ptn)) {
       if (_state.get(ptn) != State.VANISHED) {
         if (!hasMatch) {
           _state.put(ptn, State.VANISHED);
           _count.put(ptn, _count.get(ptn) + 1);
           callVanishObserver(ptn, _lastMatch.get(ptn));
         } else {
           sthgLeft = true;
         }
       }
     }
     if (!_region.isObserving()) {
       break;
     }
   }
   Debug.log(
       3,
       "observe: checkPatterns exit: sthgLeft: %s isObserving: %s",
       sthgLeft,
       _region.isObserving());
 }