structured data editor
git clone https://git.lucas.co/cce-data-editor.git
relief values get the bevel-preview row; click opens cce-relief --key
A (relief)-annotated value — and any key named line_relief still in
integer form, the annotation only appears once a material is saved —
shows the BevelPreview cross-section (seeded from the value's k= knob
triple) instead of a plain int/text editor, and clicking it opens
cce-relief targeted at that single key (--key <flat.path>, plus
--config for the file being edited) rather than the file's shared
material. Verified in a shadow session: preview row on the
integer-form key, and the click spawns cce-relief with the right argv.
Co-Authored-By: Claude Fable 5 <[email protected]>
CLAUDE.md | 6 ++++++
src/main.rs | 46 ++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index cea6b69..6424e40 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -80,6 +80,12 @@ appears is decided in two places that must stay in agreement: the layout block i
"shoulder,base,bias" value; clicking opens `cce-relief`, whose Save is picked
up by the disk-sync watch). The annotation stays `bevel` — it is a config key,
and did not follow the tool's rename from `cce-bevel`.
+ `relief` → the same `BevelPreview`, seeded from the `(relief)` value's `k=`
+ knob triple (`cce_ui::relief_spec::ReliefSpec`), but clicking opens
+ `cce-relief --key <flat.path>` so Save rewrites that single value instead of
+ the file's shared material. Keys NAMED `line_relief` get this treatment even
+ while their value is still a plain integer (the annotation only exists once
+ a material was saved) — same key-name-heuristic convention as fonts.
- **Key-name heuristics**: `font` / `*_font` / `*.font` → `FontSelector`; keybind-ish
names (`key`, `shortcut`, `brightness_up`, …) → `KeybindRecorder`.
- **Value shape**: `#`-prefixed string → `ColorSelector`, bool → `Checkbox`,
diff --git a/src/main.rs b/src/main.rs
index dd7ca7d..8c70f4b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -630,6 +630,21 @@ impl DataEditorApp {
let local = format!("{home}/.local/bin/cce-relief");
let cmd = if std::path::Path::new(&local).exists() { local } else { "cce-relief".to_string() };
let mut command = std::process::Command::new(&cmd);
+ // A relief-valued key (the (relief) annotation, or a line_relief key
+ // still in integer form) targets its own single value: cce-relief
+ // --key seeds from it and Save rewrites only it. A (bevel) key keeps
+ // editing the file's shared material.
+ let relief_key = self.selected_key_idx.and_then(|idx| {
+ let key = self.flat_keys[idx].0.clone();
+ let by_anno = cce_ui::config::get_kdl_type_annotation(&self.raw_json_editor.text, &key)
+ .as_deref()
+ == Some("relief");
+ let by_name = key == "line_relief" || key.ends_with(".line_relief");
+ (by_anno || by_name).then_some(key)
+ });
+ if let Some(ref key) = relief_key {
+ command.args(["--key", key]);
+ }
// Target the file being edited: per-app configs get their own
// material instead of cce-relief's default shared-config.kdl save.
if let Some(ref path) = self.current_file_path {
@@ -1600,6 +1615,7 @@ impl Application for DataEditorApp {
let mut menu_options = Vec::new();
let mut is_button_type = false;
let mut is_bevel_type = false;
+ let mut is_relief_type = false;
let mut annotation_str = None;
if let Some(annotation) = cce_ui::config::get_kdl_type_annotation(&self.raw_json_editor.text, key_name) {
annotation_str = Some(annotation.clone());
@@ -1611,16 +1627,38 @@ impl Application for DataEditorApp {
is_button_type = true;
} else if annotation == "bevel" {
is_bevel_type = true;
+ } else if annotation == "relief" {
+ is_relief_type = true;
}
}
+ // line_relief keys get the relief treatment even in
+ // integer form (the (relief) annotation only appears once
+ // a material was saved): the preview is the affordance
+ // that opens cce-relief --key on them — same key-name
+ // heuristic convention as fonts and keybinds.
+ if !is_relief_type
+ && !is_bevel_type
+ && (key_name == "line_relief" || key_name.ends_with(".line_relief"))
+ {
+ is_relief_type = true;
+ }
// Parked unless the bevel branch below places it (the other
// branches never show it, so one shared park suffices).
self.selected_bevel_editor.set_rect(-1000.0, -1000.0, 1.0, 1.0);
- if is_bevel_type {
- // The (bevel) preview: a mini lit cross-section of the
- // knob triple; clicking it opens cce-relief.
- if let serde_json::Value::String(st) = val {
+ if is_bevel_type || is_relief_type {
+ // The (bevel)/(relief) preview: a mini lit
+ // cross-section of the knob triple; clicking it opens
+ // cce-relief (targeted at the KEY for a relief value).
+ if is_relief_type {
+ let knobs = if let serde_json::Value::String(st) = val {
+ cce_ui::relief_spec::ReliefSpec::parse(st).and_then(|s| s.knobs)
+ } else {
+ None
+ };
+ let (a, b, c) = knobs.unwrap_or((0.5, 0.5, 0.5));
+ self.selected_bevel_editor.set_knobs_str(&format!("{a:.3},{b:.3},{c:.3}"));
+ } else if let serde_json::Value::String(st) = val {
self.selected_bevel_editor.set_knobs_str(st);
}
self.selected_bevel_editor.set_rect(row_x + 245.0, row_y + 1.0, 125.0, 26.0);