TSplitPane initial
authorKevin Lamonte <kevin.lamonte@gmail.com>
Sun, 18 Aug 2019 15:52:10 +0000 (10:52 -0500)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Sun, 18 Aug 2019 15:52:10 +0000 (10:52 -0500)
src/jexer/TApplication.java
src/jexer/TPanel.java
src/jexer/TSplitPane.java [new file with mode: 0644]
src/jexer/TText.java
src/jexer/TWidget.java
src/jexer/TWindow.java
src/jexer/bits/ColorTheme.java
src/jexer/demos/Demo8.java [new file with mode: 0644]
src/jexer/demos/Demo8.properties [new file with mode: 0644]
src/jexer/menu/TMenu.java
src/jexer/menu/TMenu.properties

index 9c9c5714c67cbad7eb7a093fe049644f88250b13..f86ca27a1c2fdc3d4935c65abb55ed30617672d6 100644 (file)
@@ -1296,6 +1296,8 @@ public class TApplication implements Runnable {
                 }
             } else if (event instanceof TKeypressEvent) {
                 dispatchToDesktop = false;
+            } else if (event instanceof TMenuEvent) {
+                dispatchToDesktop = false;
             }
 
             if (debugEvents) {
index 1a8dab1d6ebb79b64bf491d121acc8bfb768638a..c38f8e1f50ee1d76b34821fc56f5959597784d84 100644 (file)
@@ -28,6 +28,8 @@
  */
 package jexer;
 
+import jexer.event.TResizeEvent;
+
 /**
  * TPanel is an empty container for other widgets.
  */
@@ -56,6 +58,35 @@ public class TPanel extends TWidget {
         super(parent, x, y, width, height);
     }
 
+    // ------------------------------------------------------------------------
+    // Event handlers ---------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * 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)
+                ) {
+                    child.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                            resize.getWidth(), resize.getHeight()));
+                }
+                return;
+            }
+        }
+
+        // Pass on to TWidget.
+        super.onResize(resize);
+    }
+
     // ------------------------------------------------------------------------
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
diff --git a/src/jexer/TSplitPane.java b/src/jexer/TSplitPane.java
new file mode 100644 (file)
index 0000000..0a3443b
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * 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;
+
+import jexer.bits.CellAttributes;
+import jexer.bits.GraphicsChars;
+import jexer.event.TMenuEvent;
+import jexer.event.TMouseEvent;
+import jexer.event.TResizeEvent;
+import jexer.menu.TMenu;
+
+/**
+ * TSplitPane contains two widgets with a draggable horizontal or vertical
+ * bar between them.
+ */
+public class TSplitPane extends TWidget {
+
+    // ------------------------------------------------------------------------
+    // Variables --------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * If true, split vertically.  If false, split horizontally.
+     */
+    private boolean vertical = true;
+
+    /**
+     * The location of the split bar, either as a column number for vertical
+     * split or a row number for horizontal split.
+     */
+    private int split = 0;
+
+    /**
+     * The widget on the left side.
+     */
+    private TWidget left;
+
+    /**
+     * The widget on the right side.
+     */
+    private TWidget right;
+
+    /**
+     * The widget on the top side.
+     */
+    private TWidget top;
+
+    /**
+     * The widget on the bottom side.
+     */
+    private TWidget bottom;
+
+    /**
+     * If true, we are in the middle of a split move.
+     */
+    private boolean inSplitMove = false;
+
+    // ------------------------------------------------------------------------
+    // Constructors -----------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Public constructor.
+     *
+     * @param parent parent widget
+     * @param x column relative to parent
+     * @param y row relative to parent
+     * @param width width of widget
+     * @param height height of widget
+     * @param vertical if true, split vertically
+     */
+    public TSplitPane(final TWidget parent, final int x, final int y,
+        final int width, final int height, final boolean vertical) {
+
+        super(parent, x, y, width, height);
+
+        this.vertical = vertical;
+        center();
+    }
+
+    // ------------------------------------------------------------------------
+    // Event handlers ---------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Handle window/screen resize events.
+     *
+     * @param event resize event
+     */
+    @Override
+    public void onResize(final TResizeEvent event) {
+        if (event.getType() == TResizeEvent.Type.WIDGET) {
+            // Resize me
+            super.onResize(event);
+
+            if (vertical && (split >= getWidth() - 2)) {
+                center();
+            } else if (!vertical && (split >= getHeight() - 2)) {
+                center();
+            } else {
+                layoutChildren();
+            }
+        }
+    }
+
+    /**
+     * Handle mouse button presses.
+     *
+     * @param mouse mouse button event
+     */
+    @Override
+    public void onMouseDown(final TMouseEvent mouse) {
+
+        inSplitMove = false;
+
+        if (mouse.isMouse1()) {
+            if (vertical) {
+                inSplitMove = (mouse.getX() == split);
+            } else {
+                inSplitMove = (mouse.getY() == split);
+            }
+            if (inSplitMove) {
+                return;
+            }
+        }
+
+        // I didn't take it, pass it on to my children
+        super.onMouseDown(mouse);
+    }
+
+    /**
+     * Handle mouse button releases.
+     *
+     * @param mouse mouse button release event
+     */
+    @Override
+    public void onMouseUp(final TMouseEvent mouse) {
+
+        if (inSplitMove && mouse.isMouse1()) {
+            // Stop moving split
+            inSplitMove = false;
+            return;
+        }
+
+        // I didn't take it, pass it on to my children
+        super.onMouseUp(mouse);
+    }
+
+    /**
+     * Handle mouse movements.
+     *
+     * @param mouse mouse motion event
+     */
+    @Override
+    public void onMouseMotion(final TMouseEvent mouse) {
+
+        if (inSplitMove) {
+            if (vertical) {
+                split = mouse.getX();
+                split = Math.min(Math.max(1, split), getWidth() - 2);
+            } else {
+                split = mouse.getY();
+                split = Math.min(Math.max(1, split), getHeight() - 2);
+            }
+            layoutChildren();
+            return;
+        }
+
+        // I didn't take it, pass it on to my children
+        super.onMouseMotion(mouse);
+    }
+
+    // ------------------------------------------------------------------------
+    // TWidget ----------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Draw me on screen.
+     */
+    @Override
+    public void draw() {
+        CellAttributes attr = getTheme().getColor("tsplitpane");
+        if (vertical) {
+            vLineXY(split, 0, getHeight(), GraphicsChars.WINDOW_SIDE, attr);
+            // TODO: draw intersections of children
+        } else {
+            hLineXY(0, split, getWidth(), GraphicsChars.SINGLE_BAR, attr);
+            // TODO: draw intersections of children
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // TSplitPane -------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Get the widget on the left side.
+     *
+     * @return the widget on the left, or null if not set
+     */
+    public TWidget getLeft() {
+        return left;
+    }
+
+    /**
+     * Set the widget on the left side.
+     *
+     * @param left the widget to set, or null to remove
+     */
+    public void setLeft(final TWidget left) {
+        if (!vertical) {
+            throw new IllegalArgumentException("cannot set left on " +
+                "horizontal split pane");
+        }
+        if (left == null) {
+            remove(this.left);
+            this.left = null;
+            return;
+        }
+        this.left = left;
+        left.setParent(this, false);
+        onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
+                getHeight()));
+    }
+
+    /**
+     * Get the widget on the right side.
+     *
+     * @return the widget on the right, or null if not set
+     */
+    public TWidget getRight() {
+        return right;
+    }
+
+    /**
+     * Set the widget on the right side.
+     *
+     * @param right the widget to set, or null to remove
+     */
+    public void setRight(final TWidget right) {
+        if (!vertical) {
+            throw new IllegalArgumentException("cannot set right on " +
+                "horizontal split pane");
+        }
+        if (right == null) {
+            remove(this.right);
+            this.right = null;
+            return;
+        }
+        this.right = right;
+        right.setParent(this, false);
+        onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
+                getHeight()));
+    }
+
+    /**
+     * Get the widget on the top side.
+     *
+     * @return the widget on the top, or null if not set
+     */
+    public TWidget getTop() {
+        return top;
+    }
+
+    /**
+     * Set the widget on the top side.
+     *
+     * @param top the widget to set, or null to remove
+     */
+    public void setTop(final TWidget top) {
+        if (vertical) {
+            throw new IllegalArgumentException("cannot set top on vertical " +
+                "split pane");
+        }
+        if (top == null) {
+            remove(this.top);
+            this.top = null;
+            return;
+        }
+        this.top = top;
+        top.setParent(this, false);
+        onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
+                getHeight()));
+    }
+
+    /**
+     * Get the widget on the bottom side.
+     *
+     * @return the widget on the bottom, or null if not set
+     */
+    public TWidget getBottom() {
+        return bottom;
+    }
+
+    /**
+     * Set the widget on the bottom side.
+     *
+     * @param bottom the widget to set, or null to remove
+     */
+    public void setBottom(final TWidget bottom) {
+        if (vertical) {
+            throw new IllegalArgumentException("cannot set bottom on " +
+                "vertical split pane");
+        }
+        if (bottom == null) {
+            remove(this.bottom);
+            this.bottom = null;
+            return;
+        }
+        this.bottom = bottom;
+        bottom.setParent(this, false);
+        onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
+                getHeight()));
+    }
+
+    /**
+     * Layout the two child widgets.
+     */
+    private void layoutChildren() {
+        if (vertical) {
+            if (left != null) {
+                left.setDimensions(0, 0, split, getHeight());
+                left.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                        left.getWidth(), left.getHeight()));
+            }
+            if (right != null) {
+                right.setDimensions(split + 1, 0, getWidth() - split - 1,
+                    getHeight());
+                right.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                        right.getWidth(), right.getHeight()));
+            }
+        } else {
+            if (top != null) {
+                top.setDimensions(0, 0, getWidth(), split);
+                top.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                        top.getWidth(), top.getHeight()));
+            }
+            if (bottom != null) {
+                bottom.setDimensions(0, split + 1, getWidth(),
+                    getHeight() - split - 1);
+                bottom.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                        bottom.getWidth(), bottom.getHeight()));
+            }
+        }
+    }
+
+    /**
+     * Recenter the split to the middle of this split pane.
+     */
+    public void center() {
+        if (vertical) {
+            split = getWidth() / 2;
+        } else {
+            split = getHeight() / 2;
+        }
+        layoutChildren();
+    }
+
+}
index 6fea16f3a43ff066165eda982c100797cd517f0d..22bc4b89051d31e586a60b91a274b55d3292bade 100644 (file)
@@ -225,8 +225,10 @@ public class TText extends TScrollableWidget {
             } else {
                 line = "";
             }
