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>>>);