2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 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
.io
.BufferedReader
;
32 import java
.io
.FileReader
;
33 import java
.io
.FileWriter
;
34 import java
.io
.IOException
;
35 import java
.io
.Reader
;
36 import java
.util
.ArrayList
;
37 import java
.util
.List
;
39 import java
.util
.SortedMap
;
40 import java
.util
.StringTokenizer
;
41 import java
.util
.TreeMap
;
44 * ColorTheme is a collection of colors keyed by string. A default theme is
45 * also provided that matches the blue-and-white theme used by Turbo Vision.
47 public class ColorTheme
{
49 // ------------------------------------------------------------------------
50 // Variables --------------------------------------------------------------
51 // ------------------------------------------------------------------------
54 * The current theme colors.
56 private SortedMap
<String
, CellAttributes
> colors
;
58 // ------------------------------------------------------------------------
59 // Constructors -----------------------------------------------------------
60 // ------------------------------------------------------------------------
63 * Public constructor sets the theme to the default.
66 colors
= new TreeMap
<String
, CellAttributes
>();
70 // ------------------------------------------------------------------------
71 // ColorTheme -------------------------------------------------------------
72 // ------------------------------------------------------------------------
75 * Retrieve the CellAttributes for a named theme color.
77 * @param name theme color name, e.g. "twindow.border"
78 * @return color associated with name, e.g. bold yellow on blue
80 public CellAttributes
getColor(final String name
) {
81 CellAttributes attr
= (CellAttributes
) colors
.get(name
);
86 * Retrieve all the names in the theme.
88 * @return a list of names
90 public List
<String
> getColorNames() {
91 Set
<String
> keys
= colors
.keySet();
92 List
<String
> names
= new ArrayList
<String
>(keys
.size());
98 * Set the color for a named theme color.
100 * @param name theme color name, e.g. "twindow.border"
101 * @param color the new color to associate with name, e.g. bold yellow on
104 public void setColor(final String name
, final CellAttributes color
) {
105 colors
.put(name
, color
);
109 * Save the color theme mappings to an ASCII file.
111 * @param filename file to write to
112 * @throws IOException if the I/O fails
114 public void save(final String filename
) throws IOException
{
115 FileWriter file
= new FileWriter(filename
);
116 for (String key
: colors
.keySet()) {
117 CellAttributes color
= getColor(key
);
118 file
.write(String
.format("%s = %s\n", key
, color
));
124 * Read color theme mappings from an ASCII file.
126 * @param filename file to read from
127 * @throws IOException if the I/O fails
129 public void load(final String filename
) throws IOException
{
130 load(new FileReader(filename
));
134 * Set a color based on a text string. Color text string is of the form:
135 * <code>[ bold ] [ blink ] { foreground on background }</code>
137 * @param key the color key string
138 * @param text the text string
140 public void setColorFromString(final String key
, final String text
) {
141 boolean bold
= false;
142 boolean blink
= false;
147 StringTokenizer tokenizer
= new StringTokenizer(text
);
148 token
= tokenizer
.nextToken();
150 if (token
.toLowerCase().equals("rgb:")) {
152 int foreColorRGB
= -1;
154 foreColorRGB
= Integer
.parseInt(tokenizer
.nextToken(), 16);
155 } catch (NumberFormatException e
) {
160 if (!tokenizer
.nextToken().toLowerCase().equals("on")) {
166 int backColorRGB
= -1;
168 backColorRGB
= Integer
.parseInt(tokenizer
.nextToken(), 16);
169 } catch (NumberFormatException e
) {
173 CellAttributes color
= new CellAttributes();
174 color
.setForeColorRGB(foreColorRGB
);
175 color
.setBackColorRGB(backColorRGB
);
176 colors
.put(key
, color
);
180 while (token
.equals("bold") || token
.equals("blink")) {
181 if (token
.equals("bold")) {
183 token
= tokenizer
.nextToken();
185 if (token
.equals("blink")) {
187 token
= tokenizer
.nextToken();
191 // What's left is "blah on blah"
192 foreColor
= token
.toLowerCase();
194 if (!tokenizer
.nextToken().toLowerCase().equals("on")) {
198 backColor
= tokenizer
.nextToken().toLowerCase();
200 CellAttributes color
= new CellAttributes();
205 color
.setBlink(true);
207 color
.setForeColor(Color
.getColor(foreColor
));
208 color
.setBackColor(Color
.getColor(backColor
));
209 colors
.put(key
, color
);
213 * Read color theme mappings from a Reader. The reader is closed at the
216 * @param reader the reader to read from
217 * @throws IOException if the I/O fails
219 public void load(final Reader reader
) throws IOException
{
220 BufferedReader bufferedReader
= new BufferedReader(reader
);
221 String line
= bufferedReader
.readLine();
222 for (; line
!= null; line
= bufferedReader
.readLine()) {
223 // Look for lines that resemble:
224 // "key = blah on blah"
225 // "key = bold blah on blah"
226 // "key = blink bold blah on blah"
227 // "key = bold blink blah on blah"
228 // "key = blink blah on blah"
229 if (line
.indexOf('=') == -1) {
233 String key
= line
.substring(0, line
.indexOf(':')).trim();
234 String text
= line
.substring(line
.indexOf(':') + 1);
235 setColorFromString(key
, text
);
238 bufferedReader
.close();
242 * Sets to defaults that resemble the Borland IDE colors.
244 public void setDefaultTheme() {
245 CellAttributes color
;
248 color
= new CellAttributes();
249 color
.setForeColor(Color
.WHITE
);
250 color
.setBackColor(Color
.BLUE
);
252 colors
.put("twindow.border", color
);
254 // TWindow background
255 color
= new CellAttributes();
256 color
.setForeColor(Color
.YELLOW
);
257 color
.setBackColor(Color
.BLUE
);
259 colors
.put("twindow.background", color
);
261 // TWindow border - inactive
262 color
= new CellAttributes();
263 color
.setForeColor(Color
.BLACK
);
264 color
.setBackColor(Color
.BLUE
);
266 colors
.put("twindow.border.inactive", color
);
268 // TWindow background - inactive
269 color
= new CellAttributes();
270 color
.setForeColor(Color
.YELLOW
);
271 color
.setBackColor(Color
.BLUE
);
273 colors
.put("twindow.background.inactive", color
);
275 // TWindow border - modal
276 color
= new CellAttributes();
277 color
.setForeColor(Color
.WHITE
);
278 color
.setBackColor(Color
.WHITE
);
280 colors
.put("twindow.border.modal", color
);
282 // TWindow background - modal
283 color
= new CellAttributes();
284 color
.setForeColor(Color
.BLACK
);
285 color
.setBackColor(Color
.WHITE
);
286 color
.setBold(false);
287 colors
.put("twindow.background.modal", color
);
289 // TWindow border - modal + inactive
290 color
= new CellAttributes();
291 color
.setForeColor(Color
.BLACK
);
292 color
.setBackColor(Color
.WHITE
);
294 colors
.put("twindow.border.modal.inactive", color
);
296 // TWindow background - modal + inactive
297 color
= new CellAttributes();
298 color
.setForeColor(Color
.BLACK
);
299 color
.setBackColor(Color
.WHITE
);
300 color
.setBold(false);
301 colors
.put("twindow.background.modal.inactive", color
);
303 // TWindow border - during window movement - modal
304 color
= new CellAttributes();
305 color
.setForeColor(Color
.GREEN
);
306 color
.setBackColor(Color
.WHITE
);
308 colors
.put("twindow.border.modal.windowmove", color
);
310 // TWindow border - during window movement
311 color
= new CellAttributes();
312 color
.setForeColor(Color
.GREEN
);
313 color
.setBackColor(Color
.BLUE
);
315 colors
.put("twindow.border.windowmove", color
);
317 // TWindow background - during window movement
318 color
= new CellAttributes();
319 color
.setForeColor(Color
.YELLOW
);
320 color
.setBackColor(Color
.BLUE
);
321 color
.setBold(false);
322 colors
.put("twindow.background.windowmove", color
);
324 // TDesktop background
325 color
= new CellAttributes();
326 color
.setForeColor(Color
.BLUE
);
327 color
.setBackColor(Color
.WHITE
);
328 color
.setBold(false);
329 colors
.put("tdesktop.background", color
);
332 color
= new CellAttributes();
333 color
.setForeColor(Color
.BLACK
);
334 color
.setBackColor(Color
.GREEN
);
335 color
.setBold(false);
336 colors
.put("tbutton.inactive", color
);
337 color
= new CellAttributes();
338 color
.setForeColor(Color
.CYAN
);
339 color
.setBackColor(Color
.GREEN
);
341 colors
.put("tbutton.active", color
);
342 color
= new CellAttributes();
343 color
.setForeColor(Color
.BLACK
);
344 color
.setBackColor(Color
.WHITE
);
346 colors
.put("tbutton.disabled", color
);
347 color
= new CellAttributes();
348 color
.setForeColor(Color
.YELLOW
);
349 color
.setBackColor(Color
.GREEN
);
351 colors
.put("tbutton.mnemonic", color
);
352 color
= new CellAttributes();
353 color
.setForeColor(Color
.YELLOW
);
354 color
.setBackColor(Color
.GREEN
);
356 colors
.put("tbutton.mnemonic.highlighted", color
);
359 color
= new CellAttributes();
360 color
.setForeColor(Color
.WHITE
);
361 color
.setBackColor(Color
.BLUE
);
363 colors
.put("tlabel", color
);
366 color
= new CellAttributes();
367 color
.setForeColor(Color
.WHITE
);
368 color
.setBackColor(Color
.BLUE
);
369 color
.setBold(false);
370 colors
.put("ttext", color
);
373 color
= new CellAttributes();
374 color
.setForeColor(Color
.WHITE
);
375 color
.setBackColor(Color
.BLUE
);
376 color
.setBold(false);
377 colors
.put("tfield.inactive", color
);
378 color
= new CellAttributes();
379 color
.setForeColor(Color
.YELLOW
);
380 color
.setBackColor(Color
.BLACK
);
382 colors
.put("tfield.active", color
);
385 color
= new CellAttributes();
386 color
.setForeColor(Color
.WHITE
);
387 color
.setBackColor(Color
.BLUE
);
388 color
.setBold(false);
389 colors
.put("tcheckbox.inactive", color
);
390 color
= new CellAttributes();
391 color
.setForeColor(Color
.YELLOW
);
392 color
.setBackColor(Color
.BLACK
);
394 colors
.put("tcheckbox.active", color
);
397 color
= new CellAttributes();
398 color
.setForeColor(Color
.BLACK
);
399 color
.setBackColor(Color
.WHITE
);
400 color
.setBold(false);
401 colors
.put("tcombobox.inactive", color
);
402 color
= new CellAttributes();
403 color
.setForeColor(Color
.BLUE
);
404 color
.setBackColor(Color
.CYAN
);
405 color
.setBold(false);
406 colors
.put("tcombobox.active", color
);
409 color
= new CellAttributes();
410 color
.setForeColor(Color
.BLACK
);
411 color
.setBackColor(Color
.WHITE
);
412 color
.setBold(false);
413 colors
.put("tspinner.inactive", color
);
414 color
= new CellAttributes();
415 color
.setForeColor(Color
.BLUE
);
416 color
.setBackColor(Color
.CYAN
);
417 color
.setBold(false);
418 colors
.put("tspinner.active", color
);
421 color
= new CellAttributes();
422 color
.setForeColor(Color
.WHITE
);
423 color
.setBackColor(Color
.BLUE
);
424 color
.setBold(false);
425 colors
.put("tcalendar.background", color
);
426 color
= new CellAttributes();
427 color
.setForeColor(Color
.WHITE
);
428 color
.setBackColor(Color
.BLUE
);
429 color
.setBold(false);
430 colors
.put("tcalendar.day", color
);
431 color
= new CellAttributes();
432 color
.setForeColor(Color
.RED
);
433 color
.setBackColor(Color
.WHITE
);
434 color
.setBold(false);
435 colors
.put("tcalendar.day.selected", color
);
436 color
= new CellAttributes();
437 color
.setForeColor(Color
.BLUE
);
438 color
.setBackColor(Color
.CYAN
);
439 color
.setBold(false);
440 colors
.put("tcalendar.arrow", color
);
441 color
= new CellAttributes();
442 color
.setForeColor(Color
.WHITE
);
443 color
.setBackColor(Color
.BLUE
);
445 colors
.put("tcalendar.title", color
);
448 color
= new CellAttributes();
449 color
.setForeColor(Color
.WHITE
);
450 color
.setBackColor(Color
.BLUE
);
451 color
.setBold(false);
452 colors
.put("tradiobutton.inactive", color
);
453 color
= new CellAttributes();
454 color
.setForeColor(Color
.YELLOW
);
455 color
.setBackColor(Color
.BLACK
);
457 colors
.put("tradiobutton.active", color
);
460 color
= new CellAttributes();
461 color
.setForeColor(Color
.WHITE
);
462 color
.setBackColor(Color
.BLUE
);
463 color
.setBold(false);
464 colors
.put("tradiogroup.inactive", color
);
465 color
= new CellAttributes();
466 color
.setForeColor(Color
.YELLOW
);
467 color
.setBackColor(Color
.BLUE
);
469 colors
.put("tradiogroup.active", color
);
472 color
= new CellAttributes();
473 color
.setForeColor(Color
.BLACK
);
474 color
.setBackColor(Color
.WHITE
);
475 color
.setBold(false);
476 colors
.put("tmenu", color
);
477 color
= new CellAttributes();
478 color
.setForeColor(Color
.BLACK
);
479 color
.setBackColor(Color
.GREEN
);
480 color
.setBold(false);
481 colors
.put("tmenu.highlighted", color
);
482 color
= new CellAttributes();
483 color
.setForeColor(Color
.RED
);
484 color
.setBackColor(Color
.WHITE
);
485 color
.setBold(false);
486 colors
.put("tmenu.mnemonic", color
);
487 color
= new CellAttributes();
488 color
.setForeColor(Color
.RED
);
489 color
.setBackColor(Color
.GREEN
);
490 color
.setBold(false);
491 colors
.put("tmenu.mnemonic.highlighted", color
);
492 color
= new CellAttributes();
493 color
.setForeColor(Color
.BLACK
);
494 color
.setBackColor(Color
.WHITE
);
496 colors
.put("tmenu.disabled", color
);
499 color
= new CellAttributes();
500 color
.setForeColor(Color
.BLUE
);
501 color
.setBackColor(Color
.BLUE
);
503 colors
.put("tprogressbar.complete", color
);
504 color
= new CellAttributes();
505 color
.setForeColor(Color
.WHITE
);
506 color
.setBackColor(Color
.BLUE
);
507 color
.setBold(false);
508 colors
.put("tprogressbar.incomplete", color
);
510 // THScroller / TVScroller
511 color
= new CellAttributes();
512 color
.setForeColor(Color
.CYAN
);
513 color
.setBackColor(Color
.BLUE
);
514 color
.setBold(false);
515 colors
.put("tscroller.bar", color
);
516 color
= new CellAttributes();
517 color
.setForeColor(Color
.BLUE
);
518 color
.setBackColor(Color
.CYAN
);
519 color
.setBold(false);
520 colors
.put("tscroller.arrows", color
);
523 color
= new CellAttributes();
524 color
.setForeColor(Color
.WHITE
);
525 color
.setBackColor(Color
.BLUE
);
526 color
.setBold(false);
527 colors
.put("ttreeview", color
);
528 color
= new CellAttributes();
529 color
.setForeColor(Color
.GREEN
);
530 color
.setBackColor(Color
.BLUE
);
532 colors
.put("ttreeview.expandbutton", color
);
533 color
= new CellAttributes();
534 color
.setForeColor(Color
.BLACK
);
535 color
.setBackColor(Color
.CYAN
);
536 color
.setBold(false);
537 colors
.put("ttreeview.selected", color
);
538 color
= new CellAttributes();
539 color
.setForeColor(Color
.RED
);
540 color
.setBackColor(Color
.BLUE
);
541 color
.setBold(false);
542 colors
.put("ttreeview.unreadable", color
);
543 color
= new CellAttributes();
544 // color.setForeColor(Color.BLACK);
545 // color.setBackColor(Color.BLUE);
546 // color.setBold(true);
547 color
.setForeColor(Color
.WHITE
);
548 color
.setBackColor(Color
.BLUE
);
549 color
.setBold(false);
550 colors
.put("ttreeview.inactive", color
);
551 color
= new CellAttributes();
552 color
.setForeColor(Color
.BLACK
);
553 color
.setBackColor(Color
.WHITE
);
554 color
.setBold(false);
555 colors
.put("ttreeview.selected.inactive", color
);
558 color
= new CellAttributes();
559 color
.setForeColor(Color
.WHITE
);
560 color
.setBackColor(Color
.BLUE
);
561 color
.setBold(false);
562 colors
.put("tlist", color
);
563 color
= new CellAttributes();
564 color
.setForeColor(Color
.BLACK
);
565 color
.setBackColor(Color
.CYAN
);
566 color
.setBold(false);
567 colors
.put("tlist.selected", color
);
568 color
= new CellAttributes();
569 color
.setForeColor(Color
.BLACK
);
570 color
.setBackColor(Color
.CYAN
);
571 color
.setBold(false);
572 colors
.put("tlist.unreadable", color
);
573 color
= new CellAttributes();
574 // color.setForeColor(Color.BLACK);
575 // color.setBackColor(Color.BLUE);
576 // color.setBold(true);
577 color
.setForeColor(Color
.WHITE
);
578 color
.setBackColor(Color
.BLUE
);
579 color
.setBold(false);
580 colors
.put("tlist.inactive", color
);
581 color
= new CellAttributes();
582 color
.setForeColor(Color
.BLACK
);
583 color
.setBackColor(Color
.WHITE
);
584 color
.setBold(false);
585 colors
.put("tlist.selected.inactive", color
);
588 color
= new CellAttributes();
589 color
.setForeColor(Color
.BLACK
);
590 color
.setBackColor(Color
.WHITE
);
591 color
.setBold(false);
592 colors
.put("tstatusbar.text", color
);
593 color
= new CellAttributes();
594 color
.setForeColor(Color
.RED
);
595 color
.setBackColor(Color
.WHITE
);
596 color
.setBold(false);
597 colors
.put("tstatusbar.button", color
);
598 color
= new CellAttributes();
599 color
.setForeColor(Color
.WHITE
);
600 color
.setBackColor(Color
.BLUE
);
601 color
.setBold(false);
602 colors
.put("tstatusbar.selected", color
);
605 color
= new CellAttributes();
606 color
.setForeColor(Color
.WHITE
);
607 color
.setBackColor(Color
.BLUE
);
608 color
.setBold(false);
609 colors
.put("teditor", color
);
614 * Make human-readable description of this Cell.
616 * @return displayable String
619 public String
toString() {
620 return colors
.toString();