+++ /dev/null
-/*
- * 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-2015 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<Location> AUTO_ASSIGN_ORDER = Collections.unmodifiableList(Arrays.asList(
- Location.CENTER,
- Location.TOP,
- Location.BOTTOM,
- Location.LEFT,
- Location.RIGHT));
-
- @Override
- public TerminalSize getPreferredSize(List<Component> components) {
- EnumMap<Location, Component> 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<Component> components) {
- EnumMap<Location, Component> 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<Location, Component> makeLookupMap(List<Component> components) {
- EnumMap<Location, Component> map = new EnumMap<BorderLayout.Location, Component>(Location.class);
- List<Component> unassignedComponents = new ArrayList<Component>();
- 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;
- }
-}