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 with an [`Area`].
5use std::{
6    cell::RefCell,
7    sync::{Arc, Mutex},
8};
9
10use lender::Lender;
11
12use crate::{
13    context,
14    data::{Pass, RwData},
15    mode::{Cursor, Cursors, Selection, Selections},
16    opts::PrintOpts,
17    text::{Searcher, Text, TextParts, TwoPoints, txt},
18    ui::{Area, DynSpawnSpecs, PushSpecs, RwArea, Widget},
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/// # duat_core::doc_duat!(duat);
33/// use duat::prelude::*;
34///
35/// /// A very basic example Mode.
36/// #[derive(Clone)]
37/// struct PlacesCharactersAndMoves;
38///
39/// impl Mode for PlacesCharactersAndMoves {
40///     type Widget = Buffer;
41///
42///     // ..
43///     fn send_key(&mut self, _: &mut Pass, _: KeyEvent, _: Handle) {
44///         todo!();
45///     }
46/// }
47/// ```
48///
49/// In order to modify the widget, you must implement the
50/// [`Mode::send_key`] method. In it, you receive the following:
51///
52/// - A [`&mut Pass`], which will give you access to all of duat's
53///   shared state;
54/// - The [key] that was sent, may be a [mapped] key.
55/// - The [`Handle`] for a [`Mode::Widget`].
56///
57/// ```rust
58/// # duat_core::doc_duat!(duat);
59/// use duat::prelude::*;
60///
61/// #[derive(Clone)]
62/// struct PlacesCharactersAndMoves;
63/// impl Mode for PlacesCharactersAndMoves {
64///     type Widget = Buffer;
65///
66///     fn send_key(&mut self, pa: &mut Pass, key_event: KeyEvent, handle: Handle) {
67///         match key_event {
68///             // actions based on the key pressed
69///             event!(KeyCode::Char(char)) => {
70///                 // Do something when the character 'c' is typed.
71///             }
72///             _ => todo!("The remaining keys"),
73///         }
74///     }
75/// }
76/// ```
77///
78/// Note the [`event!`] macro. It (alongside [`alt!`], [`ctrl!`] and
79/// [`shift!`]) can be used to easily create [`KeyEvent`]s for
80/// matching purposes. They are very useful for succinctly describing
81/// an exact match in just a short pattern:
82///
83/// ```rust
84/// # duat_core::doc_duat!(duat);
85/// use KeyCode::*;
86/// use duat::prelude::*;
87///
88/// let key_event = KeyEvent::from(Char('a'));
89/// match key_event {
90///     event!('a' | 'b') => { /* .. */ }
91///     shift!(Right | Left) => { /* .. */ }
92///     ctrl!(alt!('d')) => { /* .. */ }
93///     _ => { /* .. */ }
94/// }
95/// ```
96///
97/// With the [`Handle`], you can modify [`Text`] in a simplified
98/// way. This is done by two actions, [editing] and [moving]. You
99/// can only do one of these on any number of selections at the same
100/// time.
101///
102/// ```rust
103/// # duat_core::doc_duat!(duat);
104/// # use duat::prelude::*;
105/// # #[derive(Clone)]
106/// # struct PlacesCharactersAndMoves;
107/// impl Mode for PlacesCharactersAndMoves {
108///     type Widget = Buffer;
109///
110///     // ..
111///     fn send_key(&mut self, pa: &mut Pass, key_event: KeyEvent, handle: Handle) {
112///         use KeyCode::*;
113///         match key_event {
114///             event!(Char(char)) => handle.edit_all(pa, |mut c| {
115///                 c.insert('c');
116///                 c.move_hor(1);
117///             }),
118///             shift!(Right) => handle.edit_all(pa, |mut c| {
119///                 if c.anchor().is_none() {
120///                     c.set_anchor();
121///                 }
122///                 c.move_hor(1);
123///             }),
124///             event!(KeyCode::Right) => handle.edit_all(pa, |mut c| {
125///                 c.unset_anchor();
126///                 c.move_hor(1);
127///             }),
128///             _ => todo!("Predictable remaining implementations"),
129///         }
130///     }
131/// # }
132/// ```
133///
134/// [`Mode`]: crate::mode::Mode
135/// [`Mode::Widget`]: crate::mode::Mode::Widget
136/// [`&mut Pass`]: Pass
137/// [`PromptLine`]: https://docs.rs/duat/latest/duat/widgets/struct.PromptLine.html
138/// [`Mode::send_key`]: crate::mode::Mode::send_key
139/// [key]: crate::mode::KeyEvent
140/// [mapped]: crate::mode::map
141/// [`read`]: RwData::read
142/// [`write`]: RwData::write
143/// [`Self::Widget`]: crate::mode::Mode::Widget
144/// [`Some(selections)`]: Some
145/// [`Area`]: crate::ui::Area
146/// [commands]: crate::cmd
147/// [`KeyEvent`]: crate::mode::KeyEvent
148/// [editing]: Cursor
149/// [moving]: Cursor
150/// [`Mode`]: crate::mode::Mode
151/// [`event!`]: crate::mode::event
152/// [`alt!`]: crate::mode::alt
153/// [`ctrl!`]: crate::mode::ctrl
154/// [`shift!`]: crate::mode::shift
155pub struct Handle<W: Widget + ?Sized = crate::buffer::Buffer, S = ()> {
156    widget: RwData<W>,
157    pub(crate) area: RwArea,
158    mask: Arc<Mutex<&'static str>>,
159    related: RelatedWidgets,
160    searcher: RefCell<S>,
161    is_closed: RwData<bool>,
162    master: Option<Box<Handle<dyn Widget>>>,
163}
164
165impl<W: Widget + ?Sized> Handle<W> {
166    /// Returns a new instance of a [`Handle<W, U>`]
167    pub(crate) fn new(
168        widget: RwData<W>,
169        area: RwArea,
170        mask: Arc<Mutex<&'static str>>,
171        master: Option<Handle<dyn Widget>>,
172    ) -> Self {
173        Self {
174            widget,
175            area,
176            mask,
177            related: RelatedWidgets(RwData::default()),
178            searcher: RefCell::new(()),
179            is_closed: RwData::new(false),
180            master: master.map(Box::new),
181        }
182    }
183}
184
185impl<W: Widget + ?Sized, S> Handle<W, S> {
186    ////////// Read and write access functions
187
188    /// Reads from 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 read<'a>(&'a self, pa: &'a Pass) -> &'a W {
201        self.widget.read(pa)
202    }
203
204    /// Tries to read as a concrete [`Widget`] implementor
205    pub fn read_as<'a, W2: Widget>(&'a self, pa: &'a Pass) -> Option<&'a W2> {
206        self.widget.read_as(pa)
207    }
208
209    /// Declares the [`Widget`] within as read
210    ///
211    /// Same as calling `handle.widget().declare_as_read()`. You
212    /// should use this function if you want to signal to others that
213    /// the widget was read, even if you don't have access to a
214    /// [`Pass`].
215    pub fn declare_as_read(&self) {
216        self.widget.declare_as_read();
217    }
218
219    /// Writes to the [`Widget`], making use of a [`Pass`]
220    ///
221    /// The consistent use of a [`Pass`] for the purposes of
222    /// reading/writing to the values of [`RwData`]s ensures that no
223    /// panic or invalid borrow happens at runtime, even while working
224    /// with untrusted code. More importantly, Duat uses these
225    /// guarantees in order to give the end user a ridiculous amount
226    /// of freedom in where they can do things, whilst keeping Rust's
227    /// number one rule and ensuring thread safety, even with a
228    /// relatively large amount of shareable state.
229    ///
230    /// [`Area`]: crate::ui::Area
231    pub fn write<'a>(&'a self, pa: &'a mut Pass) -> &'a mut W {
232        self.widget.write(pa)
233    }
234
235    /// Writes to the [`Widget`] and [`Area`], making use of a
236    /// [`Pass`]
237    ///
238    /// The consistent use of a [`Pass`] for the purposes of
239    /// reading/writing to the values of [`RwData`]s ensures that no
240    /// panic or invalid borrow happens at runtime, even while working
241    /// with untrusted code. More importantly, Duat uses these
242    /// guarantees in order to give the end user a ridiculous amount
243    /// of freedom in where they can do things, whilst keeping Rust's
244    /// number one rule and ensuring thread safety, even with a
245    /// relatively large amount of shareable state.
246    ///
247    /// [`Area`]: crate::ui::Area
248    pub fn write_with_area<'a>(&'a self, pa: &'a mut Pass) -> (&'a mut W, &'a mut Area) {
249        pa.try_write_two(&self.widget, &self.area.0).unwrap()
250    }
251
252    /// Declares the [`Widget`] within as written
253    ///
254    /// Same as calling `handle.widget().declare_written()`. You
255    /// should use this function if you want to signal to others that
256    /// the widget was written to, even if you don't have access to a
257    /// [`Pass`].
258    pub fn declare_written(&self) {
259        self.widget.declare_written();
260    }
261
262    /// Tries to downcast from `dyn Widget` to a concrete [`Widget`]
263    pub fn try_downcast<W2: Widget>(&self) -> Option<Handle<W2>> {
264        Some(Handle {
265            widget: self.widget.try_downcast()?,
266            area: self.area.clone(),
267            mask: self.mask.clone(),
268            related: self.related.clone(),
269            searcher: RefCell::new(()),
270            is_closed: self.is_closed.clone(),
271            master: self.master.clone(),
272        })
273    }
274
275    ////////// Refined access functions
276
277    /// A shared reference to the [`Text`] of the [`Widget`]
278    ///
279    /// This is the same as calling `handle.read(pa).text()`.
280    pub fn text<'a>(&'a self, pa: &'a Pass) -> &'a Text {
281        self.read(pa).text()
282    }
283
284    /// A mutable reference to the [`Text`] of the [`Widget`]
285    ///
286    /// This is the same as calling `handle.write(pa).text_mut()`.
287    pub fn text_mut<'a>(&'a self, pa: &'a mut Pass) -> &'a mut Text {
288        self.write(pa).text_mut()
289    }
290
291    /// The [`TextParts`] of the [`Widget`]
292    ///
293    /// You can use this in order to get a shared reference to the
294    /// [`Bytes`] and [`Selections`], while maintaining a mutable
295    /// reference to the [`Tags`] of the [`Text`], letting you place
296    /// [`Tag`]s while still reading other information from the
297    /// [`Widget`]
298    ///
299    /// This is the same as calling `handle.text_mut().parts()`.
300    ///
301    /// [`Bytes`]: crate::text::Bytes
302    /// [`Tags`]: crate::text::Tags
303    /// [`Tag`]: crate::text::Tag
304    pub fn text_parts<'a>(&'a self, pa: &'a mut Pass) -> TextParts<'a> {
305        self.write(pa).text_mut().parts()
306    }
307
308    /// A shared reference to the [`Selections`] of the [`Widget`]'s
309    /// [`Text`]
310    ///
311    /// This is the same as calling `handle.read(pa).selections()`.
312    pub fn selections<'a>(&'a self, pa: &'a Pass) -> &'a Selections {
313        self.read(pa).text().selections()
314    }
315
316    /// A mutable reference to the [`Selections`] of the [`Widget`]'s
317    /// [`Text`]
318    ///
319    /// This is the same as calling
320    /// `handle.write(pa).selections_mut()`.
321    pub fn selections_mut<'a>(&'a self, pa: &'a mut Pass) -> &'a mut Selections {
322        self.write(pa).text_mut().selections_mut()
323    }
324
325    ////////// Selection Editing functions
326
327    /// Edits the nth [`Selection`] in the [`Text`]
328    ///
329    /// Once dropped, the [`Selection`] in this [`Cursor`] will be
330    /// added back to the list of [`Selection`]s, unless it is
331    /// [destroyed]
332    ///
333    /// If you want to edit on the main selection, see [`edit_main`],
334    /// if you want to edit on many [`Selection`]s, see
335    /// [`edit_iter`].
336    ///
337    /// Just like all other `edit` methods, this one will populate the
338    /// [`Selections`], so if there are no [`Selection`]s, it will
339    /// create one at [`Point::default`].
340    ///
341    /// [destroyed]: Cursor::destroy
342    /// [`edit_main`]: Self::edit_main
343    /// [`edit_iter`]: Self::edit_iter
344    /// [`Point::default`]: crate::text::Point::default
345    pub fn edit_nth<Ret>(
346        &self,
347        pa: &mut Pass,
348        n: usize,
349        edit: impl FnOnce(Cursor<W, S>) -> Ret,
350    ) -> Ret {
351        fn get_parts<'a, W: Widget + ?Sized, S>(
352            pa: &'a mut Pass,
353            handle: &'a Handle<W, S>,
354            n: usize,
355        ) -> (Selection, bool, &'a mut W, &'a Area) {
356            let (widget, area) = handle.write_with_area(pa);
357            let selections = widget.text_mut().selections_mut();
358            selections.populate();
359            let Some((selection, was_main)) = selections.remove(n) else {
360                panic!("Selection index {n} out of bounds");
361            };
362
363            (selection, was_main, widget, area)
364        }
365
366        let (selection, was_main, widget, area) = get_parts(pa, self, n);
367
368        // This is safe because of the &mut Pass argument
369        let mut searcher = self.searcher.borrow_mut();
370
371        let mut selections = vec![Some((selection, n, was_main))];
372
373        let ret = edit(Cursor::new(
374            &mut selections,
375            n,
376            (widget, area),
377            None,
378            &mut searcher,
379        ));
380
381        crate::mode::reinsert_selections(selections.into_iter().flatten(), widget, None);
382
383        ret
384    }
385
386    /// Edits the main [`Selection`] in the [`Text`]
387    ///
388    /// Once dropped, the [`Selection`] in this [`Cursor`] will be
389    /// added back to the list of [`Selection`]s, unless it is
390    /// [destroyed]
391    ///
392    /// If you want to edit on the `nth` selection, see [`edit_nth`],
393    /// same for [`edit_last`], if you want to edit on many
394    /// [`Selection`]s, see [`edit_iter`].
395    ///
396    /// Just like all other `edit` methods, this one will populate the
397    /// [`Selections`], so if there are no [`Selection`]s, it will
398    /// create one at [`Point::default`].
399    ///
400    /// [destroyed]: Cursor::destroy
401    /// [`edit_nth`]: Self::edit_nth
402    /// [`edit_last`]: Self::edit_last
403    /// [`edit_iter`]: Self::edit_iter
404    /// [`Point::default`]: crate::text::Point::default
405    pub fn edit_main<Ret>(&self, pa: &mut Pass, edit: impl FnOnce(Cursor<W, S>) -> Ret) -> Ret {
406        self.edit_nth(
407            pa,
408            self.widget.read(pa).text().selections().main_index(),
409            edit,
410        )
411    }
412
413    /// Edits the last [`Selection`] in the [`Text`]
414    ///
415    /// Once dropped, the [`Selection`] in this [`Cursor`] will be
416    /// added back to the list of [`Selection`]s, unless it is
417    /// [destroyed]
418    ///
419    /// If you want to edit on the `nth` selection, see [`edit_nth`],
420    /// same for [`edit_main`], if you want to edit on many
421    /// [`Selection`]s, see [`edit_iter`].
422    ///
423    /// Just like all other `edit` methods, this one will populate the
424    /// [`Selections`], so if there are no [`Selection`]s, it will
425    /// create one at [`Point::default`].
426    ///
427    /// [destroyed]: Cursor::destroy
428    /// [`edit_nth`]: Self::edit_nth
429    /// [`edit_main`]: Self::edit_main
430    /// [`edit_iter`]: Self::edit_iter
431    /// [`Point::default`]: crate::text::Point::default
432    pub fn edit_last<Ret>(&self, pa: &mut Pass, edit: impl FnOnce(Cursor<W, S>) -> Ret) -> Ret {
433        let len = self.widget.read(pa).text().selections().len();
434        self.edit_nth(pa, len.saturating_sub(1), edit)
435    }
436
437    /// A [`Lender`] over all [`Cursor`]s of the [`Text`]
438    ///
439    /// This lets you easily iterate over all [`Selection`]s, without
440    /// having to worry about insertion affecting the order at which
441    /// they are edited (like what repeated calls to [`edit_nth`]
442    /// would do)
443    ///
444    /// Note however that you can't use a [`Lender`] (also known as a
445    /// lending iterator) in a `for` loop, but you should be able
446    /// to just `while let Some(e) = editors.next() {}` or
447    /// `handle.edit_iter().for_each(|_| {})` instead.
448    ///
449    /// Just like all other `edit` methods, this one will populate the
450    /// [`Selections`], so if there are no [`Selection`]s, it will
451    /// create one at [`Point::default`].
452    ///
453    /// [`edit_nth`]: Self::edit_nth
454    /// [`Point::default`]: crate::text::Point::default
455    pub fn edit_iter<Ret>(
456        &self,
457        pa: &mut Pass,
458        edit: impl FnOnce(Cursors<'_, W, S>) -> Ret,
459    ) -> Ret {
460        edit(self.get_iter(pa))
461    }
462
463    /// A shortcut for iterating over all selections
464    ///
465    /// This is the equivalent of calling:
466    ///
467    /// ```rust
468    /// # duat_core::doc_duat!(duat);
469    /// # use duat::prelude::*;
470    /// # fn test(pa: &mut Pass, handle: Handle) {
471    /// handle.edit_iter(pa, |iter| iter.for_each(|e| { /* .. */ }));
472    /// # }
473    /// ```
474    ///
475    /// But it can't return a value, and is meant to reduce the
476    /// indentation that will inevitably come from using the
477    /// equivalent long form call.
478    pub fn edit_all(&self, pa: &mut Pass, edit: impl FnMut(Cursor<W, S>)) {
479        self.get_iter(pa).for_each(edit);
480    }
481
482    fn get_iter<'a>(&'a self, pa: &'a mut Pass) -> Cursors<'a, W, S> {
483        let (widget, area) = self.write_with_area(pa);
484        widget.text_mut().selections_mut().populate();
485
486        let searcher = self.searcher.borrow_mut();
487
488        Cursors::new(0, widget, area, searcher)
489    }
490
491    ////////// Area functions
492
493    /// Scrolls the [`Text`] veritcally by an amount
494    ///
495    /// If [`PrintOpts.allow_overscroll`] is set, then the [`Text`]
496    /// will be allowed to scroll beyond the last line, up until
497    /// reaching the `scrolloff.y` value.
498    ///
499    /// [`PrintOpts.allow_overscroll`]: crate::opts::PrintOpts::allow_overscroll
500    pub fn scroll_ver(&self, pa: &mut Pass, dist: i32) {
501        let (widget, area) = self.write_with_area(pa);
502        area.scroll_ver(widget.text(), dist, widget.get_print_opts());
503        self.widget.declare_written();
504    }
505
506    /// Scrolls the [`Text`] to the visual line of a [`TwoPoints`]
507    ///
508    /// If `scroll_beyond` is set, then the [`Text`] will be allowed
509    /// to scroll beyond the last line, up until reaching the
510    /// `scrolloff.y` value.
511    pub fn scroll_to_points(&self, pa: &mut Pass, points: TwoPoints) {
512        let (widget, area) = self.write_with_area(pa);
513        area.scroll_to_points(widget.text(), points, widget.get_print_opts());
514        self.widget.declare_written();
515    }
516
517    /// The start points that should be printed
518    pub fn start_points(&self, pa: &Pass) -> TwoPoints {
519        let widget = self.widget.read(pa);
520        self.area
521            .start_points(pa, widget.text(), widget.get_print_opts())
522    }
523
524    /// The end points that should be printed
525    pub fn end_points(&self, pa: &Pass) -> TwoPoints {
526        let widget = self.widget.read(pa);
527        self.area
528            .end_points(pa, widget.text(), widget.get_print_opts())
529    }
530
531    ////////// Querying functions
532
533    /// This [`Handle`]'s [`Widget`]
534    pub fn widget(&self) -> &RwData<W> {
535        &self.widget
536    }
537
538    /// This [`Handle`]'s [`RwArea`]
539    pub fn area(&self) -> &RwArea {
540        &self.area
541    }
542
543    /// Gets this [`Handle`]'s mask
544    ///
545    /// This mask is going to be used to map [`Form`]s to other
546    /// [`Form`]s when printing via [`Widget::print`]. To see more
547    /// about how masks work, see [`form::enable_mask`].
548    ///
549    /// [`Form`]: crate::form::Form
550    /// [`form::enable_mask`]: crate::form::enable_mask
551    pub fn mask(&self) -> &Arc<Mutex<&'static str>> {
552        &self.mask
553    }
554
555    /// Sets this [`Handle`]'s mask, returning the previous one
556    ///
557    /// This mask is going to be used to map [`Form`]s to other
558    /// [`Form`]s when printing via [`Widget::print`]. To see more
559    /// about how masks work, see [`form::enable_mask`].
560    ///
561    /// [`Form`]: crate::form::Form
562    /// [`form::enable_mask`]: crate::form::enable_mask
563    pub fn set_mask(&self, mask: &'static str) -> &'static str {
564        self.widget.declare_written();
565        std::mem::replace(&mut self.mask.lock().unwrap(), mask)
566    }
567
568    /// Wether someone else called [`write`] or [`write_as`] since the
569    /// last [`read`] or [`write`]
570    ///
571    /// Do note that this *DOES NOT* mean that the value inside has
572    /// actually been changed, it just means a mutable reference was
573    /// acquired after the last call to [`has_changed`].
574    ///
575    /// Some types like [`Text`], and traits like [`Widget`] offer
576    /// [`needs_update`] methods, you should try to determine what
577    /// parts to look for changes.
578    ///
579    /// Generally though, you can use this method to gauge that.
580    ///
581    /// [`write`]: RwData::write
582    /// [`write_as`]: RwData::write_as
583    /// [`read`]: RwData::read
584    /// [`has_changed`]: RwData::has_changed
585    /// [`Text`]: crate::text::Text
586    /// [`Widget`]: crate::ui::Widget
587    /// [`needs_update`]: crate::ui::Widget::needs_update
588    pub fn has_changed(&self, pa: &Pass) -> bool {
589        self.widget.has_changed() || self.area.has_changed(pa)
590    }
591
592    /// Wether the [`RwData`] within and another point to the same
593    /// value
594    pub fn ptr_eq<T: ?Sized>(&self, other: &RwData<T>) -> bool {
595        self.widget.ptr_eq(other)
596    }
597
598    /// The [`Widget`]'s [`PrintOpts`]
599    pub fn opts(&self, pa: &Pass) -> PrintOpts {
600        self.widget.read(pa).get_print_opts()
601    }
602
603    ////////// Related Handles
604
605    /// Returns the [`Handle`] this one was pushed to, if it was
606    /// pushed to another
607    ///
608    /// Will return [`Some`] if this `self` was created by calling
609    /// [`Handle::push_outer_widget`], [`Handle::push_inner_widget`],
610    /// [`Handle::spawn_widget`], or if the [`Widget`] was [spawned]
611    /// on the master's [`Text`]
612    ///
613    /// [spawned]: crate::text::SpawnTag
614    pub fn master(&self) -> Result<&Handle<dyn Widget>, Text> {
615        self.master
616            .as_ref()
617            .map(|handle| handle.as_ref())
618            .ok_or_else(|| txt!("Widget was not pushed to another"))
619    }
620
621    /// Returns the [`Handle<Buffer>`] this one was pushed to, if it
622    /// was pushed to one
623    ///
624    /// Will return [`Some`] if this `self` was created by calling
625    /// [`Handle::push_outer_widget`], [`Handle::push_inner_widget`],
626    /// [`Handle::spawn_widget`], or if the [`Widget`] was [spawned]
627    /// on the master's [`Text`]
628    ///
629    /// [spawned]: crate::text::SpawnTag
630    pub fn buffer(&self) -> Result<Handle, Text> {
631        self.master
632            .as_ref()
633            .and_then(|handle| handle.try_downcast())
634            .ok_or_else(|| txt!("Widget was not pushed to a [a]Buffer"))
635    }
636
637    /// Reads related [`Widget`]s of type `W2`, as well as its
638    /// [`Area`]
639    ///
640    /// This can also be done by calling [`Handle::get_related`], and
641    /// [`Handle::read`], but this function should generally be
642    /// faster, since there is no cloning of [`Arc`]s going on.
643    pub fn read_related<'a, W2: Widget>(
644        &'a self,
645        pa: &'a Pass,
646    ) -> impl Iterator<Item = (&'a W2, &'a Area, WidgetRelation)> {
647        self.read_as(pa)
648            .map(|w| (w, self.area().read(pa), WidgetRelation::Main))
649            .into_iter()
650            .chain(self.related.0.read(pa).iter().filter_map(|(handle, rel)| {
651                handle
652                    .read_as(pa)
653                    .map(|w| (w, handle.area().read(pa), *rel))
654            }))
655    }
656
657    /// Gets related [`Handle`]s of type [`Widget`]
658    ///
659    /// If you are doing this just to read the [`Widget`] and
660    /// [`Area`], consider using [`Handle::read_related`].
661    pub fn get_related<'a, W2: Widget>(
662        &'a self,
663        pa: &'a Pass,
664    ) -> impl Iterator<Item = (Handle<W2>, WidgetRelation)> + 'a {
665        self.try_downcast()
666            .zip(Some(WidgetRelation::Main))
667            .into_iter()
668            .chain(
669                self.related
670                    .0
671                    .read(pa)
672                    .iter()
673                    .filter_map(|(handle, rel)| handle.try_downcast().zip(Some(*rel))),
674            )
675    }
676
677    /// Raw access to the related widgets
678    pub(crate) fn related(&self) -> &RwData<Vec<(Handle<dyn Widget>, WidgetRelation)>> {
679        &self.related.0
680    }
681
682    ////////// Other methods
683
684    /// Attaches a [`Searcher`] to this [`Handle`], so you can do
685    /// incremental search
686    ///
687    /// An [`Handle`] with a [`Searcher`] not only has its usual
688    /// editing capabilities, but is also able to act on requested
689    /// regex searches, like those from [`IncSearch`], in
690    /// [`duat`]. This means that a user can type up a
691    /// [prompt] to search for something, and the [`Handle`]
692    /// can use the [`Searcher`] to interpret how that search will
693    /// be utilized. Examples of this can be found in the
694    /// [`duat`] crate, as well as the [`duat-kak`] crate,
695    /// which has some more advanced usage.
696    ///
697    /// [`Searcher`]: crate::text::Searcher
698    /// [`Selection`]: crate::mode::Selection
699    /// [`Cursor`]: crate::mode::Cursor
700    /// [`IncSearch`]: https://docs.rs/duat/latest/duat/modes/struct.IncSearch.html
701    /// [`duat`]: https://docs.rs/duat/lastest/
702    /// [prompt]: https://docs.rs/duat/latest/duat/modes/trait.PromptMode.html
703    /// [`duat-kak`]: https://docs.rs/duat-kak/lastest/
704    pub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, Searcher> {
705        Handle {
706            widget: self.widget.clone(),
707            area: self.area.clone(),
708            mask: self.mask.clone(),
709            related: self.related.clone(),
710            searcher: RefCell::new(searcher),
711            is_closed: self.is_closed.clone(),
712            master: self.master.clone(),
713        }
714    }
715
716    /// Pushes a [`Widget`] around this one
717    ///
718    /// This `Widget` will be placed internally, i.e., around the
719    /// [`Area`] of `self`. This is in contrast to
720    /// [`Handle::push_outer_widget`], which will push around the
721    /// "cluster master" of `self`.
722    ///
723    /// A cluster master is the collection of every `Widget` that was
724    /// pushed around a central one with [`PushSpecs::cluster`] set to
725    /// `true`.
726    ///
727    /// Both of these functions behave identically in the situation
728    /// where no other [`Widget`]s were pushed around `self`.
729    ///
730    /// However, if, for example, a [`Widget`] was previously pushed
731    /// below `self`, when pushing to the left, the following would
732    /// happen:
733    ///
734    /// ```text
735    /// ╭────────────────╮    ╭─────┬──────────╮
736    /// │                │    │     │          │
737    /// │      self      │    │ new │   self   │
738    /// │                │ -> │     │          │
739    /// ├────────────────┤    ├─────┴──────────┤
740    /// │      old       │    │      old       │
741    /// ╰────────────────╯    ╰────────────────╯
742    /// ```
743    ///
744    /// While in [`Handle::push_outer_widget`], this happens instead:
745    ///
746    /// ```text
747    /// ╭────────────────╮    ╭─────┬──────────╮
748    /// │                │    │     │          │
749    /// │      self      │    │     │   self   │
750    /// │                │ -> │ new │          │
751    /// ├────────────────┤    │     ├──────────┤
752    /// │      old       │    │     │   old    │
753    /// ╰────────────────╯    ╰─────┴──────────╯
754    /// ```
755    ///
756    /// Note that `new` was pushed _around_ other clustered widgets in
757    /// the second case, not just around `self`.
758    pub fn push_inner_widget<PW: Widget>(
759        &self,
760        pa: &mut Pass,
761        widget: PW,
762        specs: PushSpecs,
763    ) -> Handle<PW> {
764        context::windows()
765            .push_widget(pa, (&self.area, None, specs), widget, Some(&self.area))
766            .unwrap()
767    }
768
769    /// Pushes a [`Widget`] around the "cluster master" of this one
770    ///
771    /// A cluster master is the collection of every `Widget` that was
772    /// pushed around a central one with [`PushSpecs::cluster`] set to
773    /// `true`.
774    ///
775    /// This [`Widget`] will be placed externally, i.e., around every
776    /// other [`Widget`] that was pushed around `self`. This is in
777    /// contrast to [`Handle::push_inner_widget`], which will push
778    /// only around `self`.
779    ///
780    /// Both of these functions behave identically in the situation
781    /// where no other [`Widget`]s were pushed around `self`.
782    ///
783    /// However, if, for example, a [`Widget`] was previously pushed
784    /// to the left of `self`, when pushing to the left again, the
785    /// following would happen:
786    ///
787    /// ```text
788    /// ╭──────┬──────────╮    ╭─────┬─────┬──────╮
789    /// │      │          │    │     │     │      │
790    /// │      │          │    │     │     │      │
791    /// │  old │   self   │ -> │ new │ old │ self │
792    /// │      │          │    │     │     │      │
793    /// │      │          │    │     │     │      │
794    /// ╰──────┴──────────╯    ╰─────┴─────┴──────╯
795    /// ```
796    ///
797    /// While in [`Handle::push_inner_widget`], this happens instead:
798    ///
799    /// ```text
800    /// ╭──────┬──────────╮    ╭─────┬─────┬──────╮
801    /// │      │          │    │     │     │      │
802    /// │      │          │    │     │     │      │
803    /// │  old │   self   │ -> │ old │ new │ self │
804    /// │      │          │    │     │     │      │
805    /// │      │          │    │     │     │      │
806    /// ╰──────┴──────────╯    ╰─────┴─────┴──────╯
807    /// ```
808    ///
809    /// Note that `new` was pushed _around_ other clustered widgets in
810    /// the first case, not just around `self`.
811    pub fn push_outer_widget<PW: Widget>(
812        &self,
813        pa: &mut Pass,
814        widget: PW,
815        specs: PushSpecs,
816    ) -> Handle<PW> {
817        if let Some(master) = self.area().get_cluster_master(pa) {
818            context::windows()
819                .push_widget(pa, (&master, None, specs), widget, Some(self.area()))
820                .unwrap()
821        } else {
822            context::windows()
823                .push_widget(pa, (&self.area, None, specs), widget, Some(self.area()))
824                .unwrap()
825        }
826    }
827
828    /// Spawns a floating [`Widget`]
829    pub fn spawn_widget<SW: Widget>(
830        &self,
831        pa: &mut Pass,
832        widget: SW,
833        specs: DynSpawnSpecs,
834    ) -> Option<Handle<SW>> {
835        context::windows().spawn_on_widget(pa, (&self.area, specs), widget)
836    }
837
838    /// Closes this `Handle`, removing the [`Widget`] from the
839    /// [`Window`]
840    ///
841    /// [`Window`]: crate::ui::Window
842    pub fn close(&self, pa: &mut Pass) -> Result<(), Text> {
843        context::windows().close(pa, self)
844    }
845
846    /// Wether this `Handle` was already closed
847    pub fn is_closed(&self, pa: &Pass) -> bool {
848        *self.is_closed.read(pa)
849    }
850
851    /// Declares that this `Handle` has been closed
852    pub(crate) fn declare_closed(&self, pa: &mut Pass) {
853        *self.is_closed.write(pa) = true;
854    }
855}
856
857impl<W: Widget, S> Handle<W, S> {
858    /// Transforms this [`Handle`] into a [`Handle<dyn Widget>`]
859    pub fn to_dyn(&self) -> Handle<dyn Widget> {
860        Handle {
861            widget: self.widget.to_dyn_widget(),
862            // TODO: Arc wrapper, and Area: !Clone
863            area: self.area.clone(),
864            mask: self.mask.clone(),
865            related: self.related.clone(),
866            searcher: RefCell::new(()),
867            is_closed: self.is_closed.clone(),
868            master: self.master.clone(),
869        }
870    }
871}
872
873// SAFETY: The only parts that are accessible from other threads are
874// the atomic counters from the Arcs. Everything else can only be
875// acquired when there is a Pass, i.e., on the main thread.
876unsafe impl<W: Widget + ?Sized, S> Send for Handle<W, S> {}
877unsafe impl<W: Widget + ?Sized, S> Sync for Handle<W, S> {}
878
879impl<W1, W2, S1, S2> PartialEq<Handle<W2, S2>> for Handle<W1, S1>
880where
881    W1: Widget + ?Sized,
882    W2: Widget + ?Sized,
883{
884    fn eq(&self, other: &Handle<W2, S2>) -> bool {
885        self.widget().ptr_eq(other.widget())
886    }
887}
888
889impl<W: Widget + ?Sized> Clone for Handle<W> {
890    fn clone(&self) -> Self {
891        Self {
892            widget: self.widget.clone(),
893            area: self.area.clone(),
894            mask: self.mask.clone(),
895            related: self.related.clone(),
896            searcher: self.searcher.clone(),
897            is_closed: self.is_closed.clone(),
898            master: self.master.clone(),
899        }
900    }
901}
902
903impl<W: Widget + ?Sized, S> std::fmt::Debug for Handle<W, S> {
904    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
905        f.debug_struct("Handle")
906            .field("mask", &self.mask)
907            .finish_non_exhaustive()
908    }
909}
910
911#[derive(Clone)]
912struct RelatedWidgets(RwData<Vec<(Handle<dyn Widget>, WidgetRelation)>>);
913
914/// What relation this [`Widget`] has to its parent
915#[derive(Clone, Copy, Debug)]
916pub enum WidgetRelation {
917    /// The main widget of the cluster, most commonly a [`Buffer`]
918    ///
919    /// [`Buffer`]: crate::buffer::Buffer
920    Main,
921    /// A [`Widget`] that was pushed around the main `Widget`, e.g.
922    /// [`LineNumbers`]
923    ///
924    /// [`LineNumbers`]: docs.rs/duat/latest/duat/widgets/struct.LineNumbers.html
925    Pushed,
926    /// A [`Widget`] that was spawned on the `Widget`, e.g. completion
927    /// lists
928    Spawned,
929}