Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,47 @@ pack-view `raw_url` `enc()`s the built filename) so `#`→`%23` etc. survive
The Recolor pane (`ui_recolor`) applies per-image **adjustments** then a **palette
rematch**, and the *order* of all of it is user-controlled.

- **Pane layout: 8 collapsible, drag-reorderable sections (`RecolorSection`).** Below the
always-visible preview + toolbar row (`ui_recolor_toolbar`: the image Save/export actions
on the left, collapse/expand-all flush right — see below), the pane is a `for` loop over
`self.recolor_order` — `Palette · N colors` (the swatch grid + `Export .GPL…`, which is
about the palette and nothing else, so it lives with the swatches rather than on the
toolbar; it raises its request through the `gpl_export` out-param since the section body
is a closure) / `Cleaning` (the JPEG-clean
+ de-block + undither checkboxes, grouped) / `Resize` / `Adjustments` / `Pixelate` /
`Color balance` / `Post FX` / `Recolor` (Reduce + the palette chooser + dither + the
textmode export). Each renders through the free fn **`recolor_section`** = a drag grip
(`drag_handle`) + a `CollapsingState` header + an indented body, and each section's body is
its own `ui_sec_*` method so the loop stays a `match`. A trailing `*` in the header (and a
value, e.g. `Resize * · 320×200`) says a collapsed section is doing something.
- **The open state is OURS, not egui's** — a `[bool; COUNT]` indexed by discriminant. It
has to be: `persist_egui_memory()` is false (so egui's own collapsing state dies at
exit), and the toolbar's **collapse/expand-all** button has to be able to force every
section. So
`recolor_section` calls `state.set_open(open)` before drawing and hands the post-click
value back in `SectionHead::open`. NB forcing `open` means the header's own `clicked()`
no longer toggles anything (see `CollapsingHeader::open`), which is why the title label
is a `Sense::click()` `Label` that calls `state.toggle` itself.
- **Reordering** mirrors the Adjustments row drag: the grip sets `recolor_sec_drag`,
`recolor_section_drag` paints the insertion line and moves the section on release. The
drop targets are whole sections (header + body, measured with `ui.cursor().top()`), so
dragging over an expanded section lands where it looks like it should.
- **The toolbar row (`ui_recolor_toolbar`) is NOT one of the sections** — Save has to stay
reachable on a small screen whatever is collapsed, and the collapse-all button obviously
can't live inside the thing it collapses. It always draws (even with nothing to save) so
the toggle is always there. The button is flush right in a
`Layout::right_to_left`, directly over the sections it acts on, and styled like VSCode's
Explorer toolbar: icon-only (`icons::COLLAPSE_ALL`/`EXPAND_ALL`, the Codicons) and
`frame_when_inactive(false)` so it's frameless until hovered. It lived in the pane's
header row first, where a worded label pushed **Bypass** off the end of a docked pane.
- **Persistence:** `RECOLOR_SECTIONS_KEY` (a `Vec<u8>` of discriminants) +
`RECOLOR_OPEN_KEY` (a `Vec<bool>`), restored by the pure `recolor_order_from` /
`recolor_open_from` (unit-tested). Variants are **appended, never reordered or removed** —
an unknown id is dropped and a section missing from a saved order is *appended*, so a
config written before a section existed gains it at the end rather than losing it. The
toolbar button's right-click restores the default order; `⟲ Reset all` clears *settings*,
not the layout.

- **`Adjust`** holds 12 value fields (brightness, contrast, gamma, shadows, highlights,
posterize, hue, saturation, **vibrance**, pixelate, sharpen, **invert**) plus `order:
[OpKind; 19]` — a permutation of `OpKind::ALL`. **8 of those 19 are marker ops** (no
Expand Down Expand Up @@ -1442,6 +1483,12 @@ unchanged. Between them, **nothing we draw tofus.**
FontAwesome-based, so a low codepoint gets **shadowed** (music note → "fi"). Plane-15 is
untouchable by any other stacked font. Verify a new codepoint is in the font's cmap first
(fonttools: `TTFont(path)['cmap']`; a venv one-liner — see git log).
**The one sanctioned exception** is `COLLAPSE_ALL`/`EXPAND_ALL` (U+EAC5/U+EB95), Nerd Font's
**Codicons** — VSCode's own icon set, so a collapse/expand-all toolbar button reads exactly
like the one in VSCode's Explorer. Those sit *below* the FontAwesome range, so shadowing was
checked explicitly and none of Ubuntu-Light / NotoEmoji / emoji-icon-font / Hack / DejaVu Sans
has a glyph at either codepoint. Check the same way (across every font in `apply_fonts`, not
just Nerd Font) before reaching outside plane 15 again.
- **For a plain symbol**, a normal Unicode char (`·`/`…`/`×`/`★`) still just works via DejaVu.
- Only ASCII (`*`) or a *painted* shape (see `drag_handle`'s dots) if something tofus even with
both fallbacks (very new emoji / CJK / niche pictographs). When in doubt, test in the real app.
Expand Down
Loading