From 469c2b3cf74f88072a9a1e5758379f24b14f469e Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Tue, 20 Aug 2019 16:07:04 -0500 Subject: [PATCH] #51 wip --- examples/JexerTilingWindowManager2.java | 76 ++++++++---- src/jexer/TAction.java | 8 +- src/jexer/TSplitPane.java | 52 ++++++++ src/jexer/TTerminalWidget.java | 6 + src/jexer/TWidget.java | 153 ++++++++++++++---------- src/jexer/demos/Demo8.java | 16 ++- src/jexer/menu/TMenu.java | 11 -- src/jexer/menu/TMenu.properties | 3 +- 8 files changed, 222 insertions(+), 103 deletions(-) diff --git a/examples/JexerTilingWindowManager2.java b/examples/JexerTilingWindowManager2.java index cc23aa7..bef3637 100644 --- a/examples/JexerTilingWindowManager2.java +++ b/examples/JexerTilingWindowManager2.java @@ -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; + } + } + }); } } diff --git a/src/jexer/TAction.java b/src/jexer/TAction.java index cc93819..bce0064 100644 --- a/src/jexer/TAction.java +++ b/src/jexer/TAction.java @@ -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(); } - diff --git a/src/jexer/TSplitPane.java b/src/jexer/TSplitPane.java index 796a04a..277f080 100644 --- a/src/jexer/TSplitPane.java +++ b/src/jexer/TSplitPane.java @@ -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; + } + } diff --git a/src/jexer/TTerminalWidget.java b/src/jexer/TTerminalWidget.java index 8c0082c..db405cf 100644 --- a/src/jexer/TTerminalWidget.java +++ b/src/jexer/TTerminalWidget.java @@ -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"); diff --git a/src/jexer/TWidget.java b/src/jexer/TWidget.java index 729a5f5..034c1e9 100644 --- a/src/jexer/TWidget.java +++ b/src/jexer/TWidget.java @@ -611,67 +611,6 @@ public abstract class TWidget implements Comparable { * @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 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(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(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 { 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 widgets = new ArrayList(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 widgets = new ArrayList(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 ------------------------------------------ // ------------------------------------------------------------------------ diff --git a/src/jexer/demos/Demo8.java b/src/jexer/demos/Demo8.java index a74b7a9..3b253d0 100644 --- a/src/jexer/demos/Demo8.java +++ b/src/jexer/demos/Demo8.java @@ -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); diff --git a/src/jexer/menu/TMenu.java b/src/jexer/menu/TMenu.java index acac991..6d746df 100644 --- a/src/jexer/menu/TMenu.java +++ b/src/jexer/menu/TMenu.java @@ -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); } diff --git a/src/jexer/menu/TMenu.properties b/src/jexer/menu/TMenu.properties index 494fad9..4a0f8e6 100644 --- a/src/jexer/menu/TMenu.properties +++ b/src/jexer/menu/TMenu.properties @@ -59,5 +59,4 @@ menuTableFileSaveText=Save As &Text... menuRepaintDesktop=&Repaint desktop menuViewImage=&Open image... menuScreenOptions=&Screen options... -menuSplitVertical=Split &Vertical -menuSplitHorizontal=Split &Horizontal + -- 2.27.0