1use super::Id;
9use crate::geom::Rect;
10use crate::layout::AxisInfo;
11#[allow(unused)] use crate::{Events, Layout, Widget};
12use std::ops::{Range, RangeInclusive};
13
14#[derive(Clone, Debug)]
21pub struct ChildIndices(usize, usize);
22
23impl ChildIndices {
24 #[inline]
26 pub fn none() -> Self {
27 ChildIndices(0, 0)
28 }
29
30 #[inline]
32 pub fn one(index: usize) -> Self {
33 ChildIndices(index, index + 1)
34 }
35
36 #[inline]
38 pub fn range(range: impl Into<Self>) -> Self {
39 range.into()
40 }
41
42 #[inline]
46 pub(crate) fn as_range(&self) -> Range<usize> {
47 self.0..self.1
48 }
49}
50
51impl IntoIterator for ChildIndices {
52 type Item = usize;
53 type IntoIter = ChildIndicesIter;
54
55 #[inline]
56 fn into_iter(self) -> ChildIndicesIter {
57 ChildIndicesIter(self.0..self.1)
58 }
59}
60
61impl From<Range<usize>> for ChildIndices {
62 #[inline]
63 fn from(range: Range<usize>) -> Self {
64 ChildIndices(range.start, range.end)
65 }
66}
67
68impl From<RangeInclusive<usize>> for ChildIndices {
69 #[inline]
70 fn from(range: RangeInclusive<usize>) -> Self {
71 ChildIndices(*range.start(), *range.end() + 1)
72 }
73}
74
75#[derive(Clone, Debug)]
77pub struct ChildIndicesIter(Range<usize>);
78
79impl Iterator for ChildIndicesIter {
80 type Item = usize;
81
82 #[inline]
83 fn next(&mut self) -> Option<usize> {
84 self.0.next()
85 }
86
87 #[inline]
88 fn size_hint(&self) -> (usize, Option<usize>) {
89 self.0.size_hint()
90 }
91}
92impl ExactSizeIterator for ChildIndicesIter {}
93impl DoubleEndedIterator for ChildIndicesIter {
94 #[inline]
95 fn next_back(&mut self) -> Option<usize> {
96 self.0.next_back()
97 }
98}
99
100#[macro_export]
128macro_rules! widget_core {
129 () => {
130 compile_error!(
131 "This macro may only be used in a struct affected by the `#[widget]` attribute"
132 );
133 };
134}
135
136pub trait WidgetCore: Default {
138 fn id_ref(&self) -> &Id;
146
147 #[inline]
158 fn id(&self) -> Id {
159 self.id_ref().clone()
160 }
161
162 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
164 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
165 fn status(&self) -> WidgetStatus;
166
167 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
169 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
170 #[inline]
171 fn require_status(&self, status: WidgetStatus) {
172 self.status().require(self.id_ref(), status);
173 }
174
175 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
177 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
178 #[inline]
179 fn require_status_size_rules(&self) {
180 self.require_status(WidgetStatus::SizeRulesY);
181 }
182
183 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
185 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
186 #[inline]
187 fn require_status_set_rect(&self) {
188 self.require_status(WidgetStatus::SetRect);
189 }
190
191 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
193 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
194 fn set_status(&mut self, status: WidgetStatus);
195
196 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
200 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
201 fn update_status_configured(&mut self) {
202 let status = self.status().max(WidgetStatus::Configured);
204 self.set_status(status);
205 }
206
207 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
214 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
215 fn update_status_size_rules(&mut self, axis: AxisInfo) {
216 let id = self.id_ref();
217 let mut status = self.status();
218 if axis.is_horizontal() {
219 status.require(id, WidgetStatus::Configured);
220 status = status.max(WidgetStatus::SizeRulesX);
221 } else {
222 status.require(id, WidgetStatus::SizeRulesX);
223 status = status.max(WidgetStatus::SizeRulesY);
224 }
225 self.set_status(status);
226 }
227
228 #[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
233 #[cfg_attr(docsrs, doc(cfg(internal_doc)))]
234 #[inline]
235 fn set_status_set_rect(&mut self) {
236 self.set_status(WidgetStatus::SetRect);
237 }
238}
239
240pub trait WidgetCoreRect: WidgetCore {
245 fn rect(&self) -> Rect;
249
250 fn set_rect(&mut self, rect: Rect);
252}
253
254#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
258#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
259#[derive(Default, Debug)]
260pub struct DefaultCoreType {
261 pub _id: Id,
262 pub status: WidgetStatus,
263}
264
265impl WidgetCore for DefaultCoreType {
266 #[inline]
267 fn id_ref(&self) -> &Id {
268 &self._id
269 }
270
271 #[inline]
272 fn status(&self) -> WidgetStatus {
273 self.status
274 }
275
276 #[inline]
277 fn set_status(&mut self, status: WidgetStatus) {
278 self.status = status;
279 }
280}
281
282#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
286#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
287#[derive(Default, Debug)]
288pub struct DefaultCoreRectType {
289 pub _rect: Rect,
290 pub _id: Id,
291 pub status: WidgetStatus,
292}
293
294impl WidgetCore for DefaultCoreRectType {
295 #[inline]
296 fn id_ref(&self) -> &Id {
297 &self._id
298 }
299
300 #[inline]
301 fn status(&self) -> WidgetStatus {
302 self.status
303 }
304
305 #[inline]
306 fn set_status(&mut self, status: WidgetStatus) {
307 self.status = status;
308 }
309}
310
311impl WidgetCoreRect for DefaultCoreRectType {
312 #[inline]
313 fn rect(&self) -> Rect {
314 self._rect
315 }
316
317 #[inline]
318 fn set_rect(&mut self, rect: Rect) {
319 self._rect = rect;
320 }
321}
322
323#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
331#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
332#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
333pub enum WidgetStatus {
334 #[default]
335 New,
336 Configured,
337 SizeRulesX,
338 SizeRulesY,
339 SetRect,
340}
341
342impl WidgetStatus {
343 fn require(self, id: &Id, expected: Self) {
344 if self < expected {
345 panic!("WidgetStatus of {id}: require {expected:?}, found {self:?}");
346 }
347 }
348
349 #[inline]
351 pub fn is_configured(self) -> bool {
352 self >= WidgetStatus::Configured
353 }
354
355 #[inline]
357 pub fn is_sized(self) -> bool {
358 self >= WidgetStatus::SetRect
359 }
360}