Finish up UI for viewer color scheme preferences

This commit is contained in:
Kovid Goyal 2016-09-25 10:47:19 +05:30
parent b3f119e34e
commit 718bb559b2
8 changed files with 200 additions and 60 deletions

1
imgsrc/srv/pencil.svg Normal file
View File

@ -0,0 +1 @@
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"/></svg>

After

Width:  |  Height:  |  Size: 364 B

1
imgsrc/srv/plus.svg Normal file
View File

@ -0,0 +1 @@
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1600 736v192q0 40-28 68t-68 28h-416v416q0 40-28 68t-68 28h-192q-40 0-68-28t-28-68v-416h-416q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h416v-416q0-40 28-68t68-28h192q40 0 68 28t28 68v416h416q40 0 68 28t28 68z"/></svg>

After

Width:  |  Height:  |  Size: 315 B

View File

@ -92,15 +92,16 @@ def element(elem_id, child_selector):
ans = ans.querySelector(child_selector)
return ans
def unique_id():
unique_id.count += 1
return 'auto-id-' + unique_id.count
unique_id.count = 0
def unique_id(prefix):
prefix = prefix or 'auto-id'
unique_id.counts[prefix] = num = (unique_id.counts[prefix] or 0) + 1
return prefix + '-' + num
unique_id.counts = {}
def ensure_id(w):
def ensure_id(w, prefix):
ans = w.getAttribute('id')
if not ans:
ans = unique_id()
ans = unique_id(prefix)
w.setAttribute('id', ans)
return ans

View File

@ -53,8 +53,8 @@ def set_current_spine_item(val):
default_color_schemes = {
'white':{'foreground':'black', 'background':'white', 'name':_('White')},
'black':{'foreground':'white', 'background':'black', 'name':_('Black')},
'white':{'foreground':'#000000', 'background':'#ffffff', 'name':_('White')},
'black':{'foreground':'#ffffff', 'background':'#000000', 'name':_('Black')},
'sepia-light':{'foreground':'#39322B', 'background':'#F6F3E9', 'name':_('Sepia Light')},
'sepia-dark': {'background':'#39322B', 'foreground':'#F6F3E9', 'name':_('Sepia Dark')},
}

View File

@ -9,7 +9,7 @@ from book_list.globals import get_boss
from widgets import create_spinner, create_button
from gettext import gettext as _
from read_book.toc import create_toc_panel
from read_book.prefs import create_prefs_panel
from read_book.prefs.main import create_prefs_panel
class LoadingMessage: # {{{

View File

View File

