/* * This file is part of lanterna (http://code.google.com/p/lanterna/). * * lanterna is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Copyright (C) 2010-2017 Martin Berglund */ package com.googlecode.lanterna.gui2; import com.googlecode.lanterna.TerminalSize; import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.gui2.dialogs.DialogWindow; import com.googlecode.lanterna.gui2.dialogs.ListSelectDialog; import com.googlecode.lanterna.gui2.dialogs.TextInputDialog; import com.googlecode.lanterna.gui2.dialogs.TextInputDialogBuilder; import java.io.IOException; import java.math.BigInteger; import java.util.Random; import java.util.regex.Pattern; public class DynamicGridLayoutTest extends TestBase { public static void main(String[] args) throws IOException, InterruptedException { new DynamicGridLayoutTest().run(args); } private static final TextColor[] GOOD_COLORS = new TextColor[] { TextColor.ANSI.RED, TextColor.ANSI.BLUE, TextColor.ANSI.CYAN, TextColor.ANSI.GREEN, TextColor.ANSI.MAGENTA, TextColor.ANSI.YELLOW }; private static final Random RANDOM = new Random(); @Override public void init(final WindowBasedTextGUI textGUI) { final BasicWindow window = new BasicWindow("Grid layout test"); Panel mainPanel = new Panel(); mainPanel.setLayoutManager(new LinearLayout(Direction.VERTICAL).setSpacing(1)); final Panel gridPanel = new Panel(); GridLayout gridLayout = newGridLayout(4); gridPanel.setLayoutManager(gridLayout); for(int i = 0; i < 16; i++) { gridPanel.addComponent(new EmptySpace(getRandomColor(), new TerminalSize(4, 1))); } Panel controlPanel = new Panel(); controlPanel.setLayoutManager(new LinearLayout(Direction.HORIZONTAL)); controlPanel.addComponent(new Button("Add Component", new Runnable() { @Override public void run() { onAddComponent(textGUI, gridPanel); } })); controlPanel.addComponent(new Button("Modify Component", new Runnable() { @Override public void run() { onModifyComponent(textGUI, gridPanel); } })); controlPanel.addComponent(new Button("Modify Grid", new Runnable() { @Override public void run() { onModifyGrid(textGUI, (GridLayout)gridPanel.getLayoutManager()); } })); controlPanel.addComponent(new Button("Reset Grid", new Runnable() { @Override public void run() { onResetGrid(textGUI, gridPanel); } })); controlPanel.addComponent(new Button("Exit", new Runnable() { @Override public void run() { window.close(); } })); mainPanel.addComponent(gridPanel); mainPanel.addComponent( new Separator(Direction.HORIZONTAL) .setLayoutData( LinearLayout.createLayoutData(LinearLayout.Alignment.Fill))); mainPanel.addComponent(controlPanel); window.setComponent(mainPanel); textGUI.addWindow(window); } private void onModifyGrid(WindowBasedTextGUI textGUI, GridLayout gridLayout) { GridLayoutEditor gridLayoutEditor = new GridLayoutEditor(gridLayout); gridLayoutEditor.showDialog(textGUI); } private void onAddComponent(WindowBasedTextGUI textGUI, Panel gridPanel) { SelectableComponentType componentType = ListSelectDialog.showDialog( textGUI, "Add Component", "Select component to add", SelectableComponentType.values()); if(componentType == null) { return; } Component component = null; switch(componentType) { case Block: case TextBox: String sizeString = new TextInputDialogBuilder() .setInitialContent(componentType == SelectableComponentType.Block ? "4x1" : "16x1") .setTitle("Add " + componentType) .setDescription("Enter size of " + componentType + " (<columns>x<rows>)") .setValidationPattern(Pattern.compile("[0-9]+x[0-9]+"), "Invalid format, please use <columns>x<rows>") .build() .showDialog(textGUI); if(sizeString == null) { return; } TerminalSize size = new TerminalSize(Integer.parseInt(sizeString.split("x")[0]), Integer.parseInt(sizeString.split("x")[1])); component = componentType == SelectableComponentType.Block ? new EmptySpace(getRandomColor(), size) : new TextBox(size); break; case Label: String text = TextInputDialog.showDialog(textGUI, "Add " + componentType, "Enter the text of the new Label", "Label"); component = new Label(text); break; } gridPanel.addComponent(component); } private void onModifyComponent(WindowBasedTextGUI textGUI, Panel panel) { Component[] components = panel.getChildren().toArray(new Component[panel.getChildCount()]); Component component = ListSelectDialog.showDialog(textGUI, "Modify Component", "Select component to modify", 10, components); if(component == null) { return; } GridLayoutDataEditor gridLayoutDataEditor = new GridLayoutDataEditor(component); gridLayoutDataEditor.showDialog(textGUI); } private void onResetGrid(WindowBasedTextGUI textGUI, Panel gridPanel) { BigInteger columns = TextInputDialog.showNumberDialog(textGUI, "Reset Grid", "Reset grid to how many columns?", "4"); if(columns == null) { return; } BigInteger prepopulate = TextInputDialog.showNumberDialog( textGUI, "Reset Grid", "Pre-populate grid with how many dummy components?", columns.toString()); gridPanel.removeAllComponents(); gridPanel.setLayoutManager(newGridLayout(columns.intValue())); //noinspection ConstantConditions for(int i = 0; i < prepopulate.intValue(); i++) { gridPanel.addComponent(new EmptySpace(getRandomColor(), new TerminalSize(4, 1))); } } private TextColor getRandomColor() { return GOOD_COLORS[RANDOM.nextInt(GOOD_COLORS.length)]; } private GridLayout newGridLayout(int columns) { GridLayout gridLayout = new GridLayout(columns); gridLayout.setTopMarginSize(1); gridLayout.setVerticalSpacing(1); gridLayout.setHorizontalSpacing(1); return gridLayout; } private enum SelectableComponentType { Block, Label, TextBox, } private static class GridLayoutEditor extends DialogWindow { public GridLayoutEditor(final GridLayout gridLayout) { super("GridLayoutData Editor"); Pattern numberPattern = Pattern.compile("[0-9]+"); Panel contentPane = new Panel(); contentPane.setLayoutManager(new GridLayout(2)); contentPane.addComponent(new Label("Horizontal spacing:")); final TextBox textBoxHorizontalSpacing = new TextBox(); textBoxHorizontalSpacing.setText(gridLayout.getHorizontalSpacing() + ""); textBoxHorizontalSpacing.setValidationPattern(numberPattern); contentPane.addComponent(textBoxHorizontalSpacing); contentPane.addComponent(new Label("Vertical spacing:")); final TextBox textBoxVerticalSpacing = new TextBox(); textBoxVerticalSpacing.setText(gridLayout.getVerticalSpacing() + ""); textBoxVerticalSpacing.setValidationPattern(numberPattern); contentPane.addComponent(textBoxVerticalSpacing); contentPane.addComponent(new Label("Left margin:")); final TextBox textBoxLeftMargin = new TextBox(); textBoxLeftMargin.setText(gridLayout.getLeftMarginSize() + ""); textBoxLeftMargin.setValidationPattern(numberPattern); contentPane.addComponent(textBoxLeftMargin); contentPane.addComponent(new Label("Right margin:")); final TextBox textBoxRightMargin = new TextBox(); textBoxRightMargin.setText(gridLayout.getRightMarginSize() + ""); textBoxRightMargin.setValidationPattern(numberPattern); contentPane.addComponent(textBoxRightMargin); contentPane.addComponent(new Label("Top margin:")); final TextBox textBoxTopMargin = new TextBox(); textBoxTopMargin.setText(gridLayout.getTopMarginSize() + ""); textBoxTopMargin.setValidationPattern(numberPattern); contentPane.addComponent(textBoxTopMargin); contentPane.addComponent(new Label("Bottom margin:")); final TextBox textBoxBottomMargin = new TextBox(); textBoxBottomMargin.setText(gridLayout.getBottomMarginSize() + ""); textBoxBottomMargin.setValidationPattern(numberPattern); contentPane.addComponent(textBoxBottomMargin); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); contentPane.addComponent( new Separator(Direction.HORIZONTAL).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); Button okButton = new Button("OK", new Runnable() { @Override public void run() { gridLayout.setHorizontalSpacing(Integer.parseInt(textBoxHorizontalSpacing.getTextOrDefault("0"))); gridLayout.setVerticalSpacing(Integer.parseInt(textBoxVerticalSpacing.getTextOrDefault("0"))); gridLayout.setLeftMarginSize(Integer.parseInt(textBoxLeftMargin.getTextOrDefault("0"))); gridLayout.setRightMarginSize(Integer.parseInt(textBoxRightMargin.getTextOrDefault("0"))); gridLayout.setTopMarginSize(Integer.parseInt(textBoxTopMargin.getTextOrDefault("0"))); gridLayout.setBottomMarginSize(Integer.parseInt(textBoxBottomMargin.getTextOrDefault("0"))); close(); } }); Button cancelButton = new Button("Cancel", new Runnable() { @Override public void run() { close(); } }); contentPane.addComponent( Panels.horizontal(okButton, cancelButton) .setLayoutData(GridLayout.createHorizontallyEndAlignedLayoutData(2))); setComponent(contentPane); } } private static class GridLayoutDataEditor extends DialogWindow { public GridLayoutDataEditor(final Component component) { super("GridLayoutData Editor"); GridLayout.GridLayoutData gridLayoutData = (GridLayout.GridLayoutData)component.getLayoutData(); if(gridLayoutData == null) { gridLayoutData = (GridLayout.GridLayoutData)GridLayout.createLayoutData(GridLayout.Alignment.BEGINNING, GridLayout.Alignment.BEGINNING); } Panel contentPane = new Panel(); contentPane.setLayoutManager(new GridLayout(2)); contentPane.addComponent(new Label("Horizontal alignment:")); final RadioBoxList<GridLayout.Alignment> radioBoxesHorizontalAlignment = new RadioBoxList<GridLayout.Alignment>(); radioBoxesHorizontalAlignment.addItem(GridLayout.Alignment.BEGINNING); radioBoxesHorizontalAlignment.addItem(GridLayout.Alignment.CENTER); radioBoxesHorizontalAlignment.addItem(GridLayout.Alignment.END); radioBoxesHorizontalAlignment.addItem(GridLayout.Alignment.FILL); radioBoxesHorizontalAlignment.setCheckedItem(gridLayoutData.horizontalAlignment); contentPane.addComponent(radioBoxesHorizontalAlignment); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); contentPane.addComponent(new Label("Vertical alignment:")); final RadioBoxList<GridLayout.Alignment> radioBoxesVerticalAlignment = new RadioBoxList<GridLayout.Alignment>(); radioBoxesVerticalAlignment.addItem(GridLayout.Alignment.BEGINNING); radioBoxesVerticalAlignment.addItem(GridLayout.Alignment.CENTER); radioBoxesVerticalAlignment.addItem(GridLayout.Alignment.END); radioBoxesVerticalAlignment.addItem(GridLayout.Alignment.FILL); radioBoxesVerticalAlignment.setCheckedItem(gridLayoutData.verticalAlignment); contentPane.addComponent(radioBoxesVerticalAlignment); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); contentPane.addComponent(new Label("Grab extra horizontal space:")); final CheckBox checkBoxGrabExtraHorizontalSpace = new CheckBox(""); checkBoxGrabExtraHorizontalSpace.setChecked(gridLayoutData.grabExtraHorizontalSpace); contentPane.addComponent(checkBoxGrabExtraHorizontalSpace); contentPane.addComponent(new Label("Grab extra vertical space:")); final CheckBox checkBoxGrabExtraVerticalSpace = new CheckBox(""); checkBoxGrabExtraVerticalSpace.setChecked(gridLayoutData.grabExtraVerticalSpace); contentPane.addComponent(checkBoxGrabExtraVerticalSpace); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); Pattern numberPattern = Pattern.compile("[1-9][0-9]*"); contentPane.addComponent(new Label("Horizontal span:")); final TextBox textBoxHorizontalSpan = new TextBox(new TerminalSize(5, 1), gridLayoutData.horizontalSpan + ""); textBoxHorizontalSpan.setValidationPattern(numberPattern); contentPane.addComponent(textBoxHorizontalSpan); contentPane.addComponent(new Label("Vertical span:")); final TextBox textBoxVerticalSpan = new TextBox(new TerminalSize(5, 1), gridLayoutData.verticalSpan + ""); textBoxVerticalSpan.setValidationPattern(numberPattern); contentPane.addComponent(textBoxVerticalSpan); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); contentPane.addComponent( new Separator(Direction.HORIZONTAL).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); contentPane.addComponent( new EmptySpace(TerminalSize.ONE).setLayoutData(GridLayout.createHorizontallyFilledLayoutData(2))); Button okButton = new Button("OK", new Runnable() { @Override public void run() { component.setLayoutData( GridLayout.createLayoutData( radioBoxesHorizontalAlignment.getCheckedItem(), radioBoxesVerticalAlignment.getCheckedItem(), checkBoxGrabExtraHorizontalSpace.isChecked(), checkBoxGrabExtraVerticalSpace.isChecked(), Integer.parseInt(textBoxHorizontalSpan.getTextOrDefault("1")), Integer.parseInt(textBoxVerticalSpan.getTextOrDefault("1")))); close(); } }); Button cancelButton = new Button("Cancel", new Runnable() { @Override public void run() { close(); } }); contentPane.addComponent( Panels.horizontal(okButton, cancelButton) .setLayoutData(GridLayout.createHorizontallyEndAlignedLayoutData(2))); setComponent(contentPane); } } }