TEditor working
[nikiroo-utils.git] / src / jexer / TWindow.java
index af8c2299df59f4cb8be94f52199d8fc6eee2510e..406eb7897a21a152329dbfc9c6ddee3bd52251aa 100644 (file)
@@ -30,6 +30,7 @@ package jexer;
 
 import java.util.HashSet;
 
+import jexer.backend.Screen;
 import jexer.bits.Cell;
 import jexer.bits.CellAttributes;
 import jexer.bits.GraphicsChars;
@@ -38,7 +39,6 @@ import jexer.event.TKeypressEvent;
 import jexer.event.TMenuEvent;
 import jexer.event.TMouseEvent;
 import jexer.event.TResizeEvent;
-import jexer.io.Screen;
 import jexer.menu.TMenu;
 import static jexer.TCommand.*;
 import static jexer.TKeypress.*;
@@ -67,6 +67,12 @@ public class TWindow extends TWidget {
      */
     public static final int CENTERED    = 0x04;
 
+    /**
+     * Window has no close box (default no).  Window can still be closed via
+     * TApplication.closeWindow() and TWindow.close().
+     */
+    public static final int NOCLOSEBOX  = 0x08;
+
     // ------------------------------------------------------------------------
     // Common window attributes -----------------------------------------------
     // ------------------------------------------------------------------------
@@ -278,9 +284,60 @@ public class TWindow extends TWidget {
      * @param maximumWindowWidth new maximum width
      */
     public final void setMaximumWindowWidth(final int maximumWindowWidth) {
+        if ((maximumWindowWidth != -1)
+            && (maximumWindowWidth < minimumWindowWidth + 1)
+        ) {
+            throw new IllegalArgumentException("Maximum window width cannot " +
+                "be smaller than minimum window width + 1");
+        }
         this.maximumWindowWidth = maximumWindowWidth;
     }
 
+    /**
+     * Set the minimum width for this window.
+     *
+     * @param minimumWindowWidth new minimum width
+     */
+    public final void setMinimumWindowWidth(final int minimumWindowWidth) {
+        if ((maximumWindowWidth != -1)
+            && (minimumWindowWidth > maximumWindowWidth - 1)
+        ) {
+            throw new IllegalArgumentException("Minimum window width cannot " +
+                "be larger than maximum window width - 1");
+        }
+        this.minimumWindowWidth = minimumWindowWidth;
+    }
+
+    /**
+     * Set the maximum height for this window.
+     *
+     * @param maximumWindowHeight new maximum height
+     */
+    public final void setMaximumWindowHeight(final int maximumWindowHeight) {
+        if ((maximumWindowHeight != -1)
+            && (maximumWindowHeight < minimumWindowHeight + 1)
+        ) {
+            throw new IllegalArgumentException("Maximum window height cannot " +
+                "be smaller than minimum window height + 1");
+        }
+        this.maximumWindowHeight = maximumWindowHeight;
+    }
+
+    /**
+     * Set the minimum height for this window.
+     *
+     * @param minimumWindowHeight new minimum height
+     */
+    public final void setMinimumWindowHeight(final int minimumWindowHeight) {
+        if ((maximumWindowHeight != -1)
+            && (minimumWindowHeight > maximumWindowHeight - 1)
+        ) {
+            throw new IllegalArgumentException("Minimum window height cannot " +
+                "be larger than maximum window height - 1");
+        }
+        this.minimumWindowHeight = minimumWindowHeight;
+    }
+
     /**
      * Recenter the window on-screen.
      */
@@ -303,7 +360,11 @@ public class TWindow extends TWidget {
     /**
      * Maximize window.
      */
-    private void maximize() {
+    public void maximize() {
+        if (maximized) {
+            return;
+        }
+
         restoreWindowWidth = getWidth();
         restoreWindowHeight = getHeight();
         restoreWindowX = getX();
@@ -316,9 +377,13 @@ public class TWindow extends TWidget {
     }
 
     /**
-     * Restote (unmaximize) window.
+     * Restore (unmaximize) window.
      */
-    private void restore() {
+    public void restore() {
+        if (!maximized) {
+            return;
+        }
+
         setWidth(restoreWindowWidth);
         setHeight(restoreWindowHeight);
         setX(restoreWindowX);
@@ -326,6 +391,67 @@ public class TWindow extends TWidget {
         maximized = false;
     }
 
+    // ------------------------------------------------------------------------
+    // Window visibility ------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Hidden flag.  A hidden window will still have its onIdle() called, and
+     * will also have onClose() called at application exit.  Note package
+     * private access: TApplication will force hidden false if a modal window
+     * is active.
+     */
+    boolean hidden = false;
+
+    /**
+     * Returns true if this window is hidden.
+     *
+     * @return true if this window is hidden, false if the window is shown
+     */
+    public final boolean isHidden() {
+        return hidden;
+    }
+
+    /**
+     * Returns true if this window is shown.
+     *
+     * @return true if this window is shown, false if the window is hidden
+     */
+    public final boolean isShown() {
+        return !hidden;
+    }
+
+    /**
+     * Hide window.  A hidden window will still have its onIdle() called, and
+     * will also have onClose() called at application exit.  Hidden windows
+     * will not receive any other events.
+     */
+    public void hide() {
+        application.hideWindow(this);
+    }
+
+    /**
+     * Show window.
+     */
+    public void show() {
+        application.showWindow(this);
+    }
+
+    /**
+     * Activate window (bring to top and receive events).
+     */
+    public void activate() {
+        application.activateWindow(this);
+    }
+
+    /**
+     * Close window.  Note that windows without a close box can still be
+     * closed by calling the close() method.
+     */
+    public void close() {
+        application.closeWindow(this);
+    }
+
     // ------------------------------------------------------------------------
     // Constructors -----------------------------------------------------------
     // ------------------------------------------------------------------------
@@ -433,6 +559,18 @@ public class TWindow extends TWidget {
         return true;
     }
 
+    /**
+     * Returns true if this window has a close box.
+     *
+     * @return true if this window has a close box
+     */
+    public final boolean hasCloseBox() {
+        if ((flags & NOCLOSEBOX) != 0) {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Retrieve the background color.
      *
@@ -539,18 +677,20 @@ public class TWindow extends TWidget {
         if (isActive()) {
 
             // Draw the close button
-            putCharXY(2, 0, '[', border);
-            putCharXY(4, 0, ']', border);
-            if (mouseOnClose() && mouse.isMouse1()) {
-                putCharXY(3, 0, GraphicsChars.CP437[0x0F],
-                    !isModal()
-                    ? getTheme().getColor("twindow.border.windowmove")
-                    : getTheme().getColor("twindow.border.modal.windowmove"));
-            } else {
-                putCharXY(3, 0, GraphicsChars.CP437[0xFE],
-                    !isModal()
-                    ? getTheme().getColor("twindow.border.windowmove")
-                    : getTheme().getColor("twindow.border.modal.windowmove"));
+            if ((flags & NOCLOSEBOX) == 0) {
+                putCharXY(2, 0, '[', border);
+                putCharXY(4, 0, ']', border);
+                if (mouseOnClose() && mouse.isMouse1()) {
+                    putCharXY(3, 0, GraphicsChars.CP437[0x0F],
+                        !isModal()
+                        ? getTheme().getColor("twindow.border.windowmove")
+                        : getTheme().getColor("twindow.border.modal.windowmove"));
+                } else {
+                    putCharXY(3, 0, GraphicsChars.CP437[0xFE],
+                        !isModal()
+                        ? getTheme().getColor("twindow.border.windowmove")
+                        : getTheme().getColor("twindow.border.modal.windowmove"));
+                }
             }
 
             // Draw the maximize button
@@ -593,7 +733,10 @@ public class TWindow extends TWidget {
      *
      * @return true if mouse is currently on the close button
      */
-    private boolean mouseOnClose() {
+    protected boolean mouseOnClose() {
+        if ((flags & NOCLOSEBOX) != 0) {
+            return false;
+        }
         if ((mouse != null)
             && (mouse.getAbsoluteY() == getY())
             && (mouse.getAbsoluteX() == getX() + 3)
@@ -608,7 +751,7 @@ public class TWindow extends TWidget {
      *
      * @return true if the mouse is currently on the maximize/restore button
      */
-    private boolean mouseOnMaximize() {
+    protected boolean mouseOnMaximize() {
         if ((mouse != null)
             && !isModal()
             && (mouse.getAbsoluteY() == getY())
@@ -626,7 +769,7 @@ public class TWindow extends TWidget {
      * @return true if the mouse is currently on the resizable lower right
      * corner
      */
-    private boolean mouseOnResize() {
+    protected boolean mouseOnResize() {
         if (((flags & RESIZABLE) != 0)
             && !isModal()
             && (mouse != null)
@@ -663,6 +806,20 @@ public class TWindow extends TWidget {
         // Default: do nothing
     }
 
+    /**
+     * Called by application.hideWindow().
+     */
+    public void onHide() {
+        // Default: do nothing
+    }
+
+    /**
+     * Called by application.showWindow().
+     */
+    public void onShow() {
+        // Default: do nothing
+    }
+
     /**
      * Handle mouse button presses.
      *
@@ -795,6 +952,12 @@ 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));
@@ -883,38 +1046,46 @@ public class TWindow extends TWidget {
                     setY(getY() - 1);
                 }
             }
-            if (keypress.equals(kbShiftLeft)) {
-                if ((getWidth() > minimumWindowWidth)
-                    || (minimumWindowWidth <= 0)
-                ) {
-                    setWidth(getWidth() - 1);
+
+            /*
+             * Only permit keyboard resizing if the window was RESIZABLE.
+             */
+            if ((flags & RESIZABLE) != 0) {
+
+                if (keypress.equals(kbShiftLeft)) {
+                    if ((getWidth() > minimumWindowWidth)
+                        || (minimumWindowWidth <= 0)
+                    ) {
+                        setWidth(getWidth() - 1);
+                    }
                 }
-            }
-            if (keypress.equals(kbShiftRight)) {
-                if ((getWidth() < maximumWindowWidth)
-                    || (maximumWindowWidth <= 0)
-                ) {
-                    setWidth(getWidth() + 1);
+                if (keypress.equals(kbShiftRight)) {
+                    if ((getWidth() < maximumWindowWidth)
+                        || (maximumWindowWidth <= 0)
+                    ) {
+                        setWidth(getWidth() + 1);
+                    }
                 }
-            }
-            if (keypress.equals(kbShiftUp)) {
-                if ((getHeight() > minimumWindowHeight)
-                    || (minimumWindowHeight <= 0)
-                ) {
-                    setHeight(getHeight() - 1);
+                if (keypress.equals(kbShiftUp)) {
+                    if ((getHeight() > minimumWindowHeight)
+                        || (minimumWindowHeight <= 0)
+                    ) {
+                        setHeight(getHeight() - 1);
+                    }
                 }
-            }
-            if (keypress.equals(kbShiftDown)) {
-                if ((getHeight() < maximumWindowHeight)
-                    || (maximumWindowHeight <= 0)
-                ) {
-                    setHeight(getHeight() + 1);
+                if (keypress.equals(kbShiftDown)) {
+                    if ((getHeight() < maximumWindowHeight)
+                        || (maximumWindowHeight <= 0)
+                    ) {
+                        setHeight(getHeight() + 1);
+                    }
                 }
-            }
 
-            // Pass a resize event to my children
-            onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
-                    getWidth(), getHeight()));
+                // Pass a resize event to my children
+                onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                        getWidth(), getHeight()));
+
+            } // if ((flags & RESIZABLE) != 0)
 
             return;
         }
@@ -930,37 +1101,43 @@ public class TWindow extends TWidget {
         // overrides onMenu() due to how TApplication dispatches
         // accelerators.
 
-        // Ctrl-W - close window
-        if (keypress.equals(kbCtrlW)) {
-            application.closeWindow(this);
-            return;
-        }
+        if (!(this instanceof TDesktop)) {
 
-        // F6 - behave like Alt-TAB
-        if (keypress.equals(kbF6)) {
-            application.switchWindow(true);
-            return;
-        }
+            // Ctrl-W - close window
+            if (keypress.equals(kbCtrlW)) {
+                if ((flags & NOCLOSEBOX) == 0) {
+                    application.closeWindow(this);
+                }
+                return;
+            }
 
-        // Shift-F6 - behave like Shift-Alt-TAB
-        if (keypress.equals(kbShiftF6)) {
-            application.switchWindow(false);
-            return;
-        }
+            // F6 - behave like Alt-TAB
+            if (keypress.equals(kbF6)) {
+                application.switchWindow(true);
+                return;
+            }
 
-        // F5 - zoom
-        if (keypress.equals(kbF5)) {
-            if (maximized) {
-                restore();
-            } else {
-                maximize();
+            // Shift-F6 - behave like Shift-Alt-TAB
+            if (keypress.equals(kbShiftF6)) {
+                application.switchWindow(false);
+                return;
             }
-        }
 
-        // Ctrl-F5 - size/move
-        if (keypress.equals(kbCtrlF5)) {
-            inKeyboardResize = !inKeyboardResize;
-        }
+            // F5 - zoom
+            if (keypress.equals(kbF5)) {
+                if (maximized) {
+                    restore();
+                } else {
+                    maximize();
+                }
+            }
+
+            // Ctrl-F5 - size/move
+            if (keypress.equals(kbCtrlF5)) {
+                inKeyboardResize = !inKeyboardResize;
+            }
+
+        } // if (!(this instanceof TDesktop))
 
         // I didn't take it, pass it on to my children
         super.onKeypress(keypress);
@@ -978,33 +1155,39 @@ public class TWindow extends TWidget {
         // overrides onMenu() due to how TApplication dispatches
         // accelerators.
 
-        if (command.equals(cmWindowClose)) {
-            application.closeWindow(this);
-            return;
-        }
+        if (!(this instanceof TDesktop)) {
 
-        if (command.equals(cmWindowNext)) {
-            application.switchWindow(true);
-            return;
-        }
+            if (command.equals(cmWindowClose)) {
+                if ((flags & NOCLOSEBOX) == 0) {
+                    application.closeWindow(this);
+                }
+                return;
+            }
 
-        if (command.equals(cmWindowPrevious)) {
-            application.switchWindow(false);
-            return;
-        }
+            if (command.equals(cmWindowNext)) {
+                application.switchWindow(true);
+                return;
+            }
 
-        if (command.equals(cmWindowMove)) {
-            inKeyboardResize = true;
-            return;
-        }
+            if (command.equals(cmWindowPrevious)) {
+                application.switchWindow(false);
+                return;
+            }
 
-        if (command.equals(cmWindowZoom)) {
-            if (maximized) {
-                restore();
-            } else {
-                maximize();
+            if (command.equals(cmWindowMove)) {
+                inKeyboardResize = true;
+                return;
+            }
+
+            if (command.equals(cmWindowZoom)) {
+                if (maximized) {
+                    restore();
+                } else {
+                    maximize();
+                }
             }
-        }
+
+        } // if (!(this instanceof TDesktop))
 
         // I didn't take it, pass it on to my children
         super.onCommand(command);
@@ -1017,34 +1200,41 @@ public class TWindow extends TWidget {
      */
     @Override
     public void onMenu(final TMenuEvent menu) {
-        if (menu.getId() == TMenu.MID_WINDOW_CLOSE) {
-            application.closeWindow(this);
-            return;
-        }
 
-        if (menu.getId() == TMenu.MID_WINDOW_NEXT) {
-            application.switchWindow(true);
-            return;
-        }
+        if (!(this instanceof TDesktop)) {
 
-        if (menu.getId() == TMenu.MID_WINDOW_PREVIOUS) {
-            application.switchWindow(false);
-            return;
-        }
+            if (menu.getId() == TMenu.MID_WINDOW_CLOSE) {
+                if ((flags & NOCLOSEBOX) == 0) {
+                    application.closeWindow(this);
+                }
+                return;
+            }
 
-        if (menu.getId() == TMenu.MID_WINDOW_MOVE) {
-            inKeyboardResize = true;
-            return;
-        }
+            if (menu.getId() == TMenu.MID_WINDOW_NEXT) {
+                application.switchWindow(true);
+                return;
+            }
 
-        if (menu.getId() == TMenu.MID_WINDOW_ZOOM) {
-            if (maximized) {
-                restore();
-            } else {
-                maximize();
+            if (menu.getId() == TMenu.MID_WINDOW_PREVIOUS) {
+                application.switchWindow(false);
+                return;
+            }
+
+            if (menu.getId() == TMenu.MID_WINDOW_MOVE) {
+                inKeyboardResize = true;
+                return;
             }
-            return;
-        }
+
+            if (menu.getId() == TMenu.MID_WINDOW_ZOOM) {
+                if (maximized) {
+                    restore();
+                } else {
+                    maximize();
+                }
+                return;
+            }
+
+        } // if (!(this instanceof TDesktop))
 
         // I didn't take it, pass it on to my children
         super.onMenu(menu);
@@ -1194,5 +1384,4 @@ public class TWindow extends TWidget {
         getScreen().hLineXY(x, y, n, ch, attr);
     }
 
-
 }