#51 wip
authorKevin Lamonte <kevin.lamonte@gmail.com>
Tue, 20 Aug 2019 21:07:04 +0000 (16:07 -0500)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Tue, 20 Aug 2019 21:07:04 +0000 (16:07 -0500)
examples/JexerTilingWindowManager2.java
src/jexer/TAction.java
src/jexer/TSplitPane.java
src/jexer/TTerminalWidget.java
src/jexer/TWidget.java
src/jexer/demos/Demo8.java
src/jexer/menu/TMenu.java
src/jexer/menu/TMenu.properties

index cc23aa76f0840309361e879fa40d7916eecb5f69..bef3637119b7d676ce2ecd27dbcc406979d3e074 100644 (file)
@@ -1,12 +1,12 @@
 import jexer.TAction;
 import jexer.TApplication;
 import jexer.TDesktop;
+import jexer.TPanel;
 import jexer.TTerminalWidget;
+import jexer.TSplitPane;
 import jexer.TWidget;
 import jexer.event.TKeypressEvent;
 import jexer.event.TMenuEvent;
-import jexer.event.TMouseEvent;
-import jexer.event.TResizeEvent;
 import jexer.menu.TMenu;
 
 /**
@@ -34,7 +34,7 @@ public class JexerTilingWindowManager2 extends TApplication {
      * Handle to the root widget.
      */
     private TWidget root = null;
-    
+
     /**
      * Main entry point.
      */
@@ -78,17 +78,7 @@ public class JexerTilingWindowManager2 extends TApplication {
         tileMenu.addDefaultItem(TMenu.MID_EXIT);
 
         // Spin up the root terminal
-        root = new TTerminalWidget(getDesktop(), 0, 0,
-            getDesktop().getWidth(), getDesktop().getHeight(),
-            new TAction() {
-                public void DO() {
-                    // TODO: if root's parent is TSplitPane, call
-                    // TSplitPane.removeSplit(TWidget).
-                    if (root != null) {
-                        root.remove();
-                    }
-                }
-            });
+        createRootTerminal();
     }
 
     /**
@@ -97,11 +87,38 @@ public class JexerTilingWindowManager2 extends TApplication {
     @Override
     protected boolean onMenu(TMenuEvent event) {
         if (event.getId() == MENU_SPLIT_VERTICAL) {
-            splitVertical();
+            if (root == null) {
+                createRootTerminal();
+                return true;
+            }
+            TWidget active = root.getActiveChild();
+            TSplitPane split = active.splitVertical(false,
+                new TTerminalWidget(getDesktop(), active.getX(),
+                    active.getY(), active.getWidth(), active.getHeight(),
+                    new TAction() {
+                        public void DO() {
+                            // TODO
+                        }
+                    }));
+            if (active == root) {
+                root = split;
+            }
             return true;
         }
         if (event.getId() == MENU_SPLIT_HORIZONTAL) {
-            splitHorizontal();
+            if (root == null) {
+                createRootTerminal();
+                return true;
+            }
+            TWidget active = root.getActiveChild();
+            TSplitPane split = active.splitHorizontal(false,
+                new TTerminalWidget(getDesktop(), active.getX(),
+                    active.getY(), active.getWidth(), active.getHeight(),
+                    new TAction() {
+                        public void DO() {
+                            // TODO
+                        }
+                    }));
             return true;
         }
 
@@ -109,17 +126,24 @@ public class JexerTilingWindowManager2 extends TApplication {
     }
 
     /**
-     * Perform the vertical split.
+     * Create the root terminal.
      */
-    private void splitVertical() {
-        // TODO
-    }
-
-    /**
-     * Perform the horizontal split.
-     */
-    private void splitHorizontal() {
-        // TODO
+    private void createRootTerminal() {
+        assert (root == null);
+        root = new TTerminalWidget(getDesktop(), 0, 0,
+            getDesktop().getWidth(), getDesktop().getHeight(),
+            new TAction() {
+                public void DO() {
+                    TWidget target = (TWidget) data;
+                    if (target.getParent() instanceof TPanel) {
+                        ((TSplitPane) target.getParent().getParent()).removeSplit(target, true);
+                    } else {
+                        assert (root != null);
+                        root.remove();
+                        root = null;
+                    }
+                }
+            });
     }
 
 }
