timer and progress bar working
[fanfix.git] / src / jexer / TApplication.java
index 35aa32d0d0f5dd4c892ab4a3ae79db949b90effe..8786e693271aa6511c747a6d8eb016b640ef1ed7 100644 (file)
@@ -34,8 +34,11 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import jexer.bits.CellAttributes;
 import jexer.bits.ColorTheme;
@@ -109,6 +112,11 @@ public class TApplication {
      */
     private TMenu activeMenu = null;
 
+    /**
+     * Active keyboard accelerators.
+     */
+    private Map<TKeypress, TMenuItem> accelerators;
+
     /**
      * Windows and widgets pull colors from this ColorTheme.
      */
@@ -128,6 +136,11 @@ public class TApplication {
      */
     private List<TWindow> windows;
 
+    /**
+     * Timers that are being ticked.
+     */
+    private List<TTimer> timers;
+
     /**
      * When true, exit the application.
      */
@@ -204,6 +217,8 @@ public class TApplication {
         windows         = new LinkedList<TWindow>();
         menus           = new LinkedList<TMenu>();
         subMenus        = new LinkedList<TMenu>();
+        timers          = new LinkedList<TTimer>();
+        accelerators    = new HashMap<TKeypress, TMenuItem>();
     }
 
     /**
@@ -394,8 +409,8 @@ public class TApplication {
     private void metaHandleEvent(final TInputEvent event) {
 
         /*
-         System.err.printf(String.format("metaHandleEvents event: %s\n",
-         event)); System.err.flush();
+        System.err.printf(String.format("metaHandleEvents event: %s\n",
+                event)); System.err.flush();
          */
 
         if (quit) {
@@ -404,16 +419,6 @@ public class TApplication {
             return;
         }
 
-        // DEBUG
-        if (event instanceof TKeypressEvent) {
-            TKeypressEvent keypress = (TKeypressEvent) event;
-            if (keypress.equals(kbAltX)) {
-                quit = true;
-                return;
-            }
-        }
-        // DEBUG
-
         // Special application-wide events -------------------------------
 
         // Abort everything
@@ -530,15 +535,16 @@ public class TApplication {
             return;
         }
 
-        /*
-         TODO
-
         if (event instanceof TKeypressEvent) {
             TKeypressEvent keypress = (TKeypressEvent) event;
+
             // See if this key matches an accelerator, and if so dispatch the
             // menu event.
             TKeypress keypressLowercase = keypress.getKey().toLowerCase();
-            TMenuItem item = accelerators.get(keypressLowercase);
+            TMenuItem item = null;
+            synchronized (accelerators) {
+                item = accelerators.get(keypressLowercase);
+            }
             if (item != null) {
                 // Let the menu item dispatch
                 item.dispatch();
@@ -550,7 +556,6 @@ public class TApplication {
                 }
             }
         }
-         */
 
         if (event instanceof TCommandEvent) {
             if (onCommand((TCommandEvent) event)) {
@@ -597,28 +602,25 @@ public class TApplication {
      * Do stuff when there is no user input.
      */
     private void doIdle() {
-        /*
-         TODO
         // Now run any timers that have timed out
-        auto now = Clock.currTime;
-        TTimer [] keepTimers;
-        foreach (t; timers) {
-            if (t.nextTick < now) {
-                t.tick();
-                if (t.recurring == true) {
-                    keepTimers ~= t;
+        Date now = new Date();
+        List<TTimer> keepTimers = new LinkedList<TTimer>();
+        for (TTimer timer: timers) {
+            if (timer.getNextTick().getTime() < now.getTime()) {
+                timer.tick();
+                if (timer.recurring == true) {
+                    keepTimers.add(timer);
                 }
             } else {
-                keepTimers ~= t;
+                keepTimers.add(timer);
             }
         }
         timers = keepTimers;
 
         // Call onIdle's
-        foreach (w; windows) {
-            w.onIdle();
+        for (TWindow window: windows) {
+            window.onIdle();
         }
-         */
     }
 
     /**
@@ -628,24 +630,20 @@ public class TApplication {
      * @return number of milliseconds between now and the next timer event
      */
     protected int getSleepTime(final int timeout) {
-        /*
-        auto now = Clock.currTime;
-        auto sleepTime = dur!("msecs")(timeout);
-        foreach (t; timers) {
-            if (t.nextTick < now) {
+        Date now = new Date();
+        long sleepTime = timeout;
+        for (TTimer timer: timers) {
+            if (timer.getNextTick().getTime() < now.getTime()) {
                 return 0;
             }
-            if ((t.nextTick > now) &&
-                ((t.nextTick - now) < sleepTime)
+            if ((timer.getNextTick().getTime() > now.getTime())
+                && ((timer.getNextTick().getTime() - now.getTime()) < sleepTime)
             ) {
-                sleepTime = t.nextTick - now;
+                sleepTime = timer.getNextTick().getTime() - now.getTime();
             }
         }
-        assert(sleepTime.total!("msecs")() >= 0);
-        return cast(uint)sleepTime.total!("msecs")();
-         */
-        // TODO: fix timers.  Until then, come back after 250 millis.
-        return 250;
+        assert (sleepTime >= 0);
+        return (int)sleepTime;
     }
 
     /**
@@ -1126,11 +1124,13 @@ public class TApplication {
      */
     public final void addAccelerator(final TMenuItem item,
         final TKeypress keypress) {
-        /*
-         TODO
-        assert((keypress in accelerators) is null);
-        accelerators[keypress] = item;
-         */
+
+        // System.err.printf("addAccelerator: key %s item %s\n", keypress, item);
+
+        synchronized (accelerators) {
+            assert (accelerators.get(keypress) == null);
+            accelerators.put(keypress, item);
+        }
     }
 
     /**
@@ -1310,9 +1310,9 @@ public class TApplication {
         List<TWindow> sorted = new LinkedList<TWindow>(windows);
         Collections.sort(sorted);
         Collections.reverse(sorted);
-        for (TWindow w: sorted) {
-            w.setX(x);
-            w.setY(y);
+        for (TWindow window: sorted) {
+            window.setX(x);
+            window.setY(y);
             x++;
             y++;
             if (x > getScreen().getWidth()) {
@@ -1324,4 +1324,32 @@ public class TApplication {
         }
     }
 
+    /**
+     * Convenience function to add a timer.
+     *
+     * @param duration number of milliseconds to wait between ticks
+     * @param recurring if true, re-schedule this timer after every tick
+     * @param action function to call when button is pressed
+     */
+    public final TTimer addTimer(final long duration, final boolean recurring,
+        final TAction action) {
+
+        TTimer timer = new TTimer(duration, recurring, action);
+        synchronized (timers) {
+            timers.add(timer);
+        }
+        return timer;
+    }
+
+    /**
+     * Convenience function to remove a timer.
+     *
+     * @param timer timer to remove
+     */
+    public final void removeTimer(final TTimer timer) {
+        synchronized (timers) {
+            timers.remove(timer);
+        }
+    }
+
 }