I'm experiementing with lanterna's 4th tutorial. When I create a GridLayout with 2 columns and add 2 Labels that each span the 2 columns the program runs without errors. But when I make a GridLayout with 4 columns and add 2 Labels that span the 4 columns I get the following ArrayIndexOutOfBoundsException runtime error.
[rmcgregor@cs lanterna]$ make 4
java -cp .:lanterna-3.0.0.jar GUIApp
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at com.googlecode.lanterna.gui2.GridLayout.getPreferredColumnWidths(GridLayout.java:542)
at com.googlecode.lanterna.gui2.GridLayout.getPreferredSize(GridLayout.java:387)
at com.googlecode.lanterna.gui2.Panel$1.getPreferredSize(Panel.java:187)
at com.googlecode.lanterna.gui2.Panel$1.getPreferredSize(Panel.java:182)
at com.googlecode.lanterna.gui2.AbstractComponent.calculatePreferredSize(AbstractComponent.java:194)
at com.googlecode.lanterna.gui2.Panel.calculatePreferredSize(Panel.java:217)
at com.googlecode.lanterna.gui2.AbstractComponent.getPreferredSize(AbstractComponent.java:178)
at com.googlecode.lanterna.gui2.AbstractBasePane$ContentHolder$1.getPreferredSize(AbstractBasePane.java:331)
at com.googlecode.lanterna.gui2.AbstractBasePane$ContentHolder$1.getPreferredSize(AbstractBasePane.java:324)
at com.googlecode.lanterna.gui2.AbstractComponent.calculatePreferredSize(AbstractComponent.java:194)
at com.googlecode.lanterna.gui2.AbstractComponent.getPreferredSize(AbstractComponent.java:178)
at com.googlecode.lanterna.gui2.AbstractWindow.getPreferredSize(AbstractWindow.java:161)
at com.googlecode.lanterna.gui2.DefaultWindowManager.onAdded(DefaultWindowManager.java:103)
at com.googlecode.lanterna.gui2.MultiWindowTextGUI.addWindow(MultiWindowTextGUI.java:356)
at com.googlecode.lanterna.gui2.MultiWindowTextGUI.addWindowAndWait(MultiWindowTextGUI.java:369)
at GUIApp.main(GUIApp.java:50)
Here is the source code.
import java.io.IOException;
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
import com.googlecode.lanterna.screen.Screen;
import com.googlecode.lanterna.gui2.*;
class GUIApp {
public static void main(String[] args) {
DefaultTerminalFactory terminalFactory = new DefaultTerminalFactory();
Screen screen = null;
try {
screen = terminalFactory.createScreen();
screen.startScreen();
final WindowBasedTextGUI textGUI = new MultiWindowTextGUI(screen);
final Window window = new BasicWindow();
Panel contentPanel = new Panel(new GridLayout(4));
GridLayout gridLayout = (GridLayout)contentPanel.getLayoutManager();
gridLayout.setHorizontalSpacing(3);
Label title = new Label("This is a label that spans two columns");
title.setLayoutData(GridLayout.createLayoutData(
GridLayout.Alignment.BEGINNING,
GridLayout.Alignment.BEGINNING,
true,
false,
4,
1));
contentPanel.addComponent(title);
Label alignedText = new Label("Text Box (aligned)");
alignedText.setLayoutData(GridLayout.createLayoutData(
GridLayout.Alignment.BEGINNING,
GridLayout.Alignment.BEGINNING,
true,
false,
4,
1));
contentPanel.addComponent(alignedText);
//Label moreText = new Label("more text");
//contentPanel.addComponent(moreText);
window.setComponent(contentPanel);
textGUI.addWindowAndWait(window);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if(screen != null) {
try {
screen.stopScreen();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
}
}
Any help explaining what I'm conceptually misunderstanding would be great!
I've been doing some testing and think I found a bug in the GridLayout. I've reported it on the lanterna google groups forum.
It appears that you cannot add to the first row a Button or Label that spans more than once column. They can be included on any row after the first. Interestingly, you may add to the first row EmptySpace that spans more than one column.
Here are my test cases. Hope they help understand the issue.
private static class GUIAppWindow extends BasicWindow {
GUIAppWindow() {
Panel contentPanel = new Panel(new GridLayout(4));
GridLayout gridLayout = (GridLayout)contentPanel.getLayoutManager();
gridLayout.setHorizontalSpacing(3);
// Valid First Row *****************************************************
contentPanel.addComponent(new Label("AAAAA"));
contentPanel.addComponent(new Label("BBBBB"));
contentPanel.addComponent(new Label("DDDDD"));
contentPanel.addComponent(new Label("EEEEE"));
// Valid First Row *****************************************************
contentPanel.addComponent(
new EmptySpace()
.setLayoutData(
GridLayout.createHorizontallyFilledLayoutData(3)));
contentPanel.addComponent(new Label("HHHHH"));
// Valid First Row *****************************************************
contentPanel.addComponent(new Label("HHHHH"));
contentPanel.addComponent(
new EmptySpace()
.setLayoutData(
GridLayout.createHorizontallyFilledLayoutData(2)));
contentPanel.addComponent(new Label("IIIII"));
// Valid First Row *****************************************************
contentPanel.addComponent(new Label("BBBBB"));
contentPanel.addComponent(new Label("DDDDD"));
contentPanel.addComponent(new Label("EEEEE"));
contentPanel.addComponent(new Button("Exit", new Runnable() {
@Override
public void run() {
GUIAppWindow.this.close();
}
}));
// Invalid First Row *****************************************************
contentPanel.addComponent(new Label("KKKKK"));
contentPanel.addComponent(new Label("LLLLL"));
contentPanel.addComponent(
new Button("Close", new Runnable() {
@Override
public void run() {
GUIAppWindow.this.close();
}
}), GridLayout.createHorizontallyEndAlignedLayoutData(2));
// Invalid First Row *****************************************************
contentPanel.addComponent(
new EmptySpace()
.setLayoutData(
GridLayout.createHorizontallyFilledLayoutData(2)));
contentPanel.addComponent(new Label("CCCCC"), GridLayout.createLayoutData(
GridLayout.Alignment.CENTER,
GridLayout.Alignment.BEGINNING,
false,
false,
2,
1));
// Invalid First Row *****************************************************
contentPanel.addComponent(new Label("FFFFF"), GridLayout.createLayoutData(
GridLayout.Alignment.CENTER,
GridLayout.Alignment.BEGINNING,
true,
false,
4,
1));
// Invalid First Row *****************************************************
contentPanel.addComponent(new Label("DDDDD"));
contentPanel.addComponent(new Label("EEEEE"));
contentPanel.addComponent(new Label("FFFFF"), GridLayout.createLayoutData(
GridLayout.Alignment.CENTER,
GridLayout.Alignment.BEGINNING,
true,
false,
2,
1));
this.setComponent(contentPanel);
}
}