Slide Size: choose Portrait or Landscape (#198)

The Slide Size dialog gets an Orientation choice that swaps width and
height, and design.slideSize takes orientation: portrait|landscape so a
preset can be made portrait from the CLI and MCP too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
justinjohn0306andClaude Opus 5.5 committed 2026-10-12 15:39:40 +05:30
1 parent 0ec0cc5e81
commit 1601fd250a
3 files changed
+23 -1

No files matched your search

+7 -1
View File
@@ -33,7 +33,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Slide Size",
["Design", "Customize"],
None,
"{preset?: widescreen|standard|… | w, h: pt, scale?: maximize|ensureFit|none}",
"{preset?: widescreen|standard|… | w, h: pt, orientation?: portrait|landscape, scale?: maximize|ensureFit|none}",
has_doc,
slide_size
),
@@ -251,6 +251,12 @@ fn slide_size(s: &mut Session, p: &Value) -> Result<Value> {
f64_param(p, "h").ok_or_else(|| bad("design.slideSize", "missing `h`"))?.clamp(72.0, 4032.0),
)
};
let size = match str_param(p, "orientation") {
Some("portrait") if size.width > size.height => Size::new(size.height, size.width),
Some("landscape") if size.height > size.width => Size::new(size.height, size.width),
Some("portrait" | "landscape") | None => size,
Some(o) => return Err(bad("design.slideSize", format!("unknown orientation `{o}`"))),
};
let mode = str_param(p, "scale").unwrap_or("ensureFit").to_string();
s.edit(|doc, _| {
let old = doc.slide_size;
+5
View File
@@ -244,6 +244,11 @@ fn themes_and_slide_size() {
assert_eq!(s.doc().unwrap().doc.masters[0].theme.name, "Ember");
s.execute("design.slideSize", &json!({"preset": "standard"})).unwrap();
assert_eq!(s.doc().unwrap().doc.slide_size.width, 720.0);
s.execute("design.slideSize", &json!({"preset": "widescreen", "orientation": "portrait"})).unwrap();
assert_eq!((s.doc().unwrap().doc.slide_size.width, s.doc().unwrap().doc.slide_size.height), (540.0, 960.0));
s.execute("design.slideSize", &json!({"w": 540.0, "h": 960.0, "orientation": "landscape"})).unwrap();
assert_eq!((s.doc().unwrap().doc.slide_size.width, s.doc().unwrap().doc.slide_size.height), (960.0, 540.0));
assert!(s.execute("design.slideSize", &json!({"preset": "standard", "orientation": "sideways"})).is_err());
s.execute("design.headerFooter", &json!({"slideNumber": true, "footer": true, "footerText": "Hello"})).unwrap();
let v = s.execute("slide.inspect", &json!({})).unwrap();
assert!(v["shapes"].as_array().unwrap().iter().any(|x| x["placeholder"] == "sldNum"));
+11
View File
@@ -148,6 +148,17 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool {
});
field(ui, d, "Width (in):", "w", &format!("{:.2}", cur.width / 72.0));
field(ui, d, "Height (in):", "h", &format!("{:.2}", cur.height / 72.0));
let (w, h) = (num(d, "w", cur.width / 72.0), num(d, "h", cur.height / 72.0));
ui.horizontal(|ui| {
ui.label("Orientation:");
let portrait = ui.radio(h > w, "Portrait").clicked();
let landscape = ui.radio(w >= h, "Landscape").clicked();
// Picking the other orientation swaps the width and height fields.
if portrait && w > h || landscape && h > w {
d.fields.insert("w".into(), format!("{h:.2}"));
d.fields.insert("h".into(), format!("{w:.2}"));
}
});
let maximize = check(ui, d, "Maximize content (else ensure fit)", "max", false);
let (ok, cancel) = buttons(ui, "OK");
if ok {