M3: Tabs and the window title show the document title when Initial View asks for it (DisplayDocTitle); parity for setting the document language
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d26821fdcd
commit
6a9dd32ef9
|
|
@ -267,6 +267,18 @@ impl Document {
|
|||
self.editor.as_ref().and_then(|e| printcraft_organize::info(&e.cos, key))
|
||||
}
|
||||
|
||||
/// The name shown on the tab and window: the document title when the document asks for it
|
||||
/// (Initial View ▸ Show: Document Title) and has one, else the file name.
|
||||
pub fn display_name(&self) -> String {
|
||||
self.editor
|
||||
.as_ref()
|
||||
.filter(|e| printcraft_organize::displays_doc_title(&e.cos))
|
||||
.and_then(|e| printcraft_organize::info(&e.cos, "Title"))
|
||||
.map(|t| t.trim().to_owned())
|
||||
.filter(|t| !t.is_empty())
|
||||
.unwrap_or_else(|| self.name.clone())
|
||||
}
|
||||
|
||||
/// Notes about damage repaired while opening (Document Properties ▸ Advanced, notices).
|
||||
pub fn repair_log(&self) -> Vec<String> {
|
||||
self.editor.as_ref().map(|e| e.cos.repair_log().to_vec()).unwrap_or_default()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub use labels::{LabelRange, LabelStyle, number_pages, page_label_ranges, page_l
|
|||
pub use outline::{
|
||||
Bookmark, OutlineError, add_bookmark, bookmarks, delete_bookmark, move_bookmark, rename_bookmark, set_bookmark_open, set_bookmark_page,
|
||||
};
|
||||
pub use view::{InitialView, initial_view, set_initial_view};
|
||||
pub use view::{InitialView, displays_doc_title, initial_view, set_initial_view};
|
||||
|
||||
#[derive(Debug, thiserror::Error, PartialEq)]
|
||||
pub enum OrganizeError {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,16 @@ pub fn initial_view(doc: &Document) -> InitialView {
|
|||
v
|
||||
}
|
||||
|
||||
/// Whether viewers should show the document title rather than the file name
|
||||
/// (`/ViewerPreferences /DisplayDocTitle`), without reading the rest of the initial view.
|
||||
pub fn displays_doc_title(doc: &Document) -> bool {
|
||||
let Ok((_, c)) = catalog(doc) else { return false };
|
||||
c.get(b"ViewerPreferences")
|
||||
.map(|o| doc.resolve(o))
|
||||
.and_then(|o| o.as_dict().map(|vp| matches!(vp.get(b"DisplayDocTitle").map(|x| doc.resolve(x)).as_deref(), Some(Object::Bool(true)))))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Write the initial view. An opening action that isn't a plain destination (a script, say) is
|
||||
/// kept unless the page or magnification asks for a destination.
|
||||
pub fn set_initial_view(doc: &mut Document, v: &InitialView) -> Result<(), OrganizeError> {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ pub fn tab_strip(app: &mut PrintCraftApp, ui: &mut egui::Ui) {
|
|||
let mut close = None;
|
||||
for i in 0..app.views.len() {
|
||||
let Some(doc) = app.session.get(app.views[i].id) else { continue };
|
||||
let (name, dirty) = (doc.name.clone(), doc.dirty);
|
||||
let (name, dirty) = (doc.display_name(), doc.dirty);
|
||||
if tab(ui, &t, &name, dirty, app.active == Some(i), &mut close, i).clicked() {
|
||||
app.active = Some(i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,6 +294,8 @@ pub struct PrintCraftApp {
|
|||
pending_theme: Option<ThemeKind>,
|
||||
styled: bool,
|
||||
fonts_ready: bool,
|
||||
/// The window title last sent to the platform.
|
||||
pub window_title: String,
|
||||
/// The UI control channel, when enabled (`--control`; off by default).
|
||||
control: Option<control::Control>,
|
||||
/// A bookmark being renamed in the Bookmarks panel: (path, text so far).
|
||||
|
|
@ -391,6 +393,7 @@ impl PrintCraftApp {
|
|||
attach_override: None,
|
||||
duplicate_draft: None,
|
||||
form_preview: false,
|
||||
window_title: String::new(),
|
||||
recovery: None,
|
||||
recoverable: Vec::new(),
|
||||
recovery_keys: Default::default(),
|
||||
|
|
@ -976,6 +979,15 @@ impl eframe::App for PrintCraftApp {
|
|||
ctx.request_repaint();
|
||||
return;
|
||||
}
|
||||
// The window shows the active document's name (or title, if it asks for that).
|
||||
let title = self
|
||||
.active
|
||||
.and_then(|i| self.session.get(self.views[i].id))
|
||||
.map_or_else(|| "PrintCraft".to_owned(), |d| format!("{} — PrintCraft", d.display_name()));
|
||||
if title != self.window_title {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Title(title.clone()));
|
||||
self.window_title = title;
|
||||
}
|
||||
if self.full_screen && self.active.is_some() {
|
||||
// Full screen: the page, nothing else (Esc or ⌘L to leave).
|
||||
let t = theme::Tokens::get(&ctx);
|
||||
|
|
|
|||
|
|
@ -279,3 +279,22 @@ fn fit_visible_zooms_to_the_content_width() {
|
|||
let vp = v.viewport_rect();
|
||||
assert!((ink_left - vp.left() - 16.0).abs() < 12.0, "ink at {ink_left}, viewport {vp:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tab_and_window_show_the_document_title_when_asked() {
|
||||
use printcraft_engine::Edit;
|
||||
let mut h = harness();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().window_title, "b.pdf — PrintCraft");
|
||||
{
|
||||
let s = h.state_mut();
|
||||
let id = s.views[s.active.unwrap()].id;
|
||||
s.session.apply(id, Edit::SetInfo { key: "Title".into(), value: "Quarterly report".into() }).unwrap();
|
||||
let mut v = s.session.get(id).unwrap().initial_view();
|
||||
v.display_title = true;
|
||||
s.session.apply(id, Edit::SetInitialView(Box::new(v))).unwrap();
|
||||
}
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().window_title, "Quarterly report — PrintCraft");
|
||||
h.get_by_label_contains("Quarterly report");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8863,11 +8863,11 @@ title = "Set document language"
|
|||
area = "M"
|
||||
tier = "P1"
|
||||
milestone = "M12"
|
||||
status = "planned"
|
||||
commands = []
|
||||
tools = []
|
||||
evidence = []
|
||||
notes = ""
|
||||
status = "shipped"
|
||||
commands = ["file.properties"]
|
||||
tools = ["doc_initial_view"]
|
||||
evidence = ["crates/organize/src/tests.rs::initial_view_round_trips_and_keeps_scripts", "crates/automation/tests/automation.rs::initial_view_through_tools", "crates/ui-egui/tests/viewer.rs::initial_view_is_edited_and_honoured_on_open"]
|
||||
notes = "Document Properties ▸ Initial View ▸ Language (catalog /Lang)"
|
||||
|
||||
[[feature]]
|
||||
id = "a11y.set-title-display"
|
||||
|
|
@ -8875,11 +8875,11 @@ title = "Show the document title in the window"
|
|||
area = "M"
|
||||
tier = "P1"
|
||||
milestone = "M12"
|
||||
status = "planned"
|
||||
commands = []
|
||||
tools = []
|
||||
evidence = []
|
||||
notes = ""
|
||||
status = "shipped"
|
||||
commands = ["file.properties"]
|
||||
tools = ["doc_initial_view"]
|
||||
evidence = ["crates/automation/tests/automation.rs::initial_view_through_tools", "crates/ui-egui/tests/viewer.rs::tab_and_window_show_the_document_title_when_asked"]
|
||||
notes = "Initial View ▸ Show: Document Title (/DisplayDocTitle); the tab and window then show the title"
|
||||
|
||||
[[feature]]
|
||||
id = "a11y.make-accessible-action"
|
||||
|
|
|
|||
Loading…
Reference in New Issue