@ -0,0 +1,186 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import hash_literals, bound_methods
from gettext import gettext as _
from dom import svgicon, set_css, add_extra_css, build_rule, clear, unique_id
from elementmaker import E
from book_list.globals import get_session_data
from read_book.globals import default_color_schemes
from modals import error_dialog
from widgets import create_button
CONTAINER = unique_id('reader-color-scheme')
COLOR_LIST = unique_id()
ACTION_BUTTONS = unique_id()
EDIT_SCHEME = unique_id()
add_extra_css(def():
sel = '#' + COLOR_LIST
style = build_rule(sel, list_style_type='none', display='flex', flex_wrap='wrap')
sel += ' > li'
style += build_rule(sel, padding='1ex 1rem', margin='1ex 0.5rem', border_radius='4px', cursor='pointer', border='solid 1px currentColor')
style += build_rule(sel + ' svg', visibility='hidden')
sel += '.current-color'
style += build_rule(sel + ' svg', visibility='visible')
style += build_rule('#{} #{} td'.format(CONTAINER, EDIT_SCHEME), padding='1ex 1em')
sel = '#' + ACTION_BUTTONS
style += sel + '{margin-top:2ex; padding-top:1ex; border-top: solid 1px currentColor; margin-bottom: 2ex; padding-bottom: 1ex; border-bottom: solid 1px currentColor}'
style += build_rule(sel + ' > span ', margin='1ex 0.5rem', display='inline-block')
return style
)
def get_container():
return document.getElementById(CONTAINER)
def change_current_color(ev):
ul = ev.currentTarget.parentNode
for li in ul.childNodes:
li.setAttribute('class', 'current-color' if li is ev.currentTarget else '')
set_action_button_visibility(ul.parentNode)
def new_color_scheme(ev):
container = get_container()
container.lastChild.style.display = 'block'
for inp in container.lastChild.querySelectorAll('input'):
n = inp.getAttribute('name')
inp.value = {'name':'', 'bg':'#ffffff', 'fg':'#000000'}[n]
container.lastChild.querySelector('input').focus()
return container
def edit_color_scheme(ev):
container = new_color_scheme(ev)
ccs = current_color_scheme(container)
all_schemes = all_color_schemes()
if all_schemes[ccs]:
container = document.getElementById(EDIT_SCHEME)
container.querySelector('input').value = all_schemes[ccs].name
container.querySelector('input[name=bg]').value = all_schemes[ccs].background
container.querySelector('input[name=fg]').value = all_schemes[ccs].foreground
def remove_color_scheme(ev):
ccs = current_color_scheme()
if default_color_schemes[ccs]:
return error_dialog(_('Cannot remove'), _('Cannot remove a builtin color scheme'))
sd = get_session_data()
ucs = sd.get('user_color_schemes')
v'delete ucs[ccs]'
sd.set('user_color_schemes', ucs)
create_color_buttons()
set_current_color_scheme()
def current_color_scheme():
return get_container().querySelector('li.current-color').getAttribute('data-name')
def set_current_color_scheme(value):
ul = document.getElementById(COLOR_LIST)
done = False
for li in ul.childNodes:
li.classList.remove('current-color')
if li.getAttribute('data-name') is value:
li.classList.add('current-color')
done = True
if not done:
for li in ul.childNodes:
li.classList.add('current-color')
break
set_action_button_visibility()
def add_color_scheme(ev):
div = document.getElementById(EDIT_SCHEME)
if this is not 'cancel':
name = div.querySelector('input[name=name]').value
if not name:
error_dialog(_('Name not specified'), _(
'You must specify a name for the color scheme'))
return
bg = div.querySelector('input[name=bg]').value
fg = div.querySelector('input[name=fg]').value
for col in (bg, fg):
if not /^#[0-9A-F]{6}$/i.test(bg):
error_dialog(_('Invalid color'), _(
'The color {} is not a valid color').format(col))
return
key = '*' + name
sd = get_session_data()
ucs = sd.get('user_color_schemes')
ucs[key] = {'name':name, 'foreground':fg, 'background':bg}
sd.set('user_color_schemes', ucs)
create_color_buttons()
set_current_color_scheme(key)
div.style.display = 'none'
def all_color_schemes():
all_schemes = {}
for k in default_color_schemes:
all_schemes[k] = default_color_schemes[k]
sd = get_session_data()
ucs = sd.get('user_color_schemes')
for k in ucs:
all_schemes[k] = ucs[k]
return all_schemes
def create_color_buttons():
ul = document.getElementById(COLOR_LIST)
sd = get_session_data()
clear(ul)
all_schemes = all_color_schemes()
ccs = sd.get('current_color_scheme')
for name in sorted(all_schemes, key=def(k):return all_schemes[k].name.toLowerCase();):
scheme = all_schemes[name]
item = set_css(E.li(svgicon('check'), '\xa0' + scheme.name, data_name=name, onclick=change_current_color,
class_='current-color' if name is ccs else ''),
color=scheme.foreground, background_color=scheme.background)
ul.appendChild(item)
def set_action_button_visibility():
container = get_container()
ccs = current_color_scheme(container)
is_custom = ccs.startswith('*')
is_first = True
for button in container.querySelectorAll('#' + ACTION_BUTTONS + ' > span'):
if is_first:
is_first = False
else:
button.style.display = 'inline-block' if is_custom else 'none'
def create_colors_panel(container):
container.appendChild(E.div(id=CONTAINER))
container = container.lastChild
container.appendChild(E.p(_('Choose a color scheme below'), style='margin:1ex 1em; padding: 1ex 0'))
ul = E.ul(id=COLOR_LIST)
container.appendChild(ul)
create_color_buttons()
container.appendChild(E.div(
E.span(create_button(_('New scheme'), 'plus', new_color_scheme)),
E.span(create_button(_('Edit scheme'), 'pencil', edit_color_scheme)),
E.span(create_button(_('Remove scheme'), 'trash', remove_color_scheme)),
id=ACTION_BUTTONS,
))
container.appendChild(E.div(id=EDIT_SCHEME, style='display:none',
E.table(
E.tr(E.td(_('Name:')), E.td(E.input(name='name'))),
E.tr(E.td(_('Background:')), E.td(E.input(name='bg', type='color', value='#ffffff'))),
E.tr(E.td(_('Foreground:')), E.td(E.input(name='fg', type='color', value='#000000'))),
),
E.div(style="display:flex; justify-content: flex-end; margin: 1ex 1em",
create_button(_('OK'), 'check', add_color_scheme), E.span('\xa0'), create_button(_('Cancel'), 'close', add_color_scheme.bind('cancel'))
)))
set_action_button_visibility()
develop = create_colors_panel
def commit_colors(onchange):
ccs = current_color_scheme()
sd = get_session_data()
if sd.get('current_color_scheme') is not ccs:
sd.set('current_color_scheme', ccs)
onchange()

