From 0ee88b6d705993df0d9e32cdc08c619605c7d75c Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Sat, 8 Jul 2017 21:22:49 -0400 Subject: [PATCH] #14 stubs for TDesktop --- src/jexer/TApplication.java | 60 +++++++- src/jexer/TDesktop.java | 149 ++++++++++++++++++++ src/jexer/TWidget.java | 27 +++- src/jexer/bits/ColorTheme.java | 4 +- src/jexer/demos/Demo4.java | 69 +++++++++ src/jexer/demos/DesktopDemo.java | 68 +++++++++ src/jexer/demos/DesktopDemoApplication.java | 125 ++++++++++++++++ 7 files changed, 495 insertions(+), 7 deletions(-) create mode 100644 src/jexer/TDesktop.java create mode 100644 src/jexer/demos/Demo4.java create mode 100644 src/jexer/demos/DesktopDemo.java create mode 100644 src/jexer/demos/DesktopDemoApplication.java diff --git a/src/jexer/TApplication.java b/src/jexer/TApplication.java index c2aa656..4b0efa9 100644 --- a/src/jexer/TApplication.java +++ b/src/jexer/TApplication.java @@ -527,6 +527,34 @@ public class TApplication implements Runnable { return desktopBottom; } + /** + * An optional TDesktop background window that is drawn underneath + * everything else. + */ + private TDesktop desktop; + + /** + * Set the TDesktop instance. + * + * @param desktop a TDesktop instance, or null to remove the one that is + * set + */ + public final void setDesktop(final TDesktop desktop) { + if (this.desktop != null) { + this.desktop.onClose(); + } + this.desktop = desktop; + } + + /** + * Get the TDesktop instance. + * + * @return the desktop, or null if it is not set + */ + public final TDesktop getDesktop() { + return desktop; + } + // ------------------------------------------------------------------------ // General behavior ------------------------------------------------------- // ------------------------------------------------------------------------ @@ -650,6 +678,7 @@ public class TApplication implements Runnable { timers = new LinkedList(); accelerators = new HashMap(); menuItems = new ArrayList(); + desktop = new TDesktop(this); // Setup the main consumer thread primaryEventHandler = new WidgetEventHandler(this, true); @@ -714,9 +743,10 @@ public class TApplication implements Runnable { // Start with a clean screen getScreen().clear(); - // Draw the background - CellAttributes background = theme.getColor("tapplication.background"); - getScreen().putAll(GraphicsChars.HATCH, background); + // Draw the desktop + if (desktop != null) { + desktop.drawChildren(); + } // Draw each window in reverse Z order List sorted = new LinkedList(windows); @@ -957,6 +987,10 @@ public class TApplication implements Runnable { oldMouseX = 0; oldMouseY = 0; } + if (desktop != null) { + desktop.setDimensions(0, 0, resize.getWidth(), + resize.getHeight() - 1); + } return; } @@ -1088,6 +1122,7 @@ public class TApplication implements Runnable { } // Dispatch events to the active window ------------------------------- + boolean dispatchToDesktop = true; for (TWindow window: windows) { if (window.isActive()) { if (event instanceof TMouseEvent) { @@ -1097,7 +1132,14 @@ public class TApplication implements Runnable { assert (mouse.getY() == mouse.getAbsoluteY()); mouse.setX(mouse.getX() - window.getX()); mouse.setY(mouse.getY() - window.getY()); + + if (window.mouseWouldHit(mouse)) { + dispatchToDesktop = false; + } + } else if (event instanceof TKeypressEvent) { + dispatchToDesktop = false; } + if (debugEvents) { System.err.printf("TApplication dispatch event: %s\n", event); @@ -1106,7 +1148,14 @@ public class TApplication implements Runnable { break; } } + if (dispatchToDesktop) { + // This event is fair game for the desktop to process. + if (desktop != null) { + desktop.handleEvent(event); + } + } } + /** * Dispatch one event to the appropriate widget or application-level * event handler. This is the secondary event handler used by certain @@ -1303,6 +1352,11 @@ public class TApplication implements Runnable { return; } + // Do not add the desktop to the window list. + if (window instanceof TDesktop) { + return; + } + synchronized (windows) { // Do not allow a modal window to spawn a non-modal window. If a // modal window is active, then this window will become modal diff --git a/src/jexer/TDesktop.java b/src/jexer/TDesktop.java new file mode 100644 index 0000000..68e394e --- /dev/null +++ b/src/jexer/TDesktop.java @@ -0,0 +1,149 @@ +/* + * Jexer - Java Text User Interface + * + * The MIT License (MIT) + * + * Copyright (C) 2017 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; + +import jexer.bits.CellAttributes; +import jexer.bits.GraphicsChars; +import jexer.event.TKeypressEvent; +import jexer.event.TMenuEvent; +import jexer.event.TMouseEvent; +import jexer.event.TResizeEvent; + +/** + * TDesktop is a special-class window that is drawn underneath everything + * else. + */ +public class TDesktop extends TWindow { + + /** + * Public constructor. + * + * @param parent parent application + */ + public TDesktop(final TApplication parent) { + + super(parent, "", 0, 0, parent.getScreen().getWidth(), + parent.getScreen().getHeight() - 1); + + setActive(false); + } + + /** + * The default TDesktop draws a hatch character across everything. + */ + @Override + public void draw() { + CellAttributes background = getTheme().getColor("tdesktop.background"); + putAll(GraphicsChars.HATCH, background); + } + + /** + * Handle mouse button presses. + * + * @param mouse mouse button event + */ + @Override + public void onMouseDown(final TMouseEvent mouse) { + this.mouse = mouse; + + // Pass to children + for (TWidget widget: getChildren()) { + if (widget.mouseWouldHit(mouse)) { + // Dispatch to this child, also activate it + activate(widget); + + // Set x and y relative to the child's coordinates + mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX()); + mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY()); + widget.handleEvent(mouse); + return; + } + } + } + + /** + * Handle mouse button releases. + * + * @param mouse mouse button release event + */ + @Override + public void onMouseUp(final TMouseEvent mouse) { + this.mouse = mouse; + + // Pass to children + for (TWidget widget: getChildren()) { + if (widget.mouseWouldHit(mouse)) { + // Dispatch to this child, also activate it + activate(widget); + + // Set x and y relative to the child's coordinates + mouse.setX(mouse.getAbsoluteX() - widget.getAbsoluteX()); + mouse.setY(mouse.getAbsoluteY() - widget.getAbsoluteY()); + widget.handleEvent(mouse); + return; + } + } + } + + /** + * Handle mouse movements. + * + * @param mouse mouse motion event + */ + @Override + public void onMouseMotion(final TMouseEvent mouse) { + this.mouse = mouse; + + // Default: do nothing, pass to children instead + super.onMouseMotion(mouse); + } + + /** + * Handle keystrokes. + * + * @param keypress keystroke event + */ + @Override + public void onKeypress(final TKeypressEvent keypress) { + // Default: do nothing, pass to children instead + super.onKeypress(keypress); + } + + /** + * Handle posted menu events. + * + * @param menu menu event + */ + @Override + public void onMenu(final TMenuEvent menu) { + // Default: do nothing, pass to children instead + super.onMenu(menu); + } + +} diff --git a/src/jexer/TWidget.java b/src/jexer/TWidget.java index 4450e52..5be209e 100644 --- a/src/jexer/TWidget.java +++ b/src/jexer/TWidget.java @@ -217,6 +217,23 @@ public abstract class TWidget implements Comparable { this.height = height; } + /** + * Change the dimensions. + * + * @param x absolute X position of the top-left corner + * @param y absolute Y position of the top-left corner + * @param width new widget width + * @param height new widget height + */ + public final void setDimensions(final int x, final int y, final int width, + final int height) { + + setX(x); + setY(y); + setWidth(width); + setHeight(height); + } + /** * My tab order inside a window or containing widget. */ @@ -427,7 +444,10 @@ public abstract class TWidget implements Comparable { if (parent == this) { return x; } - if ((parent instanceof TWindow) && !(parent instanceof TMenu)) { + if ((parent instanceof TWindow) + && !(parent instanceof TMenu) + && !(parent instanceof TDesktop) + ) { // Widgets on a TWindow have (0,0) as their top-left, but this is // actually the TWindow's (1,1). return parent.getAbsoluteX() + x + 1; @@ -446,7 +466,10 @@ public abstract class TWidget implements Comparable { if (parent == this) { return y; } - if ((parent instanceof TWindow) && !(parent instanceof TMenu)) { + if ((parent instanceof TWindow) + && !(parent instanceof TMenu) + && !(parent instanceof TDesktop) + ) { // Widgets on a TWindow have (0,0) as their top-left, but this is // actually the TWindow's (1,1). return parent.getAbsoluteY() + y + 1; diff --git a/src/jexer/bits/ColorTheme.java b/src/jexer/bits/ColorTheme.java index 5ed5032..8a67d18 100644 --- a/src/jexer/bits/ColorTheme.java +++ b/src/jexer/bits/ColorTheme.java @@ -240,12 +240,12 @@ public final class ColorTheme { color.setBold(false); colors.put("twindow.background.windowmove", color); - // TApplication background + // TDesktop background color = new CellAttributes(); color.setForeColor(Color.BLUE); color.setBackColor(Color.WHITE); color.setBold(false); - colors.put("tapplication.background", color); + colors.put("tdesktop.background", color); // TButton text color = new CellAttributes(); diff --git a/src/jexer/demos/Demo4.java b/src/jexer/demos/Demo4.java new file mode 100644 index 0000000..5de0bed --- /dev/null +++ b/src/jexer/demos/Demo4.java @@ -0,0 +1,69 @@ +/* + * Jexer - Java Text User Interface + * + * The MIT License (MIT) + * + * Copyright (C) 2017 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 jexer.*; + +/** + * This class is the main driver for a simple demonstration of Jexer's + * capabilities. This one shows TDesktop and TWindow API details. + */ +public class Demo4 { + + /** + * Main entry point. + * + * @param args Command line arguments + */ + public static void main(final String [] args) { + try { + // Swing is the default backend on Windows unless explicitly + // overridden by jexer.Swing. + TApplication.BackendType backendType = TApplication.BackendType.XTERM; + if (System.getProperty("os.name").startsWith("Windows")) { + backendType = TApplication.BackendType.SWING; + } + if (System.getProperty("os.name").startsWith("Mac")) { + backendType = TApplication.BackendType.SWING; + } + if (System.getProperty("jexer.Swing") != null) { + if (System.getProperty("jexer.Swing", "false").equals("true")) { + backendType = TApplication.BackendType.SWING; + } else { + backendType = TApplication.BackendType.XTERM; + } + } + DesktopDemoApplication app = new DesktopDemoApplication(backendType); + (new Thread(app)).start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/jexer/demos/DesktopDemo.java b/src/jexer/demos/DesktopDemo.java new file mode 100644 index 0000000..3cd713a --- /dev/null +++ b/src/jexer/demos/DesktopDemo.java @@ -0,0 +1,68 @@ +/* + * Jexer - Java Text User Interface + * + * The MIT License (MIT) + * + * Copyright (C) 2017 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.io.*; +import java.util.*; + +import jexer.*; +import jexer.event.*; +import jexer.menu.*; + +/** + * The modified desktop. + */ +public class DesktopDemo extends TDesktop { + + /** + * If true, draw the hatch. Note package private access. + */ + boolean drawHatch = true; + + /** + * The default TDesktop draws a hatch character across everything. This + * version is selectable. + */ + @Override + public void draw() { + if (drawHatch) { + super.draw(); + } + } + + /** + * Public constructor. + * + * @param parent parent application + */ + public DesktopDemo(final TApplication parent) { + super(parent); + } + +} diff --git a/src/jexer/demos/DesktopDemoApplication.java b/src/jexer/demos/DesktopDemoApplication.java new file mode 100644 index 0000000..395817d --- /dev/null +++ b/src/jexer/demos/DesktopDemoApplication.java @@ -0,0 +1,125 @@ +/* + * Jexer - Java Text User Interface + * + * The MIT License (MIT) + * + * Copyright (C) 2017 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.io.*; +import java.util.*; + +import jexer.*; +import jexer.event.*; +import jexer.menu.*; + +/** + * The demo application itself. + */ +public class DesktopDemoApplication extends TApplication { + + /** + * Add all the widgets of the demo. + */ + private void addAllWidgets() { + + // Add the menus + addFileMenu(); + addEditMenu(); + addWindowMenu(); + addHelpMenu(); + + final DesktopDemo desktop = new DesktopDemo(this); + setDesktop(desktop); + + desktop.addButton("&Remove HATCH", 2, 5, + new TAction() { + public void DO() { + desktop.drawHatch = false; + } + } + ); + desktop.addButton("&Show HATCH", 2, 8, + new TAction() { + public void DO() { + desktop.drawHatch = true; + } + } + ); + } + + /** + * Handle menu events. + * + * @param menu menu event + * @return if true, the event was processed and should not be passed onto + * a window + */ + @Override + public boolean onMenu(final TMenuEvent menu) { + + if (menu.getId() == TMenu.MID_OPEN_FILE) { + try { + String filename = fileOpenBox("."); + if (filename != null) { + try { + File file = new File(filename); + StringBuilder fileContents = new StringBuilder(); + Scanner scanner = new Scanner(file); + String EOL = System.getProperty("line.separator"); + + try { + while (scanner.hasNextLine()) { + fileContents.append(scanner.nextLine() + EOL); + } + new DemoTextWindow(this, filename, + fileContents.toString()); + } finally { + scanner.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + return super.onMenu(menu); + } + + /** + * Public constructor. + * + * @param backendType one of the TApplication.BackendType values + * @throws Exception if TApplication can't instantiate the Backend. + */ + public DesktopDemoApplication(final BackendType backendType) throws Exception { + super(backendType); + addAllWidgets(); + getBackend().setTitle("Jexer Demo Application"); + } +} -- 2.27.0