ElyPDF: page pictures stay through an edit until they repaint (P-02)
This commit is contained in:
8 files changed
+60
-9
No files matched your search
@@ -115,9 +115,14 @@ impl PdfView {
|
||||
// A page may now stand where another stood.
|
||||
self.retire_tiles();
|
||||
self.sizes = measured;
|
||||
self.thumbs_stale.clear();
|
||||
for (_, image) in self.thumbs.drain() {
|
||||
self.retired.push(image);
|
||||
}
|
||||
} else {
|
||||
// Same pages: old tiles stay under them until repainted.
|
||||
// Same pages: old pictures stay until repainted.
|
||||
self.keep_all();
|
||||
self.thumbs_stale.extend(self.thumbs.keys().copied());
|
||||
let read = fresh.first.len();
|
||||
self.sizes[..read].copy_from_slice(&measured[..read]);
|
||||
}
|
||||
@@ -125,9 +130,6 @@ impl PdfView {
|
||||
self.failed.clear();
|
||||
self.text.clear();
|
||||
self.asking_text.clear();
|
||||
for (_, image) in self.thumbs.drain() {
|
||||
self.retired.push(image);
|
||||
}
|
||||
self.thumbs_failed.clear();
|
||||
// Indices shift with any edit; aims start over.
|
||||
(self.layers, self.aim, self.drag) = (Default::default(), None, None);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Page pictures, and bookmarks if any (PDF-01, PDF-02).
|
||||
|
||||
use std::{collections::BTreeSet, ops::Range};
|
||||
use std::{collections::BTreeSet, ops::Range, sync::Arc};
|
||||
|
||||
use ely_gpui_component::{
|
||||
buttons::SegmentedControl,
|
||||
@@ -9,7 +9,7 @@ use ely_gpui_component::{
|
||||
theme::{ActiveTheme as _, ControlSize},
|
||||
};
|
||||
use gpui::{
|
||||
Action, App, Context, Entity, InteractiveElement as _, IntoElement, ParentElement as _, Render, Role,
|
||||
Action, App, Context, Entity, InteractiveElement as _, IntoElement, ParentElement as _, Render, RenderImage, Role,
|
||||
StatefulInteractiveElement as _, Styled as _, WeakEntity, Window, div, img, prelude::FluentBuilder as _, px,
|
||||
uniform_list,
|
||||
};
|
||||
@@ -104,7 +104,8 @@ impl PdfView {
|
||||
if self.thumbing {
|
||||
return;
|
||||
}
|
||||
let Some(page) = rows.clone().find(|page| !self.thumbs.contains_key(&(*page, dark)) && !self.thumbs_failed.contains(page)) else {
|
||||
let due = |page: &usize| !self.thumbs.contains_key(&(*page, dark)) || self.thumbs_stale.contains(&(*page, dark));
|
||||
let Some(page) = rows.clone().find(|page| due(page) && !self.thumbs_failed.contains(page)) else {
|
||||
return;
|
||||
};
|
||||
let (w, h) = self.sizes[page];
|
||||
@@ -127,6 +128,7 @@ impl PdfView {
|
||||
});
|
||||
match painted.map(|bgra| crate::pages::picture((tile[2] as u32, tile[3] as u32), bgra)) {
|
||||
Ok(Some(image)) => {
|
||||
view.thumbs_stale.remove(&(page, dark));
|
||||
if let Some(old) = view.thumbs.insert((page, dark), image) {
|
||||
view.retired.push(old);
|
||||
}
|
||||
@@ -145,13 +147,20 @@ impl PdfView {
|
||||
}
|
||||
}
|
||||
|
||||
impl PdfView {
|
||||
/// The picture a row draws; an old one until repainted.
|
||||
pub fn picture(&self, page: usize, dark: bool) -> Option<Arc<RenderImage>> {
|
||||
self.thumbs.get(&(page, dark)).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
/// One row: the page number and its picture.
|
||||
fn row(view: &Entity<PdfView>, page: usize, dark: bool, cx: &App) -> gpui::AnyElement {
|
||||
let read = view.read(cx);
|
||||
let colors = &cx.theme().colors;
|
||||
let (w, h) = read.sizes[page];
|
||||
let picked = read.picked.contains(&page);
|
||||
let picture = read.thumbs.get(&(page, dark)).cloned();
|
||||
let picture = read.picture(page, dark);
|
||||
let count = read.sizes.len();
|
||||
let label = Viewer::text(cx, "pdf.page.label", &[("n", &(page + 1).to_string())]);
|
||||
let (clicked, pressed, dropped) = (view.clone(), view.clone(), view.clone());
|
||||
|
||||
@@ -326,3 +326,31 @@ fn old_tiles_are_painted_and_freed_with_their_tab() {
|
||||
cx.update(|_, app| view.update(app, |view, _| view.retire_all()));
|
||||
assert!(cx.update(|_, app| view.read(app).backdrop.is_empty()), "closing hands every old tile over");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_edit_keeps_page_pictures_until_they_repaint() {
|
||||
let dir = tempfile::tempdir().expect("a temp dir");
|
||||
let mut cx = TestAppContext::single();
|
||||
let (viewer, cx) = windowed(&mut cx, dir.path(), &[file(dir.path(), "one.pdf", &[(612.0, 792.0, &["Hello"])])], true);
|
||||
let view = shown(cx, &viewer);
|
||||
let dark = cx.update(|_, app| ely_gpui_component::theme::ActiveTheme::theme(app).is_dark());
|
||||
settle(cx, |app| view.read(app).picture(0, dark).is_some() && repainted(view.read(app)));
|
||||
let old = cx.update(|_, app| view.read(app).picture(0, dark).expect("a picture"));
|
||||
// A picture on its way holds back the repaint.
|
||||
cx.update(|_, app| view.update(app, |view, _| view.thumbing = true));
|
||||
cx.update(|_, app| view.update(app, |view, cx| view.annotate("adding a note", vec![note()], cx)));
|
||||
settle(cx, |app| view.read(app).edited == 1 && repainted(view.read(app)));
|
||||
// Dropped from the atlas, it returns only if drawn.
|
||||
cx.update(|window, _| window.drop_image(old.clone())).expect("drops");
|
||||
super::frames(cx);
|
||||
assert!(cx.update(|window, _| window.has_image_atlas_entry(&old)), "the old picture shows meanwhile");
|
||||
cx.update(|_, app| view.update(app, |view, cx| {
|
||||
view.thumbing = false;
|
||||
cx.notify()
|
||||
}));
|
||||
settle(cx, |app| view.read(app).thumbs_stale.is_empty());
|
||||
let new = cx.update(|_, app| view.read(app).picture(0, dark).expect("a picture"));
|
||||
assert!(!std::sync::Arc::ptr_eq(&new, &old), "the new picture replaces it");
|
||||
super::frames(cx);
|
||||
assert!(cx.update(|window, _| window.has_image_atlas_entry(&new)), "and is drawn");
|
||||
}
|
||||
@@ -71,6 +71,8 @@ pub struct PdfView {
|
||||
/// Page pictures for the side panel, by page and darkness.
|
||||
pub thumbs: HashMap<(usize, bool), Arc<RenderImage>>,
|
||||
pub thumbs_failed: HashSet<usize>,
|
||||
/// Pictures from before an edit; shown until repainted.
|
||||
pub thumbs_stale: HashSet<(usize, bool)>,
|
||||
/// A picture is on its way from the worker.
|
||||
pub thumbing: bool,
|
||||
/// Pages picked in the side panel, and the anchor.
|
||||
@@ -188,6 +190,7 @@ impl PdfView {
|
||||
mark: loaded.mark,
|
||||
thumbs: HashMap::new(),
|
||||
thumbs_failed: HashSet::new(),
|
||||
thumbs_stale: HashSet::new(),
|
||||
thumbing: false,
|
||||
picked: BTreeSet::new(),
|
||||
anchor: None,
|
||||
|
||||
Reference in new issue
Block a user