index cc93819d538f708267bf179e8c5327f537c23de0..bce00646d54f31324db4eb34c4f48c3f5261386e 100644 (file)
@@ -34,9 +34,15 @@ package jexer;
  * @see TButton
  */
 public abstract class TAction {
+
+    /**
+     * An optional bit of data associated with this action.  Widgets that use
+     * this field are responsible for setting it.
+     */
+    public Object data;
+
     /**
      * Various classes will call DO() when they are clicked/selected.
      */
     public abstract void DO();
 }
-
index 796a04a8d12c6854f1a0a6607661f4a4093472ec..277f080e22af099cf0bb576eb09dd4637027e4c2 100644 (file)
@@ -418,4 +418,56 @@ public class TSplitPane extends TWidget {
         layoutChildren();
     }
 
+    /**
+     * Remove this split, removing the widget specified.
+     *
+     * @param widgetToRemove the widget to remove
+     * @param doClose if true, call the close() method before removing the
+     * child
+     * @return the pane that remains, or null if nothing is retained
+     */
+    public TWidget removeSplit(final TWidget widgetToRemove,
+        final boolean doClose) {
+
+        TWidget keep = null;
+        if (vertical) {
+            if ((widgetToRemove != left) && (widgetToRemove != right)) {
+                throw new IllegalArgumentException("widget to remove is not " +
+                    "either of the panes in this splitpane");
+            }
+            if (widgetToRemove == left) {
+                keep = right;
+            } else {
+                keep = left;
+            }
+
+        } else {
+            if ((widgetToRemove != top) && (widgetToRemove != bottom)) {
+                throw new IllegalArgumentException("widget to remove is not " +
+                    "either of the panes in this splitpane");
+            }
+            if (widgetToRemove == top) {
+                keep = bottom;
+            } else {
+                keep = top;
+            }
+        }
+
+        // Remove me from my parent widget.
+        TWidget newParent = getParent();
+        setParent(null, false);
+
+        if (keep == null) {
+            // Nothing is left of either pane.  Remove me and bail out.
+            return null;
+        }
+
+        keep.setParent(newParent, false);
+        keep.setDimensions(getX(), getY(), getWidth(), getHeight());
+        keep.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
+                getHeight()));
+
+        return keep;
+    }
+
 }
index 8c0082c08d8af431161a324c1a10316840900747..db405cfd72e0b13640f1b9bcded25ae03adf1c5d 100644 (file)
@@ -229,6 +229,9 @@ public class TTerminalWidget extends TScrollableWidget
         super(parent, x, y, width, height);
 
         this.closeAction = closeAction;
+        if (closeAction != null) {
+            this.closeAction.data = this;
+        }
 
         String [] fullCommand;
 
@@ -307,6 +310,9 @@ public class TTerminalWidget extends TScrollableWidget
         super(parent, x, y, width, height);
 
         this.closeAction = closeAction;
+        if (closeAction != null) {
+            this.closeAction.data = this;
+        }
 
         if (System.getProperty("jexer.TTerminal.shell") != null) {
             String shell = System.getProperty("jexer.TTerminal.shell");
index 729a5f5d0c3a1b43056087e43c39fae1b7f39527..034c1e9b26f0ae8fdb1a06550456db2d46bee606 100644 (file)
@@ -611,67 +611,6 @@ 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:
-            if (children.size() == 0) {
-                break;
-            }
-            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:
-            if (children.size() == 0) {
-                break;
-            }
-            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);
@@ -1608,6 +1547,98 @@ public abstract class TWidget implements Comparable<TWidget> {
         return this;
     }
 
