View › Hide Template (Cmd+Shift+W): template layers leave the canvas and come back (#2000)

Illustrator's View menu has Hide/Show Template (Shift+Ctrl+W) to leave
template layers off the screen while tracing. VectorCraft drew them (dimmed)
whatever the view, with no way to hide them short of disabling the template
option on each layer and losing the dimming.

- `view.template` toggles `ViewFlags::templates` (default on, kept across
  settings files); the View menu lists Hide Template after Lock Slices, and
  the label flips to Show Template.
- The canvas renders with the new `RenderOptions::hide_templates`, which
  leaves template layers out and nothing else; `skip_templates` (exports and
  thumbnails) also drops guide paths, so it is not reused.
- The fifteen menu catalogs translate both labels; `DYNAMIC_LABELS` lists them.

Tests: render `hide_template_leaves_only_the_template_layers_out` (the
template layer's square and image go, a guide path on another layer stays);
canvas `hide_template_leaves_template_layers_off_the_canvas` (real egui
frames: painted pixels, none after Hide Template, the same after Show
Template, each re-rendering once); the dynamic-label and catalog tests cover
the new pair.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
This commit is contained in:
wstock
2026-10-16 04:08:44 +07:00
committed by bflatastic
co-authored by Claude Fable 5.1
parent c54a9b0bef
commit 7b8730ec14
22 changed files with 117 additions and 1 deletions
+5 -1
View File
@@ -110,6 +110,8 @@ pub struct RenderOptions {
/// Leave template layers and guides out (exports and thumbnails: they're aids to drawing, not
/// artwork).
pub skip_templates: bool,
/// View › Hide Template: template layers left out of the screen view (guides stay).
pub hide_templates: bool,
/// Pattern editing mode's tile edge and swatch bounds colour (Object → Pattern → Tile Edge
/// Color), RGB.
pub tile_edge: [u8; 3],
@@ -220,6 +222,7 @@ impl Default for RenderOptions {
overprint_preview: false,
trim: false,
skip_templates: false,
hide_templates: false,
tile_edge: vectorcraft_doc::LAYER_COLORS[0].1,
guide: ([0x4a, 0xd8, 0xff], false),
mask_view: None,
@@ -1003,7 +1006,8 @@ impl Renderer {
/// Whether `a` is left out of this frame: hidden, a skipped template or guide, or culled.
fn skipped(&mut self, f: &Frame, a: &Arc<Node>) -> bool {
let skipped_template = f.opts.skip_templates && matches!(a.kind, NodeKind::Layer { template: true, .. } | NodeKind::Path { guide: true, .. });
let skipped_template = (f.opts.skip_templates || f.opts.hide_templates) && matches!(a.kind, NodeKind::Layer { template: true, .. })
|| f.opts.skip_templates && matches!(a.kind, NodeKind::Path { guide: true, .. });
if !a.visible || skipped_template || f.opts.hidden.contains(&a.id) {
return true;
}
+29
View File
@@ -119,6 +119,35 @@ fn a_template_layer_stays_in_preview_in_outline_view() {
assert_eq!(preview.pixel(25, 75), [255, 0, 0, 255]);
}
/// View › Hide Template (#2000) leaves template layers out of the screen view and nothing else:
/// a guide path on another layer still draws, unlike in an export.
#[test]
fn hide_template_leaves_only_the_template_layers_out() {
let mut d = doc(|k| {
if let NodeKind::Layer { template, .. } = k {
*template = true;
}
});
let top = d.add_layer(Some("Guides"));
let mut g = Node::path(d.alloc_id(), shapes::rectangle(Rect::new(70.0, 70.0, 90.0, 90.0)), Appearance::default());
if let NodeKind::Path { guide, .. } = &mut g.kind {
*guide = true;
}
d.insert(Some(top), 0, g).unwrap();
let render = |hide: bool| {
let opts = RenderOptions { background: Some([255, 255, 255, 255]), hide_templates: hide, ..Default::default() };
Renderer::new().render(&d, 100, 100, Affine::IDENTITY, &opts)
};
let guide_drawn = |r: &Rendered| (60..100).flat_map(|y| (60..100).map(move |x| (x, y))).any(|(x, y)| r.pixel(x, y) != [255, 255, 255, 255]);
let shown = render(false);
assert_ne!(shown.pixel(25, 25), [255, 255, 255, 255], "the template layer's square shows (dimmed)");
assert!(guide_drawn(&shown));
let hidden = render(true);
assert_eq!(hidden.pixel(25, 25), [255, 255, 255, 255], "Hide Template: the template layer is left out");
assert_eq!(hidden.pixel(65, 25), [255, 255, 255, 255], "its image too");
assert!(guide_drawn(&hidden), "the guide on the other layer still draws");
}
/// A guide path draws on screen only: exports leave it out, as they leave templates out (and as
/// the SVG, PSD and PDF exports and printing already do).
#[test]
+34
View File
@@ -283,6 +283,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
h,
outline: app.ui.view.outline,
trim: app.ui.view.trim_view,
templates: app.ui.view.templates,
ppp,
hidden: vec![],
rot: v.rotation,
@@ -331,6 +332,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
proof: vectorcraft_render::proof::active_proof(),
overprint_preview: vectorcraft_render::proof::overprint_preview_on(),
trim: app.ui.view.trim_view,
hide_templates: !app.ui.view.templates,
tile_edge: vectorcraft_color::Color::from_hex(&app.session.prefs.pattern_tile_edge_color).map_or(opts.tile_edge, |c| {
let [r, g, b, _] = c.to_rgba8(1.0);
[r, g, b]
@@ -3255,6 +3257,38 @@ mod tests {
assert!(w > 600 && !hard, "zoomed out: the screen's pixels");
}
/// View › Hide Template (#2000): a template layer's art leaves the canvas, and Show Template
/// draws it again, dimmed as before; each re-renders at once.
#[test]
fn hide_template_leaves_template_layers_off_the_canvas() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
app.canvas.worker_started = true; // render on this thread
app.session.execute("shape.rectangle", &json!({"x": 100, "y": 50, "width": 200, "height": 200})).unwrap();
let layer = app.session.active().unwrap().doc.layers[0].id.0;
app.session.execute("layer.template", &json!({"ids": [layer], "on": true})).unwrap();
let ctx = egui::Context::default();
// How many pixels of the art's raster one frame uploads are painted, None when it was not
// re-rendered.
let painted = |app: &mut VectorcraftApp| -> Option<usize> {
let (_, mut delta) = frame_output(app, &ctx);
let art = app.canvas.texture.as_ref().unwrap().id();
let n = delta.set.iter().find(|e| e.0.eq(&art)).and_then(|e| e.1.last()).map(|d| {
let egui::ImageData::Color(img) = &d.image;
img.pixels.iter().filter(|c| c.a() != 0).count()
});
delta.clear();
n
};
let shown = painted(&mut app).expect("the first frame renders the art");
assert!(shown > 1000, "the template layer's art is drawn: {shown} pixels");
assert_eq!(app.run("view.template", json!({})).unwrap(), json!(false));
assert_eq!(painted(&mut app), Some(0), "Hide Template re-renders without the template layer");
assert_eq!(painted(&mut app), None, "nothing changed: no re-render");
assert_eq!(app.run("view.template", json!({})).unwrap(), json!(true));
assert_eq!(painted(&mut app), Some(shown), "Show Template draws it again as before");
}
/// General › Anti-aliased Artwork (#394): on (the default), the art's edges are smoothed on
/// screen; off, every pixel is either painted or not, and turning it either way re-renders.
#[test]
+2
View File
@@ -504,6 +504,8 @@
Show Video Rulers Zobrazit video pravítka
Hide Bounding Box Skrýt ohraničovací rámeček
Show Bounding Box Zobrazit ohraničovací rámeček
Hide Template Skrýt šablonu
Show Template Zobrazit šablonu
Show Transparency Grid Zobrazit mřížku průhlednosti
Hide Transparency Grid Skrýt mřížku průhlednosti
Hide Text Threads Skrýt zřetězení textu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1253,6 +1253,7 @@
Hide Print Tiling Druckaufteilung ausblenden
Hide Rulers Lineale ausblenden
Hide Slices Slices ausblenden
Hide Template Vorlage ausblenden
Hide Text Threads Textverkettungen ausblenden
Hide Thumbnail Miniatur ausblenden
Hide Thumbnails Miniaturen ausblenden
@@ -2723,6 +2724,7 @@
Show Slices Slices einblenden
Show Swatch Bounds Farbfeldbegrenzung einblenden
Show Swatch Kinds Farbfeldarten einblenden
Show Template Vorlage einblenden
Show Text Threads Textverkettungen einblenden
Show The Home Screen When No Documents Are Open Startbildschirm anzeigen, wenn keine Dokumente geöffnet sind
Show Thumbnail Miniatur einblenden
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1270,6 +1270,7 @@
Hide Print Tiling Ocultar mosaico de impresión
Hide Rulers Ocultar reglas
Hide Slices Ocultar sectores
Hide Template Ocultar plantilla
Hide Text Threads Ocultar enlaces de texto
Hide Thumbnail Ocultar miniatura
Hide Thumbnails Ocultar miniaturas
@@ -2771,6 +2772,7 @@
Show Slices Mostrar sectores
Show Swatch Bounds Mostrar límites de muestra
Show Swatch Kinds Mostrar tipos de muestra
Show Template Mostrar plantilla
Show Text Threads Mostrar enlaces de texto
Show The Home Screen When No Documents Are Open Mostrar la pantalla de inicio cuando no haya documentos abiertos
Show Thumbnail Mostrar miniatura
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1269,6 +1269,7 @@
Hide Print Tiling Masquer les limites d’impression
Hide Rulers Masquer les règles
Hide Slices Masquer les tranches
Hide Template Masquer le modèle
Hide Text Threads Masquer les liens de texte
Hide Thumbnail Masquer la vignette
Hide Thumbnails Masquer les vignettes
@@ -2768,6 +2769,7 @@
Show Slices Afficher les tranches
Show Swatch Bounds Afficher les limites de la nuance
Show Swatch Kinds Afficher les types de nuance
Show Template Afficher le modèle
Show Text Threads Afficher les liens de texte
Show The Home Screen When No Documents Are Open Afficher l’écran d’accueil lorsqu’aucun document n’est ouvert
Show Thumbnail Afficher la vignette
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1613,6 +1613,7 @@
Hide Print Tiling Nyomtatási csempézés elrejtése
Hide Rulers Vonalzók elrejtése
Hide Slices Szeletek elrejtése
Hide Template Sablon elrejtése
Hide Text Threads Szövegláncok elrejtése
Hide Thumbnail Bélyegkép elrejtése
Hide Thumbnails Bélyegképek elrejtése
@@ -3354,6 +3355,7 @@
Show Slices Szeletek megjelenítése
Show Swatch Bounds Színminta határainak megjelenítése
Show Swatch Kinds Színmintafajták megjelenítése
Show Template Sablon megjelenítése
Show Text Threads Szövegláncok megjelenítése
Show The Home Screen When No Documents Are Open Kezdőképernyő megjelenítése, ha nincs nyitott dokumentum
Show Thumbnail Bélyegkép megjelenítése
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1269,6 +1269,7 @@
Hide Print Tiling Nascondi affiancamento di stampa
Hide Rulers Nascondi righelli
Hide Slices Nascondi sezioni
Hide Template Nascondi modello
Hide Text Threads Nascondi concatenamenti testo
Hide Thumbnail Nascondi miniatura
Hide Thumbnails Nascondi miniature
@@ -2774,6 +2775,7 @@
Show Slices Mostra sezioni
Show Swatch Bounds Mostra limiti campione
Show Swatch Kinds Mostra tipi di campione
Show Template Mostra modello
Show Text Threads Mostra concatenamenti testo
Show The Home Screen When No Documents Are Open Mostra la schermata iniziale quando non ci sono documenti aperti
Show Thumbnail Mostra miniatura
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -496,6 +496,7 @@
Show Video Rulers ビデオ定規を表示
Hide Bounding Box バウンディングボックスを隠す
Show Transparency Grid 透明グリッドを表示
Hide Template テンプレートを隠す
Hide Text Threads テキストのスレッドを隠す
Hide Gradient Annotator グラデーションガイドを隠す
Hide Corner Widget コーナーウィジェットを隠す
@@ -656,6 +657,7 @@
Preview プレビュー
Show Edges エッジを表示
Show Corner Widget コーナーウィジェットを表示
Show Template テンプレートを表示
Show Text Threads テキストのスレッドを表示
Hide Hidden Characters 制御文字を隠す
Show Gradient Annotator グラデーションガイドを表示
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -494,6 +494,7 @@
Show Video Rulers 비디오 눈금자 표시
Hide Bounding Box 경계 상자 숨기기
Show Transparency Grid 투명도 격자 표시
Hide Template 템플릿 숨기기
Hide Text Threads 문자 연결선 숨기기
Hide Gradient Annotator 그레이디언트 주석 숨기기
Hide Corner Widget 모퉁이 위젯 숨기기
@@ -654,6 +655,7 @@
Preview 미리 보기
Show Edges 가장자리 표시
Show Corner Widget 모퉁이 위젯 표시
Show Template 템플릿 표시
Show Text Threads 문자 스레드 표시
Hide Hidden Characters 숨겨진 문자 숨기기
Show Gradient Annotator 그레이디언트 주석 도구 표시
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -464,7 +464,9 @@
Show Bounding Box Pokaż obwiednię
Show Transparency Grid Pokaż siatkę przezroczystości
Hide Transparency Grid Ukryj siatkę przezroczystości
Hide Template Ukryj szablon
Hide Text Threads Ukryj wątki tekstu
Show Template Pokaż szablon
Show Text Threads Pokaż wątki tekstu
Hide Gradient Annotator Ukryj wskaźnik gradientu
Show Gradient Annotator Pokaż wskaźnik gradientu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1095,6 +1095,7 @@
Hide Print Tiling Ocultar Tesselação de Impressão
Hide Rulers Ocultar Réguas
Hide Slices Ocultar Fatias
Hide Template Ocultar Modelo
Hide Text Threads Ocultar Fios de Texto
Hide Thumbnail Ocultar Miniatura
Hide Thumbnails Ocultar Miniaturas
@@ -2272,6 +2273,7 @@
Show Slices Mostrar Fatias
Show Swatch Bounds Mostrar Limites das Amostras
Show Swatch Kinds Mostrar Tipos de Amostra
Show Template Mostrar Modelo
Show Text Threads Mostrar Fios de Texto
Show The Home Screen When No Documents Are Open Mostrar a Tela Inicial quando não houver Documentos Abertos
Show Thumbnail Mostrar Miniatura
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -1267,6 +1267,7 @@
Hide Print Tiling Скрыть разбиение для печати
Hide Rulers Скрыть линейки
Hide Slices Скрыть фрагменты
Hide Template Скрыть шаблон
Hide Text Threads Скрыть связи текста
Hide Thumbnail Скрыть миниатюру
Hide Thumbnails Скрыть миниатюры
@@ -2770,6 +2771,7 @@
Show Slices Показать фрагменты
Show Swatch Bounds Показать границы образца
Show Swatch Kinds Показать типы образцов
Show Template Показать шаблон
Show Text Threads Показать связи текста
Show The Home Screen When No Documents Are Open Показывать начальный экран, когда документы не открыты
Show Thumbnail Показать миниатюру
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -546,6 +546,7 @@ fn toggled_labels() -> Vec<String> {
"type.hiddenCharacters",
"view.gradientAnnotator",
"view.artboards",
"view.template",
"view.rulers",
"view.boundingBox",
"view.transparencyGrid",
+2
View File
@@ -1263,6 +1263,7 @@
Hide Print Tiling Приховати розбиття для друку
Hide Rulers Приховати лінійки
Hide Slices Приховати фрагменти
Hide Template Приховати шаблон
Hide Text Threads Приховати зв’язки тексту
Hide Thumbnail Приховати мініатюру
Hide Thumbnails Приховати мініатюри
@@ -2766,6 +2767,7 @@
Show Slices Показати фрагменти
Show Swatch Bounds Показати межі зразка
Show Swatch Kinds Показати типи зразків
Show Template Показати шаблон
Show Text Threads Показати зв’язки тексту
Show The Home Screen When No Documents Are Open Показувати початковий екран, коли документи не відкриті
Show Thumbnail Показати мініатюру
Can't render this file because it contains an unexpected character in line 718 and column 40.
+2
View File
@@ -1447,6 +1447,7 @@
Hide Print Tiling Ẩn ghép trang in
Hide Rulers Ẩn thước
Hide Slices Ẩn lát cắt
Hide Template Ẩn mẫu
Hide Text Threads Ẩn luồng văn bản
Hide Thumbnail Ẩn hình thu nhỏ
Hide Thumbnails Ẩn các hình thu nhỏ
@@ -3078,6 +3079,7 @@
Show Slices Hiện lát cắt
Show Swatch Bounds Hiện vùng giới hạn mẫu màu
Show Swatch Kinds Hiện loại mẫu màu
Show Template Hiện mẫu
Show Text Threads Hiện chuỗi văn bản
Show The Home Screen When No Documents Are Open Hiện màn hình chính khi không có tài liệu nào mở
Show Thumbnail Hiện hình thu nhỏ
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
1447
1448
1449
1450
1451
1452
1453
3079
3080
3081
3082
3083
3084
3085
+2
View File
@@ -1214,6 +1214,7 @@
Hide Print Tiling 隐藏打印分页
Hide Rulers 隐藏标尺
Hide Slices 隐藏切片
Hide Template 隐藏模板
Hide Text Threads 隐藏文本串接线
Hide Thumbnail 隐藏缩略图
Hide Thumbnails 隐藏缩略图
@@ -2617,6 +2618,7 @@
Show Slices 显示切片
Show Swatch Bounds 显示色板边界
Show Swatch Kinds 显示色板种类
Show Template 显示模板
Show Text Threads 显示文本串接线
Show The Home Screen When No Documents Are Open 没有打开文档时显示主页
Show Thumbnail 显示缩略图
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -1241,6 +1241,7 @@
Hide Print Tiling 隱藏列印分頁
Hide Rulers 隱藏尺標
Hide Slices 隱藏切片
Hide Template 隱藏範本
Hide Text Threads 隱藏文字串連
Hide Thumbnail 隱藏縮圖
Hide Thumbnails 隱藏縮圖
@@ -2747,6 +2748,7 @@
Show Slices 顯示切片
Show Swatch Bounds 顯示色票邊界
Show Swatch Kinds 顯示色票種類
Show Template 顯示範本
Show Text Threads 顯示文字串連
Show The Home Screen When No Documents Are Open 沒有開啟文件時顯示首頁
Show Thumbnail 顯示縮圖
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -321,6 +321,8 @@ pub struct CacheKey {
pub h: u32,
pub outline: bool,
pub trim: bool,
/// View › Hide Template: template layers left out ([`vectorcraft_render::RenderOptions::skip_templates`]).
pub templates: bool,
pub ppp: f32,
pub hidden: Vec<u64>,
pub rot: f64,
+12
View File
@@ -243,6 +243,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
),
("view.edges", "Hide Edges", "Cmd+H", "{}"),
("view.artboards", "Hide Artboards", "Cmd+Shift+H", "{}"),
(
"view.template",
"Hide Template",
"Cmd+Shift+W",
"{} template layers left off the canvas (Show Template draws them again, dimmed as before) → shown",
),
("view.rulers", "Show Rulers", "Cmd+R", "{}"),
("view.boundingBox", "Hide Bounding Box", "Cmd+Shift+B", "{}"),
("view.guides", "Hide Guides", "Cmd+;", "{}"),
@@ -1139,6 +1145,7 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
}
"view.edges" => flag(&mut app.ui.view.edges),
"view.artboards" => flag(&mut app.ui.view.artboards),
"view.template" => flag(&mut app.ui.view.templates),
"view.rulers" => flag(&mut app.ui.view.rulers),
"view.boundingBox" => flag(&mut app.ui.view.bounding_box),
"view.guides" => {
@@ -1671,6 +1678,7 @@ pub fn dynamic_label(app: &VectorcraftApp, id: &str, label: &str) -> String {
"view.outline" => if v.outline { "Preview" } else { "Outline" }.into(),
"window.workspace.reset" => format!("Reset {}", app.ui.workspace),
"view.edges" => if v.edges { "Hide Edges" } else { "Show Edges" }.into(),
"view.template" => if v.templates { "Hide Template" } else { "Show Template" }.into(),
"view.cornerWidget" => if v.corner_widgets { "Hide Corner Widget" } else { "Show Corner Widget" }.into(),
"view.textThreads" => if v.text_threads { "Hide Text Threads" } else { "Show Text Threads" }.into(),
"type.hiddenCharacters" => if v.hidden_chars { "Hide Hidden Characters" } else { "Show Hidden Characters" }.into(),
@@ -2650,6 +2658,7 @@ pub fn menu_tree_named(english_names: bool) -> Vec<(&'static str, Vec<Item>)> {
c("Show Print Tiling", "view.printTiling"),
c("Hide Slices", "view.slices.hide"),
c("Lock Slices", "view.slices.lock"),
c("Hide Template", "view.template"),
Sep,
sub("Rulers", vec![c("Show Rulers", "view.rulers"), todos("Change to Global Rulers", "Cmd+Alt+R"), todo("Show Video Rulers")]),
c("Hide Bounding Box", "view.boundingBox"),
@@ -3713,6 +3722,8 @@ pub const DYNAMIC_LABELS: &[&str] = &[
"Lock Guides",
"Show Slices",
"Hide Slices",
"Hide Template",
"Show Template",
"Hide Print Tiling",
"Show Print Tiling",
"Edit Envelope",
@@ -3967,6 +3978,7 @@ mod tests {
("view.textThreads", "Hide Text Threads", "Show Text Threads"),
("view.gradientAnnotator", "Hide Gradient Annotator", "Show Gradient Annotator"),
("type.hiddenCharacters", "Show Hidden Characters", "Hide Hidden Characters"),
("view.template", "Hide Template", "Show Template"),
] {
assert_eq!(dynamic_label(&app, id, ""), on);
app.run(id, json!({})).unwrap();
+4
View File
@@ -200,6 +200,9 @@ pub struct ViewFlags {
pub gradient_annotator: bool,
/// Type → Show Hidden Characters.
pub hidden_chars: bool,
/// View → Hide/Show Template: template layers drawn (dimmed) or left out of the canvas.
#[serde(default = "yes")]
pub templates: bool,
}
impl Default for ViewFlags {
@@ -222,6 +225,7 @@ impl Default for ViewFlags {
text_threads: true,
gradient_annotator: true,
hidden_chars: false,
templates: true,
}
}
}