-            String formatString = "%-" + Integer.toString(getWidth() - 1) + "s";
-            putStringXY(0, topY, String.format(formatString, line), color);
+            if (getWidth() > 3) {
+                String formatString = "%-" + Integer.toString(getWidth() - 1) + "s";
+                putStringXY(0, topY, String.format(formatString, line), color);
+            }
             topY++;
 
             if (topY >= (getHeight() - 1)) {
index d48ffe4c9ad6e477123c1e940e659360b347a1ab..bcf798ae36e9f40336d40fcd18d11e3a58b0de6c 100644 (file)
@@ -611,6 +611,61 @@ public abstract class TWidget implements Comparable<TWidget> {
      * @param menu menu event
      */
     public void onMenu(final TMenuEvent menu) {
+
+        // Special case: if a split command comes in, insert a TPanel and
+        // TSplitPane in the hierarchy here.
+        TPanel panel = null;
+        TSplitPane pane = null;
+        List<TWidget> widgets = null;
+        switch (menu.getId()) {
+        case TMenu.MID_SPLIT_VERTICAL:
+            panel = new TPanel(null, x, y, width, height);
+            pane = new TSplitPane(null, x, y, width, height, true);
+            widgets = new ArrayList<TWidget>(children);
+            for (TWidget w: widgets) {
+                w.setParent(panel, false);
+            }
+            children.clear();
+            pane.setParent(this, false);
+            pane.setLeft(panel);
+            activate(pane);
+            for (TWidget w: widgets) {
+                assert (w.window != null);
+                assert (w.parent != null);
+            }
+            assert (pane.getWindow() != null);
+            assert (pane.getParent() != null);
+            assert (panel.getWindow() != null);
+            assert (panel.getParent() != null);
+            assert (pane.isActive() == true);
+            assert (panel.isActive() == true);
+            return;
+        case TMenu.MID_SPLIT_HORIZONTAL:
+            panel = new TPanel(null, x, y, width, height);
+            pane = new TSplitPane(null, x, y, width, height, false);
+            widgets = new ArrayList<TWidget>(children);
+            for (TWidget w: widgets) {
+                w.setParent(panel, false);
+            }
+            children.clear();
+            pane.setParent(this, false);
+            pane.setTop(panel);
+            activate(pane);
+            for (TWidget w: widgets) {
+                assert (w.window != null);
+                assert (w.parent != null);
+            }
+            assert (pane.getWindow() != null);
+            assert (pane.getParent() != null);
+            assert (panel.getWindow() != null);
+            assert (panel.getParent() != null);
+            assert (pane.isActive() == true);
+            assert (panel.isActive() == true);
+            return;
+        default:
+            break;
+        }
+
         // Default: do nothing, pass to children instead
         for (TWidget widget: children) {
             widget.onMenu(menu);
@@ -729,6 +784,15 @@ public abstract class TWidget implements Comparable<TWidget> {
         }
     }
 
+    /**
+     * Remove a child widget from this container.
+     *
+     * @param child the child widget to remove
+     */
+    public final void remove(final TWidget child) {
+        remove(child, true);
+    }
+
     /**
      * Remove a child widget from this container.
      *
@@ -746,6 +810,7 @@ public abstract class TWidget implements Comparable<TWidget> {
         }
         children.remove(child);
         child.parent = null;
+        child.window = null;
         if (layout != null) {
             layout.remove(this);
         }
@@ -763,29 +828,31 @@ public abstract class TWidget implements Comparable<TWidget> {
 
         if (parent != null) {
             parent.remove(this, doClose);
+            window = null;
         }
         assert (parent == null);
-        window = newParent.window;
-        newParent.addChild(this);
+        assert (window == null);
+        parent = newParent;
+        setWindow(parent.window);
+        parent.addChild(this);
     }
 
     /**
-     * Set this widget's window to a specific window.  Parent must already be
-     * null.  Having a null parent with a specified window is only used
-     * within Jexer by TStatusBar because TApplication routes events directly
-     * to it and calls its draw() method.  Any other non-parented widgets
-     * will require similar special case functionality to receive events or
-     * be drawn to screen.
+     * Set this widget's window to a specific window.
+     *
+     * Having a null parent with a specified window is only used within Jexer
+     * by TStatusBar because TApplication routes events directly to it and
+     * calls its draw() method.  Any other non-parented widgets will require
+     * similar special case functionality to receive events or be drawn to
+     * screen.
      *
      * @param window the window to use
      */
     public final void setWindow(final TWindow window) {
-
-        if (parent != null) {
-            throw new IllegalArgumentException("Cannot have different " +
-                "windows for parent and child");
-        }
         this.window = window;
+        for (TWidget child: getChildren()) {
+            child.setWindow(window);
+        }
     }
 
     /**
@@ -2507,4 +2574,20 @@ public abstract class TWidget implements Comparable<TWidget> {
         return new TPanel(this, x, y, width, height);
     }
 
+    /**
+     * Convenience function to add a split pane to this container/window.
+     *
+     * @param x column relative to parent
+     * @param y row relative to parent
+     * @param width width of text area
+     * @param height height of text area
+     * @param vertical if true, split vertically
+     * @return the new split pane
+     */
+    public final TSplitPane addSplitPane(final int x, final int y,
+        final int width, final int height, final boolean vertical) {
+
+        return new TSplitPane(this, x, y, width, height, vertical);
+    }
+
 }
index 20f88d6da388500154b25fa0e91e7e76611871b7..222efbcde7484867b2266e399a3bd5f56076b1e8 100644 (file)
@@ -849,6 +849,31 @@ 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)
+                ) {
+                    child.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET,
+                            resize.getWidth() - 2, resize.getHeight() - 2));
+                }
+                return;
+            }
+        }
+
+        // Pass on to TWidget.
+        super.onResize(resize);
+    }
+
     // ------------------------------------------------------------------------
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
index ace1ebdde0e31b2d68493020228f9bf32f0c0a22..ffba4d472cc67c36ebda4114e503ba1db545c719 100644 (file)
@@ -666,6 +666,13 @@ public class ColorTheme {
         color.setBold(false);
         colors.put("ttable.border", color);
 
+        // TSplitPane
+        color = new CellAttributes();
+        color.setForeColor(Color.WHITE);
+        color.setBackColor(Color.BLUE);
+        color.setBold(false);
+        colors.put("tsplitpane", color);
+
     }
 
     /**
diff --git a/src/jexer/demos/Demo8.java b/src/jexer/demos/Demo8.java
new file mode 100644 (file)
index 0000000..d7b7501
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.util.ResourceBundle;
+
+import jexer.TApplication;
+import jexer.TPanel;
+import jexer.TSplitPane;
+import jexer.TText;
+import jexer.TWindow;
+import jexer.layout.BoxLayoutManager;
+import jexer.menu.TMenu;
+
+/**
+ * This class shows off TSplitPane.
+ */
+public class Demo8 {
+
+    /**
+     * Translated strings.
+     */
+    private static final ResourceBundle i18n = ResourceBundle.getBundle(Demo8.class.getName());
+
+    // ------------------------------------------------------------------------
+    // Constants --------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    private static String TEXT =
+"This is an example of a reflowable text field.  Some example text follows.\n" +
+"\n" +
+"Notice that some menu items should be disabled when this window has focus.\n" +
+"\n" +
+"This library implements a text-based windowing system loosely " +
+"reminiscent of Borland's [Turbo " +
+"Vision](http://en.wikipedia.org/wiki/Turbo_Vision) library.  For those " +
+"wishing to use the actual C++ Turbo Vision library, see [Sergio " +
+"Sigala's updated version](http://tvision.sourceforge.net/) that runs " +
+"on many more platforms.\n" +
+"\n" +
+"This library is licensed MIT.  See the file LICENSE for the full license " +
+"for the details.\n";
+
+    // ------------------------------------------------------------------------
+    // Demo8 ------------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Main entry point.
+     *
+     * @param args Command line arguments
+     */
+    public static void main(final String [] args) throws Exception {
+        // This demo will build everything "from the outside".
+
+        // 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;
+            }
+        }
+
+        // For this demo, let's disable the status bar.
+        System.setProperty("jexer.hideStatusBar", "true");
+
+        TApplication app = new TApplication(backendType);
+        app.addToolMenu();
+        app.addFileMenu();
+        TWindow window = new TWindow(app, i18n.getString("windowTitle"),
+            60, 22);
+
+        TMenu paneMenu = app.addMenu(i18n.getString("paneMenu"));
+        paneMenu.addDefaultItem(TMenu.MID_SPLIT_VERTICAL, true);
+        paneMenu.addDefaultItem(TMenu.MID_SPLIT_HORIZONTAL, true);
+
+        TSplitPane pane = window.addSplitPane(0, 0, window.getWidth() - 2,
+            window.getHeight() - 2, true);
+
+        pane.setLeft(new TText(null, TEXT, 0, 0, 10, 10));
+        pane.setRight(new TText(null, TEXT, 0, 0, 10, 10));
+
+        app.run();
+    }
+
+}
diff --git a/src/jexer/demos/Demo8.properties b/src/jexer/demos/Demo8.properties
new file mode 100644 (file)
index 0000000..2a94ca1
--- /dev/null
@@ -0,0 +1,5 @@
+windowTitle=TSplitPane Demo
+
+paneMenu=&Pane
+paneSplitVertical=Split &Vertical
+paneSplitHorizontal=Split &Horizontal
index 75802439cce48c373b82384e36dc24b4b02c3a7c..9983580ac1ff02b5742be5342ec4c0edcb218342 100644 (file)
@@ -133,6 +133,10 @@ public class TMenu extends TWindow {
     public static final int MID_TABLE_FILE_SAVE_CSV             = 116;
     public static final int MID_TABLE_FILE_SAVE_TEXT            = 117;
 
+    // Miscellaneous
+    public static final int MID_SPLIT_VERTICAL                  = 200;
+    public static final int MID_SPLIT_HORIZONTAL                = 201;
+
     // ------------------------------------------------------------------------
     // Variables --------------------------------------------------------------
     // ------------------------------------------------------------------------
@@ -772,6 +776,13 @@ public class TMenu extends TWindow {
             label = i18n.getString("menuTableFileSaveText");
             break;
 
+        case MID_SPLIT_VERTICAL:
+            label = i18n.getString("menuSplitVertical");
+            break;
+        case MID_SPLIT_HORIZONTAL:
+            label = i18n.getString("menuSplitHorizontal");
+            break;
+
         default:
             throw new IllegalArgumentException("Invalid menu ID: " + id);
         }
index 1581d0bd2491235cbf45d26fcb663ab4dfb5672f..494fad99e24f412595b6491ba07a40579b6eb3f8 100644 (file)
@@ -59,3 +59,5 @@ menuTableFileSaveText=Save As &Text...
 menuRepaintDesktop=&Repaint desktop
 menuViewImage=&Open image...
 menuScreenOptions=&Screen options...
+menuSplitVertical=Split &Vertical
+menuSplitHorizontal=Split &Horizontal