diff --git a/src/main/java/com/googlecode/lanterna/gui2/SplitPanel.java b/src/main/java/com/googlecode/lanterna/gui2/SplitPanel.java index b7f86b1fb..007975461 100644 --- a/src/main/java/com/googlecode/lanterna/gui2/SplitPanel.java +++ b/src/main/java/com/googlecode/lanterna/gui2/SplitPanel.java @@ -18,11 +18,20 @@ */ package com.googlecode.lanterna.gui2; -import com.googlecode.lanterna.*; -import com.googlecode.lanterna.graphics.*; -import com.googlecode.lanterna.input.*; - -import java.util.*; +import java.util.List; + +import com.googlecode.lanterna.SGR; +import com.googlecode.lanterna.Symbols; +import com.googlecode.lanterna.TerminalPosition; +import com.googlecode.lanterna.TerminalSize; +import com.googlecode.lanterna.TextCharacter; +import com.googlecode.lanterna.graphics.BasicTextImage; +import com.googlecode.lanterna.graphics.TextImage; +import com.googlecode.lanterna.graphics.Theme; +import com.googlecode.lanterna.graphics.ThemeDefinition; +import com.googlecode.lanterna.graphics.ThemeStyle; +import com.googlecode.lanterna.input.KeyStroke; +import com.googlecode.lanterna.input.MouseAction; /** * @author ginkoblongata @@ -71,54 +80,113 @@ ImageComponent makeThumb() { TerminalPosition drag = null; @Override - public Result handleKeyStroke(KeyStroke keyStroke) { - Result result; - if (keyStroke instanceof MouseAction) { - result = handleMouseAction((MouseAction) keyStroke); - } - // TODO: Implement keyboard based resizing - else { - result = super.handleKeyStroke(keyStroke); - } - return result; - } - - private Result handleMouseAction(MouseAction mouseAction) { - if (mouseAction.isMouseDown()) { - aSize = compA.getSize(); - bSize = compB.getSize(); - tSize = thumb.getSize(); - down = mouseAction.getPosition(); - } - if (mouseAction.isMouseDrag()) { - drag = mouseAction.getPosition(); - - // xxxxxxxxxxxxxxxxxxxxx - // this is a hack, should not be needed if the pane drag - // only on mouse down'd comp stuff was completely working - if (down == null) { - down = drag; + public Result handleKeyStroke(KeyStroke keyStroke) + { + Result result = null; + switch(keyStroke.getKeyType()) + { + case ARROW_UP: + if(!isHorizontal) { + aSize = compA.getSize(); + bSize = compB.getSize(); + tSize = thumb.getSize(); + + resize(-1); + result = Result.HANDLED; + } + else result = Result.MOVE_FOCUS_UP; + break; + + case ARROW_DOWN: + if(!isHorizontal) { + aSize = compA.getSize(); + bSize = compB.getSize(); + tSize = thumb.getSize(); + resize(1); + result = Result.HANDLED; + } + else result = Result.MOVE_FOCUS_DOWN; + break; + + case ARROW_LEFT: + if(isHorizontal) { + aSize = compA.getSize(); + bSize = compB.getSize(); + tSize = thumb.getSize(); + resize(-1); + result = Result.HANDLED; } - // xxxxxxxxxxxxxxxxxxxxx - - int delta = isHorizontal ? drag.minus(down).getColumn() : drag.minus(down).getRow(); - // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - if (isHorizontal) { - int a = Math.max(1, tSize.getColumns() + aSize.getColumns() + delta); - int b = Math.max(1, bSize.getColumns() - delta); - setRatio(a, b); - } else { - int a = Math.max(1, tSize.getRows() + aSize.getRows() + delta); - int b = Math.max(1, bSize.getRows() - delta); - setRatio(a, b); + else result = Result.MOVE_FOCUS_LEFT; + break; + + case ARROW_RIGHT: + if(isHorizontal) { + aSize = compA.getSize(); + bSize = compB.getSize(); + tSize = thumb.getSize(); + resize(1); + result = Result.HANDLED; } - // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - } - if (mouseAction.isMouseUp()) { - down = null; - drag = null; - } - return Result.HANDLED; + else result = Result.MOVE_FOCUS_LEFT; + break; + + case MOUSE_EVENT: + if (!isFocused()) { + return super.handleKeyStroke(keyStroke); + } + + MouseAction action = (MouseAction)keyStroke; + if (action.isMouseDown()) { + aSize = compA.getSize(); + bSize = compB.getSize(); + tSize = thumb.getSize(); + down = action.getPosition(); + } + + if (action.isMouseDrag()) { + drag = action.getPosition(); + + // xxxxxxxxxxxxxxxxxxxxx + // this is a hack, should not be needed if the pane drag + // only on mouse down'd comp stuff was completely working + if (down == null) { + down = drag; + } + // xxxxxxxxxxxxxxxxxxxxx + + int delta = isHorizontal ? drag.minus(down).getColumn() : drag.minus(down).getRow(); + resize(delta); + } + + if (action.isMouseUp()) { + down = null; + drag = null; + } + + result = Result.HANDLED; + break; + + default: result = super.handleKeyStroke(keyStroke); + } + + return result; + } + + private void resize(int delta) + { + if (tSize == null || aSize == null || bSize == null) return; + + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + if (isHorizontal) { + int a = Math.max(1, tSize.getColumns() + aSize.getColumns() + delta); + int b = Math.max(1, bSize.getColumns() - delta); + setRatio(a, b); + } else { + int a = Math.max(1, tSize.getRows() + aSize.getRows() + delta); + int b = Math.max(1, bSize.getRows() - delta); + setRatio(a, b); + } + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } }; return imageComponent; @@ -132,7 +200,6 @@ public ScrollPanelLayoutManager() { hasChanged = true; } - @Override public TerminalSize getPreferredSize(List components) { TerminalSize sizeA = compA.getPreferredSize(); @@ -154,11 +221,8 @@ public TerminalSize getPreferredSize(List components) { @Override public void doLayout(TerminalSize area, List components) { - TerminalSize size = getSize(); - // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - // TODO: themed - int length = isHorizontal ? size.getRows() : size.getColumns(); + int length = isHorizontal ? area.getRows() : area.getColumns(); TerminalSize tsize = new TerminalSize(isHorizontal ? 1 : length, !isHorizontal ? 1 : length); TextImage textImage = new BasicTextImage(tsize); Theme theme = getTheme(); @@ -180,8 +244,8 @@ public void doLayout(TerminalSize area, List components) { int tWidth = thumb.getPreferredSize().getColumns(); int tHeight = thumb.getPreferredSize().getRows(); - int w = size.getColumns(); - int h = size.getRows(); + int w = area.getColumns(); + int h = area.getRows(); if (isHorizontal) { w -= tWidth; @@ -198,10 +262,10 @@ public void doLayout(TerminalSize area, List components) { if (isHorizontal) { int leftWidth = Math.max(0, (int) (w * ratio)); - int leftHeight = Math.max(0, Math.min(compA.getPreferredSize().getRows(), h)); + int leftHeight = Math.max(0, h); int rightWidth = Math.max(0, w - leftWidth); - int rightHeight = Math.max(0, Math.min(compB.getPreferredSize().getRows(), h)); + int rightHeight = Math.max(0, h); compA.setSize(new TerminalSize(leftWidth, leftHeight)); thumb.setSize(thumb.getPreferredSize()); @@ -211,10 +275,10 @@ public void doLayout(TerminalSize area, List components) { thumb.setPosition(new TerminalPosition(leftWidth, h / 2 - tHeight / 2)); compB.setPosition(new TerminalPosition(leftWidth + tWidth, 0)); } else { - int leftWidth = Math.max(0, Math.min(compA.getPreferredSize().getColumns(), w)); + int leftWidth = Math.max(0, w); int leftHeight = Math.max(0, (int) (h * ratio)); - int rightWidth = Math.max(0, Math.min(compB.getPreferredSize().getColumns(), w)); + int rightWidth = Math.max(0, w); int rightHeight = Math.max(0, h - leftHeight); compA.setSize(new TerminalSize(leftWidth, leftHeight)); @@ -253,6 +317,7 @@ public void setRatio(int left, int right) { int total = Math.abs(left) + Math.abs(right); ratio = (double) left / (double) total; } + invalidate(); } public void setThumbVisible(boolean visible) { diff --git a/src/test/java/com/googlecode/lanterna/gui2/SplitPanelTest.java b/src/test/java/com/googlecode/lanterna/gui2/SplitPanelTest.java index ed6231f4a..222253053 100644 --- a/src/test/java/com/googlecode/lanterna/gui2/SplitPanelTest.java +++ b/src/test/java/com/googlecode/lanterna/gui2/SplitPanelTest.java @@ -18,9 +18,14 @@ */ package com.googlecode.lanterna.gui2; -import com.googlecode.lanterna.*; -import com.googlecode.lanterna.bundle.*; -import com.googlecode.lanterna.graphics.*; +import java.util.Arrays; + +import com.googlecode.lanterna.TerminalSize; +import com.googlecode.lanterna.TextCharacter; +import com.googlecode.lanterna.bundle.LanternaThemes; +import com.googlecode.lanterna.graphics.BasicTextImage; +import com.googlecode.lanterna.graphics.TextImage; +import com.googlecode.lanterna.gui2.LinearLayout.GrowPolicy; /** * @@ -116,6 +121,7 @@ public static void main(String[] args) throws Exception { @Override public void init(WindowBasedTextGUI textGUI) { final BasicWindow window = new BasicWindow("SplitPanelTest"); + window.setHints(Arrays.asList(Window.Hint.FULL_SCREEN)); window.setTheme(LanternaThemes.getRegisteredTheme("businessmachine")); ImageComponent left = makeImageComponent(IMAGE_X); @@ -133,9 +139,34 @@ public void init(WindowBasedTextGUI textGUI) { splitV.setRatio(20, 80); Panel mainPanel = new Panel(); - mainPanel.setLayoutManager(new GridLayout(2)); + mainPanel.setLayoutManager(new BorderLayout()); SplitPanel splitboth = SplitPanel.ofHorizontal(splitH.withBorder(Borders.singleLine("horiontal split")), splitV.withBorder(Borders.singleLine("vertical split"))); - mainPanel.addComponent(splitboth); + + Panel pnlTextV = new Panel(); + pnlTextV.setLayoutManager(new BorderLayout()); + { + String txt = "This is a multiline text box on the bottom of the vertical SplitPanel that should expand to take up the extra space."; + TextBox txtLogs = new TextBox(txt, TextBox.Style.MULTI_LINE); + txtLogs.setHorizontalFocusSwitching(false); + txtLogs.setVerticalFocusSwitching(false); + + pnlTextV.addComponent(txtLogs, BorderLayout.Location.CENTER); + } + + SplitPanel splitLeft = SplitPanel.ofVertical(splitboth.withBorder(Borders.singleLine()), pnlTextV.withBorder(Borders.singleLine())); + Panel pnlTextH = new Panel(); + pnlTextH.setLayoutManager(new BorderLayout()); + { + String txt = "This is a multiline text box on the bottom of the horizontal SplitPanel that should expand to take up the extra space."; + TextBox txtLogs = new TextBox(txt, TextBox.Style.MULTI_LINE); + txtLogs.setHorizontalFocusSwitching(false); + txtLogs.setVerticalFocusSwitching(false); + + pnlTextH.addComponent(txtLogs, BorderLayout.Location.CENTER); + } + + SplitPanel splitMain = SplitPanel.ofHorizontal(splitLeft.withBorder(Borders.singleLine("Left Component")), pnlTextH.withBorder(Borders.singleLine("Right Component"))); + mainPanel.addComponent(splitMain, BorderLayout.Location.CENTER); window.setComponent(mainPanel); textGUI.addWindow(window);