X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTApplication.java;h=e61cea28d631afba3c84964c7a2a13803c597aca;hb=eb29bbb5ec70c43895dd0f053630c7e3cd402cba;hp=b4c53ec3a5ea8899db40c6dbdda283abe85153f7;hpb=499fdccfad144aa58869d839d50edb898670626a;p=fanfix.git diff --git a/src/jexer/TApplication.java b/src/jexer/TApplication.java index b4c53ec..e61cea2 100644 --- a/src/jexer/TApplication.java +++ b/src/jexer/TApplication.java @@ -283,6 +283,10 @@ public class TApplication implements Runnable { * Wake the sleeping active event handler. */ private void wakeEventHandler() { + if (!started) { + return; + } + if (secondaryEventHandler != null) { synchronized (secondaryEventHandler) { secondaryEventHandler.notify(); @@ -350,6 +354,17 @@ public class TApplication implements Runnable { */ private int oldMouseY; + /** + * The last mouse up click time, used to determine if this is a mouse + * double-click. + */ + private long lastMouseUpTime; + + /** + * The amount of millis between mouse up events to assume a double-click. + */ + private long doubleClickTime = 250; + /** * Event queue that is filled by run(). */ @@ -415,6 +430,11 @@ public class TApplication implements Runnable { */ private List timers; + /** + * When true, the application has been started. + */ + private volatile boolean started = false; + /** * When true, exit the application. */ @@ -555,6 +575,39 @@ public class TApplication implements Runnable { // Constructors ----------------------------------------------------------- // ------------------------------------------------------------------------ + /** + * Public constructor. + * + * @param backendType BackendType.XTERM, BackendType.ECMA48 or + * BackendType.SWING + * @param windowWidth the number of text columns to start with + * @param windowHeight the number of text rows to start with + * @param fontSize the size in points + * @throws UnsupportedEncodingException if an exception is thrown when + * creating the InputStreamReader + */ + public TApplication(final BackendType backendType, final int windowWidth, + final int windowHeight, final int fontSize) + throws UnsupportedEncodingException { + + switch (backendType) { + case SWING: + backend = new SwingBackend(this, windowWidth, windowHeight, + fontSize); + break; + case XTERM: + // Fall through... + case ECMA48: + backend = new ECMA48Backend(this, null, null, windowWidth, + windowHeight, fontSize); + break; + default: + throw new IllegalArgumentException("Invalid backend type: " + + backendType); + } + TApplicationImpl(); + } + /** * Public constructor. * @@ -920,6 +973,8 @@ public class TApplication implements Runnable { primaryEventHandler = new WidgetEventHandler(this, true); (new Thread(primaryEventHandler)).start(); + started = true; + while (!quit) { synchronized (this) { boolean doWait = false; @@ -1071,6 +1126,7 @@ public class TApplication implements Runnable { if (debugEvents) { System.err.printf("Handle event: %s\n", event); } + TMouseEvent doubleClick = null; // Special application-wide events ----------------------------------- @@ -1082,6 +1138,25 @@ public class TApplication implements Runnable { oldMouseY = mouseY; mouseX = mouse.getX(); mouseY = mouse.getY(); + } else { + if (mouse.getType() == TMouseEvent.Type.MOUSE_UP) { + if ((mouse.getTime().getTime() - lastMouseUpTime) < + doubleClickTime) { + + // This is a double-click. + doubleClick = new TMouseEvent(TMouseEvent.Type. + MOUSE_DOUBLE_CLICK, + mouse.getX(), mouse.getY(), + mouse.getAbsoluteX(), mouse.getAbsoluteY(), + mouse.isMouse1(), mouse.isMouse2(), + mouse.isMouse3(), + mouse.isMouseWheelUp(), mouse.isMouseWheelDown()); + + } else { + // The first click of a potential double-click. + lastMouseUpTime = mouse.getTime().getTime(); + } + } } // See if we need to switch focus to another window or the menu @@ -1189,6 +1264,11 @@ public class TApplication implements Runnable { mouse.setX(mouse.getX() - window.getX()); mouse.setY(mouse.getY() - window.getY()); + if (doubleClick != null) { + doubleClick.setX(doubleClick.getX() - window.getX()); + doubleClick.setY(doubleClick.getY() - window.getY()); + } + if (window.mouseWouldHit(mouse)) { dispatchToDesktop = false; } @@ -1201,11 +1281,17 @@ public class TApplication implements Runnable { event); } window.handleEvent(event); + if (doubleClick != null) { + window.handleEvent(doubleClick); + } } if (dispatchToDesktop) { // This event is fair game for the desktop to process. if (desktop != null) { desktop.handleEvent(event); + if (doubleClick != null) { + desktop.handleEvent(doubleClick); + } } } } @@ -1219,6 +1305,8 @@ public class TApplication implements Runnable { * @see #primaryHandleEvent(TInputEvent event) */ private void secondaryHandleEvent(final TInputEvent event) { + TMouseEvent doubleClick = null; + // Peek at the mouse position if (event instanceof TMouseEvent) { TMouseEvent mouse = (TMouseEvent) event; @@ -1227,10 +1315,32 @@ public class TApplication implements Runnable { oldMouseY = mouseY; mouseX = mouse.getX(); mouseY = mouse.getY(); + } else { + if (mouse.getType() == TMouseEvent.Type.MOUSE_UP) { + if ((mouse.getTime().getTime() - lastMouseUpTime) < + doubleClickTime) { + + // This is a double-click. + doubleClick = new TMouseEvent(TMouseEvent.Type. + MOUSE_DOUBLE_CLICK, + mouse.getX(), mouse.getY(), + mouse.getAbsoluteX(), mouse.getAbsoluteY(), + mouse.isMouse1(), mouse.isMouse2(), + mouse.isMouse3(), + mouse.isMouseWheelUp(), mouse.isMouseWheelDown()); + + } else { + // The first click of a potential double-click. + lastMouseUpTime = mouse.getTime().getTime(); + } + } } } secondaryEventReceiver.handleEvent(event); + if (doubleClick != null) { + secondaryEventReceiver.handleEvent(doubleClick); + } } /** @@ -1546,6 +1656,12 @@ public class TApplication implements Runnable { windows.remove(0); activeWindow = null; for (TWindow w: windows) { + + // Do not activate a hidden window. + if (w.isHidden()) { + continue; + } + if (w.getZ() > z) { w.setZ(w.getZ() - 1); if (w.getZ() == 0) { @@ -1864,10 +1980,16 @@ public class TApplication implements Runnable { continue; } for (int x = w.getX(); x < w.getX() + w.getWidth(); x++) { + if (x < 0) { + continue; + } if (x >= width) { continue; } for (int y = w.getY(); y < w.getY() + w.getHeight(); y++) { + if (y < 0) { + continue; + } if (y >= height) { continue; } @@ -2317,6 +2439,24 @@ public class TApplication implements Runnable { } } + /** + * Post an event to process. + * + * @param event new event to add to the queue + */ + public final void postEvent(final TInputEvent event) { + synchronized (this) { + synchronized (fillEventQueue) { + fillEventQueue.add(event); + } + if (debugThreads) { + System.err.println(System.currentTimeMillis() + " " + + Thread.currentThread() + " postEvent() wake up main"); + } + this.notify(); + } + } + /** * Post an event to process and turn off the menu. * @@ -2720,6 +2860,53 @@ public class TApplication implements Runnable { return new TTerminalWindow(this, x, y, flags); } + /** + * Convenience function to open a terminal window and execute a custom + * command line inside it. + * + * @param x column relative to parent + * @param y row relative to parent + * @param commandLine the command line to execute + * @return the terminal new window + */ + public final TTerminalWindow openTerminal(final int x, final int y, + final String commandLine) { + + return openTerminal(x, y, TWindow.RESIZABLE, commandLine); + } + + /** + * Convenience function to open a terminal window and execute a custom + * command line inside it. + * + * @param x column relative to parent + * @param y row relative to parent + * @param flags mask of CENTERED, MODAL, or RESIZABLE + * @param command the command line to execute + * @return the terminal new window + */ + public final TTerminalWindow openTerminal(final int x, final int y, + final int flags, final String [] command) { + + return new TTerminalWindow(this, x, y, flags, command); + } + + /** + * Convenience function to open a terminal window and execute a custom + * command line inside it. + * + * @param x column relative to parent + * @param y row relative to parent + * @param flags mask of CENTERED, MODAL, or RESIZABLE + * @param commandLine the command line to execute + * @return the terminal new window + */ + public final TTerminalWindow openTerminal(final int x, final int y, + final int flags, final String commandLine) { + + return new TTerminalWindow(this, x, y, flags, commandLine.split("\\s")); + } + /** * Convenience function to spawn an file open box. *