Change build scripts
[jvcard.git] / src / com / googlecode / lanterna / graphics / AbstractTextGraphics.java
CommitLineData
a3b510ab
NR
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 */
19package com.googlecode.lanterna.graphics;
20
21import com.googlecode.lanterna.*;
22import com.googlecode.lanterna.screen.TabBehaviour;
23
24import java.util.Arrays;
25import java.util.Collection;
26import java.util.EnumSet;
27
28/**
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.
31 * @author Martin
32 */
33public 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;
39
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() {
46 @Override
47 public void onPoint(int column, int row, TextCharacter character) {
48 setCharacter(column, row, character);
49 }
50 });
51 }
52
53 @Override
54 public TextColor getBackgroundColor() {
55 return backgroundColor;
56 }
57
58 @Override
59 public TextGraphics setBackgroundColor(final TextColor backgroundColor) {
60 this.backgroundColor = backgroundColor;
61 return this;
62 }
63
64 @Override
65 public TextColor getForegroundColor() {
66 return foregroundColor;
67 }
68
69 @Override
70 public TextGraphics setForegroundColor(final TextColor foregroundColor) {
71 this.foregroundColor = foregroundColor;
72 return this;
73 }
74
75 @Override
76 public TextGraphics enableModifiers(SGR... modifiers) {
77 enableModifiers(Arrays.asList(modifiers));
78 return this;
79 }
80
81 private void enableModifiers(Collection<SGR> modifiers) {
82 this.activeModifiers.addAll(modifiers);
83 }
84
85 @Override
86 public TextGraphics disableModifiers(SGR... modifiers) {
87 disableModifiers(Arrays.asList(modifiers));
88 return this;
89 }
90
91 private void disableModifiers(Collection<SGR> modifiers) {
92 this.activeModifiers.removeAll(modifiers);
93 }
94
95 @Override
96 public synchronized TextGraphics setModifiers(EnumSet<SGR> modifiers) {
97 activeModifiers.clear();
98 activeModifiers.addAll(modifiers);
99 return this;
100 }
101
102 @Override
103 public TextGraphics clearModifiers() {
104 this.activeModifiers.clear();
105 return this;
106 }
107
108 @Override
109 public EnumSet<SGR> getActiveModifiers() {
110 return activeModifiers;
111 }
112
113 @Override
114 public TabBehaviour getTabBehaviour() {
115 return tabBehaviour;
116 }
117
118 @Override
119 public TextGraphics setTabBehaviour(TabBehaviour tabBehaviour) {
120 if(tabBehaviour != null) {
121 this.tabBehaviour = tabBehaviour;
122 }
123 return this;
124 }
125
126 @Override
127 public TextGraphics fill(char c) {
128 fillRectangle(TerminalPosition.TOP_LEFT_CORNER, getSize(), c);
129 return this;
130 }
131
132 @Override
133 public TextGraphics setCharacter(int column, int row, char character) {
134 return setCharacter(column, row, newTextCharacter(character));
135 }
136
137 @Override
138 public TextGraphics setCharacter(TerminalPosition position, TextCharacter textCharacter) {
139 setCharacter(position.getColumn(), position.getRow(), textCharacter);
140 return this;
141 }
142
143 @Override
144 public TextGraphics setCharacter(TerminalPosition position, char character) {
145 return setCharacter(position.getColumn(), position.getRow(), character);
146 }
147
148 @Override
149 public TextGraphics drawLine(TerminalPosition fromPosition, TerminalPosition toPoint, char character) {
150 return drawLine(fromPosition, toPoint, newTextCharacter(character));
151 }
152
153 @Override
154 public TextGraphics drawLine(TerminalPosition fromPoint, TerminalPosition toPoint, TextCharacter character) {
155 shapeRenderer.drawLine(fromPoint, toPoint, character);
156 return this;
157 }
158
159 @Override
160 public TextGraphics drawLine(int fromX, int fromY, int toX, int toY, char character) {
161 return drawLine(fromX, fromY, toX, toY, newTextCharacter(character));
162 }
163
164 @Override
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);
167 }
168
169 @Override
170 public TextGraphics drawTriangle(TerminalPosition p1, TerminalPosition p2, TerminalPosition p3, char character) {
171 return drawTriangle(p1, p2, p3, newTextCharacter(character));
172 }
173
174 @Override
175 public TextGraphics drawTriangle(TerminalPosition p1, TerminalPosition p2, TerminalPosition p3, TextCharacter character) {
176 shapeRenderer.drawTriangle(p1, p2, p3, character);
177 return this;
178 }
179
180 @Override
181 public TextGraphics fillTriangle(TerminalPosition p1, TerminalPosition p2, TerminalPosition p3, char character) {
182 return fillTriangle(p1, p2, p3, newTextCharacter(character));
183 }
184
185 @Override
186 public TextGraphics fillTriangle(TerminalPosition p1, TerminalPosition p2, TerminalPosition p3, TextCharacter character) {
187 shapeRenderer.fillTriangle(p1, p2, p3, character);
188 return this;
189 }
190
191 @Override
192 public TextGraphics drawRectangle(TerminalPosition topLeft, TerminalSize size, char character) {
193 return drawRectangle(topLeft, size, newTextCharacter(character));
194 }
195
196 @Override
197 public TextGraphics drawRectangle(TerminalPosition topLeft, TerminalSize size, TextCharacter character) {
198 shapeRenderer.drawRectangle(topLeft, size, character);
199 return this;
200 }
201
202 @Override
203 public TextGraphics fillRectangle(TerminalPosition topLeft, TerminalSize size, char character) {
204 return fillRectangle(topLeft, size, newTextCharacter(character));
205 }
206
207 @Override
208 public TextGraphics fillRectangle(TerminalPosition topLeft, TerminalSize size, TextCharacter character) {
209 shapeRenderer.fillRectangle(topLeft, size, character);
210 return this;
211 }
212
213 @Override
214 public TextGraphics drawImage(TerminalPosition topLeft, TextImage image) {
215 return drawImage(topLeft, image, TerminalPosition.TOP_LEFT_CORNER, image.getSize());
216 }
217
218 @Override
219 public TextGraphics drawImage(
220 TerminalPosition topLeft,
221 TextImage image,
222 TerminalPosition sourceImageTopLeft,
223 TerminalSize sourceImageSize) {
224
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);
230 }
231 if(sourceImageTopLeft.getRow() < 0) {
232 topLeft = topLeft.withRelativeRow(-sourceImageTopLeft.getRow());
233 sourceImageSize = sourceImageSize.withRelativeRows(sourceImageTopLeft.getRow());
234 sourceImageTopLeft = sourceImageTopLeft.withRow(0);
235 }
236
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());
242
243 // difference between position in image and position on target:
244 int diffRow = topLeft.getRow() - sourceImageTopLeft.getRow();
245 int diffColumn = topLeft.getColumn() - sourceImageTopLeft.getColumn();
246
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);
250
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);
254
255 if (fromRow >= untilRow || fromColumn >= untilColumn) {
256 return this;
257 }
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));
261 }
262 }
263 return this;
264 }
265
266 @Override
267 public TextGraphics putString(int column, int row, String string) {
268 if(string.contains("\n")) {
269 string = string.substring(0, string.indexOf("\n"));
270 }
271 if(string.contains("\r")) {
272 string = string.substring(0, string.indexOf("\r"));
273 }
274 string = tabBehaviour.replaceTabs(string, column);
275 int offset = 0;
276 for(int i = 0; i < string.length(); i++) {
277 char character = string.charAt(i);
278 setCharacter(
279 column + offset,
280 row,
281 new TextCharacter(
282 character,
283 foregroundColor,
284 backgroundColor,
285 activeModifiers.clone()));
286
287 if(TerminalTextUtils.isCharCJK(character)) {
288 //CJK characters are twice the normal characters in width, so next character position is two columns forward
289 offset += 2;
290 }
291 else {
292 //For "normal" characters we advance to the next column
293 offset += 1;
294 }
295 }
296 return this;
297 }
298
299 @Override
300 public TextGraphics putString(TerminalPosition position, String string) {
301 putString(position.getColumn(), position.getRow(), string);
302 return this;
303 }
304
305 @Override
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));
308 }
309
310 @Override
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);
316 return this;
317 }
318
319 @Override
320 public TextGraphics putString(TerminalPosition position, String string, SGR extraModifier, SGR... optionalExtraModifiers) {
321 putString(position.getColumn(), position.getRow(), string, extraModifier, optionalExtraModifiers);
322 return this;
323 }
324
325 @Override
326 public TextCharacter getCharacter(TerminalPosition position) {
327 return getCharacter(position.getColumn(), position.getRow());
328 }
329
330 @Override
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);
340 }
341 return new SubTextGraphics(this, topLeftCorner, size);
342 }
343
344 private TextCharacter newTextCharacter(char character) {
345 return new TextCharacter(character, foregroundColor, backgroundColor, activeModifiers);
346 }
347}