2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2019 Kevin Lamonte
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
31 import java
.awt
.Color
;
32 import java
.awt
.image
.BufferedImage
;
35 * This class represents a single text cell or bit of image on the screen.
37 public final class Cell
extends CellAttributes
{
39 // ------------------------------------------------------------------------
40 // Constants --------------------------------------------------------------
41 // ------------------------------------------------------------------------
44 * The special "this cell is unset" (null) value. This is the Unicode
45 * "not a character" value.
47 private static final char UNSET_VALUE
= (char) 65535;
49 // ------------------------------------------------------------------------
50 // Variables --------------------------------------------------------------
51 // ------------------------------------------------------------------------
54 * The character at this cell.
59 * The image at this cell.
61 private BufferedImage image
= null;
64 * The image at this cell, inverted.
66 private BufferedImage invertedImage
= null;
69 * The background color used for the area the image portion might not
72 private Color background
= null;
75 * hashCode() needs to call image.hashCode(), which can get quite
78 private int imageHashCode
= 0;
81 * hashCode() needs to call background.hashCode(), which can get quite
84 private int backgroundHashCode
= 0;
86 // ------------------------------------------------------------------------
87 // Constructors -----------------------------------------------------------
88 // ------------------------------------------------------------------------
91 * Public constructor sets default values of the cell to blank.
101 * Public constructor sets the character. Attributes are the same as
104 * @param ch character to set to
107 public Cell(final char ch
) {
112 // ------------------------------------------------------------------------
113 // Cell -------------------------------------------------------------------
114 // ------------------------------------------------------------------------
118 * Set the image data for this cell.
120 * @param image the image for this cell
122 public void setImage(final BufferedImage image
) {
124 imageHashCode
= image
.hashCode();
128 * Get the image data for this cell.
130 * @return the image for this cell
132 public BufferedImage
getImage() {
133 if (invertedImage
!= null) {
134 return invertedImage
;
140 * Get the bitmap image background color for this cell.
142 * @return the bitmap image background color
144 public Color
getBackground() {
149 * If true, this cell has image data.
151 * @return true if this cell is an image rather than a character with
154 public boolean isImage() {
162 * Restore the image in this cell to its normal version, if it has one.
164 public void restoreImage() {
165 invertedImage
= null;
169 * If true, this cell has image data, and that data is inverted.
171 * @return true if this cell is an image rather than a character with
172 * attributes, and the data is inverted
174 public boolean isInvertedImage() {
175 if ((image
!= null) && (invertedImage
!= null)) {
182 * Invert the image in this cell, if it has one.
184 public void invertImage() {
188 if (invertedImage
== null) {
189 invertedImage
= new BufferedImage(image
.getWidth(),
190 image
.getHeight(), BufferedImage
.TYPE_INT_ARGB
);
192 int [] rgbArray
= image
.getRGB(0, 0,
193 image
.getWidth(), image
.getHeight(), null, 0, image
.getWidth());
195 for (int i
= 0; i
< rgbArray
.length
; i
++) {
196 // Set the colors to fully inverted.
197 if (rgbArray
[i
] != 0x00FFFFFF) {
198 rgbArray
[i
] ^
= 0x00FFFFFF;
200 // Also set alpha to non-transparent.
201 rgbArray
[i
] |= 0xFF000000;
203 invertedImage
.setRGB(0, 0, image
.getWidth(), image
.getHeight(),
204 rgbArray
, 0, image
.getWidth());
209 * Getter for cell character.
211 * @return cell character
213 public char getChar() {
218 * Setter for cell character.
220 * @param ch new cell character
222 public void setChar(final char ch
) {
227 * Reset this cell to a blank.
230 public void reset() {
235 invertedImage
= null;
236 background
= Color
.BLACK
;
237 backgroundHashCode
= 0;
241 * UNset this cell. It will not be equal to any other cell until it has
242 * been assigned attributes and a character.
244 public void unset() {
249 invertedImage
= null;
250 background
= Color
.BLACK
;
251 backgroundHashCode
= 0;
255 * Check to see if this cell has default attributes: white foreground,
256 * black background, no bold/blink/reverse/underline/protect, and a
257 * character value of ' ' (space).
259 * @return true if this cell has default attributes.
261 public boolean isBlank() {
262 if ((ch
== UNSET_VALUE
) || (image
!= null)) {
265 if ((getForeColor().equals(Color
.WHITE
))
266 && (getBackColor().equals(Color
.BLACK
))
283 * Comparison check. All fields must match to return true.
285 * @param rhs another Cell instance
286 * @return true if all fields are equal
289 public boolean equals(final Object rhs
) {
290 if (!(rhs
instanceof Cell
)) {
294 Cell that
= (Cell
) rhs
;
296 // Unsetted cells can never be equal.
297 if ((ch
== UNSET_VALUE
) || (that
.ch
== UNSET_VALUE
)) {
301 // If this or rhs has an image and the other doesn't, these are not
303 if ((image
!= null) && (that
.image
== null)) {
306 if ((image
== null) && (that
.image
!= null)) {
309 // If this and rhs have images, both must match.
310 if ((image
!= null) && (that
.image
!= null)) {
311 if ((invertedImage
== null) && (that
.invertedImage
!= null)) {
314 if ((invertedImage
!= null) && (that
.invertedImage
== null)) {
317 // Either both objects have their image inverted, or neither do.
318 // Now if the images are identical the cells are the same
320 if (image
.equals(that
.image
)
321 && (background
.equals(that
.background
))
329 // Normal case: character and attributes must match.
331 return super.equals(rhs
);
337 * Hashcode uses all fields in equals().
342 public int hashCode() {
346 hash
= (B
* hash
) + super.hashCode();
347 hash
= (B
* hash
) + (int)ch
;
350 hash = (B * hash) + image.hashCode();
351 hash = (B * hash) + background.hashCode();
353 hash
= (B
* hash
) + imageHashCode
;
354 hash
= (B
* hash
) + backgroundHashCode
;
356 if (invertedImage
!= null) {
357 hash
= (B
* hash
) + invertedImage
.hashCode();
363 * Set my field values to that's field.
365 * @param rhs an instance of either Cell or CellAttributes
368 public void setTo(final Object rhs
) {
369 // Let this throw a ClassCastException
370 CellAttributes thatAttr
= (CellAttributes
) rhs
;
372 this.imageHashCode
= 0;
373 this.backgroundHashCode
= 0;
374 super.setTo(thatAttr
);
376 if (rhs
instanceof Cell
) {
377 Cell that
= (Cell
) rhs
;
379 this.image
= that
.image
;
380 this.invertedImage
= that
.invertedImage
;
381 this.background
= that
.background
;
382 this.imageHashCode
= that
.imageHashCode
;
383 this.backgroundHashCode
= that
.backgroundHashCode
;
388 * Set my field attr values to that's field.
390 * @param that a CellAttributes instance
392 public void setAttr(final CellAttributes that
) {
398 * Make human-readable description of this Cell.
400 * @return displayable String
403 public String
toString() {
404 return String
.format("fore: %s back: %s bold: %s blink: %s ch %c",
405 getForeColor(), getBackColor(), isBold(), isBlink(), ch
);