Skip to content

Commit

Permalink
Table of Contents
Browse files Browse the repository at this point in the history
  • Loading branch information
baskerville committed Feb 16, 2018
1 parent 3e522c6 commit 9546b52
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 34 deletions.
2 changes: 1 addition & 1 deletion doc/MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Gestures by region:
- hold: previous chapter.
- *B*:
- tap: toggle the top and bottom bars.
- hold: take screenshot.
- hold: perform a full screen refresh.
- *N*:
- tap: next page.
- hold: next chapter.
Expand Down
1 change: 0 additions & 1 deletion doc/TODO.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
- Search text within document.
- Add, remove, rename categories.
- Table of contents view.
- Pocket articles.
- Landscape mode.
- Fit to width. Repage.
Expand Down
11 changes: 8 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ pub fn run() -> Result<()> {
context.metadata.append(&mut metadata.unwrap());
}
}
view.handle_event(&Event::Back, &tx, &mut bus, &mut context);
view.handle_event(&Event::Reseed, &tx, &mut bus, &mut context);
} else {
context.plugged = false;
tx.send(Event::BatteryTick).unwrap();
Expand Down Expand Up @@ -303,7 +303,7 @@ pub fn run() -> Result<()> {
},
Event::Mount => {
if !context.mounted {
if let Some(v) = history.pop() {
while let Some(v) = history.pop() {
view.handle_event(&Event::Back, &tx, &mut bus, &mut context);
view = v;
}
Expand Down Expand Up @@ -382,11 +382,16 @@ pub fn run() -> Result<()> {
handle_event(view.as_mut(), &Event::Invalid(info2), &tx, &mut bus, &mut context);
}
},
Event::OpenToc(ref toc, current_page) => {
let r = Reader::from_toc(fb_rect, toc, current_page, &tx, &mut context);
history.push(view as Box<View>);
view = Box::new(r) as Box<View>;
},
Event::Back => {
if let Some(v) = history.pop() {
view = v;
view.handle_event(&Event::Reseed, &tx, &mut bus, &mut context);
}
view.handle_event(&evt, &tx, &mut bus, &mut context);
},
Event::Show(ViewId::Frontlight) => {
if !context.settings.frontlight {
Expand Down
2 changes: 1 addition & 1 deletion src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn toc_as_html(toc: &[TocEntry], index: usize) -> String {
pub fn toc_as_html_aux(toc: &[TocEntry], buf: &mut String, chap: Option<&TocEntry>) {
buf.push_str("<ul>");
for entry in toc {
buf.push_str(&format!(r##"<li><a href="#{}">"##, entry.page));
buf.push_str(&format!(r#"<li><a href="@{}">"#, entry.page));
let title = entry.title.replace('<', "&lt;").replace('>', "&gt;");
if chap.is_some() && ptr::eq(entry, chap.unwrap()) {
buf.push_str(&format!("<strong>{}</strong>", title));
Expand Down
7 changes: 6 additions & 1 deletion src/emulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,16 @@ pub fn run() -> Result<()> {
handle_event(view.as_mut(), &Event::Invalid(info2), &tx, &mut bus, &mut context);
}
},
Event::OpenToc(ref toc, current_page) => {
let r = Reader::from_toc(fb_rect, toc, current_page, &tx, &mut context);
history.push(view as Box<View>);
view = Box::new(r) as Box<View>;
},
Event::Back => {
if let Some(v) = history.pop() {
view = v;
view.handle_event(&Event::Reseed, &tx, &mut bus, &mut context);
}
view.handle_event(&evt, &tx, &mut bus, &mut context);
},
Event::Show(ViewId::Frontlight) => {
if !context.settings.frontlight {
Expand Down
2 changes: 1 addition & 1 deletion src/view/home/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,7 @@ impl View for Home {
self.set_current_page(dir, hub);
true
},
Event::Back => {
Event::Reseed => {
self.reseed(hub, context);
true
},
Expand Down
3 changes: 3 additions & 0 deletions src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use std::fmt::{self, Debug};
use fnv::FnvHashMap;
use downcast_rs::Downcast;
use font::Fonts;
use document::TocEntry;
use metadata::{Info, SortMethod, Margin};
use framebuffer::{Framebuffer, UpdateMode};
use input::{DeviceEvent, FingerStatus};
Expand Down Expand Up @@ -188,6 +189,7 @@ pub enum Event {
Keyboard(KeyboardEvent),
Key(KeyKind),
Open(Box<Info>),
OpenToc(Vec<TocEntry>, usize),
Invalid(Box<Info>),
Remove(Box<Info>),
Page(CycleDir),
Expand Down Expand Up @@ -219,6 +221,7 @@ pub enum Event {
Mount,
Validate,
Cancel,
Reseed,
Back,
Quit,
}
Expand Down
117 changes: 98 additions & 19 deletions src/view/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod margin_cropper;
mod viewer;

use std::rc::Rc;
use std::path::PathBuf;
use chrono::Local;
use regex::Regex;
use input::FingerStatus;
Expand All @@ -23,8 +24,9 @@ use view::filler::Filler;
use view::named_input::NamedInput;
use view::keyboard::{Keyboard, DEFAULT_LAYOUT};
use view::menu::{Menu, MenuKind};
use document::{Document, open, chapter_at, chapter_relative};
use metadata::{Info, ReaderInfo, Margin};
use document::{Document, TocEntry, open, toc_as_html, chapter_at, chapter_relative};
use document::pdf::PdfOpener;
use metadata::{Info, FileInfo, ReaderInfo, Margin};
use geom::{Rectangle, CycleDir, halves};
use color::BLACK;
use app::Context;
Expand All @@ -39,6 +41,7 @@ pub struct Reader {
pages_count: usize,
page_turns: usize,
finished: bool,
ephemeral: bool,
refresh_every: Option<u8>,
focus: Option<ViewId>,
}
Expand Down Expand Up @@ -84,13 +87,14 @@ impl Reader {
let margin = info.reader.as_ref()
.and_then(|r| r.margin_at(current_page))
.cloned().unwrap_or_default();
let pixmap = Rc::new(build_pixmap(&rect, doc.as_ref(), current_page, &margin));
let (pixmap, scale) = build_pixmap(&rect, doc.as_ref(), current_page, &margin);
let frame = rect![(margin.left * pixmap.width as f32).ceil() as i32,
(margin.top * pixmap.height as f32).ceil() as i32,
((1.0 - margin.right) * pixmap.width as f32).floor() as i32,
((1.0 - margin.bottom) * pixmap.height as f32).floor() as i32];

let viewer = Viewer::new(rect, pixmap.clone(), frame, UpdateMode::Partial);
let pixmap = Rc::new(pixmap);
let viewer = Viewer::new(rect, doc.links(current_page).unwrap_or_default(),
pixmap.clone(), frame, scale, UpdateMode::Partial);
children.push(Box::new(viewer) as Box<View>);

hub.send(Event::Render(rect, UpdateMode::Partial)).unwrap();
Expand All @@ -105,12 +109,64 @@ impl Reader {
pages_count,
page_turns: 0,
finished: false,
ephemeral: false,
refresh_every: settings.refresh_every,
focus: None,
}
})
}

pub fn from_toc(rect: Rectangle, toc: &[TocEntry], mut current_page: usize, hub: &Hub, context: &mut Context) -> Reader {
let mut children = Vec::new();
let html = toc_as_html(toc, current_page);

let info = Info {
title: "Table of Contents".to_string(),
file: FileInfo {
path: PathBuf::from("toc:"),
kind: "html".to_string(),
size: html.len() as u64,
},
.. Default::default()
};

let mut opener = PdfOpener::new().unwrap();
opener.set_user_css("css/toc.css").unwrap();
let doc = opener.open_memory("html", html.as_bytes()).unwrap();
let pages_count = doc.pages_count();

current_page = chapter_at(toc, current_page).and_then(|chap| {
let link_uri = format!("@{}", chap.page);
(0..pages_count).find(|index| doc.links(*index).as_ref()
.and_then(|links| links.iter()
.find(|link| link.uri == link_uri))
.is_some())}).unwrap_or(0);

let (pixmap, scale) = build_pixmap(&rect, &doc, current_page, &Margin::default());
let pixmap = Rc::new(pixmap);
let frame = rect![0, 0, pixmap.width, pixmap.height];
let viewer = Viewer::new(rect, doc.links(current_page).unwrap_or_default(),
pixmap.clone(), frame, scale, UpdateMode::Partial);

children.push(Box::new(viewer) as Box<View>);
hub.send(Event::Render(rect, UpdateMode::Partial)).unwrap();

Reader {
rect,
children,
info,
doc: Box::new(doc) as Box<Document>,
pixmap,
current_page,
pages_count,
page_turns: 0,
finished: false,
ephemeral: true,
refresh_every: context.settings.refresh_every,
focus: None,
}
}

fn go_to_page(&mut self, index: usize, hub: &Hub) {
if index >= self.pages_count {
return;
Expand Down Expand Up @@ -174,14 +230,16 @@ impl Reader {
let margin = self.info.reader.as_ref()
.and_then(|r| r.margin_at(self.current_page))
.cloned().unwrap_or_default();
self.pixmap = Rc::new(build_pixmap(&self.rect, self.doc.as_ref(), self.current_page, &margin));
let (pixmap, scale) = build_pixmap(&self.rect, self.doc.as_ref(), self.current_page, &margin);
self.pixmap = Rc::new(pixmap);
let frame = rect![(margin.left * self.pixmap.width as f32).ceil() as i32,
(margin.top * self.pixmap.height as f32).ceil() as i32,
((1.0 - margin.right) * self.pixmap.width as f32).floor() as i32,
((1.0 - margin.bottom) * self.pixmap.height as f32).floor() as i32];
if let Some(index) = locate::<Viewer>(self) {
let viewer = self.children[index].as_mut().downcast_mut::<Viewer>().unwrap();
viewer.update(self.pixmap.clone(), frame, update_mode, hub);
viewer.update(self.doc.links(self.current_page).unwrap_or_default(),
self.pixmap.clone(), frame, scale, update_mode, hub);
}
}

Expand Down Expand Up @@ -365,10 +423,10 @@ impl Reader {
.and_then(|r| r.margin_at(self.current_page))
.cloned().unwrap_or_default();

let pixmap = build_pixmap(&pixmap_rect,
self.doc.as_ref(),
self.current_page,
&Margin::default());
let (pixmap, _) = build_pixmap(&pixmap_rect,
self.doc.as_ref(),
self.current_page,
&Margin::default());

let margin_cropper = MarginCropper::new(self.rect, pixmap, &margin);
hub.send(Event::Render(*margin_cropper.rect(), UpdateMode::Gui)).unwrap();
Expand Down Expand Up @@ -401,12 +459,28 @@ impl Reader {
self.update_viewer(hub);
}

fn reseed(&mut self, hub: &Hub, context: &mut Context) {
if let Some(index) = locate::<TopBar>(self) {
self.child_mut(index).downcast_mut::<TopBar>().unwrap()
.update_frontlight_icon(hub, context);
}

hub.send(Event::ClockTick).unwrap();
hub.send(Event::BatteryTick).unwrap();
hub.send(Event::Render(self.rect, UpdateMode::Gui)).unwrap();
}

fn quit(&mut self, context: &mut Context) {
if self.ephemeral {
return;
}

if let Some(ref mut r) = self.info.reader {
r.current_page = self.current_page;
r.pages_count = self.pages_count;
r.finished = self.finished;
}

for i in &mut context.metadata {
if i.file.path == self.info.file.path {
*i = self.info.clone();
Expand Down Expand Up @@ -452,12 +526,7 @@ impl View for Reader {
},
Event::Toggle(ViewId::TopBottomBars) => {
self.toggle_bars(context);
let update_mode = if locate::<TopBar>(self).is_some() {
UpdateMode::Gui
} else {
UpdateMode::Full
};
hub.send(Event::Render(self.rect, update_mode)).unwrap();
hub.send(Event::Render(self.rect, UpdateMode::Gui)).unwrap();
true
},
Event::Toggle(ViewId::GoToPage) => {
Expand All @@ -484,6 +553,12 @@ impl View for Reader {
self.toggle_go_to_page(Some(false), hub, &mut context.fonts);
true
},
Event::Show(ViewId::TableOfContents) => {
if self.doc.has_toc() {
hub.send(Event::OpenToc(self.doc.toc().unwrap(), self.current_page)).unwrap();
}
true
},
Event::Show(ViewId::MarginCropper) => {
self.toggle_margin_cropper(true, hub, context);
true
Expand All @@ -503,6 +578,10 @@ impl View for Reader {
}
true
},
Event::Reseed => {
self.reseed(hub, context);
true
},
Event::Select(EntryId::Quit) |
Event::Select(EntryId::Reboot) |
Event::Select(EntryId::StartNickel) |
Expand Down Expand Up @@ -539,12 +618,12 @@ impl View for Reader {
}
}

fn build_pixmap(rect: &Rectangle, doc: &Document, index: usize, margin: &Margin) -> Pixmap {
fn build_pixmap(rect: &Rectangle, doc: &Document, index: usize, margin: &Margin) -> (Pixmap, f32) {
let (width, height) = doc.dims(index).unwrap();
let p_width = (1.0 - (margin.left + margin.right)) * width;
let p_height = (1.0 - (margin.top + margin.bottom)) * height;
let w_ratio = rect.width() as f32 / p_width;
let h_ratio = rect.height() as f32 / p_height;
let scale = w_ratio.min(h_ratio);
doc.pixmap(index, scale).unwrap()
(doc.pixmap(index, scale).unwrap(), scale)
}
9 changes: 8 additions & 1 deletion src/view/reader/top_bar.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use framebuffer::Framebuffer;
use framebuffer::{Framebuffer, UpdateMode};
use metadata::Info;
use gesture::GestureEvent;
use view::{View, Event, Hub, Bus, ViewId, Align};
Expand Down Expand Up @@ -64,6 +64,13 @@ impl TopBar {
children,
}
}

pub fn update_frontlight_icon(&mut self, hub: &Hub, context: &mut Context) {
let name = if context.settings.frontlight { "frontlight" } else { "frontlight-disabled" };
let icon = self.child_mut(4).downcast_mut::<Icon>().unwrap();
icon.name = name.to_string();
hub.send(Event::Render(*icon.rect(), UpdateMode::Gui)).unwrap();
}
}

impl View for TopBar {
Expand Down
Loading

0 comments on commit 9546b52

Please sign in to comment.