X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTWindow.java;h=4d14d0eee2debcf23b03e2df314ea41721c38c8c;hb=HEAD;hp=140a38aa263f1c2138aed7ff558ada47df9507e1;hpb=d6ee0801333ff93dffd851f4c1a44519c96c371d;p=fanfix.git diff --git a/src/jexer/TWindow.java b/src/jexer/TWindow.java index 140a38a..4d14d0e 100644 --- a/src/jexer/TWindow.java +++ b/src/jexer/TWindow.java @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (C) 2017 Kevin Lamonte + * 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"), @@ -32,9 +32,9 @@ import java.util.HashSet; import java.util.Set; import jexer.backend.Screen; -import jexer.bits.Cell; import jexer.bits.CellAttributes; import jexer.bits.GraphicsChars; +import jexer.bits.StringUtils; import jexer.event.TCommandEvent; import jexer.event.TKeypressEvent; import jexer.event.TMenuEvent; @@ -91,6 +91,11 @@ public class TWindow extends TWidget { */ public static final int HIDEONCLOSE = 0x40; + /** + * Menus cannot be used when this window is active (default no). + */ + public static final int OVERRIDEMENU = 0x80; + // ------------------------------------------------------------------------ // Variables -------------------------------------------------------------- // ------------------------------------------------------------------------ @@ -185,6 +190,20 @@ public class TWindow extends TWidget { */ protected TStatusBar statusBar = null; + /** + * A window may request that TApplication NOT draw the mouse cursor over + * it by setting this to true. This is currently only used within Jexer + * by TTerminalWindow so that only the bottom-most instance of nested + * Jexer's draws the mouse within its application window. But perhaps + * other applications can use it, so public getter/setter is provided. + */ + private boolean hideMouse = false; + + /** + * The help topic for this window. + */ + protected String helpTopic = "Help"; + // ------------------------------------------------------------------------ // Constructors ----------------------------------------------------------- // ------------------------------------------------------------------------ @@ -337,19 +356,32 @@ public class TWindow extends TWidget { return false; } + /** + * Subclasses should override this method to perform any user prompting + * before they are offscreen. Note that unlike other windowing toolkits, + * windows can NOT use this function in some manner to avoid being + * closed. This is called by application.closeWindow(). + */ + protected void onPreClose() { + // Default: do nothing. + } + /** * Subclasses should override this method to cleanup resources. This is * called by application.closeWindow(). */ - public void onClose() { - // Default: do nothing + protected void onClose() { + // Default: perform widget-specific cleanup. + for (TWidget w: getChildren()) { + w.close(); + } } /** * Called by application.switchWindow() when this window gets the * focus, and also by application.addWindow(). */ - public void onFocus() { + protected void onFocus() { // Default: do nothing } @@ -357,21 +389,21 @@ public class TWindow extends TWidget { * Called by application.switchWindow() when another window gets the * focus. */ - public void onUnfocus() { + protected void onUnfocus() { // Default: do nothing } /** * Called by application.hideWindow(). */ - public void onHide() { + protected void onHide() { // Default: do nothing } /** * Called by application.showWindow(). */ - public void onShow() { + protected void onShow() { // Default: do nothing } @@ -385,6 +417,8 @@ public class TWindow extends TWidget { this.mouse = mouse; inKeyboardResize = false; + inWindowMove = false; + inWindowResize = false; if ((mouse.getAbsoluteY() == getY()) && mouse.isMouse1() @@ -512,12 +546,6 @@ public class TWindow extends TWidget { } if (inWindowResize) { - // Do not permit resizing below the status line - if (mouse.getAbsoluteY() == application.getDesktopBottom()) { - inWindowResize = false; - return; - } - // Move window over setWidth(resizeWindowWidth + (mouse.getAbsoluteX() - moveWindowMouseX)); @@ -537,23 +565,22 @@ public class TWindow extends TWidget { // Keep within min/max bounds if (getWidth() < minimumWindowWidth) { setWidth(minimumWindowWidth); - inWindowResize = false; } if (getHeight() < minimumWindowHeight) { setHeight(minimumWindowHeight); - inWindowResize = false; } if ((maximumWindowWidth > 0) && (getWidth() > maximumWindowWidth) ) { setWidth(maximumWindowWidth); - inWindowResize = false; } if ((maximumWindowHeight > 0) && (getHeight() > maximumWindowHeight) ) { setHeight(maximumWindowHeight); - inWindowResize = false; + } + if (getHeight() + getY() >= getApplication().getDesktopBottom()) { + setHeight(getApplication().getDesktopBottom() - getY()); } // Pass a resize event to my children @@ -579,6 +606,15 @@ public class TWindow extends TWidget { @Override public void onKeypress(final TKeypressEvent keypress) { + if (inWindowMove || inWindowResize) { + // ESC or ENTER - Exit size/move + if (keypress.equals(kbEsc) || keypress.equals(kbEnter)) { + inWindowMove = false; + inWindowResize = false; + return; + } + } + if (inKeyboardResize) { // ESC or ENTER - Exit size/move @@ -820,6 +856,38 @@ public class TWindow extends TWidget { super.onMenu(menu); } + /** + * Method that subclasses can override to handle window/screen resize + * events. + * + * @param resize resize event + */ + @Override + public void onResize(final TResizeEvent resize) { + if (resize.getType() == TResizeEvent.Type.WIDGET) { + if (getChildren().size() == 1) { + TWidget child = getChildren().get(0); + if ((child instanceof TSplitPane) + || (child instanceof TPanel) + ) { + if (this instanceof TDesktop) { + child.onResize(new TResizeEvent( + TResizeEvent.Type.WIDGET, + resize.getWidth(), resize.getHeight())); + } else { + child.onResize(new TResizeEvent( + TResizeEvent.Type.WIDGET, + resize.getWidth() - 2, resize.getHeight() - 2)); + } + } + return; + } + } + + // Pass on to TWidget. + super.onResize(resize); + } + // ------------------------------------------------------------------------ // TWidget ---------------------------------------------------------------- // ------------------------------------------------------------------------ @@ -854,14 +922,15 @@ public class TWindow extends TWidget { CellAttributes background = getBackground(); int borderType = getBorderType(); - getScreen().drawBox(0, 0, getWidth(), getHeight(), border, - background, borderType, true); + drawBox(0, 0, getWidth(), getHeight(), border, background, borderType, + true); // Draw the title - int titleLeft = (getWidth() - title.length() - 2) / 2; + int titleLength = StringUtils.width(title); + int titleLeft = (getWidth() - titleLength - 2) / 2; putCharXY(titleLeft, 0, ' ', border); - putStringXY(titleLeft + 1, 0, title); - putCharXY(titleLeft + title.length() + 1, 0, ' ', border); + putStringXY(titleLeft + 1, 0, title, border); + putCharXY(titleLeft + titleLength + 1, 0, ' ', border); if (isActive()) { @@ -1094,9 +1163,9 @@ public class TWindow extends TWidget { restoreWindowX = getX(); restoreWindowY = getY(); setWidth(getScreen().getWidth()); - setHeight(application.getDesktopBottom() - 1); + setHeight(application.getDesktopBottom() - application.getDesktopTop()); setX(0); - setY(1); + setY(application.getDesktopTop()); maximized = true; onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(), @@ -1158,6 +1227,7 @@ public class TWindow extends TWidget { /** * Activate window (bring to top and receive events). */ + @Override public void activate() { application.activateWindow(this); } @@ -1166,6 +1236,7 @@ public class TWindow extends TWidget { * Close window. Note that windows without a close box can still be * closed by calling the close() method. */ + @Override public void close() { application.closeWindow(this); } @@ -1227,6 +1298,20 @@ public class TWindow extends TWidget { return false; } + /** + * Returns true if this window does not want menus to work while it is + * visible. + * + * @return true if this window does not want menus to work while it is + * visible + */ + public final boolean hasOverriddenMenu() { + if ((flags & OVERRIDEMENU) != 0) { + return true; + } + return false; + } + /** * Retrieve the background color. * @@ -1264,7 +1349,15 @@ public class TWindow extends TWidget { if (!isModal() && (inWindowMove || inWindowResize || inKeyboardResize) ) { - assert (isActive()); + if (!isActive()) { + // The user's terminal never passed a mouse up event, and now + // another window is active but we never finished a drag. + inWindowMove = false; + inWindowResize = false; + inKeyboardResize = false; + return getTheme().getColor("twindow.border.inactive"); + } + return getTheme().getColor("twindow.border.windowmove"); } else if (isModal() && inWindowMove) { assert (isActive()); @@ -1323,148 +1416,48 @@ public class TWindow extends TWidget { } } - // ------------------------------------------------------------------------ - // Passthru for Screen functions ------------------------------------------ - // ------------------------------------------------------------------------ - /** - * Get the attributes at one location. + * Returns true if this window does not want the application-wide mouse + * cursor drawn over it. * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @return attributes at (x, y) + * @return true if this window does not want the application-wide mouse + * cursor drawn over it */ - public final CellAttributes getAttrXY(final int x, final int y) { - return getScreen().getAttrXY(x, y); + public boolean hasHiddenMouse() { + return hideMouse; } /** - * Set the attributes at one location. + * Set request to prevent the application-wide mouse cursor from being + * drawn over this window. * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param attr attributes to use (bold, foreColor, backColor) + * @param hideMouse if true, this window does not want the + * application-wide mouse cursor drawn over it */ - public final void putAttrXY(final int x, final int y, - final CellAttributes attr) { - - getScreen().putAttrXY(x, y, attr); + public final void setHiddenMouse(final boolean hideMouse) { + this.hideMouse = hideMouse; } /** - * Set the attributes at one location. + * Get this window's help topic to load. * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param attr attributes to use (bold, foreColor, backColor) - * @param clip if true, honor clipping/offset + * @return the topic name */ - public final void putAttrXY(final int x, final int y, - final CellAttributes attr, final boolean clip) { - - getScreen().putAttrXY(x, y, attr, clip); + public String getHelpTopic() { + return helpTopic; } /** - * Fill the entire screen with one character with attributes. + * Generate a human-readable string for this window. * - * @param ch character to draw - * @param attr attributes to use (bold, foreColor, backColor) + * @return a human-readable string */ - public final void putAll(final char ch, final CellAttributes attr) { - getScreen().putAll(ch, attr); - } - - /** - * Render one character with attributes. - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param ch character + attributes to draw - */ - public final void putCharXY(final int x, final int y, final Cell ch) { - getScreen().putCharXY(x, y, ch); - } - - /** - * Render one character with attributes. - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param ch character to draw - * @param attr attributes to use (bold, foreColor, backColor) - */ - public final void putCharXY(final int x, final int y, final char ch, - final CellAttributes attr) { - - getScreen().putCharXY(x, y, ch, attr); - } - - /** - * Render one character without changing the underlying attributes. - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param ch character to draw - */ - public final void putCharXY(final int x, final int y, final char ch) { - getScreen().putCharXY(x, y, ch); - } - - /** - * Render a string. Does not wrap if the string exceeds the line. - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param str string to draw - * @param attr attributes to use (bold, foreColor, backColor) - */ - public final void putStringXY(final int x, final int y, final String str, - final CellAttributes attr) { - - getScreen().putStringXY(x, y, str, attr); - } - - /** - * Render a string without changing the underlying attribute. Does not - * wrap if the string exceeds the line. - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param str string to draw - */ - public final void putStringXY(final int x, final int y, final String str) { - getScreen().putStringXY(x, y, str); - } - - /** - * Draw a vertical line from (x, y) to (x, y + n). - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param n number of characters to draw - * @param ch character to draw - * @param attr attributes to use (bold, foreColor, backColor) - */ - public final void vLineXY(final int x, final int y, final int n, - final char ch, final CellAttributes attr) { - - getScreen().vLineXY(x, y, n, ch, attr); - } - - /** - * Draw a horizontal line from (x, y) to (x + n, y). - * - * @param x column coordinate. 0 is the left-most column. - * @param y row coordinate. 0 is the top-most row. - * @param n number of characters to draw - * @param ch character to draw - * @param attr attributes to use (bold, foreColor, backColor) - */ - public final void hLineXY(final int x, final int y, final int n, - final char ch, final CellAttributes attr) { - - getScreen().hLineXY(x, y, n, ch, attr); + @Override + public String toString() { + return String.format("%s(%8x) \'%s\' Z %d position (%d, %d) " + + "geometry %dx%d hidden %s modal %s", + getClass().getName(), hashCode(), title, getZ(), + getX(), getY(), getWidth(), getHeight(), hidden, isModal()); } }