+    /**
+     * Split this widget into two, putting all of this widget's children into
+     * a new TPanel, and returning a new TSplitPane with that panel on the
+     * left or right pane.
+     *
+     * @param newWidgetOnLeft if true, the new widget (if specified) will be
+     * on the left pane, and this widget's children will be placed on the
+     * right pane
+     * @param newWidget the new widget to add to the other pane, or null
+     * @return the new split pane widget
+     */
+    public TSplitPane splitVertical(final boolean newWidgetOnLeft,
+        final TWidget newWidget) {
+
+        TPanel panel = new TPanel(null, x, y, width, height);
+        TSplitPane splitPane = new TSplitPane(null, x, y, width, height, true);
+        List<TWidget> widgets = new ArrayList<TWidget>(children);
+        for (TWidget w: widgets) {
+            w.setParent(panel, false);
+        }
+        children.clear();
+        splitPane.setParent(parent, false);
+        parent = null;
+        window = null;
+        if (newWidgetOnLeft) {
+            splitPane.setLeft(newWidget);
+            splitPane.setRight(panel);
+        } else {
+            splitPane.setRight(newWidget);
+            splitPane.setLeft(panel);
+        }
+        activate(splitPane);
+        for (TWidget w: widgets) {
+            assert (w.window != null);
+            assert (w.parent != null);
+        }
+        assert (splitPane.getWindow() != null);
+        assert (splitPane.getParent() != null);
+        assert (panel.getWindow() != null);
+        assert (panel.getParent() != null);
+        assert (splitPane.isActive() == true);
+        assert (panel.isActive() == true);
+        return splitPane;
+    }
+
+    /**
+     * Split this widget into two, putting all of this widget's children into
+     * a new TPanel, and returning a new TSplitPane with that panel on the
+     * top or bottom pane.
+     *
+     * @param newWidgetOnTop if true, the new widget (if specified) will be
+     * on the top pane, and this widget's children will be placed on the
+     * bottom pane
+     * @param newWidget the new widget to add to the other pane, or null
+     * @return the new split pane widget
+     */
+    public TSplitPane splitHorizontal(final boolean newWidgetOnTop,
+        final TWidget newWidget) {
+
+        TPanel panel = new TPanel(null, x, y, width, height);
+        TSplitPane splitPane = new TSplitPane(null, x, y, width, height, false);
+        List<TWidget> widgets = new ArrayList<TWidget>(children);
+        for (TWidget w: widgets) {
+            w.setParent(panel, false);
+        }
+        children.clear();
+        splitPane.setParent(parent, false);
+        parent = null;
+        splitPane.setTop(panel);
+        parent = null;
+        window = null;
+        if (newWidgetOnTop) {
+            splitPane.setTop(newWidget);
+            splitPane.setBottom(panel);
+        } else {
+            splitPane.setBottom(newWidget);
+            splitPane.setTop(panel);
+        }
+        activate(splitPane);
+        for (TWidget w: widgets) {
+            assert (w.window != null);
+            assert (w.parent != null);
+        }
+        assert (splitPane.getWindow() != null);
+        assert (splitPane.getParent() != null);
+        assert (panel.getWindow() != null);
+        assert (panel.getParent() != null);
+        assert (splitPane.isActive() == true);
+        assert (panel.isActive() == true);
+        return splitPane;
+    }
+
     // ------------------------------------------------------------------------
     // Passthru for Screen functions ------------------------------------------
     // ------------------------------------------------------------------------
index a74b7a9717f0c9dae0a0ac8c1818affea8b4a9b4..3b253d0c5aea2210a6b8013a17bf9de6d12e06ab 100644 (file)
@@ -68,6 +68,16 @@ public class Demo8 {
 "This library is licensed MIT.  See the file LICENSE for the full license " +
 "for the details.\n";
 
+    /**
+     * Menu item: split vertically.
+     */
+    private static final int MENU_SPLIT_VERTICAL = 2000;
+
+    /**
+     * Menu item: split horizontally.
+     */
+    private static final int MENU_SPLIT_HORIZONTAL = 2001;
+
     // ------------------------------------------------------------------------
     // Demo8 ------------------------------------------------------------------
     // ------------------------------------------------------------------------
@@ -107,8 +117,10 @@ public class Demo8 {
             60, 22);
 
         TMenu paneMenu = app.addMenu(i18n.getString("paneMenu"));
-        paneMenu.addDefaultItem(TMenu.MID_SPLIT_VERTICAL, true);
-        paneMenu.addDefaultItem(TMenu.MID_SPLIT_HORIZONTAL, true);
+        paneMenu.addItem(MENU_SPLIT_VERTICAL,
+            i18n.getString("paneSplitVertical"));
+        paneMenu.addItem(MENU_SPLIT_HORIZONTAL,
+            i18n.getString("paneSplitHorizontal"));
 
         TSplitPane pane = window.addSplitPane(0, 0, window.getWidth() - 2,
             window.getHeight() - 2, true);
index acac991ea571e9979e909a5d7197922284208f8e..6d746df0c42ebc3f6da6ede018a33ff439233235 100644 (file)
@@ -133,10 +133,6 @@ 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 --------------------------------------------------------------
     // ------------------------------------------------------------------------
@@ -775,13 +771,6 @@ 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 494fad99e24f412595b6491ba07a40579b6eb3f8..4a0f8e6f6fef8b301b7467be871263b5858639cc 100644 (file)
@@ -59,5 +59,4 @@ menuTableFileSaveText=Save As &Text...
 menuRepaintDesktop=&Repaint desktop
 menuViewImage=&Open image...
 menuScreenOptions=&Screen options...
-menuSplitVertical=Split &Vertical
-menuSplitHorizontal=Split &Horizontal
+