Print boards and cards with configurable components and named print profiles
⌘P had no story: KanbanApp removed the platform's Print row outright on 11-command-nexus.md's "No Print story in v1 (⌘P unused)" line. That line retires. File ▸ Print… now prints the board in front — lanes left to right, each lane's cards top to bottom, as a linear document rather than a picture of the strip — or, from a card window, that card. The trash is unreachable by construction: it is a sibling container of `lanes`, not a lane. The rules live in a pure layer nothing AppKit can reach. `PrintOptions` is one Codable value carrying the printing card's five bullets — which components (title, icon+labels line, rendered body, comments off by default with either reading order), page breaks, one base face and size every other size derives from, and a toggleable running head and foot. `PrintSource` is what is being printed, frozen at ⌘P so the panel's repeated relayouts and a board reloading underneath cannot disagree. `PrintDocumentBuilder` turns the pair into a block list, which is where every decision a rendered page hides becomes something a test can hold: component order, comment ordering, and page-break markers that are markers rather than whitespace. Empty is empty all the way up — a card with nothing to print consumes no page break, and a lane whose cards all dropped out takes its heading with it. A page break is a pagination fact, not a spacing one. TextKit has no page-break character, so `PrintDocumentView` splits the document into sections at its breaks and flows each into as many page-sized text containers as it needs: a container boundary *is* a sheet boundary, at any paper size with any margins. Bodies come from the app's one Markdown pass — `BodyMarkup.parse` into `BodyMarkupRenderer` — re-faced run by run so the chosen family reaches the text and fixed-pitch code keeps its own, and drawn under a forced light appearance so the card window's dynamic label colours do not print white. Options ride in the print panel's own accessory rather than a pre-flight sheet of ours, which buys the system's live preview of the real paginated document; the preview refreshes through one KVO revision counter rather than thirteen mirrored properties. Profiles persist app-side in UserDefaults, never in board files — a print profile is how this user likes to read, not what a board is (`BoardZoomStore`'s argument). A name is a profile's identity, folded case-insensitively; "Last Used" is reserved in every spelling, kept out of the stored list, and captured when an operation actually ran, so a cancelled print rewrites nothing. Both decoders are total: one unrecognized key must not cost a user every profile they saved. DESIGN/11-command-nexus.md gains the Print row and loses the sentence saying it would never have one. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
+15
-5
@@ -306,11 +306,21 @@ struct KanbanApp: App {
|
||||
}
|
||||
}
|
||||
|
||||
// "No Print story in v1 (⌘P unused)" (11-command-nexus.md ▸ Standard macOS furniture) — the
|
||||
// system's default Print item is removed outright rather than left dead, since a menu item
|
||||
// with nothing behind it is exactly what the Nexus's "a command absent here doesn't exist"
|
||||
// rules out in the other direction too.
|
||||
CommandGroup(replacing: .printItem) {}
|
||||
// File ▸ Print… (⌘P) — **the app's own row**, replacing the system's nil-target one
|
||||
// (11-command-nexus.md's Print row; the "No Print story in v1 (⌘P unused)" line it retired).
|
||||
//
|
||||
// `replacing: .printItem` rather than an addition, for the same reason Undo/Redo replace the
|
||||
// platform's pair: the standard rows are nil-target actions resolved through the responder
|
||||
// chain, and this app's print target is the *frontmatter-shaped document behind the focused
|
||||
// window*, which no responder vends. Two items sharing the title "Print…" is also exactly what
|
||||
// titles-are-API forbids.
|
||||
//
|
||||
// Page Setup… stays absent with it: the paper questions are answered in the print panel's own
|
||||
// page-setup group (`PrintCoordinator`), so a second dialog would be a second place to set one
|
||||
// margin.
|
||||
CommandGroup(replacing: .printItem) {
|
||||
PrintCommand(appModel: appModel)
|
||||
}
|
||||
|
||||
// Help carries "the one line teaching the System Settings remap path" (11-command-nexus.md ▸
|
||||
// Standard macOS furniture) — this app's whole Help menu, since there is no other content to
|
||||
|
||||
Reference in New Issue
Block a user