From 42903d7bd3e94aedc818db69dd11dc06acd1dbbd Mon Sep 17 00:00:00 2001 From: moppeeer <339764117+moppeeer@users.noreply.github.com> Date: Sun, 18 Oct 2026 23:43:17 +0200 Subject: [PATCH] TOC-5: open numbering options from section markers --- ROADMAP.md | 2 ++ crates/ui-egui/src/panels/pages.rs | 56 +++++++++++++++++++++++++++++- docs/ui-parity.md | 3 ++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 4b47f97a0..3cb6d4d0b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -348,6 +348,8 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m Newest first. +- **2026-10-18** · Double-clicking a section triangle in the Pages panel opens that page’s numbering options, including from parent-page editing. No readiness percentage change. + - **2026-10-16** · Threading: the loaded text cursor threads into a text frame inside a group (it hit the group and showed it could not thread); a plain click still selects the group (#1075). Gap 27 closed. No readiness percentage change. - **2026-10-16** · Greek text hyphenates. The patterns were never compiled in, so Greek set unhyphenated however narrow the column; `"Greek"`, `"Greek: Greece"`, `el` and `el-GR` all resolve now and ανθρωπος breaks αν-θρω-πος. They are the monotonic patterns (hyph-el-monoton, Dimitrios Filippou, under MIT), which is what polytonic text hyphenates by too. Five of InDesign's ~40 hyphenation languages. No readiness percentage change. - **2026-10-16** · A swatch applied to a placed greyscale or bitmap image colours it, as in InDesign: IDML's `` is read and written, greyscale pixels become a tint of the swatch on opaque white and a bitmap's white lets the frame show through, on screen and in PDF (spot swatches print on their plate). Colour images keep their colours. Applying the swatch from the Swatches panel comes next. No readiness percentage change. diff --git a/crates/ui-egui/src/panels/pages.rs b/crates/ui-egui/src/panels/pages.rs index ef9895373..88f04e362 100644 --- a/crates/ui-egui/src/panels/pages.rs +++ b/crates/ui-egui/src/panels/pages.rs @@ -472,7 +472,24 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) { t.icon, Stroke::NONE, )); - + let marker = + ui.interact(egui::Rect::from_center_size(c, vec2(12.0, 8.0)), ui.id().with(("section", abs)), Sense::click()); + let label = format!( + "{}: {}", + crate::i18n::tr(&app.ui.language, "Numbering & Section Options…").trim_end_matches('…'), + app.session.page_label(abs) + ); + marker.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, &label)); + if marker.double_clicked() { + if editing_parents { + let _ = app.run("layout.parents.edit", json!({"on": false})); + if let Some(view) = app.view_mut() { + view.fitted = false; + } + } + crate::canvas::go_to_page(app, abs); + crate::menus::activate(app, "layout.section", &serde_json::Value::Null); + } } // Parent prefix in the outer top corner (black on white). if let Some(pid) = p.parent @@ -1123,6 +1140,43 @@ mod spread_label_tests { use super::*; + /// Section-marker activation targets its page and leaves parent editing without editing the document. + #[test] + fn double_clicking_a_section_marker_opens_that_pages_numbering_options() { + let mut app = app(); + app.run("layout.section", json!({"page": 1, "startNumber": 1, "style": "lowerRoman"})).unwrap(); + app.run("layout.section", json!({"page": 3, "startNumber": 1, "style": "arabic"})).unwrap(); + app.canvas_rect = Some(egui::Rect::from_min_size(egui::Pos2::ZERO, vec2(1000.0, 800.0))); + app.run("layout.parents.edit", json!({"on": true})).unwrap(); + let mut h = Harness::builder().with_size(vec2(280.0, 900.0)).with_step_dt(1.0 / 60.0).build_ui_state( + |ui, app: &mut DesignApp| { + let key = egui::Id::new("section_marker_test_fonts"); + if ui.data(|d| d.get_temp::(key)).is_none() { + crate::theme::install_fonts(ui.ctx(), ""); + ui.data_mut(|d| d.insert_temp(key, true)); + return; + } + show(app, ui); + }, + app, + ); + h.run_steps(3); + let pos = h.get_by_label("Numbering & Section Options: 1").rect().center(); + let before = h.state().session.doc().unwrap().doc.clone(); + for _ in 0..2 { + for pressed in [true, false] { + h.event(egui::Event::PointerMoved(pos)); + h.event(egui::Event::PointerButton { pos, button: egui::PointerButton::Primary, pressed, modifiers: egui::Modifiers::NONE }); + h.run_steps(1); + } + } + let dialog = h.state().ui.dialog.as_ref().unwrap(); + assert_eq!(dialog.id, "numberingSection"); + assert_eq!(dialog.fields.get("page"), Some(&json!(3))); + assert!(!h.state().session.doc().unwrap().editing_parents); + assert!(std::sync::Arc::ptr_eq(&h.state().session.doc().unwrap().doc, &before), "opening options does not edit the section"); + } + fn app() -> DesignApp { let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); app.run("file.new", json!({"facingPages": true, "pages": 9})).unwrap(); diff --git a/docs/ui-parity.md b/docs/ui-parity.md index 2dcf4687a..5c3f0b8b6 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -126,3 +126,6 @@ covers checking the sampled and redefined settings in the styles tutorial (2:45 | 2026-10-11 | minor | Added held Cmd+Space / Cmd+Alt+Space Zoom navigation and canvas input regression tests | | 2026-10-10 | minor | Threading row corrected to ✗ after checking the code (no out-port interaction, no thread command) | | 2026-10-10 | major | Created: measured menu coverage, 27-row interaction checklist from the code and issues | + +Double-clicking a section triangle in the Pages panel opens Numbering & Section Options for +that section’s first page. It leaves parent-page editing and does not edit section data until confirmed.