Merge branch 'master' of https://github.com/klamonte/jexer
[nikiroo-utils.git] / src / jexer / bits / ColorTheme.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2017 Kevin Lamonte
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
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.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29 package jexer.bits;
30
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;
38 import java.util.Set;
39 import java.util.SortedMap;
40 import java.util.StringTokenizer;
41 import java.util.TreeMap;
42
43 /**
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.
46 */
47 public final class ColorTheme {
48
49 // ------------------------------------------------------------------------
50 // Variables --------------------------------------------------------------
51 // ------------------------------------------------------------------------
52
53 /**
54 * The current theme colors.
55 */
56 private SortedMap<String, CellAttributes> colors;
57
58 // ------------------------------------------------------------------------
59 // Constructors -----------------------------------------------------------
60 // ------------------------------------------------------------------------
61
62 /**
63 * Public constructor sets the theme to the default.
64 */
65 public ColorTheme() {
66 colors = new TreeMap<String, CellAttributes>();
67 setDefaultTheme();
68 }
69
70 // ------------------------------------------------------------------------
71 // ColorTheme -------------------------------------------------------------
72 // ------------------------------------------------------------------------
73
74 /**
75 * Retrieve the CellAttributes for a named theme color.
76 *
77 * @param name theme color name, e.g. "twindow.border"
78 * @return color associated with name, e.g. bold yellow on blue
79 */
80 public CellAttributes getColor(final String name) {
81 CellAttributes attr = (CellAttributes) colors.get(name);
82 return attr;
83 }
84
85 /**
86 * Retrieve all the names in the theme.
87 *
88 * @return a list of names
89 */
90 public List<String> getColorNames() {
91 Set<String> keys = colors.keySet();
92 List<String> names = new ArrayList<String>(keys.size());
93 names.addAll(keys);
94 return names;
95 }
96
97 /**
98 * Set the color for a named theme color.
99 *
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
102 * blue
103 */
104 public void setColor(final String name, final CellAttributes color) {
105 colors.put(name, color);
106 }
107
108 /**
109 * Save the color theme mappings to an ASCII file.
110 *
111 * @param filename file to write to
112 * @throws IOException if the I/O fails
113 */
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));
119 }
120 file.close();
121 }
122
123 /**
124 * Read color theme mappings from an ASCII file.
125 *
126 * @param filename file to read from
127 * @throws IOException if the I/O fails
128 */
129 public void load(final String filename) throws IOException {
130 load(new FileReader(filename));
131 }
132
133 /**
134 * Set a color based on a text string. Color text string is of the form:
135 * <code>[ bold ] [ blink ] { foreground on background }</code>
136 *
137 * @param key the color key string
138 * @param text the text string
139 */
140 public void setColorFromString(final String key, final String text) {
141 boolean bold = false;
142 boolean blink = false;
143 String foreColor;
144 String backColor;
145 String token;
146
147 StringTokenizer tokenizer = new StringTokenizer(text);
148 token = tokenizer.nextToken();
149 while (token.equals("bold") || token.equals("blink")) {
150 if (token.equals("bold")) {
151 bold = true;
152 token = tokenizer.nextToken();
153 }
154 if (token.equals("blink")) {
155 blink = true;
156 token = tokenizer.nextToken();
157 }
158 }
159
160 // What's left is "blah on blah"
161 foreColor = token.toLowerCase();
162
163 if (!tokenizer.nextToken().toLowerCase().equals("on")) {
164 // Invalid line.
165 return;
166 }
167 backColor = tokenizer.nextToken().toLowerCase();
168
169 CellAttributes color = new CellAttributes();
170 if (bold) {
171 color.setBold(true);
172 }
173 if (blink) {
174 color.setBlink(true);
175 }
176 color.setForeColor(Color.getColor(foreColor));
177 color.setBackColor(Color.getColor(backColor));
178 colors.put(key, color);
179 }
180
181 /**
182 * Read color theme mappings from a Reader. The reader is closed at the
183 * end.
184 *
185 * @param reader the reader to read from
186 * @throws IOException if the I/O fails
187 */
188 public void load(final Reader reader) throws IOException {
189 BufferedReader bufferedReader = new BufferedReader(reader);
190 String line = bufferedReader.readLine();
191 for (; line != null; line = bufferedReader.readLine()) {
192 // Look for lines that resemble:
193 // "key = blah on blah"
194 // "key = bold blah on blah"
195 // "key = blink bold blah on blah"
196 // "key = bold blink blah on blah"
197 // "key = blink blah on blah"
198 if (line.indexOf('=') == -1) {
199 // Invalid line.
200 continue;
201 }
202 String key = line.substring(0, line.indexOf(':')).trim();
203 String text = line.substring(line.indexOf(':') + 1);
204 setColorFromString(key, text);
205 }
206 // All done.
207 bufferedReader.close();
208 }
209
210 /**
211 * Sets to defaults that resemble the Borland IDE colors.
212 */
213 public void setDefaultTheme() {
214 CellAttributes color;
215
216 // TWindow border
217 color = new CellAttributes();
218 color.setForeColor(Color.WHITE);
219 color.setBackColor(Color.BLUE);
220 color.setBold(true);
221 colors.put("twindow.border", color);
222
223 // TWindow background
224 color = new CellAttributes();
225 color.setForeColor(Color.YELLOW);
226 color.setBackColor(Color.BLUE);
227 color.setBold(true);
228 colors.put("twindow.background", color);
229
230 // TWindow border - inactive
231 color = new CellAttributes();
232 color.setForeColor(Color.BLACK);
233 color.setBackColor(Color.BLUE);
234 color.setBold(true);
235 colors.put("twindow.border.inactive", color);
236
237 // TWindow background - inactive
238 color = new CellAttributes();
239 color.setForeColor(Color.YELLOW);
240 color.setBackColor(Color.BLUE);
241 color.setBold(true);
242 colors.put("twindow.background.inactive", color);
243
244 // TWindow border - modal
245 color = new CellAttributes();
246 color.setForeColor(Color.WHITE);
247 color.setBackColor(Color.WHITE);
248 color.setBold(true);
249 colors.put("twindow.border.modal", color);
250
251 // TWindow background - modal
252 color = new CellAttributes();
253 color.setForeColor(Color.BLACK);
254 color.setBackColor(Color.WHITE);
255 color.setBold(false);
256 colors.put("twindow.background.modal", color);
257
258 // TWindow border - modal + inactive
259 color = new CellAttributes();
260 color.setForeColor(Color.BLACK);
261 color.setBackColor(Color.WHITE);
262 color.setBold(true);
263 colors.put("twindow.border.modal.inactive", color);
264
265 // TWindow background - modal + inactive
266 color = new CellAttributes();
267 color.setForeColor(Color.BLACK);
268 color.setBackColor(Color.WHITE);
269 color.setBold(false);
270 colors.put("twindow.background.modal.inactive", color);
271
272 // TWindow border - during window movement - modal
273 color = new CellAttributes();
274 color.setForeColor(Color.GREEN);
275 color.setBackColor(Color.WHITE);
276 color.setBold(true);
277 colors.put("twindow.border.modal.windowmove", color);
278
279 // TWindow border - during window movement
280 color = new CellAttributes();
281 color.setForeColor(Color.GREEN);
282 color.setBackColor(Color.BLUE);
283 color.setBold(true);
284 colors.put("twindow.border.windowmove", color);
285
286 // TWindow background - during window movement
287 color = new CellAttributes();
288 color.setForeColor(Color.YELLOW);
289 color.setBackColor(Color.BLUE);
290 color.setBold(false);
291 colors.put("twindow.background.windowmove", color);
292
293 // TDesktop background
294 color = new CellAttributes();
295 color.setForeColor(Color.BLUE);
296 color.setBackColor(Color.WHITE);
297 color.setBold(false);
298 colors.put("tdesktop.background", color);
299
300 // TButton text
301 color = new CellAttributes();
302 color.setForeColor(Color.BLACK);
303 color.setBackColor(Color.GREEN);
304 color.setBold(false);
305 colors.put("tbutton.inactive", color);
306 color = new CellAttributes();
307 color.setForeColor(Color.CYAN);
308 color.setBackColor(Color.GREEN);
309 color.setBold(true);
310 colors.put("tbutton.active", color);
311 color = new CellAttributes();
312 color.setForeColor(Color.BLACK);
313 color.setBackColor(Color.WHITE);
314 color.setBold(true);
315 colors.put("tbutton.disabled", color);
316 color = new CellAttributes();
317 color.setForeColor(Color.YELLOW);
318 color.setBackColor(Color.GREEN);
319 color.setBold(true);
320 colors.put("tbutton.mnemonic", color);
321 color = new CellAttributes();
322 color.setForeColor(Color.YELLOW);
323 color.setBackColor(Color.GREEN);
324 color.setBold(true);
325 colors.put("tbutton.mnemonic.highlighted", color);
326
327 // TLabel text
328 color = new CellAttributes();
329 color.setForeColor(Color.WHITE);
330 color.setBackColor(Color.BLUE);
331 color.setBold(true);
332 colors.put("tlabel", color);
333
334 // TText text
335 color = new CellAttributes();
336 color.setForeColor(Color.WHITE);
337 color.setBackColor(Color.BLUE);
338 color.setBold(false);
339 colors.put("ttext", color);
340
341 // TField text
342 color = new CellAttributes();
343 color.setForeColor(Color.WHITE);
344 color.setBackColor(Color.BLUE);
345 color.setBold(false);
346 colors.put("tfield.inactive", color);
347 color = new CellAttributes();
348 color.setForeColor(Color.YELLOW);
349 color.setBackColor(Color.BLACK);
350 color.setBold(true);
351 colors.put("tfield.active", color);
352
353 // TCheckbox
354 color = new CellAttributes();
355 color.setForeColor(Color.WHITE);
356 color.setBackColor(Color.BLUE);
357 color.setBold(false);
358 colors.put("tcheckbox.inactive", color);
359 color = new CellAttributes();
360 color.setForeColor(Color.YELLOW);
361 color.setBackColor(Color.BLACK);
362 color.setBold(true);
363 colors.put("tcheckbox.active", color);
364
365 // TRadioButton
366 color = new CellAttributes();
367 color.setForeColor(Color.WHITE);
368 color.setBackColor(Color.BLUE);
369 color.setBold(false);
370 colors.put("tradiobutton.inactive", color);
371 color = new CellAttributes();
372 color.setForeColor(Color.YELLOW);
373 color.setBackColor(Color.BLACK);
374 color.setBold(true);
375 colors.put("tradiobutton.active", color);
376
377 // TRadioGroup
378 color = new CellAttributes();
379 color.setForeColor(Color.WHITE);
380 color.setBackColor(Color.BLUE);
381 color.setBold(false);
382 colors.put("tradiogroup.inactive", color);
383 color = new CellAttributes();
384 color.setForeColor(Color.YELLOW);
385 color.setBackColor(Color.BLUE);
386 color.setBold(true);
387 colors.put("tradiogroup.active", color);
388
389 // TMenu
390 color = new CellAttributes();
391 color.setForeColor(Color.BLACK);
392 color.setBackColor(Color.WHITE);
393 color.setBold(false);
394 colors.put("tmenu", color);
395 color = new CellAttributes();
396 color.setForeColor(Color.BLACK);
397 color.setBackColor(Color.GREEN);
398 color.setBold(false);
399 colors.put("tmenu.highlighted", color);
400 color = new CellAttributes();
401 color.setForeColor(Color.RED);
402 color.setBackColor(Color.WHITE);
403 color.setBold(false);
404 colors.put("tmenu.mnemonic", color);
405 color = new CellAttributes();
406 color.setForeColor(Color.RED);
407 color.setBackColor(Color.GREEN);
408 color.setBold(false);
409 colors.put("tmenu.mnemonic.highlighted", color);
410 color = new CellAttributes();
411 color.setForeColor(Color.BLACK);
412 color.setBackColor(Color.WHITE);
413 color.setBold(true);
414 colors.put("tmenu.disabled", color);
415
416 // TProgressBar
417 color = new CellAttributes();
418 color.setForeColor(Color.BLUE);
419 color.setBackColor(Color.BLUE);
420 color.setBold(true);
421 colors.put("tprogressbar.complete", color);
422 color = new CellAttributes();
423 color.setForeColor(Color.WHITE);
424 color.setBackColor(Color.BLUE);
425 color.setBold(false);
426 colors.put("tprogressbar.incomplete", color);
427
428 // THScroller / TVScroller
429 color = new CellAttributes();
430 color.setForeColor(Color.CYAN);
431 color.setBackColor(Color.BLUE);
432 color.setBold(false);
433 colors.put("tscroller.bar", color);
434 color = new CellAttributes();
435 color.setForeColor(Color.BLUE);
436 color.setBackColor(Color.CYAN);
437 color.setBold(false);
438 colors.put("tscroller.arrows", color);
439
440 // TTreeView
441 color = new CellAttributes();
442 color.setForeColor(Color.WHITE);
443 color.setBackColor(Color.BLUE);
444 color.setBold(false);
445 colors.put("ttreeview", color);
446 color = new CellAttributes();
447 color.setForeColor(Color.GREEN);
448 color.setBackColor(Color.BLUE);
449 color.setBold(true);
450 colors.put("ttreeview.expandbutton", color);
451 color = new CellAttributes();
452 color.setForeColor(Color.BLACK);
453 color.setBackColor(Color.CYAN);
454 color.setBold(false);
455 colors.put("ttreeview.selected", color);
456 color = new CellAttributes();
457 color.setForeColor(Color.RED);
458 color.setBackColor(Color.BLUE);
459 color.setBold(false);
460 colors.put("ttreeview.unreadable", color);
461 color = new CellAttributes();
462 // color.setForeColor(Color.BLACK);
463 // color.setBackColor(Color.BLUE);
464 // color.setBold(true);
465 color.setForeColor(Color.WHITE);
466 color.setBackColor(Color.BLUE);
467 color.setBold(false);
468 colors.put("ttreeview.inactive", color);
469 color = new CellAttributes();
470 color.setForeColor(Color.BLACK);
471 color.setBackColor(Color.WHITE);
472 color.setBold(false);
473 colors.put("ttreeview.selected.inactive", color);
474
475 // TList
476 color = new CellAttributes();
477 color.setForeColor(Color.WHITE);
478 color.setBackColor(Color.BLUE);
479 color.setBold(false);
480 colors.put("tlist", color);
481 color = new CellAttributes();
482 color.setForeColor(Color.BLACK);
483 color.setBackColor(Color.CYAN);
484 color.setBold(false);
485 colors.put("tlist.selected", color);
486 color = new CellAttributes();
487 color.setForeColor(Color.BLACK);
488 color.setBackColor(Color.CYAN);
489 color.setBold(false);
490 colors.put("tlist.unreadable", color);
491 color = new CellAttributes();
492 // color.setForeColor(Color.BLACK);
493 // color.setBackColor(Color.BLUE);
494 // color.setBold(true);
495 color.setForeColor(Color.WHITE);
496 color.setBackColor(Color.BLUE);
497 color.setBold(false);
498 colors.put("tlist.inactive", color);
499 color = new CellAttributes();
500 color.setForeColor(Color.BLACK);
501 color.setBackColor(Color.WHITE);
502 color.setBold(false);
503 colors.put("tlist.selected.inactive", color);
504
505 // TStatusBar
506 color = new CellAttributes();
507 color.setForeColor(Color.BLACK);
508 color.setBackColor(Color.WHITE);
509 color.setBold(false);
510 colors.put("tstatusbar.text", color);
511 color = new CellAttributes();
512 color.setForeColor(Color.RED);
513 color.setBackColor(Color.WHITE);
514 color.setBold(false);
515 colors.put("tstatusbar.button", color);
516 color = new CellAttributes();
517 color.setForeColor(Color.WHITE);
518 color.setBackColor(Color.BLUE);
519 color.setBold(false);
520 colors.put("tstatusbar.selected", color);
521
522 // TEditor
523 color = new CellAttributes();
524 color.setForeColor(Color.WHITE);
525 color.setBackColor(Color.BLUE);
526 color.setBold(false);
527 colors.put("teditor", color);
528
529 }
530
531 /**
532 * Make human-readable description of this Cell.
533 *
534 * @return displayable String
535 */
536 @Override
537 public String toString() {
538 return colors.toString();
539 }
540
541 }