
com.googlecode.lanterna.gui2.BorderLayout Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lanterna Show documentation
Show all versions of lanterna Show documentation
Java library for creating text-based terminal GUIs
/*
* 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 .
*
* Copyright (C) 2010-2016 Martin
*/
package com.googlecode.lanterna.gui2;
import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TerminalSize;
import java.util.*;
/**
* BorderLayout imitates the BorderLayout class from AWT, allowing you to add a center component with optional
* components around it in top, bottom, left and right locations. The edge components will be sized at their preferred
* size and the center component will take up whatever remains.
* @author martin
*/
public class BorderLayout implements LayoutManager {
/**
* This type is what you use as the layout data for components added to a panel using {@code BorderLayout} for its
* layout manager. This values specified where inside the panel the component should be added.
*/
public enum Location implements LayoutData {
/**
* The component with this value as its layout data will occupy the center space, whatever is remaining after
* the other components (if any) have allocated their space.
*/
CENTER,
/**
* The component with this value as its layout data will occupy the left side of the container, attempting to
* allocate the preferred width of the component and at least the preferred height, but could be more depending
* on the other components added.
*/
LEFT,
/**
* The component with this value as its layout data will occupy the right side of the container, attempting to
* allocate the preferred width of the component and at least the preferred height, but could be more depending
* on the other components added.
*/
RIGHT,
/**
* The component with this value as its layout data will occupy the top side of the container, attempting to
* allocate the preferred height of the component and at least the preferred width, but could be more depending
* on the other components added.
*/
TOP,
/**
* The component with this value as its layout data will occupy the bottom side of the container, attempting to
* allocate the preferred height of the component and at least the preferred width, but could be more depending
* on the other components added.
*/
BOTTOM,
;
}
//When components don't have a location, we'll assign an available location based on this order
private static final List AUTO_ASSIGN_ORDER = Collections.unmodifiableList(Arrays.asList(
Location.CENTER,
Location.TOP,
Location.BOTTOM,
Location.LEFT,
Location.RIGHT));
@Override
public TerminalSize getPreferredSize(List components) {
EnumMap layout = makeLookupMap(components);
int preferredHeight =
(layout.containsKey(Location.TOP) ? layout.get(Location.TOP).getPreferredSize().getRows() : 0)
+
Math.max(
layout.containsKey(Location.LEFT) ? layout.get(Location.LEFT).getPreferredSize().getRows() : 0,
Math.max(
layout.containsKey(Location.CENTER) ? layout.get(Location.CENTER).getPreferredSize().getRows() : 0,
layout.containsKey(Location.RIGHT) ? layout.get(Location.RIGHT).getPreferredSize().getRows() : 0))
+
(layout.containsKey(Location.BOTTOM) ? layout.get(Location.BOTTOM).getPreferredSize().getRows() : 0);
int preferredWidth =
Math.max(
(layout.containsKey(Location.LEFT) ? layout.get(Location.LEFT).getPreferredSize().getColumns() : 0) +
(layout.containsKey(Location.CENTER) ? layout.get(Location.CENTER).getPreferredSize().getColumns() : 0) +
(layout.containsKey(Location.RIGHT) ? layout.get(Location.RIGHT).getPreferredSize().getColumns() : 0),
Math.max(
layout.containsKey(Location.TOP) ? layout.get(Location.TOP).getPreferredSize().getColumns() : 0,
layout.containsKey(Location.BOTTOM) ? layout.get(Location.BOTTOM).getPreferredSize().getColumns() : 0));
return new TerminalSize(preferredWidth, preferredHeight);
}
@Override
public void doLayout(TerminalSize area, List components) {
EnumMap layout = makeLookupMap(components);
int availableHorizontalSpace = area.getColumns();
int availableVerticalSpace = area.getRows();
//We'll need this later on
int topComponentHeight = 0;
int leftComponentWidth = 0;
//First allocate the top
if(layout.containsKey(Location.TOP)) {
Component topComponent = layout.get(Location.TOP);
topComponentHeight = Math.min(topComponent.getPreferredSize().getRows(), availableVerticalSpace);
topComponent.setPosition(TerminalPosition.TOP_LEFT_CORNER);
topComponent.setSize(new TerminalSize(availableHorizontalSpace, topComponentHeight));
availableVerticalSpace -= topComponentHeight;
}
//Next allocate the bottom
if(layout.containsKey(Location.BOTTOM)) {
Component bottomComponent = layout.get(Location.BOTTOM);
int bottomComponentHeight = Math.min(bottomComponent.getPreferredSize().getRows(), availableVerticalSpace);
bottomComponent.setPosition(new TerminalPosition(0, area.getRows() - bottomComponentHeight));
bottomComponent.setSize(new TerminalSize(availableHorizontalSpace, bottomComponentHeight));
availableVerticalSpace -= bottomComponentHeight;
}
//Now divide the remaining space between LEFT, CENTER and RIGHT
if(layout.containsKey(Location.LEFT)) {
Component leftComponent = layout.get(Location.LEFT);
leftComponentWidth = Math.min(leftComponent.getPreferredSize().getColumns(), availableHorizontalSpace);
leftComponent.setPosition(new TerminalPosition(0, topComponentHeight));
leftComponent.setSize(new TerminalSize(leftComponentWidth, availableVerticalSpace));
availableHorizontalSpace -= leftComponentWidth;
}
if(layout.containsKey(Location.RIGHT)) {
Component rightComponent = layout.get(Location.RIGHT);
int rightComponentWidth = Math.min(rightComponent.getPreferredSize().getColumns(), availableHorizontalSpace);
rightComponent.setPosition(new TerminalPosition(area.getColumns() - rightComponentWidth, topComponentHeight));
rightComponent.setSize(new TerminalSize(rightComponentWidth, availableVerticalSpace));
availableHorizontalSpace -= rightComponentWidth;
}
if(layout.containsKey(Location.CENTER)) {
Component centerComponent = layout.get(Location.CENTER);
centerComponent.setPosition(new TerminalPosition(leftComponentWidth, topComponentHeight));
centerComponent.setSize(new TerminalSize(availableHorizontalSpace, availableVerticalSpace));
}
//Set the remaining components to 0x0
for(Component component: components) {
if(!layout.values().contains(component)) {
component.setPosition(TerminalPosition.TOP_LEFT_CORNER);
component.setSize(TerminalSize.ZERO);
}
}
}
private EnumMap makeLookupMap(List components) {
EnumMap map = new EnumMap(Location.class);
List unassignedComponents = new ArrayList();
for(Component component: components) {
if(component.getLayoutData() instanceof Location) {
map.put((Location)component.getLayoutData(), component);
}
else {
unassignedComponents.add(component);
}
}
//Try to assign components to available locations
for(Component component: unassignedComponents) {
for(Location location: AUTO_ASSIGN_ORDER) {
if(!map.containsKey(location)) {
map.put(location, component);
break;
}
}
}
return map;
}
@Override
public boolean hasChanged() {
//No internal state
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy