#18 Eliminate initial delay
[nikiroo-utils.git] / src / jexer / TApplication.java
index c783d8d087237f129e2171ad967be60619ed550d..09f617ed82fd45a259ce62410d1d35e82641cf03 100644 (file)
@@ -54,6 +54,7 @@ import jexer.backend.Backend;
 import jexer.backend.Screen;
 import jexer.backend.SwingBackend;
 import jexer.backend.ECMA48Backend;
+import jexer.backend.TWindowBackend;
 import jexer.menu.TMenu;
 import jexer.menu.TMenuItem;
 import static jexer.TCommand.*;
@@ -405,7 +406,15 @@ public class TApplication implements Runnable {
      * @return the Screen
      */
     public final Screen getScreen() {
-        return backend.getScreen();
+        if (backend instanceof TWindowBackend) {
+            // We are being rendered to a TWindow.  We can't use its
+            // getScreen() method because that is how it is rendering to a
+            // hardware backend somewhere.  Instead use its getOtherScreen()
+            // method.
+            return ((TWindowBackend) backend).getOtherScreen();
+        } else {
+            return backend.getScreen();
+        }
     }
 
     /**
@@ -571,7 +580,7 @@ public class TApplication implements Runnable {
     }
 
     /**
-     * Get the list of windows.
+     * Get a (shallow) copy of the window list.
      *
      * @return a copy of the list of windows for this application
      */
@@ -719,6 +728,7 @@ public class TApplication implements Runnable {
      */
     public TApplication(final Backend backend) {
         this.backend = backend;
+        backend.setListener(this);
         TApplicationImpl();
     }
 
@@ -921,10 +931,16 @@ public class TApplication implements Runnable {
      * Run this application until it exits.
      */
     public void run() {
+        boolean first = true;
+
         while (!quit) {
             // Timeout is in milliseconds, so default timeout after 1 second
             // of inactivity.
             long timeout = 1000;
+            if (first) {
+                first = false;
+                timeout = 0;
+            }
 
             // If I've got no updates to render, wait for something from the
             // backend or a timer.
@@ -1061,19 +1077,6 @@ public class TApplication implements Runnable {
             return;
         }
 
-        // Peek at the mouse position
-        if (event instanceof TMouseEvent) {
-            TMouseEvent mouse = (TMouseEvent) event;
-            synchronized (getScreen()) {
-                if ((mouseX != mouse.getX()) || (mouseY != mouse.getY())) {
-                    oldMouseX = mouseX;
-                    oldMouseY = mouseY;
-                    mouseX = mouse.getX();
-                    mouseY = mouse.getY();
-                }
-            }
-        }
-
         // Put into the main queue
         drainEventQueue.add(event);
     }
@@ -1096,6 +1099,14 @@ public class TApplication implements Runnable {
 
         // Peek at the mouse position
         if (event instanceof TMouseEvent) {
+            TMouseEvent mouse = (TMouseEvent) event;
+            if ((mouseX != mouse.getX()) || (mouseY != mouse.getY())) {
+                oldMouseX = mouseX;
+                oldMouseY = mouseY;
+                mouseX = mouse.getX();
+                mouseY = mouse.getY();
+            }
+
             // See if we need to switch focus to another window or the menu
             checkSwitchFocus((TMouseEvent) event);
         }
@@ -1231,6 +1242,17 @@ public class TApplication implements Runnable {
      * @see #primaryHandleEvent(TInputEvent event)
      */
     private void secondaryHandleEvent(final TInputEvent event) {
+        // Peek at the mouse position
+        if (event instanceof TMouseEvent) {
+            TMouseEvent mouse = (TMouseEvent) event;
+            if ((mouseX != mouse.getX()) || (mouseY != mouse.getY())) {
+                oldMouseX = mouseX;
+                oldMouseY = mouseY;
+                mouseX = mouse.getX();
+                mouseY = mouse.getY();
+            }
+        }
+
         secondaryEventReceiver.handleEvent(event);
     }
 
@@ -1380,6 +1402,13 @@ public class TApplication implements Runnable {
             return;
         }
 
+        // Whatever window might be moving/dragging, stop it now.
+        for (TWindow w: windows) {
+            if (w.inMovements()) {
+                w.stopMovements();
+            }
+        }
+
         assert (windows.size() > 0);
 
         if (window.isHidden()) {
@@ -1439,6 +1468,13 @@ public class TApplication implements Runnable {
             return;
         }
 
+        // Whatever window might be moving/dragging, stop it now.
+        for (TWindow w: windows) {
+            if (w.inMovements()) {
+                w.stopMovements();
+            }
+        }
+
         assert (windows.size() > 0);
 
         if (!window.hidden) {
@@ -1470,6 +1506,13 @@ public class TApplication implements Runnable {
             return;
         }
 
+        // Whatever window might be moving/dragging, stop it now.
+        for (TWindow w: windows) {
+            if (w.inMovements()) {
+                w.stopMovements();
+            }
+        }
+
         assert (windows.size() > 0);
 
         if (window.hidden) {
@@ -1495,6 +1538,13 @@ public class TApplication implements Runnable {
         }
 
         synchronized (windows) {
+            // Whatever window might be moving/dragging, stop it now.
+            for (TWindow w: windows) {
+                if (w.inMovements()) {
+                    w.stopMovements();
+                }
+            }
+
             int z = window.getZ();
             window.setZ(-1);
             window.onUnfocus();
@@ -1559,6 +1609,12 @@ public class TApplication implements Runnable {
         assert (activeWindow != null);
 
         synchronized (windows) {
+            // Whatever window might be moving/dragging, stop it now.
+            for (TWindow w: windows) {
+                if (w.inMovements()) {
+                    w.stopMovements();
+                }
+            }
 
             // Swap z/active between active window and the next in the list
             int activeWindowI = -1;
@@ -1617,6 +1673,13 @@ public class TApplication implements Runnable {
         }
 
         synchronized (windows) {
+            // Whatever window might be moving/dragging, stop it now.
+            for (TWindow w: windows) {
+                if (w.inMovements()) {
+                    w.stopMovements();
+                }
+            }
+
             // Do not allow a modal window to spawn a non-modal window.  If a
             // modal window is active, then this window will become modal
             // too.
@@ -2077,6 +2140,53 @@ public class TApplication implements Runnable {
         }
     }
 
+    /**
+     * Get a (shallow) copy of the menu list.
+     *
+     * @return a copy of the menu list
+     */
+    public final List<TMenu> getAllMenus() {
+        return new LinkedList<TMenu>(menus);
+    }
+
+    /**
+     * Add a top-level menu to the list.
+     *
+     * @param menu the menu to add
+     * @throws IllegalArgumentException if the menu is already used in
+     * another TApplication
+     */
+    public final void addMenu(final TMenu menu) {
+        if ((menu.getApplication() != null)
+            && (menu.getApplication() != this)
+        ) {
+            throw new IllegalArgumentException("Menu " + menu + " is already " +
+                "part of application " + menu.getApplication());
+        }
+        closeMenu();
+        menus.add(menu);
+        recomputeMenuX();
+    }
+
+    /**
+     * Remove a top-level menu from the list.
+     *
+     * @param menu the menu to remove
+     * @throws IllegalArgumentException if the menu is already used in
+     * another TApplication
+     */
+    public final void removeMenu(final TMenu menu) {
+        if ((menu.getApplication() != null)
+            && (menu.getApplication() != this)
+        ) {
+            throw new IllegalArgumentException("Menu " + menu + " is already " +
+                "part of application " + menu.getApplication());
+        }
+        closeMenu();
+        menus.remove(menu);
+        recomputeMenuX();
+    }
+
     /**
      * Turn off a sub-menu.
      */
@@ -2357,6 +2467,16 @@ public class TApplication implements Runnable {
             return true;
         }
 
+        if (command.equals(cmMenu)) {
+            if (!modalWindowActive() && (activeMenu == null)) {
+                if (menus.size() > 0) {
+                    menus.get(0).setActive(true);
+                    activeMenu = menus.get(0);
+                    return true;
+                }
+            }
+        }
+
         return false;
     }