/*
* 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-2015 Martin
*/
package com.googlecode.lanterna;
/**
* Terminal dimensions in 2-d space, measured in number of rows and columns. This class is immutable and cannot change
* its internal state after creation.
*
* @author Martin
*/
public class TerminalSize {
public static final TerminalSize ZERO = new TerminalSize(0, 0);
public static final TerminalSize ONE = new TerminalSize(1, 1);
private final int columns;
private final int rows;
/**
* Creates a new terminal size representation with a given width (columns) and height (rows)
* @param columns Width, in number of columns
* @param rows Height, in number of columns
*/
public TerminalSize(int columns, int rows) {
if (columns < 0) {
throw new IllegalArgumentException("TerminalSize.columns cannot be less than 0!");
}
if (rows < 0) {
throw new IllegalArgumentException("TerminalSize.rows cannot be less than 0!");
}
this.columns = columns;
this.rows = rows;
}
/**
* @return Returns the width of this size representation, in number of columns
*/
public int getColumns() {
return columns;
}
/**
* Creates a new size based on this size, but with a different width
* @param columns Width of the new size, in columns
* @return New size based on this one, but with a new width
*/
public TerminalSize withColumns(int columns) {
if(this.columns == columns) {
return this;
}
if(columns == 0 && this.rows == 0) {
return ZERO;
}
return new TerminalSize(columns, this.rows);
}
/**
* @return Returns the height of this size representation, in number of rows
*/
public int getRows() {
return rows;
}
/**
* Creates a new size based on this size, but with a different height
* @param rows Height of the new size, in rows
* @return New size based on this one, but with a new height
*/
public TerminalSize withRows(int rows) {
if(this.rows == rows) {
return this;
}
if(rows == 0 && this.columns == 0) {
return ZERO;
}
return new TerminalSize(this.columns, rows);
}
/**
* Creates a new TerminalSize object representing a size with the same number of rows, but with a column size offset by a
* supplied value. Calling this method with delta 0 will return this, calling it with a positive delta will return
* a terminal size delta number of columns wider and for negative numbers shorter.
* @param delta Column offset
* @return New terminal size based off this one but with an applied transformation
*/
public TerminalSize withRelativeColumns(int delta) {
if(delta == 0) {
return this;
}
return withColumns(columns + delta);
}
/**
* Creates a new TerminalSize object representing a size with the same number of columns, but with a row size offset by a
* supplied value. Calling this method with delta 0 will return this, calling it with a positive delta will return
* a terminal size delta number of rows longer and for negative numbers shorter.
* @param delta Row offset
* @return New terminal size based off this one but with an applied transformation
*/
public TerminalSize withRelativeRows(int delta) {
if(delta == 0) {
return this;
}
return withRows(rows + delta);
}
/**
* Creates a new TerminalSize object representing a size based on this object's size but with a delta applied.
* This is the same as calling
* withRelativeColumns(delta.getColumns()).withRelativeRows(delta.getRows())
* @param delta Column and row offset
* @return New terminal size based off this one but with an applied resize
*/
public TerminalSize withRelative(TerminalSize delta) {
return withRelative(delta.getColumns(), delta.getRows());
}
/**
* Creates a new TerminalSize object representing a size based on this object's size but with a delta applied.
* This is the same as calling
* withRelativeColumns(deltaColumns).withRelativeRows(deltaRows)
* @param deltaColumns How many extra columns the new TerminalSize will have (negative values are allowed)
* @param deltaRows How many extra rows the new TerminalSize will have (negative values are allowed)
* @return New terminal size based off this one but with an applied resize
*/
public TerminalSize withRelative(int deltaColumns, int deltaRows) {
return withRelativeRows(deltaRows).withRelativeColumns(deltaColumns);
}
/**
* Takes a different TerminalSize and returns a new TerminalSize that has the largest dimensions of the two,
* measured separately. So calling 3x5 on a 5x3 will return 5x5.
* @param other Other TerminalSize to compare with
* @return TerminalSize that combines the maximum width between the two and the maximum height
*/
public TerminalSize max(TerminalSize other) {
return withColumns(Math.max(columns, other.columns))
.withRows(Math.max(rows, other.rows));
}
/**
* Takes a different TerminalSize and returns a new TerminalSize that has the smallest dimensions of the two,
* measured separately. So calling 3x5 on a 5x3 will return 3x3.
* @param other Other TerminalSize to compare with
* @return TerminalSize that combines the minimum width between the two and the minimum height
*/
public TerminalSize min(TerminalSize other) {
return withColumns(Math.min(columns, other.columns))
.withRows(Math.min(rows, other.rows));
}
/**
* Returns itself if it is equal to the supplied size, otherwise the supplied size. You can use this if you have a
* size field which is frequently recalculated but often resolves to the same size; it will keep the same object
* in memory instead of swapping it out every cycle.
* @param size Size you want to return
* @return Itself if this size equals the size passed in, otherwise the size passed in
*/
public TerminalSize with(TerminalSize size) {
if(equals(size)) {
return this;
}
return size;
}
@Override
public String toString() {
return "{" + columns + "x" + rows + "}";
}
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if (!(obj instanceof TerminalSize)) {
return false;
}
TerminalSize other = (TerminalSize) obj;
return columns == other.columns
&& rows == other.rows;
}
@Override
public int hashCode() {
int hash = 5;
hash = 53 * hash + this.columns;
hash = 53 * hash + this.rows;
return hash;
}
}