Merge pull request #269 from CanonicalLtd/mwhudson/simplify-colors

refactor color / palette setup
This commit is contained in:
Michael Hudson-Doyle 2017-11-22 13:28:43 +13:00 committed by GitHub
commit 26147d3cc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 96 deletions

View File

@ -24,7 +24,7 @@ log = logging.getLogger('console_conf.core')
class Subiquity(Application):
from subiquity.palette import PALETTE, STYLES, STYLES_MONO
from subiquity.palette import COLORS, STYLES, STYLES_MONO
project = "subiquity"

View File

@ -15,61 +15,18 @@
""" Palette definitions """
black = 'black' # index 0
dark_red = 'dark red' # index 1
dark_green = 'dark green' # index 2
brown = 'brown' # index 3
dark_blue = 'dark blue' # index 4 # This is overwritten to ubuntu orange at startup
dark_magenta = 'dark magenta' # index 5
dark_cyan = 'dark cyan' # index 6
light_gray = 'light gray' # index 7
dark_gray = 'dark gray' # index 8
light_red = 'light red' # index 9
light_green = 'light green' # index 10
yellow = 'yellow' # index 11
light_blue = 'light blue' # index 12
light_magenta = 'light magenta' # index 13
light_cyan = 'light cyan' # index 14
white = 'white' # index 15
URWID_16_NAMES = [
'black',
'dark red',
'dark green',
'brown',
'dark blue',
'dark magenta',
'dark cyan',
'light gray',
COLORS = [
("bg", (0x00, 0x00, 0x00)),
("orange", (0xe9, 0x54, 0x20)),
("danger", (0xff, 0x00, 0x00)),
("good", (0x00, 0xff, 0x00)),
("neutral", (0x00, 0xff, 0xff)),
("gray", (0x7f, 0x7f, 0x7f)),
("aubergine", (0x77, 0x21, 0x6f)),
("fg", (0xff, 0xff, 0xff)),
]
URWID16 = {}
URWID256 = {}
PALETTE = bytearray(8*3)
colors = {
0: ("bg", (0x00, 0x00, 0x00)),
1: ("orange", (0xe9, 0x54, 0x20)),
2: ("danger", (0xff, 0x00, 0x00)),
3: ("good", (0x00, 0xff, 0x00)),
4: ("neutral", (0x00, 0xff, 0xff)),
5: ("gray", (0x7f, 0x7f, 0x7f)),
6: ("aubergine", (0x77, 0x21, 0x6f)),
7: ("fg", (0xff, 0xff, 0xff)),
}
for i, (c, (r, g, b)) in colors.items():
URWID16[c] = URWID_16_NAMES[i]
PALETTE[i*3+0] = r
PALETTE[i*3+1] = g
PALETTE[i*3+2] = b
URWID256[c] = 'h' + str(i+16)
orange = "#e51"
warm_gray = "g15"
STYLES = [
('frame_header', 'fg', 'orange'),
('frame_footer', 'fg', 'gray'),
@ -102,22 +59,20 @@ focus_styles = set([
for i in range(len(STYLES)):
name, fg, bg = STYLES[i]
STYLES[i] = (name, URWID16[fg], URWID16[bg], '', URWID256[fg], URWID256[bg])
if name in focus_styles:
STYLES.append(
(name + ' focus', URWID16[bg], URWID16[fg], '', URWID256[bg], URWID256[fg]))
STYLES.append((name + ' focus', bg, fg))
STYLES_MONO = [
('frame_header', white, black, '', '', ''),
('frame_footer', white, black, '', '', ''),
('body', white, black, '', '', ''),
('info_minor', white, black, '', '', ''),
('menu_button', '', '', '', white, ''),
('menu_button focus', '', '', '', white, ''),
('button', white, black, '', '', ''),
('button focus', white, black, '', '', ''),
('string_input', '', '', '', white, ''),
('string_input focus', '', '', '', white, ''),
('progress_incomplete', '', '', '', '', black),
('progress_complete', '', '', '', '', white),
('frame_header', 'white', 'black'),
('frame_footer', 'white', 'black'),
('body', 'white', 'black'),
('info_minor', 'white', 'black'),
('menu_button', '', ''),
('menu_button focus', '', ''),
('button', 'white', 'black'),
('button focus', 'white', 'black'),
('string_input', '', ''),
('string_input focus', '', ''),
('progress_incomplete', '', ''),
('progress_complete', '', ''),
]

View File

@ -17,7 +17,6 @@ from concurrent import futures
import fcntl
import logging
import sys
import os
import urwid
import yaml
@ -42,21 +41,19 @@ PIO_CMAP = 0x4B71 # sets colour palette on VGA+
UO_R, UO_G, UO_B = 0xe9, 0x54, 0x20
def setup_ubuntu_orange(pal, additional_opts):
"""Overwrite color 4 (usually "dark blue") to Ubuntu orange."""
if is_linux_tty():
curpal = bytearray(16*3)
fcntl.ioctl(sys.stdout.fileno(), GIO_CMAP, curpal)
curpal[:8] = pal
fcntl.ioctl(sys.stdout.fileno(), PIO_CMAP, curpal)
elif os.environ['TERM'] == 'fbterm':
print('\033[3;4;%i;%i;%i}' % (UO_R, UO_G, UO_B), flush=True)
else:
additional_opts['screen'].set_terminal_properties(colors=256)
entries = []
for i in range(8):
entries.append((i+16, pal[i*3+0], pal[i*3+1], pal[i*3+2]))
additional_opts['screen'].modify_terminal_palette(entries)
class ISO_8613_3_Screen(urwid.raw_display.Screen):
def __init__(self, _urwid_name_to_rgb):
self._fg_to_rgb = _urwid_name_to_rgb.copy()
self._fg_to_rgb['default'] = _urwid_name_to_rgb['light gray']
self._bg_to_rgb = _urwid_name_to_rgb.copy()
self._bg_to_rgb['default'] = _urwid_name_to_rgb['black']
super().__init__()
def _attrspec_to_escape(self, a):
f_r, f_g, f_b = self._fg_to_rgb[a.foreground]
b_r, b_g, b_b = self._bg_to_rgb[a.background]
return "\x1b[38;2;{};{};{};48;2;{};{};{}m".format(f_r, f_g, f_b, b_r, b_g, b_b)
def is_linux_tty():
@ -69,6 +66,56 @@ def is_linux_tty():
return r == b'\x02'
def setup_screen(colors, styles):
"""Return a palette and screen to be passed to MainLoop.
colors is a list of exactly 8 tuples (name, (r, g, b))
styles is a list of tuples (stylename, fg_color, bg_color) where
fg_color and bg_color are defined in 'colors'
"""
# The part that makes this "fun" is that urwid insists on referring
# to the basic colors by their "standard" names but we overwrite
# these colors to mean different things. So we convert styles into
# an urwid palette by mapping the names in colors to the standard
# name, and then either overwrite the first 8 colors to be the
# colors from 'colors' (on the linux vt) or use a custom screen
# class that displays maps the standard color name to the value
# specified in colors using 24-bit control codes.
if len(colors) != 8:
raise Exception("setup_screen must be passed a list of exactly 8 colors")
urwid_8_names = (
'black',
'dark red',
'dark green',
'brown',
'dark blue',
'dark magenta',
'dark cyan',
'light gray',
)
urwid_name = dict(zip([c[0] for c in colors], urwid_8_names))
urwid_palette = []
for name, fg, bg in styles:
urwid_palette.append((name, urwid_name[fg], urwid_name[bg]))
if is_linux_tty():
curpal = bytearray(16*3)
fcntl.ioctl(sys.stdout.fileno(), GIO_CMAP, curpal)
for i in range(8):
for j in range(3):
curpal[i*3+j] = colors[i][1][j]
fcntl.ioctl(sys.stdout.fileno(), PIO_CMAP, curpal)
return urwid.raw_display.Screen(), urwid_palette
else:
_urwid_name_to_rgb = {}
for i, n in enumerate(urwid_8_names):
_urwid_name_to_rgb[n] = colors[i][1]
return ISO_8613_3_Screen(_urwid_name_to_rgb), urwid_palette
class Application:
# A concrete subclass must set project and controllers attributes, e.g.:
@ -167,25 +214,17 @@ class Application:
def exit(self):
raise urwid.ExitMainLoop()
def header_hotkeys(self, key):
return False
def run(self):
if not hasattr(self, 'loop'):
palette = self.STYLES
additional_opts = {
'screen': urwid.raw_display.Screen(),
'unhandled_input': self.header_hotkeys,
'handle_mouse': False,
'pop_ups': True,
}
if self.common['opts'].run_on_serial:
palette = self.STYLES_MONO
screen = urwid.raw_display.Screen()
else:
setup_ubuntu_orange(self.PALETTE, additional_opts)
screen, palette = setup_screen(self.COLORS, self.STYLES)
self.common['loop'] = urwid.MainLoop(
self.common['ui'], palette, **additional_opts)
self.common['ui'], palette=palette, screen=screen,
handle_mouse=False, pop_ups=True)
log.debug("Running event loop: {}".format(
self.common['loop'].event_loop))