1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! Per-file WORKBENCH registry — a UI FILTER over feature-CREATION.
//!
//! A "workbench" trims the feature-creation UI (the "Add new feature" palette and
//! the selection context bar) and can gate workbench-specific toolbar buttons /
//! panels. It NEVER changes what the feature history executes, renders, or lets
//! the user edit: a document full of sheet-metal features opens and works
//! identically under Modeling. The ONLY things a workbench touches are the palette
//! (see [`includes_feature`]) and the context offers.
//!
//! EXTENSIBILITY is the whole point: a new workbench = one new file here + one
//! entry in [`WORKBENCHES`]. No enums to edit. Each file exposes a single
//! `'static` [`Workbench`] that OWNS its own inclusion decision (`includes`), its
//! extra toolbar buttons (data only), and the ids of existing panels it claims.
//!
//! `"All"` is special: it accepts every feature and its buttons are the DERIVED
//! union of every other workbench's buttons ([`workbench_buttons`]) — never
//! hand-maintained — so adding a workbench automatically grows it.
/// The minimal view of one catalogue entry a workbench predicate consumes: the
/// feature `type` CODE (e.g. `"E"`, `"S"`, `"SM.F"`), read from the existing
/// app-side catalogue accessor ([`brep_render::features::feature_catalogue`]).
/// Each workbench file classifies DIRECTLY off this code (no kernel-stamped
/// category — the kernel stays untouched). Borrows from the runtime catalogue
/// JSON, hence the lifetime — the registry itself stays `'static` because the
/// fn-pointer predicate is higher-ranked over the borrow.
/// A workbench-specific toolbar button, DATA ONLY (no egui, no behavior): the
/// shared toolbar-button helper renders it and a click surfaces `id` out of the
/// toolbar to the shell, which dispatches on `id`. Phase 1 ships none.
/// One workbench: a UI filter + optional toolbar buttons + claimed panels. Fully
/// `'static` — fn-pointer predicate and `&'static` slices, no `OnceLock`.
/// The fallback / default workbench id. Boot-read validation is implicit:
/// [`resolve`] maps any unknown stored id to this, so there is no separate boot
/// step — every consumer routes through `resolve`.
pub const DEFAULT_WORKBENCH_ID: &str = "modeling";
/// Every workbench, in DROPDOWN ORDER: All, Modeling, Sheet Metal. The dropdown
/// iterates THIS — labels are never hardcoded. A new workbench is appended here.
pub static WORKBENCHES: & = &;
/// Pure lookup by id — `None` if there is no such workbench.
/// Resolve a (possibly stale / unknown) stored id to a live workbench, falling
/// back to the default. This IS the boot/read validation — route ALL consumers
/// (dropdown display, palette/offer filters, buttons, panels) through here.
/// The active workbench's toolbar buttons. For `"all"` this is the DEDUPED UNION
/// of every workbench's buttons (so "All" shows every icon without a
/// hand-maintained list); for any other workbench it is that workbench's own
/// buttons.
/// Collect buttons across lists, keeping FIRST occurrence per `id` and preserving
/// order. The union logic behind [`workbench_buttons`] for `"all"`.
/// Whether a catalogue entry belongs in workbench `active_id`'s feature-creation
/// UI. The ONE entry point the palette + context-offer filters call: builds a
/// [`FeatureInfo`] from the feature `type_code` and runs the resolved workbench's
/// predicate (each workbench file owns its classification off the code).
/// Whether panel `panel_id` is visible in workbench `active_id`. Claim-based: a
/// panel is visible UNLESS it is claimed by ≥1 workbench and the active workbench
/// does not list it. `"all"` sees every panel (mirrors the button union). With
/// v1's empty `panels` slices nothing is claimed, so every panel is visible in
/// every workbench — the scaffolding is wired but hides nothing.
/// The workbench list as `{id, label}` JSON plus the resolved current id — the
/// `__brepWorkbench` logical-state global the headed verifier reads to drive the
/// dropdown and confirm the active workbench. `current` is the RESOLVED id (an
/// unknown stored id reads back as the default).
// BREP private tests: 2f65fdf0861e7fcb