mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement the basic item list panel
This commit is contained in:
parent
9c916a3679
commit
d7180443da
@ -1,7 +1,7 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
from book_list.ui import BookList
|
from book_list.ui import UI
|
||||||
|
|
||||||
class Boss:
|
class Boss:
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ class Boss:
|
|||||||
self.current_library_id = interface_data['default_library']
|
self.current_library_id = interface_data['default_library']
|
||||||
self.current_library_name = interface_data['library_map'][self.current_library_id]
|
self.current_library_name = interface_data['library_map'][self.current_library_id]
|
||||||
self.update_window_title()
|
self.update_window_title()
|
||||||
self.book_list = BookList(interface_data)
|
self.ui = UI(interface_data)
|
||||||
|
|
||||||
def update_window_title(self):
|
def update_window_title(self):
|
||||||
document.title = 'calibre :: ' + self.current_library_name
|
document.title = 'calibre :: ' + self.current_library_name
|
||||||
|
78
src/pyj/book_list/item_list.pyj
Normal file
78
src/pyj/book_list/item_list.pyj
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from dom import build_rule
|
||||||
|
from elementmaker import E
|
||||||
|
|
||||||
|
from book_list.theme import get_font_size, get_color
|
||||||
|
|
||||||
|
iv_counter = 0
|
||||||
|
|
||||||
|
class ItemsView:
|
||||||
|
|
||||||
|
def __init__(self, interface_data):
|
||||||
|
nonlocal iv_counter
|
||||||
|
iv_counter += 1
|
||||||
|
self.container_id = 'items-view-' + iv_counter
|
||||||
|
style = ''
|
||||||
|
cid = '#' + self.container_id
|
||||||
|
style += build_rule(cid + ' li', padding='1em', border_bottom='solid 1px ' + get_color('window-foreground'), border_top='solid 1px ' + get_color('window-background'), cursor='pointer', list_style='none')
|
||||||
|
style += build_rule(cid + ' .title', font_size=get_font_size('item-list-title'))
|
||||||
|
style += build_rule(cid + ' .subtitle', font_size=get_font_size('item-list-subtitle'), font_style='italic')
|
||||||
|
style += build_rule(cid + ' li:hover', color=get_color('bar-foreground'), background_color=get_color('bar-background'), border_top_color=get_color('bar-foreground'))
|
||||||
|
style += build_rule(cid + ' li:active', color=get_color('bar-highlight'))
|
||||||
|
self.base_style = style
|
||||||
|
div = E.div(
|
||||||
|
id=self.container_id, style='display:none',
|
||||||
|
E.style(style, type='text/css')
|
||||||
|
)
|
||||||
|
document.body.appendChild(div)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def container(self):
|
||||||
|
return document.getElementById(self.container_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_visible(self):
|
||||||
|
self.container.style.display == 'block'
|
||||||
|
|
||||||
|
@is_visible.setter
|
||||||
|
def is_visible(self, val):
|
||||||
|
self.container.style.display = 'block' if val else 'none'
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
c = self.container
|
||||||
|
while c.lastChild is not c.firstChild:
|
||||||
|
c.removeChild(c.lastChild)
|
||||||
|
return c
|
||||||
|
|
||||||
|
def init(self, data):
|
||||||
|
items = getattr(data, 'items', data)
|
||||||
|
subtitle = getattr(data, 'subtitle', None)
|
||||||
|
c = self.clear()
|
||||||
|
if subtitle:
|
||||||
|
c.appendChild(E.p(subtitle))
|
||||||
|
ul = E.ul()
|
||||||
|
c.appendChild(ul)
|
||||||
|
has_icons = has_subtitles = False
|
||||||
|
for item in items:
|
||||||
|
if item.icon_name:
|
||||||
|
has_icons = True
|
||||||
|
if item.subtitle:
|
||||||
|
has_subtitles = True
|
||||||
|
if has_icons and has_subtitles:
|
||||||
|
break
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
ul.appendChild(E.li(E.a(href='javascript:void(0)',
|
||||||
|
E.div(item.title, class_='title')
|
||||||
|
)))
|
||||||
|
a = ul.lastChild.firstChild
|
||||||
|
if item.subtitle:
|
||||||
|
a.appendChild(E.div(item.subtitle, class_='subtitle'))
|
||||||
|
if item.action:
|
||||||
|
a.addEventListener('click', def(event): event.preventDefault(), item.action();)
|
||||||
|
|
||||||
|
|
||||||
|
def create_item(title, action=None, subtitle=None, icon_name=None):
|
||||||
|
return {'title':title, 'action':action, 'subtitle':subtitle, 'icon_name':icon_name}
|
@ -14,4 +14,6 @@ def get_color(name):
|
|||||||
def get_font_size(name):
|
def get_font_size(name):
|
||||||
return {
|
return {
|
||||||
'title': '1.4rem',
|
'title': '1.4rem',
|
||||||
|
'item-list-title': '1.2rem',
|
||||||
|
'item-list-subtitle': '0.8 rem',
|
||||||
}[name]
|
}[name]
|
||||||
|
@ -81,7 +81,7 @@ class TopBar:
|
|||||||
href="javascript:void(0)", title=tooltip,
|
href="javascript:void(0)", title=tooltip,
|
||||||
E.i(class_='fa fa-' + icon_name)
|
E.i(class_='fa fa-' + icon_name)
|
||||||
))
|
))
|
||||||
a = right.firstChild
|
a = right.lastChild
|
||||||
if bar is self.bar:
|
if bar is self.bar:
|
||||||
if action is not None:
|
if action is not None:
|
||||||
a.addEventListener('click', def(event): event.preventDefault(), action();)
|
a.addEventListener('click', def(event): event.preventDefault(), action();)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from book_list.globals import get_boss
|
||||||
from book_list.theme import get_color
|
from book_list.theme import get_color
|
||||||
from book_list.top_bar import TopBar
|
from book_list.top_bar import TopBar
|
||||||
from book_list.views import BooksView
|
from book_list.views import BooksView
|
||||||
|
from book_list.item_list import ItemsView, create_item
|
||||||
from dom import set_css
|
from dom import set_css
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from utils import debounce
|
from utils import debounce
|
||||||
@ -17,21 +19,94 @@ class BarState:
|
|||||||
def add_button(self, **kw):
|
def add_button(self, **kw):
|
||||||
self.buttons.push(kw)
|
self.buttons.push(kw)
|
||||||
|
|
||||||
class BookList:
|
class ClosePanelBar(BarState):
|
||||||
|
|
||||||
|
def __init__(self, title, tooltip=''):
|
||||||
|
tooltip = tooltip or _('Close this panel')
|
||||||
|
BarState.__init__(self, title=title, tooltip=tooltip, action=close_panel, icon_name='times')
|
||||||
|
|
||||||
|
class UIState:
|
||||||
|
|
||||||
|
def __init__(self, top_bar_state=None, main_panel=None, panel_data=None):
|
||||||
|
self.top_bar_state = top_bar_state
|
||||||
|
self.main_panel = main_panel or get_boss().ui.items_view
|
||||||
|
self.panel_data = panel_data
|
||||||
|
|
||||||
|
def add_button(self, **kw):
|
||||||
|
self.top_bar_state.add_button(**kw)
|
||||||
|
|
||||||
|
panels = {}
|
||||||
|
|
||||||
|
def panel(key):
|
||||||
|
ans = panels[key]
|
||||||
|
if not ans:
|
||||||
|
ans = panels[key] = create_panel[key]()
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def close_panel():
|
||||||
|
get_boss().ui.close_panel()
|
||||||
|
|
||||||
|
def replace_panel_action(replacement):
|
||||||
|
return def():
|
||||||
|
get_boss().ui.replace_panel(panel(replacement))
|
||||||
|
|
||||||
|
def show_panel_action(key):
|
||||||
|
return def():
|
||||||
|
get_boss().ui.show_panel(panel(key))
|
||||||
|
|
||||||
|
create_panel = {
|
||||||
|
'more-actions-menu': def more_actions_menu():
|
||||||
|
return UIState(ClosePanelBar(_('More actions')), panel_data=[
|
||||||
|
create_item(_('Book List Mode'), replace_panel_action('booklist-mode-menu'), _('Change how the list of books is displayed')),
|
||||||
|
])
|
||||||
|
,
|
||||||
|
|
||||||
|
'booklist-mode-menu': def booklist_mode_menu():
|
||||||
|
return UIState(ClosePanelBar(_('Book List Mode')), panel_data=[
|
||||||
|
])
|
||||||
|
,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UI:
|
||||||
|
|
||||||
def __init__(self, interface_data):
|
def __init__(self, interface_data):
|
||||||
set_css(document.body, background_color=get_color('window-background'))
|
set_css(document.body, background_color=get_color('window-background'))
|
||||||
self.states = []
|
self.states, self.panels = [], []
|
||||||
self.initial_bar_state = ibs = BarState(run_animation=True)
|
self.top_bar = TopBar()
|
||||||
|
self.books_view = BooksView(interface_data)
|
||||||
|
self.items_view = ItemsView(interface_data)
|
||||||
|
ibs = BarState(run_animation=True)
|
||||||
ibs.add_button(icon_name='sort-alpha-asc', tooltip=_('Sort books'))
|
ibs.add_button(icon_name='sort-alpha-asc', tooltip=_('Sort books'))
|
||||||
ibs.add_button(icon_name='search', tooltip=_('Search for books'))
|
ibs.add_button(icon_name='search', tooltip=_('Search for books'))
|
||||||
ibs.add_button(icon_name='bars', tooltip=_('More actions'))
|
ibs.add_button(icon_name='ellipsis-v', tooltip=_('More actions'), action=show_panel_action('more-actions-menu'))
|
||||||
self.states.append(ibs)
|
self.states.append(UIState(ibs, self.books_view))
|
||||||
self.top_bar = TopBar()
|
self.apply_state(self.states[0])
|
||||||
self.top_bar.apply_state(ibs.left_state, ibs.buttons)
|
|
||||||
self.books_view = BooksView(interface_data)
|
|
||||||
ibs.left_state.run_animation = False
|
ibs.left_state.run_animation = False
|
||||||
window.addEventListener('resize', debounce(bind(self.on_resize, self), 250))
|
window.addEventListener('resize', debounce(bind(self.on_resize, self), 250))
|
||||||
|
self.panels = v'[self.books_view, self.items_view]'
|
||||||
|
|
||||||
def on_resize(self):
|
def on_resize(self):
|
||||||
self.books_view.on_resize()
|
self.books_view.on_resize()
|
||||||
|
|
||||||
|
def apply_state(self, state):
|
||||||
|
self.top_bar.apply_state(state.top_bar_state.left_state, state.top_bar_state.buttons)
|
||||||
|
for panel in self.panels:
|
||||||
|
panel.is_visible = panel is state.main_panel
|
||||||
|
if callable(state.main_panel.init):
|
||||||
|
state.main_panel.init(state.panel_data)
|
||||||
|
|
||||||
|
def close_panel(self):
|
||||||
|
if len(self.states) > 1:
|
||||||
|
self.states.pop()
|
||||||
|
self.apply_state(self.states[-1])
|
||||||
|
|
||||||
|
def replace_panel(self, state):
|
||||||
|
if len(self.states) > 1:
|
||||||
|
self.states.pop()
|
||||||
|
self.states.append(state)
|
||||||
|
self.apply_state(self.states[-1])
|
||||||
|
|
||||||
|
def show_panel(self, state):
|
||||||
|
self.states.append(state)
|
||||||
|
self.apply_state(self.states[-1])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user