mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
M1: merge main and complete Turkish artwork drag translations
Add the three Turkish catalog entries requested by the maintainer on #3479. Preserve upstream catalog additions and place existing tab-drag entries beside stable menu labels to avoid append conflicts. Update feature progress notes for all 24 catalogs. Simplify an equivalent Effect Gallery selection predicate required by the Rust 1.95 clippy gate. Full cargo xtask ci passed all 10 checks, including tab-drag regressions and wasm.
This commit is contained in:
@@ -154,6 +154,7 @@ pub const LANGUAGES: &[(&str, Quotes)] = &[
|
||||
("Polish", Quotes { double: ['„', '”'], single: ['‚', '’'] }),
|
||||
("Czech", Quotes { double: ['„', '“'], single: ['‚', '‘'] }),
|
||||
("Russian", Quotes { double: ['«', '»'], single: ['„', '“'] }),
|
||||
("Turkish", Quotes { double: ['“', '”'], single: ['‘', '’'] }),
|
||||
("Japanese", Quotes { double: ['「', '」'], single: ['『', '』'] }),
|
||||
("Chinese", Quotes { double: ['“', '”'], single: ['‘', '’'] }),
|
||||
];
|
||||
|
||||
+11
-1
@@ -1713,8 +1713,18 @@ impl TextObject {
|
||||
/// How far the characters' strokes paint past their glyphs, in document space: they scale
|
||||
/// with the type.
|
||||
pub fn char_stroke_outset(&self) -> f64 {
|
||||
self.char_strokes(CharStyle::stroke_outset)
|
||||
}
|
||||
/// How far the characters' strokes can paint past their glyphs, their miter spikes and square
|
||||
/// caps included ([`StrokeLayer::reach`]), in document space: what a change of the type must
|
||||
/// redraw. The visual bounds take [`Self::char_stroke_outset`].
|
||||
pub fn char_stroke_reach(&self) -> f64 {
|
||||
self.char_strokes(|style| if style.has_stroke() { style.stroke_layer().reach() } else { 0.0 })
|
||||
}
|
||||
/// The farthest `outset` of the characters' styles, scaled with the type.
|
||||
fn char_strokes(&self, outset: impl Fn(&CharStyle) -> f64) -> f64 {
|
||||
let k = crate::node::Scaling::factor(self.xf).unwrap_or(1.0);
|
||||
self.runs.iter().map(|r| r.style.stroke_outset()).fold(0.0, f64::max) * k
|
||||
self.runs.iter().map(|r| outset(&r.style)).fold(0.0, f64::max) * k
|
||||
}
|
||||
pub fn transform(&mut self, a: Affine) {
|
||||
self.xf = a * self.xf;
|
||||
|
||||
@@ -793,6 +793,17 @@ pub fn open_filters() -> impl Iterator<Item = (&'static str, &'static [&'static
|
||||
.chain(std::iter::once(("Plug-ins", super::plugin::EXTS)))
|
||||
}
|
||||
|
||||
/// Open-dialog filters for Swatch Libraries and Graphic Style Libraries Other Library… and Locate
|
||||
/// Library…. The library formats come first so Linux file portals (which grey out files that don't
|
||||
/// match the default filter) still list `.ase` and the other library extensions; then the same
|
||||
/// filters as [`open_filters`] so a document can be picked for its swatches or graphic styles.
|
||||
pub fn library_open_filters(
|
||||
library_label: &'static str,
|
||||
library_exts: &'static [&'static str],
|
||||
) -> impl Iterator<Item = (&'static str, &'static [&'static str])> {
|
||||
std::iter::once((library_label, library_exts)).chain(open_filters())
|
||||
}
|
||||
|
||||
/// File → Place dialog filters: "All placeable files", then one per placeable format, then text,
|
||||
/// RTF and Word.
|
||||
pub fn place_filters() -> impl Iterator<Item = (&'static str, &'static [&'static str])> {
|
||||
|
||||
@@ -384,6 +384,14 @@ fn open_exts_cover_every_readable_format() {
|
||||
assert_eq!(filters.last(), Some(&("Plug-ins", crate::cmd::plugin::EXTS)), "File › Open installs plug-ins");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn library_open_filters_list_library_formats_first() {
|
||||
let filters: Vec<_> = library_open_filters("Swatch libraries", super::swatchlib::LIBRARY_EXTS).collect();
|
||||
assert_eq!(filters[0], ("Swatch libraries", super::swatchlib::LIBRARY_EXTS));
|
||||
assert!(filters[0].1.contains(&"ase"));
|
||||
assert_eq!(filters[1], ("All readable files", OPEN_EXTS));
|
||||
}
|
||||
|
||||
/// The extensions usage texts list for export: one per writable format, each picking that format
|
||||
/// (`.png` picks PNG; PNG-8 is asked for by `format`).
|
||||
#[test]
|
||||
|
||||
@@ -159,9 +159,10 @@ fn expanded_art_keeps_the_random_transforms_the_canvas_drew() {
|
||||
assert_eq!(differ, RANDOM_CASES.map(|case| (case, 0)));
|
||||
}
|
||||
|
||||
/// The reply lists each object whose appearance expanded once, by the id it has in the document.
|
||||
/// In "group copies" the two copies of the square share an id until Expand Appearance gives them
|
||||
/// ids of their own, and the reply names the group, then each copy by its new id.
|
||||
/// The reply lists each object whose appearance expanded once, by the id it has in the document,
|
||||
/// starting with the selected object. In "group copies" the two copies of the square share an id
|
||||
/// until Expand Appearance gives them ids of their own, and the reply names the group, then each
|
||||
/// copy by its new id.
|
||||
#[test]
|
||||
fn the_reply_names_each_expanded_copy_by_its_own_id() {
|
||||
for case in RANDOM_CASES {
|
||||
@@ -169,6 +170,7 @@ fn the_reply_names_each_expanded_copy_by_its_own_id() {
|
||||
let id = random_transforms(&mut s, case);
|
||||
let r = run(&mut s, "effect.expandAppearance", json!({}));
|
||||
let ids: Vec<u64> = r["ids"].as_array().unwrap().iter().map(|v| v.as_u64().unwrap()).collect();
|
||||
assert_eq!(ids.first(), Some(&id.0), "{case}: {ids:?}");
|
||||
let unique: std::collections::HashSet<_> = ids.iter().collect();
|
||||
assert_eq!(unique.len(), ids.len(), "{case}: {ids:?}");
|
||||
assert!(ids.iter().all(|&i| s.doc().unwrap().doc.node(NodeId(i)).is_some()), "{case}: {ids:?}");
|
||||
|
||||
@@ -489,11 +489,12 @@ fn cull_bounds_in(symbols: &SymbolBoxes, n: &Node, after_reshape: bool) -> Optio
|
||||
}
|
||||
|
||||
/// The box of type `t`'s glyphs as laid out (its layout bounds, else laid out now), grown by its
|
||||
/// characters' strokes and by `outset`: on a path they stand above it and run past its ends, in an
|
||||
/// area they can hang past its frame, where its own box ([`Node::visual_bounds_with`]) doesn't.
|
||||
/// characters' strokes, miter spikes included, and by `outset`: on a path they stand above it and
|
||||
/// run past its ends, in an area they can hang past its frame, where its own box
|
||||
/// ([`Node::visual_bounds_with`]) doesn't.
|
||||
fn glyphs_box(t: &vectorcraft_doc::TextObject, outset: f64) -> Option<Rect> {
|
||||
let b = t.cached_bounds.unwrap_or_else(|| vectorcraft_text::layout(vectorcraft_text::FontDb::global(), t).bounds);
|
||||
let o = outset.max(t.char_stroke_outset());
|
||||
let o = outset.max(t.char_stroke_reach());
|
||||
(b.width() > 0.0 || b.height() > 0.0).then(|| t.xf.transform_rect_bbox(b).inflate(o, o))
|
||||
}
|
||||
|
||||
|
||||
@@ -192,6 +192,28 @@ fn reshaping_the_path_of_type_on_a_path_changes_where_its_letters_were_and_are()
|
||||
redraw(&old, &new);
|
||||
}
|
||||
|
||||
/// Stroked type with sharp corners: the miter spikes of its characters' strokes reach past half
|
||||
/// the weight, and change where they were and where they are.
|
||||
#[test]
|
||||
fn moving_type_with_mitred_strokes_changes_where_its_spikes_reach() {
|
||||
let mut old = Document::new(110.0, 80.0);
|
||||
let l = old.layers[0].id;
|
||||
let style = vectorcraft_doc::text::CharStyle {
|
||||
size: 30.0,
|
||||
stroke: Paint::solid(Color::BLACK),
|
||||
stroke_width: 10.0,
|
||||
stroke_join: vectorcraft_doc::LineJoin::Miter,
|
||||
stroke_miter_limit: 10.0,
|
||||
..Default::default()
|
||||
};
|
||||
let mut t = vectorcraft_doc::text::TextObject::point(Point::new(10.0, 50.0), "VAWV", style);
|
||||
t.cached_bounds = Some(vectorcraft_text::layout(vectorcraft_text::FontDb::global(), &t).bounds);
|
||||
let text = old.insert(Some(l), 0, Node::new(NodeId(0), NodeKind::Text(Box::new(t)))).unwrap();
|
||||
let mut new = old.clone();
|
||||
new.node_mut(text).unwrap().transform(Affine::translate((9.0, 7.0)), false);
|
||||
redraw(&old, &new);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_unchanged_document_changes_nothing_and_a_new_symbol_everything() {
|
||||
let (old, _) = document();
|
||||
|
||||
@@ -78,6 +78,7 @@ fn unit(d: &Dialog) -> Unit {
|
||||
Unit::named(&d.str("units")).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// The General tab of Document Setup (units, bleed, artboard editing, options).
|
||||
fn general(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
let units: Vec<(&str, &str)> = Unit::ALL.iter().map(|u| (u.label(), u.label())).collect();
|
||||
choice(ui, d, "units", tl!("Units:"), &units);
|
||||
@@ -88,7 +89,7 @@ fn general(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool
|
||||
let mut close = false;
|
||||
widgets::label_row(ui, "", LABEL, |ui| {
|
||||
// Applies the settings, then edits the artboards with the Artboard tool.
|
||||
if widgets::flat_button(ui, tl!("Edit Artboards"), 120.0).clicked() && confirm(app, d).is_ok() {
|
||||
if widgets::flat_button_fit(ui, tl!("Edit Artboards"), 120.0).clicked() && confirm(app, d).is_ok() {
|
||||
app.select_tool("artboard");
|
||||
// The shared frame restores its working copy after drawing the body. Tell it to
|
||||
// close too, otherwise it reopens the dialog that confirm just closed.
|
||||
|
||||
@@ -0,0 +1,478 @@
|
||||
//! Effect → Effect Gallery: browse Photoshop-style raster filters by category, build a stack, and
|
||||
//! apply it as separate appearance effects in one undo step.
|
||||
|
||||
use egui;
|
||||
use serde_json::{Map, Value, json};
|
||||
use vectorcraft_effects::{EffectInfo, PIXEL_EFFECTS};
|
||||
|
||||
use super::{DialogSpec, effect, form};
|
||||
use crate::state::Dialog;
|
||||
use crate::theme::Tokens;
|
||||
use crate::{VectorcraftApp, widgets};
|
||||
|
||||
/// Dialog kind for the Effect Gallery.
|
||||
pub const KIND: &str = "effectGallery";
|
||||
|
||||
/// Raster effect submenus in the gallery (the six Photoshop-style folders it holds).
|
||||
const CATEGORIES: [(&str, &[&str]); 6] = [
|
||||
("Artistic", &["Effect", "Artistic"]),
|
||||
("Brush Strokes", &["Effect", "Brush Strokes"]),
|
||||
("Distort", &["Effect", "Distort"]),
|
||||
("Sketch", &["Effect", "Sketch"]),
|
||||
("Stylize", &["Effect", "Stylize"]),
|
||||
("Texture", &["Effect", "Texture"]),
|
||||
];
|
||||
|
||||
pub(super) const SPEC: DialogSpec = DialogSpec {
|
||||
heading: |_| tl!("Effect Gallery").into(),
|
||||
body,
|
||||
confirm,
|
||||
preview: true,
|
||||
min_width: 720.0,
|
||||
max_width: Some(820.0),
|
||||
..DialogSpec::FORM
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct StackEntry {
|
||||
effect: String,
|
||||
visible: bool,
|
||||
params: Map<String, Value>,
|
||||
}
|
||||
|
||||
/// Open the gallery on the current selection.
|
||||
pub fn open(app: &mut VectorcraftApp, _p: &Value) -> Result<Value, String> {
|
||||
if app.session.active().is_none_or(|s| s.selection.is_empty()) {
|
||||
return Err(tl!("Select artwork to apply effects").into());
|
||||
}
|
||||
let selected = effects_in_category(0).first().map(|e| e.id).unwrap_or("");
|
||||
app.ui.dialog = Some(Dialog::new(
|
||||
KIND,
|
||||
json!({ "category": 0, "selected": selected, "stack": [], "stackSelected": 0, "stackFocus": false, "preview": true }),
|
||||
));
|
||||
Ok(Value::Null)
|
||||
}
|
||||
|
||||
fn effects_in_category(cat: usize) -> Vec<EffectInfo> {
|
||||
let path = CATEGORIES.get(cat).map(|(_, p)| *p).unwrap_or(CATEGORIES[0].1);
|
||||
let mut out: Vec<EffectInfo> =
|
||||
vectorcraft_effects::effect_catalog().into_iter().filter(|e| e.menu == path && PIXEL_EFFECTS.contains(&e.id)).collect();
|
||||
out.sort_by(|a, b| a.label.cmp(b.label));
|
||||
out
|
||||
}
|
||||
|
||||
fn default_params(id: &str) -> Map<String, Value> {
|
||||
match vectorcraft_effects::effect_info(id).map(|e| e.defaults) {
|
||||
Some(Value::Object(m)) => m,
|
||||
_ => Map::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn merged_params(id: &str, stored: &Map<String, Value>) -> Map<String, Value> {
|
||||
match vectorcraft_effects::merged_params(id, &Value::Object(stored.clone())) {
|
||||
Value::Object(m) => m,
|
||||
_ => default_params(id),
|
||||
}
|
||||
}
|
||||
|
||||
fn stack_of(d: &Dialog) -> Vec<StackEntry> {
|
||||
d.fields
|
||||
.get("stack")
|
||||
.and_then(Value::as_array)
|
||||
.map(|rows| {
|
||||
rows.iter()
|
||||
.filter_map(|row| {
|
||||
let effect = row.get("effect").and_then(Value::as_str)?;
|
||||
let visible = row.get("visible").and_then(Value::as_bool).unwrap_or(true);
|
||||
let params = row
|
||||
.get("params")
|
||||
.and_then(Value::as_object)
|
||||
.cloned()
|
||||
.map(|m| merged_params(effect, &m))
|
||||
.unwrap_or_else(|| default_params(effect));
|
||||
Some(StackEntry { effect: effect.to_string(), visible, params })
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn write_stack(d: &mut Dialog, stack: &[StackEntry]) {
|
||||
let rows: Vec<Value> = stack.iter().map(|e| json!({ "effect": e.effect, "visible": e.visible, "params": e.params })).collect();
|
||||
d.fields.insert("stack".into(), Value::Array(rows));
|
||||
}
|
||||
|
||||
fn category_ix(d: &Dialog) -> usize {
|
||||
d.fields.get("category").and_then(Value::as_u64).unwrap_or(0) as usize
|
||||
}
|
||||
|
||||
fn selected_id(d: &Dialog) -> String {
|
||||
d.str("selected")
|
||||
}
|
||||
|
||||
fn set_selected(d: &mut Dialog, id: &str) {
|
||||
d.fields.insert("selected".into(), json!(id));
|
||||
}
|
||||
|
||||
fn stack_focus(d: &Dialog) -> bool {
|
||||
d.fields.get("stackFocus").and_then(Value::as_bool).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn set_stack_focus(d: &mut Dialog, on: bool) {
|
||||
d.fields.insert("stackFocus".into(), json!(on));
|
||||
}
|
||||
|
||||
fn browse_params(d: &Dialog) -> Map<String, Value> {
|
||||
let effect = d.fields.get("browseEffect").and_then(Value::as_str).unwrap_or("");
|
||||
let stored = d.fields.get("browseParams").and_then(Value::as_object).cloned().unwrap_or_default();
|
||||
if effect.is_empty() { stored } else { merged_params(effect, &stored) }
|
||||
}
|
||||
|
||||
fn set_browse_params(d: &mut Dialog, effect: &str, params: Map<String, Value>) {
|
||||
d.fields.insert("browseEffect".into(), json!(effect));
|
||||
d.fields.insert("browseParams".into(), Value::Object(params));
|
||||
}
|
||||
|
||||
/// The effect whose parameters the panel edits, and its values.
|
||||
fn param_target(d: &Dialog, stack: &[StackEntry], stack_sel: usize, browse: &str) -> (String, Map<String, Value>) {
|
||||
if stack_focus(d) {
|
||||
let entry = stack.get(stack_sel);
|
||||
if let Some(e) = entry {
|
||||
return (e.effect.clone(), e.params.clone());
|
||||
}
|
||||
}
|
||||
let id = browse.to_string();
|
||||
let params = if d.fields.get("browseEffect").and_then(Value::as_str) == Some(browse) { browse_params(d) } else { default_params(browse) };
|
||||
(id, params)
|
||||
}
|
||||
|
||||
fn write_param_target(d: &mut Dialog, stack: &mut [StackEntry], stack_sel: usize, browse: &str, effect: &str, params: Map<String, Value>) {
|
||||
if stack_focus(d) {
|
||||
if let Some(e) = stack.get_mut(stack_sel)
|
||||
&& e.effect == effect
|
||||
{
|
||||
e.params = params;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if browse == effect {
|
||||
set_browse_params(d, effect, params);
|
||||
}
|
||||
}
|
||||
|
||||
/// Reuse the live effect dialog's fields for `effect_id` and `params`.
|
||||
fn effect_param_fields(app: &mut VectorcraftApp, ui: &mut egui::Ui, effect_id: &str, params: &mut Map<String, Value>) {
|
||||
if effect_id.is_empty() {
|
||||
return;
|
||||
}
|
||||
let label =
|
||||
vectorcraft_effects::effect_info(effect_id).map(|e| e.label.trim_end_matches('…').to_string()).unwrap_or_else(|| effect_id.to_string());
|
||||
let mut fields = params.clone();
|
||||
fields.insert("__effect".into(), json!(effect_id));
|
||||
fields.insert("__label".into(), json!(label));
|
||||
fields.insert("preview".into(), json!(false));
|
||||
let mut temp = Dialog::new("effect", Value::Object(fields));
|
||||
(effect::SPEC.body)(app, ui, &mut temp);
|
||||
if let Value::Object(m) = form::params(&temp) {
|
||||
*params = m;
|
||||
}
|
||||
if let Value::Object(m) = vectorcraft_effects::upgrade_params(effect_id, &Value::Object(params.clone())) {
|
||||
*params = m;
|
||||
}
|
||||
}
|
||||
|
||||
fn stack_batch_commands(stack: &[StackEntry]) -> Vec<Value> {
|
||||
let mut commands = Vec::with_capacity(stack.len() * 2);
|
||||
for (i, entry) in stack.iter().enumerate() {
|
||||
let params = Value::Object(entry.params.clone());
|
||||
commands.push(json!({ "command": "effect.apply", "params": { "effect": entry.effect, "params": params } }));
|
||||
if !entry.visible {
|
||||
commands.push(json!({ "command": "effect.setParams", "params": { "index": i, "visible": false } }));
|
||||
}
|
||||
}
|
||||
commands
|
||||
}
|
||||
|
||||
fn stack_batch_params(stack: &[StackEntry]) -> Value {
|
||||
json!({ "label": "Effect Gallery", "commands": stack_batch_commands(stack) })
|
||||
}
|
||||
|
||||
/// Live canvas preview of the stack (`command.batch` would settle the dialog interaction each frame).
|
||||
fn preview_stack_on_canvas(app: &mut VectorcraftApp, stack: &[StackEntry]) {
|
||||
if app.session.in_interaction() {
|
||||
let _ = app.session.cancel_interaction();
|
||||
}
|
||||
let _ = app.session.begin_interaction("Effect Gallery");
|
||||
for (i, entry) in stack.iter().enumerate() {
|
||||
let params = Value::Object(entry.params.clone());
|
||||
if app.run("effect.apply", json!({ "effect": entry.effect, "params": params })).is_err() {
|
||||
let _ = app.session.cancel_interaction();
|
||||
return;
|
||||
}
|
||||
if !entry.visible && app.run("effect.setParams", json!({ "index": i, "visible": false })).is_err() {
|
||||
let _ = app.session.cancel_interaction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn stack_preview_row(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog, stack: &[StackEntry]) {
|
||||
const LAST: &str = super::form::PREVIEWED;
|
||||
ui.add_space(8.0);
|
||||
let mut on = d.bool("preview");
|
||||
if widgets::check(ui, tl!("Preview"), on, true) {
|
||||
on = !on;
|
||||
d.fields.insert("preview".into(), json!(on));
|
||||
}
|
||||
if !on {
|
||||
if d.fields.remove(LAST).is_some() {
|
||||
let _ = app.session.cancel_interaction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if stack.is_empty() {
|
||||
if d.fields.remove(LAST).is_some() {
|
||||
let _ = app.session.cancel_interaction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
let batch = stack_batch_params(stack);
|
||||
if d.fields.get(LAST) != Some(&batch) || !app.session.in_interaction() {
|
||||
preview_stack_on_canvas(app, stack);
|
||||
d.fields.insert(LAST.into(), batch);
|
||||
}
|
||||
}
|
||||
|
||||
fn effect_label(id: &str) -> String {
|
||||
vectorcraft_effects::effect_info(id).map(|e| tl!(e.label).trim_end_matches('…').to_string()).unwrap_or_else(|| id.to_string())
|
||||
}
|
||||
|
||||
fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let cat = category_ix(d);
|
||||
let effects = effects_in_category(cat);
|
||||
let mut sel = selected_id(d);
|
||||
if !effects.iter().any(|e| e.id == sel) {
|
||||
sel = effects.first().map(|e| e.id.to_string()).unwrap_or_default();
|
||||
set_selected(d, &sel);
|
||||
}
|
||||
|
||||
let mut stack = stack_of(d);
|
||||
let mut stack_sel = d.fields.get("stackSelected").and_then(Value::as_u64).unwrap_or(0) as usize;
|
||||
if stack_sel >= stack.len() && !stack.is_empty() {
|
||||
stack_sel = stack.len() - 1;
|
||||
}
|
||||
let (param_effect, mut param_values) = param_target(d, &stack, stack_sel, &sel);
|
||||
if !param_effect.is_empty() {
|
||||
widgets::subheader(ui, tl!("Settings"));
|
||||
egui::ScrollArea::vertical().max_height(200.0).show(ui, |ui| {
|
||||
effect_param_fields(app, ui, ¶m_effect, &mut param_values);
|
||||
});
|
||||
write_param_target(d, &mut stack, stack_sel, &sel, ¶m_effect, param_values);
|
||||
}
|
||||
|
||||
ui.horizontal_top(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
widgets::subheader(ui, tl!("Categories"));
|
||||
ui.set_width(120.0);
|
||||
for (i, (name, _)) in CATEGORIES.iter().enumerate() {
|
||||
let count = effects_in_category(i).len();
|
||||
if count == 0 {
|
||||
continue;
|
||||
}
|
||||
let label = tl!(name);
|
||||
if ui.add(egui::Button::selectable(cat == i, label)).clicked() {
|
||||
d.fields.insert("category".into(), json!(i));
|
||||
let first = effects_in_category(i).first().map(|e| e.id).unwrap_or("");
|
||||
set_selected(d, first);
|
||||
set_stack_focus(d, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.add_space(8.0);
|
||||
ui.vertical(|ui| {
|
||||
widgets::subheader(ui, tl!("Filters"));
|
||||
ui.set_width(220.0);
|
||||
egui::ScrollArea::vertical().max_height(220.0).show(ui, |ui| {
|
||||
for e in &effects {
|
||||
let picked = e.id == sel;
|
||||
let name = tl!(e.label).trim_end_matches('…').to_string();
|
||||
let resp = ui.add(egui::Button::selectable(picked, name));
|
||||
if resp.clicked() {
|
||||
set_selected(d, e.id);
|
||||
set_stack_focus(d, false);
|
||||
}
|
||||
if resp.double_clicked() {
|
||||
set_selected(d, e.id);
|
||||
set_stack_focus(d, false);
|
||||
add_selected(d, e.id);
|
||||
stack = stack_of(d);
|
||||
}
|
||||
}
|
||||
});
|
||||
if widgets::flat_button(ui, tl!("Add to Stack"), 120.0).clicked() && !sel.is_empty() {
|
||||
add_selected(d, &sel);
|
||||
stack = stack_of(d);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(10.0);
|
||||
widgets::subheader(ui, tl!("Applied Filters"));
|
||||
let mut stack_sel = d.fields.get("stackSelected").and_then(Value::as_u64).unwrap_or(0) as usize;
|
||||
if stack_sel >= stack.len() && !stack.is_empty() {
|
||||
stack_sel = stack.len() - 1;
|
||||
}
|
||||
enum StackOp {
|
||||
Toggle(usize),
|
||||
Up(usize),
|
||||
Down(usize),
|
||||
Remove(usize),
|
||||
Select(usize),
|
||||
}
|
||||
let mut op = None;
|
||||
let stack_len = stack.len();
|
||||
egui::ScrollArea::vertical().max_height(120.0).show(ui, |ui| {
|
||||
if stack.is_empty() {
|
||||
ui.label(egui::RichText::new(tl!("Add filters from the list above")).color(t.text_dim));
|
||||
return;
|
||||
}
|
||||
for (i, entry) in stack.iter().enumerate().take(stack_len) {
|
||||
ui.horizontal(|ui| {
|
||||
let eye = if entry.visible { "eye" } else { "eye-off" };
|
||||
if widgets::icon_button(ui, eye, tl!("Click to toggle visibility"), false, 22.0).clicked() {
|
||||
op = Some(StackOp::Toggle(i));
|
||||
}
|
||||
let name = effect_label(&entry.effect);
|
||||
if ui.add(egui::Button::selectable(stack_sel == i, name)).clicked() {
|
||||
op = Some(StackOp::Select(i));
|
||||
}
|
||||
if widgets::icon_button_enabled(ui, "dc-arrow-up", tl!("Move Up"), false, i > 0, 22.0).clicked() {
|
||||
op = Some(StackOp::Up(i));
|
||||
}
|
||||
if widgets::icon_button_enabled(ui, "dc-arrow-down", tl!("Move Down"), false, i + 1 < stack_len, 22.0).clicked() {
|
||||
op = Some(StackOp::Down(i));
|
||||
}
|
||||
if widgets::flat_button(ui, tl!("Remove"), 64.0).clicked() {
|
||||
op = Some(StackOp::Remove(i));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
match op {
|
||||
Some(StackOp::Toggle(i)) if stack.get(i).is_some() => stack[i].visible = !stack[i].visible,
|
||||
Some(StackOp::Select(i)) => {
|
||||
stack_sel = i;
|
||||
set_stack_focus(d, true);
|
||||
}
|
||||
Some(StackOp::Up(i)) if i > 0 => {
|
||||
stack.swap(i, i - 1);
|
||||
stack_sel = i - 1;
|
||||
}
|
||||
Some(StackOp::Down(i)) if i + 1 < stack.len() => {
|
||||
stack.swap(i, i + 1);
|
||||
stack_sel = i + 1;
|
||||
}
|
||||
Some(StackOp::Remove(i)) if i < stack.len() => {
|
||||
stack.remove(i);
|
||||
if stack_sel >= stack.len() && !stack.is_empty() {
|
||||
stack_sel = stack.len() - 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
write_stack(d, &stack);
|
||||
d.fields.insert("stackSelected".into(), json!(stack_sel));
|
||||
stack_preview_row(app, ui, d, &stack);
|
||||
false
|
||||
}
|
||||
|
||||
fn add_selected(d: &mut Dialog, id: &str) {
|
||||
let params =
|
||||
if !stack_focus(d) && d.fields.get("browseEffect").and_then(Value::as_str) == Some(id) { browse_params(d) } else { default_params(id) };
|
||||
let mut stack = stack_of(d);
|
||||
stack.push(StackEntry { effect: id.to_string(), visible: true, params });
|
||||
write_stack(d, &stack);
|
||||
d.fields.insert("stackSelected".into(), json!(stack.len().saturating_sub(1)));
|
||||
set_stack_focus(d, true);
|
||||
}
|
||||
|
||||
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
|
||||
let stack = stack_of(d);
|
||||
if stack.is_empty() {
|
||||
if app.session.in_interaction() {
|
||||
let _ = app.session.cancel_interaction();
|
||||
}
|
||||
app.ui.dialog = None;
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
let batch = stack_batch_params(&stack);
|
||||
if d.bool("preview") && app.session.in_interaction() {
|
||||
return super::form::commit_preview(app, "command.batch", batch);
|
||||
}
|
||||
let r = app.run("command.batch", batch);
|
||||
if r.is_ok() {
|
||||
app.ui.dialog = None;
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
use vectorcraft_engine::Session;
|
||||
|
||||
use crate::VectorcraftApp;
|
||||
|
||||
fn frame(app: &mut VectorcraftApp) {
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
crate::theme::apply(&ctx, Default::default());
|
||||
let raw = egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1200.0, 900.0))), ..Default::default() };
|
||||
let mut out = ctx.run_ui(raw, |ui| crate::dialogs::show(app, ui.ctx()));
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stack_preview_is_one_interaction() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 200})).unwrap();
|
||||
let id = app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 40, "height": 40})).unwrap()["id"].as_u64().unwrap();
|
||||
app.run("ui.effectGalleryDialog", json!({})).unwrap();
|
||||
let d = app.ui.dialog.as_mut().unwrap();
|
||||
d.fields.insert("stack".into(), json!([{ "effect": "artistic.cutout", "visible": true, "params": { "levels": 3 } }]));
|
||||
frame(&mut app);
|
||||
assert!(app.session.in_interaction(), "the stack previews on the canvas");
|
||||
crate::dialogs::cancel(&mut app);
|
||||
assert!(!app.session.in_interaction());
|
||||
assert!(app.session.active().unwrap().doc.node(vectorcraft_doc::NodeId(id)).unwrap().appearance.effects.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stack_ok_is_one_undo_step() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 200})).unwrap();
|
||||
let id = app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 40, "height": 40})).unwrap()["id"].as_u64().unwrap();
|
||||
app.run("ui.effectGalleryDialog", json!({})).unwrap();
|
||||
assert_eq!(app.ui.dialog.as_ref().map(|d| d.kind.as_str()), Some(super::KIND));
|
||||
let d = app.ui.dialog.as_mut().unwrap();
|
||||
d.fields.insert(
|
||||
"stack".into(),
|
||||
json!([
|
||||
{ "effect": "artistic.cutout", "visible": true, "params": { "levels": 3 } },
|
||||
{ "effect": "stylize.glowingEdges", "visible": false, "params": { "edgeWidth": 2 } }
|
||||
]),
|
||||
);
|
||||
frame(&mut app);
|
||||
let steps = app.session.active().unwrap().history.undo.len();
|
||||
crate::dialogs::confirm(&mut app).unwrap();
|
||||
let st = app.session.active().unwrap();
|
||||
let n = st.doc.node(vectorcraft_doc::NodeId(id)).unwrap();
|
||||
assert_eq!(n.appearance.effects.len(), 2);
|
||||
assert_eq!(n.appearance.effects[0].id, "artistic.cutout");
|
||||
assert_eq!(n.appearance.effects[0].params.get("levels").and_then(|v| v.as_i64()), Some(3));
|
||||
assert_eq!(n.appearance.effects[1].id, "stylize.glowingEdges");
|
||||
assert!(!n.appearance.effects[1].visible);
|
||||
assert_eq!(st.history.undo.len(), steps + 1);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ pub mod dxf_import;
|
||||
pub mod dxf_options;
|
||||
pub mod edit_selection;
|
||||
mod effect;
|
||||
pub mod effect_gallery;
|
||||
pub mod envelope;
|
||||
pub mod eps_options;
|
||||
pub mod expand;
|
||||
@@ -301,6 +302,7 @@ registry! {
|
||||
SwatchConflict: [swatch_conflict::KIND] => swatch_conflict::SPEC,
|
||||
FileInfo: [file_info::KIND] => file_info::SPEC,
|
||||
RasterEffectsSettings: [raster_effects::KIND] => raster_effects::SPEC,
|
||||
EffectGallery: [effect_gallery::KIND] => effect_gallery::SPEC,
|
||||
MissingLinks: [missing_links::KIND] => missing_links::SPEC,
|
||||
MissingFonts: [missing_fonts::KIND] => missing_fonts::SPEC,
|
||||
FindLinks: [find_links::KIND] => find_links::SPEC,
|
||||
|
||||
@@ -1049,6 +1049,11 @@
|
||||
Fidelity: Точност:
|
||||
Figure Space Цифрово разстояние
|
||||
Figure: Фигура:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Поставяне на графика
|
||||
@msg {key} must be [x, y] with finite coordinates {key} трябва да е [x, y] с крайни координати
|
||||
@msg ids must contain 1–10000 object ids ids трябва да съдържа от 1 до 10000 идентификатора на обекти
|
||||
|
||||
File Файл
|
||||
File Dimensions Размери на файла
|
||||
File Format: Файлов формат:
|
||||
@@ -5310,6 +5315,14 @@ theme Appearance Външен вид
|
||||
Full Justify Пълно двустранно
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Минималната стойност не може да надвишава желаната, нито желаната – максималната.
|
||||
Justification Подравняване
|
||||
Add filters from the list above Добавете филтри от списъка по-горе
|
||||
Add to Stack Добавяне към стека
|
||||
Applied Filters Приложени филтри
|
||||
Categories Категории
|
||||
Choose a filter Изберете филтър
|
||||
Effect Gallery Галерия с ефекти
|
||||
Filters Филтри
|
||||
Select artwork to apply effects Изберете графика, за да приложите ефекти
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them променливите и наборите от данни на файла не бяха прочетени (променливи: {variables}, набори от данни: {data_sets}): панелът „Променливи“ не ги показва
|
||||
# Select by Color (select.color)
|
||||
Select by Color Избиране по цвят
|
||||
@@ -5343,8 +5356,5 @@ theme Appearance Външен вид
|
||||
Shift: Изместване:
|
||||
Fresco… Фреска…
|
||||
Fresco Фреска
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Поставяне на графика
|
||||
@msg {key} must be [x, y] with finite coordinates {key} трябва да е [x, y] с крайни координати
|
||||
@msg ids must contain 1–10000 object ids ids трябва да съдържа от 1 до 10000 идентификатора на обекти
|
||||
Effect Gallery… Галерия с ефекти…
|
||||
Effect Gallery Dialog Диалог „Галерия с ефекти“
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -34,6 +34,11 @@
|
||||
Medium Light Středně světlý
|
||||
Light Světlý
|
||||
Quit VectorCraft Ukončit VectorCraft
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Umístit grafiku
|
||||
@msg {key} must be [x, y] with finite coordinates {key} musí být [x, y] s konečnými souřadnicemi
|
||||
@msg ids must contain 1–10000 object ids ids musí obsahovat 1–10000 identifikátorů objektů
|
||||
|
||||
File Soubor
|
||||
New… Nový…
|
||||
New Without Dialog Nový bez dialogového okna
|
||||
@@ -5333,6 +5338,7 @@ mark-style Japanese Japonské
|
||||
@msg Persistent libraries not found: {files} Trvalé knihovny nebyly nalezeny: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` není panel knihovny (viz window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open panel knihovny `{given}` není otevřený
|
||||
@msg library panel `{given}` isn't missing its library knihovna panelu knihovny `{given}` nechybí
|
||||
@msg too many library panels were opened in this session v této relaci bylo otevřeno příliš mnoho panelů knihoven
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Obraz má {_1} × {_2} pixelů, na jedné straně více než {LARGE_TRACE_SIDE}: vektorizuje se, ale pomaleji. Rychleji se vektorizuje s předvolbou nižší věrnosti nebo menší kopie obrazu.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Obraz byl vektorizován v rozlišení {_1} × {_2} pixelů, zmenšený z {_3} × {_4} (nejvýše {_5} megapixelů).
|
||||
@@ -5353,6 +5359,14 @@ mark-style Japanese Japonské
|
||||
Full Justify Zarovnat do bloku
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum nesmí překročit požadovanou hodnotu ani požadovaná hodnota maximum.
|
||||
Justification Zarovnání do bloku
|
||||
Add filters from the list above Přidejte filtry ze seznamu výše
|
||||
Add to Stack Přidat na zásobník
|
||||
Applied Filters Použité filtry
|
||||
Categories Kategorie
|
||||
Choose a filter Vyberte filtr
|
||||
Effect Gallery Galerie efektů
|
||||
Filters Filtry
|
||||
Select artwork to apply effects Vyberte grafiku, na kterou chcete použít efekty
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them proměnné a sady dat souboru nebyly načteny (proměnné: {variables}, sady dat: {data_sets}): panel Proměnné je nezobrazuje
|
||||
# Select by Color (select.color)
|
||||
Select by Color Vybrat podle barvy
|
||||
@@ -5386,8 +5400,5 @@ mark-style Japanese Japonské
|
||||
Shift: Posun:
|
||||
Fresco… Freska…
|
||||
Fresco Freska
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Umístit grafiku
|
||||
@msg {key} must be [x, y] with finite coordinates {key} musí být [x, y] s konečnými souřadnicemi
|
||||
@msg ids must contain 1–10000 object ids ids musí obsahovat 1–10000 identifikátorů objektů
|
||||
Effect Gallery… Galerie efektů…
|
||||
Effect Gallery Dialog Dialog Galerie efektů
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -20,6 +20,11 @@
|
||||
Medium Light Mellemlys
|
||||
Light Lys
|
||||
Quit VectorCraft Slut VectorCraft
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Slip illustration
|
||||
@msg {key} must be [x, y] with finite coordinates {key} skal være [x, y] med endelige koordinater
|
||||
@msg ids must contain 1–10000 object ids ids skal indeholde 1–10000 objekt-id’er
|
||||
|
||||
File Filer
|
||||
New… Ny…
|
||||
New Without Dialog Ny uden dialog
|
||||
@@ -5306,6 +5311,14 @@ swatch Bright Violet Kraftig violet
|
||||
Full Justify Lige margener
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum må ikke overstige Ønsket, og Ønsket ikke Maksimum.
|
||||
Justification Justering
|
||||
Add filters from the list above Tilføj filtre fra listen ovenfor
|
||||
Add to Stack Tilføj til stak
|
||||
Applied Filters Anvendte filtre
|
||||
Categories Kategorier
|
||||
Choose a filter Vælg et filter
|
||||
Effect Gallery Effektgalleri
|
||||
Filters Filtre
|
||||
Select artwork to apply effects Vælg grafik for at anvende effekter
|
||||
# Select by Color (select.color)
|
||||
Select by Color Markér efter farve
|
||||
Smudge Stick… Udtværingsstift…
|
||||
@@ -5359,8 +5372,5 @@ swatch Bright Violet Kraftig violet
|
||||
Shift: Forskydning:
|
||||
Fresco… Fresko…
|
||||
Fresco Fresko
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Slip illustration
|
||||
@msg {key} must be [x, y] with finite coordinates {key} skal være [x, y] med endelige koordinater
|
||||
@msg ids must contain 1–10000 object ids ids skal indeholde 1–10000 objekt-id’er
|
||||
Effect Gallery… Effektgalleri…
|
||||
Effect Gallery Dialog Dialogboksen Effektgalleri
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1046,6 +1046,11 @@
|
||||
Fidelity: Genauigkeit:
|
||||
Figure Space Ziffernleerzeichen
|
||||
Figure: Ziffern:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Grafik ablegen
|
||||
@msg {key} must be [x, y] with finite coordinates {key} muss [x, y] mit endlichen Koordinaten sein
|
||||
@msg ids must contain 1–10000 object ids ids muss 1–10000 Objekt-IDs enthalten
|
||||
|
||||
File Datei
|
||||
File Dimensions Dateiabmessungen
|
||||
File Format: Dateiformat:
|
||||
@@ -4913,6 +4918,7 @@ effect Soft Weich
|
||||
@msg Persistent libraries not found: {files} Dauerhafte Bibliotheken nicht gefunden: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` ist kein Bibliotheksbedienfeld (siehe window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open Bibliotheksbedienfeld `{given}` ist nicht geöffnet
|
||||
@msg library panel `{given}` isn't missing its library dem Bibliotheksbedienfeld `{given}` fehlt seine Bibliothek nicht
|
||||
@msg too many library panels were opened in this session in dieser Sitzung wurden zu viele Bibliotheksbedienfelder geöffnet
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Das Bild hat {_1} × {_2} Pixel, mehr als {LARGE_TRACE_SIDE} auf einer Seite: Es wird nachgezeichnet, aber langsamer. Eine Vorgabe mit geringerer Detailtreue oder eine kleinere Kopie des Bildes geht schneller.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Das Bild wurde mit {_1} × {_2} Pixeln nachgezeichnet, verkleinert von {_3} × {_4} (höchstens {_5} Megapixel).
|
||||
@@ -4934,6 +4940,14 @@ effect Soft Weich
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Das Minimum darf den optimalen Wert nicht übersteigen, der optimale Wert nicht das Maximum.
|
||||
Minimum Minimum
|
||||
Justification Abstände
|
||||
Add filters from the list above Filter aus der Liste oben hinzufügen
|
||||
Add to Stack Zum Stapel hinzufügen
|
||||
Applied Filters Angewendete Filter
|
||||
Categories Kategorien
|
||||
Choose a filter Filter wählen
|
||||
Effect Gallery Effekt-Galerie
|
||||
Filters Filter
|
||||
Select artwork to apply effects Wählen Sie Grafik aus, um Effekte anzuwenden
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them die Variablen und Datensätze der Datei wurden nicht gelesen (Variablen: {variables}, Datensätze: {data_sets}): Das Bedienfeld „Variablen“ listet sie nicht auf
|
||||
# Select by Color (select.color)
|
||||
Select by Color Nach Farbe auswählen
|
||||
@@ -4967,8 +4981,5 @@ effect Soft Weich
|
||||
Shift: Verschiebung:
|
||||
Fresco… Fresko…
|
||||
Fresco Fresko
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Grafik ablegen
|
||||
@msg {key} must be [x, y] with finite coordinates {key} muss [x, y] mit endlichen Koordinaten sein
|
||||
@msg ids must contain 1–10000 object ids ids muss 1–10000 Objekt-IDs enthalten
|
||||
Effect Gallery… Effekt-Galerie…
|
||||
Effect Gallery Dialog Dialogfeld „Effekt-Galerie“
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1015,6 +1015,11 @@
|
||||
Fidelity: Πιστότητα:
|
||||
Figure Space Κενό ψηφίου
|
||||
Figure: Σχήμα:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Απόθεση γραφικών
|
||||
@msg {key} must be [x, y] with finite coordinates Το {key} πρέπει να είναι [x, y] με πεπερασμένες συντεταγμένες
|
||||
@msg ids must contain 1–10000 object ids Το ids πρέπει να περιέχει 1–10000 αναγνωριστικά αντικειμένων
|
||||
|
||||
File Αρχείο
|
||||
File Dimensions Διαστάσεις αρχείου
|
||||
File Format: Μορφή αρχείου:
|
||||
@@ -5285,6 +5290,7 @@ effect Points Σημεία
|
||||
@msg Persistent libraries not found: {files} Δεν βρέθηκαν μόνιμες βιβλιοθήκες: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) Το `{given}` δεν είναι πίνακας βιβλιοθήκης (δείτε window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open ο πίνακας βιβλιοθήκης `{given}` δεν είναι ανοιχτός
|
||||
@msg library panel `{given}` isn't missing its library η βιβλιοθήκη του πίνακα βιβλιοθήκης `{given}` δεν λείπει
|
||||
@msg too many library panels were opened in this session άνοιξαν πάρα πολλοί πίνακες βιβλιοθηκών σε αυτή τη συνεδρία
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Η εικόνα είναι {_1} × {_2} εικονοστοιχεία, πάνω από {LARGE_TRACE_SIDE} σε μία πλευρά: ανιχνεύεται, αλλά πιο αργά. Μια προρύθμιση χαμηλότερης πιστότητας ή ένα μικρότερο αντίγραφο της εικόνας ανιχνεύεται γρηγορότερα.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Η εικόνα ανιχνεύτηκε σε {_1} × {_2} εικονοστοιχεία, σμικρυμένη από {_3} × {_4} (το πολύ {_5} megapixel).
|
||||
@@ -5305,6 +5311,14 @@ effect Points Σημεία
|
||||
Full Justify Στοίχιση και στα δύο άκρα
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Το ελάχιστο δεν πρέπει να υπερβαίνει το επιθυμητό, ούτε το επιθυμητό το μέγιστο.
|
||||
Justification Πλήρης στοίχιση
|
||||
Add filters from the list above Προσθέστε φίλτρα από τη λίστα παραπάνω
|
||||
Add to Stack Προσθήκη στη στοίβα
|
||||
Applied Filters Εφαρμοσμένα φίλτρα
|
||||
Categories Κατηγορίες
|
||||
Choose a filter Επιλέξτε φίλτρο
|
||||
Effect Gallery Συλλογή εφέ
|
||||
Filters Φίλτρα
|
||||
Select artwork to apply effects Επιλέξτε γραφικά για να εφαρμόσετε εφέ
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them οι μεταβλητές και τα σύνολα δεδομένων του αρχείου δεν διαβάστηκαν (μεταβλητές: {variables}, σύνολα δεδομένων: {data_sets}): ο πίνακας Μεταβλητές δεν τα εμφανίζει
|
||||
# Select by Color (select.color)
|
||||
Select by Color Επιλογή βάσει χρώματος
|
||||
@@ -5338,8 +5352,5 @@ effect Points Σημεία
|
||||
Shift: Μετατόπιση:
|
||||
Fresco… Νωπογραφία…
|
||||
Fresco Νωπογραφία
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Απόθεση γραφικών
|
||||
@msg {key} must be [x, y] with finite coordinates Το {key} πρέπει να είναι [x, y] με πεπερασμένες συντεταγμένες
|
||||
@msg ids must contain 1–10000 object ids Το ids πρέπει να περιέχει 1–10000 αναγνωριστικά αντικειμένων
|
||||
Effect Gallery… Συλλογή εφέ…
|
||||
Effect Gallery Dialog Παράθυρο διαλόγου Συλλογή εφέ
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2045 and column 19.
|
@@ -1069,6 +1069,11 @@
|
||||
Fidelity: Fidelidad:
|
||||
Figure Space Espacio de cifra
|
||||
Figure: Cifras:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Soltar ilustración
|
||||
@msg {key} must be [x, y] with finite coordinates {key} debe ser [x, y] con coordenadas finitas
|
||||
@msg ids must contain 1–10000 object ids ids debe contener entre 1 y 10000 identificadores de objetos
|
||||
|
||||
File Archivo
|
||||
File Dimensions Dimensiones del archivo
|
||||
File Format: Formato de archivo:
|
||||
@@ -5275,6 +5280,7 @@ mark-style Japanese Japonesas
|
||||
@msg Persistent libraries not found: {files} No se encontraron bibliotecas persistentes: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` no es un panel de biblioteca (consulte window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open el panel de biblioteca `{given}` no está abierto
|
||||
@msg library panel `{given}` isn't missing its library la biblioteca del panel de biblioteca `{given}` no falta
|
||||
@msg too many library panels were opened in this session se abrieron demasiados paneles de biblioteca en esta sesión
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. La imagen tiene {_1} × {_2} píxeles, más de {LARGE_TRACE_SIDE} en un lado: se calcará, pero más despacio. Un ajuste preestablecido de menor fidelidad o una copia más pequeña de la imagen se calcan más rápido.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). La imagen se calcó a {_1} × {_2} píxeles, reducida desde {_3} × {_4} ({_5} megapíxeles como máximo).
|
||||
@@ -5295,6 +5301,14 @@ mark-style Japanese Japonesas
|
||||
Full Justify Justificar completamente
|
||||
Minimum must not exceed Desired, nor Desired Maximum. El mínimo no puede superar el deseado, ni el deseado el máximo.
|
||||
Justification Justificación
|
||||
Add filters from the list above Añada filtros de la lista de arriba
|
||||
Add to Stack Añadir a la pila
|
||||
Applied Filters Filtros aplicados
|
||||
Categories Categorías
|
||||
Choose a filter Elija un filtro
|
||||
Effect Gallery Galería de efectos
|
||||
Filters Filtros
|
||||
Select artwork to apply effects Seleccione gráficos para aplicar efectos
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them no se leyeron las variables ni los conjuntos de datos del archivo (variables: {variables}, conjuntos de datos: {data_sets}): el panel Variables no los muestra
|
||||
# Select by Color (select.color)
|
||||
Select by Color Seleccionar por color
|
||||
@@ -5328,8 +5342,5 @@ mark-style Japanese Japonesas
|
||||
Shift: Desplazamiento:
|
||||
Fresco… Fresco…
|
||||
Fresco Fresco
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Soltar ilustración
|
||||
@msg {key} must be [x, y] with finite coordinates {key} debe ser [x, y] con coordenadas finitas
|
||||
@msg ids must contain 1–10000 object ids ids debe contener entre 1 y 10000 identificadores de objetos
|
||||
Effect Gallery… Galería de efectos…
|
||||
Effect Gallery Dialog Cuadro de diálogo Galería de efectos
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -42,6 +42,11 @@
|
||||
Medium Light Keskivaalea
|
||||
Light Vaalea
|
||||
Quit VectorCraft Lopeta VectorCraft
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Pudota kuvitus
|
||||
@msg {key} must be [x, y] with finite coordinates {key} on annettava muodossa [x, y] äärellisillä koordinaateilla
|
||||
@msg ids must contain 1–10000 object ids ids-arvon on sisällettävä 1–10000 objektitunnusta
|
||||
|
||||
File Tiedosto
|
||||
New… Uusi…
|
||||
New Without Dialog Uusi ilman valintaikkunaa
|
||||
@@ -5297,6 +5302,7 @@ mark-style Japanese Japanilainen
|
||||
@msg Persistent libraries not found: {files} Pysyviä kirjastoja ei löytynyt: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` ei ole kirjastopaneeli (katso window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open kirjastopaneeli `{given}` ei ole auki
|
||||
@msg library panel `{given}` isn't missing its library kirjastopaneelin `{given}` kirjasto ei puutu
|
||||
@msg too many library panels were opened in this session tässä istunnossa on avattu liian monta kirjastopaneelia
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Kuva on {_1} × {_2} kuvapistettä, yhdeltä sivultaan yli {LARGE_TRACE_SIDE}: se jäljitetään, mutta hitaammin. Pienemmän tarkkuuden esiasetus tai kuvan pienempi kopio jäljittyy nopeammin.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Kuva jäljitettiin kokoon {_1} × {_2} kuvapistettä pienennettynä koosta {_3} × {_4} (enintään {_5} megapikseliä).
|
||||
@@ -5317,6 +5323,14 @@ mark-style Japanese Japanilainen
|
||||
Full Justify Täysi tasaus
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimi ei saa ylittää haluttua arvoa eikä haluttu arvo maksimia.
|
||||
Justification Tasaus
|
||||
Add filters from the list above Lisää suodattimia yllä olevasta luettelosta
|
||||
Add to Stack Lisää pinoon
|
||||
Applied Filters Käytetyt suodattimet
|
||||
Categories Luokat
|
||||
Choose a filter Valitse suodatin
|
||||
Effect Gallery Tehostegalleria
|
||||
Filters Suodattimet
|
||||
Select artwork to apply effects Valitse grafiikka, johon tehosteet otetaan
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them tiedoston muuttujia ja tietojoukkoja ei luettu (muuttujia: {variables}, tietojoukkoja: {data_sets}): Muuttujat-paneeli ei näytä niitä
|
||||
# Select by Color (select.color)
|
||||
Select by Color Valitse värin mukaan
|
||||
@@ -5417,8 +5431,5 @@ swatch Bright Violet Kirkas violetti
|
||||
Shift: Siirtymä:
|
||||
Fresco… Fresko…
|
||||
Fresco Fresko
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Pudota kuvitus
|
||||
@msg {key} must be [x, y] with finite coordinates {key} on annettava muodossa [x, y] äärellisillä koordinaateilla
|
||||
@msg ids must contain 1–10000 object ids ids-arvon on sisällettävä 1–10000 objektitunnusta
|
||||
Effect Gallery… Tehostegalleria…
|
||||
Effect Gallery Dialog Tehostegalleria-valintaikkuna
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1069,6 +1069,11 @@
|
||||
Fidelity: Fidélité :
|
||||
Figure Space Espace numérique
|
||||
Figure: Chiffres :
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Déposer l’illustration
|
||||
@msg {key} must be [x, y] with finite coordinates {key} doit être [x, y] avec des coordonnées finies
|
||||
@msg ids must contain 1–10000 object ids ids doit contenir de 1 à 10000 identifiants d’objets
|
||||
|
||||
File Fichier
|
||||
File Dimensions Dimensions du fichier
|
||||
File Format: Format de fichier :
|
||||
@@ -5332,6 +5337,7 @@ theme Appearance Apparence
|
||||
@msg Persistent libraries not found: {files} Bibliothèques persistantes introuvables : {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` n’est pas un panneau de bibliothèque (voir window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open le panneau de bibliothèque `{given}` n’est pas ouvert
|
||||
@msg library panel `{given}` isn't missing its library la bibliothèque du panneau de bibliothèque `{given}` ne manque pas
|
||||
@msg too many library panels were opened in this session trop de panneaux de bibliothèque ont été ouverts dans cette session
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. L’image fait {_1} × {_2} pixels, plus de {LARGE_TRACE_SIDE} sur un côté : elle est vectorisée, mais plus lentement. Un paramètre prédéfini moins fidèle ou une copie plus petite de l’image se vectorise plus vite.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). L’image a été vectorisée à {_1} × {_2} pixels, réduite de {_3} × {_4} ({_5} mégapixels au plus).
|
||||
@@ -5352,6 +5358,14 @@ theme Appearance Apparence
|
||||
Full Justify Justification complète
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Le minimum ne doit pas dépasser la valeur optimale, ni la valeur optimale le maximum.
|
||||
Justification Justification
|
||||
Add filters from the list above Ajoutez des filtres à partir de la liste ci-dessus
|
||||
Add to Stack Ajouter à la pile
|
||||
Applied Filters Filtres appliqués
|
||||
Categories Catégories
|
||||
Choose a filter Choisir un filtre
|
||||
Effect Gallery Galerie d'effets
|
||||
Filters Filtres
|
||||
Select artwork to apply effects Sélectionnez des éléments graphiques pour appliquer des effets
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them les variables et jeux de données du fichier n’ont pas été lus (variables : {variables}, jeux de données : {data_sets}) : le panneau Variables ne les affiche pas
|
||||
# Select by Color (select.color)
|
||||
Select by Color Sélectionner par couleur
|
||||
@@ -5385,8 +5399,5 @@ theme Appearance Apparence
|
||||
Shift: Décalage :
|
||||
Fresco… Fresque…
|
||||
Fresco Fresque
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Déposer l’illustration
|
||||
@msg {key} must be [x, y] with finite coordinates {key} doit être [x, y] avec des coordonnées finies
|
||||
@msg ids must contain 1–10000 object ids ids doit contenir de 1 à 10000 identifiants d’objets
|
||||
Effect Gallery… Galerie d'effets…
|
||||
Effect Gallery Dialog Boîte de dialogue Galerie d'effets
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1355,6 +1355,11 @@
|
||||
Fidelity: Pontosság:
|
||||
Figure Space Számjegyszóköz
|
||||
Figure: Számjegyek:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Grafika elhelyezése
|
||||
@msg {key} must be [x, y] with finite coordinates A(z) {key} értékének [x, y] alakúnak kell lennie véges koordinátákkal
|
||||
@msg ids must contain 1–10000 object ids Az ids értékének 1–10000 objektumazonosítót kell tartalmaznia
|
||||
|
||||
File Fájl
|
||||
File Dimensions Fájl méretei
|
||||
File Format: Fájlformátum:
|
||||
@@ -5319,6 +5324,7 @@ imageTrace Outline Körvonal
|
||||
@msg Persistent libraries not found: {files} Nem találhatók állandó könyvtárak: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) A(z) `{given}` nem könyvtárpanel (lásd: window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open a(z) `{given}` könyvtárpanel nincs megnyitva
|
||||
@msg library panel `{given}` isn't missing its library a(z) `{given}` könyvtárpanel könyvtára nem hiányzik
|
||||
@msg too many library panels were opened in this session ebben a munkamenetben túl sok könyvtárpanel nyílt meg
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. A kép {_1} × {_2} képpont, egyik oldalán több mint {LARGE_TRACE_SIDE}: a vektorizálás megtörténik, de lassabban. Kisebb hűségű előbeállítással vagy a kép kisebb másolatával gyorsabb.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). A kép vektorizálása {_1} × {_2} képponton történt, {_3} × {_4} méretről kicsinyítve (legfeljebb {_5} megapixel).
|
||||
@@ -5339,6 +5345,14 @@ imageTrace Outline Körvonal
|
||||
Full Justify Teljes sorkizárás
|
||||
Minimum must not exceed Desired, nor Desired Maximum. A minimum nem haladhatja meg a kívánt értéket, sem a kívánt érték a maximumot.
|
||||
Justification Sorkizárás
|
||||
Add filters from the list above Adjon hozzá szűrőket a fenti listából
|
||||
Add to Stack Hozzáadás a veremhez
|
||||
Applied Filters Alkalmazott szűrők
|
||||
Categories Kategóriák
|
||||
Choose a filter Válasszon szűrőt
|
||||
Effect Gallery Effektusgaléria
|
||||
Filters Szűrők
|
||||
Select artwork to apply effects Válasszon ki grafikát az effektusok alkalmazásához
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them a fájl változói és adatkészletei nem lettek beolvasva (változók: {variables}, adatkészletek: {data_sets}): a Változók panel nem listázza őket
|
||||
# Select by Color (select.color)
|
||||
Select by Color Kijelölés szín szerint
|
||||
@@ -5372,8 +5386,5 @@ imageTrace Outline Körvonal
|
||||
Shift: Eltolás:
|
||||
Fresco… Freskó…
|
||||
Fresco Freskó
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Grafika elhelyezése
|
||||
@msg {key} must be [x, y] with finite coordinates A(z) {key} értékének [x, y] alakúnak kell lennie véges koordinátákkal
|
||||
@msg ids must contain 1–10000 object ids Az ids értékének 1–10000 objektumazonosítót kell tartalmaznia
|
||||
Effect Gallery… Effektusgaléria…
|
||||
Effect Gallery Dialog Effektusgaléria párbeszédpanel
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -20,6 +20,11 @@
|
||||
Medium Light Agak terang
|
||||
Light Terang
|
||||
Quit VectorCraft Keluar dari VectorCraft
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Letakkan karya
|
||||
@msg {key} must be [x, y] with finite coordinates {key} harus berupa [x, y] dengan koordinat berhingga
|
||||
@msg ids must contain 1–10000 object ids ids harus berisi 1–10000 ID objek
|
||||
|
||||
File Berkas
|
||||
New… Baru…
|
||||
New Without Dialog Baru tanpa dialog
|
||||
@@ -5306,6 +5311,14 @@ swatch Bright Violet Violet cerah
|
||||
Full Justify Rata Penuh
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum tidak boleh melebihi Diinginkan, dan Diinginkan tidak boleh melebihi Maksimum.
|
||||
Justification Justifikasi
|
||||
Add filters from the list above Tambahkan filter dari daftar di atas
|
||||
Add to Stack Tambahkan ke Tumpukan
|
||||
Applied Filters Filter yang Diterapkan
|
||||
Categories Kategori
|
||||
Choose a filter Pilih filter
|
||||
Effect Gallery Galeri Efek
|
||||
Filters Filter
|
||||
Select artwork to apply effects Pilih grafis untuk menerapkan efek
|
||||
# Select by Color (select.color)
|
||||
Select by Color Pilih berdasarkan warna
|
||||
Smudge Stick… Tongkat olesan…
|
||||
@@ -5359,8 +5372,5 @@ swatch Bright Violet Violet cerah
|
||||
Shift: Pergeseran:
|
||||
Fresco… Fresko…
|
||||
Fresco Fresko
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Letakkan karya
|
||||
@msg {key} must be [x, y] with finite coordinates {key} harus berupa [x, y] dengan koordinat berhingga
|
||||
@msg ids must contain 1–10000 object ids ids harus berisi 1–10000 ID objek
|
||||
Effect Gallery… Galeri Efek…
|
||||
Effect Gallery Dialog Dialog Galeri Efek
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3816 and column 19.
|
@@ -1069,6 +1069,11 @@
|
||||
Fidelity: Fedeltà:
|
||||
Figure Space Spazio cifra
|
||||
Figure: Cifre:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Rilascia illustrazione
|
||||
@msg {key} must be [x, y] with finite coordinates {key} deve essere [x, y] con coordinate finite
|
||||
@msg ids must contain 1–10000 object ids ids deve contenere da 1 a 10000 identificatori di oggetti
|
||||
|
||||
File File
|
||||
File Dimensions Dimensioni file
|
||||
File Format: Formato file:
|
||||
@@ -4947,6 +4952,7 @@ lighting Light Luce
|
||||
@msg Persistent libraries not found: {files} Librerie persistenti non trovate: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` non è un pannello libreria (vedi window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open il pannello libreria `{given}` non è aperto
|
||||
@msg library panel `{given}` isn't missing its library la libreria del pannello libreria `{given}` non è mancante
|
||||
@msg too many library panels were opened in this session in questa sessione sono stati aperti troppi pannelli libreria
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. L’immagine è di {_1} × {_2} pixel, più di {LARGE_TRACE_SIDE} su un lato: viene vettorializzata, ma più lentamente. Un predefinito a fedeltà più bassa o una copia più piccola dell’immagine è più veloce.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). L’immagine è stata vettorializzata a {_1} × {_2} pixel, ridotta da {_3} × {_4} (al massimo {_5} megapixel).
|
||||
@@ -4968,6 +4974,14 @@ lighting Light Luce
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Il minimo non può superare il valore desiderato, né il desiderato il massimo.
|
||||
Minimum Minimo
|
||||
Justification Giustificazione
|
||||
Add filters from the list above Aggiungi filtri dall'elenco sopra
|
||||
Add to Stack Aggiungi alla pila
|
||||
Applied Filters Filtri applicati
|
||||
Categories Categorie
|
||||
Choose a filter Scegli un filtro
|
||||
Effect Gallery Galleria effetti
|
||||
Filters Filtri
|
||||
Select artwork to apply effects Seleziona la grafica a cui applicare gli effetti
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them le variabili e i set di dati del file non sono stati letti (variabili: {variables}, set di dati: {data_sets}): il pannello Variabili non li elenca
|
||||
# Select by Color (select.color)
|
||||
Select by Color Seleziona per colore
|
||||
@@ -5001,8 +5015,5 @@ lighting Light Luce
|
||||
Shift: Spostamento:
|
||||
Fresco… Affresco…
|
||||
Fresco Affresco
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Rilascia illustrazione
|
||||
@msg {key} must be [x, y] with finite coordinates {key} deve essere [x, y] con coordinate finite
|
||||
@msg ids must contain 1–10000 object ids ids deve contenere da 1 a 10000 identificatori di oggetti
|
||||
Effect Gallery… Galleria effetti…
|
||||
Effect Gallery Dialog Finestra di dialogo Galleria effetti
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -75,6 +75,11 @@
|
||||
Medium Light やや明るい
|
||||
Light 明るい
|
||||
Quit VectorCraft VectorCraft を終了
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork アートワークをドロップ
|
||||
@msg {key} must be [x, y] with finite coordinates {key} は有限の座標を持つ [x, y] である必要があります
|
||||
@msg ids must contain 1–10000 object ids ids には 1~10000 個のオブジェクト ID を指定してください
|
||||
|
||||
File ファイル
|
||||
New… 新規…
|
||||
New Without Dialog ダイアログなしで新規
|
||||
@@ -4987,6 +4992,7 @@ lighting Light ライト
|
||||
@msg Persistent libraries not found: {files} 永続ライブラリが見つかりません: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` はライブラリパネルではありません (window.swatchLibrary を参照)
|
||||
@msg library panel `{given}` isn't open ライブラリパネル `{given}` は開いていません
|
||||
@msg library panel `{given}` isn't missing its library ライブラリパネル `{given}` のライブラリは欠落していません
|
||||
@msg too many library panels were opened in this session このセッションで開いたライブラリパネルが多すぎます
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. 画像は {_1} × {_2} ピクセルで、一辺が {LARGE_TRACE_SIDE} を超えています。トレースはできますが、時間がかかります。忠実度の低いプリセットや画像の小さいコピーを使うと速くなります。
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). 画像は {_3} × {_4} から縮小した {_1} × {_2} ピクセルでトレースされました (最大 {_5} メガピクセル)。
|
||||
@@ -5008,6 +5014,14 @@ lighting Light ライト
|
||||
Minimum must not exceed Desired, nor Desired Maximum. 最小値は最適値を、最適値は最大値を超えることはできません。
|
||||
Minimum 最小
|
||||
Justification 文字組み
|
||||
Add filters from the list above 上のリストからフィルターを追加
|
||||
Add to Stack スタックに追加
|
||||
Applied Filters 適用したフィルター
|
||||
Categories カテゴリ
|
||||
Choose a filter フィルターを選択
|
||||
Effect Gallery 効果ギャラリー
|
||||
Filters フィルター
|
||||
Select artwork to apply effects 効果を適用するグラフィックを選択してください
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them ファイルの変数とデータセットは読み込まれませんでした (変数: {variables}、データセット: {data_sets})。変数パネルには表示されません
|
||||
# Select by Color (select.color)
|
||||
Select by Color カラーで選択
|
||||
@@ -5048,8 +5062,5 @@ lighting Light ライト
|
||||
Shift: シフト:
|
||||
Fresco… フレスコ…
|
||||
Fresco フレスコ
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork アートワークをドロップ
|
||||
@msg {key} must be [x, y] with finite coordinates {key} は有限の座標を持つ [x, y] である必要があります
|
||||
@msg ids must contain 1–10000 object ids ids には 1~10000 個のオブジェクト ID を指定してください
|
||||
Effect Gallery… 効果ギャラリー…
|
||||
Effect Gallery Dialog 効果ギャラリーダイアログ
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -27,6 +27,11 @@
|
||||
Medium Light საშუალოდ ღია
|
||||
Light ღია
|
||||
Quit VectorCraft VectorCraft-იდან გასვლა
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork ნამუშევრის განთავსება
|
||||
@msg {key} must be [x, y] with finite coordinates {key} უნდა იყოს [x, y] სასრული კოორდინატებით
|
||||
@msg ids must contain 1–10000 object ids ids უნდა შეიცავდეს 1–10000 ობიექტის იდენტიფიკატორს
|
||||
|
||||
File ფაილი
|
||||
New… ახალი…
|
||||
New Without Dialog ახალი დიალოგის გარეშე
|
||||
@@ -5191,6 +5196,7 @@ imageTrace Outline კონტური
|
||||
@msg handle must be in or out handle უნდა იყოს in ან out
|
||||
@msg index must be ≥ 0 index უნდა იყოს ≥ 0
|
||||
@msg library panel `{given}` isn't open ბიბლიოთეკის პანელი `{given}` გახსნილი არ არის
|
||||
@msg library panel `{given}` isn't missing its library ბიბლიოთეკის პანელს `{given}` ბიბლიოთეკა არ აკლია
|
||||
@msg mask art ends outside a mask dictionary ნიღბის ნახატი ნიღბის ლექსიკონის გარეთ მთავრდება
|
||||
@msg missing number `{key}` აკლია რიცხვი `{key}`
|
||||
@msg missing integer `{key}` აკლია მთელი რიცხვი `{key}`
|
||||
@@ -5296,8 +5302,12 @@ imageTrace Outline კონტური
|
||||
Shift: წანაცვლება:
|
||||
Fresco… ფრესკა…
|
||||
Fresco ფრესკა
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork ნამუშევრის განთავსება
|
||||
@msg {key} must be [x, y] with finite coordinates {key} უნდა იყოს [x, y] სასრული კოორდინატებით
|
||||
@msg ids must contain 1–10000 object ids ids უნდა შეიცავდეს 1–10000 ობიექტის იდენტიფიკატორს
|
||||
Effect Gallery ეფექტების გალერეა
|
||||
Add filters from the list above დაამატეთ ფილტრები ზემოთ მოცემული სიიდან
|
||||
Add to Stack დასტაში დამატება
|
||||
Applied Filters გამოყენებული ფილტრები
|
||||
Categories კატეგორიები
|
||||
Filters ფილტრები
|
||||
Select artwork to apply effects აირჩიეთ ნამუშევარი ეფექტების გამოსაყენებლად
|
||||
Effect Gallery… ეფექტების გალერეა…
|
||||
Effect Gallery Dialog ეფექტების გალერეა დიალოგი
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -71,6 +71,11 @@
|
||||
Medium Light 약간 밝게
|
||||
Light 밝게
|
||||
Quit VectorCraft VectorCraft 종료
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork 아트워크 놓기
|
||||
@msg {key} must be [x, y] with finite coordinates {key}은(는) 유한한 좌표의 [x, y]여야 합니다
|
||||
@msg ids must contain 1–10000 object ids ids에는 1~10000개의 오브젝트 ID가 있어야 합니다
|
||||
|
||||
File 파일
|
||||
New… 새로 만들기…
|
||||
New Without Dialog 대화상자 없이 새로 만들기
|
||||
@@ -4910,6 +4915,7 @@ lighting Light 광원
|
||||
@msg Persistent libraries not found: {files} 지속 라이브러리를 찾을 수 없습니다: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}`은(는) 라이브러리 패널이 아닙니다(window.swatchLibrary 참조)
|
||||
@msg library panel `{given}` isn't open 라이브러리 패널 `{given}`이(가) 열려 있지 않습니다
|
||||
@msg library panel `{given}` isn't missing its library 라이브러리 패널 `{given}`의 라이브러리가 누락되지 않았습니다
|
||||
@msg too many library panels were opened in this session 이 세션에서 라이브러리 패널을 너무 많이 열었습니다
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. 이미지가 {_1} × {_2}픽셀로 한 변이 {LARGE_TRACE_SIDE}을 넘습니다. 추적은 되지만 더 느립니다. 충실도가 낮은 사전 설정이나 이미지의 작은 사본을 사용하면 더 빠릅니다.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). 이미지를 {_3} × {_4}에서 축소한 {_1} × {_2}픽셀로 추적했습니다(최대 {_5}메가픽셀).
|
||||
@@ -4931,6 +4937,14 @@ lighting Light 광원
|
||||
Minimum must not exceed Desired, nor Desired Maximum. 최소값은 희망값을, 희망값은 최대값을 넘을 수 없습니다.
|
||||
Minimum 최소
|
||||
Justification 양끝 맞춤
|
||||
Add filters from the list above 위 목록에서 필터 추가
|
||||
Add to Stack 스택에 추가
|
||||
Applied Filters 적용된 필터
|
||||
Categories 범주
|
||||
Choose a filter 필터 선택
|
||||
Effect Gallery 효과 갤러리
|
||||
Filters 필터
|
||||
Select artwork to apply effects 효과를 적용할 그래픽을 선택하세요
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them 파일의 변수와 데이터 세트를 읽지 않았습니다(변수: {variables}, 데이터 세트: {data_sets}). 변수 패널에 표시되지 않습니다
|
||||
# Select by Color (select.color)
|
||||
Select by Color 색상별 선택
|
||||
@@ -4964,8 +4978,5 @@ lighting Light 광원
|
||||
Shift: 이동:
|
||||
Fresco… 프레스코…
|
||||
Fresco 프레스코
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork 아트워크 놓기
|
||||
@msg {key} must be [x, y] with finite coordinates {key}은(는) 유한한 좌표의 [x, y]여야 합니다
|
||||
@msg ids must contain 1–10000 object ids ids에는 1~10000개의 오브젝트 ID가 있어야 합니다
|
||||
Effect Gallery… 효과 갤러리…
|
||||
Effect Gallery Dialog 효과 갤러리 대화 상자
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -94,7 +94,7 @@ fn plural_polish(n: u64) -> usize {
|
||||
}
|
||||
|
||||
/// The registry. English first: it is the fallback and the source language.
|
||||
pub static LANGUAGES: [LangInfo; 24] = [
|
||||
pub static LANGUAGES: [LangInfo; 25] = [
|
||||
LangInfo { code: "en", name: "English", source: "", plural: plural_one_other, complete_menus: false, catalog: OnceLock::new() },
|
||||
// Greek: the whole interface and the status and error messages, keeping the same names in
|
||||
// English as Spanish; every `el-*` locale (including `el-GR` and `el-CY`) resolves here.
|
||||
@@ -263,6 +263,10 @@ pub static LANGUAGES: [LangInfo; 24] = [
|
||||
// English as Spanish; one/other plurals with the partitive after any number but 1 ("2 tasoa").
|
||||
// Every `fi-*` locale resolves here.
|
||||
LangInfo { code: "fi", name: "Suomi", source: include_str!("fi.tsv"), plural: plural_one_other, complete_menus: true, catalog: OnceLock::new() },
|
||||
// Turkish: the whole interface and the status and error messages, keeping the same names in
|
||||
// English as Spanish; a count takes the singular ("3 katman"), so plurals have one form. Every
|
||||
// `tr-*` locale (including `tr-TR` and `tr-CY`) resolves here.
|
||||
LangInfo { code: "tr", name: "Türkçe", source: include_str!("tr.tsv"), plural: plural_none, complete_menus: true, catalog: OnceLock::new() },
|
||||
];
|
||||
|
||||
impl LangInfo {
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
Medium Light Gemiddeld licht
|
||||
Light Licht
|
||||
Quit VectorCraft VectorCraft afsluiten
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Illustratie neerzetten
|
||||
@msg {key} must be [x, y] with finite coordinates {key} moet [x, y] met eindige coördinaten zijn
|
||||
@msg ids must contain 1–10000 object ids ids moet 1–10000 object-id’s bevatten
|
||||
|
||||
File Bestand
|
||||
New… Nieuw…
|
||||
New Without Dialog Nieuw zonder dialoogvenster
|
||||
@@ -5329,6 +5334,7 @@ swatch Bright Violet Felviolet
|
||||
@msg Persistent libraries not found: {files} Permanente bibliotheken niet gevonden: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` is geen bibliotheekpaneel (zie window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open bibliotheekpaneel `{given}` is niet geopend
|
||||
@msg library panel `{given}` isn't missing its library de bibliotheek van bibliotheekpaneel `{given}` ontbreekt niet
|
||||
@msg too many library panels were opened in this session er zijn in deze sessie te veel bibliotheekpanelen geopend
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. De afbeelding is {_1} × {_2} pixels, meer dan {LARGE_TRACE_SIDE} aan één zijde: ze wordt getraceerd, maar langzamer. Een voorinstelling met minder detail of een kleinere kopie van de afbeelding traceert sneller.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). De afbeelding is getraceerd op {_1} × {_2} pixels, verkleind van {_3} × {_4} (maximaal {_5} megapixels).
|
||||
@@ -5348,6 +5354,14 @@ swatch Bright Violet Felviolet
|
||||
Full Justify Volledig uitvullen
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum mag niet groter zijn dan Gewenst, en Gewenst niet groter dan Maximum.
|
||||
Justification Uitvullen
|
||||
Add filters from the list above Voeg filters toe uit de lijst hierboven
|
||||
Add to Stack Toevoegen aan stapel
|
||||
Applied Filters Toegepaste filters
|
||||
Categories Categorieën
|
||||
Choose a filter Kies een filter
|
||||
Effect Gallery Effectgalerij
|
||||
Filters Filters
|
||||
Select artwork to apply effects Selecteer grafiek om effecten toe te passen
|
||||
# Select by Color (select.color)
|
||||
Select by Color Selecteren op kleur
|
||||
Smudge Stick… Uitsmeerstift…
|
||||
@@ -5401,8 +5415,5 @@ swatch Bright Violet Felviolet
|
||||
Shift: Verschuiving:
|
||||
Fresco… Fresco…
|
||||
Fresco Fresco
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Illustratie neerzetten
|
||||
@msg {key} must be [x, y] with finite coordinates {key} moet [x, y] met eindige coördinaten zijn
|
||||
@msg ids must contain 1–10000 object ids ids moet 1–10000 object-id’s bevatten
|
||||
Effect Gallery… Effectgalerij…
|
||||
Effect Gallery Dialog Dialoogvenster Effectgalerij
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -38,6 +38,11 @@
|
||||
Medium Light Średnio jasny
|
||||
Light Jasny
|
||||
Quit VectorCraft Zakończ VectorCraft
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Upuść kompozycję
|
||||
@msg {key} must be [x, y] with finite coordinates {key} musi mieć postać [x, y] ze skończonymi współrzędnymi
|
||||
@msg ids must contain 1–10000 object ids ids musi zawierać od 1 do 10000 identyfikatorów obiektów
|
||||
|
||||
File Plik
|
||||
New… Nowy…
|
||||
New Without Dialog Nowy bez okna dialogowego
|
||||
@@ -5185,6 +5190,7 @@ mark-style Japanese Japońskie
|
||||
@msg Persistent libraries not found: {files} Nie znaleziono trwałych bibliotek: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` nie jest panelem biblioteki (zobacz window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open panel biblioteki `{given}` nie jest otwarty
|
||||
@msg library panel `{given}` isn't missing its library panelowi biblioteki `{given}` nie brakuje biblioteki
|
||||
@msg too many library panels were opened in this session w tej sesji otwarto zbyt wiele paneli bibliotek
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Obraz ma {_1} × {_2} pikseli, ponad {LARGE_TRACE_SIDE} na jednym boku: zostanie obrysowany, ale wolniej. Ustawienie wstępne o niższej wierności lub mniejsza kopia obrazu obrysuje się szybciej.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Obraz obrysowano w rozdzielczości {_1} × {_2} pikseli, po zmniejszeniu z {_3} × {_4} (najwyżej {_5} megapikseli).
|
||||
@@ -5205,6 +5211,14 @@ mark-style Japanese Japońskie
|
||||
Full Justify Pełne justowanie
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum nie może przekraczać wartości optymalnej, a wartość optymalna maksimum.
|
||||
Justification Justowanie
|
||||
Add filters from the list above Dodaj filtry z listy powyżej
|
||||
Add to Stack Dodaj do stosu
|
||||
Applied Filters Zastosowane filtry
|
||||
Categories Kategorie
|
||||
Choose a filter Wybierz filtr
|
||||
Effect Gallery Galeria efektów
|
||||
Filters Filtry
|
||||
Select artwork to apply effects Wybierz grafikę, aby zastosować efekty
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them zmienne i zestawy danych pliku nie zostały wczytane (zmienne: {variables}, zestawy danych: {data_sets}): panel Zmienne ich nie wyświetla
|
||||
# Select by Color (select.color)
|
||||
Select by Color Zaznacz według koloru
|
||||
@@ -5238,8 +5252,5 @@ mark-style Japanese Japońskie
|
||||
Shift: Przesunięcie:
|
||||
Fresco… Fresk…
|
||||
Fresco Fresk
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Upuść kompozycję
|
||||
@msg {key} must be [x, y] with finite coordinates {key} musi mieć postać [x, y] ze skończonymi współrzędnymi
|
||||
@msg ids must contain 1–10000 object ids ids musi zawierać od 1 do 10000 identyfikatorów obiektów
|
||||
Effect Gallery… Galeria efektów…
|
||||
Effect Gallery Dialog Okno dialogowe Galeria efektów
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -947,6 +947,11 @@
|
||||
Fidelity: Fidelidade:
|
||||
Figure Space Espaço de Figura
|
||||
Figure: Figura:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Soltar arte
|
||||
@msg {key} must be [x, y] with finite coordinates {key} deve ser [x, y] com coordenadas finitas
|
||||
@msg ids must contain 1–10000 object ids ids deve conter de 1 a 10000 IDs de objetos
|
||||
|
||||
File Arquivo
|
||||
File Format: Formato do Arquivo:
|
||||
File Formats Formatos de Arquivo
|
||||
@@ -5250,6 +5255,7 @@ mark-style Japanese Japonesas
|
||||
@msg Persistent libraries not found: {files} Bibliotecas persistentes não encontradas: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` não é um painel de biblioteca (consulte window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open o painel de biblioteca `{given}` não está aberto
|
||||
@msg library panel `{given}` isn't missing its library a biblioteca do painel de biblioteca `{given}` não está faltando
|
||||
@msg too many library panels were opened in this session foram abertos painéis de biblioteca demais nesta sessão
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. A imagem tem {_1} × {_2} pixels, mais de {LARGE_TRACE_SIDE} em um lado: ela é traçada, mas mais devagar. Uma predefinição de menor fidelidade ou uma cópia menor da imagem traça mais rápido.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). A imagem foi traçada em {_1} × {_2} pixels, reduzida de {_3} × {_4} (no máximo {_5} megapixels).
|
||||
@@ -5270,6 +5276,14 @@ mark-style Japanese Japonesas
|
||||
Full Justify Justificação Completa
|
||||
Minimum must not exceed Desired, nor Desired Maximum. O mínimo não pode passar do desejado, nem o desejado do máximo.
|
||||
Justification Justificação
|
||||
Add filters from the list above Adicione filtros da lista acima
|
||||
Add to Stack Adicionar à Pilha
|
||||
Applied Filters Filtros Aplicados
|
||||
Categories Categorias
|
||||
Choose a filter Escolha um filtro
|
||||
Effect Gallery Galeria de Efeitos
|
||||
Filters Filtros
|
||||
Select artwork to apply effects Selecione a arte para aplicar efeitos
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them as variáveis e os conjuntos de dados do arquivo não foram lidos (variáveis: {variables}, conjuntos de dados: {data_sets}): o painel Variáveis não os lista
|
||||
# Select by Color (select.color)
|
||||
Select by Color Selecionar por Cor
|
||||
@@ -5303,8 +5317,5 @@ mark-style Japanese Japonesas
|
||||
Shift: Deslocamento:
|
||||
Fresco… Afresco…
|
||||
Fresco Afresco
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Soltar arte
|
||||
@msg {key} must be [x, y] with finite coordinates {key} deve ser [x, y] com coordenadas finitas
|
||||
@msg ids must contain 1–10000 object ids ids deve conter de 1 a 10000 IDs de objetos
|
||||
Effect Gallery… Galeria de Efeitos…
|
||||
Effect Gallery Dialog Caixa de diálogo Galeria de Efeitos
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1067,6 +1067,11 @@
|
||||
Fidelity: Точность:
|
||||
Figure Space Цифровая шпация
|
||||
Figure: Цифры:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Поместить графику
|
||||
@msg {key} must be [x, y] with finite coordinates {key} должен быть [x, y] с конечными координатами
|
||||
@msg ids must contain 1–10000 object ids ids должен содержать от 1 до 10000 идентификаторов объектов
|
||||
|
||||
File Файл
|
||||
File Dimensions Размеры файла
|
||||
File Format: Формат файла:
|
||||
@@ -4943,6 +4948,7 @@ lighting Light Свет
|
||||
@msg Persistent libraries not found: {files} Постоянные библиотеки не найдены: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` — не панель библиотеки (см. window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open панель библиотеки `{given}` не открыта
|
||||
@msg library panel `{given}` isn't missing its library библиотека панели библиотеки `{given}` не отсутствует
|
||||
@msg too many library panels were opened in this session в этом сеансе открыто слишком много панелей библиотек
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Изображение {_1} × {_2} пикселей, больше {LARGE_TRACE_SIDE} по одной стороне: трассировка выполняется, но медленнее. Стиль с меньшей точностью или уменьшенная копия изображения трассируются быстрее.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Изображение трассировано в размере {_1} × {_2} пикселей, уменьшенное с {_3} × {_4} (не более {_5} мегапикселей).
|
||||
@@ -4964,6 +4970,14 @@ lighting Light Свет
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Минимум не может превышать желательное значение, а желательное — максимум.
|
||||
Minimum Минимум
|
||||
Justification Выключка
|
||||
Add filters from the list above Добавьте фильтры из списка выше
|
||||
Add to Stack Добавить в стек
|
||||
Applied Filters Применённые фильтры
|
||||
Categories Категории
|
||||
Choose a filter Выберите фильтр
|
||||
Effect Gallery Галерея эффектов
|
||||
Filters Фильтры
|
||||
Select artwork to apply effects Выберите графику, чтобы применить эффекты
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them переменные и наборы данных файла не прочитаны (переменных: {variables}, наборов данных: {data_sets}): панель «Переменные» их не показывает
|
||||
# Select by Color (select.color)
|
||||
Select by Color Выделить по цвету
|
||||
@@ -4997,8 +5011,5 @@ lighting Light Свет
|
||||
Shift: Сдвиг:
|
||||
Fresco… Фреска…
|
||||
Fresco Фреска
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Поместить графику
|
||||
@msg {key} must be [x, y] with finite coordinates {key} должен быть [x, y] с конечными координатами
|
||||
@msg ids must contain 1–10000 object ids ids должен содержать от 1 до 10000 идентификаторов объектов
|
||||
Effect Gallery… Галерея эффектов…
|
||||
Effect Gallery Dialog Диалог «Галерея эффектов»
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1051,6 +1051,11 @@
|
||||
Fidelity: Återgivning:
|
||||
Figure Space Siffermellanrum
|
||||
Figure: Figur:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Släpp grafik
|
||||
@msg {key} must be [x, y] with finite coordinates {key} måste vara [x, y] med ändliga koordinater
|
||||
@msg ids must contain 1–10000 object ids ids måste innehålla 1–10000 objekt-id:n
|
||||
|
||||
File Fil
|
||||
File Dimensions Fildimensioner
|
||||
File Format: Filformat:
|
||||
@@ -5289,6 +5294,7 @@ theme Appearance Utseende
|
||||
@msg Persistent libraries not found: {files} Beständiga bibliotek hittades inte: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` är inte en bibliotekspanel (se window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open bibliotekspanelen `{given}` är inte öppen
|
||||
@msg library panel `{given}` isn't missing its library bibliotekspanelen `{given}` saknar inte sitt bibliotek
|
||||
@msg too many library panels were opened in this session för många bibliotekspaneler har öppnats i den här sessionen
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Bilden är {_1} × {_2} pixlar, mer än {LARGE_TRACE_SIDE} på en sida: den vektoriseras, men långsammare. En förinställning med lägre återgivning eller en mindre kopia av bilden går snabbare.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Bilden vektoriserades vid {_1} × {_2} pixlar, nedskalad från {_3} × {_4} (högst {_5} megapixlar).
|
||||
@@ -5309,6 +5315,14 @@ theme Appearance Utseende
|
||||
Full Justify Fullständig marginaljustering
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Minimum får inte överstiga Önskat, och Önskat inte Maximum.
|
||||
Justification Justering
|
||||
Add filters from the list above Lägg till filter från listan ovan
|
||||
Add to Stack Lägg till i stacken
|
||||
Applied Filters Tillämpade filter
|
||||
Categories Kategorier
|
||||
Choose a filter Välj ett filter
|
||||
Effect Gallery Effektgalleri
|
||||
Filters Filter
|
||||
Select artwork to apply effects Välj grafik för att tillämpa effekter
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them filens variabler och datauppsättningar lästes inte (variabler: {variables}, datauppsättningar: {data_sets}): panelen Variabler visar dem inte
|
||||
# Select by Color (select.color)
|
||||
Select by Color Markera efter färg
|
||||
@@ -5342,8 +5356,5 @@ theme Appearance Utseende
|
||||
Shift: Förskjutning:
|
||||
Fresco… Fresk…
|
||||
Fresco Fresk
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Släpp grafik
|
||||
@msg {key} must be [x, y] with finite coordinates {key} måste vara [x, y] med ändliga koordinater
|
||||
@msg ids must contain 1–10000 object ids ids måste innehålla 1–10000 objekt-id:n
|
||||
Effect Gallery… Effektgalleri…
|
||||
Effect Gallery Dialog Dialogrutan Effektgalleri
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -870,7 +870,7 @@ fn cs() -> Lang {
|
||||
}
|
||||
|
||||
/// Languages whose catalogs leave [`MENU_KEEP_AS_IS`] in English.
|
||||
const KEEPS_MENU_NAMES: [&str; 17] = ["cs", "de", "el", "es", "fr", "hu", "it", "ja", "ka", "ko", "pl", "pt-br", "ru", "sv", "uk", "vi", "fi"];
|
||||
const KEEPS_MENU_NAMES: [&str; 18] = ["cs", "de", "el", "es", "fr", "hu", "it", "ja", "ka", "ko", "pl", "pt-br", "ru", "sv", "uk", "vi", "fi", "tr"];
|
||||
|
||||
/// Menu labels the menu-complete catalogs (Czech, German, Spanish, Italian, Japanese, Brazilian Portuguese) show as they are: the product name, a format name, the built-in workspace
|
||||
/// names and the perspective grid presets (names, shown untranslated wherever else they appear).
|
||||
@@ -1190,6 +1190,41 @@ fn finnish_reads_as_finnish() {
|
||||
assert_eq!(message(fi(), nested), "komento `object.group` ei ole nyt käytettävissä: mitään ei ole valittu");
|
||||
}
|
||||
|
||||
/// The Turkish catalog registers under `tr`, claims complete menus and messages, and passes
|
||||
/// locale resolution, vocabulary and count formatting checks.
|
||||
#[test]
|
||||
fn turkish_reads_as_turkish() {
|
||||
assert_eq!(tr_lang().name(), "Türkçe");
|
||||
assert!(tr_lang().complete_menus());
|
||||
assert_eq!(Lang::from_pref("tr"), tr_lang());
|
||||
assert_eq!(Lang::from_pref("TR"), tr_lang());
|
||||
for tag in ["tr", "tr-TR", "tr_TR.UTF-8", "TR-tr", "tr-CY"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(tr_lang()), "{tag}");
|
||||
}
|
||||
for (en, want) in [
|
||||
("Artboard Tool", "Çalışma Yüzeyi Aracı"),
|
||||
("Swatches", "Renk Örnekleri"),
|
||||
("Stroke", "Kontur"),
|
||||
("Fill", "Dolgu"),
|
||||
("Direct Selection Tool", "Doğrudan Seçim Aracı"),
|
||||
("Save As…", "Farklı Kaydet…"),
|
||||
("Undo", "Geri Al"),
|
||||
("Close", "Kapat"),
|
||||
] {
|
||||
assert_eq!(tr(tr_lang(), en), want);
|
||||
}
|
||||
for n in [0, 1, 3, 21] {
|
||||
assert_eq!(trn(tr_lang(), n, "{n} Layer", "{n} Layers"), format!("{n} Katman"));
|
||||
}
|
||||
let nested = "command `object.group` is not available right now: nothing selected";
|
||||
assert_eq!(message(tr_lang(), nested), "`object.group` komutu şu anda kullanılamıyor: hiçbir şey seçilmedi");
|
||||
}
|
||||
|
||||
/// The [`Lang`] handle for the Turkish catalog.
|
||||
fn tr_lang() -> Lang {
|
||||
Lang::from_code("tr").expect("tr registered")
|
||||
}
|
||||
|
||||
/// Ambiguous English terms keep their intended Vietnamese meaning across UI contexts.
|
||||
#[test]
|
||||
fn vietnamese_domain_terms_are_consistent() {
|
||||
@@ -2104,7 +2139,7 @@ fn shared_param_check_errors_are_translated() {
|
||||
|
||||
/// Languages whose catalogs cover every status and error message.
|
||||
const COMPLETE_MESSAGES: &[&str] =
|
||||
&["cs", "de", "el", "es", "fr", "hu", "it", "ja", "ka", "ko", "pl", "pt-br", "ru", "sv", "uk", "vi", "zh-hans", "zh-hant", "fi"];
|
||||
&["cs", "de", "el", "es", "fr", "hu", "it", "ja", "ka", "ko", "pl", "pt-br", "ru", "sv", "uk", "vi", "zh-hans", "zh-hant", "fi", "tr"];
|
||||
|
||||
/// Crates whose error and status messages reach the status bar.
|
||||
const MESSAGE_CRATES: &[&str] = &["ui-egui", "engine", "doc", "format", "svg", "pdf", "eps", "text", "plugins", "metafile", "cad", "trace"];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1063,6 +1063,11 @@
|
||||
Fidelity: Точність:
|
||||
Figure Space Цифрова шпація
|
||||
Figure: Цифри:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Розмістити графіку
|
||||
@msg {key} must be [x, y] with finite coordinates {key} має бути [x, y] зі скінченними координатами
|
||||
@msg ids must contain 1–10000 object ids ids має містити від 1 до 10000 ідентифікаторів об’єктів
|
||||
|
||||
File Файл
|
||||
File Dimensions Розміри файлу
|
||||
File Format: Формат файлу:
|
||||
@@ -4927,6 +4932,7 @@ lighting Light Світло
|
||||
@msg Persistent libraries not found: {files} Постійні бібліотеки не знайдено: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` — не панель бібліотеки (див. window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open панель бібліотеки `{given}` не відкрита
|
||||
@msg library panel `{given}` isn't missing its library бібліотека панелі бібліотеки `{given}` не відсутня
|
||||
@msg too many library panels were opened in this session у цьому сеансі відкрито забагато панелей бібліотек
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Зображення {_1} × {_2} пікселів, понад {LARGE_TRACE_SIDE} з одного боку: трасування виконується, але повільніше. Стиль із нижчою точністю або менша копія зображення трасуються швидше.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Зображення трасовано в розмірі {_1} × {_2} пікселів, зменшене з {_3} × {_4} (щонайбільше {_5} мегапікселів).
|
||||
@@ -4948,6 +4954,14 @@ lighting Light Світло
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Мінімум не може перевищувати бажане значення, а бажане — максимум.
|
||||
Minimum Мінімум
|
||||
Justification Вирівнювання за шириною
|
||||
Add filters from the list above Додайте фільтри зі списку вище
|
||||
Add to Stack Додати до стека
|
||||
Applied Filters Застосовані фільтри
|
||||
Categories Категорії
|
||||
Choose a filter Виберіть фільтр
|
||||
Effect Gallery Галерея ефектів
|
||||
Filters Фільтри
|
||||
Select artwork to apply effects Виберіть графіку, щоб застосувати ефекти
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them змінні та набори даних файлу не прочитано (змінних: {variables}, наборів даних: {data_sets}): панель «Змінні» їх не показує
|
||||
# Select by Color (select.color)
|
||||
Select by Color Виділити за кольором
|
||||
@@ -4981,8 +4995,5 @@ lighting Light Світло
|
||||
Shift: Зсув:
|
||||
Fresco… Фреска…
|
||||
Fresco Фреска
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Розмістити графіку
|
||||
@msg {key} must be [x, y] with finite coordinates {key} має бути [x, y] зі скінченними координатами
|
||||
@msg ids must contain 1–10000 object ids ids має містити від 1 до 10000 ідентифікаторів об’єктів
|
||||
Effect Gallery… Галерея ефектів…
|
||||
Effect Gallery Dialog Діалог «Галерея ефектів»
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 733 and column 40.
|
@@ -1232,6 +1232,11 @@
|
||||
Fidelity: Độ trung thực:
|
||||
Figure Space Khoảng trắng chữ số
|
||||
Figure: Chữ số:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Thả hình đồ họa
|
||||
@msg {key} must be [x, y] with finite coordinates {key} phải là [x, y] với tọa độ hữu hạn
|
||||
@msg ids must contain 1–10000 object ids ids phải chứa từ 1 đến 10000 mã định danh đối tượng
|
||||
|
||||
File Tệp
|
||||
File Dimensions Kích thước tệp
|
||||
File Format: Định dạng tệp:
|
||||
@@ -4927,6 +4932,7 @@ theme Appearance Giao diện
|
||||
@msg Persistent libraries not found: {files} Không tìm thấy thư viện lưu giữ: {files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` không phải là bảng thư viện (xem window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open bảng thư viện `{given}` chưa được mở
|
||||
@msg library panel `{given}` isn't missing its library thư viện của bảng thư viện `{given}` không bị thiếu
|
||||
@msg too many library panels were opened in this session đã mở quá nhiều bảng thư viện trong phiên này
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. Ảnh có kích thước {_1} × {_2} điểm ảnh, hơn {LARGE_TRACE_SIDE} ở một cạnh: ảnh vẫn được dò, nhưng chậm hơn. Một thiết lập sẵn có độ trung thực thấp hơn hoặc một bản sao nhỏ hơn của ảnh sẽ dò nhanh hơn.
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). Ảnh đã được dò ở {_1} × {_2} điểm ảnh, thu nhỏ từ {_3} × {_4} (tối đa {_5} megapixel).
|
||||
@@ -4948,6 +4954,14 @@ theme Appearance Giao diện
|
||||
Minimum must not exceed Desired, nor Desired Maximum. Giá trị tối thiểu không được vượt quá giá trị mong muốn, và giá trị mong muốn không được vượt quá tối đa.
|
||||
Minimum Tối thiểu
|
||||
Justification Căn đều
|
||||
Add filters from the list above Thêm bộ lọc từ danh sách phía trên
|
||||
Add to Stack Thêm vào ngăn xếp
|
||||
Applied Filters Bộ lọc đã áp dụng
|
||||
Categories Danh mục
|
||||
Choose a filter Chọn bộ lọc
|
||||
Effect Gallery Thư viện hiệu ứng
|
||||
Filters Bộ lọc
|
||||
Select artwork to apply effects Chọn đồ họa để áp dụng hiệu ứng
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them các biến và tập dữ liệu của tệp chưa được đọc (biến: {variables}, tập dữ liệu: {data_sets}): bảng Biến không liệt kê chúng
|
||||
# Select by Color (select.color)
|
||||
Select by Color Chọn theo màu
|
||||
@@ -4981,8 +4995,5 @@ theme Appearance Giao diện
|
||||
Shift: Dịch chuyển:
|
||||
Fresco… Bích họa…
|
||||
Fresco Bích họa
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork Thả hình đồ họa
|
||||
@msg {key} must be [x, y] with finite coordinates {key} phải là [x, y] với tọa độ hữu hạn
|
||||
@msg ids must contain 1–10000 object ids ids phải chứa từ 1 đến 10000 mã định danh đối tượng
|
||||
Effect Gallery… Thư viện hiệu ứng…
|
||||
Effect Gallery Dialog Hộp thoại Thư viện hiệu ứng
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4028 and column 10.
|
@@ -1010,6 +1010,11 @@
|
||||
Fidelity: 精确度:
|
||||
Figure Space 数字空格
|
||||
Figure: 数字:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork 放置图稿
|
||||
@msg {key} must be [x, y] with finite coordinates {key} 必须是具有有限坐标的 [x, y]
|
||||
@msg ids must contain 1–10000 object ids ids 必须包含 1–10000 个对象 ID
|
||||
|
||||
File 文件
|
||||
File Dimensions 文件尺寸
|
||||
File Format: 文件格式:
|
||||
@@ -5166,6 +5171,7 @@ lighting Light 光源
|
||||
@msg Persistent libraries not found: {files} 找不到持久库:{files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` 不是库面板 (请参阅 window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open 库面板 `{given}` 未打开
|
||||
@msg library panel `{given}` isn't missing its library 库面板 `{given}` 的库未缺失
|
||||
@msg too many library panels were opened in this session 本次会话中打开的库面板过多
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. 图像为 {_1} × {_2} 像素,某一边超过 {LARGE_TRACE_SIDE}:会进行描摹,但速度较慢。使用保真度较低的预设或图像的较小副本会更快。
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). 图像已按 {_1} × {_2} 像素描摹,由 {_3} × {_4} 缩小而来(最多 {_5} 百万像素)。
|
||||
@@ -5192,6 +5198,14 @@ lighting Light 光源
|
||||
Minimum must not exceed Desired, nor Desired Maximum. 最小值不能超过所需值,所需值不能超过最大值。
|
||||
Minimum 最小值
|
||||
Justification 对齐设置
|
||||
Add filters from the list above 从上方列表添加滤镜
|
||||
Add to Stack 添加到堆栈
|
||||
Applied Filters 已应用的滤镜
|
||||
Categories 类别
|
||||
Choose a filter 选择滤镜
|
||||
Effect Gallery 效果库
|
||||
Filters 滤镜
|
||||
Select artwork to apply effects 选择要应用效果的图稿
|
||||
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them 文件的变量和数据集未被读取(变量:{variables},数据集:{data_sets}):“变量”面板不会列出它们
|
||||
# Select by Color (select.color)
|
||||
Select by Color 按颜色选择
|
||||
@@ -5225,8 +5239,5 @@ lighting Light 光源
|
||||
Shift: 偏移:
|
||||
Fresco… 壁画…
|
||||
Fresco 壁画
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork 放置图稿
|
||||
@msg {key} must be [x, y] with finite coordinates {key} 必须是具有有限坐标的 [x, y]
|
||||
@msg ids must contain 1–10000 object ids ids 必须包含 1–10000 个对象 ID
|
||||
Effect Gallery… 效果库…
|
||||
Effect Gallery Dialog 效果库对话框
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1033,6 +1033,11 @@
|
||||
Fidelity: 精確度:
|
||||
Figure Space 數字空格
|
||||
Figure: 數字:
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork 放置圖稿
|
||||
@msg {key} must be [x, y] with finite coordinates {key} 必須是具有有限座標的 [x, y]
|
||||
@msg ids must contain 1–10000 object ids ids 必須包含 1–10000 個物件 ID
|
||||
|
||||
File 檔案
|
||||
File Dimensions 檔案尺寸
|
||||
File Format: 檔案格式:
|
||||
@@ -2329,6 +2334,7 @@ file-filter Templates 範本
|
||||
@msg Persistent libraries not found: {files} 找不到持久資料庫:{files}
|
||||
@msg `{given}` isn't a library panel (see window.swatchLibrary) `{given}` 不是資料庫面板 (請參閱 window.swatchLibrary)
|
||||
@msg library panel `{given}` isn't open 資料庫面板 `{given}` 未開啟
|
||||
@msg library panel `{given}` isn't missing its library 資料庫面板 `{given}` 的資料庫未遺失
|
||||
@msg too many library panels were opened in this session 本次工作階段開啟的資料庫面板過多
|
||||
@msg The image is {_1} × {_2} pixels, more than {LARGE_TRACE_SIDE} on a side: it is traced, but more slowly. A lower-fidelity preset or a smaller copy of the image traces faster. 影像為 {_1} × {_2} 像素,有一邊超過 {LARGE_TRACE_SIDE}:仍會描圖,但速度較慢。使用精確度較低的預設集或較小的影像拷貝,描圖會較快。
|
||||
@msg The image was traced at {_1} × {_2} pixels, scaled down from {_3} × {_4} ({_5} megapixels at most). 影像已以 {_1} × {_2} 像素描圖,由 {_3} × {_4} 縮小而來 (最多 {_5} 百萬像素)。
|
||||
@@ -4982,6 +4988,14 @@ lighting Light 光源
|
||||
Minimum must not exceed Desired, nor Desired Maximum. 最小值不可超過所需值,所需值不可超過最大值。
|
||||
Minimum 最小值
|
||||
Justification 對齊設定
|
||||
Add filters from the list above 從上方清單新增濾鏡
|
||||
Add to Stack 加入堆疊
|
||||
Applied Filters 已套用的濾鏡
|
||||
Categories 類別
|
||||
Choose a filter 選擇濾鏡
|
||||
Effect Gallery 效果庫
|
||||
Filters 濾鏡
|
||||
Select artwork to apply effects 選取要套用效果的圖稿
|
||||
# Select by Color (select.color)
|
||||
Select by Color 依顏色選取
|
||||
@msg missing integer `{key}` 未提供整數 `{key}`
|
||||
@@ -5020,8 +5034,5 @@ lighting Light 光源
|
||||
Shift: 偏移:
|
||||
Fresco… 壁畫…
|
||||
Fresco 壁畫
|
||||
|
||||
# Artwork drag between document tabs.
|
||||
Drop Artwork 放置圖稿
|
||||
@msg {key} must be [x, y] with finite coordinates {key} 必須是具有有限座標的 [x, y]
|
||||
@msg ids must contain 1–10000 object ids ids 必須包含 1–10000 個物件 ID
|
||||
Effect Gallery… 效果庫…
|
||||
Effect Gallery Dialog 效果庫對話框
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -857,6 +857,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
"",
|
||||
"{} open Document Raster Effects Settings (dialog `rasterEffectsSettings`: the document.rasterEffectsSettings fields); OK runs it. The menu item opens it too",
|
||||
),
|
||||
(
|
||||
"ui.effectGalleryDialog",
|
||||
"Effect Gallery Dialog",
|
||||
"",
|
||||
"{} open Effect Gallery (dialog `effectGallery`: browse raster filters, build a stack, OK applies it as separate effects in one undo step). Effect → Effect Gallery… opens it too",
|
||||
),
|
||||
(
|
||||
"ui.pdfPresetsDialog",
|
||||
"PDF Presets…",
|
||||
@@ -1770,6 +1776,7 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
|
||||
"file.exportAs" => io::export(app, s("format").as_deref(), s("path"), p),
|
||||
"ui.fileInfoDialog" => crate::dialogs::file_info::open(app),
|
||||
"ui.rasterEffectsSettingsDialog" => crate::dialogs::raster_effects::open(app),
|
||||
"ui.effectGalleryDialog" => crate::dialogs::effect_gallery::open(app, p),
|
||||
"ui.pdfPresetsDialog" => {
|
||||
crate::dialogs::pdf_presets::open(app, s("selected").as_deref());
|
||||
Ok(Value::Null)
|
||||
@@ -2436,7 +2443,7 @@ pub fn enabled(app: &VectorcraftApp, id: &str) -> bool {
|
||||
id if id.starts_with("view.goto") => {
|
||||
id["view.goto".len()..].parse::<usize>().is_ok_and(|n| n >= 1 && app.session.active().is_some_and(|d| n <= d.doc.views.len()))
|
||||
}
|
||||
"effect.dialog" | "ui.recolorDialog" => app.session.active().is_some_and(|d| !d.selection.is_empty()),
|
||||
"effect.dialog" | "ui.recolorDialog" | "ui.effectGalleryDialog" => app.session.active().is_some_and(|d| !d.selection.is_empty()),
|
||||
"ui.cropImage" => selected_image(app, |_| true),
|
||||
"effect.applyLast" | "effect.last" => app.last_effect.is_some() && app.session.active().is_some_and(|d| !d.selection.is_empty()),
|
||||
"file.export.pdf" | "ui.savePdfDialog" | "ui.fileInfoDialog" | "ui.rasterEffectsSettingsDialog" => app.session.active().is_some(),
|
||||
@@ -4055,6 +4062,7 @@ fn effect_menu() -> Vec<Item> {
|
||||
if !raster.is_empty() {
|
||||
out.push(Sep);
|
||||
out.push(Item::Header("Raster Effects"));
|
||||
out.push(c("Effect Gallery…", "ui.effectGalleryDialog"));
|
||||
out.extend(raster);
|
||||
}
|
||||
// Anything not placed above (future effects) still shows up.
|
||||
|
||||
@@ -767,7 +767,7 @@ pub(crate) fn load_library(app: &mut VectorcraftApp, params: Value) -> Result<Va
|
||||
|
||||
/// Other Library…: load the library (or document) at `path`, else one picked in an open dialog.
|
||||
pub(crate) fn other_library(app: &mut VectorcraftApp, path: Option<String>) -> Result<Value, String> {
|
||||
match library_panel::pick_library_file(app, path)? {
|
||||
match library_panel::pick_library_file(app, path, library_panel::library_pick_filters(GraphicStyleLibraries::KIND))? {
|
||||
Some(path) => load_library(app, json!({ "path": path })),
|
||||
None => Ok(Value::Null),
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ use std::sync::{Mutex, PoisonError};
|
||||
use egui::{Rect, Sense, Ui};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_engine::cmd::swatchlib::LibraryInfo;
|
||||
use vectorcraft_doc::style_libs::STYLES_EXT;
|
||||
use vectorcraft_engine::cmd::fileio;
|
||||
use vectorcraft_engine::cmd::swatchlib::{self, LibraryInfo};
|
||||
|
||||
use super::swatches::{View, click_selection, folder_tile, list_row, list_row_name, tile_grid};
|
||||
use super::{pstate, set_pstate};
|
||||
@@ -487,19 +489,24 @@ pub(crate) fn command(app: &mut VectorcraftApp, p: &Value) -> Result<Value, Stri
|
||||
}
|
||||
|
||||
/// `ui.libraryPanel.locate {panel, path?}`: Locate Library… of a library panel whose library is
|
||||
/// missing. Load the library at `path`, else one picked in an open dialog (on the web the picked
|
||||
/// file arrives later and opens in a panel of its own, as Other Library…'s does), and show it in
|
||||
/// open panel `panel`, which keeps its view, Show Find Field and Persistent. When the file's
|
||||
/// library has a panel open already, `panel` closes and is forgotten, and that panel is brought
|
||||
/// forward, made persistent when `panel` was. → what `ui.libraryPanel` answers
|
||||
/// missing ([`missing_file`]; any other panel is an error). Load the library at `path`, else one
|
||||
/// picked in an open dialog (on the web the picked file arrives later and opens in a panel of its
|
||||
/// own, as Other Library…'s does), and show it in open panel `panel`, which keeps its view, Show
|
||||
/// Find Field and Persistent. When the file's library has a panel open already, `panel` closes and
|
||||
/// is forgotten, and that panel is brought forward, made persistent when `panel` was. → what
|
||||
/// `ui.libraryPanel` answers
|
||||
pub(crate) fn locate(app: &mut VectorcraftApp, p: &Value) -> Result<Value, String> {
|
||||
let given = p.get("panel").and_then(Value::as_str).unwrap_or_default();
|
||||
let (k, id) = parse(given).ok_or_else(|| format!("`{given}` isn't a library panel (see window.swatchLibrary)"))?;
|
||||
if !is_open(&app.ui, given) {
|
||||
return Err(format!("library panel `{given}` isn't open"));
|
||||
}
|
||||
if missing_file(app, k, id).is_none() {
|
||||
return Err(format!("library panel `{given}` isn't missing its library"));
|
||||
}
|
||||
let path = p.get("path").and_then(Value::as_str).map(str::to_string);
|
||||
let Some(path) = pick_library_file(app, path)? else { return Ok(Value::Null) };
|
||||
let filters = library_pick_filters(k.kind);
|
||||
let Some(path) = pick_library_file(app, path, filters)? else { return Ok(Value::Null) };
|
||||
let r = app.run(k.load, json!({ "path": path }))?;
|
||||
let next = r["library"].as_str().unwrap_or_default().to_string();
|
||||
let to = panel_id(k.kind, &next);
|
||||
@@ -525,9 +532,22 @@ fn set(app: &mut VectorcraftApp, panel: &str, mut params: Value) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Open-dialog filters for Other Library… / Locate Library… of library panels of kind `kind`.
|
||||
pub(crate) fn library_pick_filters(kind: &str) -> Vec<(&'static str, &'static [&'static str])> {
|
||||
match kind {
|
||||
super::swatches::SwatchLibraries::KIND => fileio::library_open_filters("Swatch libraries", swatchlib::LIBRARY_EXTS).collect(),
|
||||
super::graphic_styles::GraphicStyleLibraries::KIND => fileio::library_open_filters("Graphic Style Libraries", &[STYLES_EXT]).collect(),
|
||||
_ => fileio::open_filters().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Other Library…: the library file at `path`, else one picked in an open dialog; `None` when the
|
||||
/// pick is asynchronous (on the web the picked file arrives later through [`crate::io::open_bytes`]).
|
||||
pub(crate) fn pick_library_file(app: &mut VectorcraftApp, path: Option<String>) -> Result<Option<String>, String> {
|
||||
pub(crate) fn pick_library_file(
|
||||
app: &mut VectorcraftApp,
|
||||
path: Option<String>,
|
||||
filters: Vec<(&'static str, &'static [&'static str])>,
|
||||
) -> Result<Option<String>, String> {
|
||||
if path.is_none()
|
||||
&& let Some(f) = app.services.open_async.as_mut()
|
||||
{
|
||||
@@ -535,7 +555,7 @@ pub(crate) fn pick_library_file(app: &mut VectorcraftApp, path: Option<String>)
|
||||
return Ok(None);
|
||||
}
|
||||
path.or_else(|| {
|
||||
let pick = crate::FilePick { filters: crate::FilePick::filters(vectorcraft_engine::cmd::fileio::open_filters()), ..Default::default() };
|
||||
let pick = crate::FilePick { filters: crate::FilePick::filters(filters), ..Default::default() };
|
||||
crate::picks::open(app, &pick)
|
||||
})
|
||||
.map(Some)
|
||||
@@ -1293,6 +1313,26 @@ mod tests {
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn locate_library_leaves_a_panel_whose_library_is_there_alone() {
|
||||
let dir = std::env::temp_dir().join(format!("vc-locate-found-library-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let gpl = dir.join("Brand.gpl");
|
||||
std::fs::write(&gpl, "GIMP Palette\nName: Brand\n#\n255 0 0\tRed\n").unwrap();
|
||||
let mut app = app();
|
||||
let pastels = panel_of(app.run("window.swatchLibrary", json!({"library": "pastels"})).unwrap());
|
||||
for persistent in [false, true] {
|
||||
app.run("ui.libraryPanel", json!({"panel": pastels, "persistent": persistent})).unwrap();
|
||||
let e = app.run("ui.libraryPanel.locate", json!({"panel": pastels, "path": gpl.to_string_lossy()})).unwrap_err();
|
||||
assert!(e.contains("isn't missing its library"), "{e}");
|
||||
assert!(is_open(&app.ui, &pastels), "persistent: {persistent}");
|
||||
assert_eq!(settings(&app.ui, "swatches", "pastels").map(|s| s.persistent), Some(persistent));
|
||||
}
|
||||
assert!(SwatchLibraries::get(&app, &format!("loaded/{}", gpl.to_string_lossy())).is_none(), "the file isn't loaded");
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn previous_and_next_show_the_neighbouring_library_in_the_same_panel() {
|
||||
let mut app = app();
|
||||
|
||||
@@ -382,6 +382,12 @@ pub(crate) fn proxy(app: &mut VectorcraftApp, ui: &mut Ui, size: f32) {
|
||||
if let Some(stroke) = c.pick {
|
||||
app.run("ui.colorPicker", json!({ "stroke": stroke })).ok();
|
||||
}
|
||||
if let Some(p) = c.dropped_fill {
|
||||
app.run("paint.setFill", p).ok();
|
||||
}
|
||||
if let Some(p) = c.dropped_stroke {
|
||||
app.run("paint.setStroke", p).ok();
|
||||
}
|
||||
}
|
||||
|
||||
/// The Fill (or `stroke`) chip of the Control bar and the Properties panel, `size` square (with a
|
||||
@@ -538,6 +544,43 @@ pub(crate) fn empty_state(ui: &mut Ui, icon: &str, title: &str, body: &str) {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dropping_a_proxy_paint_on_the_other_proxy_applies_it() {
|
||||
use egui::{Event, Modifiers, PointerButton};
|
||||
use vectorcraft_color::{Color, Paint};
|
||||
|
||||
use crate::widgets::PanelDrag;
|
||||
|
||||
let mut app = crate::VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 200})).unwrap();
|
||||
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 40, "height": 40})).unwrap();
|
||||
app.run("paint.setFill", json!({"color": "#ff0000"})).unwrap();
|
||||
app.run("paint.setStroke", json!({"color": "#0000ff"})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
let stroke_at = std::cell::Cell::new(egui::Pos2::ZERO);
|
||||
let frame = |app: &mut crate::VectorcraftApp, events: Vec<Event>| {
|
||||
let mut out = ctx.run_ui(egui::RawInput { events, ..Default::default() }, |ui| {
|
||||
proxy(app, ui, 36.0);
|
||||
if let Some(c) = ctx.read_response(ui.id().with("stroke-proxy")).map(|r| r.rect.center()) {
|
||||
stroke_at.set(c);
|
||||
}
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
};
|
||||
frame(&mut app, vec![]);
|
||||
let at = stroke_at.get();
|
||||
let red = PanelDrag::paint(Paint::solid(Color::from_hex("#ff0000").unwrap()));
|
||||
egui::DragAndDrop::set_payload(&ctx, red);
|
||||
let release = Event::PointerButton { pos: at, button: PointerButton::Primary, pressed: false, modifiers: Modifiers::NONE };
|
||||
frame(&mut app, vec![Event::PointerMoved(at), release]);
|
||||
let stroke = app.session.shown_stroke().unwrap();
|
||||
assert_eq!(stroke.paint.color().map(|c| c.to_hex()), Some("#ff0000".into()), "{}", app.ui.status);
|
||||
let st = app.session.active().unwrap();
|
||||
let id = st.selection.objects[0];
|
||||
assert_eq!(st.doc.node(id).unwrap().appearance.fill_paint().color().map(|c| c.to_hex()), Some("#ff0000".into()));
|
||||
assert!(egui::DragAndDrop::payload::<PanelDrag>(&ctx).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paint_params_roundtrip_shapes() {
|
||||
assert_eq!(paint_params(&Paint::None), json!({"none": true}));
|
||||
|
||||
@@ -1214,7 +1214,7 @@ pub(crate) fn load_library(app: &mut VectorcraftApp, params: Value) -> Result<Va
|
||||
/// Other Library…: load the library (or document) at `path`, else one picked in an open dialog
|
||||
/// (on the web the picked file arrives later and opens through [`crate::io::open_bytes`]).
|
||||
pub(crate) fn other_library(app: &mut VectorcraftApp, path: Option<String>) -> Result<Value, String> {
|
||||
match library_panel::pick_library_file(app, path)? {
|
||||
match library_panel::pick_library_file(app, path, library_panel::library_pick_filters(SwatchLibraries::KIND))? {
|
||||
Some(path) => load_library(app, json!({ "path": path })),
|
||||
None => Ok(Value::Null),
|
||||
}
|
||||
|
||||
@@ -260,7 +260,10 @@ fn other_swatch_library_asks_off_the_ui_thread() {
|
||||
app.run("swatch.new", json!({"name": "Signal", "color": "#ff3300"})).unwrap();
|
||||
let (dir, file) = saved_document(&mut app, "swatches");
|
||||
click(&mut app, "Other Library…", library_menu::<SwatchLibraries>);
|
||||
assert!(matches!(shown.requests().as_slice(), [PickRequest::Open(_)]));
|
||||
assert!(matches!(
|
||||
shown.requests().as_slice(),
|
||||
[PickRequest::Open(p)] if p.filters.first().is_some_and(|(label, exts)| label == "Swatch libraries" && exts.iter().any(|e| e == "ase"))
|
||||
));
|
||||
poll(&mut app);
|
||||
assert!(library_panel::last_open(&app.ui).is_none() && app.ui.status.is_empty(), "{}", app.ui.status);
|
||||
shown.answer(&[&file]);
|
||||
|
||||
@@ -44,6 +44,20 @@ pub fn flat_button(ui: &mut Ui, text: &str, width: f32) -> Response {
|
||||
resp
|
||||
}
|
||||
|
||||
/// A [`flat_button`] that expands to fit localized labels wider than `min_width`.
|
||||
pub fn flat_button_fit(ui: &mut Ui, text: &str, min_width: f32) -> Response {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let galley = ui.painter().layout_no_wrap(tl!(text).to_string(), egui::FontId::proportional(12.5), t.text_strong);
|
||||
let width = (galley.size().x + 24.0).max(min_width);
|
||||
let (rect, resp) = ui.allocate_exact_size(vec2(width, 24.0), Sense::click());
|
||||
let rect = rect.shrink2(vec2(0.0, 0.5));
|
||||
ui.painter().rect_filled(rect, CornerRadius::same(5), t.button);
|
||||
flat_fill(ui, rect, &resp);
|
||||
ui.painter().with_clip_rect(rect).text(rect.center(), egui::Align2::CENTER_CENTER, tl!(text), egui::FontId::proportional(12.5), t.text_strong);
|
||||
resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, ui.is_enabled(), tl!(text)));
|
||||
resp
|
||||
}
|
||||
|
||||
/// Width of a [`split_button`]'s arrow.
|
||||
pub const SPLIT_ARROW: f32 = 18.0;
|
||||
|
||||
@@ -825,7 +839,7 @@ pub fn chip_button_named(ui: &mut Ui, size: f32, chevron: bool, tip: &str, draw:
|
||||
}
|
||||
|
||||
/// What the user did on a [`fill_stroke_proxy`].
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ProxyClicks {
|
||||
pub fill: bool,
|
||||
pub stroke: bool,
|
||||
@@ -833,6 +847,10 @@ pub struct ProxyClicks {
|
||||
pub default: bool,
|
||||
/// Double-clicked a square: open the Color Picker for it (`true` = the stroke).
|
||||
pub pick: Option<bool>,
|
||||
/// A paint dragged from the other proxy (or a swatch) dropped on the fill square.
|
||||
pub dropped_fill: Option<serde_json::Value>,
|
||||
/// A paint dropped on the stroke square.
|
||||
pub dropped_stroke: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
/// The Fill/Stroke proxy pair (two overlapping squares). `mixed` (fill, stroke) draws a "?" square
|
||||
@@ -845,6 +863,8 @@ pub fn fill_stroke_proxy(ui: &mut Ui, fill: &Paint, stroke: &Paint, mixed: (bool
|
||||
let stroke_r = Rect::from_min_size(rect.max - Vec2::splat(s), Vec2::splat(s));
|
||||
let stroke_resp = ui.interact(stroke_r, ui.id().with("stroke-proxy"), Sense::click_and_drag());
|
||||
let fill_resp = ui.interact(fill_r, ui.id().with("fill-proxy"), Sense::click_and_drag());
|
||||
let dropped_fill = if mixed.0 { None } else { proxy_paint_drop(ui, &fill_resp) };
|
||||
let dropped_stroke = if mixed.1 { None } else { proxy_paint_drop(ui, &stroke_resp) };
|
||||
// A proxy drags its paint (onto the Swatches panel or art), unless it shows "?".
|
||||
for (resp, paint, mixed) in [(&fill_resp, fill, mixed.0), (&stroke_resp, stroke, mixed.1)] {
|
||||
if !mixed {
|
||||
@@ -901,9 +921,26 @@ pub fn fill_stroke_proxy(ui: &mut Ui, fill: &Paint, stroke: &Paint, mixed: (bool
|
||||
swap: swap.on_hover_text(tl!("Swap Fill and Stroke (Shift+X)")).clicked(),
|
||||
default: def.on_hover_text(tl!("Default Fill and Stroke (D)")).clicked(),
|
||||
pick,
|
||||
dropped_fill,
|
||||
dropped_stroke,
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`PanelDrag::Paint`] released on a Fill/Stroke proxy square: highlight while held over it.
|
||||
fn proxy_paint_drop(ui: &Ui, resp: &Response) -> Option<serde_json::Value> {
|
||||
if let Some(drag) = resp.dnd_hover_payload::<PanelDrag>()
|
||||
&& let PanelDrag::Paint { params, .. } = &*drag
|
||||
&& !params.is_null()
|
||||
{
|
||||
let t = Tokens::get(ui.ctx());
|
||||
ui.painter().rect_stroke(resp.rect, 0.0, Stroke::new(2.0, t.accent), StrokeKind::Outside);
|
||||
}
|
||||
resp.dnd_release_payload::<PanelDrag>().and_then(|d| {
|
||||
let PanelDrag::Paint { params, .. } = &*d else { return None };
|
||||
(!params.is_null()).then_some(params.clone())
|
||||
})
|
||||
}
|
||||
|
||||
/// A compact dropdown of interface labels (shown in the UI language). Returns the chosen index.
|
||||
pub fn dropdown(ui: &mut Ui, id: impl std::hash::Hash + std::fmt::Debug, current: &str, options: &[&str], width: f32) -> Option<usize> {
|
||||
dropdown_with(ui, id, current, options, width, |_| true)
|
||||
@@ -2845,3 +2882,24 @@ mod combo_keyboard_tests {
|
||||
assert!(!egui::Popup::is_any_open(&ctx), "the list closes after a keyboard pick");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod button_tests {
|
||||
use super::*;
|
||||
|
||||
/// [`flat_button_fit`] preserves minimum width for short labels and expands for long ones.
|
||||
#[test]
|
||||
fn flat_button_fit_expands_for_long_text() {
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
let raw = egui::RawInput::default();
|
||||
let mut out = ctx.run_ui(raw, |ui| {
|
||||
let resp_short = flat_button_fit(ui, "OK", 100.0);
|
||||
assert_eq!(resp_short.rect.width(), 100.0);
|
||||
|
||||
let resp_long = flat_button_fit(ui, "Çalışma Yüzeylerini Düzenle", 100.0);
|
||||
assert!(resp_long.rect.width() > 160.0);
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -431,7 +431,7 @@ onto a flyer through the command API; its screenshot was inspected, source prese
|
||||
Undo/Redo checked. Physical mouse hover on the desktop is not covered by that native smoke test.
|
||||
Public behavior reference: [Illustrator public duplication documentation](https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/duplicate-objects.html).
|
||||
The tab-hover workflow follows the contributor’s requested behavior. All test artwork is original geometry/text generated locally.
|
||||
The new command and validation messages are translated in all 23 language catalogs.
|
||||
The new command and validation messages are translated in all 24 language catalogs, including Turkish.
|
||||
Scores and hour estimates are unchanged.
|
||||
|
||||
## Revision history
|
||||
@@ -444,9 +444,10 @@ Scores and hour estimates are unchanged.
|
||||
| 2026-10-14 | minor | Document registration of every explicitly supplied craft-fonts face after the existing script-specific prefix; empty input and web selection remain unchanged. |
|
||||
| 2026-10-13 | minor | Document pinned PngSuite files, integrity checks and download budgets (#1729). |
|
||||
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream, including the Turkish catalog and all three tab-drag translations requested in #3479; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
|
||||
| Date | Change | Tab-drag history |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Merge current main and complete the Turkish tab-drag labels and validation messages requested by the maintainer; all 24 catalogs covered; scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
+2
-1
@@ -521,9 +521,10 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
| 2026-10-10 | minor | Alpha blockers checked against the core-workflow gate: none |
|
||||
| 2026-10-10 | major | Moved from the ROADMAP's "Where we're lacking"; kept ids G1–G8, added G9–G19 (file formats, stability, bugs, preferences, 30.x additions, pen hardware, performance, localization, ecosystem, AI, accessibility) and re-ranked |
|
||||
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream, including the Turkish catalog and all three tab-drag translations requested in #3479; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
|
||||
| Date | Change | Tab-drag history |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Merge current main and complete the Turkish tab-drag labels and validation messages requested by the maintainer; all 24 catalogs covered; scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
+3
-1
@@ -1718,7 +1718,9 @@ under `ui.library_panels`.
|
||||
`ui.libraryPanel.locate {panel, path?}` is Locate Library…: it loads the library at `path` (without one, it
|
||||
asks for a file) as Other Library… does and shows it in the open panel `panel`, which keeps its view, find
|
||||
field and Persistent, and answers as `ui.libraryPanel` does. When the file's library already has a panel open,
|
||||
`panel` closes and is forgotten, and that panel is brought forward, made persistent when `panel` was.
|
||||
`panel` closes and is forgotten, and that panel is brought forward, made persistent when `panel` was. On a
|
||||
panel whose library isn't missing, it answers an error without asking for or loading a file, and the panel
|
||||
keeps its library.
|
||||
`window.swatchLibrary` and `window.graphicStyleLibrary` also take a missing library's id, so a closed missing
|
||||
panel opens again; they answer its file's name without the extension and `count: 0`.
|
||||
|
||||
|
||||
+2
-1
@@ -221,9 +221,10 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
| 2026-10-10 | minor | Added the Alpha gate table (core-workflow gate): all six workflows work end to end, `.ai` exchange partial but not blocking; stage stays alpha |
|
||||
| 2026-10-10 | major | Created from ROADMAP.md's milestone table and "Where we're going"; added Current focus and the beta list |
|
||||
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream, including the Turkish catalog and all three tab-drag translations requested in #3479; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
|
||||
| Date | Change | Tab-drag history |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Merge current main and complete the Turkish tab-drag labels and validation messages requested by the maintainer; all 24 catalogs covered; scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
@@ -1132,9 +1132,10 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
| 2026-10-05 | major | (in ROADMAP.md) M3 and M4 rows re-derived after the paint and files milestones |
|
||||
| 2026-10-02 | major | (in ROADMAP.md) First 22-area weighted estimate |
|
||||
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream, including the Turkish catalog and all three tab-drag translations requested in #3479; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
|
||||
| Date | Change | Tab-drag history |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Merge current main and complete the Turkish tab-drag labels and validation messages requested by the maintainer; all 24 catalogs covered; scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
+2
-1
@@ -383,9 +383,10 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
| 2026-10-11 | minor | Direct Selection: dragging a path selected whole by an anchor moves it whole; Alt-drag copies by an anchor too, toggles during the drag and snaps onto the original (#1104); score unchanged (estimated) |
|
||||
| 2026-10-10 | major | First checklist, built from the tool sources and tests against Illustrator 2026's public documentation |
|
||||
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
> **Tab-drag status (2026-10-22):** updated from upstream, including the Turkish catalog and all three tab-drag translations requested in #3479; drag lifecycle, insertion and regression contracts documented; behavior, scores and estimates unchanged.
|
||||
|
||||
| Date | Change | Tab-drag history |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Merge current main and complete the Turkish tab-drag labels and validation messages requested by the maintainer; all 24 catalogs covered; scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
Reference in New Issue
Block a user