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
.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
= 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
) {
156 // Default to white on black
157 foreColorRGB
= 0xFFFFFF;
161 if (!tokenizer
.nextToken().toLowerCase().equals("on")) {
167 int backColorRGB
= -1;
169 backColorRGB
= Integer
.parseInt(tokenizer
.nextToken(), 16);
170 } catch (NumberFormatException e
) {
174 CellAttributes color
= new CellAttributes();
175 color
.setForeColorRGB(foreColorRGB
);
176 color
.setBackColorRGB(backColorRGB
);
177 colors
.put(key
, color
);
181 while (token
.equals("bold")
182 || token
.equals("bright")
183 || token
.equals("blink")
185 if (token
.equals("bold") || token
.equals("bright")) {
187 token
= tokenizer
.nextToken();
189 if (token
.equals("blink")) {
191 token
= tokenizer
.nextToken();
195 // What's left is "blah on blah"
196 foreColor
= token
.toLowerCase();
198 if (!tokenizer
.nextToken().toLowerCase().equals("on")) {
202 backColor
= tokenizer
.nextToken().toLowerCase();
204 CellAttributes color
= new CellAttributes();
209 color
.setBlink(true);
211 color
.setForeColor(Color
.getColor(foreColor
));
212 color
.setBackColor(Color
.getColor(backColor
));
213 colors
.put(key
, color
);
217 * Read color theme mappings from a Reader. The reader is closed at the
220 * @param reader the reader to read from
221 * @throws IOException if the I/O fails
223 public void load(final Reader reader
) throws IOException
{
224 BufferedReader bufferedReader
= new BufferedReader(reader
);
225 String line
= bufferedReader
.readLine();
226 for (; line
!= null; line
= bufferedReader
.readLine()) {
227 // Look for lines that resemble:
228 // "key = blah on blah"
229 // "key = bold blah on blah"
230 // "key = blink bold blah on blah"
231 // "key = bold blink blah on blah"
232 // "key = blink blah on blah"
233 if (line
.indexOf('=') == -1) {
237 String key
= line
.substring(0, line
.indexOf('=')).trim();
238 String text
= line
.substring(line
.indexOf('=') + 1);
239 setColorFromString(key
, text
);
242 bufferedReader
.close();
246 * Sets to defaults that resemble the Borland IDE colors.
248 public void setDefaultTheme() {
249 CellAttributes color
;
252 color
= new CellAttributes();
253 color
.setForeColor(Color
.WHITE
);
254 color
.setBackColor(Color
.BLUE
);
256 colors
.put("twindow.border", color
);
258 // TWindow background
259 color
= new CellAttributes();
260 color
.setForeColor(Color
.YELLOW
);
261 color
.setBackColor(Color
.BLUE
);
263 colors
.put("twindow.background", color
);
265 // TWindow border - inactive
266 color
= new CellAttributes();
267 color
.setForeColor(Color
.BLACK
);
268 color
.setBackColor(Color
.BLUE
);
270 colors
.put("twindow.border.inactive", color
);
272 // TWindow background - inactive
273 color
= new CellAttributes();
274 color
.setForeColor(Color
.YELLOW
);
275 color
.setBackColor(Color
.BLUE
);
277 colors
.put("twindow.background.inactive", color
);
279 // TWindow border - modal
280 color
= new CellAttributes();
281 color
.setForeColor(Color
.WHITE
);
282 color
.setBackColor(Color
.WHITE
);
284 colors
.put("twindow.border.modal", color
);
286 // TWindow background - modal
287 color
= new CellAttributes();
288 color
.setForeColor(Color
.BLACK
);
289 color
.setBackColor(Color
.WHITE
);
290 color
.setBold(false);
291 colors
.put("twindow.background.modal", color
);
293 // TWindow border - modal + inactive
294 color
= new CellAttributes();
295 color
.setForeColor(Color
.BLACK
);
296 color
.setBackColor(Color
.WHITE
);
298 colors
.put("twindow.border.modal.inactive", color
);
300 // TWindow background - modal + inactive
301 color
= new CellAttributes();
302 color
.setForeColor(Color
.BLACK
);
303 color
.setBackColor(Color
.WHITE
);
304 color
.setBold(false);
305 colors
.put("twindow.background.modal.inactive", color
);
307 // TWindow border - during window movement - modal
308 color
= new CellAttributes();
309 color
.setForeColor(Color
.GREEN
);
310 color
.setBackColor(Color
.WHITE
);
312 colors
.put("twindow.border.modal.windowmove", color
);
314 // TWindow border - during window movement
315 color
= new CellAttributes();
316 color
.setForeColor(Color
.GREEN
);
317 color
.setBackColor(Color
.BLUE
);
319 colors
.put("twindow.border.windowmove", color
);
321 // TWindow background - during window movement
322 color
= new CellAttributes();
323 color
.setForeColor(Color
.YELLOW
);
324 color
.setBackColor(Color
.BLUE
);
325 color
.setBold(false);
326 colors
.put("twindow.background.windowmove", color
);
328 // TDesktop background
329 color
= new CellAttributes();
330 color
.setForeColor(Color
.BLUE
);
331 color
.setBackColor(Color
.WHITE
);
332 color
.setBold(false);
333 colors
.put("tdesktop.background", color
);
336 color
= new CellAttributes();
337 color
.setForeColor(Color
.BLACK
);
338 color
.setBackColor(Color
.GREEN
);
339 color
.setBold(false);
340 colors
.put("tbutton.inactive", color
);
341 color
= new CellAttributes();
342 color
.setForeColor(Color
.CYAN
);
343 color
.setBackColor(Color
.GREEN
);
345 colors
.put("tbutton.active", color
);
346 color
= new CellAttributes();
347 color
.setForeColor(Color
.BLACK
);
348 color
.setBackColor(Color
.WHITE
);
350 colors
.put("tbutton.disabled", color
);
351 color
= new CellAttributes();
352 color
.setForeColor(Color
.YELLOW
);
353 color
.setBackColor(Color
.GREEN
);
355 colors
.put("tbutton.mnemonic", color
);
356 color
= new CellAttributes();
357 color
.setForeColor(Color
.YELLOW
);
358 color
.setBackColor(Color
.GREEN
);
360 colors
.put("tbutton.mnemonic.highlighted", color
);
363 color
= new CellAttributes();
364 color
.setForeColor(Color
.WHITE
);
365 color
.setBackColor(Color
.BLUE
);
367 colors
.put("tlabel", color
);
368 color
= new CellAttributes();
369 color
.setForeColor(Color
.YELLOW
);
370 color
.setBackColor(Color
.BLUE
);
372 colors
.put("tlabel.mnemonic", color
);
375 color
= new CellAttributes();
376 color
.setForeColor(Color
.WHITE
);
377 color
.setBackColor(Color
.BLUE
);
378 color
.setBold(false);
379 colors
.put("ttext", color
);
382 color
= new CellAttributes();
383 color
.setForeColor(Color
.BLACK
);
384 color
.setBackColor(Color
.WHITE
);
385 color
.setBold(false);
386 colors
.put("tfield.inactive", color
);
387 color
= new CellAttributes();
388 color
.setForeColor(Color
.BLACK
);
389 color
.setBackColor(Color
.CYAN
);
390 color
.setBold(false);
391 colors
.put("tfield.active", color
);
394 color
= new CellAttributes();
395 color
.setForeColor(Color
.WHITE
);
396 color
.setBackColor(Color
.BLUE
);
397 color
.setBold(false);
398 colors
.put("tcheckbox.inactive", color
);
399 color
= new CellAttributes();
400 color
.setForeColor(Color
.YELLOW
);
401 color
.setBackColor(Color
.BLACK
);
403 colors
.put("tcheckbox.active", color
);
404 color
= new CellAttributes();
405 color
.setForeColor(Color
.YELLOW
);
406 color
.setBackColor(Color
.BLUE
);
408 colors
.put("tcheckbox.mnemonic", color
);
409 color
= new CellAttributes();
410 color
.setForeColor(Color
.RED
);
411 color
.setBackColor(Color
.BLACK
);
413 colors
.put("tcheckbox.mnemonic.highlighted", color
);
416 color
= new CellAttributes();
417 color
.setForeColor(Color
.BLACK
);
418 color
.setBackColor(Color
.WHITE
);
419 color
.setBold(false);
420 colors
.put("tcombobox.inactive", color
);
421 color
= new CellAttributes();
422 color
.setForeColor(Color
.BLUE
);
423 color
.setBackColor(Color
.CYAN
);
424 color
.setBold(false);
425 colors
.put("tcombobox.active", color
);
428 color
= new CellAttributes();
429 color
.setForeColor(Color
.BLACK
);
430 color
.setBackColor(Color
.WHITE
);
431 color
.setBold(false);
432 colors
.put("tspinner.inactive", color
);
433 color
= new CellAttributes();
434 color
.setForeColor(Color
.BLUE
);
435 color
.setBackColor(Color
.CYAN
);
436 color
.setBold(false);
437 colors
.put("tspinner.active", color
);
440 color
= new CellAttributes();
441 color
.setForeColor(Color
.WHITE
);
442 color
.setBackColor(Color
.BLUE
);
443 color
.setBold(false);
444 colors
.put("tcalendar.background", color
);
445 color
= new CellAttributes();
446 color
.setForeColor(Color
.WHITE
);
447 color
.setBackColor(Color
.BLUE
);
448 color
.setBold(false);
449 colors
.put("tcalendar.day", color
);
450 color
= new CellAttributes();
451 color
.setForeColor(Color
.RED
);
452 color
.setBackColor(Color
.WHITE
);
453 color
.setBold(false);
454 colors
.put("tcalendar.day.selected", color
);
455 color
= new CellAttributes();
456 color
.setForeColor(Color
.BLUE
);
457 color
.setBackColor(Color
.CYAN
);
458 color
.setBold(false);
459 colors
.put("tcalendar.arrow", color
);
460 color
= new CellAttributes();
461 color
.setForeColor(Color
.WHITE
);
462 color
.setBackColor(Color
.BLUE
);
464 colors
.put("tcalendar.title", color
);
467 color
= new CellAttributes();
468 color
.setForeColor(Color
.WHITE
);
469 color
.setBackColor(Color
.BLUE
);
470 color
.setBold(false);
471 colors
.put("tradiobutton.inactive", color
);
472 color
= new CellAttributes();
473 color
.setForeColor(Color
.YELLOW
);
474 color
.setBackColor(Color
.BLACK
);
476 colors
.put("tradiobutton.active", color
);
477 color
= new CellAttributes();
478 color
.setForeColor(Color
.YELLOW
);
479 color
.setBackColor(Color
.BLUE
);
481 colors
.put("tradiobutton.mnemonic", color
);
482 color
= new CellAttributes();
483 color
.setForeColor(Color
.RED
);
484 color
.setBackColor(Color
.BLACK
);
486 colors
.put("tradiobutton.mnemonic.highlighted", color
);
489 color
= new CellAttributes();
490 color
.setForeColor(Color
.WHITE
);
491 color
.setBackColor(Color
.BLUE
);
492 color
.setBold(false);
493 colors
.put("tradiogroup.inactive", color
);
494 color
= new CellAttributes();
495 color
.setForeColor(Color
.YELLOW
);
496 color
.setBackColor(Color
.BLUE
);
498 colors
.put("tradiogroup.active", color
);
501 color
= new CellAttributes();
502 color
.setForeColor(Color
.BLACK
);
503 color
.setBackColor(Color
.WHITE
);
504 color
.setBold(false);
505 colors
.put("tmenu", color
);
506 color
= new CellAttributes();
507 color
.setForeColor(Color
.BLACK
);
508 color
.setBackColor(Color
.GREEN
);
509 color
.setBold(false);
510 colors
.put("tmenu.highlighted", color
);
511 color
= new CellAttributes();
512 color
.setForeColor(Color
.RED
);
513 color
.setBackColor(Color
.WHITE
);
514 color
.setBold(false);
515 colors
.put("tmenu.mnemonic", color
);
516 color
= new CellAttributes();
517 color
.setForeColor(Color
.RED
);
518 color
.setBackColor(Color
.GREEN
);
519 color
.setBold(false);
520 colors
.put("tmenu.mnemonic.highlighted", color
);
521 color
= new CellAttributes();
522 color
.setForeColor(Color
.BLACK
);
523 color
.setBackColor(Color
.WHITE
);
525 colors
.put("tmenu.disabled", color
);
528 color
= new CellAttributes();
529 color
.setForeColor(Color
.BLUE
);
530 color
.setBackColor(Color
.BLUE
);
532 colors
.put("tprogressbar.complete", color
);
533 color
= new CellAttributes();
534 color
.setForeColor(Color
.WHITE
);
535 color
.setBackColor(Color
.BLUE
);
536 color
.setBold(false);
537 colors
.put("tprogressbar.incomplete", color
);
539 // THScroller / TVScroller
540 color
= new CellAttributes();
541 color
.setForeColor(Color
.CYAN
);
542 color
.setBackColor(Color
.BLUE
);
543 color
.setBold(false);
544 colors
.put("tscroller.bar", color
);
545 color
= new CellAttributes();
546 color
.setForeColor(Color
.BLUE
);
547 color
.setBackColor(Color
.CYAN
);
548 color
.setBold(false);
549 colors
.put("tscroller.arrows", color
);
552 color
= new CellAttributes();
553 color
.setForeColor(Color
.WHITE
);
554 color
.setBackColor(Color
.BLUE
);
555 color
.setBold(false);
556 colors
.put("ttreeview", color
);
557 color
= new CellAttributes();
558 color
.setForeColor(Color
.GREEN
);
559 color
.setBackColor(Color
.BLUE
);
561 colors
.put("ttreeview.expandbutton", color
);
562 color
= new CellAttributes();
563 color
.setForeColor(Color
.BLACK
);
564 color
.setBackColor(Color
.CYAN
);
565 color
.setBold(false);
566 colors
.put("ttreeview.selected", color
);
567 color
= new CellAttributes();
568 color
.setForeColor(Color
.RED
);
569 color
.setBackColor(Color
.BLUE
);
570 color
.setBold(false);
571 colors
.put("ttreeview.unreadable", color
);
572 color
= new CellAttributes();
573 // color.setForeColor(Color.BLACK);
574 // color.setBackColor(Color.BLUE);
575 // color.setBold(true);
576 color
.setForeColor(Color
.WHITE
);
577 color
.setBackColor(Color
.BLUE
);
578 color
.setBold(false);
579 colors
.put("ttreeview.inactive", color
);
580 color
= new CellAttributes();
581 color
.setForeColor(Color
.BLACK
);
582 color
.setBackColor(Color
.WHITE
);
583 color
.setBold(false);
584 colors
.put("ttreeview.selected.inactive", color
);
587 color
= new CellAttributes();
588 color
.setForeColor(Color
.WHITE
);
589 color
.setBackColor(Color
.BLUE
);
590 color
.setBold(false);
591 colors
.put("tlist", color
);
592 color
= new CellAttributes();
593 color
.setForeColor(Color
.BLACK
);
594 color
.setBackColor(Color
.CYAN
);
595 color
.setBold(false);
596 colors
.put("tlist.selected", color
);
597 color
= new CellAttributes();
598 color
.setForeColor(Color
.BLACK
);
599 color
.setBackColor(Color
.CYAN
);
600 color
.setBold(false);
601 colors
.put("tlist.unreadable", color
);
602 color
= new CellAttributes();
603 // color.setForeColor(Color.BLACK);
604 // color.setBackColor(Color.BLUE);
605 // color.setBold(true);
606 color
.setForeColor(Color
.WHITE
);
607 color
.setBackColor(Color
.BLUE
);
608 color
.setBold(false);
609 colors
.put("tlist.inactive", color
);
610 color
= new CellAttributes();
611 color
.setForeColor(Color
.BLACK
);
612 color
.setBackColor(Color
.WHITE
);
613 color
.setBold(false);
614 colors
.put("tlist.selected.inactive", color
);
617 color
= new CellAttributes();
618 color
.setForeColor(Color
.BLACK
);
619 color
.setBackColor(Color
.WHITE
);
620 color
.setBold(false);
621 colors
.put("tstatusbar.text", color
);
622 color
= new CellAttributes();
623 color
.setForeColor(Color
.RED
);
624 color
.setBackColor(Color
.WHITE
);
625 color
.setBold(false);
626 colors
.put("tstatusbar.button", color
);
627 color
= new CellAttributes();
628 color
.setForeColor(Color
.WHITE
);
629 color
.setBackColor(Color
.BLUE
);
630 color
.setBold(false);
631 colors
.put("tstatusbar.selected", color
);
634 color
= new CellAttributes();
635 color
.setForeColor(Color
.WHITE
);
636 color
.setBackColor(Color
.BLUE
);
637 color
.setBold(false);
638 colors
.put("teditor", color
);
639 color
= new CellAttributes();
640 color
.setForeColor(Color
.BLACK
);
641 color
.setBackColor(Color
.CYAN
);
642 color
.setBold(false);
643 colors
.put("teditor.selected", color
);
646 color
= new CellAttributes();
647 color
.setForeColor(Color
.WHITE
);
648 color
.setBackColor(Color
.BLUE
);
649 color
.setBold(false);
650 colors
.put("ttable.inactive", color
);
651 color
= new CellAttributes();
652 color
.setForeColor(Color
.BLACK
);
653 color
.setBackColor(Color
.CYAN
);
654 color
.setBold(false);
655 colors
.put("ttable.active", color
);
656 color
= new CellAttributes();
657 color
.setForeColor(Color
.YELLOW
);
658 color
.setBackColor(Color
.CYAN
);
660 colors
.put("ttable.selected", color
);
661 color
= new CellAttributes();
662 color
.setForeColor(Color
.BLACK
);
663 color
.setBackColor(Color
.WHITE
);
664 color
.setBold(false);
665 colors
.put("ttable.label", color
);
666 color
= new CellAttributes();
667 color
.setForeColor(Color
.BLUE
);
668 color
.setBackColor(Color
.WHITE
);
669 color
.setBold(false);
670 colors
.put("ttable.label.selected", color
);
671 color
= new CellAttributes();
672 color
.setForeColor(Color
.WHITE
);
673 color
.setBackColor(Color
.BLUE
);
674 color
.setBold(false);
675 colors
.put("ttable.border", color
);
678 color
= new CellAttributes();
679 color
.setForeColor(Color
.WHITE
);
680 color
.setBackColor(Color
.BLUE
);
681 color
.setBold(false);
682 colors
.put("tsplitpane", color
);
684 // THelpWindow border - during window movement
685 color
= new CellAttributes();
686 color
.setForeColor(Color
.GREEN
);
687 color
.setBackColor(Color
.CYAN
);
689 colors
.put("thelpwindow.windowmove", color
);
691 // THelpWindow border
692 color
= new CellAttributes();
693 color
.setForeColor(Color
.GREEN
);
694 color
.setBackColor(Color
.CYAN
);
696 colors
.put("thelpwindow.border", color
);
698 // THelpWindow background
699 color
= new CellAttributes();
700 color
.setForeColor(Color
.WHITE
);
701 color
.setBackColor(Color
.CYAN
);
703 colors
.put("thelpwindow.background", color
);
706 color
= new CellAttributes();
707 color
.setForeColor(Color
.WHITE
);
708 color
.setBackColor(Color
.BLUE
);
709 color
.setBold(false);
710 colors
.put("thelpwindow.text", color
);
713 color
= new CellAttributes();
714 color
.setForeColor(Color
.YELLOW
);
715 color
.setBackColor(Color
.BLUE
);
717 colors
.put("thelpwindow.link", color
);
719 // THelpWindow link - active
720 color
= new CellAttributes();
721 color
.setForeColor(Color
.YELLOW
);
722 color
.setBackColor(Color
.CYAN
);
724 colors
.put("thelpwindow.link.active", color
);
729 * Make human-readable description of this Cell.
731 * @return displayable String
734 public String
toString() {
735 return colors
.toString();