Fix continuous page seeking
This commit is contained in:
parent
f0d5cf3496
commit
1b3783b795
1 changed files with 48 additions and 8 deletions
|
|
@ -243,6 +243,7 @@ impl ViewerWindow {
|
||||||
navigation_message,
|
navigation_message,
|
||||||
navigation_message_label,
|
navigation_message_label,
|
||||||
navigation_message_generation: Rc::new(Cell::new(0)),
|
navigation_message_generation: Rc::new(Cell::new(0)),
|
||||||
|
continuous_programmatic_scroll: Cell::new(false),
|
||||||
state: RefCell::new(ViewerState {
|
state: RefCell::new(ViewerState {
|
||||||
pages: Vec::new(),
|
pages: Vec::new(),
|
||||||
anchor: 0,
|
anchor: 0,
|
||||||
|
|
@ -333,6 +334,7 @@ struct ViewerController {
|
||||||
navigation_message: gtk::Box,
|
navigation_message: gtk::Box,
|
||||||
navigation_message_label: gtk::Label,
|
navigation_message_label: gtk::Label,
|
||||||
navigation_message_generation: Rc<Cell<u64>>,
|
navigation_message_generation: Rc<Cell<u64>>,
|
||||||
|
continuous_programmatic_scroll: Cell<bool>,
|
||||||
state: RefCell<ViewerState>,
|
state: RefCell<ViewerState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -948,13 +950,16 @@ impl ViewerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continuous_scrolled(self: &Rc<Self>) {
|
fn continuous_scrolled(self: &Rc<Self>) {
|
||||||
if self.view_mode() != ViewMode::Continuous || self.state.borrow().pages.is_empty() {
|
let pages_empty = self.state.borrow().pages.is_empty();
|
||||||
|
if self.view_mode() != ViewMode::Continuous || pages_empty {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let visible = self.visible_indices();
|
let visible = self.visible_indices();
|
||||||
let new_anchor = visible.first().copied();
|
let new_anchor = visible.first().copied();
|
||||||
let changed = new_anchor.is_some_and(|index| index != self.state.borrow().anchor);
|
let update_anchor = !self.continuous_programmatic_scroll.get();
|
||||||
if let Some(index) = new_anchor {
|
let changed =
|
||||||
|
update_anchor && new_anchor.is_some_and(|index| index != self.state.borrow().anchor);
|
||||||
|
if let Some(index) = new_anchor.filter(|_| update_anchor) {
|
||||||
self.state.borrow_mut().anchor = index;
|
self.state.borrow_mut().anchor = index;
|
||||||
}
|
}
|
||||||
self.render_continuous(&visible);
|
self.render_continuous(&visible);
|
||||||
|
|
@ -1014,16 +1019,28 @@ impl ViewerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to_anchor(&self) {
|
fn scroll_to_anchor(&self) {
|
||||||
let state = self.state.borrow();
|
let frame = {
|
||||||
let Some(row) = state.continuous_rows.get(state.anchor) else {
|
let state = self.state.borrow();
|
||||||
return;
|
let Some(row) = state.continuous_rows.get(state.anchor) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
row.frame.clone()
|
||||||
};
|
};
|
||||||
let Some(bounds) = row.frame.compute_bounds(&self.continuous_box) else {
|
let Some(bounds) = frame.compute_bounds(&self.continuous_box) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let adjustment = self.continuous_scrolled.vadjustment();
|
let adjustment = self.continuous_scrolled.vadjustment();
|
||||||
let maximum = (adjustment.upper() - adjustment.page_size()).max(adjustment.lower());
|
let maximum = (adjustment.upper() - adjustment.page_size()).max(adjustment.lower());
|
||||||
adjustment.set_value(f64::from(bounds.y()).clamp(adjustment.lower(), maximum));
|
let target = centered_scroll_value(
|
||||||
|
f64::from(bounds.y()),
|
||||||
|
f64::from(bounds.height()),
|
||||||
|
adjustment.page_size(),
|
||||||
|
adjustment.lower(),
|
||||||
|
maximum,
|
||||||
|
);
|
||||||
|
self.continuous_programmatic_scroll.set(true);
|
||||||
|
adjustment.set_value(target);
|
||||||
|
self.continuous_programmatic_scroll.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_continuous_paintables(&self) {
|
fn clear_continuous_paintables(&self) {
|
||||||
|
|
@ -1629,6 +1646,16 @@ fn intersecting_rows(bounds: &[Option<(f64, f64)>], top: f64, bottom: f64) -> Ve
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn centered_scroll_value(
|
||||||
|
row_top: f64,
|
||||||
|
row_height: f64,
|
||||||
|
viewport_height: f64,
|
||||||
|
minimum: f64,
|
||||||
|
maximum: f64,
|
||||||
|
) -> f64 {
|
||||||
|
(row_top + row_height / 2.0 - viewport_height / 2.0).clamp(minimum, maximum)
|
||||||
|
}
|
||||||
|
|
||||||
fn page_seek_index(value: f64, count: usize) -> Option<usize> {
|
fn page_seek_index(value: f64, count: usize) -> Option<usize> {
|
||||||
(count > 0).then(|| (value.round().max(0.0) as usize).min(count - 1))
|
(count > 0).then(|| (value.round().max(0.0) as usize).min(count - 1))
|
||||||
}
|
}
|
||||||
|
|
@ -1673,6 +1700,19 @@ mod tests {
|
||||||
assert_eq!(intersecting_rows(&bounds, 3000.0, 3800.0), [2]);
|
assert_eq!(intersecting_rows(&bounds, 3000.0, 3800.0), [2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn continuous_seek_centers_the_selected_row() {
|
||||||
|
assert_eq!(
|
||||||
|
centered_scroll_value(1_000.0, 800.0, 600.0, 0.0, 5_000.0),
|
||||||
|
1_100.0
|
||||||
|
);
|
||||||
|
assert_eq!(centered_scroll_value(0.0, 400.0, 800.0, 0.0, 5_000.0), 0.0);
|
||||||
|
assert_eq!(
|
||||||
|
centered_scroll_value(5_000.0, 800.0, 600.0, 0.0, 5_000.0),
|
||||||
|
5_000.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fast_loading_prefetches_a_larger_window() {
|
fn fast_loading_prefetches_a_larger_window() {
|
||||||
assert_eq!(prefetch_window(&[10], 30, false), [10, 11, 12, 9]);
|
assert_eq!(prefetch_window(&[10], 30, false), [10, 11, 12, 9]);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue