0de71344b4dd7e2fbd57622d8bb475e35921a336
[jvcard.git] / TerminalSize.java
1 /*
2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
3 *
4 * lanterna is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Copyright (C) 2010-2015 Martin
18 */
19 package com.googlecode.lanterna;
20
21 /**
22 * Terminal dimensions in 2-d space, measured in number of rows and columns. This class is immutable and cannot change
23 * its internal state after creation.
24 *
25 * @author Martin
26 */
27 public class TerminalSize {
28 public static final TerminalSize ZERO = new TerminalSize(0, 0);
29 public static final TerminalSize ONE = new TerminalSize(1, 1);
30
31 private final int columns;
32 private final int rows;
33
34 /**
35 * Creates a new terminal size representation with a given width (columns) and height (rows)
36 * @param columns Width, in number of columns
37 * @param rows Height, in number of columns
38 */
39 public TerminalSize(int columns, int rows) {
40 if (columns < 0) {
41 throw new IllegalArgumentException("TerminalSize.columns cannot be less than 0!");
42 }
43 if (rows < 0) {
44 throw new IllegalArgumentException("TerminalSize.rows cannot be less than 0!");
45 }
46 this.columns = columns;
47 this.rows = rows;
48 }
49
50 /**
51 * @return Returns the width of this size representation, in number of columns
52 */
53 public int getColumns() {
54 return columns;
55 }
56
57 /**
58 * Creates a new size based on this size, but with a different width
59 * @param columns Width of the new size, in columns
60 * @return New size based on this one, but with a new width
61 */
62 public TerminalSize withColumns(int columns) {
63 if(this.columns == columns) {
64 return this;
65 }
66 if(columns == 0 && this.rows == 0) {
67 return ZERO;
68 }
69 return new TerminalSize(columns, this.rows);
70 }
71
72
73 /**
74 * @return Returns the height of this size representation, in number of rows
75 */
76 public int getRows() {
77 return rows;
78 }
79
80 /**
81 * Creates a new size based on this size, but with a different height
82 * @param rows Height of the new size, in rows
83 * @return New size based on this one, but with a new height
84 */
85 public TerminalSize withRows(int rows) {
86 if(this.rows == rows) {
87 return this;
88 }
89 if(rows == 0 && this.columns == 0) {
90 return ZERO;
91 }
92 return new TerminalSize(this.columns, rows);
93 }
94
95 /**
96 * Creates a new TerminalSize object representing a size with the same number of rows, but with a column size offset by a
97 * supplied value. Calling this method with delta 0 will return this, calling it with a positive delta will return
98 * a terminal size <i>delta</i> number of columns wider and for negative numbers shorter.
99 * @param delta Column offset
100 * @return New terminal size based off this one but with an applied transformation
101 */
102 public TerminalSize withRelativeColumns(int delta) {
103 if(delta == 0) {
104 return this;
105 }
106 return withColumns(columns + delta);
107 }
108
109 /**
110 * Creates a new TerminalSize object representing a size with the same number of columns, but with a row size offset by a
111 * supplied value. Calling this method with delta 0 will return this, calling it with a positive delta will return
112 * a terminal size <i>delta</i> number of rows longer and for negative numbers shorter.
113 * @param delta Row offset
114 * @return New terminal size based off this one but with an applied transformation
115 */
116 public TerminalSize withRelativeRows(int delta) {
117 if(delta == 0) {
118 return this;
119 }
120 return withRows(rows + delta);
121 }
122
123 /**
124 * Creates a new TerminalSize object representing a size based on this object's size but with a delta applied.
125 * This is the same as calling
126 * <code>withRelativeColumns(delta.getColumns()).withRelativeRows(delta.getRows())</code>
127 * @param delta Column and row offset
128 * @return New terminal size based off this one but with an applied resize
129 */
130 public TerminalSize withRelative(TerminalSize delta) {
131 return withRelative(delta.getColumns(), delta.getRows());
132 }
133
134 /**
135 * Creates a new TerminalSize object representing a size based on this object's size but with a delta applied.
136 * This is the same as calling
137 * <code>withRelativeColumns(deltaColumns).withRelativeRows(deltaRows)</code>
138 * @param deltaColumns How many extra columns the new TerminalSize will have (negative values are allowed)
139 * @param deltaRows How many extra rows the new TerminalSize will have (negative values are allowed)
140 * @return New terminal size based off this one but with an applied resize
141 */
142 public TerminalSize withRelative(int deltaColumns, int deltaRows) {
143 return withRelativeRows(deltaRows).withRelativeColumns(deltaColumns);
144 }
145
146 /**
147 * Takes a different TerminalSize and returns a new TerminalSize that has the largest dimensions of the two,
148 * measured separately. So calling 3x5 on a 5x3 will return 5x5.
149 * @param other Other TerminalSize to compare with
150 * @return TerminalSize that combines the maximum width between the two and the maximum height
151 */
152 public TerminalSize max(TerminalSize other) {
153 return withColumns(Math.max(columns, other.columns))
154 .withRows(Math.max(rows, other.rows));
155 }
156
157 /**
158 * Takes a different TerminalSize and returns a new TerminalSize that has the smallest dimensions of the two,
159 * measured separately. So calling 3x5 on a 5x3 will return 3x3.
160 * @param other Other TerminalSize to compare with
161 * @return TerminalSize that combines the minimum width between the two and the minimum height
162 */
163 public TerminalSize min(TerminalSize other) {
164 return withColumns(Math.min(columns, other.columns))
165 .withRows(Math.min(rows, other.rows));
166 }
167
168 /**
169 * Returns itself if it is equal to the supplied size, otherwise the supplied size. You can use this if you have a
170 * size field which is frequently recalculated but often resolves to the same size; it will keep the same object
171 * in memory instead of swapping it out every cycle.
172 * @param size Size you want to return
173 * @return Itself if this size equals the size passed in, otherwise the size passed in
174 */
175 public TerminalSize with(TerminalSize size) {
176 if(equals(size)) {
177 return this;
178 }
179 return size;
180 }
181
182 @Override
183 public String toString() {
184 return "{" + columns + "x" + rows + "}";
185 }
186
187 @Override
188 public boolean equals(Object obj) {
189 if(this == obj) {
190 return true;
191 }
192 if (!(obj instanceof TerminalSize)) {
193 return false;
194 }
195
196 TerminalSize other = (TerminalSize) obj;
197 return columns == other.columns
198 && rows == other.rows;
199 }
200
201 @Override
202 public int hashCode() {
203 int hash = 5;
204 hash = 53 * hash + this.columns;
205 hash = 53 * hash + this.rows;
206 return hash;
207 }
208 }