mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-01 22:26:49 -06:00
UI: add translation for remained UI
This commit is contained in:
committed by
Brandon Thomas
parent
9d85777546
commit
11900ad923
@@ -113,7 +113,12 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "DesignCraft")).font(semibold(26.0)).color(t.text_strong),
|
||||
));
|
||||
ui.label(egui::RichText::new(format!("Version {}", env!("CARGO_PKG_VERSION"))).size(12.0).color(t.text_dim));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(format!("{} {}", crate::i18n::tr(&app.ui.language, "Version"), env!("CARGO_PKG_VERSION")))
|
||||
.size(12.0)
|
||||
.color(t.text_dim),
|
||||
);
|
||||
ui.add_space(4.0);
|
||||
ui.label(crate::rtl::widget(
|
||||
ui,
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn app_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let mut menus_end = full.min.x;
|
||||
let mut tools_start = full.max.x;
|
||||
ui.horizontal_centered(|ui| {
|
||||
if icons::button(ui, "home", 24.0, app.session.active().is_none(), "Home").clicked() {
|
||||
if icons::button(ui, "home", 24.0, app.session.active().is_none(), crate::i18n::tr(&app.ui.language, "Home")).clicked() {
|
||||
app.session_home();
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
@@ -40,10 +40,18 @@ pub fn app_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let (r, _) = ui.allocate_exact_size(vec2(125.0, 18.0), Sense::click());
|
||||
ui.painter().rect(r, 1.0, t.input, Stroke::new(1.0, t.field_border), egui::StrokeKind::Inside);
|
||||
icons::paint(ui.painter(), egui::Rect::from_min_size(r.min + vec2(3.0, 2.0), vec2(14.0, 14.0)), "search", t.icon);
|
||||
ui.painter().text(r.min + vec2(20.0, 9.0), egui::Align2::LEFT_CENTER, "Search", egui::FontId::proportional(11.0), t.text_dim);
|
||||
crate::rtl::paint(
|
||||
ui.painter(),
|
||||
r.min + vec2(20.0, 9.0),
|
||||
egui::Align2::LEFT_CENTER,
|
||||
crate::i18n::tr(&app.ui.language, "Search"),
|
||||
egui::FontId::proportional(11.0),
|
||||
t.text_dim,
|
||||
);
|
||||
ui.add_space(8.0);
|
||||
let current = app.ui.workspace.clone();
|
||||
ui.menu_button(egui::RichText::new(format!("{current} ▾")).font(semibold(11.5)).color(t.text), |ui| {
|
||||
let shown = crate::i18n::workspace_name(&app.ui.language, ¤t);
|
||||
ui.menu_button(crate::rtl::widget(ui, egui::RichText::new(format!("{shown} ▾")).font(semibold(11.5)).color(t.text)), |ui| {
|
||||
let customs: Vec<String> = app.ui.custom_workspaces.iter().map(|w| w.name.clone()).collect();
|
||||
for w in
|
||||
["Essentials", "Advanced", "Book", "Digital Publishing", "Interactive for PDF", "Printing and Proofing", "Typography"]
|
||||
@@ -51,13 +59,20 @@ pub fn app_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
.map(str::to_string)
|
||||
.chain(customs.iter().cloned())
|
||||
{
|
||||
if ui.selectable_label(w == current, &w).clicked() {
|
||||
if ui.selectable_label(w == current, crate::rtl::widget(ui, crate::i18n::workspace_name(&app.ui.language, &w))).clicked()
|
||||
{
|
||||
let _ = app.run("window.workspace", json!({"name": w}));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
if ui.button(format!("Reset {current}")).clicked() {
|
||||
if ui
|
||||
.button(crate::rtl::widget(
|
||||
ui,
|
||||
format!("{} {}", crate::i18n::tr(&app.ui.language, "Reset"), crate::i18n::workspace_name(&app.ui.language, ¤t)),
|
||||
))
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("window.resetWorkspace", json!({}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -77,7 +92,7 @@ pub fn app_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
if icons::button(ui, "share", 22.0, false, "Share").clicked() {
|
||||
if icons::button(ui, "share", 22.0, false, crate::i18n::tr(&app.ui.language, "Share")).clicked() {
|
||||
app.status("Export a PDF, IDML or package to share — no cloud account needed.");
|
||||
}
|
||||
ui.add_space(8.0);
|
||||
@@ -143,7 +158,9 @@ pub fn control_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
fn icon_caption(ui: &mut egui::Ui, icon: &str, tip: &str) {
|
||||
let (r, resp) = ui.allocate_exact_size(vec2(16.0, 16.0), Sense::hover());
|
||||
icons::paint(ui.painter(), r, icon, Tokens::get(ui.ctx()).icon);
|
||||
resp.on_hover_text(tip);
|
||||
resp.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, tip);
|
||||
});
|
||||
}
|
||||
|
||||
fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
@@ -159,20 +176,20 @@ fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
None => (None, None, None, None),
|
||||
};
|
||||
egui::Grid::new("ctl_xywh").num_columns(4).spacing(vec2(4.0, 4.0)).show(ui, |ui| {
|
||||
caption(ui, "X:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "X:"));
|
||||
if let Some(v) = measure(ui, "cx", x, units, 64.0) {
|
||||
let _ = app.run("transform.set", json!({"x": v}));
|
||||
}
|
||||
caption(ui, "W:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "W:"));
|
||||
if let Some(v) = measure(ui, "cw", w, units, 64.0) {
|
||||
let _ = app.run("transform.set", json!({"width": v}));
|
||||
}
|
||||
ui.end_row();
|
||||
caption(ui, "Y:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Y:"));
|
||||
if let Some(v) = measure(ui, "cy", y, units, 64.0) {
|
||||
let _ = app.run("transform.set", json!({"y": v}));
|
||||
}
|
||||
caption(ui, "H:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "H:"));
|
||||
if let Some(v) = measure(ui, "ch", h, units, 64.0) {
|
||||
let _ = app.run("transform.set", json!({"height": v}));
|
||||
}
|
||||
@@ -183,20 +200,20 @@ fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let tv = if info.is_some() { app.session.execute("transform.info", &json!({})).ok() } else { None };
|
||||
let tv_get = |k: &str| tv.as_ref().and_then(|v| v[k].as_f64());
|
||||
egui::Grid::new("ctl_srs").num_columns(4).spacing(vec2(4.0, 4.0)).show(ui, |ui| {
|
||||
icon_caption(ui, "tool-scale", "Scale X Percentage");
|
||||
icon_caption(ui, "tool-scale", crate::i18n::tr(&app.ui.language, "Scale X Percentage"));
|
||||
if let Some(v) = number(ui, "csx", tv_get("scaleX"), "%", 56.0, 1) {
|
||||
let _ = app.run("transform.set", json!({"scaleX": v}));
|
||||
}
|
||||
icon_caption(ui, "tool-rotate", "Rotation Angle");
|
||||
icon_caption(ui, "tool-rotate", crate::i18n::tr(&app.ui.language, "Rotation Angle"));
|
||||
if let Some(v) = number(ui, "crot", tv_get("rotation"), "°", 50.0, 1) {
|
||||
let _ = app.run("transform.set", json!({"rotation": v}));
|
||||
}
|
||||
ui.end_row();
|
||||
icon_caption(ui, "tool-scale", "Scale Y Percentage");
|
||||
icon_caption(ui, "tool-scale", crate::i18n::tr(&app.ui.language, "Scale Y Percentage"));
|
||||
if let Some(v) = number(ui, "csy", tv_get("scaleY"), "%", 56.0, 1) {
|
||||
let _ = app.run("transform.set", json!({"scaleY": v}));
|
||||
}
|
||||
icon_caption(ui, "tool-shear", "Shear X Angle");
|
||||
icon_caption(ui, "tool-shear", crate::i18n::tr(&app.ui.language, "Shear X Angle"));
|
||||
if let Some(v) = number(ui, "cshr", tv_get("shear"), "°", 50.0, 1) {
|
||||
let _ = app.run("transform.set", json!({"shear": v}));
|
||||
}
|
||||
@@ -206,7 +223,7 @@ fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Rotate / flip.
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if icons::button(ui, "tool-rotate", 20.0, false, "Rotate 90° Counterclockwise").clicked() {
|
||||
if icons::button(ui, "tool-rotate", 20.0, false, crate::i18n::tr(&app.ui.language, "Rotate 90° Counterclockwise")).clicked() {
|
||||
let _ = app.run("transform.rotate", json!({"angle": 90}));
|
||||
}
|
||||
if ui
|
||||
@@ -244,13 +261,13 @@ fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Fill / stroke.
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Fill");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Fill"));
|
||||
panels::swatch_picker(app, ui, "ctlfill", info.as_ref().map(|i| i.fill.clone()), |app, name| {
|
||||
let _ = app.run("object.fill", json!({"swatch": name}));
|
||||
});
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Stroke");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Stroke"));
|
||||
panels::swatch_picker(app, ui, "ctlstroke", info.as_ref().map(|i| i.stroke.clone()), |app, name| {
|
||||
let _ = app.run("object.stroke", json!({"swatch": name}));
|
||||
});
|
||||
@@ -263,13 +280,15 @@ fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Opacity, fx.
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Opacity");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Opacity"));
|
||||
if let Some(v) = number(ui, "cop", info.as_ref().map(|i| i.opacity * 100.0), "%", 42.0, 0) {
|
||||
let _ = app.run("object.opacity", json!({"opacity": v / 100.0}));
|
||||
}
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
if icons::button(ui, "panel-effects", 20.0, info.as_ref().is_some_and(|i| i.shadow), "Drop Shadow").clicked() {
|
||||
if icons::button(ui, "panel-effects", 20.0, info.as_ref().is_some_and(|i| i.shadow), crate::i18n::tr(&app.ui.language, "Drop Shadow"))
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("object.dropShadow", json!({}));
|
||||
}
|
||||
});
|
||||
@@ -325,7 +344,7 @@ fn control_object(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
vsep(ui);
|
||||
ui.vertical(|ui| {
|
||||
caption(ui, "Columns");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Columns"));
|
||||
if let Some(v) = number(ui, "ccols", Some(cols as f64), "", 36.0, 0) {
|
||||
let _ = app.run("object.textFrameOptions", json!({"columns": v.max(1.0) as u64}));
|
||||
}
|
||||
@@ -359,7 +378,7 @@ fn control_text(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if let Some(v) = number(ui, "csize", chars["size"].as_f64(), " pt", 54.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"size": v}}));
|
||||
}
|
||||
caption(ui, "VA");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "VA"));
|
||||
if let Some(v) = number(ui, "ctrack", chars["tracking"].as_f64(), "", 48.0, 0) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"tracking": v}}));
|
||||
}
|
||||
@@ -372,7 +391,7 @@ fn control_text(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if let Some(v) = number(ui, "clead", lead, " pt", 54.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"leading": {"kind": "points", "value": v}}}));
|
||||
}
|
||||
caption(ui, "IT");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "IT"));
|
||||
if let Some(v) = number(ui, "chs", chars["hScale"].as_f64().map(|v| v * 100.0), "%", 48.0, 0) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"hScale": v / 100.0}}));
|
||||
}
|
||||
@@ -426,7 +445,7 @@ fn control_text(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
panels::para_style_picker(app, ui, &ps, ov > 0, 170.0);
|
||||
let hy = para["hyphenate"].as_bool().unwrap_or(true);
|
||||
let mut h = hy;
|
||||
if ui.checkbox(&mut h, "Hyphenate").changed() {
|
||||
if ui.checkbox(&mut h, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Hyphenate"))).changed() {
|
||||
let _ = app.run("type.para", json!({"attrs": {"hyphenate": h}}));
|
||||
}
|
||||
});
|
||||
@@ -503,10 +522,10 @@ pub fn status_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.add_space(8.0);
|
||||
let n = app.session.active().map(|d| d.doc.page_count()).unwrap_or(1);
|
||||
let cur = crate::canvas::current_page(app).unwrap_or(0);
|
||||
if icons::button(ui, "first", 14.0, false, "First Spread").clicked() {
|
||||
if icons::button(ui, "first", 14.0, false, crate::i18n::tr(&app.ui.language, "First Spread")).clicked() {
|
||||
crate::canvas::go_to_page(app, 0);
|
||||
}
|
||||
if icons::button(ui, "prev", 14.0, false, "Previous Spread").clicked() {
|
||||
if icons::button(ui, "prev", 14.0, false, crate::i18n::tr(&app.ui.language, "Previous Spread")).clicked() {
|
||||
crate::canvas::go_to_page(app, cur.saturating_sub(1));
|
||||
}
|
||||
let name = app.session.page_label(cur);
|
||||
@@ -525,10 +544,10 @@ pub fn status_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
});
|
||||
});
|
||||
if icons::button(ui, "next", 14.0, false, "Next Spread").clicked() {
|
||||
if icons::button(ui, "next", 14.0, false, crate::i18n::tr(&app.ui.language, "Next Spread")).clicked() {
|
||||
crate::canvas::go_to_page(app, (cur + 1).min(n - 1));
|
||||
}
|
||||
if icons::button(ui, "last", 14.0, false, "Last Spread").clicked() {
|
||||
if icons::button(ui, "last", 14.0, false, crate::i18n::tr(&app.ui.language, "Last Spread")).clicked() {
|
||||
crate::canvas::go_to_page(app, n - 1);
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
@@ -542,11 +561,12 @@ pub fn status_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
4.0,
|
||||
if errors == 0 { Color32::from_rgb(60, 200, 90) } else { Color32::from_rgb(235, 50, 50) },
|
||||
);
|
||||
ui.label(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(if errors == 0 {
|
||||
"No errors ▾".to_string()
|
||||
format!("{} ▾", crate::i18n::tr(&app.ui.language, "No errors"))
|
||||
} else {
|
||||
format!("{errors} error{} ▾", if errors == 1 { "" } else { "s" })
|
||||
format!("{errors} {} ▾", crate::i18n::tr(&app.ui.language, if errors == 1 { "error" } else { "errors" }))
|
||||
})
|
||||
.font(small.clone()),
|
||||
);
|
||||
|
||||
+236
-146
@@ -107,7 +107,7 @@ fn text_field(ui: &mut egui::Ui, d: &mut Dialog, key: &str, w: f32) {
|
||||
/// new keys (Esc cancels, Backspace clears).
|
||||
/// Edit › Spelling › User Dictionary: added words and hyphenation exceptions (applied at once).
|
||||
fn user_dictionary(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
ui.label(egui::RichText::new("Hyphenation Exceptions").font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Hyphenation Exceptions")).font(semibold(12.0)));
|
||||
ui.label(crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(
|
||||
@@ -136,7 +136,7 @@ fn user_dictionary(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
let w = w.as_str().unwrap_or("").to_string();
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(&w);
|
||||
if ui.small_button("Remove").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Remove"))).clicked() {
|
||||
let _ = app.run("hyphenation.removeException", json!({"word": w}));
|
||||
}
|
||||
});
|
||||
@@ -146,7 +146,11 @@ fn user_dictionary(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
|
||||
fn keyboard_shortcuts(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
let mut q = d.s("query");
|
||||
ui.add(egui::TextEdit::singleline(&mut q).hint_text("Search commands").desired_width(f32::INFINITY));
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(&mut q)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Search commands")))
|
||||
.desired_width(f32::INFINITY),
|
||||
);
|
||||
d.fields.insert("query".into(), json!(q));
|
||||
let recording = d.s("recording");
|
||||
// Capture the next key press for the command being recorded.
|
||||
@@ -188,7 +192,7 @@ fn keyboard_shortcuts(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
egui::ScrollArea::vertical().max_height(360.0).show(ui, |ui| {
|
||||
egui::Grid::new("shortcuts").num_columns(3).striped(true).spacing([12.0, 4.0]).show(ui, |ui| {
|
||||
for (id, label, menu) in &rows {
|
||||
ui.label(label.trim_end_matches('…'))
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label.trim_end_matches('…')))
|
||||
.on_hover_text(format!("{id}{}", if menu.is_empty() { String::new() } else { format!(" ({menu})") }));
|
||||
let cur = crate::menus::shortcut_of(app, id).map(|s| crate::menus::shortcut_text(&s)).unwrap_or_else(|| "—".into());
|
||||
let text = if recording == *id { "Press keys…".to_string() } else { cur };
|
||||
@@ -197,7 +201,7 @@ fn keyboard_shortcuts(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
d.fields.insert("message".into(), json!(""));
|
||||
}
|
||||
if app.ui.shortcuts.contains_key(id) {
|
||||
if ui.small_button("Default").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Default"))).clicked() {
|
||||
let _ = app.run("window.setShortcut", json!({"id": id, "shortcut": null}));
|
||||
}
|
||||
} else {
|
||||
@@ -303,7 +307,7 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
.width(110.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [("print", "Print"), ("web", "Web"), ("mobile", "Mobile")] {
|
||||
if ui.selectable_label(cur == v, l).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
d.fields.insert("intent".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -319,22 +323,22 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Start Page #:"));
|
||||
text_field(ui, d, "startPage", 60.0);
|
||||
ui.end_row();
|
||||
ui.label("Binding:");
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Binding:"));
|
||||
let rtl = d.s("binding") == "rightToLeft";
|
||||
egui::ComboBox::from_id_salt("ds_binding").selected_text(if rtl { "Right to Left" } else { "Left to Right" }).width(110.0).show_ui(
|
||||
ui,
|
||||
|ui| {
|
||||
egui::ComboBox::from_id_salt("ds_binding")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if rtl { "Right to Left" } else { "Left to Right" })))
|
||||
.width(110.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [("leftToRight", "Left to Right"), ("rightToLeft", "Right to Left")] {
|
||||
if ui.selectable_label((v == "rightToLeft") == rtl, l).clicked() {
|
||||
if ui.selectable_label((v == "rightToLeft") == rtl, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
d.fields.insert("binding".into(), json!(v));
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
ui.end_row();
|
||||
});
|
||||
ui.add_space(8.0);
|
||||
ui.label(egui::RichText::new("Page Size").font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Page Size")).font(semibold(12.0)));
|
||||
let (w, h) = (d.m("width").unwrap_or(612.0), d.m("height").unwrap_or(792.0));
|
||||
let preset =
|
||||
designcraft_doc::build::PRESETS.iter().find(|p| (p.width - w).abs() < 0.5 && (p.height - h).abs() < 0.5).map_or("Custom", |p| p.name);
|
||||
@@ -351,7 +355,9 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Orientation:"));
|
||||
ui.horizontal(|ui| {
|
||||
for (portrait, l) in [(true, "Portrait"), (false, "Landscape")] {
|
||||
if ui.selectable_label((h >= w) == portrait, l).clicked() && (h >= w) != portrait {
|
||||
if ui.selectable_label((h >= w) == portrait, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked()
|
||||
&& (h >= w) != portrait
|
||||
{
|
||||
let (fw, fh) = (d.s("width"), d.s("height"));
|
||||
d.fields.insert("width".into(), json!(fh));
|
||||
d.fields.insert("height".into(), json!(fw));
|
||||
@@ -370,11 +376,11 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
egui::Grid::new("ds_bleed").num_columns(5).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
ui.label("");
|
||||
for e in ["Top", "Bottom", "Inside", "Outside"] {
|
||||
ui.label(e);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, e));
|
||||
}
|
||||
ui.end_row();
|
||||
for (k, l) in [("bleed", "Bleed:"), ("slug", "Slug:")] {
|
||||
ui.label(l);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
for e in ["Top", "Bottom", "Inside", "Outside"] {
|
||||
text_field(ui, d, &format!("{k}{e}"), 60.0);
|
||||
}
|
||||
@@ -431,7 +437,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
ui.vertical(|ui| {
|
||||
ui.set_width(150.0);
|
||||
for (id, label) in sections {
|
||||
if ui.selectable_label(cur == *id, *label).clicked() {
|
||||
if ui.selectable_label(cur == *id, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
d.fields.insert("section".into(), json!(id));
|
||||
}
|
||||
}
|
||||
@@ -457,7 +463,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
}
|
||||
}
|
||||
"spelling" => {
|
||||
ui.label(egui::RichText::new("Dynamic Spelling").font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Dynamic Spelling")).font(semibold(12.0)));
|
||||
check(ui, d, "dynamicSpelling", crate::i18n::tr(&app.ui.language, "Enable Dynamic Spelling (underline misspelled words)"));
|
||||
}
|
||||
"autocorrect" => {
|
||||
@@ -542,7 +548,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Position"));
|
||||
ui.end_row();
|
||||
for (k, l) in [("superscript", "Superscript:"), ("subscript", "Subscript:")] {
|
||||
ui.label(l);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
for f in ["Size", "Position"] {
|
||||
ui.horizontal(|ui| {
|
||||
text_field(ui, d, &format!("adv.{k}{f}"), 50.0);
|
||||
@@ -562,11 +568,17 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "On Screen:"));
|
||||
let rich = d.b("richBlack");
|
||||
egui::ComboBox::from_id_salt("pref_black")
|
||||
.selected_text(if rich { "Display All Blacks as Rich Black" } else { "Display All Blacks Accurately" })
|
||||
.selected_text(crate::rtl::widget(
|
||||
ui,
|
||||
crate::i18n::tr(
|
||||
&app.ui.language,
|
||||
if rich { "Display All Blacks as Rich Black" } else { "Display All Blacks Accurately" },
|
||||
),
|
||||
))
|
||||
.width(240.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [(false, "Display All Blacks Accurately"), (true, "Display All Blacks as Rich Black")] {
|
||||
if ui.selectable_label(v == rich, l).clicked() {
|
||||
if ui.selectable_label(v == rich, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
d.fields.insert("richBlack".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -576,11 +588,17 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Printing / Exporting:"));
|
||||
let rich = d.b("richBlackOutput");
|
||||
egui::ComboBox::from_id_salt("pref_black_out")
|
||||
.selected_text(if rich { "Output All Blacks as Rich Black" } else { "Output All Blacks Accurately" })
|
||||
.selected_text(crate::rtl::widget(
|
||||
ui,
|
||||
crate::i18n::tr(
|
||||
&app.ui.language,
|
||||
if rich { "Output All Blacks as Rich Black" } else { "Output All Blacks Accurately" },
|
||||
),
|
||||
))
|
||||
.width(240.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [(false, "Output All Blacks Accurately"), (true, "Output All Blacks as Rich Black")] {
|
||||
if ui.selectable_label(v == rich, l).clicked() {
|
||||
if ui.selectable_label(v == rich, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
d.fields.insert("richBlackOutput".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -596,7 +614,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
}
|
||||
}
|
||||
"interface" => {
|
||||
ui.label(egui::RichText::new("UI Scaling").font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "UI Scaling")).font(semibold(12.0)));
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "UI Size:"));
|
||||
let mut v = d.n("uiScale").unwrap_or(100.0);
|
||||
@@ -616,16 +634,18 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Relative To:"));
|
||||
let cur = d.s("bg.relativeTo");
|
||||
egui::ComboBox::from_id_salt("bg_rel").selected_text(if cur == "topMargin" { "Top Margin" } else { "Top of Page" }).show_ui(
|
||||
ui,
|
||||
|ui| {
|
||||
egui::ComboBox::from_id_salt("bg_rel")
|
||||
.selected_text(crate::rtl::widget(
|
||||
ui,
|
||||
crate::i18n::tr(&app.ui.language, if cur == "topMargin" { "Top Margin" } else { "Top of Page" }),
|
||||
))
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [("topOfPage", "Top of Page"), ("topMargin", "Top Margin")] {
|
||||
if ui.selectable_label(cur == v, l).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
d.fields.insert("bg.relativeTo".into(), json!(v));
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Increment Every:"));
|
||||
text_field(ui, d, "bg.increment", 80.0);
|
||||
@@ -656,10 +676,10 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
check(ui, d, "grid.inBack", crate::i18n::tr(&app.ui.language, "Grids in Back"));
|
||||
}
|
||||
"guides" => {
|
||||
ui.label(egui::RichText::new("Color").font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Color")).font(semibold(12.0)));
|
||||
egui::Grid::new("pref_guides").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
for (k, l) in [("marginColor", "Margins:"), ("columnColor", "Columns:"), ("bleedColor", "Bleed:"), ("slugColor", "Slug:")] {
|
||||
ui.label(l);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
color_field(ui, d, k);
|
||||
ui.end_row();
|
||||
}
|
||||
@@ -703,7 +723,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
})
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [("fast", "Fast"), ("typical", "Typical"), ("high", "High Quality")] {
|
||||
if ui.selectable_label(cur == v, l).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
d.fields.insert("displayQuality".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -714,15 +734,21 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Ruler Units")).font(semibold(12.0)));
|
||||
egui::Grid::new("pref_units").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
for (key, label) in [("horizontalUnits", "Horizontal:"), ("verticalUnits", "Vertical:")] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
let cur: Unit = d.fields.get(key).and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
|
||||
egui::ComboBox::from_id_salt(key).selected_text(cur.label()).width(140.0).show_ui(ui, |ui| {
|
||||
for u in Unit::ALL {
|
||||
if ui.selectable_label(u == cur, u.label()).clicked() {
|
||||
d.fields.insert(key.into(), json!(u));
|
||||
egui::ComboBox::from_id_salt(key)
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur.label())))
|
||||
.width(140.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for u in Unit::ALL {
|
||||
if ui
|
||||
.selectable_label(u == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, u.label())))
|
||||
.clicked()
|
||||
{
|
||||
d.fields.insert(key.into(), json!(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
@@ -740,7 +766,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "When Scaling")).font(semibold(12.0)));
|
||||
check(ui, d, "scaleStrokes", crate::i18n::tr(&app.ui.language, "Include Stroke Weight"));
|
||||
ui.add_space(6.0);
|
||||
ui.label(egui::RichText::new("Transform").font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Transform")).font(semibold(12.0)));
|
||||
check(ui, d, "dimensionsIncludeStroke", crate::i18n::tr(&app.ui.language, "Dimensions Include Stroke Weight"));
|
||||
check(ui, d, "transformationsAreTotals", crate::i18n::tr(&app.ui.language, "Transformations are Totals"));
|
||||
ui.add_space(6.0);
|
||||
@@ -906,7 +932,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
"findChange" => {
|
||||
ui.horizontal(|ui| {
|
||||
for (label, grep) in [("Text", false), ("GREP", true)] {
|
||||
if ui.selectable_label(!d.b("objectMode") && d.b("grep") == grep, label).clicked() {
|
||||
if ui.selectable_label(!d.b("objectMode") && d.b("grep") == grep, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
d.fields.insert("grep".into(), json!(grep));
|
||||
d.fields.insert("objectMode".into(), json!(false));
|
||||
}
|
||||
@@ -920,10 +946,10 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
let swatches: Vec<String> = app.session.active().map(|st| st.doc.swatches.iter().filter(|w| !w.hidden).map(|w| w.name.clone()).collect()).unwrap_or_default();
|
||||
egui::Grid::new("fco").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
for (key, label, any) in [("objFill", "Find fill:", "(any)"), ("objChangeFill", "Change fill to:", "(unchanged)")] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
let cur = d.s(key);
|
||||
egui::ComboBox::from_id_salt(key).selected_text(if cur.is_empty() { any } else { cur.as_str() }).width(180.0).show_ui(ui, |ui| {
|
||||
if ui.selectable_label(cur.is_empty(), any).clicked() {
|
||||
if ui.selectable_label(cur.is_empty(), crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, any))).clicked() {
|
||||
d.fields.insert(key.into(), json!(""));
|
||||
}
|
||||
for w in &swatches {
|
||||
@@ -938,7 +964,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
let cur = d.s("objKind");
|
||||
egui::ComboBox::from_id_salt("objKind").selected_text(if cur.is_empty() { "(any)" } else { cur.as_str() }).show_ui(ui, |ui| {
|
||||
for v in ["", "text", "graphic", "shape", "line", "group"] {
|
||||
if ui.selectable_label(cur == v, if v.is_empty() { "(any)" } else { v }).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if v.is_empty() { "(any)" } else { v }))).clicked() {
|
||||
d.fields.insert("objKind".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -975,9 +1001,9 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Search:"));
|
||||
let cur = d.s("scope");
|
||||
egui::ComboBox::from_id_salt("fcscope").selected_text(&cur).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt("fcscope").selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur))).show_ui(ui, |ui| {
|
||||
for v in ["document", "story", "selection"] {
|
||||
if ui.selectable_label(cur == v, v).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, v))).clicked() {
|
||||
d.fields.insert("scope".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -1030,7 +1056,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
"pdfImport" => {
|
||||
ui.label(egui::RichText::new(d.s("path")).size(11.0));
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!("Page (1–{}):", d.n("pages").unwrap_or(1.0)));
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Page (1–{count}):").replace("{count}", &d.n("pages").unwrap_or(1.0).to_string()));
|
||||
text_field(ui, &mut d, "page", 60.0);
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
@@ -1043,7 +1069,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
"media" => crate::i18n::tr(&app.ui.language, "Media"),
|
||||
_ => crate::i18n::tr(&app.ui.language, "Crop"),
|
||||
};
|
||||
egui::ComboBox::from_id_salt("pdf_crop").selected_text(label(&cur)).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt("pdf_crop").selected_text(crate::rtl::widget(ui, label(&cur))).show_ui(ui, |ui| {
|
||||
for v in ["crop", "trim", "bleed", "art", "media"] {
|
||||
if ui.selectable_label(label(&cur) == label(v), label(v)).clicked() {
|
||||
d.fields.insert("crop".into(), json!(v));
|
||||
@@ -1069,7 +1095,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
let profiles = d.fields.get("profiles").and_then(Value::as_array).cloned().unwrap_or_default();
|
||||
egui::Grid::new("color_settings").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
for (key, label, kind) in [("rgb", "RGB:", "rgb"), ("cmyk", "CMYK:", "cmyk")] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
let cur = d.s(key);
|
||||
egui::ComboBox::from_id_salt(("ws", key)).selected_text(&cur).width(260.0).show_ui(ui, |ui| {
|
||||
for pr in profiles.iter().filter(|p| p["kind"] == kind) {
|
||||
@@ -1084,10 +1110,10 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Intent:"));
|
||||
let cur = d.s("intent");
|
||||
egui::ComboBox::from_id_salt("ws_intent")
|
||||
.selected_text(designcraft_color::cms::Intent::parse(&cur).map_or("", |i| i.label()))
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, designcraft_color::cms::Intent::parse(&cur).map_or("", |i| i.label()))))
|
||||
.show_ui(ui, |ui| {
|
||||
for i in designcraft_color::cms::Intent::ALL {
|
||||
if ui.selectable_label(i.id() == cur, i.label()).clicked() {
|
||||
if ui.selectable_label(i.id() == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, i.label()))).clicked() {
|
||||
d.fields.insert("intent".into(), json!(i.id()));
|
||||
}
|
||||
}
|
||||
@@ -1116,7 +1142,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
for (menu, label) in crate::menus::all_menu_items().into_iter().filter(|(m, l)| q.is_empty() || m.to_lowercase().contains(&q) || l.to_lowercase().contains(&q)) {
|
||||
let key = crate::menus::menu_key(&menu, &label);
|
||||
let mut visible = !app.ui.hidden_menu_items.contains(&key);
|
||||
if ui.checkbox(&mut visible, format!("{menu} › {label}")).changed() {
|
||||
if ui.checkbox(&mut visible, crate::rtl::widget(ui, format!("{} › {}", crate::i18n::tr(&app.ui.language, &menu), crate::i18n::tr(&app.ui.language, &label)))).changed() {
|
||||
let _ = app.run("window.hideMenuItem", json!({"item": key, "hidden": !visible}));
|
||||
}
|
||||
}
|
||||
@@ -1128,7 +1154,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
if !d.b("removeStyles") {
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Style Name Conflicts")).font(semibold(12.0)));
|
||||
let conflicts: Vec<String> = d.fields.get("conflicts").and_then(Value::as_array).map(|a| a.iter().filter_map(|v| v.as_str().map(str::to_string)).collect()).unwrap_or_default();
|
||||
ui.label(if conflicts.is_empty() { "No conflicts".to_string() } else { format!("{} conflict(s): {}", conflicts.len(), conflicts.join(", ")) });
|
||||
ui.label(if conflicts.is_empty() { crate::i18n::tr(&app.ui.language, "No conflicts").to_string() } else { format!("{} conflict(s): {}", conflicts.len(), conflicts.join(", ")) });
|
||||
let cur = d.s("styleConflicts");
|
||||
ui.horizontal(|ui| {
|
||||
for (v, l) in [("useExisting", "Use Document Style Definition"), ("redefine", "Redefine Document Style"), ("autoRename", "Auto Rename")] {
|
||||
@@ -1146,7 +1172,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
ui.label(w);
|
||||
let mapped = d.fields.get("map").and_then(|m| m.get(w)).and_then(Value::as_str).unwrap_or("").to_string();
|
||||
let shown = if mapped.is_empty() { "(import)".to_string() } else { mapped.clone() };
|
||||
egui::ComboBox::from_id_salt(("imp_map", w)).selected_text(shown).width(170.0).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt(("imp_map", w)).selected_text(crate::rtl::widget(ui, &shown)).width(170.0).show_ui(ui, |ui| {
|
||||
if ui.selectable_label(mapped.is_empty(),crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "(import)"))).clicked()
|
||||
&& let Some(m) = d.fields.get_mut("map").and_then(Value::as_object_mut)
|
||||
{
|
||||
@@ -1187,9 +1213,9 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
};
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Fitting:"));
|
||||
egui::ComboBox::from_id_salt("ff_fit").selected_text(label(&cur)).width(200.0).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt("ff_fit").selected_text(crate::rtl::widget(ui, label(&cur))).width(200.0).show_ui(ui, |ui| {
|
||||
for v in ["none", "fillProportionally", "fitProportionally", "fitContentToFrame", "centerContent"] {
|
||||
if ui.selectable_label(cur == v, label(v)).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, label(v))).clicked() {
|
||||
d.fields.insert("fitting".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -1220,12 +1246,12 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Crop Amount")).font(semibold(12.0)));
|
||||
egui::Grid::new("ff_crop").num_columns(4).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
for (k, l) in [("cropTop", "Top:"), ("cropLeft", "Left:")] {
|
||||
ui.label(l);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
text_field(ui, &mut d, k, 70.0);
|
||||
}
|
||||
ui.end_row();
|
||||
for (k, l) in [("cropBottom", "Bottom:"), ("cropRight", "Right:")] {
|
||||
ui.label(l);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
text_field(ui, &mut d, k, 70.0);
|
||||
}
|
||||
ui.end_row();
|
||||
@@ -1242,9 +1268,9 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
"vcard" => crate::i18n::tr(&app.ui.language, "Business Card"),
|
||||
_ => crate::i18n::tr(&app.ui.language, "Web Hyperlink"),
|
||||
};
|
||||
egui::ComboBox::from_id_salt("qr_type").selected_text(label(&cur)).width(160.0).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt("qr_type").selected_text(crate::rtl::widget(ui, label(&cur))).width(160.0).show_ui(ui, |ui| {
|
||||
for v in ["url", "text", "sms", "email", "vcard"] {
|
||||
if ui.selectable_label(cur == v, label(v)).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, label(v))).clicked() {
|
||||
d.fields.insert("type".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -1259,7 +1285,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
};
|
||||
egui::Grid::new("qr_fields").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
for (k, l) in fields {
|
||||
ui.label(*l);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
text_field(ui, &mut d, k, 260.0);
|
||||
ui.end_row();
|
||||
}
|
||||
@@ -1290,10 +1316,10 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
}
|
||||
"ruby" => {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Ruby:");
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Ruby:"));
|
||||
text_field(ui, &mut d, "text", 200.0);
|
||||
});
|
||||
ui.label(egui::RichText::new("Set over the selected text; empty removes it.").size(11.0));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Set over the selected text; empty removes it.")).size(11.0));
|
||||
}
|
||||
"insertTable" => {
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Table Dimensions")).font(semibold(12.0)));
|
||||
@@ -1323,9 +1349,9 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Vertical justification"));
|
||||
let cur = d.s("verticalJustification");
|
||||
egui::ComboBox::from_id_salt("vj").selected_text(&cur).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt("vj").selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur))).show_ui(ui, |ui| {
|
||||
for v in ["top", "center", "bottom", "justify"] {
|
||||
if ui.selectable_label(cur == v, v).clicked() {
|
||||
if ui.selectable_label(cur == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, v))).clicked() {
|
||||
d.fields.insert("verticalJustification".into(), json!(v));
|
||||
}
|
||||
}
|
||||
@@ -1710,7 +1736,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
("color", "Character Color"),
|
||||
("export", "Export Tagging"),
|
||||
] {
|
||||
if ui.selectable_label(d.s("section") == id, label).clicked() {
|
||||
if ui.selectable_label(d.s("section") == id, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
d.fields.insert("section".into(), json!(id));
|
||||
}
|
||||
}
|
||||
@@ -1728,13 +1754,16 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Tag:"));
|
||||
let cur = d.s("x.tag");
|
||||
egui::ComboBox::from_id_salt("export_tag").selected_text(&cur).show_ui(ui, |ui| {
|
||||
for t in ["[Automatic]", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "pre", "li", "figcaption", "aside", "div"] {
|
||||
if ui.selectable_label(cur == t, t).clicked() {
|
||||
d.fields.insert("x.tag".into(), json!(t));
|
||||
egui::ComboBox::from_id_salt("export_tag")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur)))
|
||||
.show_ui(ui, |ui| {
|
||||
for t in ["[Automatic]", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "pre", "li", "figcaption", "aside", "div"]
|
||||
{
|
||||
if ui.selectable_label(cur == t, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, t))).clicked() {
|
||||
d.fields.insert("x.tag".into(), json!(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Class:"));
|
||||
@@ -1749,42 +1778,51 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
for (i, ns) in list.iter_mut().enumerate() {
|
||||
ui.horizontal(|ui| {
|
||||
let style = ns["style"].as_str().unwrap_or("[None]").to_string();
|
||||
egui::ComboBox::from_id_salt(("ns_style", i)).selected_text(&style).width(110.0).show_ui(ui, |ui| {
|
||||
for c in &cnames {
|
||||
if ui.selectable_label(*c == style, c).clicked() {
|
||||
ns["style"] = json!(c);
|
||||
changed = true;
|
||||
egui::ComboBox::from_id_salt(("ns_style", i))
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &style)))
|
||||
.width(110.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for c in &cnames {
|
||||
if ui
|
||||
.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, c)))
|
||||
.clicked()
|
||||
{
|
||||
ns["style"] = json!(c);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
let through = ns["through"].as_bool().unwrap_or(true);
|
||||
egui::ComboBox::from_id_salt(("ns_thr", i)).selected_text(if through { "through" } else { "up to" }).width(70.0).show_ui(
|
||||
ui,
|
||||
|ui| {
|
||||
egui::ComboBox::from_id_salt(("ns_thr", i))
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if through { "through" } else { "up to" })))
|
||||
.width(70.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (v, l) in [(true, "through"), (false, "up to")] {
|
||||
if ui.selectable_label(v == through, l).clicked() {
|
||||
if ui.selectable_label(v == through, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
ns["through"] = json!(v);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
let mut n = ns["count"].as_u64().unwrap_or(1) as u32;
|
||||
if ui.add(egui::DragValue::new(&mut n).range(1..=999)).changed() {
|
||||
ns["count"] = json!(n);
|
||||
changed = true;
|
||||
}
|
||||
let kind = ns["until"]["kind"].as_str().unwrap_or("words").to_string();
|
||||
egui::ComboBox::from_id_salt(("ns_until", i)).selected_text(&kind).width(100.0).show_ui(ui, |ui| {
|
||||
for k in
|
||||
["sentences", "words", "characters", "letters", "digits", "tab", "forcedLineBreak", "emSpace", "enSpace", "chars"]
|
||||
{
|
||||
if ui.selectable_label(k == kind, k).clicked() {
|
||||
ns["until"] = if k == "chars" { json!({"kind": "chars", "chars": ":"}) } else { json!({"kind": k}) };
|
||||
changed = true;
|
||||
egui::ComboBox::from_id_salt(("ns_until", i))
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &kind)))
|
||||
.width(100.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for k in
|
||||
["sentences", "words", "characters", "letters", "digits", "tab", "forcedLineBreak", "emSpace", "enSpace", "chars"]
|
||||
{
|
||||
if ui.selectable_label(k == kind, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, k))).clicked() {
|
||||
ns["until"] = if k == "chars" { json!({"kind": "chars", "chars": ":"}) } else { json!({"kind": k}) };
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if kind == "chars" {
|
||||
let mut c = ns["until"]["chars"].as_str().unwrap_or("").to_string();
|
||||
if ui.add(egui::TextEdit::singleline(&mut c).desired_width(40.0)).changed() {
|
||||
@@ -1822,21 +1860,27 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
for (i, l) in lines.iter_mut().enumerate() {
|
||||
ui.horizontal(|ui| {
|
||||
let style = l["style"].as_str().unwrap_or("").to_string();
|
||||
egui::ComboBox::from_id_salt(("nls_style", i)).selected_text(&style).width(130.0).show_ui(ui, |ui| {
|
||||
for c in &cnames {
|
||||
if ui.selectable_label(*c == style, c).clicked() {
|
||||
l["style"] = json!(c);
|
||||
changed = true;
|
||||
egui::ComboBox::from_id_salt(("nls_style", i))
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &style)))
|
||||
.width(130.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for c in &cnames {
|
||||
if ui
|
||||
.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, c)))
|
||||
.clicked()
|
||||
{
|
||||
l["style"] = json!(c);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "for"));
|
||||
let mut n = l["lines"].as_u64().unwrap_or(1) as u32;
|
||||
if ui.add(egui::DragValue::new(&mut n).range(1..=999)).changed() {
|
||||
l["lines"] = json!(n);
|
||||
changed = true;
|
||||
}
|
||||
ui.label(if n == 1 { "line" } else { "lines" });
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, if n == 1 { "line" } else { "lines" }));
|
||||
if ui
|
||||
.small_button("×")
|
||||
.on_hover_ui(|ui| {
|
||||
@@ -1869,14 +1913,20 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Apply Style:"));
|
||||
let style = g["style"].as_str().unwrap_or("").to_string();
|
||||
egui::ComboBox::from_id_salt(("gs_style", i)).selected_text(&style).width(110.0).show_ui(ui, |ui| {
|
||||
for c in &cnames {
|
||||
if ui.selectable_label(*c == style, c).clicked() {
|
||||
g["style"] = json!(c);
|
||||
changed = true;
|
||||
egui::ComboBox::from_id_salt(("gs_style", i))
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &style)))
|
||||
.width(110.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for c in &cnames {
|
||||
if ui
|
||||
.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, c)))
|
||||
.clicked()
|
||||
{
|
||||
g["style"] = json!(c);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "To Text:"));
|
||||
let mut pat = g["pattern"].as_str().unwrap_or("").to_string();
|
||||
let bad = regex_ok(&pat).is_err();
|
||||
@@ -1935,7 +1985,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
});
|
||||
ui.end_row();
|
||||
for (label, key, suffix) in [("Size:", "size", " pt"), ("Tracking:", "tracking", "")] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
let v = cur(d, &format!("c.{key}"), &cv[key]).as_f64();
|
||||
if let Some(n) = crate::widgets::number(ui, &format!("ps{key}"), v, suffix, 80.0, 2) {
|
||||
d.fields.insert(format!("c.{key}"), json!(n));
|
||||
@@ -1957,13 +2007,16 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
egui::Grid::new("psi").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Alignment:"));
|
||||
let a: designcraft_doc::Align = serde_json::from_value(cur(d, "p.align", &pv["align"])).unwrap_or_default();
|
||||
egui::ComboBox::from_id_salt("psalign").selected_text(a.label()).width(240.0).show_ui(ui, |ui| {
|
||||
for al in designcraft_doc::Align::ALL {
|
||||
if ui.selectable_label(al == a, al.label()).clicked() {
|
||||
d.fields.insert("p.align".into(), serde_json::to_value(al).unwrap_or_default());
|
||||
egui::ComboBox::from_id_salt("psalign")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, a.label())))
|
||||
.width(240.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for al in designcraft_doc::Align::ALL {
|
||||
if ui.selectable_label(al == a, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, al.label()))).clicked() {
|
||||
d.fields.insert("p.align".into(), serde_json::to_value(al).unwrap_or_default());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
ui.end_row();
|
||||
for (label, key) in [
|
||||
("Left Indent:", "leftIndent"),
|
||||
@@ -1972,7 +2025,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
("Space Before:", "spaceBefore"),
|
||||
("Space After:", "spaceAfter"),
|
||||
] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
let v = cur(d, &format!("p.{key}"), &pv[key]).as_f64();
|
||||
if let Some(n) = crate::widgets::measure(ui, &format!("ps{key}"), v, units, 80.0) {
|
||||
d.fields.insert(format!("p.{key}"), json!(n));
|
||||
@@ -1993,7 +2046,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
("Before Last:", "hyphBeforeLast"),
|
||||
("Hyphen Limit:", "hyphLimit"),
|
||||
] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
let v = cur(d, &format!("p.{key}"), &pv[key]).as_f64();
|
||||
if let Some(n) = crate::widgets::number(ui, &format!("ps{key}"), v, "", 60.0, 0) {
|
||||
d.fields.insert(format!("p.{key}"), json!(n.max(0.0) as u64));
|
||||
@@ -2010,11 +2063,11 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Maximum"));
|
||||
ui.end_row();
|
||||
for (label, base) in [("Word Spacing:", "wordSpace"), ("Letter Spacing:", "letterSpace"), ("Glyph Scaling:", "glyphScale")] {
|
||||
crate::rtl::label(ui, label);
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
for suffix in ["Min", "Desired", "Max"] {
|
||||
let key = format!("{base}{suffix}");
|
||||
let v = cur(d, &format!("p.{key}"), &pv[key.as_str()]).as_f64().map(|x| x * 100.0);
|
||||
if let Some(n) = crate::widgets::number(ui, &format!("ps{key}"), v, "%", 60.0, 0) {
|
||||
if let Some(n) = ui.scope(|ui| crate::widgets::number(ui, &format!("ps{key}"), v, "%", 60.0, 0)).inner {
|
||||
d.fields.insert(format!("p.{key}"), json!(n / 100.0));
|
||||
}
|
||||
}
|
||||
@@ -2029,9 +2082,9 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
d.fields.insert("p.composer".into(), json!("singleLine"));
|
||||
}
|
||||
ui.end_row();
|
||||
ui.label("Insert Kashidas:");
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Insert Kashidas:"));
|
||||
let mut k = cur(d, "p.kashidas", &pv["kashidas"]).as_bool().unwrap_or(true);
|
||||
if ui.checkbox(&mut k, "In justified Arabic text").changed() {
|
||||
if ui.checkbox(&mut k, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "In justified Arabic text"))).changed() {
|
||||
d.fields.insert("p.kashidas".into(), json!(k));
|
||||
}
|
||||
ui.end_row();
|
||||
@@ -2072,19 +2125,29 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
.map(str::to_string)
|
||||
.or(style.based_on.clone())
|
||||
.unwrap_or_else(|| "[No Paragraph Style]".into());
|
||||
egui::ComboBox::from_id_salt("psbased").selected_text(&based).width(220.0).show_ui(ui, |ui| {
|
||||
for n in &names {
|
||||
if ui.selectable_label(*n == based, n).clicked() {
|
||||
d.fields.insert("basedOn".into(), json!(n));
|
||||
egui::ComboBox::from_id_salt("psbased")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &based)))
|
||||
.width(220.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for n in &names {
|
||||
if ui.selectable_label(*n == based, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, n))).clicked() {
|
||||
d.fields.insert("basedOn".into(), json!(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
ui.end_row();
|
||||
});
|
||||
ui.add_space(8.0);
|
||||
ui.label(
|
||||
egui::RichText::new(format!("{} {} {:.1} pt · {}", cp.font_family, cp.font_style, cp.size, pp.align.label()))
|
||||
.color(crate::theme::Tokens::get(ui.ctx()).text_dim),
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(format!(
|
||||
"{} {} {:.1} pt · {}",
|
||||
cp.font_family,
|
||||
cp.font_style,
|
||||
cp.size,
|
||||
crate::i18n::tr(&app.ui.language, pp.align.label())
|
||||
))
|
||||
.color(crate::theme::Tokens::get(ui.ctx()).text_dim),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -2094,15 +2157,21 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
||||
fn combo(ui: &mut egui::Ui, d: &mut Dialog, key: &str, opts: &[(&str, &str)]) {
|
||||
let cur = d.s(key);
|
||||
let shown = opts.iter().find(|o| o.0 == cur).map_or(cur.as_str(), |o| o.1).to_string();
|
||||
egui::ComboBox::from_id_salt(key).selected_text(shown).width(170.0).show_ui(ui, |ui| {
|
||||
egui::ComboBox::from_id_salt(key).selected_text(crate::rtl::widget(ui, &shown)).width(170.0).show_ui(ui, |ui| {
|
||||
for (v, label) in opts {
|
||||
if ui.selectable_label(cur == *v, *label).clicked() {
|
||||
if ui.selectable_label(cur == *v, crate::rtl::widget(ui, *label)).clicked() {
|
||||
d.fields.insert(key.into(), json!(v));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Translate enum captions without changing serialized values or user-defined names.
|
||||
fn translated_combo(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, key: &str, opts: &[(&str, &str)]) {
|
||||
let opts: Vec<_> = opts.iter().map(|(value, label)| (*value, crate::i18n::tr(lang, label))).collect();
|
||||
combo(ui, d, key, &opts);
|
||||
}
|
||||
|
||||
/// Style name picker (paragraph or character styles of the active document).
|
||||
fn style_combo(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, key: &str, character: bool) {
|
||||
let names: Vec<String> = app
|
||||
@@ -2116,9 +2185,9 @@ fn style_combo(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, key: &str, ch
|
||||
}
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut opts: Vec<(&str, &str)> = names.iter().map(|n| (n.as_str(), n.as_str())).collect();
|
||||
let mut opts: Vec<(&str, &str)> = names.iter().map(|n| (n.as_str(), crate::i18n::style_name(&app.ui.language, n))).collect();
|
||||
if character && !names.iter().any(|n| n == designcraft_doc::NO_CHAR_STYLE) {
|
||||
opts.insert(0, (designcraft_doc::NO_CHAR_STYLE, designcraft_doc::NO_CHAR_STYLE));
|
||||
opts.insert(0, (designcraft_doc::NO_CHAR_STYLE, crate::i18n::style_name(&app.ui.language, designcraft_doc::NO_CHAR_STYLE)));
|
||||
}
|
||||
combo(ui, d, key, &opts);
|
||||
}
|
||||
@@ -2127,7 +2196,7 @@ fn style_combo(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, key: &str, ch
|
||||
fn footnote_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
ui.horizontal(|ui| {
|
||||
for (tab, label) in [("numbering", "Numbering and Formatting"), ("layout", "Layout")] {
|
||||
if ui.selectable_label(d.s("tab") == tab, label).clicked() {
|
||||
if ui.selectable_label(d.s("tab") == tab, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
d.fields.insert("tab".into(), json!(tab));
|
||||
}
|
||||
}
|
||||
@@ -2135,7 +2204,7 @@ fn footnote_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
ui.separator();
|
||||
let head = |ui: &mut egui::Ui, t: &str| {
|
||||
ui.add_space(4.0);
|
||||
ui.label(egui::RichText::new(t).font(semibold(12.0)));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, t)).font(semibold(12.0)));
|
||||
};
|
||||
if d.s("tab") == "layout" {
|
||||
head(ui, "Spacing Options");
|
||||
@@ -2150,7 +2219,8 @@ fn footnote_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
head(ui, "First Baseline");
|
||||
egui::Grid::new("fn_fb").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Offset:"));
|
||||
combo(
|
||||
translated_combo(
|
||||
&app.ui.language,
|
||||
ui,
|
||||
d,
|
||||
"firstBaseline",
|
||||
@@ -2186,7 +2256,8 @@ fn footnote_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
head(ui, "Numbering");
|
||||
egui::Grid::new("fn_num").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Style:"));
|
||||
combo(
|
||||
translated_combo(
|
||||
&app.ui.language,
|
||||
ui,
|
||||
d,
|
||||
"style",
|
||||
@@ -2205,10 +2276,22 @@ fn footnote_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
text_field(ui, d, "startAt", 60.0);
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Restart Numbering Every:"));
|
||||
combo(ui, d, "restart", &[("never", "Never (continuous)"), ("page", "Page"), ("spread", "Spread"), ("section", "Section")]);
|
||||
translated_combo(
|
||||
&app.ui.language,
|
||||
ui,
|
||||
d,
|
||||
"restart",
|
||||
&[("never", "Never (continuous)"), ("page", "Page"), ("spread", "Spread"), ("section", "Section")],
|
||||
);
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Show Prefix/Suffix in:"));
|
||||
combo(ui, d, "affixIn", &[("none", "None"), ("reference", "Footnote Reference"), ("text", "Footnote Text"), ("both", "Both")]);
|
||||
translated_combo(
|
||||
&app.ui.language,
|
||||
ui,
|
||||
d,
|
||||
"affixIn",
|
||||
&[("none", "None"), ("reference", "Footnote Reference"), ("text", "Footnote Text"), ("both", "Both")],
|
||||
);
|
||||
ui.end_row();
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Prefix:"));
|
||||
text_field(ui, d, "prefix", 60.0);
|
||||
@@ -2220,7 +2303,8 @@ fn footnote_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
head(ui, "Footnote Reference Number in Text");
|
||||
egui::Grid::new("fn_ref").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Position:"));
|
||||
combo(
|
||||
translated_combo(
|
||||
&app.ui.language,
|
||||
ui,
|
||||
d,
|
||||
"refPosition",
|
||||
@@ -2345,7 +2429,8 @@ fn command_form(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
check(ui, d, &f.key, "");
|
||||
} else if !f.choices.is_empty() {
|
||||
let mut opts: Vec<(&str, &str)> = vec![("", "—")];
|
||||
opts.extend(f.choices.iter().map(|c| (c.as_str(), c.as_str())));
|
||||
let labels: Vec<_> = f.choices.iter().map(|c| humanize(c)).collect();
|
||||
opts.extend(f.choices.iter().zip(&labels).map(|(value, label)| (value.as_str(), crate::i18n::tr(&app.ui.language, label))));
|
||||
combo(ui, d, &f.key, &opts);
|
||||
} else {
|
||||
let mut s = d.s(&f.key);
|
||||
@@ -2499,7 +2584,12 @@ fn find_font(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
}
|
||||
let fonts = d.fields.get("_fonts").and_then(Value::as_array).cloned().unwrap_or_default();
|
||||
let missing = fonts.iter().filter(|f| f["missing"] == true || f["styleMissing"] == true).count();
|
||||
ui.label(format!("Fonts in Document: {} Missing: {missing}", fonts.len()));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
crate::i18n::tr(&app.ui.language, "Fonts in Document: {count} Missing: {missing}")
|
||||
.replace("{count}", &fonts.len().to_string())
|
||||
.replace("{missing}", &missing.to_string()),
|
||||
);
|
||||
egui::ScrollArea::vertical().id_salt("ff_list").max_height(180.0).show(ui, |ui| {
|
||||
for f in &fonts {
|
||||
let (fam, st) = (f["family"].as_str().unwrap_or(""), f["style"].as_str().unwrap_or(""));
|
||||
|
||||
@@ -132,9 +132,11 @@ pub fn flyout(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
egui::Area::new(egui::Id::new("panel_flyout")).order(egui::Order::Foreground).fixed_pos(pos).show(ctx, |ui| {
|
||||
egui::Frame::popup(ui.style()).fill(t.panel).inner_margin(egui::Margin::same(0)).show(ui, |ui| {
|
||||
ui.set_width(256.0);
|
||||
// A previous shorter flyout must not constrain the next panel's scroll viewport.
|
||||
ui.set_max_height((screen.max.y - pos.y - 12.0).max(80.0));
|
||||
let (strip, _) = ui.allocate_exact_size(vec2(256.0, 26.0), Sense::hover());
|
||||
ui.painter().rect_filled(strip, 0.0, t.panel_darker);
|
||||
ui.painter().text(strip.min + vec2(10.0, 13.0), egui::Align2::LEFT_CENTER, label, semibold(12.0), t.text_strong);
|
||||
crate::rtl::paint(ui.painter(), strip.min + vec2(10.0, 13.0), egui::Align2::LEFT_CENTER, &label, semibold(12.0), t.text_strong);
|
||||
let close = egui::Rect::from_min_size(egui::pos2(strip.max.x - 22.0, strip.min.y + 4.0), vec2(18.0, 18.0));
|
||||
if ui.interact(close, ui.id().with("flyclose"), Sense::click()).clicked() {
|
||||
open = false;
|
||||
|
||||
+829
-3
@@ -204,7 +204,7 @@ const TABLE: &[(&str, [&str; 5])] = &[
|
||||
("Color Settings", ["Color Settings", "Color Settings", "Color Settings", "Color Settings", "颜色设置"]),
|
||||
("Color:", ["Color:", "Color:", "Color:", "Color:", "颜色:"]),
|
||||
("Columns", ["Columns", "Columns", "Columns", "Columns", "栏"]),
|
||||
("Composer:", ["Composer:", "Composer:", "Composer:", "Composer:", "书写器:"]),
|
||||
("Composer:", ["Composer:", "Composer:", "Composer:", "Composer:", "排版器:"]),
|
||||
("Copies:", ["Copies:", "Copies:", "Copies:", "Copies:", "份数:"]),
|
||||
("Count", ["Count", "Count", "Count", "Count", "数量"]),
|
||||
("Create", ["Create", "Create", "Create", "Create", "创建"]),
|
||||
@@ -362,7 +362,7 @@ const TABLE: &[(&str, [&str; 5])] = &[
|
||||
("Orientation:", ["Orientation:", "Orientation:", "Orientation:", "Orientation:", "方向:"]),
|
||||
("Outside", ["Outside", "Outside", "Outside", "Outside", "外侧"]),
|
||||
("Pages:", ["Pages:", "Pages:", "Pages:", "Pages:", "页面:"]),
|
||||
("Paragraph Composer", ["Paragraph Composer", "Paragraph Composer", "Paragraph Composer", "Paragraph Composer", "段落书写器"]),
|
||||
("Paragraph Composer", ["Paragraph Composer", "Paragraph Composer", "Paragraph Composer", "Paragraph Composer", "段落排版器"]),
|
||||
(
|
||||
"Paragraph Style Options",
|
||||
["Paragraph Style Options", "Paragraph Style Options", "Paragraph Style Options", "Paragraph Style Options", "段落样式选项"],
|
||||
@@ -442,7 +442,7 @@ const TABLE: &[(&str, [&str; 5])] = &[
|
||||
),
|
||||
("Show Tag Markers", ["Show Tag Markers", "Show Tag Markers", "Show Tag Markers", "Show Tag Markers", "显示标记的框架"]),
|
||||
("Single-line", ["Single-line", "Single-line", "Single-line", "Single-line", "单行"]),
|
||||
("Single-line Composer", ["Single-line Composer", "Single-line Composer", "Single-line Composer", "Single-line Composer", "单行书写器"]),
|
||||
("Single-line Composer", ["Single-line Composer", "Single-line Composer", "Single-line Composer", "Single-line Composer", "单行排版器"]),
|
||||
("Size:", ["Size:", "Size:", "Size:", "Size:", "大小:"]),
|
||||
(
|
||||
"Space Between Footnotes:",
|
||||
@@ -1786,6 +1786,816 @@ const TABLE: &[(&str, [&str; 5])] = &[
|
||||
["⌥-click clears overrides", "⌥-click clears overrides", "⌥-click clears overrides", "⌥-click clears overrides", "⌥-单击清除覆盖"],
|
||||
),
|
||||
("⚠ out of date", ["⚠ out of date", "⚠ out of date", "⚠ out of date", "⚠ out of date", "⚠ 已过期"]),
|
||||
("General", ["General", "General", "General", "General", "常规"]),
|
||||
(
|
||||
"Basic Character Formats",
|
||||
["Basic Character Formats", "Basic Character Formats", "Basic Character Formats", "Basic Character Formats", "基本字符格式"],
|
||||
),
|
||||
("Indents and Spacing", ["Indents and Spacing", "Indents and Spacing", "Indents and Spacing", "Indents and Spacing", "缩进和间距"]),
|
||||
("Hyphenation", ["Hyphenation", "Hyphenation", "Hyphenation", "Hyphenation", "断字"]),
|
||||
("Justification", ["Justification", "Justification", "Justification", "Justification", "两端对齐"]),
|
||||
(
|
||||
"Drop Caps and Nested Styles",
|
||||
[
|
||||
"Drop Caps and Nested Styles",
|
||||
"Drop Caps and Nested Styles",
|
||||
"Drop Caps and Nested Styles",
|
||||
"Drop Caps and Nested Styles",
|
||||
"首字下沉和嵌套样式",
|
||||
],
|
||||
),
|
||||
("GREP Style", ["GREP Style", "GREP Style", "GREP Style", "GREP Style", "GREP 样式"]),
|
||||
("Character Color", ["Character Color", "Character Color", "Character Color", "Character Color", "字符颜色"]),
|
||||
(
|
||||
"Numbering and Formatting",
|
||||
["Numbering and Formatting", "Numbering and Formatting", "Numbering and Formatting", "Numbering and Formatting", "编号和格式"],
|
||||
),
|
||||
("Spacing Options", ["Spacing Options", "Spacing Options", "Spacing Options", "Spacing Options", "间距选项"]),
|
||||
("First Baseline", ["First Baseline", "First Baseline", "First Baseline", "First Baseline", "首行基线"]),
|
||||
("Rule Above", ["Rule Above", "Rule Above", "Rule Above", "Rule Above", "上方横线"]),
|
||||
("Numbering", ["Numbering", "Numbering", "Numbering", "Numbering", "编号"]),
|
||||
(
|
||||
"Footnote Reference Number in Text",
|
||||
[
|
||||
"Footnote Reference Number in Text",
|
||||
"Footnote Reference Number in Text",
|
||||
"Footnote Reference Number in Text",
|
||||
"Footnote Reference Number in Text",
|
||||
"正文中的脚注引用编号",
|
||||
],
|
||||
),
|
||||
("Footnote Formatting", ["Footnote Formatting", "Footnote Formatting", "Footnote Formatting", "Footnote Formatting", "脚注格式"]),
|
||||
(
|
||||
"Span Footnotes Across Columns",
|
||||
[
|
||||
"Span Footnotes Across Columns",
|
||||
"Span Footnotes Across Columns",
|
||||
"Span Footnotes Across Columns",
|
||||
"Span Footnotes Across Columns",
|
||||
"脚注跨栏",
|
||||
],
|
||||
),
|
||||
("Rule On", ["Rule On", "Rule On", "Rule On", "Rule On", "启用横线"]),
|
||||
("Ascent", ["Ascent", "Ascent", "Ascent", "Ascent", "升部"]),
|
||||
("Cap Height", ["Cap Height", "Cap Height", "Cap Height", "Cap Height", "大写字母高度"]),
|
||||
("Leading", ["Leading", "Leading", "Leading", "Leading", "行距"]),
|
||||
("x Height", ["x Height", "x Height", "x Height", "x Height", "x 字高"]),
|
||||
("Fixed", ["Fixed", "Fixed", "Fixed", "Fixed", "固定"]),
|
||||
("Never (continuous)", ["Never (continuous)", "Never (continuous)", "Never (continuous)", "Never (continuous)", "从不(连续编号)"]),
|
||||
("Page", ["Page", "Page", "Page", "Page", "页面"]),
|
||||
("Spread", ["Spread", "Spread", "Spread", "Spread", "跨页"]),
|
||||
("Section", ["Section", "Section", "Section", "Section", "章节"]),
|
||||
("Footnote Reference", ["Footnote Reference", "Footnote Reference", "Footnote Reference", "Footnote Reference", "脚注引用"]),
|
||||
("Footnote Text", ["Footnote Text", "Footnote Text", "Footnote Text", "Footnote Text", "脚注文本"]),
|
||||
("Both", ["Both", "Both", "Both", "Both", "两者"]),
|
||||
("Apply Superscript", ["Apply Superscript", "Apply Superscript", "Apply Superscript", "Apply Superscript", "应用上标"]),
|
||||
("Apply Subscript", ["Apply Subscript", "Apply Subscript", "Apply Subscript", "Apply Subscript", "应用下标"]),
|
||||
("Apply Normal", ["Apply Normal", "Apply Normal", "Apply Normal", "Apply Normal", "应用正常位置"]),
|
||||
("OpenType Superscript", ["OpenType Superscript", "OpenType Superscript", "OpenType Superscript", "OpenType Superscript", "OpenType 上标"]),
|
||||
("through", ["through", "through", "through", "through", "直到(包含)"]),
|
||||
("up to", ["up to", "up to", "up to", "up to", "直到(不包含)"]),
|
||||
("line", ["line", "line", "line", "line", "行"]),
|
||||
("lines", ["lines", "lines", "lines", "lines", "行"]),
|
||||
("sentences", ["sentences", "sentences", "sentences", "sentences", "句子"]),
|
||||
("words", ["words", "words", "words", "words", "单词"]),
|
||||
("characters", ["characters", "characters", "characters", "characters", "字符"]),
|
||||
("letters", ["letters", "letters", "letters", "letters", "字母"]),
|
||||
("digits", ["digits", "digits", "digits", "digits", "数字"]),
|
||||
("tab", ["tab", "tab", "tab", "tab", "制表符"]),
|
||||
("forcedLineBreak", ["forcedLineBreak", "forcedLineBreak", "forcedLineBreak", "forcedLineBreak", "强制换行符"]),
|
||||
("emSpace", ["emSpace", "emSpace", "emSpace", "emSpace", "全角空格"]),
|
||||
("enSpace", ["enSpace", "enSpace", "enSpace", "enSpace", "半角空格"]),
|
||||
("chars", ["chars", "chars", "chars", "chars", "指定字符"]),
|
||||
("[Automatic]", ["[Automatic]", "[Automatic]", "[Automatic]", "[Automatic]", "[自动]"]),
|
||||
("Tracking:", ["Tracking:", "Tracking:", "Tracking:", "Tracking:", "字距:"]),
|
||||
("Right Indent:", ["Right Indent:", "Right Indent:", "Right Indent:", "Right Indent:", "右缩进:"]),
|
||||
("First Line Indent:", ["First Line Indent:", "First Line Indent:", "First Line Indent:", "First Line Indent:", "首行缩进:"]),
|
||||
("Space Before:", ["Space Before:", "Space Before:", "Space Before:", "Space Before:", "段前间距:"]),
|
||||
("Space After:", ["Space After:", "Space After:", "Space After:", "Space After:", "段后间距:"]),
|
||||
("Words with at Least:", ["Words with at Least:", "Words with at Least:", "Words with at Least:", "Words with at Least:", "最少单词长度:"]),
|
||||
("After First:", ["After First:", "After First:", "After First:", "After First:", "前部最少保留:"]),
|
||||
("Before Last:", ["Before Last:", "Before Last:", "Before Last:", "Before Last:", "后部最少保留:"]),
|
||||
("Hyphen Limit:", ["Hyphen Limit:", "Hyphen Limit:", "Hyphen Limit:", "Hyphen Limit:", "连续断字上限:"]),
|
||||
("Word Spacing:", ["Word Spacing:", "Word Spacing:", "Word Spacing:", "Word Spacing:", "单词间距:"]),
|
||||
("Letter Spacing:", ["Letter Spacing:", "Letter Spacing:", "Letter Spacing:", "Letter Spacing:", "字母间距:"]),
|
||||
("Glyph Scaling:", ["Glyph Scaling:", "Glyph Scaling:", "Glyph Scaling:", "Glyph Scaling:", "字形缩放:"]),
|
||||
("Insert Kashidas:", ["Insert Kashidas:", "Insert Kashidas:", "Insert Kashidas:", "Insert Kashidas:", "插入延长线:"]),
|
||||
(
|
||||
"In justified Arabic text",
|
||||
[
|
||||
"In justified Arabic text",
|
||||
"In justified Arabic text",
|
||||
"In justified Arabic text",
|
||||
"In justified Arabic text",
|
||||
"在两端对齐的阿拉伯语文本中",
|
||||
],
|
||||
),
|
||||
("Binding:", ["Binding:", "Binding:", "Binding:", "Binding:", "装订方向:"]),
|
||||
("Ruby:", ["Ruby:", "Ruby:", "Ruby:", "Ruby:", "注音:"]),
|
||||
(
|
||||
"Set over the selected text; empty removes it.",
|
||||
[
|
||||
"Set over the selected text; empty removes it.",
|
||||
"Set over the selected text; empty removes it.",
|
||||
"Set over the selected text; empty removes it.",
|
||||
"Set over the selected text; empty removes it.",
|
||||
"在所选文本上方添加注音;留空可移除。",
|
||||
],
|
||||
),
|
||||
("[Basic Paragraph]", ["[Basic Paragraph]", "[Basic Paragraph]", "[Basic Paragraph]", "[Basic Paragraph]", "[基本段落]"]),
|
||||
("[No Paragraph Style]", ["[No Paragraph Style]", "[No Paragraph Style]", "[No Paragraph Style]", "[No Paragraph Style]", "[无段落样式]"]),
|
||||
("Align left", ["Align left", "Align left", "Align left", "Align left", "左对齐"]),
|
||||
("Align center", ["Align center", "Align center", "Align center", "Align center", "居中对齐"]),
|
||||
("Align right", ["Align right", "Align right", "Align right", "Align right", "右对齐"]),
|
||||
(
|
||||
"Justify with last line aligned left",
|
||||
[
|
||||
"Justify with last line aligned left",
|
||||
"Justify with last line aligned left",
|
||||
"Justify with last line aligned left",
|
||||
"Justify with last line aligned left",
|
||||
"两端对齐,末行左对齐",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Justify with last line aligned center",
|
||||
[
|
||||
"Justify with last line aligned center",
|
||||
"Justify with last line aligned center",
|
||||
"Justify with last line aligned center",
|
||||
"Justify with last line aligned center",
|
||||
"两端对齐,末行居中",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Justify with last line aligned right",
|
||||
[
|
||||
"Justify with last line aligned right",
|
||||
"Justify with last line aligned right",
|
||||
"Justify with last line aligned right",
|
||||
"Justify with last line aligned right",
|
||||
"两端对齐,末行右对齐",
|
||||
],
|
||||
),
|
||||
("Justify all lines", ["Justify all lines", "Justify all lines", "Justify all lines", "Justify all lines", "所有行两端对齐"]),
|
||||
("Align towards spine", ["Align towards spine", "Align towards spine", "Align towards spine", "Align towards spine", "朝向书脊对齐"]),
|
||||
("Align away from spine", ["Align away from spine", "Align away from spine", "Align away from spine", "Align away from spine", "背向书脊对齐"]),
|
||||
(
|
||||
"Create New Style from Selection",
|
||||
[
|
||||
"Create New Style from Selection",
|
||||
"Create New Style from Selection",
|
||||
"Create New Style from Selection",
|
||||
"Create New Style from Selection",
|
||||
"从所选内容创建新样式",
|
||||
],
|
||||
),
|
||||
("No text selected", ["No text selected", "No text selected", "No text selected", "No text selected", "未选择文本"]),
|
||||
("Search", ["Search", "Search", "Search", "Search", "搜索"]),
|
||||
("Essentials", ["Essentials", "Essentials", "Essentials", "Essentials", "基本功能"]),
|
||||
("Advanced", ["Advanced", "Advanced", "Advanced", "Advanced", "高级"]),
|
||||
("Digital Publishing", ["Digital Publishing", "Digital Publishing", "Digital Publishing", "Digital Publishing", "数字出版"]),
|
||||
("Interactive for PDF", ["Interactive for PDF", "Interactive for PDF", "Interactive for PDF", "Interactive for PDF", "PDF 交互"]),
|
||||
("Printing and Proofing", ["Printing and Proofing", "Printing and Proofing", "Printing and Proofing", "Printing and Proofing", "打印和校样"]),
|
||||
("Typography", ["Typography", "Typography", "Typography", "Typography", "文字排版"]),
|
||||
("Rulers & Grids", ["Rulers & Grids", "Rulers & Grids", "Rulers & Grids", "Rulers & Grids", "标尺和网格"]),
|
||||
("No errors", ["No errors", "No errors", "No errors", "No errors", "无错误"]),
|
||||
("error", ["error", "error", "error", "error", "个错误"]),
|
||||
("errors", ["errors", "errors", "errors", "errors", "个错误"]),
|
||||
("Reset", ["Reset", "Reset", "Reset", "Reset", "重置"]),
|
||||
("Right to Left", ["Right to Left", "Right to Left", "Right to Left", "Right to Left", "从右向左"]),
|
||||
("Left to Right", ["Left to Right", "Left to Right", "Left to Right", "Left to Right", "从左向右"]),
|
||||
("Portrait", ["Portrait", "Portrait", "Portrait", "Portrait", "纵向"]),
|
||||
("Landscape", ["Landscape", "Landscape", "Landscape", "Landscape", "横向"]),
|
||||
(
|
||||
"Display All Blacks as Rich Black",
|
||||
[
|
||||
"Display All Blacks as Rich Black",
|
||||
"Display All Blacks as Rich Black",
|
||||
"Display All Blacks as Rich Black",
|
||||
"Display All Blacks as Rich Black",
|
||||
"所有黑色显示为浓黑",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Display All Blacks Accurately",
|
||||
[
|
||||
"Display All Blacks Accurately",
|
||||
"Display All Blacks Accurately",
|
||||
"Display All Blacks Accurately",
|
||||
"Display All Blacks Accurately",
|
||||
"准确显示所有黑色",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Output All Blacks as Rich Black",
|
||||
[
|
||||
"Output All Blacks as Rich Black",
|
||||
"Output All Blacks as Rich Black",
|
||||
"Output All Blacks as Rich Black",
|
||||
"Output All Blacks as Rich Black",
|
||||
"所有黑色输出为浓黑",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Output All Blacks Accurately",
|
||||
[
|
||||
"Output All Blacks Accurately",
|
||||
"Output All Blacks Accurately",
|
||||
"Output All Blacks Accurately",
|
||||
"Output All Blacks Accurately",
|
||||
"准确输出所有黑色",
|
||||
],
|
||||
),
|
||||
("Top Margin", ["Top Margin", "Top Margin", "Top Margin", "Top Margin", "上边距"]),
|
||||
("Top of Page", ["Top of Page", "Top of Page", "Top of Page", "Top of Page", "页面顶部"]),
|
||||
(
|
||||
"Paragraph Styles panel",
|
||||
["Paragraph Styles panel", "Paragraph Styles panel", "Paragraph Styles panel", "Paragraph Styles panel", "段落样式面板"],
|
||||
),
|
||||
(
|
||||
"Character Styles panel",
|
||||
["Character Styles panel", "Character Styles panel", "Character Styles panel", "Character Styles panel", "字符样式面板"],
|
||||
),
|
||||
("Create new style", ["Create new style", "Create new style", "Create new style", "Create new style", "创建新样式"]),
|
||||
("Clear overrides", ["Clear overrides", "Clear overrides", "Clear overrides", "Clear overrides", "清除覆盖"]),
|
||||
("Apply", ["Apply", "Apply", "Apply", "Apply", "应用"]),
|
||||
("Accept", ["Accept", "Accept", "Accept", "Accept", "接受"]),
|
||||
("Reject", ["Reject", "Reject", "Reject", "Reject", "拒绝"]),
|
||||
("Add Selection", ["Add Selection", "Add Selection", "Add Selection", "Add Selection", "添加所选内容"]),
|
||||
("Align Stroke:", ["Align Stroke:", "Align Stroke:", "Align Stroke:", "Align Stroke:", "描边对齐:"]),
|
||||
("Angle", ["Angle", "Angle", "Angle", "Angle", "角度"]),
|
||||
("Angle:", ["Angle:", "Angle:", "Angle:", "Angle:", "角度:"]),
|
||||
("Baseline", ["Baseline", "Baseline", "Baseline", "Baseline", "基线"]),
|
||||
("Cap:", ["Cap:", "Cap:", "Cap:", "Cap:", "端点:"]),
|
||||
("Cell Text", ["Cell Text", "Cell Text", "Cell Text", "Cell Text", "单元格文本"]),
|
||||
("Cell Type", ["Cell Type", "Cell Type", "Cell Type", "Cell Type", "单元格类型"]),
|
||||
("Composer", ["Composer", "Composer", "Composer", "Composer", "排版器"]),
|
||||
("Convert to Text", ["Convert to Text", "Convert to Text", "Convert to Text", "Convert to Text", "转换为文本"]),
|
||||
("Create New Layer", ["Create New Layer", "Create New Layer", "Create New Layer", "Create New Layer", "创建新图层"]),
|
||||
("Delete DTD", ["Delete DTD", "Delete DTD", "Delete DTD", "Delete DTD", "删除 DTD"]),
|
||||
("Digits", ["Digits", "Digits", "Digits", "Digits", "数字"]),
|
||||
("Direction", ["Direction", "Direction", "Direction", "Direction", "方向"]),
|
||||
("Distance", ["Distance", "Distance", "Distance", "Distance", "距离"]),
|
||||
("Distribute ↔", ["Distribute ↔", "Distribute ↔", "Distribute ↔", "Distribute ↔", "水平分布"]),
|
||||
("Distribute ↕", ["Distribute ↕", "Distribute ↕", "Distribute ↕", "Distribute ↕", "垂直分布"]),
|
||||
("Effects: Drop Shadow", ["Effects: Drop Shadow", "Effects: Drop Shadow", "Effects: Drop Shadow", "Effects: Drop Shadow", "效果:投影"]),
|
||||
("Favorites", ["Favorites", "Favorites", "Favorites", "Favorites", "收藏"]),
|
||||
("First Spread", ["First Spread", "First Spread", "First Spread", "First Spread", "第一个跨页"]),
|
||||
("Gap Color:", ["Gap Color:", "Gap Color:", "Gap Color:", "Gap Color:", "间隙颜色:"]),
|
||||
("Graphic…", ["Graphic…", "Graphic…", "Graphic…", "Graphic…", "图形…"]),
|
||||
("Home", ["Home", "Home", "Home", "Home", "主页"]),
|
||||
("Join:", ["Join:", "Join:", "Join:", "Join:", "连接:"]),
|
||||
("Language", ["Language", "Language", "Language", "Language", "语言"]),
|
||||
("Last Spread", ["Last Spread", "Last Spread", "Last Spread", "Last Spread", "最后一个跨页"]),
|
||||
("Load DTD…", ["Load DTD…", "Load DTD…", "Load DTD…", "Load DTD…", "载入 DTD…"]),
|
||||
("Location:", ["Location:", "Location:", "Location:", "Location:", "位置:"]),
|
||||
("Lock Guides", ["Lock Guides", "Lock Guides", "Lock Guides", "Lock Guides", "锁定参考线"]),
|
||||
("Miter Limit:", ["Miter Limit:", "Miter Limit:", "Miter Limit:", "Miter Limit:", "斜接限制:"]),
|
||||
(
|
||||
"New Article from Selection",
|
||||
[
|
||||
"New Article from Selection",
|
||||
"New Article from Selection",
|
||||
"New Article from Selection",
|
||||
"New Article from Selection",
|
||||
"从所选内容新建文章",
|
||||
],
|
||||
),
|
||||
("New Note at Cursor", ["New Note at Cursor", "New Note at Cursor", "New Note at Cursor", "New Note at Cursor", "在光标处新建附注"]),
|
||||
("New Swatch", ["New Swatch", "New Swatch", "New Swatch", "New Swatch", "新建色板"]),
|
||||
("New condition name", ["New condition name", "New condition name", "New condition name", "New condition name", "新条件名称"]),
|
||||
("New group…", ["New group…", "New group…", "New group…", "New group…", "新建组…"]),
|
||||
("New tag", ["New tag", "New tag", "New tag", "New tag", "新建标签"]),
|
||||
("Next Spread", ["Next Spread", "Next Spread", "Next Spread", "Next Spread", "下一个跨页"]),
|
||||
("Note text", ["Note text", "Note text", "Note text", "Note text", "附注文本"]),
|
||||
("Offset", ["Offset", "Offset", "Offset", "Offset", "偏移"]),
|
||||
("Offsets", ["Offsets", "Offsets", "Offsets", "Offsets", "偏移量"]),
|
||||
("Paragraph alignment", ["Paragraph alignment", "Paragraph alignment", "Paragraph alignment", "Paragraph alignment", "段落对齐"]),
|
||||
("Previous Spread", ["Previous Spread", "Previous Spread", "Previous Spread", "Previous Spread", "上一个跨页"]),
|
||||
("Release to Objects", ["Release to Objects", "Release to Objects", "Release to Objects", "Release to Objects", "释放为对象"]),
|
||||
("Remove", ["Remove", "Remove", "Remove", "Remove", "移除"]),
|
||||
(
|
||||
"Rotate 90° Counterclockwise",
|
||||
[
|
||||
"Rotate 90° Counterclockwise",
|
||||
"Rotate 90° Counterclockwise",
|
||||
"Rotate 90° Counterclockwise",
|
||||
"Rotate 90° Counterclockwise",
|
||||
"逆时针旋转 90°",
|
||||
],
|
||||
),
|
||||
("Rotation Angle", ["Rotation Angle", "Rotation Angle", "Rotation Angle", "Rotation Angle", "旋转角度"]),
|
||||
("Rows", ["Rows", "Rows", "Rows", "Rows", "行数"]),
|
||||
("Run", ["Run", "Run", "Run", "Run", "运行"]),
|
||||
("Scale X Percentage", ["Scale X Percentage", "Scale X Percentage", "Scale X Percentage", "Scale X Percentage", "水平缩放百分比"]),
|
||||
("Scale Y Percentage", ["Scale Y Percentage", "Scale Y Percentage", "Scale Y Percentage", "Scale Y Percentage", "垂直缩放百分比"]),
|
||||
("Search commands", ["Search commands", "Search commands", "Search commands", "Search commands", "搜索命令"]),
|
||||
("Search fonts", ["Search fonts", "Search fonts", "Search fonts", "Search fonts", "搜索字体"]),
|
||||
(
|
||||
"Search styles and commands…",
|
||||
[
|
||||
"Search styles and commands…",
|
||||
"Search styles and commands…",
|
||||
"Search styles and commands…",
|
||||
"Search styles and commands…",
|
||||
"搜索样式和命令…",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Search: character or U+code",
|
||||
[
|
||||
"Search: character or U+code",
|
||||
"Search: character or U+code",
|
||||
"Search: character or U+code",
|
||||
"Search: character or U+code",
|
||||
"搜索字符或 U+ 编码",
|
||||
],
|
||||
),
|
||||
("Share", ["Share", "Share", "Share", "Share", "分享"]),
|
||||
("Shear X Angle", ["Shear X Angle", "Shear X Angle", "Shear X Angle", "Shear X Angle", "水平倾斜角度"]),
|
||||
("Show Baseline Grid", ["Show Baseline Grid", "Show Baseline Grid", "Show Baseline Grid", "Show Baseline Grid", "显示基线网格"]),
|
||||
("Show Document Grid", ["Show Document Grid", "Show Document Grid", "Show Document Grid", "Show Document Grid", "显示文档网格"]),
|
||||
("Show Guides", ["Show Guides", "Show Guides", "Show Guides", "Show Guides", "显示参考线"]),
|
||||
("Smart Guides", ["Smart Guides", "Smart Guides", "Smart Guides", "Smart Guides", "智能参考线"]),
|
||||
("Stop Color:", ["Stop Color:", "Stop Color:", "Stop Color:", "Stop Color:", "色标颜色:"]),
|
||||
("Style", ["Style", "Style", "Style", "Style", "样式"]),
|
||||
("Styles panel", ["Styles panel", "Styles panel", "Styles panel", "Styles panel", "样式面板"]),
|
||||
("Text", ["Text", "Text", "Text", "Text", "文本"]),
|
||||
(
|
||||
"The structure is valid.",
|
||||
["The structure is valid.", "The structure is valid.", "The structure is valid.", "The structure is valid.", "结构有效。"],
|
||||
),
|
||||
("Toggle double column", ["Toggle double column", "Toggle double column", "Toggle double column", "Toggle double column", "切换双列布局"]),
|
||||
("Tracking", ["Tracking", "Tracking", "Tracking", "Tracking", "字距"]),
|
||||
("Untag Selection", ["Untag Selection", "Untag Selection", "Untag Selection", "Untag Selection", "移除所选内容的标签"]),
|
||||
("Validate", ["Validate", "Validate", "Validate", "Validate", "验证"]),
|
||||
("Weight", ["Weight", "Weight", "Weight", "Weight", "粗细"]),
|
||||
("Subtract", ["Subtract", "Subtract", "Subtract", "Subtract", "减去"]),
|
||||
("Intersect", ["Intersect", "Intersect", "Intersect", "Intersect", "交集"]),
|
||||
("Exclude Overlap", ["Exclude Overlap", "Exclude Overlap", "Exclude Overlap", "Exclude Overlap", "排除重叠"]),
|
||||
("Minus Back", ["Minus Back", "Minus Back", "Minus Back", "Minus Back", "减去后方对象"]),
|
||||
("Align left edges", ["Align left edges", "Align left edges", "Align left edges", "Align left edges", "左边缘对齐"]),
|
||||
(
|
||||
"Align horizontal centers",
|
||||
["Align horizontal centers", "Align horizontal centers", "Align horizontal centers", "Align horizontal centers", "水平居中对齐"],
|
||||
),
|
||||
("Align right edges", ["Align right edges", "Align right edges", "Align right edges", "Align right edges", "右边缘对齐"]),
|
||||
("Align top edges", ["Align top edges", "Align top edges", "Align top edges", "Align top edges", "顶边缘对齐"]),
|
||||
(
|
||||
"Align vertical centers",
|
||||
["Align vertical centers", "Align vertical centers", "Align vertical centers", "Align vertical centers", "垂直居中对齐"],
|
||||
),
|
||||
("Align bottom edges", ["Align bottom edges", "Align bottom edges", "Align bottom edges", "Align bottom edges", "底边缘对齐"]),
|
||||
("Align to Selection", ["Align to Selection", "Align to Selection", "Align to Selection", "Align to Selection", "对齐到所选对象"]),
|
||||
("Align to Key Object", ["Align to Key Object", "Align to Key Object", "Align to Key Object", "Align to Key Object", "对齐到关键对象"]),
|
||||
("Align to Margins", ["Align to Margins", "Align to Margins", "Align to Margins", "Align to Margins", "对齐到边距"]),
|
||||
("Align to Page", ["Align to Page", "Align to Page", "Align to Page", "Align to Page", "对齐到页面"]),
|
||||
("Align to Spread", ["Align to Spread", "Align to Spread", "Align to Spread", "Align to Spread", "对齐到跨页"]),
|
||||
("No Text Wrap", ["No Text Wrap", "No Text Wrap", "No Text Wrap", "No Text Wrap", "无文本绕排"]),
|
||||
(
|
||||
"Wrap Around Bounding Box",
|
||||
["Wrap Around Bounding Box", "Wrap Around Bounding Box", "Wrap Around Bounding Box", "Wrap Around Bounding Box", "绕排定界框"],
|
||||
),
|
||||
(
|
||||
"Wrap Around Object Shape",
|
||||
["Wrap Around Object Shape", "Wrap Around Object Shape", "Wrap Around Object Shape", "Wrap Around Object Shape", "绕排对象形状"],
|
||||
),
|
||||
("Jump Object", ["Jump Object", "Jump Object", "Jump Object", "Jump Object", "跳过对象"]),
|
||||
("Jump to Next Column", ["Jump to Next Column", "Jump to Next Column", "Jump to Next Column", "Jump to Next Column", "跳至下一栏"]),
|
||||
("Bulleted List", ["Bulleted List", "Bulleted List", "Bulleted List", "Bulleted List", "项目符号列表"]),
|
||||
("Numbered List", ["Numbered List", "Numbered List", "Numbered List", "Numbered List", "编号列表"]),
|
||||
("UPPERCASE", ["UPPERCASE", "UPPERCASE", "UPPERCASE", "UPPERCASE", "大写"]),
|
||||
("Small Caps", ["Small Caps", "Small Caps", "Small Caps", "Small Caps", "小型大写字母"]),
|
||||
("Normal", ["Normal", "Normal", "Normal", "Normal", "正常"]),
|
||||
("Butt", ["Butt", "Butt", "Butt", "Butt", "平头"]),
|
||||
("Round", ["Round", "Round", "Round", "Round", "圆形"]),
|
||||
("Projecting", ["Projecting", "Projecting", "Projecting", "Projecting", "突出"]),
|
||||
("Miter", ["Miter", "Miter", "Miter", "Miter", "斜接"]),
|
||||
("Bevel", ["Bevel", "Bevel", "Bevel", "Bevel", "斜角"]),
|
||||
("Center", ["Center", "Center", "Center", "Center", "居中"]),
|
||||
("Start/End:", ["Start/End:", "Start/End:", "Start/End:", "Start/End:", "起点/终点:"]),
|
||||
("Left", ["Left", "Left", "Left", "Left", "左"]),
|
||||
("Right", ["Right", "Right", "Right", "Right", "右"]),
|
||||
("First", ["First", "First", "First", "First", "首行"]),
|
||||
("Last", ["Last", "Last", "Last", "Last", "末行"]),
|
||||
("Before", ["Before", "Before", "Before", "Before", "段前"]),
|
||||
("After", ["After", "After", "After", "After", "段后"]),
|
||||
("Shading", ["Shading", "Shading", "Shading", "Shading", "底纹"]),
|
||||
("Border", ["Border", "Border", "Border", "Border", "边框"]),
|
||||
("Overprint Fill", ["Overprint Fill", "Overprint Fill", "Overprint Fill", "Overprint Fill", "叠印填色"]),
|
||||
("Overprint Stroke", ["Overprint Stroke", "Overprint Stroke", "Overprint Stroke", "Overprint Stroke", "叠印描边"]),
|
||||
("Overprint Gap", ["Overprint Gap", "Overprint Gap", "Overprint Gap", "Overprint Gap", "叠印间隙"]),
|
||||
("Nonprinting", ["Nonprinting", "Nonprinting", "Nonprinting", "Nonprinting", "不打印"]),
|
||||
("At Least", ["At Least", "At Least", "At Least", "At Least", "至少"]),
|
||||
("Exactly", ["Exactly", "Exactly", "Exactly", "Exactly", "固定"]),
|
||||
("Justify", ["Justify", "Justify", "Justify", "Justify", "两端对齐"]),
|
||||
("Underline Options", ["Underline Options", "Underline Options", "Underline Options", "Underline Options", "下划线选项"]),
|
||||
("Strikethrough Options", ["Strikethrough Options", "Strikethrough Options", "Strikethrough Options", "Strikethrough Options", "删除线选项"]),
|
||||
(
|
||||
"Discretionary Ligatures",
|
||||
["Discretionary Ligatures", "Discretionary Ligatures", "Discretionary Ligatures", "Discretionary Ligatures", "任意连字"],
|
||||
),
|
||||
("Fractions", ["Fractions", "Fractions", "Fractions", "Fractions", "分数"]),
|
||||
("Ordinal", ["Ordinal", "Ordinal", "Ordinal", "Ordinal", "序数"]),
|
||||
("Swash", ["Swash", "Swash", "Swash", "Swash", "花体"]),
|
||||
("Titling Alternates", ["Titling Alternates", "Titling Alternates", "Titling Alternates", "Titling Alternates", "标题替代字形"]),
|
||||
("Contextual Alternates", ["Contextual Alternates", "Contextual Alternates", "Contextual Alternates", "Contextual Alternates", "上下文替代字形"]),
|
||||
("Slashed Zero", ["Slashed Zero", "Slashed Zero", "Slashed Zero", "Slashed Zero", "斜线零"]),
|
||||
("Tabular Lining", ["Tabular Lining", "Tabular Lining", "Tabular Lining", "Tabular Lining", "等宽齐线数字"]),
|
||||
("Proportional Oldstyle", ["Proportional Oldstyle", "Proportional Oldstyle", "Proportional Oldstyle", "Proportional Oldstyle", "比例旧式数字"]),
|
||||
("Proportional Lining", ["Proportional Lining", "Proportional Lining", "Proportional Lining", "Proportional Lining", "比例齐线数字"]),
|
||||
("Tabular Oldstyle", ["Tabular Oldstyle", "Tabular Oldstyle", "Tabular Oldstyle", "Tabular Oldstyle", "等宽旧式数字"]),
|
||||
("Default Figure Style", ["Default Figure Style", "Default Figure Style", "Default Figure Style", "Default Figure Style", "默认数字样式"]),
|
||||
("Not a button", ["Not a button", "Not a button", "Not a button", "Not a button", "非按钮"]),
|
||||
("Go To Next Page", ["Go To Next Page", "Go To Next Page", "Go To Next Page", "Go To Next Page", "转到下一页"]),
|
||||
("Go To Previous Page", ["Go To Previous Page", "Go To Previous Page", "Go To Previous Page", "Go To Previous Page", "转到上一页"]),
|
||||
("Go To First Page", ["Go To First Page", "Go To First Page", "Go To First Page", "Go To First Page", "转到第一页"]),
|
||||
("Go To Last Page", ["Go To Last Page", "Go To Last Page", "Go To Last Page", "Go To Last Page", "转到最后一页"]),
|
||||
("Go To Page", ["Go To Page", "Go To Page", "Go To Page", "Go To Page", "转到页面"]),
|
||||
("Go To URL", ["Go To URL", "Go To URL", "Go To URL", "Go To URL", "转到网址"]),
|
||||
("Not a form field", ["Not a form field", "Not a form field", "Not a form field", "Not a form field", "非表单域"]),
|
||||
("Text Field", ["Text Field", "Text Field", "Text Field", "Text Field", "文本域"]),
|
||||
("Check Box", ["Check Box", "Check Box", "Check Box", "Check Box", "复选框"]),
|
||||
("Radio Button", ["Radio Button", "Radio Button", "Radio Button", "Radio Button", "单选按钮"]),
|
||||
("Combo Box", ["Combo Box", "Combo Box", "Combo Box", "Combo Box", "组合框"]),
|
||||
("List Box", ["List Box", "List Box", "List Box", "List Box", "列表框"]),
|
||||
("Signature", ["Signature", "Signature", "Signature", "Signature", "签名"]),
|
||||
("Resize width", ["Resize width", "Resize width", "Resize width", "Resize width", "调整宽度"]),
|
||||
("Resize height", ["Resize height", "Resize height", "Resize height", "Resize height", "调整高度"]),
|
||||
("Pin top", ["Pin top", "Pin top", "Pin top", "Pin top", "固定顶部"]),
|
||||
("Pin bottom", ["Pin bottom", "Pin bottom", "Pin bottom", "Pin bottom", "固定底部"]),
|
||||
("Pin left", ["Pin left", "Pin left", "Pin left", "Pin left", "固定左侧"]),
|
||||
("Pin right", ["Pin right", "Pin right", "Pin right", "Pin right", "固定右侧"]),
|
||||
("Inward", ["Inward", "Inward", "Inward", "Inward", "向内"]),
|
||||
("Horizontal", ["Horizontal", "Horizontal", "Horizontal", "Horizontal", "水平"]),
|
||||
("Vertical", ["Vertical", "Vertical", "Vertical", "Vertical", "垂直"]),
|
||||
("Metrics", ["Metrics", "Metrics", "Metrics", "Metrics", "度量"]),
|
||||
("Optical", ["Optical", "Optical", "Optical", "Optical", "视觉"]),
|
||||
("Applies to fill", ["Applies to fill", "Applies to fill", "Applies to fill", "Applies to fill", "应用于填色"]),
|
||||
("Applies to text", ["Applies to text", "Applies to text", "Applies to text", "Applies to text", "应用于文本"]),
|
||||
("Gray", ["Gray", "Gray", "Gray", "Gray", "灰度"]),
|
||||
("Linear", ["Linear", "Linear", "Linear", "Linear", "线性"]),
|
||||
("Radial", ["Radial", "Radial", "Radial", "Radial", "径向"]),
|
||||
("Arabic", ["Arabic", "Arabic", "Arabic", "Arabic", "阿拉伯语"]),
|
||||
("Beveled Rectangle", ["Beveled Rectangle", "Beveled Rectangle", "Beveled Rectangle", "Beveled Rectangle", "斜角矩形"]),
|
||||
("Chinese", ["Chinese", "Chinese", "Chinese", "Chinese", "中文"]),
|
||||
(
|
||||
"Constrain proportions for width and height",
|
||||
[
|
||||
"Constrain proportions for width and height",
|
||||
"Constrain proportions for width and height",
|
||||
"Constrain proportions for width and height",
|
||||
"Constrain proportions for width and height",
|
||||
"约束宽高比例",
|
||||
],
|
||||
),
|
||||
("Corner", ["Corner", "Corner", "Corner", "Corner", "角"]),
|
||||
("Custom", ["Custom", "Custom", "Custom", "Custom", "自定义"]),
|
||||
("Czech", ["Czech", "Czech", "Czech", "Czech", "捷克语"]),
|
||||
("Danish", ["Danish", "Danish", "Danish", "Danish", "丹麦语"]),
|
||||
("Dashed", ["Dashed", "Dashed", "Dashed", "Dashed", "虚线"]),
|
||||
("Dotted", ["Dotted", "Dotted", "Dotted", "Dotted", "点线"]),
|
||||
("Dutch: 2005 Reform", ["Dutch: 2005 Reform", "Dutch: 2005 Reform", "Dutch: 2005 Reform", "Dutch: 2005 Reform", "荷兰语:2005 年拼写改革"]),
|
||||
("Embedded", ["Embedded", "Embedded", "Embedded", "Embedded", "已嵌入"]),
|
||||
("English: Canadian", ["English: Canadian", "English: Canadian", "English: Canadian", "English: Canadian", "英语:加拿大"]),
|
||||
("English: UK", ["English: UK", "English: UK", "English: UK", "English: UK", "英语:英国"]),
|
||||
("English: USA", ["English: USA", "English: USA", "English: USA", "English: USA", "英语:美国"]),
|
||||
("Farsi", ["Farsi", "Farsi", "Farsi", "Farsi", "波斯语"]),
|
||||
("Finnish", ["Finnish", "Finnish", "Finnish", "Finnish", "芬兰语"]),
|
||||
("Fit Frame to Content", ["Fit Frame to Content", "Fit Frame to Content", "Fit Frame to Content", "Fit Frame to Content", "框架适合内容"]),
|
||||
("French", ["French", "French", "French", "French", "法语"]),
|
||||
("French: Canadian", ["French: Canadian", "French: Canadian", "French: Canadian", "French: Canadian", "法语:加拿大"]),
|
||||
("German: 2006 Reform", ["German: 2006 Reform", "German: 2006 Reform", "German: 2006 Reform", "German: 2006 Reform", "德语:2006 年拼写改革"]),
|
||||
(
|
||||
"German: Swiss 2006 Reform",
|
||||
[
|
||||
"German: Swiss 2006 Reform",
|
||||
"German: Swiss 2006 Reform",
|
||||
"German: Swiss 2006 Reform",
|
||||
"German: Swiss 2006 Reform",
|
||||
"德语:瑞士 2006 年拼写改革",
|
||||
],
|
||||
),
|
||||
("Greek", ["Greek", "Greek", "Greek", "Greek", "希腊语"]),
|
||||
("Hebrew", ["Hebrew", "Hebrew", "Hebrew", "Hebrew", "希伯来语"]),
|
||||
("Hindi", ["Hindi", "Hindi", "Hindi", "Hindi", "印地语"]),
|
||||
("Hungarian", ["Hungarian", "Hungarian", "Hungarian", "Hungarian", "匈牙利语"]),
|
||||
(
|
||||
"Inverse Rounded Rectangle",
|
||||
["Inverse Rounded Rectangle", "Inverse Rounded Rectangle", "Inverse Rounded Rectangle", "Inverse Rounded Rectangle", "内凹圆角矩形"],
|
||||
),
|
||||
("Italian", ["Italian", "Italian", "Italian", "Italian", "意大利语"]),
|
||||
("Japanese", ["Japanese", "Japanese", "Japanese", "Japanese", "日语"]),
|
||||
("Korean", ["Korean", "Korean", "Korean", "Korean", "韩语"]),
|
||||
(
|
||||
"Make all settings the same",
|
||||
["Make all settings the same", "Make all settings the same", "Make all settings the same", "Make all settings the same", "统一所有设置"],
|
||||
),
|
||||
("Native", ["Native", "Native", "Native", "Native", "本地数字"]),
|
||||
("Norwegian: Bokmål", ["Norwegian: Bokmål", "Norwegian: Bokmål", "Norwegian: Bokmål", "Norwegian: Bokmål", "挪威语:书面语"]),
|
||||
("Orthogonal Line", ["Orthogonal Line", "Orthogonal Line", "Orthogonal Line", "Orthogonal Line", "正交线"]),
|
||||
("Polish", ["Polish", "Polish", "Polish", "Polish", "波兰语"]),
|
||||
("Portuguese", ["Portuguese", "Portuguese", "Portuguese", "Portuguese", "葡萄牙语"]),
|
||||
("Portuguese: Brazilian", ["Portuguese: Brazilian", "Portuguese: Brazilian", "Portuguese: Brazilian", "Portuguese: Brazilian", "葡萄牙语:巴西"]),
|
||||
("Rounded Rectangle", ["Rounded Rectangle", "Rounded Rectangle", "Rounded Rectangle", "Rounded Rectangle", "圆角矩形"]),
|
||||
("Russian", ["Russian", "Russian", "Russian", "Russian", "俄语"]),
|
||||
("Solid", ["Solid", "Solid", "Solid", "Solid", "实线"]),
|
||||
("Spanish", ["Spanish", "Spanish", "Spanish", "Spanish", "西班牙语"]),
|
||||
("Story Editor", ["Story Editor", "Story Editor", "Story Editor", "Story Editor", "文章编辑器"]),
|
||||
("Swedish", ["Swedish", "Swedish", "Swedish", "Swedish", "瑞典语"]),
|
||||
("Thick - Thick", ["Thick - Thick", "Thick - Thick", "Thick - Thick", "Thick - Thick", "粗线-粗线"]),
|
||||
("Thick - Thin", ["Thick - Thin", "Thick - Thin", "Thick - Thin", "Thick - Thin", "粗线-细线"]),
|
||||
("Thin - Thick", ["Thin - Thick", "Thin - Thick", "Thin - Thick", "Thin - Thick", "细线-粗线"]),
|
||||
("Thin - Thin", ["Thin - Thin", "Thin - Thin", "Thin - Thin", "Thin - Thin", "细线-细线"]),
|
||||
("Thin - Thick - Thin", ["Thin - Thick - Thin", "Thin - Thick - Thin", "Thin - Thick - Thin", "Thin - Thick - Thin", "细线-粗线-细线"]),
|
||||
("Thick - Thin - Thick", ["Thick - Thin - Thick", "Thick - Thin - Thick", "Thick - Thin - Thick", "Thick - Thin - Thick", "粗线-细线-粗线"]),
|
||||
("Wavy", ["Wavy", "Wavy", "Wavy", "Wavy", "波浪线"]),
|
||||
("Straight Hash", ["Straight Hash", "Straight Hash", "Straight Hash", "Straight Hash", "直斜线"]),
|
||||
("Stripes", ["Stripes", "Stripes", "Stripes", "Stripes", "条纹"]),
|
||||
("Triangle", ["Triangle", "Triangle", "Triangle", "Triangle", "三角形"]),
|
||||
("Turkish", ["Turkish", "Turkish", "Turkish", "Turkish", "土耳其语"]),
|
||||
("Ukrainian", ["Ukrainian", "Ukrainian", "Ukrainian", "Ukrainian", "乌克兰语"]),
|
||||
("Cell Style", ["Cell Style", "Cell Style", "Cell Style", "Cell Style", "单元格样式"]),
|
||||
("Table Style", ["Table Style", "Table Style", "Table Style", "Table Style", "表格样式"]),
|
||||
("Col ←", ["Col ←", "Col ←", "Col ←", "Col ←", "左侧插入列"]),
|
||||
("Col →", ["Col →", "Col →", "Col →", "Col →", "右侧插入列"]),
|
||||
("Row ↑", ["Row ↑", "Row ↑", "Row ↑", "Row ↑", "上方插入行"]),
|
||||
("Row ↓", ["Row ↓", "Row ↓", "Row ↓", "Row ↓", "下方插入行"]),
|
||||
("Hide Others", ["Hide Others", "Hide Others", "Hide Others", "Hide Others", "隐藏其他图层"]),
|
||||
("Lock Others", ["Lock Others", "Lock Others", "Lock Others", "Lock Others", "锁定其他图层"]),
|
||||
("Show All Layers", ["Show All Layers", "Show All Layers", "Show All Layers", "Show All Layers", "显示所有图层"]),
|
||||
("Unlock", ["Unlock", "Unlock", "Unlock", "Unlock", "解锁"]),
|
||||
("Unlock All Layers", ["Unlock All Layers", "Unlock All Layers", "Unlock All Layers", "Unlock All Layers", "解锁所有图层"]),
|
||||
("Added", ["Added", "Added", "Added", "Added", "已添加"]),
|
||||
("Deleted", ["Deleted", "Deleted", "Deleted", "Deleted", "已删除"]),
|
||||
("Guide-based", ["Guide-based", "Guide-based", "Guide-based", "Guide-based", "基于参考线"]),
|
||||
("Loop", ["Loop", "Loop", "Loop", "Loop", "循环播放"]),
|
||||
("Object-based", ["Object-based", "Object-based", "Object-based", "Object-based", "基于对象"]),
|
||||
("Off", ["Off", "Off", "Off", "Off", "关闭"]),
|
||||
("Play on Page Load", ["Play on Page Load", "Play on Page Load", "Play on Page Load", "Play on Page Load", "页面载入时播放"]),
|
||||
("Re-center", ["Re-center", "Re-center", "Re-center", "Re-center", "重新居中"]),
|
||||
("Show Controls", ["Show Controls", "Show Controls", "Show Controls", "Show Controls", "显示控件"]),
|
||||
("Signature Field", ["Signature Field", "Signature Field", "Signature Field", "Signature Field", "签名域"]),
|
||||
(
|
||||
"Select text to apply a condition",
|
||||
[
|
||||
"Select text to apply a condition",
|
||||
"Select text to apply a condition",
|
||||
"Select text to apply a condition",
|
||||
"Select text to apply a condition",
|
||||
"选择文本以应用条件",
|
||||
],
|
||||
),
|
||||
("Blinds", ["Blinds", "Blinds", "Blinds", "Blinds", "百叶窗"]),
|
||||
("Box", ["Box", "Box", "Box", "Box", "方框"]),
|
||||
("Comb", ["Comb", "Comb", "Comb", "Comb", "梳状"]),
|
||||
("Cover", ["Cover", "Cover", "Cover", "Cover", "覆盖"]),
|
||||
("Dissolve", ["Dissolve", "Dissolve", "Dissolve", "Dissolve", "溶解"]),
|
||||
("Fade", ["Fade", "Fade", "Fade", "Fade", "淡入淡出"]),
|
||||
("Push", ["Push", "Push", "Push", "Push", "推入"]),
|
||||
("Split", ["Split", "Split", "Split", "Split", "分割"]),
|
||||
("Uncover", ["Uncover", "Uncover", "Uncover", "Uncover", "揭开"]),
|
||||
("Wipe", ["Wipe", "Wipe", "Wipe", "Wipe", "擦除"]),
|
||||
("Simple", ["Simple", "Simple", "Simple", "Simple", "简单"]),
|
||||
("Simple - Wide", ["Simple - Wide", "Simple - Wide", "Simple - Wide", "Simple - Wide", "简单-宽"]),
|
||||
("Triangle - Wide", ["Triangle - Wide", "Triangle - Wide", "Triangle - Wide", "Triangle - Wide", "三角形-宽"]),
|
||||
("Barbed", ["Barbed", "Barbed", "Barbed", "Barbed", "倒钩"]),
|
||||
("Curved", ["Curved", "Curved", "Curved", "Curved", "曲线"]),
|
||||
("Circle", ["Circle", "Circle", "Circle", "Circle", "圆形"]),
|
||||
("Circle - Solid", ["Circle - Solid", "Circle - Solid", "Circle - Solid", "Circle - Solid", "实心圆"]),
|
||||
("Square", ["Square", "Square", "Square", "Square", "正方形"]),
|
||||
("Square - Solid", ["Square - Solid", "Square - Solid", "Square - Solid", "Square - Solid", "实心正方形"]),
|
||||
("Bar", ["Bar", "Bar", "Bar", "Bar", "短线"]),
|
||||
("Fit Text", ["Fit Text", "Fit Text", "Fit Text", "Fit Text", "适合文本"]),
|
||||
("Preview (W)", ["Preview (W)", "Preview (W)", "Preview (W)", "Preview (W)", "预览 (W)"]),
|
||||
("Normal (W)", ["Normal (W)", "Normal (W)", "Normal (W)", "Normal (W)", "正常 (W)"]),
|
||||
("objects", ["objects", "objects", "objects", "objects", "个对象"]),
|
||||
("pages", ["pages", "pages", "pages", "pages", "页"]),
|
||||
("stories", ["stories", "stories", "stories", "stories", "篇文章"]),
|
||||
("items", ["items", "items", "items", "items", "个项目"]),
|
||||
("warnings", ["warnings", "warnings", "warnings", "warnings", "个警告"]),
|
||||
("Render", ["Render", "Render", "Render", "Render", "渲染"]),
|
||||
("Set", ["Set", "Set", "Set", "Set", "样式集"]),
|
||||
("unused", ["unused", "unused", "unused", "unused", "未使用"]),
|
||||
("⚠ Missing", ["⚠ Missing", "⚠ Missing", "⚠ Missing", "⚠ Missing", "⚠ 缺失"]),
|
||||
("▲ Modified", ["▲ Modified", "▲ Modified", "▲ Modified", "▲ Modified", "▲ 已修改"]),
|
||||
("(Text Color)", ["(Text Color)", "(Text Color)", "(Text Color)", "(Text Color)", "(文本颜色)"]),
|
||||
(
|
||||
"{count} glyphs — click to insert at the text cursor",
|
||||
[
|
||||
"{count} glyphs — click to insert at the text cursor",
|
||||
"{count} glyphs — click to insert at the text cursor",
|
||||
"{count} glyphs — click to insert at the text cursor",
|
||||
"{count} glyphs — click to insert at the text cursor",
|
||||
"{count} 个字形 — 单击插入到文本光标处",
|
||||
],
|
||||
),
|
||||
(
|
||||
"{pages} Pages in {spreads} Spreads",
|
||||
[
|
||||
"{pages} Pages in {spreads} Spreads",
|
||||
"{pages} Pages in {spreads} Spreads",
|
||||
"{pages} Pages in {spreads} Spreads",
|
||||
"{pages} Pages in {spreads} Spreads",
|
||||
"共 {pages} 页,{spreads} 个跨页",
|
||||
],
|
||||
),
|
||||
(" (auto)", [" (auto)", " (auto)", " (auto)", " (auto)", "(自动)"]),
|
||||
(
|
||||
"Absolute Numbering (instead of Section Numbering)",
|
||||
[
|
||||
"Absolute Numbering (instead of Section Numbering)",
|
||||
"Absolute Numbering (instead of Section Numbering)",
|
||||
"Absolute Numbering (instead of Section Numbering)",
|
||||
"Absolute Numbering (instead of Section Numbering)",
|
||||
"绝对页码(而非章节页码)",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Add and remove pages as the primary text frame's story grows and shrinks",
|
||||
[
|
||||
"Add and remove pages as the primary text frame's story grows and shrinks",
|
||||
"Add and remove pages as the primary text frame's story grows and shrinks",
|
||||
"Add and remove pages as the primary text frame's story grows and shrinks",
|
||||
"Add and remove pages as the primary text frame's story grows and shrinks",
|
||||
"随主文本框架内容增减自动添加或删除页面",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Added Text (highlighted)",
|
||||
["Added Text (highlighted)", "Added Text (highlighted)", "Added Text (highlighted)", "Added Text (highlighted)", "新增文本(高亮)"],
|
||||
),
|
||||
(
|
||||
"Adjust Layout (objects follow the new page size)",
|
||||
[
|
||||
"Adjust Layout (objects follow the new page size)",
|
||||
"Adjust Layout (objects follow the new page size)",
|
||||
"Adjust Layout (objects follow the new page size)",
|
||||
"Adjust Layout (objects follow the new page size)",
|
||||
"调整版面(对象随页面尺寸调整)",
|
||||
],
|
||||
),
|
||||
("Auto-Fit", ["Auto-Fit", "Auto-Fit", "Auto-Fit", "Auto-Fit", "自动适合"]),
|
||||
("Case sensitive", ["Case sensitive", "Case sensitive", "Case sensitive", "Case sensitive", "区分大小写"]),
|
||||
(
|
||||
"Custom Tracking/Kerning",
|
||||
["Custom Tracking/Kerning", "Custom Tracking/Kerning", "Custom Tracking/Kerning", "Custom Tracking/Kerning", "自定义字距/字偶距"],
|
||||
),
|
||||
(
|
||||
"Dimensions Include Stroke Weight",
|
||||
[
|
||||
"Dimensions Include Stroke Weight",
|
||||
"Dimensions Include Stroke Weight",
|
||||
"Dimensions Include Stroke Weight",
|
||||
"Dimensions Include Stroke Weight",
|
||||
"尺寸包含描边粗细",
|
||||
],
|
||||
),
|
||||
("Enable Autocorrect", ["Enable Autocorrect", "Enable Autocorrect", "Enable Autocorrect", "Enable Autocorrect", "启用自动更正"]),
|
||||
(
|
||||
"Enable Dynamic Spelling (underline misspelled words)",
|
||||
[
|
||||
"Enable Dynamic Spelling (underline misspelled words)",
|
||||
"Enable Dynamic Spelling (underline misspelled words)",
|
||||
"Enable Dynamic Spelling (underline misspelled words)",
|
||||
"Enable Dynamic Spelling (underline misspelled words)",
|
||||
"启用动态拼写检查(在拼写错误下加线)",
|
||||
],
|
||||
),
|
||||
("Grids in Back", ["Grids in Back", "Grids in Back", "Grids in Back", "Grids in Back", "网格置于后方"]),
|
||||
("H&J Violations", ["H&J Violations", "H&J Violations", "H&J Violations", "H&J Violations", "断字与对齐违规"]),
|
||||
("Include Bleed", ["Include Bleed", "Include Bleed", "Include Bleed", "Include Bleed", "包含出血"]),
|
||||
("Include Stroke Weight", ["Include Stroke Weight", "Include Stroke Weight", "Include Stroke Weight", "Include Stroke Weight", "包含描边粗细"]),
|
||||
("Join our Discord", ["Join our Discord", "Join our Discord", "Join our Discord", "Join our Discord", "加入我们的 Discord 社区"]),
|
||||
("Keep Violations", ["Keep Violations", "Keep Violations", "Keep Violations", "Keep Violations", "保持选项违规"]),
|
||||
(
|
||||
"Overprint [Black] Swatch at 100%",
|
||||
[
|
||||
"Overprint [Black] Swatch at 100%",
|
||||
"Overprint [Black] Swatch at 100%",
|
||||
"Overprint [Black] Swatch at 100%",
|
||||
"Overprint [Black] Swatch at 100%",
|
||||
"100% 黑色色板叠印",
|
||||
],
|
||||
),
|
||||
("Printer's Marks", ["Printer's Marks", "Printer's Marks", "Printer's Marks", "Printer's Marks", "打印标记"]),
|
||||
(
|
||||
"Remove Styles and Formatting from Text and Tables",
|
||||
[
|
||||
"Remove Styles and Formatting from Text and Tables",
|
||||
"Remove Styles and Formatting from Text and Tables",
|
||||
"Remove Styles and Formatting from Text and Tables",
|
||||
"Remove Styles and Formatting from Text and Tables",
|
||||
"移除文本和表格中的样式与格式",
|
||||
],
|
||||
),
|
||||
("Ruby", ["Ruby", "Ruby", "Ruby", "Ruby", "注音"]),
|
||||
(
|
||||
"Show Note Anchors in Layout View",
|
||||
[
|
||||
"Show Note Anchors in Layout View",
|
||||
"Show Note Anchors in Layout View",
|
||||
"Show Note Anchors in Layout View",
|
||||
"Show Note Anchors in Layout View",
|
||||
"在版面视图显示附注锚点",
|
||||
],
|
||||
),
|
||||
("Spreads", ["Spreads", "Spreads", "Spreads", "Spreads", "跨页"]),
|
||||
("Substituted Fonts", ["Substituted Fonts", "Substituted Fonts", "Substituted Fonts", "Substituted Fonts", "替换的字体"]),
|
||||
(
|
||||
"Transformations are Totals",
|
||||
["Transformations are Totals", "Transformations are Totals", "Transformations are Totals", "Transformations are Totals", "显示累计变换值"],
|
||||
),
|
||||
(
|
||||
"Use Black Point Compensation",
|
||||
[
|
||||
"Use Black Point Compensation",
|
||||
"Use Black Point Compensation",
|
||||
"Use Black Point Compensation",
|
||||
"Use Black Point Compensation",
|
||||
"使用黑场补偿",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Use Typographer's Quotes",
|
||||
["Use Typographer's Quotes", "Use Typographer's Quotes", "Use Typographer's Quotes", "Use Typographer's Quotes", "使用排版引号"],
|
||||
),
|
||||
("Whole word", ["Whole word", "Whole word", "Whole word", "Whole word", "全字匹配"]),
|
||||
("Interface", ["Interface", "Interface", "Interface", "Interface", "界面"]),
|
||||
("Advanced Type", ["Advanced Type", "Advanced Type", "Advanced Type", "Advanced Type", "高级文字"]),
|
||||
("Composition", ["Composition", "Composition", "Composition", "Composition", "排版"]),
|
||||
("Units & Increments", ["Units & Increments", "Units & Increments", "Units & Increments", "Units & Increments", "单位与增量"]),
|
||||
("Grids", ["Grids", "Grids", "Grids", "Grids", "网格"]),
|
||||
("Guides & Pasteboard", ["Guides & Pasteboard", "Guides & Pasteboard", "Guides & Pasteboard", "Guides & Pasteboard", "参考线与粘贴板"]),
|
||||
("Dictionary", ["Dictionary", "Dictionary", "Dictionary", "Dictionary", "词典"]),
|
||||
("Autocorrect", ["Autocorrect", "Autocorrect", "Autocorrect", "Autocorrect", "自动更正"]),
|
||||
("Story Editor Display", ["Story Editor Display", "Story Editor Display", "Story Editor Display", "Story Editor Display", "文章编辑器显示"]),
|
||||
("File Handling", ["File Handling", "File Handling", "File Handling", "File Handling", "文件处理"]),
|
||||
(
|
||||
"Formatting affects container (J)",
|
||||
[
|
||||
"Formatting affects container (J)",
|
||||
"Formatting affects container (J)",
|
||||
"Formatting affects container (J)",
|
||||
"Formatting affects container (J)",
|
||||
"格式应用于容器 (J)",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Formatting affects text (J)",
|
||||
[
|
||||
"Formatting affects text (J)",
|
||||
"Formatting affects text (J)",
|
||||
"Formatting affects text (J)",
|
||||
"Formatting affects text (J)",
|
||||
"格式应用于文字 (J)",
|
||||
],
|
||||
),
|
||||
("Apply None", ["Apply None", "Apply None", "Apply None", "Apply None", "应用无色"]),
|
||||
("Height Only", ["Height Only", "Height Only", "Height Only", "Height Only", "仅高度"]),
|
||||
("Width Only", ["Width Only", "Width Only", "Width Only", "Width Only", "仅宽度"]),
|
||||
("Height and Width", ["Height and Width", "Height and Width", "Height and Width", "Height and Width", "高度和宽度"]),
|
||||
("Height only", ["Height only", "Height only", "Height only", "Height only", "仅高度"]),
|
||||
("Width only", ["Width only", "Width only", "Width only", "Width only", "仅宽度"]),
|
||||
("Height and width", ["Height and width", "Height and width", "Height and width", "Height and width", "高度和宽度"]),
|
||||
("Version", ["Version", "Version", "Version", "Version", "版本"]),
|
||||
(
|
||||
"{count} characters don't fit",
|
||||
[
|
||||
"{count} characters don't fit",
|
||||
"{count} characters don't fit",
|
||||
"{count} characters don't fit",
|
||||
"{count} characters don't fit",
|
||||
"有 {count} 个字符溢出",
|
||||
],
|
||||
),
|
||||
("document", ["document", "document", "document", "document", "文档"]),
|
||||
("story", ["story", "story", "story", "story", "文章"]),
|
||||
("selection", ["selection", "selection", "selection", "selection", "选区"]),
|
||||
("top", ["top", "top", "top", "top", "顶部"]),
|
||||
("center", ["center", "center", "center", "center", "居中"]),
|
||||
("bottom", ["bottom", "bottom", "bottom", "bottom", "底部"]),
|
||||
("justify", ["justify", "justify", "justify", "justify", "两端对齐"]),
|
||||
("text", ["text", "text", "text", "text", "文字"]),
|
||||
("graphic", ["graphic", "graphic", "graphic", "graphic", "图形"]),
|
||||
("unassigned", ["unassigned", "unassigned", "unassigned", "unassigned", "未指定"]),
|
||||
("Perceptual", ["Perceptual", "Perceptual", "Perceptual", "Perceptual", "可感知"]),
|
||||
("Relative Colorimetric", ["Relative Colorimetric", "Relative Colorimetric", "Relative Colorimetric", "Relative Colorimetric", "相对比色"]),
|
||||
("Saturation", ["Saturation", "Saturation", "Saturation", "Saturation", "饱和度"]),
|
||||
("Absolute Colorimetric", ["Absolute Colorimetric", "Absolute Colorimetric", "Absolute Colorimetric", "Absolute Colorimetric", "绝对比色"]),
|
||||
("No conflicts", ["No conflicts", "No conflicts", "No conflicts", "No conflicts", "没有冲突"]),
|
||||
("Page (1–{count}):", ["Page (1–{count}):", "Page (1–{count}):", "Page (1–{count}):", "Page (1–{count}):", "页码 (1–{count}):"]),
|
||||
(
|
||||
"Fonts in Document: {count} Missing: {missing}",
|
||||
[
|
||||
"Fonts in Document: {count} Missing: {missing}",
|
||||
"Fonts in Document: {count} Missing: {missing}",
|
||||
"Fonts in Document: {count} Missing: {missing}",
|
||||
"Fonts in Document: {count} Missing: {missing}",
|
||||
"文档中的字体:{count} 缺失:{missing}",
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
/// Interface direction; independent of document binding and paragraph direction.
|
||||
@@ -1816,6 +2626,22 @@ pub fn tr<'a>(lang: &str, s: &'a str) -> &'a str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Localize reserved built-in style names only; user-defined names are document data.
|
||||
pub fn style_name<'a>(lang: &str, name: &'a str) -> &'a str {
|
||||
match name {
|
||||
designcraft_doc::NO_PARA_STYLE | designcraft_doc::BASIC_PARAGRAPH | designcraft_doc::NO_CHAR_STYLE => tr(lang, name),
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Built-in workspace captions; custom workspace names remain unchanged.
|
||||
pub fn workspace_name<'a>(lang: &str, name: &'a str) -> &'a str {
|
||||
match name {
|
||||
"Essentials" | "Advanced" | "Book" | "Digital Publishing" | "Interactive for PDF" | "Printing and Proofing" | "Typography" => tr(lang, name),
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -273,4 +273,740 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Options", "خيارات"),
|
||||
("More Options", "خيارات إضافية"),
|
||||
("Dialog", "مربع حوار"),
|
||||
("General", "عام"),
|
||||
("Basic Character Formats", "تنسيقات الأحرف الأساسية"),
|
||||
("Indents and Spacing", "المسافات البادئة والتباعد"),
|
||||
("Justification", "الضبط"),
|
||||
("Drop Caps and Nested Styles", "الأحرف الاستهلالية والأنماط المتداخلة"),
|
||||
("GREP Style", "نمط GREP"),
|
||||
("Character Color", "لون الأحرف"),
|
||||
("Export Tagging", "وسوم التصدير"),
|
||||
("Numbering and Formatting", "الترقيم والتنسيق"),
|
||||
("Spacing Options", "خيارات التباعد"),
|
||||
("First Baseline", "خط الأساس الأول"),
|
||||
("Rule Above", "خط علوي"),
|
||||
("Numbering", "الترقيم"),
|
||||
("Footnote Reference Number in Text", "رقم مرجع الحاشية في النص"),
|
||||
("Footnote Formatting", "تنسيق الحواشي"),
|
||||
("Span Footnotes Across Columns", "امتداد الحواشي عبر الأعمدة"),
|
||||
("Rule On", "إظهار الخط"),
|
||||
("Ascent", "ارتفاع الحروف الصاعدة"),
|
||||
("Cap Height", "ارتفاع الأحرف الكبيرة"),
|
||||
("x Height", "ارتفاع حرف x"),
|
||||
("Fixed", "ثابت"),
|
||||
("Never (continuous)", "أبدًا (ترقيم متصل)"),
|
||||
("Spread", "صفحتان متقابلتان"),
|
||||
("Section", "قسم"),
|
||||
("Footnote Reference", "مرجع الحاشية"),
|
||||
("Footnote Text", "نص الحاشية"),
|
||||
("Both", "كلاهما"),
|
||||
("Apply Superscript", "تطبيق مرتفع"),
|
||||
("Apply Subscript", "تطبيق منخفض"),
|
||||
("Apply Normal", "تطبيق عادي"),
|
||||
("OpenType Superscript", "مرتفع OpenType"),
|
||||
("through", "حتى شاملًا"),
|
||||
("up to", "حتى باستثناء"),
|
||||
("line", "سطر"),
|
||||
("lines", "أسطر"),
|
||||
("sentences", "جمل"),
|
||||
("words", "كلمات"),
|
||||
("characters", "محارف"),
|
||||
("letters", "حروف"),
|
||||
("digits", "أرقام"),
|
||||
("tab", "جدولة"),
|
||||
("forcedLineBreak", "فاصل سطر إجباري"),
|
||||
("emSpace", "مسافة em"),
|
||||
("enSpace", "مسافة en"),
|
||||
("chars", "محارف محددة"),
|
||||
("[Automatic]", "[تلقائي]"),
|
||||
("Size:", "الحجم:"),
|
||||
("Tracking:", "التباعد:"),
|
||||
("Left Indent:", "المسافة البادئة اليسرى:"),
|
||||
("Right Indent:", "المسافة البادئة اليمنى:"),
|
||||
("First Line Indent:", "المسافة البادئة للسطر الأول:"),
|
||||
("Space Before:", "المسافة قبل الفقرة:"),
|
||||
("Space After:", "المسافة بعد الفقرة:"),
|
||||
("Words with at Least:", "الحد الأدنى لطول الكلمة:"),
|
||||
("After First:", "الأحرف قبل الواصلة:"),
|
||||
("Before Last:", "الأحرف بعد الواصلة:"),
|
||||
("Hyphen Limit:", "حد الأسطر المتتالية بواصلة:"),
|
||||
("Word Spacing:", "تباعد الكلمات:"),
|
||||
("Letter Spacing:", "تباعد الحروف:"),
|
||||
("Glyph Scaling:", "تحجيم الحروف:"),
|
||||
("Insert Kashidas:", "إدراج الكشيدة:"),
|
||||
("In justified Arabic text", "في النص العربي المضبوط"),
|
||||
("Minimum Space Before First Footnote:", "أقل مسافة قبل الحاشية الأولى:"),
|
||||
("Space Between Footnotes:", "المسافة بين الحواشي:"),
|
||||
("Offset:", "الإزاحة:"),
|
||||
("Min:", "الحد الأدنى:"),
|
||||
("Weight:", "السماكة:"),
|
||||
("Color:", "اللون:"),
|
||||
("Width:", "العرض:"),
|
||||
("Style:", "النمط:"),
|
||||
("Start at:", "بدء الترقيم من:"),
|
||||
("Restart Numbering Every:", "إعادة بدء الترقيم كل:"),
|
||||
("Show Prefix/Suffix in:", "إظهار البادئة واللاحقة في:"),
|
||||
("Prefix:", "البادئة:"),
|
||||
("Suffix:", "اللاحقة:"),
|
||||
("Position:", "الموضع:"),
|
||||
("Character Style:", "نمط الأحرف:"),
|
||||
("Paragraph Style:", "نمط الفقرة:"),
|
||||
("Separator:", "الفاصل:"),
|
||||
("EPUB and HTML", "EPUB وHTML"),
|
||||
("Tag:", "الوسم:"),
|
||||
("Class:", "الفئة:"),
|
||||
("Nested Styles", "الأنماط المتداخلة"),
|
||||
("Nested Line Styles", "أنماط الأسطر المتداخلة"),
|
||||
("New Nested Style", "نمط متداخل جديد"),
|
||||
("New Line Style", "نمط سطر جديد"),
|
||||
("GREP Styles", "أنماط GREP"),
|
||||
("Apply Style:", "تطبيق النمط:"),
|
||||
("To Text:", "على النص:"),
|
||||
("New GREP Style", "نمط GREP جديد"),
|
||||
("Font Family:", "عائلة الخط:"),
|
||||
("Font Style:", "نمط الخط:"),
|
||||
("Leading:", "تباعد الأسطر:"),
|
||||
("Alignment:", "المحاذاة:"),
|
||||
("Hyphenate", "إضافة واصلات"),
|
||||
("Minimum", "الحد الأدنى"),
|
||||
("Desired", "المطلوب"),
|
||||
("Maximum", "الحد الأقصى"),
|
||||
("Composer:", "منضّد النص:"),
|
||||
("Paragraph Composer", "منضّد الفقرات"),
|
||||
("Single-line Composer", "منضّد السطر الواحد"),
|
||||
("Style Name:", "اسم النمط:"),
|
||||
("Based On:", "استنادًا إلى:"),
|
||||
("for", "لعدد"),
|
||||
("Hyphenation Exceptions", "استثناءات الواصلة"),
|
||||
("Binding:", "اتجاه التجليد:"),
|
||||
("Dynamic Spelling", "التدقيق الإملائي التلقائي"),
|
||||
("UI Scaling", "تحجيم الواجهة"),
|
||||
("Ruby:", "روبي:"),
|
||||
("Set over the selected text; empty removes it.", "تُضاف فوق النص المحدد؛ اتركها فارغة للإزالة."),
|
||||
("Document Footnote Options…", "خيارات حواشي المستند…"),
|
||||
("Insert Footnote", "إدراج حاشية"),
|
||||
("Go to Footnote Reference", "الانتقال إلى مرجع الحاشية"),
|
||||
("Footnotes", "الحواشي"),
|
||||
("Paragraph Style Options…", "خيارات نمط الفقرة…"),
|
||||
("New Paragraph Style…", "نمط فقرة جديد…"),
|
||||
("New Character Style…", "نمط أحرف جديد…"),
|
||||
("[Basic Paragraph]", "[فقرة أساسية]"),
|
||||
("[No Paragraph Style]", "[بلا نمط فقرة]"),
|
||||
("Align left", "محاذاة إلى اليسار"),
|
||||
("Align center", "محاذاة إلى الوسط"),
|
||||
("Align right", "محاذاة إلى اليمين"),
|
||||
("Justify with last line aligned left", "ضبط مع محاذاة السطر الأخير إلى اليسار"),
|
||||
("Justify with last line aligned center", "ضبط مع توسيط السطر الأخير"),
|
||||
("Justify with last line aligned right", "ضبط مع محاذاة السطر الأخير إلى اليمين"),
|
||||
("Justify all lines", "ضبط جميع الأسطر"),
|
||||
("Align towards spine", "محاذاة نحو الكعب"),
|
||||
("Align away from spine", "محاذاة بعيدًا عن الكعب"),
|
||||
("Create New Style from Selection", "إنشاء نمط جديد من التحديد"),
|
||||
("No text selected", "لم يتم تحديد نص"),
|
||||
("Essentials", "الأساسيات"),
|
||||
("Advanced", "متقدم"),
|
||||
("Book", "كتاب"),
|
||||
("Digital Publishing", "النشر الرقمي"),
|
||||
("Interactive for PDF", "التفاعل في PDF"),
|
||||
("Printing and Proofing", "الطباعة والتدقيق"),
|
||||
("Typography", "تنضيد النصوص"),
|
||||
("No errors", "لا توجد أخطاء"),
|
||||
("error", "خطأ"),
|
||||
("errors", "أخطاء"),
|
||||
("Display All Blacks as Rich Black", "عرض كل درجات الأسود كأسود غني"),
|
||||
("Display All Blacks Accurately", "عرض كل درجات الأسود بدقة"),
|
||||
("Output All Blacks as Rich Black", "إخراج كل درجات الأسود كأسود غني"),
|
||||
("Output All Blacks Accurately", "إخراج كل درجات الأسود بدقة"),
|
||||
("Top Margin", "الهامش العلوي"),
|
||||
("Top of Page", "أعلى الصفحة"),
|
||||
("Paragraph Styles panel", "لوحة أنماط الفقرات"),
|
||||
("Character Styles panel", "لوحة أنماط الأحرف"),
|
||||
("Create new style", "إنشاء نمط جديد"),
|
||||
("Clear overrides", "مسح التجاوزات"),
|
||||
("Accept", "قبول"),
|
||||
("Reject", "رفض"),
|
||||
("Add Selection", "إضافة التحديد"),
|
||||
("Add the selection", "إضافة التحديد"),
|
||||
("Add to Swatches", "إضافة إلى الحوامل"),
|
||||
("Align Stroke:", "محاذاة الحد:"),
|
||||
("All Caps", "أحرف كبيرة"),
|
||||
("Angle", "الزاوية"),
|
||||
("Angle:", "الزاوية:"),
|
||||
("Baseline", "خط الأساس"),
|
||||
("Cap:", "نهاية الخط:"),
|
||||
("Cell Text", "نص الخلية"),
|
||||
("Cell Type", "نوع الخلية"),
|
||||
("Column Width", "عرض العمود"),
|
||||
("Composer", "منضّد النص"),
|
||||
("Convert Selection to Multi-State Object", "تحويل التحديد إلى كائن متعدد الحالات"),
|
||||
("Convert to Text", "تحويل إلى نص"),
|
||||
("Create New Layer", "إنشاء طبقة جديدة"),
|
||||
("Default", "افتراضي"),
|
||||
("Delete DTD", "حذف DTD"),
|
||||
("Delete Layer", "حذف الطبقة"),
|
||||
("Delete Page", "حذف الصفحة"),
|
||||
("Digits", "الأرقام"),
|
||||
("Distance", "المسافة"),
|
||||
("Distribute ↔", "توزيع أفقي"),
|
||||
("Distribute ↕", "توزيع عمودي"),
|
||||
("Drop Shadow", "ظل ساقط"),
|
||||
("Effects: Drop Shadow", "التأثيرات: ظل ساقط"),
|
||||
("Favorites", "المفضلة"),
|
||||
("First Spread", "أول صفحتين متقابلتين"),
|
||||
("Frame Fitting", "ملاءمة الإطار"),
|
||||
("Gap Color:", "لون الفجوة:"),
|
||||
("Go To", "انتقال إلى"),
|
||||
("Graphic…", "رسم…"),
|
||||
("Home", "الرئيسية"),
|
||||
("Hyperlink from the selected text or frames", "إنشاء رابط من النص أو الإطارات المحددة"),
|
||||
("Include when exporting", "تضمين عند التصدير"),
|
||||
("Join:", "وصلة الخط:"),
|
||||
("Last Spread", "آخر صفحتين متقابلتين"),
|
||||
("Linked Stories", "النصوص المرتبطة"),
|
||||
("Load DTD…", "تحميل DTD…"),
|
||||
("Location:", "الموضع:"),
|
||||
("Miter Limit:", "حد الوصلة الحادة:"),
|
||||
("Move", "نقل"),
|
||||
("New Article from Selection", "مقال جديد من التحديد"),
|
||||
("New Note at Cursor", "ملاحظة جديدة عند المؤشر"),
|
||||
("New condition name", "اسم الشرط الجديد"),
|
||||
("New group…", "مجموعة جديدة…"),
|
||||
("New tag", "وسم جديد"),
|
||||
("Next Spread", "الصفحتان التاليتان"),
|
||||
("Note text", "نص الملاحظة"),
|
||||
("Offset", "الإزاحة"),
|
||||
("Offsets", "الإزاحات"),
|
||||
("Open", "فتح"),
|
||||
("Paragraph alignment", "محاذاة الفقرة"),
|
||||
("Pick a file in the folder holding the moved graphics", "اختر ملفًا من المجلد الذي يحتوي على الرسومات المنقولة"),
|
||||
("Place", "إدراج"),
|
||||
("Previous Spread", "الصفحتان السابقتان"),
|
||||
("Release to Objects", "تحرير إلى كائنات"),
|
||||
("Reverse the gradient", "عكس التدرج"),
|
||||
("Rotate 90° Counterclockwise", "تدوير 90° عكس عقارب الساعة"),
|
||||
("Rotation Angle", "زاوية الدوران"),
|
||||
("Row Height", "ارتفاع الصف"),
|
||||
("Run", "تشغيل"),
|
||||
("Scale X Percentage", "نسبة التحجيم الأفقي"),
|
||||
("Scale Y Percentage", "نسبة التحجيم العمودي"),
|
||||
("Search commands", "البحث عن الأوامر"),
|
||||
("Search fonts", "البحث عن الخطوط"),
|
||||
("Search styles and commands…", "البحث عن الأنماط والأوامر…"),
|
||||
("Search: character or U+code", "البحث بحرف أو رمز U+"),
|
||||
("Separated by commas", "مفصولة بفواصل"),
|
||||
("Share", "مشاركة"),
|
||||
("Shear X Angle", "زاوية الميل الأفقي"),
|
||||
("Show / hide text with this condition", "إظهار أو إخفاء النص بهذا الشرط"),
|
||||
("Show Favorites Only", "إظهار المفضلة فقط"),
|
||||
("Show in the text", "إظهار في النص"),
|
||||
("Spreads of up to 10 pages", "مجموعات تصل إلى 10 صفحات"),
|
||||
("Stop Color:", "لون نقطة التدرج:"),
|
||||
("Strikethrough", "يتوسطه خط"),
|
||||
("Structure", "البنية"),
|
||||
("Style", "النمط"),
|
||||
("Style source", "مصدر الأنماط"),
|
||||
("Styles panel", "لوحة الأنماط"),
|
||||
("Superscript", "مرتفع"),
|
||||
("Tag the selection", "إضافة وسم للتحديد"),
|
||||
("The structure is valid.", "البنية صالحة."),
|
||||
("Toggle double column", "تبديل التخطيط بعمودين"),
|
||||
("Type:", "النوع:"),
|
||||
("Underline", "تسطير"),
|
||||
("Untag Selection", "إزالة الوسم عن التحديد"),
|
||||
("Update", "تحديث"),
|
||||
("Validate", "تحقق"),
|
||||
("Weight", "السماكة"),
|
||||
("Subtract", "طرح"),
|
||||
("Intersect", "تقاطع"),
|
||||
("Exclude Overlap", "استبعاد التداخل"),
|
||||
("Minus Back", "طرح الخلفية"),
|
||||
("Make Compound", "إنشاء مسار مركب"),
|
||||
("Release", "تحرير"),
|
||||
("Paths", "مسارات"),
|
||||
("Align left edges", "محاذاة الحواف اليسرى"),
|
||||
("Align horizontal centers", "محاذاة المراكز أفقيًا"),
|
||||
("Align right edges", "محاذاة الحواف اليمنى"),
|
||||
("Align top edges", "محاذاة الحواف العليا"),
|
||||
("Align vertical centers", "محاذاة المراكز عموديًا"),
|
||||
("Align bottom edges", "محاذاة الحواف السفلى"),
|
||||
("Align to Selection", "محاذاة إلى التحديد"),
|
||||
("Align to Key Object", "محاذاة إلى الكائن الرئيسي"),
|
||||
("Align to Margins", "محاذاة إلى الهوامش"),
|
||||
("Align to Page", "محاذاة إلى الصفحة"),
|
||||
("Align to Spread", "محاذاة إلى الصفحات المتقابلة"),
|
||||
("No Text Wrap", "بلا التفاف للنص"),
|
||||
("Wrap Around Bounding Box", "التفاف حول المربع المحيط"),
|
||||
("Wrap Around Object Shape", "التفاف حول شكل الكائن"),
|
||||
("Jump Object", "تجاوز الكائن"),
|
||||
("Jump to Next Column", "انتقال إلى العمود التالي"),
|
||||
("Bulleted List", "قائمة نقطية"),
|
||||
("Numbered List", "قائمة مرقمة"),
|
||||
("UPPERCASE", "أحرف كبيرة"),
|
||||
("Small Caps", "أحرف كبيرة صغيرة الحجم"),
|
||||
("Butt", "مسطحة"),
|
||||
("Round", "مستديرة"),
|
||||
("Projecting", "بارزة"),
|
||||
("Miter", "حادة"),
|
||||
("Bevel", "مشطوفة"),
|
||||
("Center", "وسط"),
|
||||
("Start/End:", "البداية/النهاية:"),
|
||||
("First", "الأول"),
|
||||
("Last", "الأخير"),
|
||||
("Before", "قبل"),
|
||||
("After", "بعد"),
|
||||
("Shading", "تظليل"),
|
||||
("Border", "إطار"),
|
||||
("Overprint Fill", "طباعة التعبئة فوقيًا"),
|
||||
("Overprint Stroke", "طباعة الحد فوقيًا"),
|
||||
("Overprint Gap", "طباعة الفجوة فوقيًا"),
|
||||
("Nonprinting", "غير قابل للطباعة"),
|
||||
("At Least", "على الأقل"),
|
||||
("Exactly", "بالضبط"),
|
||||
("Justify", "ضبط"),
|
||||
("Underline Options", "خيارات التسطير"),
|
||||
("Strikethrough Options", "خيارات الخط المتوسط"),
|
||||
("Discretionary Ligatures", "روابط اختيارية"),
|
||||
("Fractions", "كسور"),
|
||||
("Ordinal", "ترتيبي"),
|
||||
("Swash", "زخرفي"),
|
||||
("Titling Alternates", "بدائل العناوين"),
|
||||
("Contextual Alternates", "بدائل سياقية"),
|
||||
("Slashed Zero", "صفر مشطوب"),
|
||||
("Tabular Lining", "أرقام منتظمة ثابتة العرض"),
|
||||
("Proportional Oldstyle", "أرقام قديمة متناسبة"),
|
||||
("Proportional Lining", "أرقام منتظمة متناسبة"),
|
||||
("Tabular Oldstyle", "أرقام قديمة ثابتة العرض"),
|
||||
("Default Figure Style", "نمط الأرقام الافتراضي"),
|
||||
("Not a button", "ليس زرًا"),
|
||||
("Go To Next Page", "انتقال إلى الصفحة التالية"),
|
||||
("Go To Previous Page", "انتقال إلى الصفحة السابقة"),
|
||||
("Go To First Page", "انتقال إلى الصفحة الأولى"),
|
||||
("Go To Last Page", "انتقال إلى الصفحة الأخيرة"),
|
||||
("Go To Page", "انتقال إلى صفحة"),
|
||||
("Go To URL", "انتقال إلى عنوان URL"),
|
||||
("Not a form field", "ليس حقل نموذج"),
|
||||
("Text Field", "حقل نص"),
|
||||
("Check Box", "خانة اختيار"),
|
||||
("Radio Button", "زر اختيار"),
|
||||
("Combo Box", "مربع تحرير وسرد"),
|
||||
("List Box", "مربع قائمة"),
|
||||
("Signature", "توقيع"),
|
||||
("Resize width", "تغيير العرض"),
|
||||
("Resize height", "تغيير الارتفاع"),
|
||||
("Pin top", "تثبيت الأعلى"),
|
||||
("Pin bottom", "تثبيت الأسفل"),
|
||||
("Pin left", "تثبيت اليسار"),
|
||||
("Pin right", "تثبيت اليمين"),
|
||||
("Inward", "إلى الداخل"),
|
||||
("Metrics", "مقاييس"),
|
||||
("Optical", "بصري"),
|
||||
("Applies to fill", "يُطبّق على التعبئة"),
|
||||
("Applies to text", "يُطبّق على النص"),
|
||||
("Gray", "رمادي"),
|
||||
("Linear", "خطي"),
|
||||
("Radial", "شعاعي"),
|
||||
("Arabic", "العربية"),
|
||||
("Beveled Rectangle", "مستطيل مشطوف"),
|
||||
("Chinese", "الصينية"),
|
||||
("Constrain proportions for width and height", "تقييد نسب العرض والارتفاع"),
|
||||
("Custom", "مخصص"),
|
||||
("Czech", "التشيكية"),
|
||||
("Danish", "الدنماركية"),
|
||||
("Dashed", "متقطع"),
|
||||
("Dotted", "منقط"),
|
||||
("Dutch: 2005 Reform", "الهولندية: إصلاح 2005"),
|
||||
("Embedded", "مضمّن"),
|
||||
("English: Canadian", "الإنجليزية: كندا"),
|
||||
("English: UK", "الإنجليزية: المملكة المتحدة"),
|
||||
("English: USA", "الإنجليزية: الولايات المتحدة"),
|
||||
("Farsi", "الفارسية"),
|
||||
("Finnish", "الفنلندية"),
|
||||
("French", "الفرنسية"),
|
||||
("French: Canadian", "الفرنسية: كندا"),
|
||||
("German: 2006 Reform", "الألمانية: إصلاح 2006"),
|
||||
("German: Swiss 2006 Reform", "الألمانية: الإصلاح السويسري 2006"),
|
||||
("Greek", "اليونانية"),
|
||||
("Hebrew", "العبرية"),
|
||||
("Hindi", "الهندية"),
|
||||
("Hungarian", "المجرية"),
|
||||
("Inverse Rounded Rectangle", "مستطيل بزوايا دائرية معكوسة"),
|
||||
("Italian", "الإيطالية"),
|
||||
("Japanese", "اليابانية"),
|
||||
("Korean", "الكورية"),
|
||||
("Make all settings the same", "توحيد جميع الإعدادات"),
|
||||
("Native", "أرقام محلية"),
|
||||
("Norwegian: Bokmål", "النرويجية: بوكمول"),
|
||||
("Orthogonal Line", "خط متعامد"),
|
||||
("Polish", "البولندية"),
|
||||
("Portuguese", "البرتغالية"),
|
||||
("Portuguese: Brazilian", "البرتغالية: البرازيل"),
|
||||
("Rounded Rectangle", "مستطيل مستدير الزوايا"),
|
||||
("Russian", "الروسية"),
|
||||
("Solid", "متصل"),
|
||||
("Spanish", "الإسبانية"),
|
||||
("Swedish", "السويدية"),
|
||||
("Thick - Thick", "سميك - سميك"),
|
||||
("Thick - Thin", "سميك - رفيع"),
|
||||
("Thin - Thick", "رفيع - سميك"),
|
||||
("Thin - Thin", "رفيع - رفيع"),
|
||||
("Thin - Thick - Thin", "رفيع - سميك - رفيع"),
|
||||
("Thick - Thin - Thick", "سميك - رفيع - سميك"),
|
||||
("Wavy", "متموج"),
|
||||
("Straight Hash", "شرطات مائلة"),
|
||||
("Stripes", "خطوط"),
|
||||
("Triangle", "مثلث"),
|
||||
("Turkish", "التركية"),
|
||||
("Ukrainian", "الأوكرانية"),
|
||||
("Cell Style", "نمط الخلية"),
|
||||
("Table Style", "نمط الجدول"),
|
||||
("Col ←", "إدراج عمود يسارًا"),
|
||||
("Col →", "إدراج عمود يمينًا"),
|
||||
("Row ↑", "إدراج صف أعلى"),
|
||||
("Row ↓", "إدراج صف أسفل"),
|
||||
("Hide Others", "إخفاء الطبقات الأخرى"),
|
||||
("Lock Others", "قفل الطبقات الأخرى"),
|
||||
("Show All Layers", "إظهار كل الطبقات"),
|
||||
("Unlock", "إلغاء القفل"),
|
||||
("Unlock All Layers", "إلغاء قفل كل الطبقات"),
|
||||
("Added", "مضاف"),
|
||||
("Deleted", "محذوف"),
|
||||
("Guide-based", "استنادًا إلى الأدلة"),
|
||||
("Loop", "تكرار"),
|
||||
("Object-based", "استنادًا إلى الكائنات"),
|
||||
("Play on Page Load", "تشغيل عند تحميل الصفحة"),
|
||||
("Re-center", "إعادة التوسيط"),
|
||||
("Show Controls", "إظهار عناصر التحكم"),
|
||||
("Signature Field", "حقل توقيع"),
|
||||
("Select text to apply a condition", "حدد نصًا لتطبيق شرط"),
|
||||
("Blinds", "ستائر"),
|
||||
("Box", "مربع"),
|
||||
("Comb", "مشط"),
|
||||
("Cover", "تغطية"),
|
||||
("Dissolve", "تلاشي متناثر"),
|
||||
("Fade", "تلاشي"),
|
||||
("Push", "دفع"),
|
||||
("Split", "انقسام"),
|
||||
("Uncover", "كشف"),
|
||||
("Wipe", "مسح"),
|
||||
("Simple", "بسيط"),
|
||||
("Simple - Wide", "بسيط - عريض"),
|
||||
("Triangle - Wide", "مثلث - عريض"),
|
||||
("Barbed", "مسنن"),
|
||||
("Curved", "منحني"),
|
||||
("Circle", "دائرة"),
|
||||
("Circle - Solid", "دائرة مصمتة"),
|
||||
("Square", "مربع"),
|
||||
("Square - Solid", "مربع مصمت"),
|
||||
("Bar", "شرطة"),
|
||||
("Hide", "إخفاء"),
|
||||
("Show", "إظهار"),
|
||||
("Select", "تحديد"),
|
||||
("Fit Text", "ملاءمة النص"),
|
||||
("Preview (W)", "معاينة (W)"),
|
||||
("Normal (W)", "عادي (W)"),
|
||||
("Conveyor", "ناقل المحتوى"),
|
||||
("objects", "كائنات"),
|
||||
("pages", "صفحات"),
|
||||
("stories", "نصوص"),
|
||||
("items", "عناصر"),
|
||||
("warnings", "تحذيرات"),
|
||||
("Render", "تصيير"),
|
||||
("Set", "مجموعة"),
|
||||
("unused", "غير مستخدم"),
|
||||
("⚠ Missing", "⚠ مفقود"),
|
||||
("▲ Modified", "▲ معدّل"),
|
||||
("(Text Color)", "(لون النص)"),
|
||||
("{count} glyphs — click to insert at the text cursor", "عدد المحارف: {count} — انقر للإدراج عند مؤشر النص"),
|
||||
("{pages} Pages in {spreads} Spreads", "عدد الصفحات: {pages}، المجموعات: {spreads}"),
|
||||
("Text Frame", "إطار نص"),
|
||||
("Text Style", "نمط النص"),
|
||||
(" (auto)", " (تلقائي)"),
|
||||
("Absolute Numbering (instead of Section Numbering)", "ترقيم مطلق بدلًا من ترقيم الأقسام"),
|
||||
("Add and remove pages as the primary text frame's story grows and shrinks", "إضافة الصفحات وحذفها مع زيادة نص الإطار الرئيسي أو نقصانه"),
|
||||
("Added Text (highlighted)", "النص المضاف (مميز)"),
|
||||
("Adjust Layout (objects follow the new page size)", "ضبط التخطيط وفق حجم الصفحة الجديد"),
|
||||
("Auto-Fit", "ملاءمة تلقائية"),
|
||||
("Case sensitive", "مراعاة حالة الأحرف"),
|
||||
("Custom Tracking/Kerning", "تباعد أحرف وأزواج مخصص"),
|
||||
("Dimensions Include Stroke Weight", "تضمين سماكة الحد في الأبعاد"),
|
||||
("Enable Autocorrect", "تمكين التصحيح التلقائي"),
|
||||
("Enable Dynamic Spelling (underline misspelled words)", "تمكين التدقيق الإملائي التلقائي (تسطير الأخطاء)"),
|
||||
("Grids in Back", "الشبكات في الخلف"),
|
||||
("H&J Violations", "مخالفات الواصلة والضبط"),
|
||||
("Include Bleed", "تضمين النزف"),
|
||||
("Include Stroke Weight", "تضمين سماكة الحد"),
|
||||
("Keep Violations", "مخالفات خيارات إبقاء النص"),
|
||||
("Overprint [Black] Swatch at 100%", "طباعة حامل الأسود بنسبة 100% فوقيًا"),
|
||||
("Printer's Marks", "علامات الطباعة"),
|
||||
("Remove Styles and Formatting from Text and Tables", "إزالة الأنماط والتنسيق من النص والجداول"),
|
||||
("Ruby", "روبي"),
|
||||
("Show Note Anchors in Layout View", "إظهار مراسي الملاحظات في عرض التخطيط"),
|
||||
("Spreads", "صفحات متقابلة"),
|
||||
("Substituted Fonts", "الخطوط المستبدلة"),
|
||||
("Transformations are Totals", "عرض قيم التحويل الإجمالية"),
|
||||
("Use Black Point Compensation", "استخدام تعويض النقطة السوداء"),
|
||||
("Use Typographer's Quotes", "استخدام علامات الاقتباس الطباعية"),
|
||||
("Whole word", "كلمة كاملة"),
|
||||
(" Close ", " إغلاق "),
|
||||
("(Top Level)", "(المستوى الأعلى)"),
|
||||
("(import)", "(استيراد)"),
|
||||
("Accept All", "قبول الكل"),
|
||||
("Add Document…", "إضافة مستند…"),
|
||||
("Add to Previous Spread", "إضافة إلى الصفحات المتقابلة السابقة"),
|
||||
("Align From:", "المحاذاة من:"),
|
||||
("Align to baseline grid", "محاذاة إلى شبكة خطوط الأساس"),
|
||||
("All Spots to Process", "تحويل كل الألوان الموضعية إلى ألوان معالجة"),
|
||||
("Allow Spread to Shuffle", "السماح بإعادة ترتيب الصفحات المتقابلة"),
|
||||
("Alternating Row Fills", "تعبئة الصفوف بالتناوب"),
|
||||
("Apply Gradient", "تطبيق تدرج"),
|
||||
("Apply None (/)", "تطبيق بلا لون (/)"),
|
||||
("Apply Parent", "تطبيق الصفحة الأصلية"),
|
||||
("Apply to All Spreads", "تطبيق على كل الصفحات المتقابلة"),
|
||||
("Apply to Stroke", "تطبيق على الحد"),
|
||||
("Art", "حدود الرسم"),
|
||||
("Baseline Grid", "شبكة خطوط الأساس"),
|
||||
("Bleed and Slug", "النزف ومنطقة المعلومات"),
|
||||
("Body Rows", "صفوف المتن"),
|
||||
("Break Link to Style", "فك الارتباط بالنمط"),
|
||||
("Bullets and Numbering", "التعداد النقطي والرقمي"),
|
||||
("Business Card", "بطاقة عمل"),
|
||||
("Buttons act in interactive PDF export.", "تعمل الأزرار عند التصدير إلى PDF تفاعلي."),
|
||||
("Change to:", "التغيير إلى:"),
|
||||
("Character Settings", "إعدادات الأحرف"),
|
||||
("Characters", "أحرف"),
|
||||
("Checked by default", "محدد افتراضيًا"),
|
||||
("Choices", "الخيارات"),
|
||||
("Choose Image…", "اختيار صورة…"),
|
||||
("Choose a link.", "اختر رابطًا."),
|
||||
("Content Fitting", "ملاءمة المحتوى"),
|
||||
("Convert Shape", "تحويل الشكل"),
|
||||
("Copies:", "عدد النسخ:"),
|
||||
("Count", "عدّ"),
|
||||
("Create", "إنشاء"),
|
||||
("Create Alternate Layout", "إنشاء تخطيط بديل"),
|
||||
("Create Table…", "إنشاء جدول…"),
|
||||
("Crop", "قص"),
|
||||
("Crop Amount", "مقدار القص"),
|
||||
("Crop to:", "القص إلى:"),
|
||||
("Cross-Reference Format", "تنسيق المرجع المتقاطع"),
|
||||
("Cursor Key:", "مفتاح المؤشر:"),
|
||||
("Default Fill and Stroke (D)", "التعبئة والحد الافتراضيان (D)"),
|
||||
("Default View:", "العرض الافتراضي:"),
|
||||
("Delete Column", "حذف العمود"),
|
||||
("Delete Condition", "حذف الشرط"),
|
||||
("Delete Row", "حذف الصف"),
|
||||
("Delete Swatch", "حذف حامل اللون"),
|
||||
("Delete Unused Layers", "حذف الطبقات غير المستخدمة"),
|
||||
("Delete Workspace", "حذف مساحة العمل"),
|
||||
("Document Grid", "شبكة المستند"),
|
||||
("Document Recovery Data", "بيانات استرداد المستند"),
|
||||
("Duplicate Spread", "تكرار الصفحات المتقابلة"),
|
||||
("Email", "بريد إلكتروني"),
|
||||
("Embed", "تضمين"),
|
||||
("Fast", "سريع"),
|
||||
("Fill (X)", "تعبئة (X)"),
|
||||
("Fill with Placeholder Text", "ملء بنص مؤقت"),
|
||||
("Find All", "بحث عن الكل"),
|
||||
("Find what:", "البحث عن:"),
|
||||
("Fit frame height to text", "ملاءمة ارتفاع الإطار للنص"),
|
||||
("Fitting:", "الملاءمة:"),
|
||||
("Flip Horizontal", "قلب أفقي"),
|
||||
("Flip Vertical", "قلب عمودي"),
|
||||
("Font Size:", "حجم الخط:"),
|
||||
("Form Field", "حقل نموذج"),
|
||||
("Format:", "التنسيق:"),
|
||||
("Height:", "الارتفاع:"),
|
||||
("Hide Bar", "إخفاء الشريط"),
|
||||
("High Quality", "جودة عالية"),
|
||||
("Highlight", "تمييز"),
|
||||
("Horizontal Gridline Every:", "تباعد خطوط الشبكة الأفقية:"),
|
||||
("Horizontal Margins:", "الهوامش الأفقية:"),
|
||||
("Import XML…", "استيراد XML…"),
|
||||
("Increment Every:", "مقدار الزيادة:"),
|
||||
("Ink Manager", "مدير الأحبار"),
|
||||
("Insert Column", "إدراج عمود"),
|
||||
("Insert Page After", "إدراج صفحة بعدها"),
|
||||
("Insert Row", "إدراج صف"),
|
||||
("Inset spacing", "التباعد الداخلي"),
|
||||
("Intent:", "الغرض:"),
|
||||
("Invert", "عكس"),
|
||||
("Keyboard Increments", "زيادات لوحة المفاتيح"),
|
||||
("Kind:", "النوع:"),
|
||||
("Link To:", "الربط إلى:"),
|
||||
("Liquid guides", "أدلة التخطيط المرن"),
|
||||
("Load Profile…", "تحميل ملف تعريف…"),
|
||||
("Load Swatches…", "تحميل حوامل الألوان…"),
|
||||
("Load…", "تحميل…"),
|
||||
("Media", "وسائط"),
|
||||
("Merge into Active Layer", "دمج في الطبقة النشطة"),
|
||||
("Misspelled word → Correction (one per line):", "كلمة خاطئة ← تصحيح (واحد في كل سطر):"),
|
||||
("Mobile", "جهاز محمول"),
|
||||
("More ArtCraft apps", "المزيد من تطبيقات ArtCraft"),
|
||||
("Move Selection Here", "نقل التحديد إلى هنا"),
|
||||
("Move to Color Group", "نقل إلى مجموعة ألوان"),
|
||||
("Move to Group", "نقل إلى مجموعة"),
|
||||
("Multiline", "متعدد الأسطر"),
|
||||
("Multiple Objects", "كائنات متعددة"),
|
||||
("Name:", "الاسم:"),
|
||||
("New Bookmark for This Page", "إشارة مرجعية جديدة لهذه الصفحة"),
|
||||
("New Book…", "كتاب جديد…"),
|
||||
("New Color Group", "مجموعة ألوان جديدة"),
|
||||
("New Color Group with Swatch", "مجموعة ألوان جديدة من الحامل"),
|
||||
("New Library…", "مكتبة جديدة…"),
|
||||
("New Workspace…", "مساحة عمل جديدة…"),
|
||||
("No articles: exports follow page order.", "لا توجد مقالات؛ يتبع التصدير ترتيب الصفحات."),
|
||||
("No book open.", "لا يوجد كتاب مفتوح."),
|
||||
("No bookmarks. They become the PDF outline.", "لا توجد إشارات مرجعية. تظهر في مخطط PDF."),
|
||||
("No changes.", "لا توجد تغييرات."),
|
||||
("No conditions. Create one, then select text and click it to apply.", "لا توجد شروط. أنشئ شرطًا ثم حدد النص وانقر عليه لتطبيقه."),
|
||||
("No document.", "لا يوجد مستند."),
|
||||
("No hyperlinks. Select text or a frame, type a URL and click New.", "لا توجد روابط. حدد نصًا أو إطارًا وأدخل عنوان URL ثم انقر على جديد."),
|
||||
("No library open.", "لا توجد مكتبة مفتوحة."),
|
||||
("No notes in this document.", "لا توجد ملاحظات في هذا المستند."),
|
||||
("No placed graphics.", "لا توجد رسومات مدرجة."),
|
||||
("No scripts. Add one below.", "لا توجد نصوص برمجية. أضف واحدًا أدناه."),
|
||||
("No spot inks", "لا توجد أحبار موضعية"),
|
||||
("No text anchors in this document.", "لا توجد مراسي نصية في هذا المستند."),
|
||||
("Number of Pages:", "عدد الصفحات:"),
|
||||
("Number of Sides:", "عدد الأضلاع:"),
|
||||
("Number of columns", "عدد الأعمدة"),
|
||||
("OK changes all: text and paragraph/character styles.", "تطبّق الموافقة التغييرات على النص وأنماط الفقرات والأحرف."),
|
||||
("OVERSET", "نص فائض"),
|
||||
("On Release", "عند الإفلات"),
|
||||
("On Screen:", "على الشاشة:"),
|
||||
("Open source. No telemetry.", "مفتوح المصدر. بلا تتبع للاستخدام."),
|
||||
("Options for Black on RGB and Grayscale Devices", "خيارات الأسود لأجهزة RGB والتدرج الرمادي"),
|
||||
("Orientation:", "الاتجاه:"),
|
||||
("Page Numbering", "ترقيم الصفحات"),
|
||||
("Page · PPI", "صفحة · PPI"),
|
||||
("Pages:", "الصفحات:"),
|
||||
("Part of the ArtCraft suite of open creative tools.", "جزء من مجموعة ArtCraft للأدوات الإبداعية المفتوحة."),
|
||||
("Pasteboard Options", "خيارات مساحة اللصق"),
|
||||
("Path", "مسار"),
|
||||
("Place the insertion point in a table, or create one.", "ضع نقطة الإدراج داخل جدول أو أنشئ جدولًا."),
|
||||
("Plain Text", "نص عادي"),
|
||||
("Plays in EPUB export; print and PDF show the poster.", "يعمل في تصدير EPUB؛ وتعرض الطباعة وPDF صورة الغلاف."),
|
||||
("Poster", "صورة الغلاف"),
|
||||
("Printer:", "الطابعة:"),
|
||||
("Printing / Exporting:", "الطباعة / التصدير:"),
|
||||
("Properties Panel", "لوحة الخصائص"),
|
||||
("Recently Used", "المستخدمة مؤخرًا"),
|
||||
("Reject All", "رفض الكل"),
|
||||
("Relative To:", "بالنسبة إلى:"),
|
||||
("Relink to Folder…", "إعادة الربط بمجلد…"),
|
||||
("Relink…", "إعادة الربط…"),
|
||||
("Remove Conditions from Selection", "إزالة الشروط عن التحديد"),
|
||||
("Repeat Header Rows", "تكرار صفوف الرأس"),
|
||||
("Replace With", "استبدال بـ"),
|
||||
("Required", "مطلوب"),
|
||||
("Reset All to Defaults", "إعادة تعيين الكل إلى الافتراضي"),
|
||||
("Reverse", "عكس"),
|
||||
("Right-click: stroke, groups", "نقرة يمنى: الحد والمجموعات"),
|
||||
("Rotate 90° Clockwise", "تدوير 90° مع عقارب الساعة"),
|
||||
("Ruler Units", "وحدات المسطرة"),
|
||||
("Save Swatches for Exchange…", "حفظ الحوامل للتبادل…"),
|
||||
("Save recovery data every:", "حفظ بيانات الاسترداد كل:"),
|
||||
("Saves which bars show and where the panels are.", "يحفظ الأشرطة الظاهرة ومواضع اللوحات."),
|
||||
("Search:", "البحث:"),
|
||||
(
|
||||
"Select a placed video or sound (File › Place a .mp4, .mov, .mp3, .wav …).",
|
||||
"حدد فيديو أو صوتًا مدرجًا (ملف › إدراج ملف .mp4 أو .mov أو .mp3 أو .wav …).",
|
||||
),
|
||||
("Select an object to color its fill or stroke.", "حدد كائنًا لتلوين تعبئته أو حده."),
|
||||
("Select an object to give its fill a gradient.", "حدد كائنًا لإضافة تدرج إلى تعبئته."),
|
||||
("Select an object to make it a button.", "حدد كائنًا لتحويله إلى زر."),
|
||||
("Select an object.", "حدد كائنًا."),
|
||||
("Select text or a text frame.", "حدد نصًا أو إطار نص."),
|
||||
("Select two or more objects (or a group) to make a multi-state object.", "حدد كائنين أو أكثر (أو مجموعة) لإنشاء كائن متعدد الحالات."),
|
||||
("Show Tag Markers", "إظهار علامات الوسوم"),
|
||||
("Single-line", "سطر واحد"),
|
||||
("Smart Text Reflow", "إعادة تدفق النص الذكية"),
|
||||
("Speed", "السرعة"),
|
||||
("Star Inset:", "تقعر النجمة:"),
|
||||
("Start Page #:", "رقم صفحة البداية:"),
|
||||
("Start:", "البداية:"),
|
||||
("Status", "الحالة"),
|
||||
("Stroke (X)", "حد (X)"),
|
||||
("Style Mapping", "مطابقة الأنماط"),
|
||||
("Style Name Conflicts", "تعارض أسماء الأنماط"),
|
||||
("Stylistic Sets", "المجموعات الأسلوبية"),
|
||||
("Subdivisions:", "التقسيمات الفرعية:"),
|
||||
("Swap Fill and Stroke (Shift+X)", "تبديل التعبئة والحد (Shift+X)"),
|
||||
("Synchronize", "مزامنة"),
|
||||
("System default", "افتراضي النظام"),
|
||||
("Table Dimensions", "أبعاد الجدول"),
|
||||
("Text Display Options", "خيارات عرض النص"),
|
||||
("Text Message", "رسالة نصية"),
|
||||
("The fill isn't a gradient.", "التعبئة ليست تدرجًا."),
|
||||
("The library is empty. Select objects and Add Selection.", "المكتبة فارغة. حدد كائنات ثم أضف التحديد."),
|
||||
("This PDF has no layers.", "ملف PDF هذا لا يحتوي على طبقات."),
|
||||
("Track Changes in All Stories", "تتبع التغييرات في جميع النصوص"),
|
||||
("Transitions play in interactive PDF (full-screen mode).", "تعمل الانتقالات في PDF التفاعلي بوضع ملء الشاشة."),
|
||||
("Trim", "حدود التشذيب"),
|
||||
("Type Options", "خيارات النص"),
|
||||
("Typical", "نموذجي"),
|
||||
("UI Size:", "حجم الواجهة:"),
|
||||
("Ungroup Color Group", "فك مجموعة الألوان"),
|
||||
("Unmerge", "إلغاء الدمج"),
|
||||
("Update Numbering", "تحديث الترقيم"),
|
||||
("Use Global Light", "استخدام الإضاءة العامة"),
|
||||
("User Dictionary (this document)", "قاموس المستخدم (هذا المستند)"),
|
||||
("Variable Font", "خط متغير"),
|
||||
("Vertical Gridline Every:", "تباعد خطوط الشبكة العمودية:"),
|
||||
("Vertical Margins:", "الهوامش العمودية:"),
|
||||
("Vertical justification", "المحاذاة العمودية"),
|
||||
("View Threshold:", "حد العرض:"),
|
||||
("Web", "ويب"),
|
||||
("Web Hyperlink", "رابط ويب"),
|
||||
("When Scaling", "عند التحجيم"),
|
||||
("Words, one per line:", "الكلمات، واحدة في كل سطر:"),
|
||||
("[Basic] (working) ▾", "[أساسي] (قيد العمل) ▾"),
|
||||
("[Black] Overprint", "طباعة [الأسود] فوقيًا"),
|
||||
("[No Group]", "[بلا مجموعة]"),
|
||||
("[None] — choose a colour on the ramp.", "[بلا] — اختر لونًا على شريط التدرج."),
|
||||
("⌥-click clears overrides", "النقر مع ⌥ يمسح التجاوزات"),
|
||||
("⚠ out of date", "⚠ غير محدّث"),
|
||||
("Interface", "الواجهة"),
|
||||
("Advanced Type", "إعدادات النص المتقدمة"),
|
||||
("Composition", "تنضيد النص"),
|
||||
("Units & Increments", "الوحدات والزيادات"),
|
||||
("Grids", "الشبكات"),
|
||||
("Guides & Pasteboard", "الأدلة ولوحة اللصق"),
|
||||
("Dictionary", "القاموس"),
|
||||
("Spelling", "التدقيق الإملائي"),
|
||||
("Autocorrect", "التصحيح التلقائي"),
|
||||
("Track Changes", "تعقب التغييرات"),
|
||||
("Story Editor Display", "عرض محرر النص"),
|
||||
("Display Performance", "أداء العرض"),
|
||||
("Appearance of Black", "مظهر الأسود"),
|
||||
("File Handling", "معالجة الملفات"),
|
||||
("Formatting affects container (J)", "تطبيق التنسيق على الحاوية (J)"),
|
||||
("Formatting affects text (J)", "تطبيق التنسيق على النص (J)"),
|
||||
("Apply Color", "تطبيق اللون"),
|
||||
("Apply None", "إزالة اللون"),
|
||||
("Height Only", "الارتفاع فقط"),
|
||||
("Width Only", "العرض فقط"),
|
||||
("Height and Width", "الارتفاع والعرض"),
|
||||
("Height only", "الارتفاع فقط"),
|
||||
("Width only", "العرض فقط"),
|
||||
("Height and width", "الارتفاع والعرض"),
|
||||
("Version", "الإصدار"),
|
||||
("{count} characters don't fit", "عدد الأحرف الزائدة: {count}"),
|
||||
("document", "المستند"),
|
||||
("story", "النص"),
|
||||
("selection", "التحديد"),
|
||||
("top", "أعلى"),
|
||||
("center", "وسط"),
|
||||
("bottom", "أسفل"),
|
||||
("justify", "ضبط"),
|
||||
("text", "نص"),
|
||||
("graphic", "رسم"),
|
||||
("unassigned", "غير معين"),
|
||||
("Perceptual", "إدراكي"),
|
||||
("Relative Colorimetric", "قياس لوني نسبي"),
|
||||
("Saturation", "التشبع"),
|
||||
("Absolute Colorimetric", "قياس لوني مطلق"),
|
||||
("No conflicts", "لا توجد تعارضات"),
|
||||
("Page (1–{count}):", "الصفحة (1–{count}):"),
|
||||
("Fonts in Document: {count} Missing: {missing}", "الخطوط في المستند: {count} المفقودة: {missing}"),
|
||||
];
|
||||
|
||||
@@ -1902,7 +1902,11 @@ pub fn palette(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
let mut run: Option<(String, Value)> = None;
|
||||
egui::Modal::new(egui::Id::new("palette")).show(ctx, |ui| {
|
||||
ui.set_width(480.0);
|
||||
let r = ui.add(egui::TextEdit::singleline(&mut q).hint_text("Search styles and commands…").desired_width(f32::INFINITY));
|
||||
let r = ui.add(
|
||||
egui::TextEdit::singleline(&mut q)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Search styles and commands…")))
|
||||
.desired_width(f32::INFINITY),
|
||||
);
|
||||
r.request_focus();
|
||||
let items = quick_apply_items(&app.session, &q);
|
||||
egui::ScrollArea::vertical().max_height(340.0).show(ui, |ui| {
|
||||
|
||||
@@ -28,7 +28,9 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let (row, _) = ui.allocate_exact_size(vec2(ui.available_width(), 22.0), Sense::hover());
|
||||
// Visibility (eye).
|
||||
let eye = egui::Rect::from_min_size(row.min + vec2(2.0, 3.0), vec2(16.0, 16.0));
|
||||
let er = ui.interact(eye, ui.id().with(("cond_eye", &c.name)), Sense::click()).on_hover_text("Show / hide text with this condition");
|
||||
let er = ui.interact(eye, ui.id().with(("cond_eye", &c.name)), Sense::click()).on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Show / hide text with this condition"));
|
||||
});
|
||||
if c.visible {
|
||||
crate::icons::paint(ui.painter(), eye, "eye", t.text_dim);
|
||||
}
|
||||
@@ -73,7 +75,11 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let id = egui::Id::new("new_condition_name");
|
||||
let mut name: String = ui.data(|d| d.get_temp(id)).unwrap_or_default();
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::TextEdit::singleline(&mut name).hint_text("New condition name").desired_width(150.0));
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(&mut name)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New condition name")))
|
||||
.desired_width(150.0),
|
||||
);
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New"))).clicked() && !name.trim().is_empty() {
|
||||
match app.run("condition.new", json!({"name": name.trim()})) {
|
||||
Ok(_) => name.clear(),
|
||||
|
||||
@@ -50,7 +50,11 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
});
|
||||
});
|
||||
ui.add(egui::TextEdit::singleline(&mut st.query).hint_text("Search: character or U+code").desired_width(f32::INFINITY));
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(&mut st.query)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Search: character or U+code")))
|
||||
.desired_width(f32::INFINITY),
|
||||
);
|
||||
let face = db.face(&st.family, &st.style);
|
||||
let q = st.query.trim().to_string();
|
||||
let code = q.strip_prefix("U+").or_else(|| q.strip_prefix("u+")).and_then(|h| u32::from_str_radix(h, 16).ok());
|
||||
@@ -129,6 +133,13 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
Err(e) => app.status(format!("Glyphs: {e}")),
|
||||
}
|
||||
}
|
||||
ui.label(egui::RichText::new(format!("{} glyphs — click to insert at the text cursor", chars.len())).size(10.5).color(t.text_dim));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(
|
||||
crate::i18n::tr(&app.ui.language, "{count} glyphs — click to insert at the text cursor").replace("{count}", &chars.len().to_string()),
|
||||
)
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
);
|
||||
ui.data_mut(|d| d.insert_temp(id, st));
|
||||
}
|
||||
|
||||
@@ -25,7 +25,13 @@ pub fn hyperlinks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let has_target = app.session.active().is_some_and(|d| d.selection.text.is_some_and(|t| !t.is_caret()) || !d.selection.items.is_empty());
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::TextEdit::singleline(&mut url).desired_width(170.0));
|
||||
if ui.add_enabled(has_target, egui::Button::new("New")).on_hover_text("Hyperlink from the selected text or frames").clicked() {
|
||||
if ui
|
||||
.add_enabled(has_target, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New"))))
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Hyperlink from the selected text or frames"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let p = if let Some(m) = url.strip_prefix("mailto:") { json!({"email": m}) } else { json!({"url": url}) };
|
||||
if let Err(e) = app.run("hyperlink.create", p) {
|
||||
app.status(format!("Hyperlinks: {e}"));
|
||||
@@ -36,12 +42,15 @@ pub fn hyperlinks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.separator();
|
||||
let list = app.session.execute("hyperlink.list", &json!({})).ok().and_then(|v| v.as_array().cloned()).unwrap_or_default();
|
||||
if list.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No hyperlinks. Select text or a frame, type a URL and click New."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No hyperlinks. Select text or a frame, type a URL and click New."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
}
|
||||
for h in list {
|
||||
let hid = h["id"].clone();
|
||||
@@ -51,7 +60,7 @@ pub fn hyperlinks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let _ = app.run("hyperlink.goToSource", json!({"id": hid}));
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Delete").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))).clicked() {
|
||||
let _ = app.run("hyperlink.delete", json!({"id": hid}));
|
||||
}
|
||||
});
|
||||
@@ -68,10 +77,13 @@ pub fn bookmarks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.separator();
|
||||
let list = app.session.execute("bookmark.list", &json!({})).ok().and_then(|v| v.as_array().cloned()).unwrap_or_default();
|
||||
if list.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No bookmarks. They become the PDF outline.")).size(11.0).color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No bookmarks. They become the PDF outline.")).size(11.0).color(t.text_dim),
|
||||
),
|
||||
);
|
||||
}
|
||||
for (i, b) in list.iter().enumerate() {
|
||||
let page = b["page"].as_u64().unwrap_or(0) as usize;
|
||||
@@ -81,7 +93,7 @@ pub fn bookmarks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
crate::canvas::go_to_page(app, page);
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Delete").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))).clicked() {
|
||||
let _ = app.run("bookmark.delete", json!({"index": i}));
|
||||
}
|
||||
});
|
||||
@@ -93,31 +105,51 @@ pub fn bookmarks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
pub fn articles(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let has_sel = app.session.active().is_some_and(|d| !d.selection.items.is_empty());
|
||||
if ui.add_enabled(has_sel, egui::Button::new("New Article from Selection")).clicked() {
|
||||
if ui.add_enabled(has_sel, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New Article from Selection")))).clicked() {
|
||||
let _ = app.run("article.new", json!({}));
|
||||
}
|
||||
ui.separator();
|
||||
let list = app.session.execute("article.list", &json!({})).ok().and_then(|v| v.as_array().cloned()).unwrap_or_default();
|
||||
if list.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No articles: exports follow page order.")).size(11.0).color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No articles: exports follow page order.")).size(11.0).color(t.text_dim),
|
||||
),
|
||||
);
|
||||
}
|
||||
for a in list {
|
||||
let name = a["name"].as_str().unwrap_or("").to_string();
|
||||
let mut export = a["export"].as_bool().unwrap_or(true);
|
||||
ui.horizontal(|ui| {
|
||||
if ui.checkbox(&mut export, "").on_hover_text("Include when exporting").changed() {
|
||||
if ui
|
||||
.checkbox(&mut export, "")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Include when exporting"));
|
||||
})
|
||||
.changed()
|
||||
{
|
||||
let _ = app.run("article.options", json!({"name": name, "export": export}));
|
||||
}
|
||||
ui.label(egui::RichText::new(&name).strong());
|
||||
ui.label(egui::RichText::new(format!("{} objects", a["items"].as_array().map_or(0, Vec::len))).size(10.5).color(t.text_dim));
|
||||
crate::rtl::label(ui, egui::RichText::new(&name).strong());
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(format!("{} {}", a["items"].as_array().map_or(0, Vec::len), crate::i18n::tr(&app.ui.language, "objects")))
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
);
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Delete").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))).clicked() {
|
||||
let _ = app.run("article.delete", json!({"name": name}));
|
||||
}
|
||||
if ui.add_enabled(has_sel, egui::Button::new("Add").small()).on_hover_text("Add the selection").clicked() {
|
||||
if ui
|
||||
.add_enabled(has_sel, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Add"))).small())
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Add the selection"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("article.add", json!({"name": name}));
|
||||
}
|
||||
});
|
||||
@@ -136,7 +168,11 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let id = egui::Id::new("new_tag_name");
|
||||
let mut name: String = ui.data(|d| d.get_temp(id)).unwrap_or_default();
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::TextEdit::singleline(&mut name).hint_text("New tag").desired_width(140.0));
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(&mut name)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New tag")))
|
||||
.desired_width(140.0),
|
||||
);
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New"))).clicked() && !name.trim().is_empty() {
|
||||
match app.run("xml.newTag", json!({"name": name.trim()})) {
|
||||
Ok(_) => name.clear(),
|
||||
@@ -153,17 +189,23 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if c.len() == 3 {
|
||||
ui.painter().rect_filled(r, 2.0, egui::Color32::from_rgb(c[0], c[1], c[2]));
|
||||
}
|
||||
if ui.add_enabled(has_sel || text_sel, egui::Button::new(&n).frame(false)).on_hover_text("Tag the selection").clicked() {
|
||||
if ui
|
||||
.add_enabled(has_sel || text_sel, egui::Button::new(&n).frame(false))
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Tag the selection"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = if text_sel { app.run("xml.tagText", json!({"tag": n})) } else { app.run("xml.tag", json!({"tag": n})) };
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Delete").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))).clicked() {
|
||||
let _ = app.run("xml.deleteTag", json!({"name": n}));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (has_sel || text_sel) && ui.small_button("Untag Selection").clicked() {
|
||||
if (has_sel || text_sel) && ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Untag Selection"))).clicked() {
|
||||
let _ = if text_sel { app.run("xml.tagText", json!({"tag": null})) } else { app.run("xml.tag", json!({"tag": null})) };
|
||||
}
|
||||
let mut markers = app.ui.tag_markers;
|
||||
@@ -171,9 +213,9 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let _ = app.run("view.tagMarkers", json!({"on": markers}));
|
||||
}
|
||||
ui.separator();
|
||||
ui.label(egui::RichText::new("Structure").strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Structure")).strong());
|
||||
let st = app.session.execute("xml.structure", &json!({})).unwrap_or_default();
|
||||
ui.label(egui::RichText::new(st["root"].as_str().unwrap_or("Root")).size(11.0).color(t.text_dim));
|
||||
crate::rtl::label(ui, egui::RichText::new(st["root"].as_str().unwrap_or("Root")).size(11.0).color(t.text_dim));
|
||||
for el in st["elements"].as_array().cloned().unwrap_or_default() {
|
||||
let text = el["text"].as_str().unwrap_or("").chars().take(40).collect::<String>();
|
||||
let label = format!(" <{}> {}", el["tag"].as_str().unwrap_or(""), text);
|
||||
@@ -185,7 +227,7 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let vid = egui::Id::new("dtd_problems");
|
||||
let mut problems: Option<Vec<String>> = ui.data(|d| d.get_temp(vid));
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Load DTD…").clicked()
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Load DTD…"))).clicked()
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|f| f("dtd"))
|
||||
{
|
||||
match app.run("xml.loadDtd", json!({"path": path})) {
|
||||
@@ -194,7 +236,7 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
}
|
||||
let has_dtd = info["dtd"].as_bool().unwrap_or(false);
|
||||
if ui.add_enabled(has_dtd, egui::Button::new("Validate")).clicked()
|
||||
if ui.add_enabled(has_dtd, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Validate")))).clicked()
|
||||
&& let Ok(v) = app.session.execute("xml.validate", &json!({}))
|
||||
{
|
||||
problems = Some(
|
||||
@@ -206,18 +248,18 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
if has_dtd && ui.small_button("Delete DTD").clicked() {
|
||||
if has_dtd && ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete DTD"))).clicked() {
|
||||
let _ = app.run("xml.deleteDtd", json!({}));
|
||||
problems = None;
|
||||
}
|
||||
});
|
||||
match &problems {
|
||||
Some(list) if list.is_empty() => {
|
||||
ui.label(egui::RichText::new("The structure is valid.").size(11.0).color(t.text_dim));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "The structure is valid.")).size(11.0).color(t.text_dim));
|
||||
}
|
||||
Some(list) => {
|
||||
for p in list {
|
||||
ui.label(egui::RichText::new(format!("⚠ {p}")).size(11.0));
|
||||
crate::rtl::label(ui, egui::RichText::new(format!("⚠ {p}")).size(11.0));
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
@@ -251,13 +293,21 @@ pub fn states(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let info = app.session.execute("states.list", &json!({})).ok();
|
||||
let list = info.as_ref().and_then(|i| i["states"].as_array().cloned()).unwrap_or_default();
|
||||
if list.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Select two or more objects (or a group) to make a multi-state object."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
));
|
||||
if ui.add_enabled(n > 0, egui::Button::new("Convert Selection to Multi-State Object")).clicked()
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Select two or more objects (or a group) to make a multi-state object."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
if ui
|
||||
.add_enabled(
|
||||
n > 0,
|
||||
egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Convert Selection to Multi-State Object"))),
|
||||
)
|
||||
.clicked()
|
||||
&& let Err(e) = app.run("states.create", json!({}))
|
||||
{
|
||||
app.status(format!("Object States: {e}"));
|
||||
@@ -271,7 +321,7 @@ pub fn states(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
if ui.small_button("Release to Objects").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Release to Objects"))).clicked() {
|
||||
let _ = app.run("states.release", json!({}));
|
||||
}
|
||||
}
|
||||
@@ -280,10 +330,13 @@ pub fn states(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let Some(id) = app.session.active().and_then(|d| d.selection.items.first().copied()) else {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Select an object to make it a button.")).size(11.0).color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Select an object to make it a button.")).size(11.0).color(t.text_dim),
|
||||
),
|
||||
);
|
||||
return;
|
||||
};
|
||||
let cur = app.session.active().and_then(|d| d.doc.item(id)).and_then(|it| it.button.clone());
|
||||
@@ -309,13 +362,15 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let mut pick = None;
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "On Release"));
|
||||
egui::ComboBox::from_id_salt("button_action").selected_text(labels.iter().find(|l| l.0 == kind).map_or("", |l| l.1)).show_ui(ui, |ui| {
|
||||
for (k, l) in labels {
|
||||
if ui.selectable_label(k == kind, l).clicked() {
|
||||
pick = Some(k);
|
||||
egui::ComboBox::from_id_salt("button_action")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, labels.iter().find(|l| l.0 == kind).map_or("", |l| l.1))))
|
||||
.show_ui(ui, |ui| {
|
||||
for (k, l) in labels {
|
||||
if ui.selectable_label(k == kind, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
pick = Some(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
let mut params = None;
|
||||
if let Some(k) = pick {
|
||||
@@ -345,10 +400,13 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
app.status(format!("Buttons: {e}"));
|
||||
}
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Buttons act in interactive PDF export.")).size(10.5).color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Buttons act in interactive PDF export.")).size(10.5).color(t.text_dim),
|
||||
),
|
||||
);
|
||||
// Form field.
|
||||
ui.separator();
|
||||
let ff = app.session.active().and_then(|d| d.doc.item(id)).and_then(|it| it.form_field.clone());
|
||||
@@ -364,16 +422,18 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let cur = ff.as_ref().map(|f| f.kind);
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Form Field"));
|
||||
egui::ComboBox::from_id_salt("form_kind").selected_text(kinds.iter().find(|k| k.0 == cur).map_or("", |k| k.1)).show_ui(ui, |ui| {
|
||||
for (k, l) in kinds {
|
||||
if ui.selectable_label(k == cur, l).clicked() {
|
||||
let _ = match k {
|
||||
Some(k) => app.run("form.set", json!({"kind": k})),
|
||||
None => app.run("form.clear", json!({})),
|
||||
};
|
||||
egui::ComboBox::from_id_salt("form_kind")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, kinds.iter().find(|k| k.0 == cur).map_or("", |k| k.1))))
|
||||
.show_ui(ui, |ui| {
|
||||
for (k, l) in kinds {
|
||||
if ui.selectable_label(k == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
let _ = match k {
|
||||
Some(k) => app.run("form.set", json!({"kind": k})),
|
||||
None => app.run("form.clear", json!({})),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
if let Some(f) = ff {
|
||||
let key = egui::Id::new(("form_edit", id.0));
|
||||
@@ -398,7 +458,12 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if matches!(f.kind, K::ComboBox | K::ListBox) {
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Choices"));
|
||||
commit |= ui.text_edit_singleline(&mut opts).on_hover_text("Separated by commas").lost_focus();
|
||||
commit |= ui
|
||||
.text_edit_singleline(&mut opts)
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Separated by commas"));
|
||||
})
|
||||
.lost_focus();
|
||||
});
|
||||
}
|
||||
let mut req = f.required;
|
||||
@@ -433,15 +498,29 @@ pub fn liquid(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let Some((si, pi)) = d.page_loc(page) else { return };
|
||||
let pg = d.spreads[si].pages[pi].clone();
|
||||
use designcraft_doc::LiquidRule as L;
|
||||
ui.label(egui::RichText::new(format!("Page {}", d.page_name(page))).strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(format!("{} {}", crate::i18n::tr(&app.ui.language, "Page"), d.page_name(page))).strong());
|
||||
let mut rule = pg.liquid;
|
||||
egui::ComboBox::from_id_salt("liquid_rule").selected_text(format!("{rule:?}")).show_ui(ui, |ui| {
|
||||
for (r, label) in
|
||||
[(L::Off, "Off"), (L::Scale, "Scale"), (L::ReCenter, "Re-center"), (L::GuideBased, "Guide-based"), (L::ObjectBased, "Object-based")]
|
||||
{
|
||||
ui.selectable_value(&mut rule, r, label);
|
||||
}
|
||||
});
|
||||
egui::ComboBox::from_id_salt("liquid_rule")
|
||||
.selected_text(crate::rtl::widget(
|
||||
ui,
|
||||
crate::i18n::tr(
|
||||
&app.ui.language,
|
||||
match rule {
|
||||
L::Off => "Off",
|
||||
L::Scale => "Scale",
|
||||
L::ReCenter => "Re-center",
|
||||
L::GuideBased => "Guide-based",
|
||||
L::ObjectBased => "Object-based",
|
||||
},
|
||||
),
|
||||
))
|
||||
.show_ui(ui, |ui| {
|
||||
for (r, label) in
|
||||
[(L::Off, "Off"), (L::Scale, "Scale"), (L::ReCenter, "Re-center"), (L::GuideBased, "Guide-based"), (L::ObjectBased, "Object-based")]
|
||||
{
|
||||
ui.selectable_value(&mut rule, r, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label)));
|
||||
}
|
||||
});
|
||||
if rule != pg.liquid {
|
||||
let _ = app.run("liquid.pageRule", json!({"rule": rule, "pages": [page + 1]}));
|
||||
}
|
||||
@@ -456,7 +535,7 @@ pub fn liquid(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let labels = ["Resize width", "Resize height", "Pin top", "Pin bottom", "Pin left", "Pin right"];
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
for ((on, key), label) in v.iter_mut().zip(keys).zip(labels) {
|
||||
if ui.checkbox(on, label).changed() {
|
||||
if ui.checkbox(on, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).changed() {
|
||||
let _ = app.run("liquid.object", json!({key: *on}));
|
||||
}
|
||||
}
|
||||
@@ -495,18 +574,21 @@ pub fn liquid(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
pub fn media(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let Ok(m) = app.session.execute("media.get", &json!({})) else {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Select a placed video or sound (File › Place a .mp4, .mov, .mp3, .wav …)."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Select a placed video or sound (File › Place a .mp4, .mov, .mp3, .wav …)."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
return;
|
||||
};
|
||||
ui.label(egui::RichText::new(format!("{} — {}", m["kind"].as_str().unwrap_or(""), m["name"].as_str().unwrap_or(""))).strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(format!("{} — {}", m["kind"].as_str().unwrap_or(""), m["name"].as_str().unwrap_or(""))).strong());
|
||||
for (key, label) in [("playOnPageLoad", "Play on Page Load"), ("loop", "Loop"), ("controls", "Show Controls")] {
|
||||
let mut on = m[key].as_bool().unwrap_or(false);
|
||||
if ui.checkbox(&mut on, label).changed() {
|
||||
if ui.checkbox(&mut on, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).changed() {
|
||||
let _ = app.run("media.options", json!({key: on}));
|
||||
}
|
||||
}
|
||||
@@ -518,14 +600,19 @@ pub fn media(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
app.status(format!("Media: {e}"));
|
||||
}
|
||||
if !m["poster"].is_null() && ui.small_button("None").clicked() {
|
||||
if !m["poster"].is_null() && ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "None"))).clicked() {
|
||||
let _ = app.run("media.options", json!({"poster": null}));
|
||||
}
|
||||
});
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Plays in EPUB export; print and PDF show the poster.")).size(10.5).color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Plays in EPUB export; print and PDF show the poster."))
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Page Transitions panel: the current spread's transition for interactive PDF.
|
||||
@@ -536,14 +623,16 @@ pub fn transitions(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let Some((si, _)) = d.page_loc(page) else { return };
|
||||
let cur = d.spreads[si].pages.first().and_then(|p| p.transition);
|
||||
use designcraft_doc::TransitionKind as K;
|
||||
ui.label(egui::RichText::new(format!("Spread {}", si + 1)).strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(format!("{} {}", crate::i18n::tr(&app.ui.language, "Spread"), si + 1)).strong());
|
||||
let mut kind = cur.map(|c| c.kind);
|
||||
egui::ComboBox::from_id_salt("transition_kind").selected_text(kind.map_or("None", K::label)).show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut kind, None, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "None")));
|
||||
for k in K::ALL {
|
||||
ui.selectable_value(&mut kind, Some(k), k.label());
|
||||
}
|
||||
});
|
||||
egui::ComboBox::from_id_salt("transition_kind")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, kind.map_or("None", K::label))))
|
||||
.show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut kind, None, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "None")));
|
||||
for k in K::ALL {
|
||||
ui.selectable_value(&mut kind, Some(k), crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, k.label())));
|
||||
}
|
||||
});
|
||||
let mut duration = cur.map_or(1.0, |c| c.duration);
|
||||
let mut horizontal = cur.is_some_and(|c| c.horizontal);
|
||||
let mut changed = kind != cur.map(|c| c.kind);
|
||||
@@ -553,7 +642,12 @@ pub fn transitions(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
changed |= ui.add(egui::DragValue::new(&mut duration).range(0.1..=10.0).speed(0.1).suffix(" s")).changed();
|
||||
});
|
||||
if matches!(kind, Some(K::Blinds | K::Box | K::Split)) {
|
||||
changed |= ui.checkbox(&mut horizontal, if kind == Some(K::Box) { "Inward" } else { "Horizontal" }).changed();
|
||||
changed |= ui
|
||||
.checkbox(
|
||||
&mut horizontal,
|
||||
crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if kind == Some(K::Box) { "Inward" } else { "Horizontal" })),
|
||||
)
|
||||
.changed();
|
||||
}
|
||||
}
|
||||
let params = |all: bool| {
|
||||
@@ -570,12 +664,15 @@ pub fn transitions(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Apply to All Spreads"))).clicked() {
|
||||
let _ = app.run("page.transition", params(true));
|
||||
}
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Transitions play in interactive PDF (full-screen mode)."))
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Transitions play in interactive PDF (full-screen mode)."))
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Track Changes panel: tracking on/off and each change with Accept / Reject.
|
||||
@@ -598,18 +695,28 @@ pub fn track_changes(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let kind = c["kind"].as_str().unwrap_or("");
|
||||
let text: String = c["text"].as_str().unwrap_or("").chars().take(40).collect();
|
||||
ui.horizontal(|ui| {
|
||||
let label =
|
||||
egui::RichText::new(format!("{} “{}”", if kind == "inserted" { "Added" } else { "Deleted" }, text.replace('\n', "¶"))).size(11.0);
|
||||
let label = egui::RichText::new(format!(
|
||||
"{} “{}”",
|
||||
crate::i18n::tr(&app.ui.language, if kind == "inserted" { "Added" } else { "Deleted" }),
|
||||
text.replace('\n', "¶")
|
||||
))
|
||||
.size(11.0);
|
||||
let label = if kind == "deleted" { label.strikethrough() } else { label };
|
||||
if ui.selectable_label(false, label).on_hover_text("Show in the text").clicked() {
|
||||
if ui
|
||||
.selectable_label(false, label)
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Show in the text"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let end = c["end"].clone();
|
||||
let _ = app.run("text.select", json!({"story": story, "anchor": start, "focus": end}));
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Reject").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Reject"))).clicked() {
|
||||
let _ = app.run("changes.reject", json!({"story": story, "start": start}));
|
||||
}
|
||||
if ui.small_button("Accept").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Accept"))).clicked() {
|
||||
let _ = app.run("changes.accept", json!({"story": story, "start": start}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,7 +49,15 @@ fn c32(c: [u8; 3]) -> Color32 {
|
||||
}
|
||||
|
||||
/// Eye and lock cells (with column rules). Returns (eye clicked, lock clicked).
|
||||
fn eye_lock(ui: &mut Ui, row: Rect, visible: bool, locked: bool, dim: bool, key: impl std::hash::Hash + std::fmt::Debug + Copy) -> (bool, bool) {
|
||||
fn eye_lock(
|
||||
ui: &mut Ui,
|
||||
language: &str,
|
||||
row: Rect,
|
||||
visible: bool,
|
||||
locked: bool,
|
||||
dim: bool,
|
||||
key: impl std::hash::Hash + std::fmt::Debug + Copy,
|
||||
) -> (bool, bool) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let eye = Rect::from_min_size(row.min, vec2(COL_W, ROW_H));
|
||||
let lock = Rect::from_min_size(row.min + vec2(COL_W, 0.0), vec2(COL_W, ROW_H));
|
||||
@@ -63,13 +71,25 @@ fn eye_lock(ui: &mut Ui, row: Rect, visible: bool, locked: bool, dim: bool, key:
|
||||
if locked {
|
||||
icons::paint(ui.painter(), Rect::from_center_size(lock.center(), vec2(13.0, 13.0)), "lock", col);
|
||||
}
|
||||
let e = ui.interact(eye, ui.id().with(("eye", key)), Sense::click()).on_hover_text(if visible { "Hide" } else { "Show" });
|
||||
let l = ui.interact(lock, ui.id().with(("lock", key)), Sense::click()).on_hover_text(if locked { "Unlock" } else { "Lock" });
|
||||
let e = ui.interact(eye, ui.id().with(("eye", key)), Sense::click()).on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(language, if visible { "Hide" } else { "Show" }));
|
||||
});
|
||||
let l = ui.interact(lock, ui.id().with(("lock", key)), Sense::click()).on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(language, if locked { "Unlock" } else { "Lock" }));
|
||||
});
|
||||
(e.clicked(), l.clicked())
|
||||
}
|
||||
|
||||
/// The selection square at the right of a row: filled = selected; hollow on hover.
|
||||
fn selection_square(ui: &mut Ui, row: Rect, color: Color32, selected: bool, small: bool, key: impl std::hash::Hash + std::fmt::Debug) -> bool {
|
||||
fn selection_square(
|
||||
ui: &mut Ui,
|
||||
language: &str,
|
||||
row: Rect,
|
||||
color: Color32,
|
||||
selected: bool,
|
||||
small: bool,
|
||||
key: impl std::hash::Hash + std::fmt::Debug,
|
||||
) -> bool {
|
||||
let s = if small { 7.0 } else { 8.0 };
|
||||
let r = Rect::from_center_size(pos2(row.max.x - 12.0, row.center().y), vec2(s, s));
|
||||
let resp = ui.interact(r.expand(4.0), ui.id().with(("selsq", key)), Sense::click());
|
||||
@@ -78,7 +98,10 @@ fn selection_square(ui: &mut Ui, row: Rect, color: Color32, selected: bool, smal
|
||||
} else if resp.hovered() {
|
||||
ui.painter().rect_stroke(r, 0.0, Stroke::new(1.0, color), StrokeKind::Inside);
|
||||
}
|
||||
resp.on_hover_text("Select").clicked()
|
||||
resp.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(language, "Select"));
|
||||
})
|
||||
.clicked()
|
||||
}
|
||||
|
||||
pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
@@ -103,7 +126,7 @@ pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
} else if resp.hovered() {
|
||||
ui.painter().rect_filled(row, 0.0, t.hover);
|
||||
}
|
||||
let (eye, lock) = eye_lock(ui, row, l.visible, l.locked, false, ("layer", l.id.0));
|
||||
let (eye, lock) = eye_lock(ui, &app.ui.language, row, l.visible, l.locked, false, ("layer", l.id.0));
|
||||
// Disclosure triangle.
|
||||
let tri = Rect::from_min_size(row.min + vec2(2.0 * COL_W + 2.0, 0.0), vec2(14.0, ROW_H));
|
||||
let c = tri.center();
|
||||
@@ -127,7 +150,7 @@ pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
if l.id == active {
|
||||
icons::paint(ui.painter(), Rect::from_center_size(pos2(row.max.x - 32.0, row.center().y), vec2(13.0, 13.0)), "tool-pen", t.icon);
|
||||
}
|
||||
let sq = selection_square(ui, row, lc, sel_layers.contains(&l.id), false, ("layer", l.id.0));
|
||||
let sq = selection_square(ui, &app.ui.language, row, lc, sel_layers.contains(&l.id), false, ("layer", l.id.0));
|
||||
if eye {
|
||||
let _ = app.run("layer.set", json!({"id": l.id.0, "visible": !l.visible}));
|
||||
} else if lock {
|
||||
@@ -163,7 +186,7 @@ pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
("Show All Layers", json!({"id": l.id.0, "show": true})),
|
||||
("Unlock All Layers", json!({"id": l.id.0, "unlock": true})),
|
||||
] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("layer.others", params);
|
||||
ui.close();
|
||||
}
|
||||
@@ -182,7 +205,7 @@ pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
if resp.hovered() {
|
||||
ui.painter().rect_filled(row, 0.0, t.hover);
|
||||
}
|
||||
let (eye, lock) = eye_lock(ui, row, !it.hidden, it.locked, !l.visible, ("item", it.id.0));
|
||||
let (eye, lock) = eye_lock(ui, &app.ui.language, row, !it.hidden, it.locked, !l.visible, ("item", it.id.0));
|
||||
let name = item_label(&doc, it);
|
||||
let clip = Rect::from_min_max(row.min, pos2(row.max.x - 26.0, row.max.y));
|
||||
ui.painter().with_clip_rect(clip).text(
|
||||
@@ -192,7 +215,7 @@ pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
egui::FontId::proportional(11.0),
|
||||
if it.hidden { t.text_dim } else { t.text },
|
||||
);
|
||||
let sq = selection_square(ui, row, lc, is_sel, true, ("item", it.id.0));
|
||||
let sq = selection_square(ui, &app.ui.language, row, lc, is_sel, true, ("item", it.id.0));
|
||||
if eye {
|
||||
let _ = app.run("object.setFlags", json!({"ids": [it.id.0], "hidden": !it.hidden}));
|
||||
} else if lock {
|
||||
@@ -217,10 +240,10 @@ pub fn show(app: &mut DesignApp, ui: &mut Ui) {
|
||||
.color(t.text_dim),
|
||||
);
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if icons::button(ui, "trash", 20.0, false, "Delete Layer").clicked() {
|
||||
if icons::button(ui, "trash", 20.0, false, crate::i18n::tr(&app.ui.language, "Delete Layer")).clicked() {
|
||||
let _ = app.run("layer.delete", json!({"id": active.0}));
|
||||
}
|
||||
if icons::button(ui, "plus", 20.0, false, "Create New Layer").clicked() {
|
||||
if icons::button(ui, "plus", 20.0, false, crate::i18n::tr(&app.ui.language, "Create New Layer")).clicked() {
|
||||
let _ = app.run("layer.new", json!({}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,20 +10,23 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
// Content Collector conveyor.
|
||||
let conveyor = app.session.conveyor.iter().map(|c| c.0.clone()).collect::<Vec<_>>();
|
||||
ui.label(egui::RichText::new(format!("Conveyor ({})", conveyor.len())).strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(format!("{} ({})", crate::i18n::tr(&app.ui.language, "Conveyor"), conveyor.len())).strong());
|
||||
if conveyor.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(
|
||||
&app.ui.language,
|
||||
"Collect objects with the Content Collector (B); place them with the Content Placer.",
|
||||
))
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(
|
||||
&app.ui.language,
|
||||
"Collect objects with the Content Collector (B); place them with the Content Placer.",
|
||||
))
|
||||
.size(10.5)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ui.label(egui::RichText::new(conveyor.join(", ")).size(10.5));
|
||||
if ui.small_button("Clear").clicked() {
|
||||
crate::rtl::label(ui, egui::RichText::new(conveyor.join(", ")).size(10.5));
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Clear"))).clicked() {
|
||||
let _ = app.run("conveyor.clear", json!({}));
|
||||
}
|
||||
}
|
||||
@@ -45,7 +48,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
return;
|
||||
};
|
||||
let has_sel = app.session.active().is_some_and(|d| !d.selection.items.is_empty());
|
||||
if ui.add_enabled(has_sel, egui::Button::new("Add Selection")).clicked()
|
||||
if ui.add_enabled(has_sel, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Add Selection")))).clicked()
|
||||
&& let Err(e) = app.run("library.add", json!({}))
|
||||
{
|
||||
app.status(format!("Library: {e}"));
|
||||
@@ -53,22 +56,25 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.separator();
|
||||
let items = items.as_array().cloned().unwrap_or_default();
|
||||
if items.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "The library is empty. Select objects and Add Selection."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "The library is empty. Select objects and Add Selection."))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
),
|
||||
);
|
||||
}
|
||||
for it in items {
|
||||
let i = it["index"].clone();
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(it["name"].as_str().unwrap_or(""));
|
||||
crate::rtl::label(ui, it["name"].as_str().unwrap_or(""));
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Delete").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))).clicked() {
|
||||
let _ = app.run("library.remove", json!({"index": i}));
|
||||
}
|
||||
if ui.small_button("Place").clicked()
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Place"))).clicked()
|
||||
&& let Err(e) = app.run("library.place", json!({"index": i}))
|
||||
{
|
||||
app.status(format!("Library: {e}"));
|
||||
@@ -107,15 +113,27 @@ pub fn book(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let name = std::path::Path::new(&path).file_stem().map(|n| n.to_string_lossy().to_string()).unwrap_or_default();
|
||||
let (first, pages) = (d["firstPage"].as_u64().unwrap_or(1), d["pages"].as_u64().unwrap_or(0));
|
||||
ui.horizontal(|ui| {
|
||||
if ui.selectable_label(i == source, if i == source { "◆" } else { "◇" }).on_hover_text("Style source").clicked() {
|
||||
if ui
|
||||
.selectable_label(i == source, if i == source { "◆" } else { "◇" })
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Style source"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("book.styleSource", json!({"index": i}));
|
||||
}
|
||||
if ui.selectable_label(false, &name).on_hover_text("Open").clicked() {
|
||||
if ui
|
||||
.selectable_label(false, &name)
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Open"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("file.open", json!({"path": path}));
|
||||
}
|
||||
ui.label(egui::RichText::new(format!("{first}–{}", first + pages.saturating_sub(1))).size(10.5).color(t.text_dim));
|
||||
crate::rtl::label(ui, egui::RichText::new(format!("{first}–{}", first + pages.saturating_sub(1))).size(10.5).color(t.text_dim));
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.small_button("Remove").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Remove"))).clicked() {
|
||||
let _ = app.run("book.remove", json!({"index": i}));
|
||||
}
|
||||
});
|
||||
@@ -150,10 +168,10 @@ pub fn scripts(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let sel_id = egui::Id::new("scripts_sel");
|
||||
let mut sel: usize = ui.data(|d| d.get_temp(sel_id)).unwrap_or(0);
|
||||
if app.ui.scripts.is_empty() {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "No scripts. Add one below.")).size(11.0).color(t.text_dim),
|
||||
));
|
||||
crate::rtl::widget(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "No scripts. Add one below.")).size(11.0).color(t.text_dim)),
|
||||
);
|
||||
}
|
||||
let mut run: Option<usize> = None;
|
||||
for (i, (name, _)) in app.ui.scripts.iter().enumerate() {
|
||||
@@ -167,7 +185,7 @@ pub fn scripts(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
ui.separator();
|
||||
ui.horizontal(|ui| {
|
||||
if ui.add_enabled(!app.ui.scripts.is_empty(), egui::Button::new("Run")).clicked() {
|
||||
if ui.add_enabled(!app.ui.scripts.is_empty(), egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Run")))).clicked() {
|
||||
run = Some(sel);
|
||||
}
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New"))).clicked() {
|
||||
@@ -187,7 +205,11 @@ pub fn scripts(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
Err(e) => app.status(format!("Scripts: {e}")),
|
||||
}
|
||||
}
|
||||
if ui.add_enabled(!app.ui.scripts.is_empty(), egui::Button::new("Delete")).clicked() && sel < app.ui.scripts.len() {
|
||||
if ui
|
||||
.add_enabled(!app.ui.scripts.is_empty(), egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))))
|
||||
.clicked()
|
||||
&& sel < app.ui.scripts.len()
|
||||
{
|
||||
app.ui.scripts.remove(sel);
|
||||
sel = sel.saturating_sub(1);
|
||||
}
|
||||
|
||||
@@ -201,8 +201,14 @@ pub fn font_family_picker(app: &mut DesignApp, ui: &mut egui::Ui, current: &str,
|
||||
|ui| {
|
||||
ui.set_min_width(300.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::TextEdit::singleline(&mut query).hint_text("Search fonts").desired_width(200.0));
|
||||
ui.toggle_value(&mut only_favs, "Favorites").on_hover_text("Show Favorites Only");
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(&mut query)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Search fonts")))
|
||||
.desired_width(200.0),
|
||||
);
|
||||
ui.toggle_value(&mut only_favs, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Favorites"))).on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Show Favorites Only"));
|
||||
});
|
||||
});
|
||||
let q = query.to_lowercase();
|
||||
let ppp = ui.ctx().pixels_per_point();
|
||||
@@ -285,10 +291,11 @@ pub fn font_style_picker(app: &mut DesignApp, ui: &mut egui::Ui, family: &str, c
|
||||
pub fn para_style_picker(app: &mut DesignApp, ui: &mut egui::Ui, current: &str, overridden: bool, width: f32) {
|
||||
let names: Vec<String> = app.session.active().map(|d| d.doc.styles.paragraph.iter().map(|p| p.name.clone()).collect()).unwrap_or_default();
|
||||
let mut pick = None;
|
||||
let label = if overridden { format!("{current}+") } else { current.to_string() };
|
||||
egui::ComboBox::from_id_salt("para_style").selected_text(label).width(width).show_ui(ui, |ui| {
|
||||
let shown = crate::i18n::style_name(&app.ui.language, current);
|
||||
let label = if overridden { format!("{shown}+") } else { shown.to_string() };
|
||||
egui::ComboBox::from_id_salt("para_style").selected_text(crate::rtl::widget(ui, label)).width(width).show_ui(ui, |ui| {
|
||||
for n in names.iter().filter(|n| *n != designcraft_doc::NO_PARA_STYLE) {
|
||||
if ui.selectable_label(n == current, n).clicked() {
|
||||
if ui.selectable_label(n == current, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, n))).clicked() {
|
||||
pick = Some(n.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,19 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let has_text = app.session.active().is_some_and(|d| d.selection.text.is_some());
|
||||
let id = egui::Id::new("new_note_text");
|
||||
let mut draft: String = ui.data(|d| d.get_temp(id)).unwrap_or_default();
|
||||
ui.add(egui::TextEdit::multiline(&mut draft).hint_text("Note text").desired_rows(2).desired_width(f32::INFINITY));
|
||||
if ui.add_enabled(has_text && !draft.trim().is_empty(), egui::Button::new("New Note at Cursor")).clicked() {
|
||||
ui.add(
|
||||
egui::TextEdit::multiline(&mut draft)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Note text")))
|
||||
.desired_rows(2)
|
||||
.desired_width(f32::INFINITY),
|
||||
);
|
||||
if ui
|
||||
.add_enabled(
|
||||
has_text && !draft.trim().is_empty(),
|
||||
egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New Note at Cursor"))),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
match app.run("note.new", json!({"text": draft.trim()})) {
|
||||
Ok(_) => draft.clear(),
|
||||
Err(e) => app.status(format!("Notes: {e}")),
|
||||
@@ -37,13 +48,13 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
ui.label(n["text"].as_str().unwrap_or(""));
|
||||
ui.horizontal(|ui| {
|
||||
if ui.small_button("Go To").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Go To"))).clicked() {
|
||||
let _ = app.run("text.select", json!({"story": story, "anchor": at, "focus": at + 3}));
|
||||
}
|
||||
if ui.small_button("Convert to Text").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Convert to Text"))).clicked() {
|
||||
let _ = app.run("note.convertToText", json!({"story": story, "id": nid}));
|
||||
}
|
||||
if ui.small_button("Delete").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Delete"))).clicked() {
|
||||
let _ = app.run("note.delete", json!({"story": story, "id": nid}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -186,12 +186,21 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.add_space(6.0);
|
||||
ui.spacing_mut().item_spacing.y = 4.0;
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(egui::RichText::new(format!("{} Pages in {} Spreads", doc.page_count(), doc.spreads.len())).size(11.0).color(t.text_dim));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(
|
||||
crate::i18n::tr(&app.ui.language, "{pages} Pages in {spreads} Spreads")
|
||||
.replace("{pages}", &doc.page_count().to_string())
|
||||
.replace("{spreads}", &doc.spreads.len().to_string()),
|
||||
)
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
);
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if icons::button(ui, "trash", 20.0, false, "Delete Page").clicked() {
|
||||
if icons::button(ui, "trash", 20.0, false, crate::i18n::tr(&app.ui.language, "Delete Page")).clicked() {
|
||||
let _ = app.run("layout.pages.delete", json!({"pages": [cur]}));
|
||||
}
|
||||
if icons::button(ui, "plus", 20.0, false, "Insert Page").clicked() {
|
||||
if icons::button(ui, "plus", 20.0, false, crate::i18n::tr(&app.ui.language, "Insert Page")).clicked() {
|
||||
let _ = app.run("layout.pages.insert", json!({"after": cur, "count": 1}));
|
||||
}
|
||||
});
|
||||
@@ -223,7 +232,9 @@ fn page_menu(app: &mut DesignApp, ui: &mut egui::Ui, doc: &designcraft_doc::Docu
|
||||
if si > 0
|
||||
&& ui
|
||||
.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Add to Previous Spread")))
|
||||
.on_hover_text("Spreads of up to 10 pages")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Spreads of up to 10 pages"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("layout.pages.toSpread", json!({"page": abs + 1, "spread": si - 1}));
|
||||
@@ -240,7 +251,7 @@ fn page_menu(app: &mut DesignApp, ui: &mut egui::Ui, doc: &designcraft_doc::Docu
|
||||
("layout.removeOverrides", "Remove All Local Overrides"),
|
||||
("layout.detachAll", "Detach All Objects from Parent"),
|
||||
] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run(id, json!({"page": abs}));
|
||||
ui.close();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
("fit-frame", "fitFrameToContent", "Fit Frame to Content"),
|
||||
("fit-center", "centerContent", "Center Content"),
|
||||
] {
|
||||
if icon_toggle(ui, icon, false, tip).clicked() {
|
||||
if icon_toggle(ui, icon, false, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run("object.fit", json!({"mode": mode}));
|
||||
}
|
||||
}
|
||||
@@ -197,10 +197,10 @@ fn document_sections(app: &mut DesignApp, ui: &mut Ui) {
|
||||
let mut orient = None;
|
||||
place(ui, sub(b, 126.0, 0.0, 52.0, FIELD_H), |ui| {
|
||||
ui.spacing_mut().item_spacing.x = 4.0;
|
||||
if icon_toggle(ui, "orient-portrait", !landscape, "Portrait").clicked() && landscape {
|
||||
if icon_toggle(ui, "orient-portrait", !landscape, crate::i18n::tr(&app.ui.language, "Portrait")).clicked() && landscape {
|
||||
orient = Some(());
|
||||
}
|
||||
if icon_toggle(ui, "orient-landscape", landscape, "Landscape").clicked() && !landscape {
|
||||
if icon_toggle(ui, "orient-landscape", landscape, crate::i18n::tr(&app.ui.language, "Landscape")).clicked() && !landscape {
|
||||
orient = Some(());
|
||||
}
|
||||
});
|
||||
@@ -258,7 +258,9 @@ fn document_sections(app: &mut DesignApp, ui: &mut Ui) {
|
||||
for (k, (icon, tip, v, x, y)) in fields.into_iter().enumerate() {
|
||||
let ir = sub(b, x, y + 2.0, 17.0, 17.0);
|
||||
icons::paint(ui.painter(), ir, icon, t.icon);
|
||||
ui.interact(ir, ui.id().with(("micon", k)), Sense::hover()).on_hover_text(tip);
|
||||
ui.interact(ir, ui.id().with(("micon", k)), Sense::hover()).on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, tip));
|
||||
});
|
||||
let nv = place(ui, sub(b, x + 20.0, y, 73.0, FIELD_H), |ui| {
|
||||
NumField::measure(tip, Some(v), u).width(73.0).spinner().range(0.0, 8000.0).show(ui)
|
||||
});
|
||||
@@ -326,13 +328,13 @@ fn document_sections(app: &mut DesignApp, ui: &mut Ui) {
|
||||
let (mut rulers, mut bl, mut dg) = (app.ui.rulers, app.ui.baseline_grid, app.ui.document_grid);
|
||||
section_row(ui, crate::i18n::tr(&app.ui.language, "Rulers & Grids"), |ui| {
|
||||
ui.spacing_mut().item_spacing.x = 14.0;
|
||||
if icon_toggle(ui, "grid-document", dg, "Show Document Grid").clicked() {
|
||||
if icon_toggle(ui, "grid-document", dg, crate::i18n::tr(&app.ui.language, "Show Document Grid")).clicked() {
|
||||
dg = !dg;
|
||||
}
|
||||
if icon_toggle(ui, "grid-baseline", bl, "Show Baseline Grid").clicked() {
|
||||
if icon_toggle(ui, "grid-baseline", bl, crate::i18n::tr(&app.ui.language, "Show Baseline Grid")).clicked() {
|
||||
bl = !bl;
|
||||
}
|
||||
if icon_toggle(ui, "rulers", rulers, "Show Rulers").clicked() {
|
||||
if icon_toggle(ui, "rulers", rulers, crate::i18n::tr(&app.ui.language, "Show Rulers")).clicked() {
|
||||
rulers = !rulers;
|
||||
}
|
||||
});
|
||||
@@ -347,13 +349,13 @@ fn document_sections(app: &mut DesignApp, ui: &mut Ui) {
|
||||
let (mut guides, mut locked, mut smart) = (app.ui.guides, app.ui.guides_locked, app.ui.smart_guides);
|
||||
section_row(ui, crate::i18n::tr(&app.ui.language, "Guides"), |ui| {
|
||||
ui.spacing_mut().item_spacing.x = 14.0;
|
||||
if icon_toggle(ui, "guides-smart", smart, "Smart Guides").clicked() {
|
||||
if icon_toggle(ui, "guides-smart", smart, crate::i18n::tr(&app.ui.language, "Smart Guides")).clicked() {
|
||||
smart = !smart;
|
||||
}
|
||||
if icon_toggle(ui, "guides-lock", locked, "Lock Guides").clicked() {
|
||||
if icon_toggle(ui, "guides-lock", locked, crate::i18n::tr(&app.ui.language, "Lock Guides")).clicked() {
|
||||
locked = !locked;
|
||||
}
|
||||
if icon_toggle(ui, "guides-show", guides, "Show Guides").clicked() {
|
||||
if icon_toggle(ui, "guides-show", guides, crate::i18n::tr(&app.ui.language, "Show Guides")).clicked() {
|
||||
guides = !guides;
|
||||
}
|
||||
});
|
||||
@@ -457,7 +459,7 @@ fn transform_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
set.insert("ref".into(), json!(rp));
|
||||
let _ = app.run("transform.set", Value::Object(set));
|
||||
}
|
||||
if more_options(ui).clicked() {
|
||||
if more_options(ui, &app.ui.language).clicked() {
|
||||
app.ui.open_panel = Some("info".into());
|
||||
}
|
||||
}
|
||||
@@ -477,7 +479,7 @@ fn stroke_type_dropdown(app: &mut DesignApp, ui: &mut Ui, cur: &str, w: f32) {
|
||||
egui::Popup::menu(&resp).show(|ui| {
|
||||
ui.set_min_width(140.0);
|
||||
for (label, kind) in TYPES {
|
||||
if ui.selectable_label(*kind == cur, *label).clicked() {
|
||||
if ui.selectable_label(*kind == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let ty = if *kind == "dashed" { json!({"kind": "dashed", "pattern": [12.0, 4.0]}) } else { json!({"kind": kind}) };
|
||||
let _ = app.run("object.stroke", json!({"type": ty}));
|
||||
ui.close();
|
||||
@@ -573,7 +575,14 @@ fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
swatch_menu(app, &resp, &doc, &i.fill, |app, n| {
|
||||
let _ = app.run("object.fill", json!({"swatch": n}));
|
||||
});
|
||||
ui.painter().text(b.min + vec2(34.0, FIELD_H / 2.0), egui::Align2::LEFT_CENTER, "Fill", egui::FontId::proportional(11.5), t.text);
|
||||
crate::rtl::paint(
|
||||
ui.painter(),
|
||||
b.min + vec2(34.0, FIELD_H / 2.0),
|
||||
egui::Align2::LEFT_CENTER,
|
||||
crate::i18n::tr(&app.ui.language, "Fill"),
|
||||
egui::FontId::proportional(11.5),
|
||||
t.text,
|
||||
);
|
||||
ui.add_space(4.0);
|
||||
// Stroke.
|
||||
let b = block(ui, FIELD_H);
|
||||
@@ -585,7 +594,7 @@ fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
swatch_menu(app, &resp, &doc, &i.stroke, |app, n| {
|
||||
let _ = app.run("object.stroke", json!({"swatch": n}));
|
||||
});
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, "Stroke", 56.0)).clicked() {
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, crate::i18n::tr(&app.ui.language, "Stroke"), 56.0)).clicked() {
|
||||
app.ui.open_panel = Some("stroke".into());
|
||||
}
|
||||
const WEIGHTS: &[f64] = &[0.0, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 30.0, 40.0, 50.0, 100.0];
|
||||
@@ -600,7 +609,7 @@ fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
// Corner.
|
||||
let b = block(ui, FIELD_H);
|
||||
icons::paint(ui.painter(), sub(b, 3.0, 1.0, 19.0, 19.0), "corner", t.accent);
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, "Corner", 56.0)).clicked() {
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, crate::i18n::tr(&app.ui.language, "Corner"), 56.0)).clicked() {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("frameSize", json!({})));
|
||||
}
|
||||
let (shape, size) = i.corner;
|
||||
@@ -615,7 +624,7 @@ fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
egui::Popup::menu(&resp).show(|ui| {
|
||||
ui.set_min_width(140.0);
|
||||
for s in CornerShape::ALL {
|
||||
if ui.selectable_label(s == shape, s.label()).clicked() {
|
||||
if ui.selectable_label(s == shape, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, s.label()))).clicked() {
|
||||
let _ = app.run("object.cornerOptions", json!({"shape": s, "size": if size > 0.0 { size } else { 12.0 }}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -626,7 +635,7 @@ fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
// Opacity.
|
||||
let b = block(ui, FIELD_H);
|
||||
icons::paint(ui.painter(), sub(b, 3.0, 1.0, 19.0, 19.0), "opacity", t.icon);
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, "Opacity", 56.0)).clicked() {
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, crate::i18n::tr(&app.ui.language, "Opacity"), 56.0)).clicked() {
|
||||
app.ui.open_panel = Some("effects".into());
|
||||
}
|
||||
if let Some(v) = place(ui, sub(b, 96.0, 0.0, 51.0, FIELD_H), |ui| {
|
||||
@@ -644,10 +653,10 @@ fn appearance_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
ui.add_space(6.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 10.0;
|
||||
if icon_toggle(ui, "frame-dashed", false, "Frame Fitting").clicked() {
|
||||
if icon_toggle(ui, "frame-dashed", false, crate::i18n::tr(&app.ui.language, "Frame Fitting")).clicked() {
|
||||
app.ui.open_panel = Some("textWrap".into());
|
||||
}
|
||||
if icon_toggle(ui, "fx", i.shadow, "Effects: Drop Shadow").clicked() {
|
||||
if icon_toggle(ui, "fx", i.shadow, crate::i18n::tr(&app.ui.language, "Effects: Drop Shadow")).clicked() {
|
||||
let _ = app.run("object.dropShadow", json!({"on": !i.shadow}));
|
||||
}
|
||||
});
|
||||
@@ -692,7 +701,7 @@ fn align_row(app: &mut DesignApp, ui: &mut Ui) {
|
||||
("Align to Page", "page"),
|
||||
("Align to Spread", "spread"),
|
||||
] {
|
||||
if ui.selectable_label(app.ui.align_to == id, label).clicked() {
|
||||
if ui.selectable_label(app.ui.align_to == id, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
app.ui.align_to = id.into();
|
||||
ui.close();
|
||||
}
|
||||
@@ -708,7 +717,7 @@ fn align_row(app: &mut DesignApp, ui: &mut Ui) {
|
||||
("vcenter", "objalign-vcenter", "Align vertical centers"),
|
||||
("bottom", "objalign-bottom", "Align bottom edges"),
|
||||
] {
|
||||
if icon_toggle(ui, icon, false, tip).clicked() {
|
||||
if icon_toggle(ui, icon, false, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run("object.align", json!({"edge": edge, "to": to}));
|
||||
}
|
||||
}
|
||||
@@ -725,7 +734,7 @@ fn wrap_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
("wrap-jump", "jumpObject", "Jump Object"),
|
||||
("wrap-next", "jumpToNextColumn", "Jump to Next Column"),
|
||||
] {
|
||||
if icon_toggle(ui, icon, i.wrap == mode, tip).clicked() {
|
||||
if icon_toggle(ui, icon, i.wrap == mode, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run("object.textWrap", json!({"mode": mode}));
|
||||
}
|
||||
}
|
||||
@@ -737,7 +746,7 @@ fn wrap_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
let _ = app.run("object.textWrap", json!({"mode": i.wrap, "invert": inv}));
|
||||
}
|
||||
});
|
||||
if more_options(ui).clicked() {
|
||||
if more_options(ui, &app.ui.language).clicked() {
|
||||
app.ui.open_panel = Some("textWrap".into());
|
||||
}
|
||||
}
|
||||
@@ -750,7 +759,7 @@ fn arrange_menu(app: &mut DesignApp, resp: &egui::Response) {
|
||||
("Send Backward", "object.sendBackward"),
|
||||
("Send to Back", "object.sendToBack"),
|
||||
] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run(cmd, json!({}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -771,7 +780,7 @@ fn convert_shape_menu(app: &mut DesignApp, resp: &egui::Response) {
|
||||
("Line", "line"),
|
||||
("Orthogonal Line", "orthogonalLine"),
|
||||
] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
if let Err(e) = app.run("object.convertShape", json!({"to": to})) {
|
||||
app.status(format!("Convert Shape: {e}"));
|
||||
}
|
||||
@@ -806,7 +815,7 @@ fn quick_actions_object(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
|
||||
ui.spacing_mut().item_spacing.x = 10.0;
|
||||
let r = outline_button(ui, crate::i18n::tr(&app.ui.language, "Arrange"), hw);
|
||||
arrange_menu(app, &r);
|
||||
if outline_button(ui, if i.count > 1 { "Group" } else { "Lock" }, hw).clicked() {
|
||||
if outline_button(ui, crate::i18n::tr(&app.ui.language, if i.count > 1 { "Group" } else { "Lock" }), hw).clicked() {
|
||||
let _ = app.run(if i.count > 1 { "object.group" } else { "object.lock" }, json!({}));
|
||||
}
|
||||
});
|
||||
@@ -829,7 +838,12 @@ fn text_style_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
let Some(a) = text_attrs(app) else { return };
|
||||
let tab = app.ui.text_style_tab;
|
||||
let fw = full_width(ui);
|
||||
if let Some(k) = widgets::segmented(ui, &["Paragraph Styles", "Character Styles"], tab as usize, fw) {
|
||||
if let Some(k) = widgets::segmented(
|
||||
ui,
|
||||
&[crate::i18n::tr(&app.ui.language, "Paragraph Styles"), crate::i18n::tr(&app.ui.language, "Character Styles")],
|
||||
tab as usize,
|
||||
fw,
|
||||
) {
|
||||
app.ui.text_style_tab = k as u8;
|
||||
}
|
||||
ui.add_space(5.0);
|
||||
@@ -845,13 +859,15 @@ fn text_style_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
}
|
||||
};
|
||||
let ov = if tab == 0 { a["paraOverrides"].as_u64().unwrap_or(0) + a["charOverrides"].as_u64().unwrap_or(0) } else { 0 };
|
||||
let label = if ov > 0 { format!("{cur}+") } else { cur.clone() };
|
||||
let shown = crate::i18n::style_name(&app.ui.language, &cur);
|
||||
let label = if ov > 0 { format!("{shown}+") } else { shown.to_string() };
|
||||
let resp = widgets::dropdown_h(ui, "", fw, 34.0);
|
||||
// "Ag" swatch + style name.
|
||||
let ag = Rect::from_min_size(resp.rect.min + vec2(6.0, 6.0), vec2(22.0, 22.0));
|
||||
ui.painter().rect_filled(ag, 1.0, egui::Color32::WHITE);
|
||||
ui.painter().text(ag.center(), egui::Align2::CENTER_CENTER, "Ag", egui::FontId::new(13.0, egui::FontFamily::Proportional), egui::Color32::BLACK);
|
||||
ui.painter().with_clip_rect(resp.rect.shrink2(vec2(20.0, 0.0))).text(
|
||||
crate::rtl::paint(
|
||||
&ui.painter().with_clip_rect(resp.rect.shrink2(vec2(20.0, 0.0))),
|
||||
pos2(ag.max.x + 8.0, resp.rect.center().y),
|
||||
egui::Align2::LEFT_CENTER,
|
||||
&label,
|
||||
@@ -863,7 +879,7 @@ fn text_style_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
ui.set_min_width(fw);
|
||||
egui::ScrollArea::vertical().max_height(320.0).show(ui, |ui| {
|
||||
for n in &names {
|
||||
if ui.selectable_label(*n == cur, n).clicked() {
|
||||
if ui.selectable_label(*n == cur, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, n))).clicked() {
|
||||
pick = Some(n.clone());
|
||||
ui.close();
|
||||
}
|
||||
@@ -880,20 +896,32 @@ fn text_style_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
ui.add_space(4.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 8.0;
|
||||
if icon_toggle(ui, "pilcrow-menu", false, if tab == 0 { "Paragraph Styles panel" } else { "Character Styles panel" }).clicked() {
|
||||
if icon_toggle(
|
||||
ui,
|
||||
"pilcrow-menu",
|
||||
false,
|
||||
crate::i18n::tr(&app.ui.language, if tab == 0 { "Paragraph Styles panel" } else { "Character Styles panel" }),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
app.ui.open_panel = Some(if tab == 0 { "paragraphStyles" } else { "characterStyles" }.into());
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
ui.spacing_mut().item_spacing.x = 12.0;
|
||||
ui.add_space(4.0);
|
||||
if icon_toggle(ui, "style-new", false, "Create new style").clicked() {
|
||||
if icon_toggle(ui, "style-new", false, crate::i18n::tr(&app.ui.language, crate::i18n::tr(&app.ui.language, "Create new style"))).clicked()
|
||||
{
|
||||
let cmd = if tab == 0 { "style.paragraph.create" } else { "style.character.create" };
|
||||
let _ = app.run(cmd, json!({}));
|
||||
}
|
||||
if icon_toggle(ui, "style-clear", false, "Clear overrides").clicked() && tab == 0 && !cur.is_empty() {
|
||||
if icon_toggle(ui, "style-clear", false, crate::i18n::tr(&app.ui.language, crate::i18n::tr(&app.ui.language, "Clear overrides")))
|
||||
.clicked()
|
||||
&& tab == 0
|
||||
&& !cur.is_empty()
|
||||
{
|
||||
let _ = app.run("style.paragraph.apply", json!({"name": cur, "clearOverrides": true}));
|
||||
}
|
||||
if icon_toggle(ui, "style-load", false, "Styles panel").clicked() {
|
||||
if icon_toggle(ui, "style-load", false, crate::i18n::tr(&app.ui.language, "Styles panel")).clicked() {
|
||||
app.ui.open_panel = Some(if tab == 0 { "paragraphStyles" } else { "characterStyles" }.into());
|
||||
}
|
||||
});
|
||||
@@ -926,9 +954,16 @@ fn text_appearance_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
let _ = app.run("type.char", json!({"attrs": {key: n}}));
|
||||
});
|
||||
if k == 0 {
|
||||
ui.painter().text(b.min + vec2(34.0, FIELD_H / 2.0), egui::Align2::LEFT_CENTER, label, egui::FontId::proportional(11.5), t.text);
|
||||
crate::rtl::paint(
|
||||
ui.painter(),
|
||||
b.min + vec2(34.0, FIELD_H / 2.0),
|
||||
egui::Align2::LEFT_CENTER,
|
||||
crate::i18n::tr(&app.ui.language, label),
|
||||
egui::FontId::proportional(11.5),
|
||||
t.text,
|
||||
);
|
||||
} else {
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, label, 56.0)).clicked() {
|
||||
if place(ui, sub(b, 34.0, 0.0, 56.0, FIELD_H), |ui| link_label(ui, crate::i18n::tr(&app.ui.language, label), 56.0)).clicked() {
|
||||
app.ui.open_panel = Some("stroke".into());
|
||||
}
|
||||
const WEIGHTS: &[f64] = &[0.0, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0];
|
||||
@@ -1019,10 +1054,10 @@ fn character_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
_ => "Metrics".to_string(),
|
||||
};
|
||||
place(ui, sub(b, 24.0, 26.0, half - 24.0, FIELD_H), |ui| {
|
||||
let resp = widgets::dropdown(ui, &kern_label, half - 24.0);
|
||||
let resp = widgets::dropdown(ui, crate::i18n::tr(&app.ui.language, &kern_label), half - 24.0);
|
||||
egui::Popup::menu(&resp).show(|ui| {
|
||||
for (label, v) in [("Metrics", json!({"kind": "metrics"})), ("Optical", json!({"kind": "optical"})), ("0", json!({"kind": "none"}))] {
|
||||
if ui.selectable_label(kern_label == label, label).clicked() {
|
||||
if ui.selectable_label(kern_label == label, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("type.char", json!({"attrs": {"kerning": v}}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -1036,7 +1071,7 @@ fn character_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
}) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"tracking": v}}));
|
||||
}
|
||||
if more_options(ui).clicked() {
|
||||
if more_options(ui, &app.ui.language).clicked() {
|
||||
app.ui.open_panel = Some("character".into());
|
||||
}
|
||||
}
|
||||
@@ -1068,7 +1103,7 @@ fn paragraph_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
}
|
||||
}
|
||||
});
|
||||
if more_options(ui).clicked() {
|
||||
if more_options(ui, &app.ui.language).clicked() {
|
||||
app.ui.open_panel = Some("paragraph".into());
|
||||
}
|
||||
}
|
||||
@@ -1080,7 +1115,7 @@ fn bullets_section(app: &mut DesignApp, ui: &mut Ui) {
|
||||
ui.spacing_mut().item_spacing.x = 10.0;
|
||||
for (icon, kind, tip) in [("bullets", "bullets", "Bulleted List"), ("numbering", "numbers", "Numbered List")] {
|
||||
let on = lt == kind;
|
||||
if icon_toggle(ui, icon, on, tip).clicked() {
|
||||
if icon_toggle(ui, icon, on, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run("type.para", json!({"attrs": {"listType": if on { "none" } else { kind }}}));
|
||||
}
|
||||
}
|
||||
@@ -1101,7 +1136,7 @@ fn quick_actions_text(app: &mut DesignApp, ui: &mut Ui) {
|
||||
let r = outline_button(ui, crate::i18n::tr(&app.ui.language, "Change Case"), hw);
|
||||
egui::Popup::menu(&r).show(|ui| {
|
||||
for (label, v) in [("UPPERCASE", "allCaps"), ("Small Caps", "smallCaps"), ("Normal", "normal")] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("type.char", json!({"attrs": {"capitalization": v}}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -1184,82 +1219,112 @@ pub fn character_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let c = a["chars"].clone();
|
||||
let fam = c["fontFamily"].as_str().unwrap_or("").to_string();
|
||||
let sty = c["fontStyle"].as_str().unwrap_or("").to_string();
|
||||
ui.label(egui::RichText::new("Character").strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Character")).strong());
|
||||
super::font_family_picker(app, ui, &fam, 220.0);
|
||||
super::font_style_picker(app, ui, &fam, &sty, 220.0);
|
||||
variable_font_axes(app, ui, &fam, &sty);
|
||||
// Language: hyphenation, spelling and typographer's quotes follow it.
|
||||
let lang = c["language"].as_str().unwrap_or("English: USA").to_string();
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Language");
|
||||
egui::ComboBox::from_id_salt("char_language").selected_text(&lang).width(170.0).show_ui(ui, |ui| {
|
||||
for l in LANGUAGES {
|
||||
if ui.selectable_label(*l == lang, *l).clicked() {
|
||||
let _ = app.run("type.char", json!({"attrs": {"language": l}}));
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Language"));
|
||||
egui::ComboBox::from_id_salt("char_language")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &lang)))
|
||||
.width(170.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for l in LANGUAGES {
|
||||
if ui.selectable_label(*l == lang, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
let _ = app.run("type.char", json!({"attrs": {"language": l}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
// Digits (World-Ready): shown for right-to-left paragraphs or once set.
|
||||
let digits = c["digits"].as_str().unwrap_or("default").to_string();
|
||||
if digits != "default" || a["para"]["direction"].as_str() == Some("rightToLeft") {
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Digits");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Digits"));
|
||||
let opts = [("default", "Default"), ("arabic", "Arabic"), ("hindi", "Hindi"), ("farsi", "Farsi"), ("native", "Native")];
|
||||
let cur = opts.iter().find(|o| o.0 == digits).map_or("Default", |o| o.1);
|
||||
egui::ComboBox::from_id_salt("char_digits").selected_text(cur).width(120.0).show_ui(ui, |ui| {
|
||||
for (k, l) in opts {
|
||||
if ui.selectable_label(k == digits, l).clicked() {
|
||||
let _ = app.run("type.char", json!({"attrs": {"digits": k}}));
|
||||
egui::ComboBox::from_id_salt("char_digits")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur)))
|
||||
.width(120.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (k, l) in opts {
|
||||
if ui.selectable_label(k == digits, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, l))).clicked() {
|
||||
let _ = app.run("type.char", json!({"attrs": {"digits": k}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
egui::Grid::new("chargrid").num_columns(4).spacing(vec2(6.0, 4.0)).show(ui, |ui| {
|
||||
caption(ui, "Size");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Size"));
|
||||
if let Some(v) = number(ui, "pcs", c["size"].as_f64(), " pt", 60.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"size": v}}));
|
||||
}
|
||||
caption(ui, "Leading");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Leading"));
|
||||
let auto = c["leading"]["kind"].as_str() != Some("points");
|
||||
let lv = if auto { c["size"].as_f64().map(|s| s * a["para"]["autoLeading"].as_f64().unwrap_or(1.2)) } else { c["leading"]["value"].as_f64() };
|
||||
if let Some(v) = number(ui, "pcl", lv, if auto { " (auto)" } else { " pt" }, 70.0, 2) {
|
||||
if let Some(v) = number(ui, "pcl", lv, if auto { crate::i18n::tr(&app.ui.language, " (auto)") } else { " pt" }, 70.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"leading": {"kind": "points", "value": v}}}));
|
||||
}
|
||||
ui.end_row();
|
||||
caption(ui, "Tracking");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Tracking"));
|
||||
if let Some(v) = number(ui, "pct", c["tracking"].as_f64(), "", 60.0, 0) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"tracking": v}}));
|
||||
}
|
||||
caption(ui, "Baseline");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Baseline"));
|
||||
if let Some(v) = number(ui, "pcb", c["baselineShift"].as_f64(), " pt", 70.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {"baselineShift": v}}));
|
||||
}
|
||||
ui.end_row();
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Color");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Color"));
|
||||
super::swatch_picker(app, ui, "tfill", c["fill"].as_str().map(str::to_string), |app, n| {
|
||||
let _ = app.run("type.char", json!({"attrs": {"fill": n}}));
|
||||
});
|
||||
ui.label(c["fill"].as_str().unwrap_or(""));
|
||||
crate::rtl::label(ui, c["fill"].as_str().unwrap_or(""));
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
let caps = c["capitalization"].as_str() == Some("allCaps");
|
||||
if ui.selectable_label(caps, "TT").on_hover_text("All Caps").clicked() {
|
||||
if ui
|
||||
.selectable_label(caps, "TT")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "All Caps"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("type.char", json!({"attrs": {"capitalization": if caps { "normal" } else { "allCaps" }}}));
|
||||
}
|
||||
let ul = c["underline"].as_bool().unwrap_or(false);
|
||||
if ui.selectable_label(ul, "U").on_hover_text("Underline").clicked() {
|
||||
if ui
|
||||
.selectable_label(ul, "U")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Underline"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("type.char", json!({"attrs": {"underline": !ul}}));
|
||||
}
|
||||
let st = c["strikethrough"].as_bool().unwrap_or(false);
|
||||
if ui.selectable_label(st, "S").on_hover_text("Strikethrough").clicked() {
|
||||
if ui
|
||||
.selectable_label(st, "S")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Strikethrough"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("type.char", json!({"attrs": {"strikethrough": !st}}));
|
||||
}
|
||||
let sup = c["position"].as_str() == Some("superscript");
|
||||
if ui.selectable_label(sup, "T¹").on_hover_text("Superscript").clicked() {
|
||||
if ui
|
||||
.selectable_label(sup, "T¹")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Superscript"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("type.char", json!({"attrs": {"position": if sup { "normal" } else { "superscript" }}}));
|
||||
}
|
||||
let features: Vec<String> =
|
||||
@@ -1271,16 +1336,16 @@ pub fn character_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if !c[key].as_bool().unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
egui::CollapsingHeader::new(title).id_salt(key).show(ui, |ui| {
|
||||
egui::CollapsingHeader::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, title))).id_salt(key).show(ui, |ui| {
|
||||
let size = c["size"].as_f64().unwrap_or(12.0);
|
||||
let auto_off = if key == "underline" { size * 0.12 } else { size * 0.3 };
|
||||
egui::Grid::new((key, "opts")).num_columns(4).spacing(vec2(6.0, 4.0)).show(ui, |ui| {
|
||||
caption(ui, "Weight");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Weight"));
|
||||
let w = c[format!("{key}Weight")].as_f64().unwrap_or(size / 14.0);
|
||||
if let Some(v) = number(ui, &format!("{key}w"), Some(w), " pt", 60.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {format!("{key}Weight"): v.max(0.0)}}));
|
||||
}
|
||||
caption(ui, "Offset");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Offset"));
|
||||
let o = c[format!("{key}Offset")].as_f64().unwrap_or(auto_off);
|
||||
if let Some(v) = number(ui, &format!("{key}o"), Some(o), " pt", 60.0, 2) {
|
||||
let _ = app.run("type.char", json!({"attrs": {format!("{key}Offset"): v}}));
|
||||
@@ -1288,12 +1353,12 @@ pub fn character_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.end_row();
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Color");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Color"));
|
||||
let cur = c[format!("{key}Color")].as_str().filter(|s| !s.is_empty()).map(str::to_string);
|
||||
super::swatch_picker(app, ui, &format!("{key}c"), cur.clone(), |app, n| {
|
||||
let _ = app.run("type.char", json!({"attrs": {format!("{key}Color"): n}}));
|
||||
});
|
||||
ui.label(cur.unwrap_or_else(|| "(Text Color)".into()));
|
||||
crate::rtl::label(ui, cur.unwrap_or_else(|| crate::i18n::tr(&app.ui.language, "(Text Color)").into()));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1305,7 +1370,7 @@ pub fn open_type_menu(app: &mut DesignApp, ui: &mut egui::Ui, features: &[String
|
||||
ui.set_min_width(220.0);
|
||||
for (tag, label, _) in otf::TOGGLES {
|
||||
let mut on = otf::is_on(features, tag);
|
||||
if ui.checkbox(&mut on, *label).clicked() {
|
||||
if ui.checkbox(&mut on, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("type.openType", json!({"feature": tag, "on": on}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -1323,7 +1388,7 @@ pub fn open_type_menu(app: &mut DesignApp, ui: &mut egui::Ui, features: &[String
|
||||
let mask = otf::stylistic_sets(features);
|
||||
for n in 1..=20u32 {
|
||||
let mut on = mask & (1 << (n - 1)) != 0;
|
||||
if ui.checkbox(&mut on, format!("Set {n}")).clicked() {
|
||||
if ui.checkbox(&mut on, crate::rtl::widget(ui, format!("{} {n}", crate::i18n::tr(&app.ui.language, "Set")))).clicked() {
|
||||
let sets: Vec<u32> = (1..=20).filter(|k| if *k == n { on } else { mask & (1 << (k - 1)) != 0 }).collect();
|
||||
let _ = app.run("type.openType", json!({"stylisticSets": sets}));
|
||||
}
|
||||
@@ -1338,7 +1403,7 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
};
|
||||
let u = units(app);
|
||||
let p = a["para"].clone();
|
||||
ui.label(egui::RichText::new("Paragraph").strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Paragraph")).strong());
|
||||
let cur: Align = serde_json::from_value(p["align"].clone()).unwrap_or_default();
|
||||
ui.horizontal(|ui| {
|
||||
for (al, icon) in [
|
||||
@@ -1356,9 +1421,9 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Paragraph Direction (World-Ready): switching also mirrors left/right alignment.
|
||||
let rtl = p["direction"] == "rightToLeft";
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Direction");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Direction"));
|
||||
for (on, label, dir) in [(!rtl, "Left to Right", "leftToRight"), (rtl, "Right to Left", "rightToLeft")] {
|
||||
if ui.selectable_label(on, label).clicked() && !on {
|
||||
if ui.selectable_label(on, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() && !on {
|
||||
let align = match cur {
|
||||
Align::Left => Align::Right,
|
||||
Align::Right => Align::Left,
|
||||
@@ -1377,11 +1442,11 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
{
|
||||
caption(ui, la);
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, la));
|
||||
if let Some(v) = measure(ui, &format!("pp{row}a"), p[ka].as_f64(), u, 64.0) {
|
||||
let _ = app.run("type.para", json!({"attrs": {ka: v}}));
|
||||
}
|
||||
caption(ui, lb);
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, lb));
|
||||
if let Some(v) = measure(ui, &format!("pp{row}b"), p[kb].as_f64(), u, 64.0) {
|
||||
let _ = app.run("type.para", json!({"attrs": {kb: v}}));
|
||||
}
|
||||
@@ -1399,7 +1464,7 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Composer");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Composer"));
|
||||
let single = p["composer"].as_str() == Some("singleLine");
|
||||
if ui.selectable_label(!single, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Paragraph"))).clicked() {
|
||||
let _ = app.run("type.para", json!({"attrs": {"composer": "paragraph"}}));
|
||||
@@ -1414,7 +1479,7 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
for (on_key, color_key, label) in [("shadingOn", "shadingColor", "Shading"), ("borderOn", "borderColor", "Border")] {
|
||||
ui.horizontal(|ui| {
|
||||
let mut on = p[on_key].as_bool().unwrap_or(false);
|
||||
if ui.checkbox(&mut on, label).changed() {
|
||||
if ui.checkbox(&mut on, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).changed() {
|
||||
let _ = app.run("type.para", json!({ on_key: on }));
|
||||
}
|
||||
if on {
|
||||
@@ -1439,7 +1504,7 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
if p["shadingOn"].as_bool().unwrap_or(false) || p["borderOn"].as_bool().unwrap_or(false) {
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Offsets");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Offsets"));
|
||||
let o = p["borderOffsets"][0].as_f64().or(p["shadingOffsets"][0].as_f64());
|
||||
if let Some(v) = number(ui, "pbo", o, " pt", 50.0, 2) {
|
||||
let o = [v; 4];
|
||||
@@ -1450,7 +1515,7 @@ pub fn paragraph_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let ps = a["paragraphStyle"].as_str().unwrap_or("").to_string();
|
||||
let ov = a["paraOverrides"].as_u64().unwrap_or(0) + a["charOverrides"].as_u64().unwrap_or(0);
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Style");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Style"));
|
||||
super::para_style_picker(app, ui, &ps, ov > 0, 190.0);
|
||||
});
|
||||
}
|
||||
@@ -1466,102 +1531,111 @@ pub fn stroke_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
};
|
||||
let t = Tokens::get(ui.ctx());
|
||||
egui::Grid::new("stroke_panel").num_columns(2).spacing(vec2(8.0, 6.0)).show(ui, |ui| {
|
||||
caption(ui, "Weight:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Weight:"));
|
||||
if let Some(v) = number(ui, "sw", Some(i.stroke_weight), " pt", 60.0, 3) {
|
||||
let _ = app.run("object.stroke", json!({"weight": v}));
|
||||
}
|
||||
ui.end_row();
|
||||
caption(ui, "Cap:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Cap:"));
|
||||
ui.horizontal(|ui| {
|
||||
for (label, v, cur) in [("Butt", "butt", Cap::Butt), ("Round", "round", Cap::Round), ("Projecting", "projecting", Cap::Projecting)] {
|
||||
if ui.selectable_label(st.cap == cur, label).clicked() {
|
||||
if ui.selectable_label(st.cap == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"cap": v}));
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
caption(ui, "Join:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Join:"));
|
||||
ui.horizontal(|ui| {
|
||||
for (label, v, cur) in [("Miter", "miter", Join::Miter), ("Round", "round", Join::Round), ("Bevel", "bevel", Join::Bevel)] {
|
||||
if ui.selectable_label(st.join == cur, label).clicked() {
|
||||
if ui.selectable_label(st.join == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"join": v}));
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
caption(ui, "Miter Limit:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Miter Limit:"));
|
||||
if let Some(v) = number(ui, "smiter", Some(st.miter_limit), " x", 60.0, 0) {
|
||||
let _ = app.run("object.stroke", json!({"miterLimit": v}));
|
||||
}
|
||||
ui.end_row();
|
||||
caption(ui, "Align Stroke:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Align Stroke:"));
|
||||
ui.horizontal(|ui| {
|
||||
for (label, a, cur) in
|
||||
[("Center", "center", StrokeAlign::Center), ("Inside", "inside", StrokeAlign::Inside), ("Outside", "outside", StrokeAlign::Outside)]
|
||||
{
|
||||
if ui.selectable_label(st.align == cur, label).clicked() {
|
||||
if ui.selectable_label(st.align == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"align": a}));
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
caption(ui, "Type:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Type:"));
|
||||
let custom: Vec<String> = app.session.active().map(|d| d.doc.stroke_styles.iter().map(|x| x.name.clone()).collect()).unwrap_or_default();
|
||||
let shown = match &st.kind {
|
||||
StrokeType::Style { name } => name.clone(),
|
||||
k => k.label().to_string(),
|
||||
};
|
||||
egui::ComboBox::from_id_salt("stype").selected_text(&shown).width(140.0).show_ui(ui, |ui| {
|
||||
let built_in = [
|
||||
"solid",
|
||||
"dashed",
|
||||
"dotted",
|
||||
"thickThin",
|
||||
"thinThick",
|
||||
"thinThin",
|
||||
"thickThick",
|
||||
"thinThickThin",
|
||||
"thickThinThick",
|
||||
"wavy",
|
||||
"hashed",
|
||||
];
|
||||
for k in built_in {
|
||||
let ty = if k == "dashed" { json!({"kind": k, "pattern": [12.0, 4.0]}) } else { json!({"kind": k}) };
|
||||
let label = serde_json::from_value::<StrokeType>(ty.clone()).map(|k| k.label()).unwrap_or("");
|
||||
if ui.selectable_label(shown == label, label).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"type": ty}));
|
||||
egui::ComboBox::from_id_salt("stype")
|
||||
.selected_text(crate::rtl::widget(
|
||||
ui,
|
||||
if matches!(st.kind, StrokeType::Style { .. }) { &shown } else { crate::i18n::tr(&app.ui.language, &shown) },
|
||||
))
|
||||
.width(140.0)
|
||||
.show_ui(ui, |ui| {
|
||||
let built_in = [
|
||||
"solid",
|
||||
"dashed",
|
||||
"dotted",
|
||||
"thickThin",
|
||||
"thinThick",
|
||||
"thinThin",
|
||||
"thickThick",
|
||||
"thinThickThin",
|
||||
"thickThinThick",
|
||||
"wavy",
|
||||
"hashed",
|
||||
];
|
||||
for k in built_in {
|
||||
let ty = if k == "dashed" { json!({"kind": k, "pattern": [12.0, 4.0]}) } else { json!({"kind": k}) };
|
||||
let label = serde_json::from_value::<StrokeType>(ty.clone()).map(|k| k.label()).unwrap_or("");
|
||||
if ui.selectable_label(shown == label, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"type": ty}));
|
||||
}
|
||||
}
|
||||
}
|
||||
if !custom.is_empty() {
|
||||
ui.separator();
|
||||
}
|
||||
for n in &custom {
|
||||
if ui.selectable_label(shown == *n, n).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"type": {"kind": "style", "name": n}}));
|
||||
if !custom.is_empty() {
|
||||
ui.separator();
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
for (key, label, cur, flip) in [("start", "Start/End:", st.start, true), ("end", "", st.end, false)] {
|
||||
caption(ui, label);
|
||||
egui::ComboBox::from_id_salt(key).selected_text(cur.label()).width(140.0).show_ui(ui, |ui| {
|
||||
for a in Arrowhead::ALL {
|
||||
ui.horizontal(|ui| {
|
||||
arrow_preview(ui, a, flip, t.text_strong);
|
||||
if ui.selectable_label(a == cur, a.label()).clicked() {
|
||||
let _ = app.run("object.stroke", json!({key: a}));
|
||||
}
|
||||
});
|
||||
for n in &custom {
|
||||
if ui.selectable_label(shown == *n, n).clicked() {
|
||||
let _ = app.run("object.stroke", json!({"type": {"kind": "style", "name": n}}));
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
for (key, label, cur, flip) in [("start", "Start/End:", st.start, true), ("end", "", st.end, false)] {
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
egui::ComboBox::from_id_salt(key)
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur.label())))
|
||||
.width(140.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for a in Arrowhead::ALL {
|
||||
ui.horizontal(|ui| {
|
||||
arrow_preview(ui, a, flip, t.text_strong);
|
||||
if ui.selectable_label(a == cur, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, a.label()))).clicked() {
|
||||
let _ = app.run("object.stroke", json!({key: a}));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
caption(ui, "Gap Color:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Gap Color:"));
|
||||
super::swatch_picker(app, ui, "sgap", Some(st.gap_swatch.clone()), |app, n| {
|
||||
let _ = app.run("object.stroke", json!({"gapSwatch": n}));
|
||||
});
|
||||
ui.end_row();
|
||||
caption(ui, "Color:");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Color:"));
|
||||
super::swatch_picker(app, ui, "spick", Some(i.stroke.clone()), |app, n| {
|
||||
let _ = app.run("object.stroke", json!({"swatch": n}));
|
||||
});
|
||||
@@ -1621,14 +1695,14 @@ pub fn wrap_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
("wrap-next", "jumpToNextColumn", "Jump to Next Column"),
|
||||
] {
|
||||
let on = info.as_ref().is_some_and(|i| i.wrap == mode);
|
||||
if icons::button(ui, icon, 26.0, on, tip).clicked() {
|
||||
if icons::button(ui, icon, 26.0, on, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run("object.textWrap", json!({"mode": mode}));
|
||||
}
|
||||
}
|
||||
});
|
||||
let u = units(app);
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Offset");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Offset"));
|
||||
if let Some(v) = measure(ui, "wo", Some(0.0), u, 60.0) {
|
||||
let _ = app.run("object.textWrap", json!({"mode": info.as_ref().map(|i| i.wrap).unwrap_or("boundingBox"), "offset": v}));
|
||||
}
|
||||
@@ -1637,12 +1711,12 @@ pub fn wrap_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
|
||||
/// Pathfinder panel: combine the selected shapes; make or release compound paths.
|
||||
pub fn pathfinder_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.label(egui::RichText::new("Pathfinder").strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Pathfinder")).strong());
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
for (label, op) in
|
||||
[("Add", "add"), ("Subtract", "subtract"), ("Intersect", "intersect"), ("Exclude Overlap", "exclude"), ("Minus Back", "minusBack")]
|
||||
{
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("object.pathfinder", json!({"op": op}));
|
||||
}
|
||||
}
|
||||
@@ -1678,7 +1752,9 @@ pub fn align_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
"vcenter" => "↕",
|
||||
_ => "⤓",
|
||||
})
|
||||
.on_hover_text(tip)
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, tip));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("object.align", json!({"edge": edge}));
|
||||
@@ -1686,10 +1762,10 @@ pub fn align_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
if ui.small_button("Distribute ↔").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Distribute ↔"))).clicked() {
|
||||
let _ = app.run("object.distribute", json!({"axis": "horizontal"}));
|
||||
}
|
||||
if ui.small_button("Distribute ↕").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Distribute ↕"))).clicked() {
|
||||
let _ = app.run("object.distribute", json!({"axis": "vertical"}));
|
||||
}
|
||||
});
|
||||
@@ -1701,17 +1777,20 @@ pub fn links_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Linked stories (Place and Link).
|
||||
let stories = app.session.execute("story.links", &json!({})).ok().and_then(|v| v.as_array().cloned()).unwrap_or_default();
|
||||
if !stories.is_empty() {
|
||||
ui.label(egui::RichText::new("Linked Stories").strong());
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Linked Stories")).strong());
|
||||
for l in &stories {
|
||||
let out = l["outOfDate"].as_bool().unwrap_or(false);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!("Story {} ← story {}", l["story"], l["parent"]));
|
||||
crate::rtl::label(ui, format!("Story {} ← story {}", l["story"], l["parent"]));
|
||||
if out {
|
||||
ui.label(crate::rtl::widget(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "⚠ out of date")).color(egui::Color32::from_rgb(230, 160, 40)),
|
||||
));
|
||||
if ui.small_button("Update").clicked() {
|
||||
crate::rtl::widget(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "⚠ out of date")).color(egui::Color32::from_rgb(230, 160, 40)),
|
||||
),
|
||||
);
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Update"))).clicked() {
|
||||
let _ = app.run("story.updateLink", json!({"story": l["story"]}));
|
||||
}
|
||||
}
|
||||
@@ -1741,7 +1820,7 @@ pub fn links_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let sel_key = egui::Id::new("links_panel_sel");
|
||||
let mut chosen: Option<u64> = ui.data(|d| d.get_temp(sel_key));
|
||||
egui::Grid::new("links_grid").num_columns(3).striped(true).spacing([10.0, 4.0]).show(ui, |ui| {
|
||||
ui.label(egui::RichText::new("Name").color(t.text_dim).size(11.0));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Name")).color(t.text_dim).size(11.0));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Status")).color(t.text_dim).size(11.0));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Page · PPI")).color(t.text_dim).size(11.0));
|
||||
ui.end_row();
|
||||
@@ -1757,7 +1836,7 @@ pub fn links_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
"embedded" => ("Embedded", t.text_dim),
|
||||
_ => ("OK", t.text_dim),
|
||||
};
|
||||
ui.label(egui::RichText::new(txt).color(col).size(11.0));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, txt)).color(col).size(11.0));
|
||||
let uses = r["uses"].as_array().cloned().unwrap_or_default();
|
||||
let info = match uses.first() {
|
||||
Some(u) => {
|
||||
@@ -1766,11 +1845,14 @@ pub fn links_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let more = if uses.len() > 1 { format!(" (+{})", uses.len() - 1) } else { String::new() };
|
||||
format!("{page}{ppi}{more}")
|
||||
}
|
||||
None => "unused".into(),
|
||||
None => crate::i18n::tr(&app.ui.language, "unused").into(),
|
||||
};
|
||||
// Low effective resolution for print is flagged like the Preflight check.
|
||||
let low = uses.first().and_then(|u| u["ppi"].as_f64()).is_some_and(|p| p < 150.0);
|
||||
ui.label(egui::RichText::new(info).size(11.0).color(if low { egui::Color32::from_rgb(0xe8, 0xb3, 0x2c) } else { t.text_dim }));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(info).size(11.0).color(if low { egui::Color32::from_rgb(0xe8, 0xb3, 0x2c) } else { t.text_dim }),
|
||||
);
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
@@ -1802,7 +1884,9 @@ pub fn links_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Choose any file in the folder: missing links are looked up there by name.
|
||||
if ui
|
||||
.button(crate::i18n::tr(&app.ui.language, "Relink to Folder…"))
|
||||
.on_hover_text("Pick a file in the folder holding the moved graphics")
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Pick a file in the folder holding the moved graphics"));
|
||||
})
|
||||
.clicked()
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|pick| pick("relink"))
|
||||
&& let Some(dir) = std::path::Path::new(&path).parent()
|
||||
@@ -1821,17 +1905,34 @@ pub fn info_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
match sel_info(app) {
|
||||
Some(i) => {
|
||||
let f = |v: f64| designcraft_geom::format_measure(v, u);
|
||||
ui.label(format!("X: {} Y: {}", f(i.page_rect.x0), f(i.page_rect.y0)));
|
||||
ui.label(format!("W: {} H: {}", f(i.page_rect.width()), f(i.page_rect.height())));
|
||||
ui.label(format!("Fill: {} Stroke: {}", i.fill, i.stroke));
|
||||
crate::rtl::label(ui, format!("X: {} Y: {}", f(i.page_rect.x0), f(i.page_rect.y0)));
|
||||
crate::rtl::label(ui, format!("W: {} H: {}", f(i.page_rect.width()), f(i.page_rect.height())));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
format!("{}: {} {}: {}", crate::i18n::tr(&app.ui.language, "Fill"), i.fill, crate::i18n::tr(&app.ui.language, "Stroke"), i.stroke),
|
||||
);
|
||||
}
|
||||
None => {
|
||||
if let Some(st) = app.session.active() {
|
||||
ui.label(format!("{} pages · {} stories · {} items", st.doc.page_count(), st.doc.stories.len(), st.doc.all_items().len()));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
format!(
|
||||
"{} {} · {} {} · {} {}",
|
||||
st.doc.page_count(),
|
||||
crate::i18n::tr(&app.ui.language, "pages"),
|
||||
st.doc.stories.len(),
|
||||
crate::i18n::tr(&app.ui.language, "stories"),
|
||||
st.doc.all_items().len(),
|
||||
crate::i18n::tr(&app.ui.language, "items")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ui.label(egui::RichText::new(format!("Render {:.1} ms", app.perf.render_ms)).color(t.text_dim));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(format!("{} {:.1} ms", crate::i18n::tr(&app.ui.language, "Render"), app.perf.render_ms)).color(t.text_dim),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn effects_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
@@ -1860,14 +1961,17 @@ pub fn effects_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
B::Luminosity,
|
||||
];
|
||||
ui.horizontal(|ui| {
|
||||
egui::ComboBox::from_id_salt("blend").selected_text(it.blend.label()).width(130.0).show_ui(ui, |ui| {
|
||||
for m in MODES {
|
||||
if ui.selectable_label(m == it.blend, m.label()).clicked() {
|
||||
let _ = app.run("object.opacity", json!({"opacity": it.opacity, "blend": m}));
|
||||
egui::ComboBox::from_id_salt("blend")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, it.blend.label())))
|
||||
.width(130.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for m in MODES {
|
||||
if ui.selectable_label(m == it.blend, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, m.label()))).clicked() {
|
||||
let _ = app.run("object.opacity", json!({"opacity": it.opacity, "blend": m}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
caption(ui, "Opacity");
|
||||
});
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Opacity"));
|
||||
if let Some(v) = number(ui, "eop", Some(it.opacity as f64 * 100.0), "%", 46.0, 0) {
|
||||
let _ = app.run("object.opacity", json!({"opacity": (v / 100.0).clamp(0.0, 1.0)}));
|
||||
}
|
||||
@@ -1880,11 +1984,11 @@ pub fn effects_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
if ds.on {
|
||||
egui::Grid::new("dsg").num_columns(4).spacing(vec2(6.0, 4.0)).show(ui, |ui| {
|
||||
caption(ui, "Distance");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Distance"));
|
||||
if let Some(v) = number(ui, "dsd", Some(ds.distance), " pt", 56.0, 1) {
|
||||
let _ = app.run("object.dropShadow", json!({"on": true, "distance": v}));
|
||||
}
|
||||
caption(ui, "Angle");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Angle"));
|
||||
let global = app.session.active().map_or(120.0, |st| st.doc.settings.global_light);
|
||||
if let Some(v) = number(ui, "dsa", Some(if ds.global_light { global } else { ds.angle }), "°", 50.0, 0) {
|
||||
// With Use Global Light on, the angle is the document's (every such shadow moves).
|
||||
@@ -1895,19 +1999,19 @@ pub fn effects_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
};
|
||||
}
|
||||
ui.end_row();
|
||||
ui.label("");
|
||||
ui.label("");
|
||||
crate::rtl::label(ui, "");
|
||||
crate::rtl::label(ui, "");
|
||||
caption(ui, "");
|
||||
let mut gl = ds.global_light;
|
||||
if ui.checkbox(&mut gl, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Use Global Light"))).changed() {
|
||||
let _ = app.run("object.dropShadow", json!({"on": true, "globalLight": gl}));
|
||||
}
|
||||
ui.end_row();
|
||||
caption(ui, "Opacity");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Opacity"));
|
||||
if let Some(v) = number(ui, "dso", Some(ds.opacity as f64 * 100.0), "%", 56.0, 0) {
|
||||
let _ = app.run("object.dropShadow", json!({"on": true, "opacity": v / 100.0}));
|
||||
}
|
||||
caption(ui, "Size");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Size"));
|
||||
if let Some(v) = number(ui, "dss", Some(ds.size), " pt", 50.0, 1) {
|
||||
let _ = app.run("object.dropShadow", json!({"on": true, "size": v}));
|
||||
}
|
||||
@@ -1927,7 +2031,19 @@ pub fn preflight_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
4.5,
|
||||
if errors == 0 { egui::Color32::from_rgb(60, 200, 90) } else { egui::Color32::from_rgb(235, 50, 50) },
|
||||
);
|
||||
ui.label(if issues.is_empty() { "No errors".to_string() } else { format!("{errors} error(s), {} warning(s)", issues.len() - errors) });
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
if issues.is_empty() {
|
||||
crate::i18n::tr(&app.ui.language, "No errors").to_string()
|
||||
} else {
|
||||
format!(
|
||||
"{errors} {}, {} {}",
|
||||
crate::i18n::tr(&app.ui.language, "errors"),
|
||||
issues.len() - errors,
|
||||
crate::i18n::tr(&app.ui.language, "warnings")
|
||||
)
|
||||
},
|
||||
);
|
||||
});
|
||||
divider(ui);
|
||||
for i in issues {
|
||||
@@ -1935,7 +2051,7 @@ pub fn preflight_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let text = format!("{} {}", if i.severity == "error" { "⛔" } else { "⚠" }, i.message);
|
||||
let resp = ui.add(egui::Button::new(egui::RichText::new(text).size(11.0)).frame(false));
|
||||
if let Some(pg) = &page {
|
||||
ui.label(egui::RichText::new(format!(" page {pg}")).size(10.0).color(t.text_dim));
|
||||
crate::rtl::label(ui, egui::RichText::new(format!(" page {pg}")).size(10.0).color(t.text_dim));
|
||||
}
|
||||
if resp.clicked() {
|
||||
if let Some(id) = i.item {
|
||||
@@ -1963,7 +2079,7 @@ pub fn attributes_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
egui::Grid::new("attributes_panel").num_columns(2).spacing(vec2(16.0, 6.0)).show(ui, |ui| {
|
||||
for (i, (key, label, on)) in rows.into_iter().enumerate() {
|
||||
let mut v = on;
|
||||
if ui.checkbox(&mut v, label).changed() {
|
||||
if ui.checkbox(&mut v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).changed() {
|
||||
let _ = app.run("object.attributes", json!({ key: v }));
|
||||
}
|
||||
if i % 2 == 1 {
|
||||
|
||||
@@ -17,10 +17,11 @@ fn list(app: &mut DesignApp, ui: &mut egui::Ui, para: bool) {
|
||||
let attrs = super::text_attrs(app);
|
||||
let current = attrs.as_ref().and_then(|a| a[if para { "paragraphStyle" } else { "characterStyle" }].as_str().map(str::to_string));
|
||||
let overrides = attrs.as_ref().map(|a| a[if para { "paraOverrides" } else { "charOverrides" }].as_u64().unwrap_or(0)).unwrap_or(0);
|
||||
ui.label(
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(match ¤t {
|
||||
Some(c) => format!("{c}{}", if overrides > 0 { "+" } else { "" }),
|
||||
None => "No text selected".into(),
|
||||
Some(c) => format!("{}{}", crate::i18n::style_name(&app.ui.language, c), if overrides > 0 { "+" } else { "" }),
|
||||
None => crate::i18n::tr(&app.ui.language, "No text selected").into(),
|
||||
})
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
@@ -52,7 +53,15 @@ fn list(app: &mut DesignApp, ui: &mut egui::Ui, para: bool) {
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "⌥-click clears overrides")).size(10.5).color(t.text_disabled),
|
||||
));
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if icons::button(ui, "plus", 20.0, false, "Create New Style from Selection").clicked() {
|
||||
if icons::button(
|
||||
ui,
|
||||
"plus",
|
||||
20.0,
|
||||
false,
|
||||
crate::i18n::tr(&app.ui.language, crate::i18n::tr(&app.ui.language, "Create New Style from Selection")),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
let cmd = if para { "style.paragraph.create" } else { "style.character.create" };
|
||||
let base = if para { "Paragraph Style 1" } else { "Character Style 1" };
|
||||
let _ = app.run(cmd, json!({"name": base, "fromSelection": true}));
|
||||
@@ -79,7 +88,14 @@ fn style_row(app: &mut DesignApp, ui: &mut egui::Ui, para: bool, n: &str, curren
|
||||
ui.painter().rect_filled(row, 0.0, t.hover);
|
||||
}
|
||||
let shown = n.rsplit('/').next().unwrap_or(n);
|
||||
ui.painter().text(row.min + vec2(8.0, 11.0), egui::Align2::LEFT_CENTER, shown, egui::FontId::proportional(12.5), t.text);
|
||||
crate::rtl::paint(
|
||||
ui.painter(),
|
||||
row.min + vec2(8.0, 11.0),
|
||||
egui::Align2::LEFT_CENTER,
|
||||
if n.contains('/') { shown } else { crate::i18n::style_name(&app.ui.language, shown) },
|
||||
egui::FontId::proportional(12.5),
|
||||
t.text,
|
||||
);
|
||||
if resp.double_clicked() && para {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("paragraphStyleOptions", json!({"name": n})));
|
||||
} else if resp.clicked() {
|
||||
@@ -89,7 +105,17 @@ fn style_row(app: &mut DesignApp, ui: &mut egui::Ui, para: bool, n: &str, curren
|
||||
}
|
||||
let kind = if para { "paragraph" } else { "character" };
|
||||
resp.context_menu(|ui| {
|
||||
if ui.button(format!("Apply \"{shown}\"")).clicked() {
|
||||
if ui
|
||||
.button(crate::rtl::widget(
|
||||
ui,
|
||||
format!(
|
||||
"{} \"{}\"",
|
||||
crate::i18n::tr(&app.ui.language, "Apply"),
|
||||
if n.contains('/') { shown } else { crate::i18n::style_name(&app.ui.language, shown) }
|
||||
),
|
||||
))
|
||||
.clicked()
|
||||
{
|
||||
let cmd = if para { "style.paragraph.apply" } else { "style.character.apply" };
|
||||
let _ = app.run(cmd, json!({"name": n}));
|
||||
ui.close();
|
||||
@@ -113,7 +139,11 @@ fn style_row(app: &mut DesignApp, ui: &mut egui::Ui, para: bool, n: &str, curren
|
||||
ui.separator();
|
||||
let id = egui::Id::new(("new_style_group", para));
|
||||
let mut name: String = ui.data(|d| d.get_temp(id)).unwrap_or_default();
|
||||
let r = ui.add(egui::TextEdit::singleline(&mut name).hint_text("New group…").desired_width(140.0));
|
||||
let r = ui.add(
|
||||
egui::TextEdit::singleline(&mut name)
|
||||
.hint_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New group…")))
|
||||
.desired_width(140.0),
|
||||
);
|
||||
if r.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) && !name.trim().is_empty() {
|
||||
let _ = app.run("style.group", json!({"kind": kind, "names": [n], "group": name.trim()}));
|
||||
name.clear();
|
||||
|
||||
@@ -14,7 +14,12 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let text = st.selection.text.is_some();
|
||||
let fill_cur = super::sel_info(app).map(|i| i.fill);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(egui::RichText::new(if text { "Applies to text" } else { "Applies to fill" }).size(11.0).color(t.text_dim));
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, if text { "Applies to text" } else { "Applies to fill" }))
|
||||
.size(11.0)
|
||||
.color(t.text_dim),
|
||||
);
|
||||
});
|
||||
// Unnamed colours (mixed in the Color panel) aren't listed until Add to Swatches; swatches in
|
||||
// colour groups are listed under their folder.
|
||||
@@ -65,7 +70,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "Right-click: stroke, groups")).size(10.5).color(t.text_disabled),
|
||||
));
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if icons::button(ui, "plus", 20.0, false, "New Swatch").clicked() {
|
||||
if icons::button(ui, "plus", 20.0, false, crate::i18n::tr(&app.ui.language, "New Swatch")).clicked() {
|
||||
let _ = app.run("swatch.create", json!({"color": {"c": 0, "m": 50, "y": 100, "k": 0}}));
|
||||
}
|
||||
ui.menu_button("☰", |ui| {
|
||||
@@ -308,7 +313,7 @@ pub fn color_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
spectrum(app, ui, target);
|
||||
ui.horizontal(|ui| {
|
||||
let unnamed = sw.as_ref().is_some_and(|w| w.hidden);
|
||||
if ui.add_enabled(unnamed, egui::Button::new("Add to Swatches")).clicked() {
|
||||
if ui.add_enabled(unnamed, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Add to Swatches")))).clicked() {
|
||||
let _ = app.run("swatch.addToSwatches", json!({"target": target}));
|
||||
}
|
||||
});
|
||||
@@ -413,15 +418,24 @@ pub fn gradient_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
};
|
||||
let radial = g.kind == designcraft_color::GradientKind::Radial;
|
||||
ui.horizontal(|ui| {
|
||||
crate::widgets::caption(ui, "Type:");
|
||||
egui::ComboBox::from_id_salt("grad_type").selected_text(g.kind.label()).width(100.0).show_ui(ui, |ui| {
|
||||
for (k, v) in [("Linear", "linear"), ("Radial", "radial")] {
|
||||
if ui.selectable_label(g.kind.label() == k, k).clicked() {
|
||||
let _ = app.run("object.gradient", json!({"kind": v}));
|
||||
crate::widgets::caption(ui, crate::i18n::tr(&app.ui.language, "Type:"));
|
||||
egui::ComboBox::from_id_salt("grad_type")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, g.kind.label())))
|
||||
.width(100.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (k, v) in [("Linear", "linear"), ("Radial", "radial")] {
|
||||
if ui.selectable_label(g.kind.label() == k, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, k))).clicked() {
|
||||
let _ = app.run("object.gradient", json!({"kind": v}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Reverse"))).on_hover_text("Reverse the gradient").clicked() {
|
||||
});
|
||||
if ui
|
||||
.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Reverse")))
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Reverse the gradient"));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
let _ = app.run("object.gradient", json!({"reverse": true}));
|
||||
}
|
||||
});
|
||||
@@ -429,7 +443,7 @@ pub fn gradient_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let drag_id = egui::Id::new("grad_drag");
|
||||
let mut sel: usize = ui.data(|d| d.get_temp(sel_id)).unwrap_or(0).min(g.stops.len().saturating_sub(1));
|
||||
ui.horizontal(|ui| {
|
||||
crate::widgets::caption(ui, "Location:");
|
||||
crate::widgets::caption(ui, crate::i18n::tr(&app.ui.language, "Location:"));
|
||||
let loc = g.stops.get(sel).map(|s| s.offset as f64 * 100.0);
|
||||
if let Some(v) = crate::widgets::number(ui, "grad_loc", loc, " %", 54.0, 1) {
|
||||
let mut stops = stops_json(&g);
|
||||
@@ -437,7 +451,7 @@ pub fn gradient_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let _ = app.run("object.gradient", json!({"stops": stops}));
|
||||
}
|
||||
if !radial {
|
||||
crate::widgets::caption(ui, "Angle:");
|
||||
crate::widgets::caption(ui, crate::i18n::tr(&app.ui.language, "Angle:"));
|
||||
let angle = fill.gradient_vector.map(|[x0, y0, x1, y1]| (-(y1 - y0)).atan2(x1 - x0).to_degrees()).or(fill.gradient_angle).unwrap_or(0.0);
|
||||
if let Some(v) = crate::widgets::number(ui, "grad_angle", Some(angle), "°", 54.0, 1) {
|
||||
let _ = app.run("object.gradient", json!({"angle": v}));
|
||||
@@ -546,7 +560,7 @@ pub fn gradient_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// The selected stop's colour.
|
||||
if let Some(s) = g.stops.get(sel) {
|
||||
ui.horizontal(|ui| {
|
||||
crate::widgets::caption(ui, "Stop Color:");
|
||||
crate::widgets::caption(ui, crate::i18n::tr(&app.ui.language, "Stop Color:"));
|
||||
let [r, gg, bb] = s.color.to_rgb();
|
||||
let mut rgb = [(r * 255.0) as u8, (gg * 255.0) as u8, (bb * 255.0) as u8];
|
||||
if egui::color_picker::color_edit_button_srgb(ui, &mut rgb).changed() {
|
||||
|
||||
@@ -32,19 +32,19 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let _ = app.run(id, p);
|
||||
};
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Cell Type");
|
||||
if ui.small_button("Graphic…").clicked()
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Cell Type"));
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Graphic…"))).clicked()
|
||||
&& let Err(e) = app.run("app.graphicCell", json!({}))
|
||||
{
|
||||
app.status(format!("Table: {e}"));
|
||||
}
|
||||
if ui.small_button("Text").clicked() {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Text"))).clicked() {
|
||||
let _ = app.run("table.textCell", json!({}));
|
||||
}
|
||||
});
|
||||
// Move the target row / column (InDesign drags them).
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Move");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Move"));
|
||||
let (nr, nc) = (rows.len(), cols.len());
|
||||
for (label, id, from, to, ok) in [
|
||||
("Row ↑", "table.moveRow", r0, r0.saturating_sub(1), r0 > 0),
|
||||
@@ -68,7 +68,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
let ccur = cell["style"].as_str().filter(|s| !s.is_empty()).unwrap_or(designcraft_doc::NO_CELL_STYLE).to_string();
|
||||
for (label, kind, names, cur) in [("Table Style", "table", tnames, tcur), ("Cell Style", "cell", cnames, ccur)] {
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, label);
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, label));
|
||||
egui::ComboBox::from_id_salt(("tp_style", kind)).selected_text(&cur).width(130.0).show_ui(ui, |ui| {
|
||||
for n in &names {
|
||||
if ui.selectable_label(*n == cur, n).clicked() {
|
||||
@@ -87,7 +87,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
}
|
||||
egui::Grid::new("table_panel").num_columns(4).spacing([6.0, 6.0]).show(ui, |ui| {
|
||||
caption(ui, "Rows");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Rows"));
|
||||
if let Some(v) = number(ui, "tp_rows", Some(rows.len() as f64), "", 52.0, 0) {
|
||||
let n = v.round().max(1.0) as usize;
|
||||
if n > rows.len() {
|
||||
@@ -100,7 +100,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
run(app, "table.deleteRow", json!({"table": tid, "rows": [n, rows.len() - 1]}));
|
||||
}
|
||||
}
|
||||
caption(ui, "Columns");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Columns"));
|
||||
if let Some(v) = number(ui, "tp_cols", Some(cols.len() as f64), "", 52.0, 0) {
|
||||
let n = v.round().max(1.0) as usize;
|
||||
if n > cols.len() {
|
||||
@@ -116,19 +116,23 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.end_row();
|
||||
let row = rows.get(r0).cloned().unwrap_or(Value::Null);
|
||||
let exactly = row["mode"] == "exactly";
|
||||
caption(ui, "Row Height");
|
||||
egui::ComboBox::from_id_salt("tp_rowmode").selected_text(if exactly { "Exactly" } else { "At Least" }).width(70.0).show_ui(ui, |ui| {
|
||||
for (label, mode) in [("At Least", "atLeast"), ("Exactly", "exactly")] {
|
||||
if ui.selectable_label((mode == "exactly") == exactly, label).clicked() {
|
||||
run(app, "table.setRowHeight", json!({"mode": mode}));
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Row Height"));
|
||||
egui::ComboBox::from_id_salt("tp_rowmode")
|
||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if exactly { "Exactly" } else { "At Least" })))
|
||||
.width(70.0)
|
||||
.show_ui(ui, |ui| {
|
||||
for (label, mode) in [("At Least", "atLeast"), ("Exactly", "exactly")] {
|
||||
if ui.selectable_label((mode == "exactly") == exactly, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked()
|
||||
{
|
||||
run(app, "table.setRowHeight", json!({"mode": mode}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if let Some(h) = measure(ui, "tp_rowh", row["height"].as_f64(), unit, 64.0) {
|
||||
run(app, "table.setRowHeight", json!({"height": h}));
|
||||
}
|
||||
ui.end_row();
|
||||
caption(ui, "Column Width");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Column Width"));
|
||||
ui.label("");
|
||||
if let Some(w) = measure(ui, "tp_colw", cols.get(c0).and_then(|c| c["width"].as_f64()), unit, 64.0) {
|
||||
run(app, "table.setColumnWidth", json!({"width": w}));
|
||||
@@ -136,10 +140,10 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
ui.end_row();
|
||||
});
|
||||
divider(ui);
|
||||
caption(ui, "Cell Text");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Cell Text"));
|
||||
ui.horizontal(|ui| {
|
||||
for (label, vj) in [("Top", "top"), ("Center", "center"), ("Bottom", "bottom"), ("Justify", "justify")] {
|
||||
if ui.selectable_label(cell["vj"] == vj, label).clicked() {
|
||||
if ui.selectable_label(cell["vj"] == vj, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
run(app, "table.setCell", json!({"vj": vj}));
|
||||
}
|
||||
}
|
||||
@@ -149,7 +153,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
egui::Grid::new("table_insets").num_columns(4).spacing([6.0, 6.0]).show(ui, |ui| {
|
||||
let labels = ["Top", "Left", "Bottom", "Right"];
|
||||
for (i, l) in labels.iter().enumerate() {
|
||||
caption(ui, l);
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, l));
|
||||
if let Some(v) = measure(ui, &format!("tp_inset{i}"), insets.get(i).copied(), unit, 56.0) {
|
||||
let mut n = insets.clone();
|
||||
n.resize(4, 4.0);
|
||||
@@ -197,11 +201,11 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
run(app, "table.options", json!({"repeatHeader": rep}));
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
caption(ui, "Header Rows");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Header Rows"));
|
||||
if let Some(v) = number(ui, "tp_hdr", info["headerRows"].as_f64(), "", 40.0, 0) {
|
||||
run(app, "table.options", json!({"headerRows": v.max(0.0) as u64}));
|
||||
}
|
||||
caption(ui, "Footer Rows");
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Footer Rows"));
|
||||
if let Some(v) = number(ui, "tp_ftr", info["footerRows"].as_f64(), "", 40.0, 0) {
|
||||
run(app, "table.options", json!({"footerRows": v.max(0.0) as u64}));
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
for (i, r) in story.para_ranges().iter().enumerate() {
|
||||
let lines = story.text[r.clone()].len() / 60 + 1;
|
||||
let style = &story.paras[i].style;
|
||||
ui.label(egui::RichText::new(style).size(11.0).color(t.text_dim));
|
||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::style_name(&app.ui.language, style)).size(11.0).color(t.text_dim));
|
||||
for _ in 1..lines {
|
||||
ui.label(egui::RichText::new(" ").size(11.0));
|
||||
}
|
||||
@@ -70,9 +70,13 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
ui,
|
||||
egui::RichText::new(crate::i18n::tr(&app.ui.language, "OVERSET")).color(egui::Color32::from_rgb(230, 40, 40)).strong(),
|
||||
));
|
||||
ui.label(
|
||||
egui::RichText::new(format!("{} characters don't fit", story.text[o.min(story.text.len())..].chars().count()))
|
||||
.color(t.text_dim),
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
egui::RichText::new(
|
||||
crate::i18n::tr(&app.ui.language, "{count} characters don't fit")
|
||||
.replace("{count}", &story.text[o.min(story.text.len())..].chars().count().to_string()),
|
||||
)
|
||||
.color(t.text_dim),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context, sel: Rect, canvas: Rect) {
|
||||
|
||||
fn split_button(ui: &mut Ui, icon: &str, label: &str) -> (egui::Response, egui::Response) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let g = ui.painter().layout_no_wrap(label.to_string(), egui::FontId::proportional(11.0), t.text);
|
||||
let g = crate::rtl::plain(ui.ctx(), label, egui::FontId::proportional(11.0), t.text);
|
||||
let w = 26.0 + g.size().x + 8.0 + widgets::SEG_W;
|
||||
let (r, _) = ui.allocate_exact_size(vec2(w, FIELD_H), Sense::hover());
|
||||
let main = Rect::from_min_max(r.min, pos2(r.max.x - widgets::SEG_W, r.max.y));
|
||||
@@ -84,7 +84,7 @@ fn split_button(ui: &mut Ui, icon: &str, label: &str) -> (egui::Response, egui::
|
||||
fn text_controls(app: &mut DesignApp, ui: &mut Ui, in_text: bool) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
if !in_text {
|
||||
let (main, seg) = split_button(ui, "fit-text", "Fit Text");
|
||||
let (main, seg) = split_button(ui, "fit-text", crate::i18n::tr(&app.ui.language, "Fit Text"));
|
||||
if main
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Fit frame height to text"));
|
||||
@@ -95,7 +95,7 @@ fn text_controls(app: &mut DesignApp, ui: &mut Ui, in_text: bool) {
|
||||
}
|
||||
egui::Popup::menu(&seg).show(|ui| {
|
||||
for (label, v) in [("Off", "off"), ("Height Only", "heightOnly"), ("Width Only", "widthOnly"), ("Height and Width", "heightAndWidth")] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("object.textFrameOptions", json!({"autoSize": v}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -155,7 +155,7 @@ fn text_controls(app: &mut DesignApp, ui: &mut Ui, in_text: bool) {
|
||||
"leftJustified" | "centerJustified" | "rightJustified" | "fullyJustified" => "palign-justify-left",
|
||||
_ => "palign-left",
|
||||
};
|
||||
let resp = widgets::icon_toggle(ui, icon, false, "Paragraph alignment");
|
||||
let resp = widgets::icon_toggle(ui, icon, false, crate::i18n::tr(&app.ui.language, "Paragraph alignment"));
|
||||
egui::Popup::menu(&resp).show(|ui| {
|
||||
for (label, v) in [
|
||||
("Align Left", "left"),
|
||||
@@ -164,13 +164,13 @@ fn text_controls(app: &mut DesignApp, ui: &mut Ui, in_text: bool) {
|
||||
("Justify", "leftJustified"),
|
||||
("Justify All", "fullyJustified"),
|
||||
] {
|
||||
if ui.selectable_label(al == v, label).clicked() {
|
||||
if ui.selectable_label(al == v, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("type.para", json!({"attrs": {"align": v}}));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
if widgets::icon_toggle(ui, "frame-options", false, "Text Frame Options").clicked() {
|
||||
if widgets::icon_toggle(ui, "frame-options", false, crate::i18n::tr(&app.ui.language, "Text Frame Options")).clicked() {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("textFrameOptions", json!({})));
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ fn object_controls(app: &mut DesignApp, ui: &mut Ui) {
|
||||
("fit-frame", "fitFrameToContent", "Fit Frame to Content"),
|
||||
("fit-center", "centerContent", "Center Content"),
|
||||
] {
|
||||
if widgets::icon_toggle(ui, icon, false, tip).clicked() {
|
||||
if widgets::icon_toggle(ui, icon, false, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run("object.fit", json!({"mode": mode}));
|
||||
}
|
||||
}
|
||||
@@ -221,11 +221,11 @@ fn object_controls(app: &mut DesignApp, ui: &mut Ui) {
|
||||
}
|
||||
sep(ui);
|
||||
for (cmd, icon, tip) in [("object.bringToFront", "objalign-top", "Bring to Front"), ("object.sendToBack", "objalign-bottom", "Send to Back")] {
|
||||
if widgets::icon_toggle(ui, icon, false, tip).clicked() {
|
||||
if widgets::icon_toggle(ui, icon, false, crate::i18n::tr(&app.ui.language, tip)).clicked() {
|
||||
let _ = app.run(cmd, json!({}));
|
||||
}
|
||||
}
|
||||
if i.count > 1 && widgets::outline_button(ui, "Group", 52.0).clicked() {
|
||||
if i.count > 1 && widgets::outline_button(ui, crate::i18n::tr(&app.ui.language, "Group"), 52.0).clicked() {
|
||||
let _ = app.run("object.group", json!({}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,14 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
// Collapse chevrons.
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(width / 2.0 - 8.0);
|
||||
if icons::button(ui, if cols == 1 { "double-chevron-right" } else { "double-chevron-left" }, 16.0, false, "Toggle double column")
|
||||
.clicked()
|
||||
if icons::button(
|
||||
ui,
|
||||
if cols == 1 { "double-chevron-right" } else { "double-chevron-left" },
|
||||
16.0,
|
||||
false,
|
||||
crate::i18n::tr(&app.ui.language, "Toggle double column"),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
app.ui.tools_double_column = !app.ui.tools_double_column;
|
||||
}
|
||||
@@ -266,7 +272,13 @@ fn fill_stroke_proxy(app: &mut DesignApp, ui: &mut egui::Ui, width: f32) {
|
||||
ui.painter().rect(r, 1.5, t.well, Stroke::new(1.0, t.well_rim), StrokeKind::Inside);
|
||||
}
|
||||
icons::paint(ui.painter(), r.shrink(1.5), icon, if on { t.text_strong } else { t.icon });
|
||||
if ui.interact(r, ui.id().with(("proxy_fmt", k)), Sense::click()).on_hover_text(tip).clicked() {
|
||||
if ui
|
||||
.interact(r, ui.id().with(("proxy_fmt", k)), Sense::click())
|
||||
.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, tip));
|
||||
})
|
||||
.clicked()
|
||||
{
|
||||
ui.data_mut(|d| d.insert_temp(text_id, k == 1));
|
||||
}
|
||||
}
|
||||
@@ -287,7 +299,7 @@ fn fill_stroke_proxy(app: &mut DesignApp, ui: &mut egui::Ui, width: f32) {
|
||||
}
|
||||
egui::Popup::context_menu(&resp).show(|ui| {
|
||||
for (label, sw) in [("Apply Color", "[Black]"), ("Apply None", "[None]")] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run(target, json!({"swatch": sw}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -297,7 +309,7 @@ fn fill_stroke_proxy(app: &mut DesignApp, ui: &mut egui::Ui, width: f32) {
|
||||
separator(ui, &t);
|
||||
// Utility (frame options).
|
||||
ui.vertical_centered(|ui| {
|
||||
if tool_button(ui, "frame-options", false, "Text Frame Options").clicked() {
|
||||
if tool_button(ui, "frame-options", false, crate::i18n::tr(&app.ui.language, "Text Frame Options")).clicked() {
|
||||
app.ui.dialog = Some(crate::dialogs::Dialog::new("textFrameOptions", json!({})));
|
||||
}
|
||||
});
|
||||
@@ -315,13 +327,15 @@ fn fill_stroke_proxy(app: &mut DesignApp, ui: &mut egui::Ui, width: f32) {
|
||||
t.text_strong,
|
||||
);
|
||||
flyout_triangle(ui.painter(), well, t.icon);
|
||||
let resp = resp.on_hover_text(if preview { "Preview (W)" } else { "Normal (W)" });
|
||||
let resp = resp.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, if preview { "Preview (W)" } else { "Normal (W)" }));
|
||||
});
|
||||
if resp.clicked() {
|
||||
let _ = app.run("view.togglePreview", json!({}));
|
||||
}
|
||||
egui::Popup::context_menu(&resp).show(|ui| {
|
||||
for (label, mode) in [("Normal", "normal"), ("Preview", "preview"), ("Bleed", "bleed"), ("Slug", "slug"), ("Presentation", "presentation")] {
|
||||
if ui.button(label).clicked() {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
let _ = app.run("view.screenMode", json!({"mode": mode}));
|
||||
ui.close();
|
||||
}
|
||||
@@ -356,5 +370,7 @@ fn tool_button(ui: &mut egui::Ui, icon: &str, active: bool, tip: &str) -> egui::
|
||||
ui.painter().rect_filled(egui::Rect::from_center_size(r.center(), egui::vec2(28.0, 20.0)), 2.0, t.hover);
|
||||
}
|
||||
icons::paint(ui.painter(), egui::Rect::from_center_size(r.center(), egui::vec2(17.0, 17.0)), icon, if active { t.text_strong } else { t.icon });
|
||||
resp.on_hover_text(tip)
|
||||
resp.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, tip);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ pub fn link_label(ui: &mut Ui, text: &str, width: f32) -> Response {
|
||||
}
|
||||
|
||||
/// `•••` more-options, right-aligned on its own row at the bottom of a section.
|
||||
pub fn more_options(ui: &mut Ui) -> Response {
|
||||
pub fn more_options(ui: &mut Ui, language: &str) -> Response {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let (row, _) = ui.allocate_exact_size(vec2(ui.available_width(), 14.0), Sense::hover());
|
||||
let r = Rect::from_min_max(pos2(row.max.x - 26.0, row.min.y), pos2(row.max.x - 4.0, row.max.y));
|
||||
@@ -367,7 +367,9 @@ pub fn more_options(ui: &mut Ui) -> Response {
|
||||
for i in 0..3 {
|
||||
ui.painter().circle_filled(pos2(r.min.x + 4.0 + i as f32 * 7.0, r.center().y), 1.9, if resp.hovered() { t.text_strong } else { t.icon });
|
||||
}
|
||||
resp.on_hover_text("More Options")
|
||||
resp.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, crate::i18n::tr(language, "More Options"));
|
||||
})
|
||||
}
|
||||
|
||||
/// A small dim label (field captions like `X:` or `W:`).
|
||||
@@ -514,7 +516,13 @@ pub fn icon_toggle_sized(ui: &mut Ui, icon: &str, on: bool, tip: &str, size: egu
|
||||
}
|
||||
let s = (size.y - 4.0).min(17.0);
|
||||
crate::icons::paint(ui.painter(), Rect::from_center_size(r.center(), vec2(s, s)), icon, if on { t.text_strong } else { t.icon });
|
||||
if tip.is_empty() { resp } else { resp.on_hover_text(tip) }
|
||||
if tip.is_empty() {
|
||||
resp
|
||||
} else {
|
||||
resp.on_hover_ui(|ui| {
|
||||
crate::rtl::label(ui, tip);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An InDesign checkbox: 12 pt rounded box, white check, label.
|
||||
@@ -552,7 +560,7 @@ pub fn segmented(ui: &mut Ui, labels: &[&str], active: usize, width: f32) -> Opt
|
||||
} else if resp.hovered() {
|
||||
ui.painter().rect_filled(sr, 0.0, t.hover);
|
||||
}
|
||||
ui.painter().text(sr.center(), egui::Align2::CENTER_CENTER, *l, label_font(), if i == active { t.accent } else { t.text });
|
||||
crate::rtl::paint(ui.painter(), sr.center(), egui::Align2::CENTER_CENTER, l, label_font(), if i == active { t.accent } else { t.text });
|
||||
if i > 0 {
|
||||
ui.painter().line_segment([sr.left_top(), sr.left_bottom()], Stroke::new(1.0, t.field_border));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user