Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
parent
7fbcd0643a
commit
bc60cbaadb
|
|
@ -651,6 +651,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
.pure(),
|
||||
CommandSpec::new("view.sideToSide", "Side to Side", "View › Page Movement", |s, _| {
|
||||
s.view.multi_page = true;
|
||||
s.view.single_column = false;
|
||||
s.view.fit = "multiplePages".into();
|
||||
Ok(json!({"pageMovement": "sideToSide"}))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ fn zoom(s: &mut Session, v: &Value) -> CmdResult {
|
|||
Some(Value::String(f)) if ["pageWidth", "onePage", "multiplePages", "textWidth"].contains(&f.as_str()) => {
|
||||
s.view.fit = f.clone();
|
||||
s.view.multi_page = f == "multiplePages";
|
||||
s.view.single_column = f == "onePage" || f == "pageWidth";
|
||||
}
|
||||
Some(x) => {
|
||||
let pct = x.as_f64().ok_or_else(|| CmdError::Params("zoom percent or fit mode".into()))? as f32;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ pub struct ViewState {
|
|||
#[serde(default)]
|
||||
pub alt_text_pane: bool,
|
||||
pub multi_page: bool,
|
||||
/// One Page or Page Width was chosen last: keep one page per row when a typed or wheel zoom replaces the fit mode.
|
||||
#[serde(default)]
|
||||
pub single_column: bool,
|
||||
/// Zoom to fit: "pageWidth", "onePage", "multiplePages", or empty.
|
||||
pub fit: String,
|
||||
pub web_width: f32,
|
||||
|
|
@ -169,6 +172,7 @@ impl Default for ViewState {
|
|||
accessibility_pane: false,
|
||||
alt_text_pane: false,
|
||||
multi_page: false,
|
||||
single_column: false,
|
||||
fit: String::new(),
|
||||
web_width: 800.0,
|
||||
read_width: default_read_width(),
|
||||
|
|
|
|||
|
|
@ -2761,6 +2761,25 @@ fn page_and_table_gridlines_toggle_independently() {
|
|||
assert_eq!(state["tableGridlines"], false);
|
||||
}
|
||||
|
||||
/// Issue #768: zooming by percent after One Page or Page Width keeps one page per row.
|
||||
#[test]
|
||||
fn zoom_after_one_page_keeps_single_column() {
|
||||
let mut s = s();
|
||||
run(&mut s, "view.onePage", json!({}));
|
||||
assert!(s.view.single_column);
|
||||
run(&mut s, "view.zoomOut", json!({}));
|
||||
assert!(s.view.fit.is_empty() && s.view.single_column);
|
||||
run(&mut s, "view.zoom", json!({"value": 50}));
|
||||
assert!(s.view.single_column);
|
||||
run(&mut s, "view.multiplePages", json!({}));
|
||||
assert!(!s.view.single_column);
|
||||
run(&mut s, "view.zoomIn", json!({}));
|
||||
assert!(!s.view.single_column);
|
||||
run(&mut s, "view.pageWidth", json!({}));
|
||||
run(&mut s, "view.sideToSide", json!({}));
|
||||
assert!(!s.view.single_column);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn navigation_pane_opens_without_changing_view_mode() {
|
||||
// Reading Mode's heading navigation is the Navigation pane; Outline is an editing view (#493).
|
||||
|
|
|
|||
|
|
@ -478,8 +478,8 @@ pub fn geometry(app: &WordApp, l: &DocLayout, avail: egui::Vec2) -> Geometry {
|
|||
scale = PX_PER_PT;
|
||||
}
|
||||
// Pages flow side by side in Print Layout whenever more than one fits across; One Page and
|
||||
// Page Width show one per row, Web Layout has no pages. Reading Mode is handled above.
|
||||
let (min_cols, auto) = if web || v.fit == "onePage" || v.fit == "pageWidth" {
|
||||
// Page Width show one per row (and so does a zoom after One Page, #768), Web Layout has no pages. Reading Mode is handled above.
|
||||
let (min_cols, auto) = if web || v.fit == "onePage" || v.fit == "pageWidth" || v.single_column {
|
||||
(1, false)
|
||||
} else if v.multi_page {
|
||||
(2, true)
|
||||
|
|
|
|||
|
|
@ -2411,6 +2411,43 @@ mod tests {
|
|||
assert_eq!(caret.page, 3);
|
||||
}
|
||||
|
||||
/// Issue #768: after One Page, zooming out (Zoom Out, the Zoom box, Ctrl + wheel) keeps one page per row.
|
||||
#[test]
|
||||
fn zoom_after_one_page_keeps_one_page_per_row() {
|
||||
let ctx = egui::Context::default();
|
||||
let mut a = app();
|
||||
for _ in 0..3 {
|
||||
a.run("insert.pageBreak", json!({})).unwrap();
|
||||
}
|
||||
let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1280.0, 800.0));
|
||||
let mut t = 0.0;
|
||||
let mut frame = |a: &mut WordApp| {
|
||||
t += 1.0 / 60.0;
|
||||
let input = egui::RawInput { time: Some(t), screen_rect: Some(screen), ..Default::default() };
|
||||
ctx.run_ui(input, |ui| {
|
||||
a.logic(ui.ctx());
|
||||
a.ui(ui);
|
||||
})
|
||||
.drop_without_applying_deltas();
|
||||
};
|
||||
a.run("view.onePage", json!({})).unwrap();
|
||||
for _ in 0..3 {
|
||||
frame(&mut a);
|
||||
}
|
||||
assert_eq!(a.canvas.cols, 1);
|
||||
a.run("view.zoom", json!({"value": 30})).unwrap();
|
||||
for _ in 0..3 {
|
||||
frame(&mut a);
|
||||
}
|
||||
assert_eq!(a.canvas.cols, 1, "30% after One Page: still one page per row");
|
||||
a.run("view.multiplePages", json!({})).unwrap();
|
||||
a.run("view.zoom", json!({"value": 30})).unwrap();
|
||||
for _ in 0..3 {
|
||||
frame(&mut a);
|
||||
}
|
||||
assert_eq!(a.canvas.cols, 4, "30% after Multiple Pages: all four pages fit across");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn user_name_survives_restart() {
|
||||
let mut first = app();
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ own (`AGENTS.md`: no Microsoft iconography, ever).
|
|||
| Tables on the page: drag column and row borders, resize handle past the bottom-right corner | ✅ resize cursors, dashed guide, one undo step per drag, selection kept; Shift moves one column; Esc cancels (#217). Missing: Ctrl and Alt drags, the left edge, borders of selected cells only, double-click AutoFit | ✅ | 80% | 1–2 |
|
||||
| Rotation handle, crop handles on canvas, alignment guides, smart guides | rotation handle (Shift: 15° steps), turned frames resize along their axes (#332); crop handles and guides missing | ✅ | 25% | 3–5 |
|
||||
| Selection: word/sentence/paragraph clicks, dragging after a double-click/triple-click/Ctrl+click extends by whole words/paragraphs/sentences (#549), Shift extend, F8 extend mode, column (Alt+drag, #237) | ✅ | ✅ | 90% | 1 |
|
||||
| Zoom: Ctrl+scroll, pinch (#179), zoom buttons (#232), pages side by side when zoomed out (#251) | ✅ | ✅ | 85% | — |
|
||||
| Zoom: Ctrl+scroll, pinch (#179), zoom buttons (#232), pages side by side when zoomed out (#251), still one per row after One Page or Page Width (#768) | ✅ | ✅ | 85% | — |
|
||||
| Touchpad smooth/inertial scroll | ✅ (#252) | ✅ | 90% | — |
|
||||
| Reading Mode | Existing Read Mode ribbon button opens a read-only, viewport-column layout with animated horizontal paging, transient width/text/spacing controls, heading navigation (Navigation pane) and resize anchoring; print/export layout unchanged | reading-optimized view and navigation | 75% | 1–2 |
|
||||
| Status bar (page x of y, words, language, view buttons, zoom slider) | ✅ (the language is the caret's; a click sets the proofing language) | ✅ | 85% | — |
|
||||
|
|
|
|||
Loading…
Reference in New Issue