mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-01 14:16:49 -06:00
Merge PR #1508: Insert Pages dialog as InDesign's: before or after a page, at the start or end, with a parent
crates/ui-egui/src/i18n/*.rs: kept both sides' rows (unique keys)
This commit is contained in:
@@ -464,6 +464,7 @@ Newest first.
|
||||
- **2026-10-21** · Find/Change has InDesign's Change Format. Specify Attributes opens Change Format Settings: Style Options (the character and paragraph style to apply, [Any Style] for none), then Basic and Advanced Character Formats, Character Color, OpenType Features, Underline and Strikethrough Options. The box shows the format ("Character Style: eggs"), and Change All gives it to the changed text. With a Change Format and nothing in Change to, the found text stays and is only formatted, as InDesign's (an ⓘ beside Change to says so). `find.change` takes `charStyle` and `paraStyle`. Found in the Learn Skills Daily course, chapter 22. No readiness percentage change.
|
||||
- **2026-10-21** · Preferences › Interface follows InDesign's: Appearance has a Color Theme swatch per interface theme (a click shows it at once, Cancel goes back) and Panels sets the Tools panel to a single or double column; UI Size moves to a UI Scaling section of its own. Interface held only UI Size, and the theme could be changed only from the Window menu. Found in the Learn Skills Daily course, chapter 26. No readiness percentage change.
|
||||
- **2026-10-21** · Preferences › File Handling shows Number of Recent Items to Display as a whole number ("20"; it read "20.0"). Found in the Learn Skills Daily course, chapter 26. No readiness percentage change.
|
||||
- **2026-10-21** · Insert Pages… opens InDesign's dialog: Pages, Insert (After Page, Before Page, At Start of Document, At End of Document) with the page by name, and Parent ([None] or a parent), set to the page in view and its parent. It was a form asking for a page index and a parent id, and pages could not go before the first page; `layout.pages.insert` takes `before` (0: at the start). Found in the Learn Skills Daily course, chapter 25. No readiness percentage change.
|
||||
- **2026-10-21** · Properties › Character and Paragraph: ••• (More Options) expands the section in place, as InDesign's: Character adds vertical and horizontal scale, baseline shift, skew, language and OpenType, and All Caps, Small Caps, Superscript, Subscript, Underline and Strikethrough; Paragraph adds the left, right, first line and last line indents, space before and after, the drop cap's lines and characters, Align to Baseline Grid and Hyphenate. It used to open the Character or Paragraph panel; the language field moved under ••• as in InDesign. Found in the Learn Skills Daily course, chapter 16. No readiness percentage change.
|
||||
- **2026-10-21** · The text Control panel has InDesign's two modes: A (Character Formatting Controls: font and style, size and leading, All Caps/Superscript/Underline and Small Caps/Subscript/Strikethrough, kerning and tracking, vertical and horizontal scale, baseline shift and skew, character style and language) and ¶ (Paragraph Formatting Controls: the nine alignments, left/first line and right/last line indents, space before and after, the drop cap's lines and characters, paragraph style, Hyphenate and Align to Baseline Grid). It used to show a fixed mix of both. Found in the Learn Skills Daily course, chapter 16. No readiness percentage change.
|
||||
- **2026-10-20** · With the Type tool, the Control panel's font size, leading and tracking fields have a spinner and a list of common values, as in InDesign (auto leading in parentheses). No readiness percentage change.
|
||||
|
||||
@@ -117,6 +117,52 @@ mod parent_margin_tests {
|
||||
assert!(s.execute("layout.marginsAndColumns", &json!({"parent": "Z", "margins": 10})).is_err());
|
||||
}
|
||||
|
||||
/// Insert Pages before a page, or at the start of the document (`before: 0`), as InDesign's
|
||||
/// dialog offers; `after` and `before` together are refused without an undo step.
|
||||
#[test]
|
||||
fn pages_go_in_before_a_page_or_at_the_start() {
|
||||
let mut s = Session::new();
|
||||
// Facing: [1] [2 3].
|
||||
s.execute("file.new", &json!({"pages": 3})).unwrap();
|
||||
let b = s.execute("layout.parents.new", &json!({"prefix": "B"})).unwrap()["id"].as_u64().unwrap();
|
||||
let ids = |s: &Session| -> Vec<u64> {
|
||||
let d = &s.doc().unwrap().doc;
|
||||
(0..d.page_count()).map(|i| d.page(i).unwrap().id.0).collect()
|
||||
};
|
||||
let parent = |s: &Session, i: usize| s.doc().unwrap().doc.page(i).unwrap().parent.map(|p| p.0);
|
||||
let old = ids(&s);
|
||||
s.execute("layout.pages.insert", &json!({"before": 0, "parent": "B"})).unwrap();
|
||||
let now = ids(&s);
|
||||
assert_eq!(now.len(), 4);
|
||||
assert_eq!(now[1..], old[..], "the old pages follow the new first page");
|
||||
assert_eq!(parent(&s, 0), Some(b));
|
||||
// Before page 4 (index 3, the old page 3): two pages without a parent.
|
||||
s.execute("layout.pages.insert", &json!({"before": 3, "count": 2, "parent": null})).unwrap();
|
||||
let then = ids(&s);
|
||||
assert_eq!(then.len(), 6);
|
||||
assert_eq!(then[..3], now[..3]);
|
||||
assert_eq!(then[5], old[2]);
|
||||
assert_eq!((parent(&s, 3), parent(&s, 4)), (None, None));
|
||||
// Refused without a change or an undo step: both placements, even one of them null, and a
|
||||
// placement that isn't a page index.
|
||||
let undo = s.doc().unwrap().history.undo.len();
|
||||
for bad in [
|
||||
json!({"after": 0, "before": 1}),
|
||||
json!({"after": 0, "before": null}),
|
||||
json!({"after": null, "before": 1}),
|
||||
json!({"before": -1}),
|
||||
json!({"before": "0"}),
|
||||
json!({"before": null}),
|
||||
json!({"after": 1.5}),
|
||||
json!({"before": 6}),
|
||||
json!({"before": 99}),
|
||||
] {
|
||||
assert!(s.execute("layout.pages.insert", &bad).is_err(), "{bad}");
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), undo, "{bad}");
|
||||
assert_eq!(ids(&s), then, "{bad}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applying_a_parent_gives_its_margins_and_local_margins_stay_local() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -12,7 +12,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Insert Pages…",
|
||||
["Layout", "Pages"],
|
||||
Some("Cmd+Shift+P"),
|
||||
"{count?: 1 (1 to 9999), after?: 0-based page index (default: the last page), parent?: id|\"A-Parent\"|\"A\"|null}",
|
||||
"{count?: 1 (1 to 9999), after?: 0-based page index (default: the last page; past it: at the end), before?: 0-based page index (instead of `after`; 0: at the start), parent?: id|\"A-Parent\"|\"A\"|null}",
|
||||
has_doc,
|
||||
|s, p| {
|
||||
const ID: &str = "layout.pages.insert";
|
||||
@@ -27,12 +27,30 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
};
|
||||
let st = s.doc()?;
|
||||
let n = st.doc.page_count();
|
||||
// An `after` past the last page appends, which `insert_after_u64_max_appends_at_the_end`
|
||||
// pins deliberately.
|
||||
let after = p.get("after").and_then(Value::as_u64).map(|v| usize::try_from(v).unwrap_or(usize::MAX)).unwrap_or(n.saturating_sub(1));
|
||||
// A placement given (null included) must be a page index; only when neither is
|
||||
// given do the pages go after the last.
|
||||
if p.get("after").is_some() && p.get("before").is_some() {
|
||||
return Err(bad("layout.pages.insert", "give `after` or `before`, not both"));
|
||||
}
|
||||
// `before` names a page of the document; an `after` past the last page appends
|
||||
// (`insert_pages_bounds.rs` pins that).
|
||||
let index = |k: &str| match p.get(k) {
|
||||
None => Ok(None),
|
||||
Some(v) => v
|
||||
.as_u64()
|
||||
.map(|v| usize::try_from(v).unwrap_or(usize::MAX))
|
||||
.filter(|&i| k == "after" || i < n)
|
||||
.map(|i| Some(i.min(n.saturating_sub(1))))
|
||||
.ok_or_else(|| bad(ID, format!("`{k}` must be the index of one of the {n} pages, not {v}"))),
|
||||
};
|
||||
// The page the new ones follow; none: they go first.
|
||||
let after = match (index("after")?, index("before")?) {
|
||||
(_, Some(b)) => b.checked_sub(1),
|
||||
(a, None) => Some(a.unwrap_or(n.saturating_sub(1))),
|
||||
};
|
||||
let parent = parent_ref(ID, &st.doc, p.get("parent"))?.unwrap_or_else(|| st.doc.parents.first().map(|x| x.id));
|
||||
s.edit(|d, _| {
|
||||
let ids = d.insert_pages(Some(after), count, parent)?;
|
||||
let ids = d.insert_pages(after, count, parent)?;
|
||||
Ok(json!({"pages": ids.len(), "total": d.page_count()}))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//! `layout.pages.insert` clamps an out-of-range `after` to the end instead of overflowing.
|
||||
//! `layout.pages.insert` clamps an out-of-range `after` to the end instead of overflowing; a
|
||||
//! `before` must name a page, and one that doesn't is refused without a change.
|
||||
use designcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
@@ -14,3 +15,13 @@ fn insert_after_u64_max_appends_at_the_end() {
|
||||
assert_eq!(after[..2], before[..], "the original pages must stay first; new pages go at the end");
|
||||
assert!(after[2..].iter().all(|id| !before.contains(id)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_before_u64_max_is_refused_without_overflow() {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"pages":2})).unwrap();
|
||||
let undo = s.doc().unwrap().history.undo.len();
|
||||
assert!(s.execute("layout.pages.insert", &json!({"before": u64::MAX, "count": 2})).is_err());
|
||||
assert_eq!(s.doc().unwrap().doc.page_count(), 2, "no pages added");
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), undo, "no undo step");
|
||||
}
|
||||
|
||||
@@ -149,6 +149,58 @@ fn text_field_named(ui: &mut egui::Ui, d: &mut Dialog, key: &str, w: f32, name:
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert Pages…, after page `abs` and with that page's parent, as InDesign's.
|
||||
pub(crate) fn open_insert_pages(app: &mut DesignApp, abs: usize) {
|
||||
let Some(st) = app.session.active() else { return };
|
||||
let abs = abs.min(st.doc.page_count().saturating_sub(1));
|
||||
let parent = st.doc.page(abs).and_then(|p| p.parent).map_or_else(String::new, |id| id.0.to_string());
|
||||
app.ui.dialog = Some(Dialog::new("insertPages", json!({"count": 1, "insert": "after", "page": abs, "parent": parent})));
|
||||
}
|
||||
|
||||
/// Insert Pages, as InDesign's: how many, where (after or before a page, at the start or the end
|
||||
/// of the document) and with which parent.
|
||||
fn insert_pages_dialog(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
let lang = app.ui.language.clone();
|
||||
let Some(st) = app.session.active() else { return };
|
||||
let pages: Vec<String> = (0..st.doc.page_count()).map(|i| app.session.page_label(i)).collect();
|
||||
let mut parents = vec![(String::new(), crate::i18n::tr(&lang, "[None]").to_string())];
|
||||
parents.extend(st.doc.parents.iter().map(|p| (p.id.0.to_string(), p.parent.as_ref().map(|i| i.label()).unwrap_or_default())));
|
||||
egui::Grid::new("insert_pages").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
let name = crate::rtl::label(ui, crate::i18n::tr(&lang, "Pages:"));
|
||||
let mut n = d.n("count").unwrap_or(1.0).clamp(1.0, 9999.0) as u32;
|
||||
if ui.add(egui::DragValue::new(&mut n).range(1..=9999)).labelled_by(name.id).changed() {
|
||||
d.fields.insert("count".into(), json!(n));
|
||||
}
|
||||
ui.end_row();
|
||||
let name = crate::rtl::label(ui, crate::i18n::tr(&lang, "Insert:"));
|
||||
ui.horizontal(|ui| {
|
||||
let wheres = [("after", "After Page"), ("before", "Before Page"), ("start", "At Start of Document"), ("end", "At End of Document")];
|
||||
translated_combo(&lang, ui, d, "insert", &wheres).labelled_by(name.id);
|
||||
// The page, by name: At Start and At End need none.
|
||||
ui.add_enabled_ui(matches!(d.s("insert").as_str(), "after" | "before"), |ui| {
|
||||
let cur = (d.n("page").unwrap_or(0.0).max(0.0) as usize).min(pages.len().saturating_sub(1));
|
||||
craft_ui::ComboBox::from_id_salt("insert_page")
|
||||
.selected_text(pages.get(cur).cloned().unwrap_or_default())
|
||||
.width(64.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (i, name) in pages.iter().enumerate() {
|
||||
if ui.selectable_label(i == cur, name).clicked() {
|
||||
d.fields.insert("page".into(), json!(i));
|
||||
}
|
||||
}
|
||||
})
|
||||
.response
|
||||
.accessible_name(crate::i18n::tr(&lang, "Page").to_owned());
|
||||
});
|
||||
});
|
||||
ui.end_row();
|
||||
let name = crate::rtl::label(ui, crate::i18n::tr(&lang, "Parent:"));
|
||||
let opts: Vec<(&str, &str)> = parents.iter().map(|(v, l)| (v.as_str(), l.as_str())).collect();
|
||||
combo(ui, d, "parent", &opts).labelled_by(name.id);
|
||||
ui.end_row();
|
||||
});
|
||||
}
|
||||
|
||||
/// Extract once when opened. Cancel is read-only; confirmation adds exactly these colours.
|
||||
pub(crate) fn open_color_theme(app: &mut DesignApp, params: Value) {
|
||||
match app.run("color.extractTheme", params) {
|
||||
@@ -186,6 +238,90 @@ fn color_theme(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
mod color_theme_tests {
|
||||
use super::*;
|
||||
|
||||
/// A page past the end shows as the last page in the dialog, and Before Page puts the new
|
||||
/// page before that one rather than at the end.
|
||||
#[test]
|
||||
fn insert_pages_before_a_page_past_the_end_goes_before_the_last() {
|
||||
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({"pages": 4, "facingPages": false})).unwrap();
|
||||
let ids = |app: &DesignApp| {
|
||||
let d = &app.session.doc().unwrap().doc;
|
||||
(0..d.page_count()).map(|i| d.page(i).unwrap().id).collect::<Vec<_>>()
|
||||
};
|
||||
let old = ids(&app);
|
||||
app.ui.dialog = Some(Dialog::new("insertPages", json!({"count": 1, "insert": "before", "page": 100, "parent": ""})));
|
||||
confirm(&mut app).unwrap();
|
||||
let now = ids(&app);
|
||||
assert_eq!(now.len(), 5);
|
||||
assert_eq!((now[..3].to_vec(), now[4]), (old[..3].to_vec(), old[3]), "the new page is fourth, before the old last page");
|
||||
}
|
||||
|
||||
/// The course's chapter 25: Insert Pages as InDesign's. It opens after the page in view with
|
||||
/// that page's parent; At Start of Document with B-Cover puts a B page first, and Before Page
|
||||
/// with [None] puts a page without a parent before the page chosen.
|
||||
#[test]
|
||||
fn insert_pages_goes_before_a_page_or_at_the_start_with_the_chosen_parent() {
|
||||
use egui::accesskit::Role;
|
||||
use egui_kittest::{Harness, kittest::Queryable};
|
||||
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
// Facing: [1] [2 3] [4].
|
||||
app.run("file.new", json!({"pages": 4})).unwrap();
|
||||
let b = app.run("layout.parents.new", json!({"prefix": "B", "name": "Cover"})).unwrap()["id"].as_u64().unwrap();
|
||||
let ids = |app: &DesignApp| -> Vec<u64> {
|
||||
let d = &app.session.doc().unwrap().doc;
|
||||
(0..d.page_count()).map(|i| d.page(i).unwrap().id.0).collect()
|
||||
};
|
||||
let old = ids(&app);
|
||||
crate::menus::activate(&mut app, "layout.pages.insert", &Value::Null);
|
||||
assert_eq!(app.ui.dialog.as_ref().unwrap().id, "insertPages");
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1000.0, 700.0)).build_ui_state(
|
||||
|ui, app: &mut DesignApp| {
|
||||
let key = egui::Id::unique("insert_pages_test_fonts");
|
||||
if ui.data(|d| d.get_temp::<bool>(key)).is_none() {
|
||||
crate::theme::install_fonts(ui.ctx(), "");
|
||||
ui.data_mut(|d| d.insert_temp(key, true));
|
||||
return;
|
||||
}
|
||||
show(app, ui.ctx());
|
||||
},
|
||||
app,
|
||||
);
|
||||
h.run_steps(3);
|
||||
for l in ["Pages:", "Insert:", "Parent:"] {
|
||||
assert!(h.query_by_label(l).is_some(), "{l}");
|
||||
}
|
||||
// The dropdown showing `shown`, then its item `choice`.
|
||||
let pick = |h: &mut Harness<'_, DesignApp>, shown: &str, choice: &str| {
|
||||
h.get_by(|n| n.role() == Role::ComboBox && n.value().as_deref() == Some(shown)).click();
|
||||
h.run_steps(2);
|
||||
h.get_by_label(choice).click();
|
||||
h.run_steps(2);
|
||||
};
|
||||
// After page 1 with A, at first; then At Start of Document, with B-Cover.
|
||||
pick(&mut h, "After Page", "At Start of Document");
|
||||
pick(&mut h, "A-Parent", "B-Cover");
|
||||
h.get_by_label(" OK ").click();
|
||||
h.run_steps(3);
|
||||
assert!(h.state().ui.dialog.is_none());
|
||||
let now = ids(h.state());
|
||||
assert_eq!(now[1..], old[..], "the new page is first");
|
||||
let parent = |app: &DesignApp, i: usize| app.session.doc().unwrap().doc.page(i).unwrap().parent.map(|p| p.0);
|
||||
assert_eq!(parent(h.state(), 0), Some(b));
|
||||
// Before page 4, with [None].
|
||||
crate::dialogs::open_insert_pages(h.state_mut(), 0);
|
||||
h.run_steps(3);
|
||||
pick(&mut h, "After Page", "Before Page");
|
||||
pick(&mut h, "1", "4");
|
||||
pick(&mut h, "B-Cover", "[None]");
|
||||
h.get_by_label(" OK ").click();
|
||||
h.run_steps(3);
|
||||
let then = ids(h.state());
|
||||
assert_eq!(then.len(), 6);
|
||||
assert_eq!(then[..3], now[..3], "the pages before it stay");
|
||||
assert_eq!(then[4..], now[3..], "page 4 and those after it follow the new page");
|
||||
assert_eq!(parent(h.state(), 3), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn color_theme_cancel_is_read_only_and_confirm_adds_the_preview() {
|
||||
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
@@ -2252,6 +2388,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
"newDocument" => crate::i18n::tr(&app.ui.language, "New Document"),
|
||||
"frameSize" => crate::i18n::tr(&app.ui.language, "Rectangle"),
|
||||
"goToPage" => crate::i18n::tr(&app.ui.language, "Go to Page"),
|
||||
"insertPages" => crate::i18n::tr(&app.ui.language, "Insert Pages"),
|
||||
"insertTable" => crate::i18n::tr(&app.ui.language, "Create Table"),
|
||||
"cellOptions" => crate::i18n::tr(&app.ui.language, "Cell Options"),
|
||||
"createGuides" => crate::i18n::tr(&app.ui.language, "Create Guides"),
|
||||
@@ -2323,6 +2460,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
let preferred_width: f32 = match d.id.as_str() {
|
||||
"alert" => 440.0,
|
||||
"closeDocument" | "updateLink" | "deletePages" | "newWorkspace" | "pagesPanelOptions" => 380.0,
|
||||
"insertPages" => 440.0,
|
||||
"newDocument" => 960.0,
|
||||
"hyphenation" => 560.0,
|
||||
"numberingSection" => 560.0,
|
||||
@@ -3013,6 +3151,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
STEP_AND_REPEAT => step_and_repeat_dialog(app, ui, &mut d),
|
||||
TOC => toc_dialog(app, ui, &mut d),
|
||||
id if id.starts_with("cmd:") => command_form(app, ui, &mut d),
|
||||
"insertPages" => insert_pages_dialog(app, ui, &mut d),
|
||||
"goToPage" => {
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Page"));
|
||||
@@ -3570,6 +3709,21 @@ fn confirm_part1(app: &mut DesignApp, d: Dialog) -> Result<Value, String> {
|
||||
)
|
||||
}
|
||||
"ruby" => app.run("type.ruby", style_cjk::ruby_params(&d)),
|
||||
"insertPages" => {
|
||||
let n = app.session.active().map_or(1, |st| st.doc.page_count());
|
||||
// The page the menu shows: a page past the end is the last.
|
||||
let page = (d.n("page").unwrap_or(0.0).max(0.0) as usize).min(n.saturating_sub(1));
|
||||
let mut p = json!({"count": d.n("count").unwrap_or(1.0).clamp(1.0, 9999.0) as u64});
|
||||
match d.s("insert").as_str() {
|
||||
"before" => p["before"] = json!(page),
|
||||
"start" => p["before"] = json!(0),
|
||||
"end" => p["after"] = json!(n.saturating_sub(1)),
|
||||
_ => p["after"] = json!(page),
|
||||
}
|
||||
// A parent's id, or [None].
|
||||
p["parent"] = d.s("parent").parse::<u64>().map_or(Value::Null, |id| json!(id));
|
||||
app.run("layout.pages.insert", p)
|
||||
}
|
||||
"goToPage" => {
|
||||
// A page name ("iv", "A-3"), a number, or "+n" for an absolute position.
|
||||
let typed = match d.fields.get("page") {
|
||||
|
||||
@@ -51,6 +51,12 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Double Column", "عمود مزدوج"),
|
||||
("Tools Panel:", "لوحة الأدوات:"),
|
||||
("Color Theme:", "سمة الألوان:"),
|
||||
("At End of Document", "في نهاية المستند"),
|
||||
("At Start of Document", "في بداية المستند"),
|
||||
("Before Page", "قبل الصفحة"),
|
||||
("After Page", "بعد الصفحة"),
|
||||
("Parent:", "الصفحة الأصلية:"),
|
||||
("Insert:", "إدراج:"),
|
||||
("Restart Numbering", "إعادة الترقيم"),
|
||||
("Continue Numbering", "متابعة الترقيم"),
|
||||
("Keep Options…", "خيارات الإبقاء…"),
|
||||
|
||||
@@ -54,6 +54,12 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Single Column", "Jednoduchý sloupec"),
|
||||
("Tools Panel:", "Panel nástrojů:"),
|
||||
("Color Theme:", "Barevný motiv:"),
|
||||
("At End of Document", "Na konec dokumentu"),
|
||||
("At Start of Document", "Na začátek dokumentu"),
|
||||
("Before Page", "Před stránku"),
|
||||
("After Page", "Za stránku"),
|
||||
("Parent:", "Vzor:"),
|
||||
("Insert:", "Vložit:"),
|
||||
("Restart Numbering", "Začít číslování znovu"),
|
||||
("Continue Numbering", "Pokračovat v číslování"),
|
||||
("Keep Options…", "Volby zachování…"),
|
||||
|
||||
@@ -168,7 +168,6 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Insert Cross-Reference", "Insérer une référence croisée"),
|
||||
("Insert Field", "Insérer un champ"),
|
||||
("Insert Math Expression", "Insérer une expression mathématique"),
|
||||
("Insert Pages", "Insérer des pages"),
|
||||
("Internet Standard RGB (sRGB)", "RVB standard Internet (sRGB)"),
|
||||
("Invalid panel layout; restored the default dock", "Disposition des panneaux non valide ; disposition par défaut restaurée"),
|
||||
("Join", "Joindre"),
|
||||
|
||||
@@ -49,6 +49,13 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Double Column", "Colonna doppia"),
|
||||
("Tools Panel:", "Pannello Strumenti:"),
|
||||
("Color Theme:", "Tema colore:"),
|
||||
("At End of Document", "Alla fine del documento"),
|
||||
("At Start of Document", "All'inizio del documento"),
|
||||
("Before Page", "Prima della pagina"),
|
||||
("After Page", "Dopo la pagina"),
|
||||
("Parent:", "Pagina mastro:"),
|
||||
("Insert:", "Inserisci:"),
|
||||
("Insert Pages", "Inserisci pagine"),
|
||||
("Restart Numbering", "Riavvia numerazione"),
|
||||
("Continue Numbering", "Continua numerazione"),
|
||||
("Keep Options…", "Opzioni di separazione…"),
|
||||
|
||||
@@ -52,6 +52,12 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Double Column", "ორმაგი სვეტი"),
|
||||
("Tools Panel:", "ხელსაწყოების პანელი:"),
|
||||
("Color Theme:", "ფერთა თემა:"),
|
||||
("At End of Document", "დოკუმენტის ბოლოს"),
|
||||
("At Start of Document", "დოკუმენტის დასაწყისში"),
|
||||
("Before Page", "გვერდის წინ"),
|
||||
("After Page", "გვერდის შემდეგ"),
|
||||
("Parent:", "საბაზო გვერდი:"),
|
||||
("Insert:", "ჩასმა:"),
|
||||
("Restart Numbering", "ნუმერაციის თავიდან დაწყება"),
|
||||
("Continue Numbering", "ნუმერაციის გაგრძელება"),
|
||||
("Keep Options…", "შენარჩუნების პარამეტრები…"),
|
||||
|
||||
@@ -52,6 +52,12 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Single Column", "Pojedyncza kolumna"),
|
||||
("Tools Panel:", "Panel narzędzi:"),
|
||||
("Color Theme:", "Motyw kolorów:"),
|
||||
("At End of Document", "Na końcu dokumentu"),
|
||||
("At Start of Document", "Na początku dokumentu"),
|
||||
("Before Page", "Przed stroną"),
|
||||
("After Page", "Po stronie"),
|
||||
("Parent:", "Strona wzorcowa:"),
|
||||
("Insert:", "Wstaw:"),
|
||||
("Restart Numbering", "Zacznij numerowanie od nowa"),
|
||||
("Continue Numbering", "Kontynuuj numerowanie"),
|
||||
("Keep Options…", "Opcje utrzymywania…"),
|
||||
|
||||
@@ -52,6 +52,13 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Double Column", "Coluna dupla"),
|
||||
("Tools Panel:", "Painel Ferramentas:"),
|
||||
("Color Theme:", "Tema de cores:"),
|
||||
("At End of Document", "No final do documento"),
|
||||
("At Start of Document", "No início do documento"),
|
||||
("Before Page", "Antes da página"),
|
||||
("After Page", "Após a página"),
|
||||
("Parent:", "Página principal:"),
|
||||
("Insert:", "Inserir:"),
|
||||
("Insert Pages", "Inserir páginas"),
|
||||
("Restart Numbering", "Reiniciar numeração"),
|
||||
("Continue Numbering", "Continuar numeração"),
|
||||
("Keep Options…", "Opções de manutenção…"),
|
||||
|
||||
@@ -56,6 +56,12 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Single Column", "Одна колонка"),
|
||||
("Tools Panel:", "Панель инструментов:"),
|
||||
("Color Theme:", "Цветовая тема:"),
|
||||
("At End of Document", "В конец документа"),
|
||||
("At Start of Document", "В начало документа"),
|
||||
("Before Page", "Перед страницей"),
|
||||
("After Page", "После страницы"),
|
||||
("Parent:", "Шаблон:"),
|
||||
("Insert:", "Вставить:"),
|
||||
("Restart Numbering", "Начать нумерацию заново"),
|
||||
("Continue Numbering", "Продолжить нумерацию"),
|
||||
("Keep Options…", "Параметры удержания…"),
|
||||
|
||||
@@ -2132,6 +2132,13 @@ pub(super) const TABLE: &[(&str, [&str; 5])] = &[
|
||||
["Insert Math Expression…", "Insérer une expression mathématique…", "Insert Math Expression…", "Insert Math Expression…", "插入数学公式…"],
|
||||
),
|
||||
("Insert Pages…", ["Insert Pages…", "Insérer des pages…", "Insert Pages…", "Insert Pages…", "插入页面…"]),
|
||||
("Insert Pages", ["Seiten einfügen", "Insérer des pages", "Insertar páginas", "ページを挿入", "插入页面"]),
|
||||
("Insert:", ["Einfügen:", "Insérer :", "Insertar:", "挿入:", "插入:"]),
|
||||
("Parent:", ["Vorlagenseite:", "Gabarit :", "Página principal:", "親ページ:", "主页:"]),
|
||||
("After Page", ["Nach Seite", "Après la page", "Después de la página", "ページの後", "页面后"]),
|
||||
("Before Page", ["Vor Seite", "Avant la page", "Antes de la página", "ページの前", "页面前"]),
|
||||
("At Start of Document", ["Am Dokumentanfang", "Au début du document", "Al principio del documento", "ドキュメントの先頭", "文档开头"]),
|
||||
("At End of Document", ["Am Dokumentende", "À la fin du document", "Al final del documento", "ドキュメントの末尾", "文档末尾"]),
|
||||
("Insert Variable", ["Insert Variable", "Insérer une variable", "Insert Variable", "Insert Variable", "插入变量"]),
|
||||
(
|
||||
"Convert Variable to Text",
|
||||
|
||||
@@ -50,6 +50,13 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Double Column", "Подвійна колонка"),
|
||||
("Tools Panel:", "Панель інструментів:"),
|
||||
("Color Theme:", "Колірна тема:"),
|
||||
("At End of Document", "У кінець документа"),
|
||||
("At Start of Document", "На початок документа"),
|
||||
("Before Page", "Перед сторінкою"),
|
||||
("After Page", "Після сторінки"),
|
||||
("Parent:", "Шаблон:"),
|
||||
("Insert:", "Вставити:"),
|
||||
("Insert Pages", "Вставити сторінки"),
|
||||
("Restart Numbering", "Почати нумерацію знову"),
|
||||
("Continue Numbering", "Продовжити нумерацію"),
|
||||
("Keep Options…", "Параметри утримання…"),
|
||||
|
||||
@@ -66,6 +66,11 @@ fn activate_inner(app: &mut DesignApp, id: &str, params: &Value) {
|
||||
crate::section_options::open(app);
|
||||
return;
|
||||
}
|
||||
if params.is_null() && id == "layout.pages.insert" {
|
||||
let cur = crate::canvas::current_page(app).unwrap_or(0);
|
||||
crate::dialogs::open_insert_pages(app, cur);
|
||||
return;
|
||||
}
|
||||
if params.is_null() && id == "layout.createGuides" {
|
||||
crate::dialogs::open_create_guides(app);
|
||||
return;
|
||||
|
||||
@@ -646,7 +646,7 @@ fn empty_menu(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let cur = crate::canvas::current_page(app).unwrap_or(0);
|
||||
let item = |ui: &mut egui::Ui, label: &str| ui.button(crate::rtl::widget(ui, crate::i18n::tr(&lang, label))).clicked();
|
||||
if item(ui, "Insert Pages…") {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("cmd:layout.pages.insert", json!({"after": cur, "count": 1})));
|
||||
crate::dialogs::open_insert_pages(app, cur);
|
||||
ui.close();
|
||||
}
|
||||
if item(ui, "Move Pages…") {
|
||||
@@ -680,7 +680,7 @@ fn page_menu(app: &mut DesignApp, ui: &mut egui::Ui, doc: &designcraft_doc::Docu
|
||||
let item = |ui: &mut egui::Ui, label: &str| ui.button(crate::rtl::widget(ui, tr(label))).clicked();
|
||||
// InDesign's order: pages, parents, layouts and numbering, shuffling.
|
||||
if item(ui, "Insert Pages…") {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("cmd:layout.pages.insert", json!({"after": abs, "count": 1})));
|
||||
crate::dialogs::open_insert_pages(app, abs);
|
||||
ui.close();
|
||||
}
|
||||
if item(ui, "Move Pages…") {
|
||||
|
||||
@@ -343,7 +343,7 @@ fn the_panel_menu_follows_indesigns_order() {
|
||||
assert_eq!(h.state().session.doc().unwrap().doc.page_count(), 3);
|
||||
h.get_by_label("Insert Pages…").click();
|
||||
h.run_steps(3);
|
||||
assert!(h.state().ui.dialog.as_ref().is_some_and(|d| d.id == "cmd:layout.pages.insert"));
|
||||
assert!(h.state().ui.dialog.as_ref().is_some_and(|d| d.id == "insertPages"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user