2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
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.
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.
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/>.
17 * Copyright (C) 2010-2015 Martin
19 package com
.googlecode
.lanterna
;
21 import java
.util
.Arrays
;
22 import java
.util
.Collection
;
23 import java
.util
.EnumSet
;
26 * Represents a single character with additional metadata such as colors and modifiers. This class is immutable and
27 * cannot be modified after creation.
30 public class TextCharacter
{
31 private static EnumSet
<SGR
> toEnumSet(SGR
... modifiers
) {
32 if(modifiers
.length
== 0) {
33 return EnumSet
.noneOf(SGR
.class);
36 return EnumSet
.copyOf(Arrays
.asList(modifiers
));
40 public static final TextCharacter DEFAULT_CHARACTER
= new TextCharacter(' ', TextColor
.ANSI
.DEFAULT
, TextColor
.ANSI
.DEFAULT
);
42 private final char character
;
43 private final TextColor foregroundColor
;
44 private final TextColor backgroundColor
;
45 private final EnumSet
<SGR
> modifiers
; //This isn't immutable, but we should treat it as such and not expose it!
48 * Creates a {@code ScreenCharacter} based on a supplied character, with default colors and no extra modifiers.
49 * @param character Physical character to use
51 public TextCharacter(char character
) {
52 this(character
, TextColor
.ANSI
.DEFAULT
, TextColor
.ANSI
.DEFAULT
);
56 * Copies another {@code ScreenCharacter}
57 * @param character screenCharacter to copy from
59 public TextCharacter(TextCharacter character
) {
60 this(character
.getCharacter(),
61 character
.getForegroundColor(),
62 character
.getBackgroundColor(),
63 character
.getModifiers().toArray(new SGR
[character
.getModifiers().size()]));
67 * Creates a new {@code ScreenCharacter} based on a physical character, color information and optional modifiers.
68 * @param character Physical character to refer to
69 * @param foregroundColor Foreground color the character has
70 * @param backgroundColor Background color the character has
71 * @param styles Optional list of modifiers to apply when drawing the character
73 @SuppressWarnings("WeakerAccess")
76 TextColor foregroundColor
,
77 TextColor backgroundColor
,
87 * Creates a new {@code ScreenCharacter} based on a physical character, color information and a set of modifiers.
88 * @param character Physical character to refer to
89 * @param foregroundColor Foreground color the character has
90 * @param backgroundColor Background color the character has
91 * @param modifiers Set of modifiers to apply when drawing the character
95 TextColor foregroundColor
,
96 TextColor backgroundColor
,
97 EnumSet
<SGR
> modifiers
) {
99 if(foregroundColor
== null) {
100 foregroundColor
= TextColor
.ANSI
.DEFAULT
;
102 if(backgroundColor
== null) {
103 backgroundColor
= TextColor
.ANSI
.DEFAULT
;
106 this.character
= character
;
107 this.foregroundColor
= foregroundColor
;
108 this.backgroundColor
= backgroundColor
;
109 this.modifiers
= EnumSet
.copyOf(modifiers
);
113 * The actual character this TextCharacter represents
114 * @return character of the TextCharacter
116 public char getCharacter() {
121 * Foreground color specified for this TextCharacter
122 * @return Foreground color of this TextCharacter
124 public TextColor
getForegroundColor() {
125 return foregroundColor
;
129 * Background color specified for this TextCharacter
130 * @return Background color of this TextCharacter
132 public TextColor
getBackgroundColor() {
133 return backgroundColor
;
137 * Returns a set of all active modifiers on this TextCharacter
138 * @return Set of active SGR codes
140 public EnumSet
<SGR
> getModifiers() {
141 return EnumSet
.copyOf(modifiers
);
145 * Returns true if this TextCharacter has the bold modifier active
146 * @return {@code true} if this TextCharacter has the bold modifier active
148 public boolean isBold() {
149 return modifiers
.contains(SGR
.BOLD
);
153 * Returns true if this TextCharacter has the reverse modifier active
154 * @return {@code true} if this TextCharacter has the reverse modifier active
156 public boolean isReversed() {
157 return modifiers
.contains(SGR
.REVERSE
);
161 * Returns true if this TextCharacter has the underline modifier active
162 * @return {@code true} if this TextCharacter has the underline modifier active
164 public boolean isUnderlined() {
165 return modifiers
.contains(SGR
.UNDERLINE
);
169 * Returns true if this TextCharacter has the blink modifier active
170 * @return {@code true} if this TextCharacter has the blink modifier active
172 public boolean isBlinking() {
173 return modifiers
.contains(SGR
.BLINK
);
177 * Returns true if this TextCharacter has the bordered modifier active
178 * @return {@code true} if this TextCharacter has the bordered modifier active
180 public boolean isBordered() {
181 return modifiers
.contains(SGR
.BORDERED
);
185 * Returns true if this TextCharacter has the crossed-out modifier active
186 * @return {@code true} if this TextCharacter has the crossed-out modifier active
188 public boolean isCrossedOut() {
189 return modifiers
.contains(SGR
.CROSSED_OUT
);
193 * Returns a new TextCharacter with the same colors and modifiers but a different underlying character
194 * @param character Character the copy should have
195 * @return Copy of this TextCharacter with different underlying character
197 @SuppressWarnings("SameParameterValue")
198 public TextCharacter
withCharacter(char character
) {
199 if(this.character
== character
) {
202 return new TextCharacter(character
, foregroundColor
, backgroundColor
, modifiers
);
206 * Returns a copy of this TextCharacter with a specified foreground color
207 * @param foregroundColor Foreground color the copy should have
208 * @return Copy of the TextCharacter with a different foreground color
210 public TextCharacter
withForegroundColor(TextColor foregroundColor
) {
211 if(this.foregroundColor
== foregroundColor
|| this.foregroundColor
.equals(foregroundColor
)) {
214 return new TextCharacter(character
, foregroundColor
, backgroundColor
, modifiers
);
218 * Returns a copy of this TextCharacter with a specified background color
219 * @param backgroundColor Background color the copy should have
220 * @return Copy of the TextCharacter with a different background color
222 public TextCharacter
withBackgroundColor(TextColor backgroundColor
) {
223 if(this.backgroundColor
== backgroundColor
|| this.backgroundColor
.equals(backgroundColor
)) {
226 return new TextCharacter(character
, foregroundColor
, backgroundColor
, modifiers
);
230 * Returns a copy of this TextCharacter with specified list of SGR modifiers. None of the currently active SGR codes
231 * will be carried over to the copy, only those in the passed in value.
232 * @param modifiers SGR modifiers the copy should have
233 * @return Copy of the TextCharacter with a different set of SGR modifiers
235 public TextCharacter
withModifiers(Collection
<SGR
> modifiers
) {
236 EnumSet
<SGR
> newSet
= EnumSet
.copyOf(modifiers
);
237 if(modifiers
.equals(newSet
)) {
240 return new TextCharacter(character
, foregroundColor
, backgroundColor
, newSet
);
244 * Returns a copy of this TextCharacter with an additional SGR modifier. All of the currently active SGR codes
245 * will be carried over to the copy, in addition to the one specified.
246 * @param modifier SGR modifiers the copy should have in additional to all currently present
247 * @return Copy of the TextCharacter with a new SGR modifier
249 public TextCharacter
withModifier(SGR modifier
) {
250 if(modifiers
.contains(modifier
)) {
253 EnumSet
<SGR
> newSet
= EnumSet
.copyOf(this.modifiers
);
254 newSet
.add(modifier
);
255 return new TextCharacter(character
, foregroundColor
, backgroundColor
, newSet
);
259 * Returns a copy of this TextCharacter with an SGR modifier removed. All of the currently active SGR codes
260 * will be carried over to the copy, except for the one specified. If the current TextCharacter doesn't have the
261 * SGR specified, it will return itself.
262 * @param modifier SGR modifiers the copy should not have
263 * @return Copy of the TextCharacter without the SGR modifier
265 public TextCharacter
withoutModifier(SGR modifier
) {
266 if(!modifiers
.contains(modifier
)) {
269 EnumSet
<SGR
> newSet
= EnumSet
.copyOf(this.modifiers
);
270 newSet
.remove(modifier
);
271 return new TextCharacter(character
, foregroundColor
, backgroundColor
, newSet
);
274 @SuppressWarnings("SimplifiableIfStatement")
276 public boolean equals(Object obj
) {
280 if(getClass() != obj
.getClass()) {
283 final TextCharacter other
= (TextCharacter
) obj
;
284 if(this.character
!= other
.character
) {
287 if(this.foregroundColor
!= other
.foregroundColor
&& (this.foregroundColor
== null || !this.foregroundColor
.equals(other
.foregroundColor
))) {
290 if(this.backgroundColor
!= other
.backgroundColor
&& (this.backgroundColor
== null || !this.backgroundColor
.equals(other
.backgroundColor
))) {
293 return !(this.modifiers
!= other
.modifiers
&& (this.modifiers
== null || !this.modifiers
.equals(other
.modifiers
)));
297 public int hashCode() {
299 hash
= 37 * hash
+ this.character
;
300 hash
= 37 * hash
+ (this.foregroundColor
!= null ?
this.foregroundColor
.hashCode() : 0);
301 hash
= 37 * hash
+ (this.backgroundColor
!= null ?
this.backgroundColor
.hashCode() : 0);
302 hash
= 37 * hash
+ (this.modifiers
!= null ?
this.modifiers
.hashCode() : 0);
307 public String
toString() {
308 return "TextCharacter{" + "character=" + character
+ ", foregroundColor=" + foregroundColor
+ ", backgroundColor=" + backgroundColor
+ ", modifiers=" + modifiers
+ '}';