duat_core/context/handles.rs
1//! Widget handles for Duat
2//!
3//! These are used pretty much everywhere, and are essentially just an
4//! [`RwData<W>`] conjoined to an [`Ui::Area`].
5
6use std::{
7 cell::RefCell,
8 sync::{Arc, Mutex},
9};
10
11use lender::Lender;
12
13use crate::{
14 cfg::PrintCfg,
15 data::{Pass, RwData},
16 mode::{Cursor, Cursors, Selection, Selections},
17 text::{Point, Searcher, Text, TwoPoints},
18 ui::{Area, AreaId, GetAreaId, MutArea, SpawnSpecs, Ui, Widget, WidgetCfg},
19};
20
21/// A handle to a [`Widget`] in Duat
22///
23/// The [`Handle`] lets you do all sorts of edits on a [`Widget`]. You
24/// can, for example, make use of the [`Selection`]s in its [`Text`]
25/// in order to edit the [`Text`] in a very declarative way.
26///
27/// One of the places where this is commonly done is within [`Mode`]s,
28/// where you get access to the [`Handle`] of the currently active
29/// [`Widget`]. Below is a very straightforward [`Mode`]:
30///
31/// ```rust
32/// use duat_core::prelude::*;
33/// /// A very basic example Mode.
34/// #[derive(Clone)]
35/// struct PlacesCharactersAndMoves;
36///
37/// impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
38/// type Widget = File<U>;
39///
40/// // ...
41/// fn send_key(&mut self, _: &mut Pass, _: KeyEvent, _: Handle<Self::Widget, U>) {
42/// todo!();
43/// }
44/// }
45/// ```
46///
47/// In order to modify the widget, you must implement the
48/// [`Mode::send_key`] method. In it, you receive the following:
49///
50/// - A [`&mut Pass`], which will give you access to all of duat's
51/// shared state;
52/// - The [key] that was sent, may be a [mapped] key.
53/// - The [`Handle`] for a [`Mode::Widget`].
54///
55/// ```rust
56/// use duat_core::prelude::*;
57/// #[derive(Clone)]
58/// struct PlacesCharactersAndMoves;
59/// impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
60/// type Widget = File<U>;
61///
62/// fn send_key(&mut self, pa: &mut Pass, key: KeyEvent, handle: Handle<File<U>, U>) {
63/// match key {
64/// // actions based on the key pressed
65/// key!(KeyCode::Char('c')) => {
66/// // Do something when the character 'c' is typed.
67/// }
68/// _ => todo!("The remaining keys"),
69/// }
70/// }
71/// }
72/// ```
73///
74/// (You can use the [`key!`] macro in order to match [`KeyEvent`]s).
75///
76/// With the [`Handle`], you can modify [`Text`] in a simplified
77/// way. This is done by two actions, [editing] and [moving]. You
78/// can only do one of these on any number of selections at the same
79/// time.
80///
81/// ```rust
82/// # use duat_core::prelude::*;
83/// # #[derive(Clone)]
84/// # struct PlacesCharactersAndMoves;
85/// impl<U: Ui> Mode<U> for PlacesCharactersAndMoves {
86/// # type Widget = File<U>;
87/// /* ... */
88/// fn send_key(&mut self, pa: &mut Pass, key: KeyEvent, handle: Handle<Self::Widget, U>) {
89/// match key {
90/// key!(KeyCode::Char(c)) => {
91/// handle.edit_all(pa, |mut e| {
92/// e.insert('c');
93/// e.move_hor(1);
94/// });
95/// },
96/// key!(KeyCode::Right, KeyMod::SHIFT) => {
97/// handle.edit_all(pa, |mut e| {
98/// if e.anchor().is_none() {
99/// e.set_anchor();
100/// }
101/// e.move_hor(1);
102/// });
103/// }
104/// key!(KeyCode::Right) => {
105/// handle.edit_all(pa, |mut e| {
106/// e.unset_anchor();
107/// e.move_hor(1);
108/// });
109/// }
110/// _ => todo!("Predictable remaining implementations")
111/// }
112/// }
113/// # }
114/// ```
115///
116/// [`Mode`]: crate::mode::Mode
117/// [`Mode::Widget`]: crate::mode::Mode::Widget
118/// [`&mut Pass`]: Pass
119/// [`PromptLine`]: https://docs.rs/duat-utils/latest/duat_utils/widgets/struct.PromptLine.html
120/// [`Mode::send_key`]: crate::mode::Mode::send_key
121/// [key]: crate::mode::KeyEvent
122/// [mapped]: crate::mode::map
123/// [`read`]: RwData::read
124/// [`write`]: RwData::write
125/// [`U::Area`]: Ui::Area
126/// [`Self::Widget`]: crate::mode::Mode::Widget
127/// [`Some(selections)`]: Some
128/// [`Ui::Area`]: crate::ui::Ui::Area
129/// [commands]: crate::cmd
130/// [`key!`]: crate::mode::key
131/// [`KeyEvent`]: crate::mode::KeyEvent
132/// [editing]: Cursor
133/// [moving]: Cursor
134/// [`Mode`]: crate::mode::Mode
135/// [`U::Area`]: Ui::Area
136pub struct Handle<W: Widget<U> + ?Sized, U: Ui, S = ()> {
137 widget: RwData<W>,
138 area: U::Area,
139 mask: Arc<Mutex<&'static str>>,
140 id: AreaId,
141 related: RelatedWidgets<U>,
142 searcher: RefCell<S>,
143}
144
145impl<W: Widget<U> + ?Sized, U: Ui> Handle<W, U> {
146 /// Returns a new instance of a [`Handle<W, U>`]
147 pub(crate) fn new(
148 widget: RwData<W>,
149 area: U::Area,
150 mask: Arc<Mutex<&'static str>>,
151 id: AreaId,
152 ) -> Self {
153 Self {
154 widget,
155 area,
156 mask,
157 id,
158 related: RelatedWidgets(RwData::default()),
159 searcher: RefCell::new(()),
160 }
161 }
162}
163
164impl<W: Widget<U> + ?Sized, U: Ui, S> Handle<W, U, S> {
165 ////////// Read and write access functions
166
167 /// Reads from the [`Widget`], making use of a [`Pass`]
168 ///
169 /// The consistent use of a [`Pass`] for the purposes of
170 /// reading/writing to the values of [`RwData`]s ensures that no
171 /// panic or invalid borrow happens at runtime, even while working
172 /// with untrusted code. More importantly, Duat uses these
173 /// guarantees in order to give the end user a ridiculous amount
174 /// of freedom in where they can do things, whilst keeping Rust's
175 /// number one rule and ensuring thread safety, even with a
176 /// relatively large amount of shareable state.
177 ///
178 /// [`Area`]: crate::ui::Area
179 pub fn read<'a>(&'a self, pa: &'a Pass) -> &'a W {
180 self.widget.read(pa)
181 }
182
183 /// Tries to read as a concrete [`Widget`] implementor
184 pub fn read_as<'a, W2: Widget<U>>(&'a self, pa: &'a Pass) -> Option<&'a W2> {
185 self.widget.read_as(pa)
186 }
187
188 /// Writes to the [`Widget`], making use of a [`Pass`]
189 ///
190 /// The consistent use of a [`Pass`] for the purposes of
191 /// reading/writing to the values of [`RwData`]s ensures that no
192 /// panic or invalid borrow happens at runtime, even while working
193 /// with untrusted code. More importantly, Duat uses these
194 /// guarantees in order to give the end user a ridiculous amount
195 /// of freedom in where they can do things, whilst keeping Rust's
196 /// number one rule and ensuring thread safety, even with a
197 /// relatively large amount of shareable state.
198 ///
199 /// [`Area`]: crate::ui::Area
200 pub fn write<'a>(&'a self, pa: &'a mut Pass) -> &'a mut W {
201 self.widget.write(pa)
202 }
203
204 /// Writes to the [`Widget`] and [`Area`], making use of a
205 /// [`Pass`]
206 ///
207 /// The consistent use of a [`Pass`] for the purposes of
208 /// reading/writing to the values of [`RwData`]s ensures that no
209 /// panic or invalid borrow happens at runtime, even while working
210 /// with untrusted code. More importantly, Duat uses these
211 /// guarantees in order to give the end user a ridiculous amount
212 /// of freedom in where they can do things, whilst keeping Rust's
213 /// number one rule and ensuring thread safety, even with a
214 /// relatively large amount of shareable state.
215 ///
216 /// [`Area`]: crate::ui::Area
217 pub fn write_with_area<'a>(&'a self, pa: &'a mut Pass) -> (&'a mut W, &'a U::Area) {
218 (self.widget.write(pa), &self.area)
219 }
220
221 /// Tries to downcast from `dyn Widget` to a concrete [`Widget`]
222 pub fn try_downcast<W2: Widget<U>>(&self) -> Option<Handle<W2, U>> {
223 Some(Handle {
224 widget: self.widget.try_downcast()?,
225 area: self.area.clone(),
226 mask: self.mask.clone(),
227 id: self.id,
228 related: self.related.clone(),
229 searcher: RefCell::new(()),
230 })
231 }
232
233 ////////// Refined access functions
234
235 /// A shared reference to the [`Text`] of the [`Widget`]
236 ///
237 /// This is the same as calling `handle.read(pa).text()`.
238 pub fn text<'a>(&'a self, pa: &'a Pass) -> &'a Text {
239 self.read(pa).text()
240 }
241
242 /// A mutable reference to the [`Text`] of the [`Widget`]
243 ///
244 /// This is the same as calling `handle.write(pa).text_mut()`.
245 pub fn text_mut<'a>(&'a self, pa: &'a mut Pass) -> &'a mut Text {
246 self.write(pa).text_mut()
247 }
248
249 /// A shared reference to the [`Selections`] of the [`Widget`]'s
250 /// [`Text`]
251 ///
252 /// This is the same as calling `handle.read(pa).selections()`.
253 pub fn selections<'a>(&'a self, pa: &'a Pass) -> &'a Selections {
254 self.read(pa).text().selections()
255 }
256
257 /// A mutable reference to the [`Selections`] of the [`Widget`]'s
258 /// [`Text`]
259 ///
260 /// This is the same as calling
261 /// `handle.write(pa).selections_mut()`.
262 pub fn selections_mut<'a>(&'a self, pa: &'a mut Pass) -> &'a mut Selections {
263 self.write(pa).text_mut().selections_mut()
264 }
265
266 ////////// Selection Editing functions
267
268 /// Edits the nth [`Selection`] in the [`Text`]
269 ///
270 /// Once dropped, the [`Selection`] in this [`Cursor`] will be
271 /// added back to the list of [`Selection`]s, unless it is
272 /// [destroyed]
273 ///
274 /// If you want to edit on the main selection, see [`edit_main`],
275 /// if you want to edit on many [`Selection`]s, see
276 /// [`edit_iter`].
277 ///
278 /// Just like all other `edit` methods, this one will populate the
279 /// [`Selections`], so if there are no [`Selection`]s, it will
280 /// create one at [`Point::default`].
281 ///
282 /// [destroyed]: Cursor::destroy
283 /// [`edit_main`]: Self::edit_main
284 /// [`edit_iter`]: Self::edit_iter
285 /// [`Point::default`]: crate::text::Point::default
286 pub fn edit_nth<Ret>(
287 &self,
288 pa: &mut Pass,
289 n: usize,
290 edit: impl FnOnce(Cursor<W, U::Area, S>) -> Ret,
291 ) -> Ret {
292 fn get_parts<'a, W: Widget<U> + ?Sized, U: Ui>(
293 pa: &'a mut Pass,
294 widget: &'a RwData<W>,
295 n: usize,
296 ) -> (Selection, bool, &'a mut W) {
297 let widget = widget.write(pa);
298 let selections = widget.text_mut().selections_mut();
299 selections.populate();
300 let Some((selection, was_main)) = selections.remove(n) else {
301 panic!("Selection index {n} out of bounds");
302 };
303
304 (selection, was_main, widget)
305 }
306
307 let (selection, was_main, widget) = get_parts(pa, &self.widget, n);
308
309 // This is safe because of the &mut Pass argument
310 let mut searcher = self.searcher.borrow_mut();
311
312 edit(Cursor::new(
313 selection,
314 n,
315 was_main,
316 &mut *widget,
317 &self.area,
318 None,
319 &mut searcher,
320 ))
321 }
322
323 /// Edits the main [`Selection`] in the [`Text`]
324 ///
325 /// Once dropped, the [`Selection`] in this [`Cursor`] will be
326 /// added back to the list of [`Selection`]s, unless it is
327 /// [destroyed]
328 ///
329 /// If you want to edit on the `nth` selection, see [`edit_nth`],
330 /// same for [`edit_last`], if you want to edit on many
331 /// [`Selection`]s, see [`edit_iter`].
332 ///
333 /// Just like all other `edit` methods, this one will populate the
334 /// [`Selections`], so if there are no [`Selection`]s, it will
335 /// create one at [`Point::default`].
336 ///
337 /// [destroyed]: Cursor::destroy
338 /// [`edit_nth`]: Self::edit_nth
339 /// [`edit_last`]: Self::edit_last
340 /// [`edit_iter`]: Self::edit_iter
341 /// [`Point::default`]: crate::text::Point::default
342 pub fn edit_main<Ret>(
343 &self,
344 pa: &mut Pass,
345 edit: impl FnOnce(Cursor<W, U::Area, S>) -> Ret,
346 ) -> Ret {
347 self.edit_nth(
348 pa,
349 self.widget.read(pa).text().selections().main_index(),
350 edit,
351 )
352 }
353
354 /// Edits the last [`Selection`] in the [`Text`]
355 ///
356 /// Once dropped, the [`Selection`] in this [`Cursor`] will be
357 /// added back to the list of [`Selection`]s, unless it is
358 /// [destroyed]
359 ///
360 /// If you want to edit on the `nth` selection, see [`edit_nth`],
361 /// same for [`edit_main`], if you want to edit on many
362 /// [`Selection`]s, see [`edit_iter`].
363 ///
364 /// Just like all other `edit` methods, this one will populate the
365 /// [`Selections`], so if there are no [`Selection`]s, it will
366 /// create one at [`Point::default`].
367 ///
368 /// [destroyed]: Cursor::destroy
369 /// [`edit_nth`]: Self::edit_nth
370 /// [`edit_main`]: Self::edit_main
371 /// [`edit_iter`]: Self::edit_iter
372 /// [`Point::default`]: crate::text::Point::default
373 pub fn edit_last<Ret>(
374 &self,
375 pa: &mut Pass,
376 edit: impl FnOnce(Cursor<W, U::Area, S>) -> Ret,
377 ) -> Ret {
378 let len = self.widget.read(pa).text().selections().len();
379 self.edit_nth(pa, len.saturating_sub(1), edit)
380 }
381
382 /// A [`Lender`] over all [`Cursor`]s of the [`Text`]
383 ///
384 /// This lets you easily iterate over all [`Selection`]s, without
385 /// having to worry about insertion affecting the order at which
386 /// they are edited (like what repeated calls to [`edit_nth`]
387 /// would do)
388 ///
389 /// Note however that you can't use a [`Lender`] (also known as a
390 /// lending iterator) in a `for` loop, but you should be able
391 /// to just `while let Some(e) = editors.next() {}` or
392 /// `handle.edit_iter().for_each(|_| {})` instead.
393 ///
394 /// Just like all other `edit` methods, this one will populate the
395 /// [`Selections`], so if there are no [`Selection`]s, it will
396 /// create one at [`Point::default`].
397 ///
398 /// [`edit_nth`]: Self::edit_nth
399 /// [`Point::default`]: crate::text::Point::default
400 pub fn edit_iter<Ret>(
401 &self,
402 pa: &mut Pass,
403 edit: impl FnOnce(Cursors<'_, W, U::Area, S>) -> Ret,
404 ) -> Ret {
405 edit(self.get_iter(pa))
406 }
407
408 /// A shortcut for iterating over all selections
409 ///
410 /// This is the equivalent of calling:
411 ///
412 /// ```rust
413 /// # use duat_core::prelude::*;
414 /// # fn test<U: Ui>(pa: &mut Pass, handle: Handle<File<U>, U, ()>) {
415 /// handle.edit_iter(pa, |iter| iter.for_each(|e| { /* .. */ }));
416 /// # }
417 /// ```
418 ///
419 /// But it can't return a value, and is meant to reduce the
420 /// indentation that will inevitably come from using the
421 /// equivalent long form call.
422 pub fn edit_all(&self, pa: &mut Pass, edit: impl FnMut(Cursor<W, U::Area, S>)) {
423 self.get_iter(pa).for_each(edit);
424 }
425
426 fn get_iter<'a>(&'a self, pa: &'a mut Pass) -> Cursors<'a, W, U::Area, S> {
427 let widget = self.widget.write(pa);
428 widget.text_mut().selections_mut().populate();
429
430 let searcher = self.searcher.borrow_mut();
431
432 Cursors::new(0, widget, &self.area, searcher)
433 }
434
435 ////////// Area functions
436
437 /// Scrolls the [`Text`] veritcally by an amount
438 ///
439 /// If [`PrintCfg.allow_overscroll`] is set, then the [`Text`]
440 /// will be allowed to scroll beyond the last line, up until
441 /// reaching the `scrolloff.y` value.
442 ///
443 /// [`PrintCfg.allow_overscroll`]: crate::cfg::PrintCfg::allow_overscroll
444 pub fn scroll_ver(&self, pa: &Pass, dist: i32) {
445 let widget = self.widget.read(pa);
446 self.area(pa)
447 .scroll_ver(widget.text(), dist, widget.print_cfg());
448 self.widget.declare_written();
449 }
450
451 /// Scrolls the [`Text`] to the visual line of a [`TwoPoints`]
452 ///
453 /// If `scroll_beyond` is set, then the [`Text`] will be allowed
454 /// to scroll beyond the last line, up until reaching the
455 /// `scrolloff.y` value.
456 pub fn scroll_to_points(&self, pa: &Pass, points: impl TwoPoints) {
457 let widget = self.widget.read(pa);
458 self.area
459 .scroll_to_points(widget.text(), points, widget.print_cfg());
460 self.widget.declare_written();
461 }
462
463 /// The start points that should be printed
464 pub fn start_points(&self, pa: &Pass) -> (Point, Option<Point>) {
465 let widget = self.widget.read(pa);
466 self.area.start_points(widget.text(), widget.print_cfg())
467 }
468
469 /// The end points that should be printed
470 pub fn end_points(&self, pa: &Pass) -> (Point, Option<Point>) {
471 let widget = self.widget.read(pa);
472 self.area.end_points(widget.text(), widget.print_cfg())
473 }
474
475 ////////// Querying functions
476
477 /// This [`Handle`]'s [`Widget`]
478 pub fn widget(&self) -> &RwData<W> {
479 &self.widget
480 }
481
482 /// This [`Handle`]'s [`U::Area`]
483 ///
484 /// [`U::Area`]: crate::ui::Ui::Area
485 pub fn area(&self, _: &Pass) -> &U::Area {
486 &self.area
487 }
488
489 /// Gets this [`Handle`]'s mask
490 ///
491 /// This mask is going to be used to map [`Form`]s to other
492 /// [`Form`]s when printing via [`Widget::print`]. To see more
493 /// about how masks work, see [`form::enable_mask`].
494 ///
495 /// [`Form`]: crate::form::Form
496 /// [`form::enable_mask`]: crate::form::enable_mask
497 pub fn mask(&self) -> &Arc<Mutex<&'static str>> {
498 &self.mask
499 }
500
501 /// Sets this [`Handle`]'s mask, returning the previous one
502 ///
503 /// This mask is going to be used to map [`Form`]s to other
504 /// [`Form`]s when printing via [`Widget::print`]. To see more
505 /// about how masks work, see [`form::enable_mask`].
506 ///
507 /// [`Form`]: crate::form::Form
508 /// [`form::enable_mask`]: crate::form::enable_mask
509 pub fn set_mask(&self, mask: &'static str) -> &'static str {
510 self.widget.declare_written();
511 std::mem::replace(&mut self.mask.lock().unwrap(), mask)
512 }
513
514 /// Wether someone else called [`write`] or [`write_as`] since the
515 /// last [`read`] or [`write`]
516 ///
517 /// Do note that this *DOES NOT* mean that the value inside has
518 /// actually been changed, it just means a mutable reference was
519 /// acquired after the last call to [`has_changed`].
520 ///
521 /// Some types like [`Text`], and traits like [`Widget`] offer
522 /// [`needs_update`] methods, you should try to determine what
523 /// parts to look for changes.
524 ///
525 /// Generally though, you can use this method to gauge that.
526 ///
527 /// [`write`]: RwData::write
528 /// [`write_as`]: RwData::write_as
529 /// [`read`]: RwData::read
530 /// [`has_changed`]: RwData::has_changed
531 /// [`Text`]: crate::text::Text
532 /// [`Widget`]: crate::ui::Widget
533 /// [`needs_update`]: crate::ui::Widget::needs_update
534 pub fn has_changed(&self) -> bool {
535 self.widget.has_changed() || self.area.has_changed()
536 }
537
538 /// Wether the [`RwData`] within and another point to the same
539 /// value
540 pub fn ptr_eq<T: ?Sized>(&self, other: &RwData<T>) -> bool {
541 self.widget.ptr_eq(other)
542 }
543
544 /// The [`Widget`]'s [`PrintCfg`]
545 pub fn cfg(&self, pa: &Pass) -> PrintCfg {
546 self.widget.read(pa).print_cfg()
547 }
548
549 /// Reads a related [`Widget`] of type `W2`, as well as it s
550 /// [`Ui::Area`]
551 ///
552 /// This can also be done by calling [`Handle::get_related`], and
553 /// [`Handle::read`], but this function should generally be
554 /// faster, since there is no cloning of [`Arc`]s going on.
555 pub fn read_related<'a, W2: Widget<U>>(
556 &'a self,
557 pa: &'a Pass,
558 ) -> Option<(&'a W2, &'a U::Area)> {
559 self.read_as(pa).map(|w| (w, self.area(pa))).or_else(|| {
560 self.related
561 .0
562 .read(pa)
563 .iter()
564 .find_map(|handle| handle.read_as(pa).map(|w| (w, handle.area(pa))))
565 })
566 }
567
568 /// Gets the [`Handle`] of a related [`Widget`]
569 ///
570 /// If you are doing this just to read the [`Widget`] and
571 /// [`Ui::Area`], consider using [`Handle::read_related`], since
572 /// that function is generally faster.
573 pub fn get_related<W2: Widget<U>>(&self, pa: &Pass) -> Option<Handle<W2, U>> {
574 self.try_downcast().or_else(|| {
575 self.related
576 .0
577 .read(pa)
578 .iter()
579 .find_map(|handle| handle.try_downcast())
580 })
581 }
582
583 /// Raw access to the related widgets
584 pub(crate) fn related(&self) -> &RwData<Vec<Handle<dyn Widget<U>, U>>> {
585 &self.related.0
586 }
587
588 ////////// Other methods
589
590 /// Attaches a [`Searcher`] to this [`Handle`], so you can do
591 /// incremental search
592 ///
593 /// An [`Handle`] with a [`Searcher`] not only has its usual
594 /// editing capabilities, but is also able to act on requested
595 /// regex searches, like those from [`IncSearch`], in
596 /// [`duat-utils`]. This means that a user can type up a
597 /// [prompt] to search for something, and the [`Handle`]
598 /// can use the [`Searcher`] to interpret how that search will
599 /// be utilized. Examples of this can be found in the
600 /// [`duat-utils`] crate, as well as the [`duat-kak`] crate,
601 /// which has some more advanced usage.
602 ///
603 /// [`Searcher`]: crate::text::Searcher
604 /// [`Selection`]: crate::mode::Selection
605 /// [`Cursor`]: crate::mode::Cursor
606 /// [`IncSearch`]: https://docs.rs/duat-utils/latest/duat_utils/modes/struct.IncSearch.html
607 /// [`duat-utils`]: https://docs.rs/duat-utils/lastest/
608 /// [prompt]: https://docs.rs/duat-utils/latest/duat_utils/modes/trait.PromptMode.html
609 /// [`duat-kak`]: https://docs.rs/duat-kak/lastest/
610 pub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, U, Searcher> {
611 Handle {
612 widget: self.widget.clone(),
613 area: self.area.clone(),
614 mask: self.mask.clone(),
615 id: self.id,
616 related: self.related.clone(),
617 searcher: RefCell::new(searcher),
618 }
619 }
620
621 /// Spawns a floating [`Widget`]
622 pub fn spawn_widget<Cfg: WidgetCfg<U>>(
623 &self,
624 _pa: &mut Pass,
625 _cfg: Cfg,
626 _specs: SpawnSpecs,
627 ) -> Result<AreaId, Text> {
628 let _area = MutArea(&self.area);
629 // let _spawned = area.spawn_floating(pa, cfg, specs)?;
630 todo!();
631 }
632}
633
634impl<W: Widget<U>, U: Ui> Handle<W, U> {
635 /// Transforms this [`Handle`] into a [`Handle<dyn Widget>`]
636 pub fn to_dyn(&self) -> Handle<dyn Widget<U>, U> {
637 Handle {
638 widget: self.widget.to_dyn_widget(),
639 // TODO: Arc wrapper, and Area: !Clone
640 area: self.area.clone(),
641 mask: self.mask.clone(),
642 id: self.id,
643 related: self.related.clone(),
644 searcher: RefCell::new(()),
645 }
646 }
647}
648
649// SAFETY: The only parts that are accessible from other threads are
650// the atomic counters from the Arcs. Everything else can only be
651// acquired when there is a Pass, i.e., on the main thread.
652unsafe impl<W: Widget<U>, U: Ui, S> Send for Handle<W, U, S> {}
653unsafe impl<W: Widget<U>, U: Ui, S> Sync for Handle<W, U, S> {}
654
655impl<W: Widget<U> + ?Sized, U: Ui, S> GetAreaId for Handle<W, U, S> {
656 fn area_id(&self) -> AreaId {
657 self.id
658 }
659}
660
661impl<T: GetAreaId, W: Widget<U> + ?Sized, U: Ui, S> PartialEq<T> for Handle<W, U, S> {
662 fn eq(&self, other: &T) -> bool {
663 self.area_id() == other.area_id()
664 }
665}
666
667impl<W: Widget<U> + ?Sized, U: Ui> Clone for Handle<W, U> {
668 fn clone(&self) -> Self {
669 Self {
670 widget: self.widget.clone(),
671 area: self.area.clone(),
672 mask: self.mask.clone(),
673 id: self.id,
674 related: self.related.clone(),
675 searcher: self.searcher.clone(),
676 }
677 }
678}
679
680#[derive(Clone)]
681struct RelatedWidgets<U: Ui>(RwData<Vec<Handle<dyn Widget<U>, U>>>);