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
176
177
178
179
180
181
182
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT
//! Child-forwarding table for container widgets.
//!
//! # What this module is, and what its name must not be read as
//!
//! [`SimpleRegistry`] is a **closure forwarding table**, not an ownership
//! registry. It maps an [`ObjectId`] to a draw closure, an event closure and an
//! optional geometry callback, so a container can paint and dispatch to a child
//! it holds only by id.
//!
//! The crate has three different things whose names sound alike, and conflating
//! them is the defect this note exists to prevent:
//!
//! | Name | Answers | Entry point | Owner |
//! |---|---|---|---|
//! | [`SimpleRegistry`] (here) | "how do I draw/forward to this id?" | [`SimpleRegistry::register`] | the container that holds it |
//! | `WidgetFactory` (`widget::capability`) | "how do I construct control *name*?" | `WidgetFactory::create` | the crate; one shared table |
//! | `widget::runtime` registry | "where is the live widget with this id?" | `widget::runtime::register` | the runtime, which owns mounting |
//!
//! The entry-point column is the enforceable part of the boundary (G-307): each
//! concept has exactly one function to start from, so a name written without its
//! entry point — "the registry" — is resolved by asking which entry point the
//! surrounding code calls. Reading a live widget is `widget::runtime::read_widget`,
//! the read counterpart of `runtime::register`; mounting owns the entry, so no
//! other table can answer that question.
//!
//! Ownership of a live control therefore lives in `widget::runtime`, never in
//! this table: dropping a [`SimpleRegistry`] removes its forwarding closures and
//! does not destroy a widget. A reader looking for "the registry" that owns the
//! widget tree should start at `widget::runtime`.
use crate;
use crate;
use crateEvent;
use crateRenderContext;
/// A forwarding table that maps an [`ObjectId`] to draw + event closures.
///
/// Container widgets use it to reach children they track only by id, without
/// requiring the event-dispatch layer to know their concrete type. It is a
/// **closure table, not an ownership registry** — see the module docs for the
/// three registry-shaped concepts in this crate and which one owns a live widget.
///
/// The name is historical. Renaming it would break the public surface for a
/// change that is purely about reading, so the distinction is stated here
/// instead; treat every "registry" mention in a container's documentation as
/// this table rather than as the runtime's widget map.
type DrawClosure = ;
type EventClosure = ;
type GeometryClosure = ;
// SAFETY: All types contained within SimpleRegistry implement Send:
// - HashMap<ObjectId, (DrawClosure, EventClosure)> where:
// * ObjectId: wraps a u64 — trivially Send.
// * DrawClosure = Box<dyn FnMut(&mut RenderContext) + Send>: Send because
// the closure is bounded by +Send and Box<dyn ... + Send> auto-implements Send.
// * EventClosure = Box<dyn FnMut(&Event) + Send>: same reasoning.
// - HashMap<K, V> implements Send when K: Send and V: Send, which holds here.
//
// SimpleRegistry is used in single-threaded contexts via Rc<RefCell<...>>,
// but the Send bound allows use in Arc<Mutex<...>> contexts. The interior
// HashMap is only accessed via &mut self, providing exclusive access, so
// there is no data race risk.
//
// NOTE: We do NOT implement Sync because Box<dyn FnMut(...) + Send> is
// not Sync — FnMut is not Sync. The &self methods (contains, len, is_empty)
// do not invoke closures, so this is safe in practice, but implementing
// Sync would be unsound according to Rust's type system because &self
// access to the HashMap requires V: Sync.
unsafe
crateimpl_default_via_new!;
/// Formats the table as its size.
///
/// The closures cannot be printed, and a caller that puts a container into a `Debug`
/// summary wants "how many children are forwarded" rather than the boxes. Implemented by
/// hand because a derive would require every closure type to be `Debug`, which no `FnMut`
/// is.