*/
package jexer;
+import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
* Wake the sleeping active event handler.
*/
private void wakeEventHandler() {
+ if (!started) {
+ return;
+ }
+
if (secondaryEventHandler != null) {
synchronized (secondaryEventHandler) {
secondaryEventHandler.notify();
*/
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().
*/
*/
private List<TTimer> timers;
+ /**
+ * When true, the application has been started.
+ */
+ private volatile boolean started = false;
+
/**
* When true, exit the application.
*/
primaryEventHandler = new WidgetEventHandler(this, true);
(new Thread(primaryEventHandler)).start();
+ started = true;
+
while (!quit) {
synchronized (this) {
boolean doWait = false;
if (debugEvents) {
System.err.printf("Handle event: %s\n", event);
}
+ TMouseEvent doubleClick = null;
// Special application-wide events -----------------------------------
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
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;
}
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);
+ }
}
}
}
* @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;
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);
+ }
}
/**
if (activeWindow != null) {
assert (activeWindow.getZ() == 0);
- activeWindow.onUnfocus();
activeWindow.setActive(false);
activeWindow.setZ(window.getZ());
+
+ // Unset activeWindow now before unfocus, so that a window
+ // lifecycle change inside onUnfocus() doesn't call
+ // switchWindow() and lead to a stack overflow.
+ TWindow oldActiveWindow = activeWindow;
+ activeWindow = null;
+ oldActiveWindow.onUnfocus();
}
activeWindow = window;
activeWindow.setZ(0);
// They selected the menu, go activate it
for (TMenu menu: menus) {
- if ((mouse.getAbsoluteX() >= menu.getX())
- && (mouse.getAbsoluteX() < menu.getX()
+ if ((mouse.getAbsoluteX() >= menu.getTitleX())
+ && (mouse.getAbsoluteX() < menu.getTitleX()
+ menu.getTitle().length() + 2)
) {
menu.setActive(true);
// See if we should switch menus
for (TMenu menu: menus) {
- if ((mouse.getAbsoluteX() >= menu.getX())
- && (mouse.getAbsoluteX() < menu.getX()
+ if ((mouse.getAbsoluteX() >= menu.getTitleX())
+ && (mouse.getAbsoluteX() < menu.getTitleX()
+ menu.getTitle().length() + 2)
) {
menu.setActive(true);
int x = 0;
for (TMenu menu: menus) {
menu.setX(x);
+ menu.setTitleX(x);
x += menu.getTitle().length() + 2;
// Don't let the menu window exceed the screen width
}
}
+ /**
+ * 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.
*
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 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);
+ }
+
/**
* Convenience function to spawn an file open box.
*
TWindow window = new TWindow(this, title, 0, 0, width, height);
return window;
}
+
/**
* Convenience function to create a new window and make it active.
* Window will be located at (0, 0).
return window;
}
+ /**
+ * Convenience function to open a file in an editor window and make it
+ * active.
+ *
+ * @param file the file to open
+ * @throws IOException if a java.io operation throws
+ */
+ public final TEditorWindow addEditor(final File file) throws IOException {
+
+ TEditorWindow editor = new TEditorWindow(this, file);
+ return editor;
+ }
+
}