import jexer.backend.SwingTerminal;
import jexer.bits.Cell;
import jexer.bits.CellAttributes;
+import jexer.event.TCommandEvent;
import jexer.event.TKeypressEvent;
import jexer.event.TMenuEvent;
import jexer.event.TMouseEvent;
import jexer.tterminal.DisplayLine;
import jexer.tterminal.DisplayListener;
import jexer.tterminal.ECMA48;
+import static jexer.TCommand.*;
import static jexer.TKeypress.*;
/**
* TTerminalWidget exposes a ECMA-48 / ANSI X3.64 style terminal in a widget.
*/
public class TTerminalWidget extends TScrollableWidget
- implements DisplayListener {
+ implements DisplayListener, EditMenuUser {
/**
* Translated strings.
// Let TWidget set my size.
super.onResize(resize);
+ if (emulator == null) {
+ return;
+ }
+
// Synchronize against the emulator so we don't stomp on its reader
// thread.
synchronized (emulator) {
return;
}
- if (emulator.isReading()) {
+ if ((emulator != null) && (emulator.isReading())) {
// Get out of scrollback
setVerticalValue(0);
emulator.addUserEvent(keypress);
typingHidMouse = false;
}
- // If the emulator is tracking mouse buttons, it needs to see wheel
- // events.
- if (emulator.getMouseProtocol() == ECMA48.MouseProtocol.OFF) {
- if (mouse.isMouseWheelUp()) {
- verticalDecrement();
- dirty = true;
- return;
+ if (emulator != null) {
+ // If the emulator is tracking mouse buttons, it needs to see
+ // wheel events.
+ if (emulator.getMouseProtocol() == ECMA48.MouseProtocol.OFF) {
+ if (mouse.isMouseWheelUp()) {
+ verticalDecrement();
+ dirty = true;
+ return;
+ }
+ if (mouse.isMouseWheelDown()) {
+ verticalIncrement();
+ dirty = true;
+ return;
+ }
}
- if (mouse.isMouseWheelDown()) {
- verticalIncrement();
- dirty = true;
+ if (mouseOnEmulator(mouse)) {
+ emulator.addUserEvent(mouse);
+ readEmulatorState();
return;
}
}
- if (mouseOnEmulator(mouse)) {
- emulator.addUserEvent(mouse);
- readEmulatorState();
- return;
- }
// Emulator didn't consume it, pass it on
super.onMouseDown(mouse);
typingHidMouse = false;
}
- if (mouseOnEmulator(mouse)) {
+ if ((emulator != null) && (mouseOnEmulator(mouse))) {
emulator.addUserEvent(mouse);
readEmulatorState();
return;
typingHidMouse = false;
}
- if (mouseOnEmulator(mouse)) {
+ if ((emulator != null) && (mouseOnEmulator(mouse))) {
emulator.addUserEvent(mouse);
readEmulatorState();
return;
super.onMouseMotion(mouse);
}
+ /**
+ * Handle posted command events.
+ *
+ * @param command command event
+ */
+ @Override
+ public void onCommand(final TCommandEvent command) {
+ if (emulator == null) {
+ return;
+ }
+
+ if (command.equals(cmPaste)) {
+ // Paste text from clipboard.
+ String text = getClipboard().pasteText();
+ if (text != null) {
+ for (int i = 0; i < text.length(); ) {
+ int ch = text.codePointAt(i);
+ emulator.addUserEvent(new TKeypressEvent(false, 0, ch,
+ false, false, false));
+ i += Character.charCount(ch);
+ }
+ }
+ return;
+ }
+ }
+
// ------------------------------------------------------------------------
// TScrollableWidget ------------------------------------------------------
// ------------------------------------------------------------------------
*/
@Override
public void draw() {
+ if (emulator == null) {
+ return;
+ }
+
int width = getDisplayWidth();
boolean syncEmulator = false;
- if ((System.currentTimeMillis() - lastUpdateTime >= 20)
- && (dirty == true)
- ) {
+ if (System.currentTimeMillis() - lastUpdateTime >= 50) {
// Too much time has passed, draw it all.
syncEmulator = true;
} else if (emulator.isReading() && (dirty == false)) {
*/
@Override
public void close() {
- emulator.close();
+ if (emulator != null) {
+ emulator.close();
+ }
if (shell != null) {
terminateShellChildProcess();
shell.destroy();
*/
@Override
public void reflowData() {
+ if (emulator == null) {
+ return;
+ }
// Synchronize against the emulator so we don't stomp on its reader
// thread.
* cursor drawn over it
*/
public boolean hasHiddenMouse() {
+ if (emulator == null) {
+ return false;
+ }
return (emulator.hasHiddenMousePointer() || typingHidMouse);
}
* side
*/
public boolean isReading() {
+ if (emulator == null) {
+ return false;
+ }
return emulator.isReading();
}
* screen.
*/
private void readEmulatorState() {
+ if (emulator == null) {
+ return;
+ }
+
// Synchronize against the emulator so we don't stomp on its reader
// thread.
synchronized (emulator) {
* @return whether or not the mouse is on the emulator
*/
private boolean mouseOnEmulator(final TMouseEvent mouse) {
+ if (emulator == null) {
+ return false;
+ }
if (!emulator.isReading()) {
return false;
* Called by emulator when fresh data has come in.
*/
public void displayChanged() {
- dirty = true;
+ if (emulator != null) {
+ // Force sync here: EMCA48.run() thread might be setting
+ // dirty=true while TTerminalWdiget.draw() is setting
+ // dirty=false. If these writes start interleaving, the display
+ // stops getting updated.
+ synchronized (emulator) {
+ dirty = true;
+ }
+ } else {
+ dirty = true;
+ }
getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT));
}
return 24;
}
+ // ------------------------------------------------------------------------
+ // EditMenuUser -----------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Check if the cut menu item should be enabled.
+ *
+ * @return true if the cut menu item should be enabled
+ */
+ public boolean isEditMenuCut() {
+ return false;
+ }
+
+ /**
+ * Check if the copy menu item should be enabled.
+ *
+ * @return true if the copy menu item should be enabled
+ */
+ public boolean isEditMenuCopy() {
+ return false;
+ }
+
+ /**
+ * Check if the paste menu item should be enabled.
+ *
+ * @return true if the paste menu item should be enabled
+ */
+ public boolean isEditMenuPaste() {
+ return true;
+ }
+
+ /**
+ * Check if the clear menu item should be enabled.
+ *
+ * @return true if the clear menu item should be enabled
+ */
+ public boolean isEditMenuClear() {
+ return false;
+ }
+
}