Type menu: Anti-Alias › None first and checked; checks follow the edited layer (#2983) (#2984)

- menu_catalog: add Type › Anti-Alias › None before Sharp, as in Photoshop.
  It used to come from the engine list, appended after Windows and built
  without a checked state, so a layer set to None showed no check.
- view_cmds::type_checked reads type_tool::target_text (the edited layer,
  else the active or a selected type layer), as the options bar and the
  Type commands do, not only the active layer.
- Anti-alias and orientation items stay check items (Some(false)) with no
  type layer, so the native menu doesn't rebuild.
- Parity floor 629 -> 630; docs/parity-checklist.md regenerated.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Valentin Klein
2026-10-11 17:35:38 +02:00
committed by GitHub
parent fd351918e5
commit 7fd5715dbd
6 changed files with 41 additions and 11 deletions
+1
View File
@@ -454,6 +454,7 @@ pub static CATALOG: &[(&[&str], &str, Option<&str>, &str)] = &[
(&["Type", "Panels"], "Character Styles Panel", None, "type.panels.characterStyles"),
(&["Type", "Panels"], "Paragraph Styles Panel", None, "type.panels.paragraphStyles"),
(&["Type"], "---", None, "---"),
(&["Type", "Anti-Alias"], "None", None, "type.antiAlias.none"),
(&["Type", "Anti-Alias"], "Sharp", None, "type.antiAlias.sharp"),
(&["Type", "Anti-Alias"], "Crisp", None, "type.antiAlias.crisp"),
(&["Type", "Anti-Alias"], "Strong", None, "type.antiAlias.strong"),
+1 -1
View File
@@ -7,7 +7,7 @@ use crate::menu_catalog::CATALOG;
use crate::menus::is_live;
/// Minimum number of live catalog items. Raise it when parity grows; never lower it.
pub const FLOOR: usize = 630;
pub const FLOOR: usize = 631;
/// One top-level menu's coverage.
#[derive(Clone, Debug, serde::Serialize)]
+27
View File
@@ -1408,6 +1408,33 @@ mod multi_layer_formatting {
assert_eq!(text(&app, ids[0]).antialias, AntiAlias::Sharp);
}
/// Type › Anti-Alias and Type › Orientation check the edited (else selected) layer's value.
#[test]
fn type_menu_checks_the_current_anti_alias_and_orientation() {
let (mut app, ids) = fixture();
app.run("type.antiAlias.none", json!({"layer": ids[0].0})).unwrap();
app.run("type.orientation.vertical", json!({"layer": ids[0].0})).unwrap();
app.run("type.antiAlias.crisp", json!({"layer": ids[1].0})).unwrap();
app.run("type.orientation.horizontal", json!({"layer": ids[1].0})).unwrap();
let checks = |app: &PhotocraftApp| -> Vec<String> {
let items = crate::menus::menu_items(app);
for id in ["type.antiAlias.none", "type.antiAlias.crisp", "type.orientation.horizontal", "type.orientation.vertical"] {
let it = items.iter().find(|i| i.id == id).unwrap();
assert!(it.checked.is_some(), "{id} is a check item");
}
items
.iter()
.filter(|i| (i.id.starts_with("type.antiAlias.") || i.id.starts_with("type.orientation.")) && i.checked == Some(true))
.map(|i| i.id.clone())
.collect()
};
editing(&mut app, ids[0]);
assert_eq!(checks(&app), ["type.antiAlias.none", "type.orientation.vertical"]);
app.ui.text_edit = None;
app.session.active_mut().unwrap().active_layer = Some(ids[1]);
assert_eq!(checks(&app), ["type.antiAlias.crisp", "type.orientation.horizontal"]);
}
#[test]
fn warp_dialog_captures_layer_selection_or_inline_edit_before_confirmation() {
for inline in [false, true] {
+8 -6
View File
@@ -397,17 +397,19 @@ pub fn checked(app: &PhotocraftApp, id: &str) -> Option<bool> {
})
}
/// Checkmarks of the Type menu's anti-aliasing, orientation and OpenType items.
/// Checkmarks of the Type menu's anti-aliasing, orientation and OpenType items, for the layer the
/// options bar and Properties show: the one being edited, else the active or a selected type layer.
/// Anti-aliasing and orientation stay check items (`Some(false)`) without a type layer: a native
/// menu can't change an item's kind in place.
fn type_checked(app: &PhotocraftApp, id: &str) -> Option<bool> {
use photocraft_doc::LayerContent;
let st = app.session.active()?;
let LayerContent::Text(t) = &st.doc.layer(st.active_layer?)?.content else { return None };
let t = crate::type_tool::target_text(app);
if let Some(k) = id.strip_prefix("type.antiAlias.") {
return Some(photocraft_engine::type_extra_cmds::aa_name(t.antialias) == k);
return Some(t.is_some_and(|t| photocraft_engine::type_extra_cmds::aa_name(t.antialias) == k));
}
if let Some(k) = id.strip_prefix("type.orientation.") {
return Some((t.orientation == photocraft_doc::text::Orientation::Vertical) == (k == "vertical"));
return Some(t.is_some_and(|t| (t.orientation == photocraft_doc::text::Orientation::Vertical) == (k == "vertical")));
}
let t = t?;
let tag = match id.strip_prefix("type.openType.")? {
"standardLigatures" => "liga",
"contextualAlternates" => "calt",
+2 -2
View File
@@ -2,7 +2,7 @@
Generated by `cargo xtask parity` from `crates/ui-egui/src/menu_catalog.rs` (Photoshop's menu tree) and the live command registry. Do not edit by hand.
**630 of 630 menu items live (100.0%).**
**631 of 631 menu items live (100.0%).**
| Menu | Live | Total | % |
|---|---:|---:|---:|
@@ -10,7 +10,7 @@ Generated by `cargo xtask parity` from `crates/ui-egui/src/menu_catalog.rs` (Pho
| Edit | 75 | 75 | 100% |
| Image | 61 | 61 | 100% |
| Layer | 163 | 163 | 100% |
| Type | 44 | 44 | 100% |
| Type | 45 | 45 | 100% |
| Select | 25 | 25 | 100% |
| Filter | 75 | 75 | 100% |
| View | 74 | 74 | 100% |
+2 -2
View File
@@ -11,7 +11,7 @@ Generated by `cargo xtask scorecard` from `perf/budgets.toml`, `perf/baseline.js
| [Tools](#tools) | 25 | 16 | 2 | |
| [Workspace and UI](#workspace-and-ui) | 9 | 8 | 6 | settings that do nothing: 32 of 154 (target 0) |
| [Type](#type) | 1 | 4 | 4 | |
| [Automation](#automation) | 3 | 2 | 6 | 630 of 630 menu items live (100.0%) |
| [Automation](#automation) | 3 | 2 | 6 | 631 of 631 menu items live (100.0%) |
| [Reliability](#reliability) | 5 | 2 | 0 | never-crash lints on 28 of 28 crates; panic_hunt present |
| [Distribution](#distribution) | 5 | 4 | 2 | |
| [Open bugs](#open-bugs) | 29 | 2 | 1 | |
@@ -222,7 +222,7 @@ Unread: `general.color_picker`, `general.animated_zoom`, `general.zoom_resizes_w
## Automation
Menu wiring (`docs/parity-checklist.md`): 630 of 630 menu items live (100.0%). This counts dispatch, not behaviour.
Menu wiring (`docs/parity-checklist.md`): 631 of 631 menu items live (100.0%). This counts dispatch, not behaviour.
| Id | Target | Status | Issue | Note |
|---|---|---|---|---|