2b913f1d41c9cf0621b3c85ff79c032465e87346
2 * Jexer - Java Text User Interface
4 * License: LGPLv3 or later
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
10 * Copyright (C) 2015 Kevin Lamonte
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
33 import jexer
.bits
.Cell
;
34 import jexer
.bits
.CellAttributes
;
36 import java
.awt
.Color
;
37 import java
.awt
.Cursor
;
39 import java
.awt
.FontMetrics
;
40 import java
.awt
.Frame
;
41 import java
.awt
.Graphics
;
42 import java
.awt
.Insets
;
43 import java
.awt
.geom
.Rectangle2D
;
44 import java
.io
.InputStream
;
47 * This Screen implementation draws to a Java AWT Frame.
49 public final class AWTScreen
extends Screen
{
51 private static Color MYBLACK
;
52 private static Color MYRED
;
53 private static Color MYGREEN
;
54 private static Color MYYELLOW
;
55 private static Color MYBLUE
;
56 private static Color MYMAGENTA
;
57 private static Color MYCYAN
;
58 private static Color MYWHITE
;
60 private static Color MYBOLD_BLACK
;
61 private static Color MYBOLD_RED
;
62 private static Color MYBOLD_GREEN
;
63 private static Color MYBOLD_YELLOW
;
64 private static Color MYBOLD_BLUE
;
65 private static Color MYBOLD_MAGENTA
;
66 private static Color MYBOLD_CYAN
;
67 private static Color MYBOLD_WHITE
;
69 private static boolean dosColors
= false;
72 * Setup AWT colors to match DOS color palette.
74 private static void setDOSColors() {
78 MYBLACK
= new Color(0x00, 0x00, 0x00);
79 MYRED
= new Color(0xa8, 0x00, 0x00);
80 MYGREEN
= new Color(0x00, 0xa8, 0x00);
81 MYYELLOW
= new Color(0xa8, 0x54, 0x00);
82 MYBLUE
= new Color(0x00, 0x00, 0xa8);
83 MYMAGENTA
= new Color(0xa8, 0x00, 0xa8);
84 MYCYAN
= new Color(0x00, 0xa8, 0xa8);
85 MYWHITE
= new Color(0xa8, 0xa8, 0xa8);
86 MYBOLD_BLACK
= new Color(0x54, 0x54, 0x54);
87 MYBOLD_RED
= new Color(0xfc, 0x54, 0x54);
88 MYBOLD_GREEN
= new Color(0x54, 0xfc, 0x54);
89 MYBOLD_YELLOW
= new Color(0xfc, 0xfc, 0x54);
90 MYBOLD_BLUE
= new Color(0x54, 0x54, 0xfc);
91 MYBOLD_MAGENTA
= new Color(0xfc, 0x54, 0xfc);
92 MYBOLD_CYAN
= new Color(0x54, 0xfc, 0xfc);
93 MYBOLD_WHITE
= new Color(0xfc, 0xfc, 0xfc);
99 * AWTFrame is our top-level hook into the AWT system.
101 class AWTFrame
extends Frame
{
104 * The terminus font resource filename.
106 private static final String FONTFILE
= "terminus-ttf-4.39/TerminusTTF-Bold-4.39.ttf";
109 * The TUI Screen data.
114 * Width of a character cell.
116 private int textWidth
= 1;
119 * Height of a character cell.
121 private int textHeight
= 1;
124 * Descent of a character cell.
126 private int maxDescent
= 0;
131 private int top
= 30;
136 private int left
= 30;
139 * Convert a CellAttributes foreground color to an AWT Color.
141 * @param attr the text attributes
142 * @return the AWT Color
144 private Color
attrToForegroundColor(final CellAttributes attr
) {
151 if (attr
.getBold()) {
152 if (attr
.getForeColor().equals(jexer
.bits
.Color
.BLACK
)) {
154 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.RED
)) {
156 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.BLUE
)) {
158 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.GREEN
)) {
160 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.YELLOW
)) {
161 return MYBOLD_YELLOW
;
162 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.CYAN
)) {
164 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.MAGENTA
)) {
165 return MYBOLD_MAGENTA
;
166 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.WHITE
)) {
170 if (attr
.getForeColor().equals(jexer
.bits
.Color
.BLACK
)) {
172 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.RED
)) {
174 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.BLUE
)) {
176 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.GREEN
)) {
178 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.YELLOW
)) {
180 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.CYAN
)) {
182 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.MAGENTA
)) {
184 } else if (attr
.getForeColor().equals(jexer
.bits
.Color
.WHITE
)) {
188 throw new IllegalArgumentException("Invalid color: " + attr
.getForeColor().getValue());
192 * Convert a CellAttributes background color to an AWT Color.
194 * @param attr the text attributes
195 * @return the AWT Color
197 private Color
attrToBackgroundColor(final CellAttributes attr
) {
204 if (attr
.getBackColor().equals(jexer
.bits
.Color
.BLACK
)) {
206 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.RED
)) {
208 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.BLUE
)) {
210 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.GREEN
)) {
212 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.YELLOW
)) {
214 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.CYAN
)) {
216 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.MAGENTA
)) {
218 } else if (attr
.getBackColor().equals(jexer
.bits
.Color
.WHITE
)) {
221 throw new IllegalArgumentException("Invalid color: " + attr
.getBackColor().getValue());
225 * Public constructor.
227 * @param screen the Screen that Backend talks to
229 public AWTFrame(final AWTScreen screen
) {
230 this.screen
= screen
;
233 setTitle("Jexer Application");
234 setBackground(java
.awt
.Color
.black
);
235 setCursor(Cursor
.getPredefinedCursor(Cursor
.TEXT_CURSOR
));
236 // setFont(new Font("Liberation Mono", Font.BOLD, 16));
237 // setFont(new Font(Font.MONOSPACED, Font.PLAIN, 16));
240 ClassLoader loader
= Thread
.currentThread().getContextClassLoader();
241 InputStream in
= loader
.getResourceAsStream(FONTFILE
);
242 Font terminusRoot
= Font
.createFont(Font
.TRUETYPE_FONT
, in
);
243 Font terminus
= terminusRoot
.deriveFont(Font
.PLAIN
, 22);
245 } catch (Exception e
) {
247 // setFont(new Font("Liberation Mono", Font.PLAIN, 24));
248 setFont(new Font(Font
.MONOSPACED
, Font
.PLAIN
, 24));
255 * Resize to font dimensions.
257 public void resizeToScreen() {
258 Graphics gr
= getGraphics();
259 FontMetrics fm
= gr
.getFontMetrics();
260 maxDescent
= fm
.getMaxDescent();
261 Rectangle2D bounds
= fm
.getMaxCharBounds(gr
);
262 int leading
= fm
.getLeading();
263 textWidth
= (int)Math
.round(bounds
.getWidth());
264 textHeight
= (int)Math
.round(bounds
.getHeight()) - maxDescent
;
265 // This also produces the same number, but works better for ugly
267 textHeight
= fm
.getMaxAscent() + maxDescent
- leading
;
269 // Figure out the thickness of borders and use that to set the
271 Insets insets
= getInsets();
275 setSize(textWidth
* screen
.width
+ insets
.left
+ insets
.right
,
276 textHeight
* screen
.height
+ insets
.top
+ insets
.bottom
);
279 System.err.printf("W: %d H: %d MD: %d L: %d\n", textWidth,
280 textHeight, maxDescent, leading);
285 * Paint redraws the whole screen.
287 * @param gr the AWT Graphics context
290 public void paint(final Graphics gr
) {
292 for (int y
= 0; y
< screen
.height
; y
++) {
293 for (int x
= 0; x
< screen
.width
; x
++) {
294 Cell lCell
= screen
.logical
[x
][y
];
295 Cell pCell
= screen
.physical
[x
][y
];
297 int xPixel
= x
* textWidth
+ left
;
298 int yPixel
= y
* textHeight
+ top
;
300 if (!lCell
.equals(pCell
)) {
302 // Draw the background rectangle, then the foreground
304 gr
.setColor(attrToBackgroundColor(lCell
));
305 gr
.fillRect(xPixel
, yPixel
, textWidth
, textHeight
);
306 gr
.setColor(attrToForegroundColor(lCell
));
307 char [] chars
= new char[1];
308 chars
[0] = lCell
.getChar();
309 gr
.drawChars(chars
, 0, 1, xPixel
,
310 yPixel
+ textHeight
- maxDescent
);
312 // Physical is always updated
313 physical
[x
][y
].setTo(lCell
);
321 * The raw AWT Frame. Note package private access.
326 * Public constructor.
329 frame
= new AWTFrame(this);
333 * Push the logical screen to the physical device.
336 public void flushPhysical() {
337 Graphics gr
= frame
.getGraphics();