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): class Subiquity(Application):
from subiquity.palette import PALETTE, STYLES, STYLES_MONO from subiquity.palette import COLORS, STYLES, STYLES_MONO
project = "subiquity" project = "subiquity"

View File

@ -15,61 +15,18 @@
""" Palette definitions """ """ 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
COLORS = [
URWID_16_NAMES = [ ("bg", (0x00, 0x00, 0x00)),
'black', ("orange", (0xe9, 0x54, 0x20)),
'dark red', ("danger", (0xff, 0x00, 0x00)),
'dark green', ("good", (0x00, 0xff, 0x00)),
'brown', ("neutral", (0x00, 0xff, 0xff)),
'dark blue', ("gray", (0x7f, 0x7f, 0x7f)),
'dark magenta', ("aubergine", (0x77, 0x21, 0x6f)),
'dark cyan', ("fg", (0xff, 0xff, 0xff)),
'light gray',
] ]
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 = [ STYLES = [
('frame_header', 'fg', 'orange'), ('frame_header', 'fg', 'orange'),
('frame_footer', 'fg', 'gray'), ('frame_footer', 'fg', 'gray'),
@ -102,22 +59,20 @@ focus_styles = set([
for i in range(len(STYLES)): for i in range(len(STYLES)):
name, fg, bg = STYLES[i] name, fg, bg = STYLES[i]
STYLES[i] = (name, URWID16[fg], URWID16[bg], '', URWID256[fg], URWID256[bg])
if name in focus_styles: if name in focus_styles:
STYLES.append( STYLES.append((name + ' focus', bg, fg))
(name + ' focus', URWID16[bg], URWID16[fg], '', URWID256[bg], URWID256[fg]))
STYLES_MONO = [ STYLES_MONO = [
('frame_header', white, black, '', '', ''), ('frame_header', 'white', 'black'),
('frame_footer', white, black, '', '', ''), ('frame_footer', 'white', 'black'),
('body', white, black, '', '', ''), ('body', 'white', 'black'),
('info_minor', white, black, '', '', ''), ('info_minor', 'white', 'black'),
('menu_button', '', '', '', white, ''), ('menu_button', '', ''),
('menu_button focus', '', '', '', white, ''), ('menu_button focus', '', ''),
('button', white, black, '', '', ''), ('button', 'white', 'black'),
('button focus', white, black, '', '', ''), ('button focus', 'white', 'black'),
('string_input', '', '', '', white, ''), ('string_input', '', ''),
('string_input focus', '', '', '', white, ''), ('string_input focus', '', ''),
('progress_incomplete', '', '', '', '', black), ('progress_incomplete', '', ''),
('progress_complete', '', '', '', '', white), ('progress_complete', '', ''),
] ]

View File

@ -17,7 +17,6 @@ from concurrent import futures
import fcntl import fcntl
import logging import logging
import sys import sys
import os
import urwid import urwid
import yaml import yaml
@ -42,21 +41,19 @@ PIO_CMAP = 0x4B71 # sets colour palette on VGA+
UO_R, UO_G, UO_B = 0xe9, 0x54, 0x20 UO_R, UO_G, UO_B = 0xe9, 0x54, 0x20
def setup_ubuntu_orange(pal, additional_opts): class ISO_8613_3_Screen(urwid.raw_display.Screen):
"""Overwrite color 4 (usually "dark blue") to Ubuntu orange."""
if is_linux_tty(): def __init__(self, _urwid_name_to_rgb):
curpal = bytearray(16*3) self._fg_to_rgb = _urwid_name_to_rgb.copy()
fcntl.ioctl(sys.stdout.fileno(), GIO_CMAP, curpal) self._fg_to_rgb['default'] = _urwid_name_to_rgb['light gray']
curpal[:8] = pal self._bg_to_rgb = _urwid_name_to_rgb.copy()
fcntl.ioctl(sys.stdout.fileno(), PIO_CMAP, curpal) self._bg_to_rgb['default'] = _urwid_name_to_rgb['black']
elif os.environ['TERM'] == 'fbterm': super().__init__()
print('\033[3;4;%i;%i;%i}' % (UO_R, UO_G, UO_B), flush=True)
else: def _attrspec_to_escape(self, a):
additional_opts['screen'].set_terminal_properties(colors=256) f_r, f_g, f_b = self._fg_to_rgb[a.foreground]
entries = [] b_r, b_g, b_b = self._bg_to_rgb[a.background]
for i in range(8): return "\x1b[38;2;{};{};{};48;2;{};{};{}m".format(f_r, f_g, f_b, b_r, b_g, b_b)
entries.append((i+16, pal[i*3+0], pal[i*3+1], pal[i*3+2]))
additional_opts['screen'].modify_terminal_palette(entries)
def is_linux_tty(): def is_linux_tty():
@ -69,6 +66,56 @@ def is_linux_tty():
return r == b'\x02' 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: class Application:
# A concrete subclass must set project and controllers attributes, e.g.: # A concrete subclass must set project and controllers attributes, e.g.:
@ -167,25 +214,17 @@ class Application:
def exit(self): def exit(self):
raise urwid.ExitMainLoop() raise urwid.ExitMainLoop()
def header_hotkeys(self, key):
return False
def run(self): def run(self):
if not hasattr(self, 'loop'): 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: if self.common['opts'].run_on_serial:
palette = self.STYLES_MONO palette = self.STYLES_MONO
screen = urwid.raw_display.Screen()
else: else:
setup_ubuntu_orange(self.PALETTE, additional_opts) screen, palette = setup_screen(self.COLORS, self.STYLES)
self.common['loop'] = urwid.MainLoop( 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( log.debug("Running event loop: {}".format(
self.common['loop'].event_loop)) self.common['loop'].event_loop))