mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-03 00:41:28 -06:00
Fix up merged PRs: one format.tabs and one Tabs dialog for #567/#569 and #637
#569 and #637 each added a `format.tabs` command and a Tabs dialog. Keep one of each: - format.tabs takes #567/#569's add/move/remove/clear/set plus #637's strict `set` (unknown alignment or non-object entries are errors, stops within 0.05 pt collapse, last wins) and opens the Tabs dialog when called with no fields, as #637 did. A defaultTab-only call no longer rewrites the stops. - The Tabs dialog is #569's; it now seeds from the dialog's params when Paragraph (or format.tabs) opened it, and on OK hands the applied stops back to Paragraph. - Tests adapted: an empty format.tabs opens the dialog; the Paragraph → Tabs test sets stops through #569's dialog fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
12df77ed19
commit
7acb9faad1
@@ -50,7 +50,9 @@ fn tabs_add_move_remove_clear_and_undo() {
|
||||
assert_eq!(tabs(&mut s).len(), 2);
|
||||
s.execute("format.tabs", &json!({"clear": true})).unwrap();
|
||||
assert!(tabs(&mut s).is_empty());
|
||||
assert!(s.execute("format.tabs", &json!({})).is_err());
|
||||
s.ui_requests.clear();
|
||||
s.execute("format.tabs", &json!({})).unwrap();
|
||||
assert!(matches!(s.ui_requests.last(), Some(crate::UiRequest::Dialog { id, .. }) if id == "tabs"), "no fields opens the Tabs dialog");
|
||||
assert!(s.execute("format.tabs", &json!({"add": {"pos": f64::MAX}})).is_ok(), "clamped, not a crash");
|
||||
for i in 0..100 {
|
||||
s.execute("format.tabs", &json!({"add": {"pos": i as f64 * 3.0}})).unwrap();
|
||||
|
||||
@@ -2773,7 +2773,9 @@ const TAB_KINDS: [(&str, &str); 4] = [("l", "Left"), ("ctr", "Center"), ("r", "R
|
||||
/// list (inches, as PowerPoint's dialog) and applied together with OK.
|
||||
fn tabs_dialog(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool {
|
||||
if !d.fields.contains_key("stops") {
|
||||
let r = app.session.execute("format.ruler", &json!({})).unwrap_or_default();
|
||||
// Opened from Paragraph (or by `format.tabs` with no fields) the stops come with the
|
||||
// dialog; otherwise they are read from the caret's paragraph.
|
||||
let r = if d.params.get("tabs").is_some() { d.params.clone() } else { app.session.execute("format.ruler", &json!({})).unwrap_or_default() };
|
||||
let stops: Vec<String> = r["tabs"]
|
||||
.as_array()
|
||||
.map(|a| a.iter().filter_map(|t| Some(format!("{}:{}", t["pos"].as_f64()? / 72.0, t["align"].as_str().unwrap_or("l")))).collect())
|
||||
@@ -2846,6 +2848,10 @@ fn tabs_dialog(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool {
|
||||
let dt = num(d, "default", 1.0).clamp(0.02, 56.0) * 72.0;
|
||||
if let Err(e) = app.run("format.tabs", json!({"set": set, "defaultTab": dt})) {
|
||||
app.set_status(e);
|
||||
} else if let Some(ret) = d.params.get_mut("returnParams").and_then(Value::as_object_mut) {
|
||||
// Back in Paragraph, its Tabs… shows what was just applied.
|
||||
ret.insert("tabs".into(), json!(set));
|
||||
ret.insert("defaultTab".into(), json!(dt));
|
||||
}
|
||||
}
|
||||
ok || cancel
|
||||
|
||||
@@ -71,8 +71,7 @@ fn tabs_from_paragraph_applies_a_stop_and_returns() {
|
||||
assert_eq!(h.state().dialog.as_ref().map(|d| d.id.as_str()), Some("tabs"), "status {:?}", h.state().status);
|
||||
{
|
||||
let d = h.state_mut().dialog.as_mut().unwrap();
|
||||
d.params["editing"] = json!(true);
|
||||
d.params["edit"] = json!([{"pos": 144.0, "align": "ctr"}]);
|
||||
d.fields.insert("stops".into(), "2:ctr".into());
|
||||
}
|
||||
h.get_by_label("OK").click_accesskit();
|
||||
// The Tabs OK frame restores Paragraph; the next frame fills its fields.
|
||||
|
||||
Reference in New Issue
Block a user