View File

@ -3,57 +3,11 @@
from __python__ import hash_literals, bound_methods
from gettext import gettext as _
from dom import svgicon, ensure_id, clear, set_css, add_extra_css, build_rule
from dom import svgicon, ensure_id, clear
from elementmaker import E
from book_list.item_list import build_list, create_item
from book_list.globals import get_session_data
from read_book.globals import default_color_schemes
from read_book.prefs.colors import create_colors_panel, commit_colors
# Colors {{{
add_extra_css(def():
sel = 'ul.color-preferences-list'
style = build_rule(sel, list_style_type='none', display='flex', flex_wrap='wrap')
sel += ' > li'
style += build_rule(sel, padding='1ex 1rem', margin='1ex 1rem', border_radius='4px', cursor='pointer', border='solid 1px currentColor')
style += build_rule(sel + ' svg', visibility='hidden')
sel += '.current-color'
style += build_rule(sel + ' svg', visibility='visible')
return style
)
def change_current_color(ev):
ul = ev.currentTarget.parentNode
for li in ul.childNodes:
li.setAttribute('class', 'current-color' if li is ev.currentTarget else '')
def current_color_scheme(container):
return container.querySelector('li.current-color').getAttribute('data-name')
def create_colors_panel(container):
container.appendChild(E.p(_('Choose a color scheme below'), style='margin:1ex 1em; padding: 1ex 0'))
all_schemes = {}
for k in default_color_schemes:
all_schemes[k] = default_color_schemes[k]
sd = get_session_data()
ucs = sd.get('user_color_schemes')
for k in ucs:
all_schemes[k] = ucs[k]
ul = E.ul(class_='color-preferences-list')
container.appendChild(ul)
for name in sorted(all_schemes, key=def(k):all_schemes[k].name;):
scheme = all_schemes[name]
item = set_css(E.li(svgicon('check'), '\xa0' + scheme.name, data_name=name, onclick=change_current_color,
class_='current-color' if name is sd.get('current_color_scheme') else ''),
color=scheme.foreground, background_color=scheme.background)
ul.appendChild(item)
def commit_colors(onchange, container):
ccs = current_color_scheme(container)
sd = get_session_data()
if sd.get('current_color_scheme') is not ccs:
sd.set('current_color_scheme', ccs)
onchange()
# }}}
class Prefs:
@ -119,6 +73,3 @@ class Prefs:
def create_prefs_panel(container, close_func):
Prefs(container, close_func)
def develop(container):
create_colors_panel(container)