From c950b791c6c4f94ab8a1777e709ecb259de7ab4f Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Fri, 8 Nov 2019 12:36:31 -0600 Subject: [PATCH] headless backend demo --- src/jexer/backend/ECMA48Terminal.java | 10 +- src/jexer/backend/HeadlessBackend.java | 134 +++++++++++++++++++++ src/jexer/demos/Demo8.java | 154 +++++++++++++++++++++++++ src/jexer/demos/Demo8.properties | 6 + 4 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 src/jexer/backend/HeadlessBackend.java create mode 100644 src/jexer/demos/Demo8.java create mode 100644 src/jexer/demos/Demo8.properties diff --git a/src/jexer/backend/ECMA48Terminal.java b/src/jexer/backend/ECMA48Terminal.java index ed2715c..0389f3d 100644 --- a/src/jexer/backend/ECMA48Terminal.java +++ b/src/jexer/backend/ECMA48Terminal.java @@ -1643,7 +1643,10 @@ public class ECMA48Terminal extends LogicalScreen * @return the width in pixels of a character cell */ public int getTextWidth() { - return (widthPixels / sessionInfo.getWindowWidth()); + if (sessionInfo.getWindowWidth() > 0) { + return (widthPixels / sessionInfo.getWindowWidth()); + } + return 16; } /** @@ -1652,7 +1655,10 @@ public class ECMA48Terminal extends LogicalScreen * @return the height in pixels of a character cell */ public int getTextHeight() { - return (heightPixels / sessionInfo.getWindowHeight()); + if (sessionInfo.getWindowHeight() > 0) { + return (heightPixels / sessionInfo.getWindowHeight()); + } + return 20; } /** diff --git a/src/jexer/backend/HeadlessBackend.java b/src/jexer/backend/HeadlessBackend.java new file mode 100644 index 0000000..19fb589 --- /dev/null +++ b/src/jexer/backend/HeadlessBackend.java @@ -0,0 +1,134 @@ +/* + * Jexer - Java Text User Interface + * + * The MIT License (MIT) + * + * Copyright (C) 2019 Kevin Lamonte + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ +package jexer.backend; + +import java.util.List; + +import jexer.event.TInputEvent; + +/** + * HeadlessBackend + */ +public class HeadlessBackend extends LogicalScreen implements Backend { + + // ------------------------------------------------------------------------ + // Variables -------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * The session information. + */ + private SessionInfo sessionInfo; + + // ------------------------------------------------------------------------ + // Constructors ----------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Public constructor. + */ + public HeadlessBackend() { + sessionInfo = new TSessionInfo(width, height); + } + + // ------------------------------------------------------------------------ + // Backend ---------------------------------------------------------------- + // ------------------------------------------------------------------------ + + /** + * Getter for sessionInfo. + * + * @return the SessionInfo + */ + public final SessionInfo getSessionInfo() { + return sessionInfo; + } + + /** + * Get a Screen, which displays the text cells to the user. + * + * @return the Screen + */ + public Screen getScreen() { + return this; + } + + /** + * Subclasses must provide an implementation that syncs the logical + * screen to the physical device. + */ + public void flushScreen() { + // NOP + } + + /** + * Check if there are events in the queue. + * + * @return if true, getEvents() has something to return to the application + */ + public boolean hasEvents() { + return false; + } + + /** + * Subclasses must provide an implementation to get keyboard, mouse, and + * screen resize events. + * + * @param queue list to append new events to + */ + public void getEvents(List queue) { + // NOP + } + + /** + * Subclasses must provide an implementation that closes sockets, + * restores console, etc. + */ + public void shutdown() { + // NOP + } + + /** + * Set listener to a different Object. + * + * @param listener the new listening object that run() wakes up on new + * input + */ + public void setListener(final Object listener) { + // NOP + } + + /** + * Reload backend options from System properties. + */ + public void reloadOptions() { + // NOP + } + +} diff --git a/src/jexer/demos/Demo8.java b/src/jexer/demos/Demo8.java new file mode 100644 index 0000000..19fe5ff --- /dev/null +++ b/src/jexer/demos/Demo8.java @@ -0,0 +1,154 @@ +/* + * Jexer - Java Text User Interface + * + * The MIT License (MIT) + * + * Copyright (C) 2019 Kevin Lamonte + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ +package jexer.demos; + +import java.net.ServerSocket; +import java.net.Socket; +import java.text.MessageFormat; +import java.util.ResourceBundle; + +import jexer.TApplication; +import jexer.backend.*; +import jexer.demos.DemoApplication; +import jexer.net.TelnetServerSocket; + + +/** + * This class shows off the use of MultiBackend and MultiScreen. + */ +public class Demo8 { + + /** + * Translated strings. + */ + private static final ResourceBundle i18n = ResourceBundle.getBundle(Demo8.class.getName()); + + // ------------------------------------------------------------------------ + // Demo8 ------------------------------------------------------------------ + // ------------------------------------------------------------------------ + + /** + * Main entry point. + * + * @param args Command line arguments + */ + public static void main(final String [] args) { + ServerSocket server = null; + try { + + /* + * In this demo we will create a headless application that anyone + * can telnet to. + */ + + /* + * Check the arguments for the port to listen on. + */ + if (args.length == 0) { + System.err.println(i18n.getString("usageString")); + return; + } + int port = Integer.parseInt(args[0]); + + /* + * We create a headless screen and use it to establish a + * MultiBackend. + */ + HeadlessBackend headlessBackend = new HeadlessBackend(); + MultiBackend multiBackend = new MultiBackend(headlessBackend); + + /* + * Now we create the shared application (a standard demo) and + * spin it up. + */ + DemoApplication demoApp = new DemoApplication(multiBackend); + (new Thread(demoApp)).start(); + multiBackend.setListener(demoApp); + + /* + * Fire up the telnet server. + */ + server = new TelnetServerSocket(port); + while (demoApp.isRunning()) { + Socket socket = server.accept(); + System.out.println(MessageFormat. + format(i18n.getString("newConnection"), socket)); + + ECMA48Backend ecmaBackend = new ECMA48Backend(demoApp, + socket.getInputStream(), + socket.getOutputStream()); + + /* + * Add this screen to the MultiBackend, and at this point we + * have the telnet client able to use the shared demo + * application. + */ + multiBackend.addBackend(ecmaBackend); + + /* + * Emit the connection information from telnet. + */ + Thread.sleep(500); + System.out.println(MessageFormat. + format(i18n.getString("terminal"), + ((jexer.net.TelnetInputStream) socket.getInputStream()). + getTerminalType())); + System.out.println(MessageFormat. + format(i18n.getString("username"), + ((jexer.net.TelnetInputStream) socket.getInputStream()). + getUsername())); + System.out.println(MessageFormat. + format(i18n.getString("language"), + ((jexer.net.TelnetInputStream) socket.getInputStream()). + getLanguage())); + + } // while (demoApp.isRunning()) + + /* + * When the application exits, kill all of the connections too. + */ + multiBackend.shutdown(); + server.close(); + + System.out.println(i18n.getString("exitMain")); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (server != null) { + try { + server.close(); + } catch (Exception e) { + // SQUASH + } + } + } + } + +} diff --git a/src/jexer/demos/Demo8.properties b/src/jexer/demos/Demo8.properties new file mode 100644 index 0000000..08a8217 --- /dev/null +++ b/src/jexer/demos/Demo8.properties @@ -0,0 +1,6 @@ +usageString=USAGE: java -cp jexer.jar jexer.demos.Demo8 port +newConnection=New connection: {0} +username=\ \ \ username: {0} +language=\ \ \ language: {0} +terminal=\ \ \ terminal: {0} +exitMain=Main thread is exiting... -- 2.27.0