/*
 * 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-2020 Martin Berglund
 */
package com.googlecode.lanterna;

import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;

Represents a single character with additional metadata such as colors and modifiers. This class is immutable and cannot be modified after creation.
Author:Martin
/** * Represents a single character with additional metadata such as colors and modifiers. This class is immutable and * cannot be modified after creation. * @author Martin */
public class TextCharacter { private static EnumSet<SGR> toEnumSet(SGR... modifiers) { if(modifiers.length == 0) { return EnumSet.noneOf(SGR.class); } else { return EnumSet.copyOf(Arrays.asList(modifiers)); } } public static final TextCharacter DEFAULT_CHARACTER = new TextCharacter(' ', TextColor.ANSI.DEFAULT, TextColor.ANSI.DEFAULT); private final char character; private final TextColor foregroundColor; private final TextColor backgroundColor; private final EnumSet<SGR> modifiers; //This isn't immutable, but we should treat it as such and not expose it!
Creates a ScreenCharacter based on a supplied character, with default colors and no extra modifiers.
Params:
  • character – Physical character to use
/** * Creates a {@code ScreenCharacter} based on a supplied character, with default colors and no extra modifiers. * @param character Physical character to use */
public TextCharacter(char character) { this(character, TextColor.ANSI.DEFAULT, TextColor.ANSI.DEFAULT); }
Copies another ScreenCharacter
Params:
  • character – screenCharacter to copy from
/** * Copies another {@code ScreenCharacter} * @param character screenCharacter to copy from */
public TextCharacter(TextCharacter character) { this(character.getCharacter(), character.getForegroundColor(), character.getBackgroundColor(), character.getModifiers().toArray(new SGR[character.getModifiers().size()])); }
Creates a new ScreenCharacter based on a physical character, color information and optional modifiers.
Params:
  • character – Physical character to refer to
  • foregroundColor – Foreground color the character has
  • backgroundColor – Background color the character has
  • styles – Optional list of modifiers to apply when drawing the character
/** * Creates a new {@code ScreenCharacter} based on a physical character, color information and optional modifiers. * @param character Physical character to refer to * @param foregroundColor Foreground color the character has * @param backgroundColor Background color the character has * @param styles Optional list of modifiers to apply when drawing the character */
@SuppressWarnings("WeakerAccess") public TextCharacter( char character, TextColor foregroundColor, TextColor backgroundColor, SGR... styles) { this(character, foregroundColor, backgroundColor, toEnumSet(styles)); }
Creates a new ScreenCharacter based on a physical character, color information and a set of modifiers.
Params:
  • character – Physical character to refer to
  • foregroundColor – Foreground color the character has
  • backgroundColor – Background color the character has
  • modifiers – Set of modifiers to apply when drawing the character
/** * Creates a new {@code ScreenCharacter} based on a physical character, color information and a set of modifiers. * @param character Physical character to refer to * @param foregroundColor Foreground color the character has * @param backgroundColor Background color the character has * @param modifiers Set of modifiers to apply when drawing the character */
public TextCharacter( char character, TextColor foregroundColor, TextColor backgroundColor, EnumSet<SGR> modifiers) { // Don't allow creating a TextCharacter containing a control character // For backward-compatibility, do allow tab for now // TODO: In lanterna 3.1, don't allow tab if(TerminalTextUtils.isControlCharacter(character) && character != '\t') { throw new IllegalArgumentException("Cannot create a TextCharacter from a control character (0x" + Integer.toHexString(character) + ")"); } if(foregroundColor == null) { foregroundColor = TextColor.ANSI.DEFAULT; } if(backgroundColor == null) { backgroundColor = TextColor.ANSI.DEFAULT; } this.character = character; this.foregroundColor = foregroundColor; this.backgroundColor = backgroundColor; this.modifiers = EnumSet.copyOf(modifiers); }
The actual character this TextCharacter represents
Returns:character of the TextCharacter
/** * The actual character this TextCharacter represents * @return character of the TextCharacter */
public char getCharacter() { return character; }
Foreground color specified for this TextCharacter
Returns:Foreground color of this TextCharacter
/** * Foreground color specified for this TextCharacter * @return Foreground color of this TextCharacter */
public TextColor getForegroundColor() { return foregroundColor; }
Background color specified for this TextCharacter
Returns:Background color of this TextCharacter
/** * Background color specified for this TextCharacter * @return Background color of this TextCharacter */
public TextColor getBackgroundColor() { return backgroundColor; }
Returns a set of all active modifiers on this TextCharacter
Returns:Set of active SGR codes
/** * Returns a set of all active modifiers on this TextCharacter * @return Set of active SGR codes */
public EnumSet<SGR> getModifiers() { return EnumSet.copyOf(modifiers); }
Returns true if this TextCharacter has the bold modifier active
Returns:true if this TextCharacter has the bold modifier active
/** * Returns true if this TextCharacter has the bold modifier active * @return {@code true} if this TextCharacter has the bold modifier active */
public boolean isBold() { return modifiers.contains(SGR.BOLD); }
Returns true if this TextCharacter has the reverse modifier active
Returns:true if this TextCharacter has the reverse modifier active
/** * Returns true if this TextCharacter has the reverse modifier active * @return {@code true} if this TextCharacter has the reverse modifier active */
public boolean isReversed() { return modifiers.contains(SGR.REVERSE); }
Returns true if this TextCharacter has the underline modifier active
Returns:true if this TextCharacter has the underline modifier active
/** * Returns true if this TextCharacter has the underline modifier active * @return {@code true} if this TextCharacter has the underline modifier active */
public boolean isUnderlined() { return modifiers.contains(SGR.UNDERLINE); }
Returns true if this TextCharacter has the blink modifier active
Returns:true if this TextCharacter has the blink modifier active
/** * Returns true if this TextCharacter has the blink modifier active * @return {@code true} if this TextCharacter has the blink modifier active */
public boolean isBlinking() { return modifiers.contains(SGR.BLINK); }
Returns true if this TextCharacter has the bordered modifier active
Returns:true if this TextCharacter has the bordered modifier active
/** * Returns true if this TextCharacter has the bordered modifier active * @return {@code true} if this TextCharacter has the bordered modifier active */
public boolean isBordered() { return modifiers.contains(SGR.BORDERED); }
Returns true if this TextCharacter has the crossed-out modifier active
Returns:true if this TextCharacter has the crossed-out modifier active
/** * Returns true if this TextCharacter has the crossed-out modifier active * @return {@code true} if this TextCharacter has the crossed-out modifier active */
public boolean isCrossedOut() { return modifiers.contains(SGR.CROSSED_OUT); }
Returns true if this TextCharacter has the italic modifier active
Returns:true if this TextCharacter has the italic modifier active
/** * Returns true if this TextCharacter has the italic modifier active * @return {@code true} if this TextCharacter has the italic modifier active */
public boolean isItalic() { return modifiers.contains(SGR.ITALIC); }
Returns a new TextCharacter with the same colors and modifiers but a different underlying character
Params:
  • character – Character the copy should have
Returns:Copy of this TextCharacter with different underlying character
/** * Returns a new TextCharacter with the same colors and modifiers but a different underlying character * @param character Character the copy should have * @return Copy of this TextCharacter with different underlying character */
@SuppressWarnings("SameParameterValue") public TextCharacter withCharacter(char character) { if(this.character == character) { return this; } return new TextCharacter(character, foregroundColor, backgroundColor, modifiers); }
Returns a copy of this TextCharacter with a specified foreground color
Params:
  • foregroundColor – Foreground color the copy should have
Returns:Copy of the TextCharacter with a different foreground color
/** * Returns a copy of this TextCharacter with a specified foreground color * @param foregroundColor Foreground color the copy should have * @return Copy of the TextCharacter with a different foreground color */
public TextCharacter withForegroundColor(TextColor foregroundColor) { if(this.foregroundColor == foregroundColor || this.foregroundColor.equals(foregroundColor)) { return this; } return new TextCharacter(character, foregroundColor, backgroundColor, modifiers); }
Returns a copy of this TextCharacter with a specified background color
Params:
  • backgroundColor – Background color the copy should have
Returns:Copy of the TextCharacter with a different background color
/** * Returns a copy of this TextCharacter with a specified background color * @param backgroundColor Background color the copy should have * @return Copy of the TextCharacter with a different background color */
public TextCharacter withBackgroundColor(TextColor backgroundColor) { if(this.backgroundColor == backgroundColor || this.backgroundColor.equals(backgroundColor)) { return this; } return new TextCharacter(character, foregroundColor, backgroundColor, modifiers); }
Returns a copy of this TextCharacter with specified list of SGR modifiers. None of the currently active SGR codes will be carried over to the copy, only those in the passed in value.
Params:
  • modifiers – SGR modifiers the copy should have
Returns:Copy of the TextCharacter with a different set of SGR modifiers
/** * Returns a copy of this TextCharacter with specified list of SGR modifiers. None of the currently active SGR codes * will be carried over to the copy, only those in the passed in value. * @param modifiers SGR modifiers the copy should have * @return Copy of the TextCharacter with a different set of SGR modifiers */
public TextCharacter withModifiers(Collection<SGR> modifiers) { EnumSet<SGR> newSet = EnumSet.copyOf(modifiers); if(modifiers.equals(newSet)) { return this; } return new TextCharacter(character, foregroundColor, backgroundColor, newSet); }
Returns a copy of this TextCharacter with an additional SGR modifier. All of the currently active SGR codes will be carried over to the copy, in addition to the one specified.
Params:
  • modifier – SGR modifiers the copy should have in additional to all currently present
Returns:Copy of the TextCharacter with a new SGR modifier
/** * Returns a copy of this TextCharacter with an additional SGR modifier. All of the currently active SGR codes * will be carried over to the copy, in addition to the one specified. * @param modifier SGR modifiers the copy should have in additional to all currently present * @return Copy of the TextCharacter with a new SGR modifier */
public TextCharacter withModifier(SGR modifier) { if(modifiers.contains(modifier)) { return this; } EnumSet<SGR> newSet = EnumSet.copyOf(this.modifiers); newSet.add(modifier); return new TextCharacter(character, foregroundColor, backgroundColor, newSet); }
Returns a copy of this TextCharacter with an SGR modifier removed. All of the currently active SGR codes will be carried over to the copy, except for the one specified. If the current TextCharacter doesn't have the SGR specified, it will return itself.
Params:
  • modifier – SGR modifiers the copy should not have
Returns:Copy of the TextCharacter without the SGR modifier
/** * Returns a copy of this TextCharacter with an SGR modifier removed. All of the currently active SGR codes * will be carried over to the copy, except for the one specified. If the current TextCharacter doesn't have the * SGR specified, it will return itself. * @param modifier SGR modifiers the copy should not have * @return Copy of the TextCharacter without the SGR modifier */
public TextCharacter withoutModifier(SGR modifier) { if(!modifiers.contains(modifier)) { return this; } EnumSet<SGR> newSet = EnumSet.copyOf(this.modifiers); newSet.remove(modifier); return new TextCharacter(character, foregroundColor, backgroundColor, newSet); } public boolean isDoubleWidth() { return TerminalTextUtils.isCharDoubleWidth(character); } @SuppressWarnings("SimplifiableIfStatement") @Override public boolean equals(Object obj) { if(obj == null) { return false; } if(getClass() != obj.getClass()) { return false; } final TextCharacter other = (TextCharacter) obj; if(this.character != other.character) { return false; } if(this.foregroundColor != other.foregroundColor && (this.foregroundColor == null || !this.foregroundColor.equals(other.foregroundColor))) { return false; } if(this.backgroundColor != other.backgroundColor && (this.backgroundColor == null || !this.backgroundColor.equals(other.backgroundColor))) { return false; } return !(this.modifiers != other.modifiers && (this.modifiers == null || !this.modifiers.equals(other.modifiers))); } @Override public int hashCode() { int hash = 7; hash = 37 * hash + this.character; hash = 37 * hash + (this.foregroundColor != null ? this.foregroundColor.hashCode() : 0); hash = 37 * hash + (this.backgroundColor != null ? this.backgroundColor.hashCode() : 0); hash = 37 * hash + (this.modifiers != null ? this.modifiers.hashCode() : 0); return hash; } @Override public String toString() { return "TextCharacter{" + "character=" + character + ", foregroundColor=" + foregroundColor + ", backgroundColor=" + backgroundColor + ", modifiers=" + modifiers + '}'; } }