Implement the basic item list panel

This commit is contained in:
Kovid Goyal 2015-11-02 17:05:47 +05:30
parent 9c916a3679
commit d7180443da
5 changed files with 166 additions and 11 deletions

View File

@ -1,7 +1,7 @@
# vim:fileencoding=utf-8
# 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:
@ -10,7 +10,7 @@ class Boss:
self.current_library_id = interface_data['default_library']
self.current_library_name = interface_data['library_map'][self.current_library_id]
self.update_window_title()
self.book_list = BookList(interface_data)
self.ui = UI(interface_data)
def update_window_title(self):
document.title = 'calibre :: ' + self.current_library_name

View 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}

View File

@ -14,4 +14,6 @@ def get_color(name):
def get_font_size(name):
return {
'title': '1.4rem',
'item-list-title': '1.2rem',
'item-list-subtitle': '0.8 rem',
}[name]

View File

@ -81,7 +81,7 @@ class TopBar:
href="javascript:void(0)", title=tooltip,
E.i(class_='fa fa-' + icon_name)
))
a = right.firstChild
a = right.lastChild
if bar is self.bar:
if action is not None:
a.addEventListener('click', def(event): event.preventDefault(), action();)

View File

@ -1,9 +1,11 @@
# vim:fileencoding=utf-8
# 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.top_bar import TopBar
from book_list.views import BooksView
from book_list.item_list import ItemsView, create_item
from dom import set_css
from gettext import gettext as _
from utils import debounce
@ -17,21 +19,94 @@ class BarState:
def add_button(self, **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):
set_css(document.body, background_color=get_color('window-background'))
self.states = []
self.initial_bar_state = ibs = BarState(run_animation=True)
self.states, self.panels = [], []
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='search', tooltip=_('Search for books'))
ibs.add_button(icon_name='bars', tooltip=_('More actions'))
self.states.append(ibs)
self.top_bar = TopBar()
self.top_bar.apply_state(ibs.left_state, ibs.buttons)
self.books_view = BooksView(interface_data)
ibs.add_button(icon_name='ellipsis-v', tooltip=_('More actions'), action=show_panel_action('more-actions-menu'))
self.states.append(UIState(ibs, self.books_view))
self.apply_state(self.states[0])
ibs.left_state.run_animation = False
window.addEventListener('resize', debounce(bind(self.on_resize, self), 250))
self.panels = v'[self.books_view, self.items_view]'
def on_resize(self):
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])