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
.graphics
;
21 import com
.googlecode
.lanterna
.*;
22 import com
.googlecode
.lanterna
.screen
.TabBehaviour
;
24 import java
.util
.Arrays
;
25 import java
.util
.Collection
;
26 import java
.util
.EnumSet
;
29 * This class hold the default logic for drawing the basic text graphic as exposed by TextGraphic. All implementations
30 * rely on a setCharacter method being implemented in subclasses.
33 public abstract class AbstractTextGraphics
implements TextGraphics
{
34 protected TextColor foregroundColor
;
35 protected TextColor backgroundColor
;
36 protected TabBehaviour tabBehaviour
;
37 protected final EnumSet
<SGR
> activeModifiers
;
38 private final ShapeRenderer shapeRenderer
;
40 protected AbstractTextGraphics() {
41 this.activeModifiers
= EnumSet
.noneOf(SGR
.class);
42 this.tabBehaviour
= TabBehaviour
.ALIGN_TO_COLUMN_4
;
43 this.foregroundColor
= TextColor
.ANSI
.DEFAULT
;
44 this.backgroundColor
= TextColor
.ANSI
.DEFAULT
;
45 this.shapeRenderer
= new DefaultShapeRenderer(new DefaultShapeRenderer
.Callback() {
47 public void onPoint(int column
, int row
, TextCharacter character
) {
48 setCharacter(column
, row
, character
);
54 public TextColor
getBackgroundColor() {
55 return backgroundColor
;
59 public TextGraphics
setBackgroundColor(final TextColor backgroundColor
) {
60 this.backgroundColor
= backgroundColor
;
65 public TextColor
getForegroundColor() {
66 return foregroundColor
;
70 public TextGraphics
setForegroundColor(final TextColor foregroundColor
) {
71 this.foregroundColor
= foregroundColor
;
76 public TextGraphics
enableModifiers(SGR
... modifiers
) {
77 enableModifiers(Arrays
.asList(modifiers
));
81 private void enableModifiers(Collection
<SGR
> modifiers
) {
82 this.activeModifiers
.addAll(modifiers
);
86 public TextGraphics
disableModifiers(SGR
... modifiers
) {
87 disableModifiers(Arrays
.asList(modifiers
));
91 private void disableModifiers(Collection
<SGR
> modifiers
) {
92 this.activeModifiers
.removeAll(modifiers
);
96 public synchronized TextGraphics
setModifiers(EnumSet
<SGR
> modifiers
) {
97 activeModifiers
.clear();
98 activeModifiers
.addAll(modifiers
);
103 public TextGraphics
clearModifiers() {
104 this.activeModifiers
.clear();
109 public EnumSet
<SGR
> getActiveModifiers() {
110 return activeModifiers
;
114 public TabBehaviour
getTabBehaviour() {
119 public TextGraphics
setTabBehaviour(TabBehaviour tabBehaviour
) {
120 if(tabBehaviour
!= null) {
121 this.tabBehaviour
= tabBehaviour
;
127 public TextGraphics
fill(char c
) {
128 fillRectangle(TerminalPosition
.TOP_LEFT_CORNER
, getSize(), c
);
133 public TextGraphics
setCharacter(int column
, int row
, char character
) {
134 return setCharacter(column
, row
, newTextCharacter(character
));
138 public TextGraphics
setCharacter(TerminalPosition position
, TextCharacter textCharacter
) {
139 setCharacter(position
.getColumn(), position
.getRow(), textCharacter
);
144 public TextGraphics
setCharacter(TerminalPosition position
, char character
) {
145 return setCharacter(position
.getColumn(), position
.getRow(), character
);
149 public TextGraphics
drawLine(TerminalPosition fromPosition
, TerminalPosition toPoint
, char character
) {
150 return drawLine(fromPosition
, toPoint
, newTextCharacter(character
));
154 public TextGraphics
drawLine(TerminalPosition fromPoint
, TerminalPosition toPoint
, TextCharacter character
) {
155 shapeRenderer
.drawLine(fromPoint
, toPoint
, character
);
160 public TextGraphics
drawLine(int fromX
, int fromY
, int toX
, int toY
, char character
) {
161 return drawLine(fromX
, fromY
, toX
, toY
, newTextCharacter(character
));
165 public TextGraphics
drawLine(int fromX
, int fromY
, int toX
, int toY
, TextCharacter character
) {
166 return drawLine(new TerminalPosition(fromX
, fromY
), new TerminalPosition(toX
, toY
), character
);
170 public TextGraphics
drawTriangle(TerminalPosition p1
, TerminalPosition p2
, TerminalPosition p3
, char character
) {
171 return drawTriangle(p1
, p2
, p3
, newTextCharacter(character
));
175 public TextGraphics
drawTriangle(TerminalPosition p1
, TerminalPosition p2
, TerminalPosition p3
, TextCharacter character
) {
176 shapeRenderer
.drawTriangle(p1
, p2
, p3
, character
);
181 public TextGraphics
fillTriangle(TerminalPosition p1
, TerminalPosition p2
, TerminalPosition p3
, char character
) {
182 return fillTriangle(p1
, p2
, p3
, newTextCharacter(character
));
186 public TextGraphics
fillTriangle(TerminalPosition p1
, TerminalPosition p2
, TerminalPosition p3
, TextCharacter character
) {
187 shapeRenderer
.fillTriangle(p1
, p2
, p3
, character
);
192 public TextGraphics
drawRectangle(TerminalPosition topLeft
, TerminalSize size
, char character
) {
193 return drawRectangle(topLeft
, size
, newTextCharacter(character
));
197 public TextGraphics
drawRectangle(TerminalPosition topLeft
, TerminalSize size
, TextCharacter character
) {
198 shapeRenderer
.drawRectangle(topLeft
, size
, character
);
203 public TextGraphics
fillRectangle(TerminalPosition topLeft
, TerminalSize size
, char character
) {
204 return fillRectangle(topLeft
, size
, newTextCharacter(character
));
208 public TextGraphics
fillRectangle(TerminalPosition topLeft
, TerminalSize size
, TextCharacter character
) {
209 shapeRenderer
.fillRectangle(topLeft
, size
, character
);
214 public TextGraphics
drawImage(TerminalPosition topLeft
, TextImage image
) {
215 return drawImage(topLeft
, image
, TerminalPosition
.TOP_LEFT_CORNER
, image
.getSize());
219 public TextGraphics
drawImage(
220 TerminalPosition topLeft
,
222 TerminalPosition sourceImageTopLeft
,
223 TerminalSize sourceImageSize
) {
225 // If the source image position is negative, offset the whole image
226 if(sourceImageTopLeft
.getColumn() < 0) {
227 topLeft
= topLeft
.withRelativeColumn(-sourceImageTopLeft
.getColumn());
228 sourceImageSize
= sourceImageSize
.withRelativeColumns(sourceImageTopLeft
.getColumn());
229 sourceImageTopLeft
= sourceImageTopLeft
.withColumn(0);
231 if(sourceImageTopLeft
.getRow() < 0) {
232 topLeft
= topLeft
.withRelativeRow(-sourceImageTopLeft
.getRow());
233 sourceImageSize
= sourceImageSize
.withRelativeRows(sourceImageTopLeft
.getRow());
234 sourceImageTopLeft
= sourceImageTopLeft
.withRow(0);
237 // cropping specified image-subrectangle to the image itself:
238 int fromRow
= Math
.max(sourceImageTopLeft
.getRow(), 0);
239 int untilRow
= Math
.min(sourceImageTopLeft
.getRow() + sourceImageSize
.getRows(), image
.getSize().getRows());
240 int fromColumn
= Math
.max(sourceImageTopLeft
.getColumn(), 0);
241 int untilColumn
= Math
.min(sourceImageTopLeft
.getColumn() + sourceImageSize
.getColumns(), image
.getSize().getColumns());
243 // difference between position in image and position on target:
244 int diffRow
= topLeft
.getRow() - sourceImageTopLeft
.getRow();
245 int diffColumn
= topLeft
.getColumn() - sourceImageTopLeft
.getColumn();
247 // top/left-crop at target(TextGraphics) rectangle: (only matters, if topLeft has a negative coordinate)
248 fromRow
= Math
.max(fromRow
, -diffRow
);
249 fromColumn
= Math
.max(fromColumn
, -diffColumn
);
251 // bot/right-crop at target(TextGraphics) rectangle: (only matters, if topLeft has a negative coordinate)
252 untilRow
= Math
.min(untilRow
, getSize().getRows() - diffRow
);
253 untilColumn
= Math
.min(untilColumn
, getSize().getColumns() - diffColumn
);
255 if (fromRow
>= untilRow
|| fromColumn
>= untilColumn
) {
258 for (int row
= fromRow
; row
< untilRow
; row
++) {
259 for (int column
= fromColumn
; column
< untilColumn
; column
++) {
260 setCharacter(column
+ diffColumn
, row
+ diffRow
, image
.getCharacterAt(column
, row
));
267 public TextGraphics
putString(int column
, int row
, String string
) {
268 if(string
.contains("\n")) {
269 string
= string
.substring(0, string
.indexOf("\n"));
271 if(string
.contains("\r")) {
272 string
= string
.substring(0, string
.indexOf("\r"));
274 string
= tabBehaviour
.replaceTabs(string
, column
);
276 for(int i
= 0; i
< string
.length(); i
++) {
277 char character
= string
.charAt(i
);
285 activeModifiers
.clone()));
287 if(TerminalTextUtils
.isCharCJK(character
)) {
288 //CJK characters are twice the normal characters in width, so next character position is two columns forward
292 //For "normal" characters we advance to the next column
300 public TextGraphics
putString(TerminalPosition position
, String string
) {
301 putString(position
.getColumn(), position
.getRow(), string
);
306 public TextGraphics
putString(int column
, int row
, String string
, SGR extraModifier
, SGR
... optionalExtraModifiers
) {clearModifiers();
307 return putString(column
, row
, string
, EnumSet
.of(extraModifier
, optionalExtraModifiers
));
311 public TextGraphics
putString(int column
, int row
, String string
, Collection
<SGR
> extraModifiers
) {
312 extraModifiers
.removeAll(activeModifiers
);
313 enableModifiers(extraModifiers
);
314 putString(column
, row
, string
);
315 disableModifiers(extraModifiers
);
320 public TextGraphics
putString(TerminalPosition position
, String string
, SGR extraModifier
, SGR
... optionalExtraModifiers
) {
321 putString(position
.getColumn(), position
.getRow(), string
, extraModifier
, optionalExtraModifiers
);
326 public TextCharacter
getCharacter(TerminalPosition position
) {
327 return getCharacter(position
.getColumn(), position
.getRow());
331 public TextGraphics
newTextGraphics(TerminalPosition topLeftCorner
, TerminalSize size
) throws IllegalArgumentException
{
332 TerminalSize writableArea
= getSize();
333 if(topLeftCorner
.getColumn() + size
.getColumns() <= 0 ||
334 topLeftCorner
.getColumn() >= writableArea
.getColumns() ||
335 topLeftCorner
.getRow() + size
.getRows() <= 0 ||
336 topLeftCorner
.getRow() >= writableArea
.getRows()) {
337 //The area selected is completely outside of this TextGraphics, so we can return a "null" object that doesn't
338 //do anything because it is impossible to change anything anyway
339 return new NullTextGraphics(size
);
341 return new SubTextGraphics(this, topLeftCorner
, size
);
344 private TextCharacter
newTextCharacter(char character
) {
345 return new TextCharacter(character
, foregroundColor
, backgroundColor
, activeModifiers
);