From 18754ac18ff9419900460275f4f9f88b61351c8c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 10 Jun 2016 09:40:31 +0530 Subject: [PATCH] Start work on ToC view --- src/pyj/read_book/iframe.pyj | 8 ++++++++ src/pyj/read_book/overlay.pyj | 25 ++++++++++++++++++++++++- src/pyj/read_book/toc.pyj | 21 +++++++++++++++++++++ src/pyj/read_book/view.pyj | 12 ++++++++++++ src/pyj/widgets.pyj | 10 ++++++++-- 5 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/pyj/read_book/toc.pyj diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index 1b99f833ef..5053cfe0c5 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -39,6 +39,7 @@ class IframeBoss: self.handlers = { 'initialize':self.initialize, 'display': self.display, + 'scroll_to_anchor': self.on_scroll_to_anchor, } self.last_window_ypos = 0 @@ -105,6 +106,13 @@ class IframeBoss: root_data, self.mathjax = finalize_resources(self.book, data.name, data.resource_data) unserialize_html(root_data, self.content_loaded) + def on_scroll_to_anchor(self, data): + frag = data.frag + if frag: + self.scroll_to_anchor(frag) + else: + self.to_scroll_fraction(0.0) + def content_loaded(self): document.documentElement.style.overflow = 'hidden' self.do_layout() diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index 630d93b7a5..87b21432dc 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -8,6 +8,7 @@ from book_list.theme import get_color 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 class LoadingMessage: # {{{ @@ -117,7 +118,7 @@ class MainOverlay: # {{{ ), display='flex', align_items='center', flex_wrap='wrap', padding='0 0.5rem', border_bottom='solid 1px currentColor'), set_css(E.ul(class_='item-list', # list of items - E.li(_('Table of Contents')), + E.li(_('Table of Contents'), onclick=self.overlay.show_toc), E.li(_('Bookmarks')), E.li(_('Go to a specific location in the book')), ), list_style_type='none'), @@ -183,6 +184,23 @@ class MainOverlay: # {{{ # }}} +class TOCOverlay: # {{{ + + def __init__(self, overlay): + self.overlay = overlay + + def on_container_click(self, evt): + pass # Dont allow panel to be closed by a click + + def show(self, container): + container.style.backgroundColor = get_color('window-background') + create_toc_panel(self.overlay.view.book, container, self.handle_activate) + + def handle_activate(self, dest, frag): + self.overlay.hide() + self.overlay.view.goto_named_destination(dest, frag) +# }}} + class Overlay: def __init__(self, view): @@ -249,3 +267,8 @@ class Overlay: self.hide_current_panel() self.panels = [DeleteBook(self, _('Are you sure you want to reload this book?'), 'refresh', _('Reload book'), True)] self.show_current_panel() + + def show_toc(self): + self.hide_current_panel() + self.panels.push(TOCOverlay(self)) + self.show_current_panel() diff --git a/src/pyj/read_book/toc.pyj b/src/pyj/read_book/toc.pyj new file mode 100644 index 0000000000..3a0a017c3a --- /dev/null +++ b/src/pyj/read_book/toc.pyj @@ -0,0 +1,21 @@ +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2016, Kovid Goyal +from __python__ import hash_literals + +from widgets import create_tree + +def create_toc_tree(toc, onclick): + + def populate_data(node, li, a): + li.dataset.tocDest = node.dest or '' + li.dataset.tocFrag = node.frag or '' + a.textContent = node.title or '' + + return create_tree(toc, populate_data, onclick) + +def create_toc_panel(book, container, onclick): + def handle_click(event, li): + if event.button is 0: + onclick(li.dataset.tocDest, li.dataset.tocFrag) + toc_panel = create_toc_tree(book.manifest.toc, handle_click) + container.appendChild(toc_panel) diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index d0ad301117..38f340aaff 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -205,6 +205,18 @@ class View: def on_scroll_to_anchor(self, data): self.show_name(data.name, initial_position={'type':'anchor', 'anchor':data.frag, 'replace_history':False}) + def goto_named_destination(self, name, frag): + if self.currently_showing.name is name: + self.send_message('scroll_to_anchor', frag=frag) + else: + spine = self.book.manifest.spine + idx = spine.indexOf(name) + if idx is -1: + self.ui.show_error(_('Destination does not exist'), _( + 'The file {} does not exist in this book').format(name)) + return + self.show_name(name, initial_position={'type':'anchor', 'anchor':frag, 'replace_history':False}) + def on_next_spine_item(self, data): spine = self.book.manifest.spine idx = spine.indexOf(self.currently_showing.name) diff --git a/src/pyj/widgets.pyj b/src/pyj/widgets.pyj index 9a67414616..a91f5f2b7e 100644 --- a/src/pyj/widgets.pyj +++ b/src/pyj/widgets.pyj @@ -95,7 +95,7 @@ class Breadcrumbs: return li def create_tree(root, populate_data, onclick): - container = E.div() + container = E.div(class_='simple-tree') set_css(container, overflow='auto') def toggle_node(li): @@ -122,7 +122,7 @@ def create_tree(root, populate_data, onclick): href='javascript: void(0)', onclick=def (event): if onclick: - onclick(event.currentTarget.parentNode.parentNode) + onclick(event, event.currentTarget.parentNode.parentNode) ), ), E.div(style='display:none'), @@ -141,9 +141,15 @@ def create_tree(root, populate_data, onclick): process_node(root, container, 0) return container +create_tree.style = ''' +div.simple-tree a:hover { color: red; } +div.simple-tree a:active { transform: scale(1.5); } +''' + def get_widget_css(): ans = 'a, button:focus { outline: none }; a, button::-moz-focus-inner { border: 0 }\n' ans += create_button.style ans += create_spinner.style ans += Breadcrumbs.STYLE_RULES + ans += create_tree.style return ans