mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Allow creation of custom styles
This commit is contained in:
parent
fdc3c82dbf
commit
081c14c18a
@ -7,7 +7,7 @@ from gettext import gettext as _
|
||||
|
||||
from book_list.globals import get_session_data
|
||||
from book_list.theme import get_color
|
||||
from dom import unique_id
|
||||
from dom import svgicon, unique_id
|
||||
from widgets import create_button
|
||||
|
||||
ICON_SIZE_VAL = 3
|
||||
@ -56,8 +56,12 @@ def all_builtin_styles():
|
||||
all_style_keys = v"'type kind which background-color text-decoration-line text-decoration-color text-decoration-style'.split(' ')"
|
||||
|
||||
|
||||
def custom_color_theme(bg):
|
||||
return {'type': 'custom', 'kind': 'color', 'which': bg}
|
||||
def custom_color_theme(lightbg, darkbg):
|
||||
return {'type': 'custom', 'kind': 'color', 'light': lightbg, 'dark': darkbg}
|
||||
|
||||
|
||||
def custom_decoration_theme(line_position, line_style, line_color):
|
||||
return {'type': 'custom', 'kind': 'decoration', 'text-decoration-line': line_position, 'text-decoration-style': line_style, 'text-decoration-color': line_color}
|
||||
|
||||
|
||||
class HighlightStyle:
|
||||
@ -78,6 +82,8 @@ class HighlightStyle:
|
||||
tdl = tds = tdc = None
|
||||
if s.type is 'builtin':
|
||||
q = builtin_decorations_dark[s.which] if is_dark else builtin_decorations_dark[s.which]
|
||||
else:
|
||||
q = s
|
||||
tdl = q['text-decoration-line'] or None
|
||||
tds = q['text-decoration-style'] or None
|
||||
tdc = q['text-decoration-color'] or None
|
||||
@ -98,8 +104,9 @@ class HighlightStyle:
|
||||
|
||||
bg = None
|
||||
if s.type is 'builtin':
|
||||
if s.kind is 'color':
|
||||
bg = builtin_color(s.which, is_dark)
|
||||
elif s.type is 'custom':
|
||||
bg = s.dark if is_dark else s.light
|
||||
if bg is None and s['background-color']:
|
||||
bg = s['background-color']
|
||||
if bg:
|
||||
@ -111,11 +118,13 @@ class HighlightStyle:
|
||||
if s.kind is 'decoration':
|
||||
if s.type is 'builtin':
|
||||
defs = builtin_decorations_dark[s.which] if is_dark else builtin_decorations_light[s.which]
|
||||
else:
|
||||
defs = s
|
||||
return defs['text-decoration-color'] or 'red'
|
||||
return 'red'
|
||||
if s.type is 'builtin':
|
||||
if s.kind is 'color':
|
||||
return builtin_color(s.which, is_dark)
|
||||
if s.type is 'custom':
|
||||
return s.dark if is_dark else s.light
|
||||
return s['background-color'] or default_color(is_dark)
|
||||
|
||||
def serialized(self):
|
||||
@ -139,12 +148,12 @@ def highlight_style_as_css(s, is_dark, foreground):
|
||||
set('text-decoration-style', keys['text-decoration-style'])
|
||||
return
|
||||
|
||||
bg = fg = None
|
||||
bg = None
|
||||
fg = foreground or None
|
||||
if s.type is 'builtin':
|
||||
if s.kind is 'color':
|
||||
bg = builtin_color(s.which, is_dark)
|
||||
if foreground:
|
||||
fg = foreground
|
||||
elif s.type is 'custom':
|
||||
bg = s.dark if is_dark else s.light
|
||||
set('background-color', bg or s['background-color'] or default_color(is_dark))
|
||||
set('color', fg or s.color or foreground)
|
||||
|
||||
@ -164,6 +173,105 @@ def custom_styles_equal(a, b):
|
||||
return True
|
||||
|
||||
|
||||
class AddStyle: # {{{
|
||||
|
||||
def __init__(self, get_container, hide_self):
|
||||
self.get_container = get_container
|
||||
self.hide_self = hide_self
|
||||
get_container().appendChild(E.div(
|
||||
style='margin: 1rem; text-align: left',
|
||||
E.h4(_('Choose the type of style you want to add')),
|
||||
E.div('\xa0'),
|
||||
E.div(
|
||||
E.label(E.input(type='radio', name='style_type', value='color', onchange=self.change_type, checked=True), _('Color')),
|
||||
'\xa0\xa0',
|
||||
E.label(E.input(type='radio', name='style_type', value='decoration', onchange=self.change_type), _('Underline')),
|
||||
),
|
||||
|
||||
E.div(
|
||||
name='color-container',
|
||||
style='margin-top:1rem; border-top: solid; padding-top: 1rem',
|
||||
E.div(E.label(_('Color for light color themes: '), E.input(type='color', name='light_color', value='#ffff00'))),
|
||||
E.div('\xa0'),
|
||||
E.div(E.label(_('Color for dark color themes: '), E.input(type='color', name='dark_color', value='#cccc00'))),
|
||||
),
|
||||
|
||||
E.div(
|
||||
name='decoration-container',
|
||||
style='margin-top:1rem; border-top: solid; padding-top: 1rem',
|
||||
E.div(
|
||||
_('Color for the line: '),
|
||||
E.label(E.input(type='radio', name='color_type', value='currentColor', checked=True), _('Text color')),
|
||||
'\xa0',
|
||||
E.label(E.input(type='radio', name='color_type', value='custom_color'), _('Custom color:')),
|
||||
'\xa0',
|
||||
E.input(type='color', name='decoration_color', value='#ff0000', onchange=def():
|
||||
self.get_container().querySelector('input[value=custom_color]').checked = True
|
||||
)
|
||||
),
|
||||
E.div('\xa0'),
|
||||
E.div(
|
||||
E.label(_('Position of line: '), E.select(name='text_decoration_line',
|
||||
E.option(_('Underline'), value='underline'),
|
||||
E.option(_('Over-line'), value='overline'),
|
||||
E.option(_('Strikeout'), value='strike-through'),
|
||||
))
|
||||
),
|
||||
E.div('\xa0'),
|
||||
E.div(
|
||||
E.label(_('Style of line: '), E.select(name='text_decoration_style',
|
||||
E.option(_('Solid'), value='solid'),
|
||||
E.option(_('Double'), value='double'),
|
||||
E.option(_('Dotted'), value='dotted'),
|
||||
E.option(_('Dashed'), value='dashed'),
|
||||
E.option(_('Wavy'), value='wavy'),
|
||||
))
|
||||
),
|
||||
),
|
||||
E.div(
|
||||
style='margin-top:1rem; border-top: solid; padding-top: 1rem; display: flex; width: 100%; justify-content: space-between',
|
||||
create_button(_('Discard'), 'close', def(ev):
|
||||
ev.stopPropagation()
|
||||
hide_self(None)
|
||||
),
|
||||
create_button(_('Save'), 'check', def(ev):
|
||||
ev.stopPropagation()
|
||||
hide_self(self.created_style)
|
||||
),
|
||||
),
|
||||
))
|
||||
self.change_type()
|
||||
|
||||
@property
|
||||
def style_type(self):
|
||||
return self.get_container().querySelector('input[name=style_type]:checked').value
|
||||
|
||||
@property
|
||||
def color_type(self):
|
||||
return self.get_container().querySelector('input[name=color_type]:checked').value
|
||||
|
||||
def change_type(self):
|
||||
c = self.get_container()
|
||||
q = self.style_type
|
||||
c.querySelector('[name=color-container]').style.display = 'block' if q is 'color' else 'none'
|
||||
c.querySelector('[name=decoration-container]').style.display = 'block' if q is 'decoration' else 'none'
|
||||
|
||||
@property
|
||||
def created_style(self):
|
||||
c = self.get_container()
|
||||
if self.style_type is 'color':
|
||||
return custom_color_theme(c.querySelector('input[name=light_color]').value, c.querySelector('input[name=dark_color]').value)
|
||||
if self.color_type is 'currentColor':
|
||||
col = 'currentColor'
|
||||
else:
|
||||
col = c.querySelector('input[name=decoration_color]').value
|
||||
return custom_decoration_theme(
|
||||
c.querySelector('select[name=text_decoration_line]').value,
|
||||
c.querySelector('select[name=text_decoration_style]').value,
|
||||
col)
|
||||
# }}}
|
||||
|
||||
|
||||
class EditNotesAndColors: # {{{
|
||||
|
||||
def __init__(self, container, is_dark_theme, current_notes, current_style, annot_id, close_editor):
|
||||
@ -197,7 +305,7 @@ class EditNotesAndColors: # {{{
|
||||
c = E.div(
|
||||
style=f'background: {get_color("window-background")}; margin: auto; text-align: center; padding: 1ex;',
|
||||
onclick=def(ev): ev.stopPropagation();,
|
||||
id=unique_id(),
|
||||
id=unique_id(), E.div(
|
||||
E.textarea(
|
||||
current_notes or '',
|
||||
placeholder=_('Add notes for this highlight. Double click or long tap on a highlight to read its notes.'),
|
||||
@ -215,11 +323,13 @@ class EditNotesAndColors: # {{{
|
||||
E.span('\xa0'),
|
||||
remove_button, apply_button
|
||||
),
|
||||
)
|
||||
))
|
||||
self.container_id = c.id
|
||||
container.appendChild(c)
|
||||
container.style.maxWidth = '40rem'
|
||||
container.style.width = '90%'
|
||||
c.appendChild(E.div(style='display:none'))
|
||||
self.add_style = AddStyle(def(): return self.container.lastChild;, self.hide_add_style)
|
||||
self.seen_colors = {}
|
||||
custom_highlight_styles = get_session_data().get('custom_highlight_styles')
|
||||
for raw in custom_highlight_styles:
|
||||
@ -228,10 +338,38 @@ class EditNotesAndColors: # {{{
|
||||
self.add_color(HighlightStyle(raw))
|
||||
if not c.querySelector('.current-swatch'):
|
||||
self.add_color(self.initial_style, True)
|
||||
parent = c.getElementsByClassName('color-block')[0]
|
||||
parent.appendChild(E.div(
|
||||
svgicon('plus', ICON_SIZE, ICON_SIZE),
|
||||
style='padding: 4px; margin: 4px;',
|
||||
title=_('Add a new highlight style'),
|
||||
class_='simple-link',
|
||||
onclick=def(ev):
|
||||
ev.stopPropagation()
|
||||
c = self.container
|
||||
c.firstChild.style.display = 'none'
|
||||
c.lastChild.style.display = 'block'
|
||||
))
|
||||
|
||||
self.set_visibility_of_remove_button()
|
||||
window.setTimeout(self.notes_edit.focus.bind(self.notes_edit), 0)
|
||||
|
||||
def hide_add_style(self, new_style):
|
||||
c = self.container
|
||||
c.firstChild.style.display = 'block'
|
||||
c.lastChild.style.display = 'none'
|
||||
if new_style:
|
||||
self.add_new_style(new_style)
|
||||
|
||||
def add_new_style(self, new_style):
|
||||
item = self.add_color(HighlightStyle(new_style), True)
|
||||
item.classList.add('custom-style')
|
||||
self.make_swatch_current(item)
|
||||
sd = get_session_data()
|
||||
custom_highlight_styles = sd.get('custom_highlight_styles')
|
||||
custom_highlight_styles.unshift(new_style)
|
||||
sd.set('custom_highlight_styles', custom_highlight_styles)
|
||||
|
||||
def set_visibility_of_remove_button(self):
|
||||
c = self.container
|
||||
item = c.querySelector('.current-swatch.custom-style')
|
||||
@ -260,17 +398,6 @@ class EditNotesAndColors: # {{{
|
||||
parent.appendChild(item)
|
||||
return item
|
||||
|
||||
def add_custom_color(self):
|
||||
bg = self.container.querySelector('input[type=color]').value
|
||||
cct = custom_color_theme(bg)
|
||||
item = self.add_color(HighlightStyle(cct), True)
|
||||
item.classList.add('custom-style')
|
||||
self.make_swatch_current(item)
|
||||
sd = get_session_data()
|
||||
custom_highlight_styles = sd.get('custom_highlight_styles')
|
||||
custom_highlight_styles.unshift(cct)
|
||||
sd.set('custom_highlight_styles', custom_highlight_styles)
|
||||
|
||||
def remove_custom_color(self):
|
||||
item = self.container.getElementsByClassName('current-swatch')[0]
|
||||
cct = JSON.parse(item.dataset.style)
|
||||
|
@ -30,7 +30,7 @@ create_button.style = build_rule('a.calibre-push-button',
|
||||
border_radius='1em', background_clip='padding-box', background_color=get_color('button-start'),
|
||||
background_image='linear-gradient(to bottom, {}, {})'.format(get_color('button-start'), get_color('button-end')),
|
||||
padding='0.5ex 1em', color=get_color('button-text'), cursor='pointer', font_size='inherit', display='inline-flex',
|
||||
align_items='center',
|
||||
align_items='center', user_select='none',
|
||||
box_shadow='0px 2px 1px rgba(50, 50, 50, 0.75)', white_space='nowrap'
|
||||
)
|
||||
create_button.style += build_rule('a.calibre-push-button:hover', transform='scale(1.05)')
|
||||
|
Loading…
x
Reference in New Issue
Block a user