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, PushSpecs, RwArea, SpawnSpecs, 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 edit(Cursor::new(
372 (selection, n, was_main),
373 (widget, area),
374 None,
375 &mut searcher,
376 false,
377 ))
378 }
379
380 /// Edits the main [`Selection`] in the [`Text`]
381 ///
382 /// Once dropped, the [`Selection`] in this [`Cursor`] will be
383 /// added back to the list of [`Selection`]s, unless it is
384 /// [destroyed]
385 ///
386 /// If you want to edit on the `nth` selection, see [`edit_nth`],
387 /// same for [`edit_last`], if you want to edit on many
388 /// [`Selection`]s, see [`edit_iter`].
389 ///
390 /// Just like all other `edit` methods, this one will populate the
391 /// [`Selections`], so if there are no [`Selection`]s, it will
392 /// create one at [`Point::default`].
393 ///
394 /// [destroyed]: Cursor::destroy
395 /// [`edit_nth`]: Self::edit_nth
396 /// [`edit_last`]: Self::edit_last
397 /// [`edit_iter`]: Self::edit_iter
398 /// [`Point::default`]: crate::text::Point::default
399 pub fn edit_main<Ret>(&self, pa: &mut Pass, edit: impl FnOnce(Cursor<W, S>) -> Ret) -> Ret {
400 self.edit_nth(
401 pa,
402 self.widget.read(pa).text().selections().main_index(),
403 edit,
404 )
405 }
406
407 /// Edits the last [`Selection`] in the [`Text`]
408 ///
409 /// Once dropped, the [`Selection`] in this [`Cursor`] will be
410 /// added back to the list of [`Selection`]s, unless it is
411 /// [destroyed]
412 ///
413 /// If you want to edit on the `nth` selection, see [`edit_nth`],
414 /// same for [`edit_main`], if you want to edit on many
415 /// [`Selection`]s, see [`edit_iter`].
416 ///
417 /// Just like all other `edit` methods, this one will populate the
418 /// [`Selections`], so if there are no [`Selection`]s, it will
419 /// create one at [`Point::default`].
420 ///
421 /// [destroyed]: Cursor::destroy
422 /// [`edit_nth`]: Self::edit_nth
423 /// [`edit_main`]: Self::edit_main
424 /// [`edit_iter`]: Self::edit_iter
425 /// [`Point::default`]: crate::text::Point::default
426 pub fn edit_last<Ret>(&self, pa: &mut Pass, edit: impl FnOnce(Cursor<W, S>) -> Ret) -> Ret {
427 let len = self.widget.read(pa).text().selections().len();
428 self.edit_nth(pa, len.saturating_sub(1), edit)
429 }
430
431 /// A [`Lender`] over all [`Cursor`]s of the [`Text`]
432 ///
433 /// This lets you easily iterate over all [`Selection`]s, without
434 /// having to worry about insertion affecting the order at which
435 /// they are edited (like what repeated calls to [`edit_nth`]
436 /// would do)
437 ///
438 /// Note however that you can't use a [`Lender`] (also known as a
439 /// lending iterator) in a `for` loop, but you should be able
440 /// to just `while let Some(e) = editors.next() {}` or
441 /// `handle.edit_iter().for_each(|_| {})` instead.
442 ///
443 /// Just like all other `edit` methods, this one will populate the
444 /// [`Selections`], so if there are no [`Selection`]s, it will
445 /// create one at [`Point::default`].
446 ///
447 /// [`edit_nth`]: Self::edit_nth
448 /// [`Point::default`]: crate::text::Point::default
449 pub fn edit_iter<Ret>(
450 &self,
451 pa: &mut Pass,
452 edit: impl FnOnce(Cursors<'_, W, S>) -> Ret,
453 ) -> Ret {
454 edit(self.get_iter(pa))
455 }
456
457 /// A shortcut for iterating over all selections
458 ///
459 /// This is the equivalent of calling:
460 ///
461 /// ```rust
462 /// # duat_core::doc_duat!(duat);
463 /// # use duat::prelude::*;
464 /// # fn test(pa: &mut Pass, handle: Handle) {
465 /// handle.edit_iter(pa, |iter| iter.for_each(|e| { /* .. */ }));
466 /// # }
467 /// ```
468 ///
469 /// But it can't return a value, and is meant to reduce the
470 /// indentation that will inevitably come from using the
471 /// equivalent long form call.
472 pub fn edit_all(&self, pa: &mut Pass, edit: impl FnMut(Cursor<W, S>)) {
473 self.get_iter(pa).for_each(edit);
474 }
475
476 fn get_iter<'a>(&'a self, pa: &'a mut Pass) -> Cursors<'a, W, S> {
477 let (widget, area) = self.write_with_area(pa);
478 widget.text_mut().selections_mut().populate();
479
480 let searcher = self.searcher.borrow_mut();
481
482 Cursors::new(0, widget, area, searcher)
483 }
484
485 ////////// Area functions
486
487 /// Scrolls the [`Text`] veritcally by an amount
488 ///
489 /// If [`PrintOpts.allow_overscroll`] is set, then the [`Text`]
490 /// will be allowed to scroll beyond the last line, up until
491 /// reaching the `scrolloff.y` value.
492 ///
493 /// [`PrintOpts.allow_overscroll`]: crate::opts::PrintOpts::allow_overscroll
494 pub fn scroll_ver(&self, pa: &mut Pass, dist: i32) {
495 let (widget, area) = self.write_with_area(pa);
496 area.scroll_ver(widget.text(), dist, widget.get_print_opts());
497 self.widget.declare_written();
498 }
499
500 /// Scrolls the [`Text`] to the visual line of a [`TwoPoints`]
501 ///
502 /// If `scroll_beyond` is set, then the [`Text`] will be allowed
503 /// to scroll beyond the last line, up until reaching the
504 /// `scrolloff.y` value.
505 pub fn scroll_to_points(&self, pa: &mut Pass, points: TwoPoints) {
506 let (widget, area) = self.write_with_area(pa);
507 area.scroll_to_points(widget.text(), points, widget.get_print_opts());
508 self.widget.declare_written();
509 }
510
511 /// The start points that should be printed
512 pub fn start_points(&self, pa: &Pass) -> TwoPoints {
513 let widget = self.widget.read(pa);
514 self.area
515 .start_points(pa, widget.text(), widget.get_print_opts())
516 }
517
518 /// The end points that should be printed
519 pub fn end_points(&self, pa: &Pass) -> TwoPoints {
520 let widget = self.widget.read(pa);
521 self.area
522 .end_points(pa, widget.text(), widget.get_print_opts())
523 }
524
525 ////////// Querying functions
526
527 /// This [`Handle`]'s [`Widget`]
528 pub fn widget(&self) -> &RwData<W> {
529 &self.widget
530 }
531
532 /// This [`Handle`]'s [`RwArea`]
533 pub fn area(&self) -> &RwArea {
534 &self.area
535 }
536
537 /// Gets this [`Handle`]'s mask
538 ///
539 /// This mask is going to be used to map [`Form`]s to other
540 /// [`Form`]s when printing via [`Widget::print`]. To see more
541 /// about how masks work, see [`form::enable_mask`].
542 ///
543 /// [`Form`]: crate::form::Form
544 /// [`form::enable_mask`]: crate::form::enable_mask
545 pub fn mask(&self) -> &Arc<Mutex<&'static str>> {
546 &self.mask
547 }
548
549 /// Sets this [`Handle`]'s mask, returning the previous one
550 ///
551 /// This mask is going to be used to map [`Form`]s to other
552 /// [`Form`]s when printing via [`Widget::print`]. To see more
553 /// about how masks work, see [`form::enable_mask`].
554 ///
555 /// [`Form`]: crate::form::Form
556 /// [`form::enable_mask`]: crate::form::enable_mask
557 pub fn set_mask(&self, mask: &'static str) -> &'static str {
558 self.widget.declare_written();
559 std::mem::replace(&mut self.mask.lock().unwrap(), mask)
560 }
561
562 /// Wether someone else called [`write`] or [`write_as`] since the
563 /// last [`read`] or [`write`]
564 ///
565 /// Do note that this *DOES NOT* mean that the value inside has
566 /// actually been changed, it just means a mutable reference was
567 /// acquired after the last call to [`has_changed`].
568 ///
569 /// Some types like [`Text`], and traits like [`Widget`] offer
570 /// [`needs_update`] methods, you should try to determine what
571 /// parts to look for changes.
572 ///
573 /// Generally though, you can use this method to gauge that.
574 ///
575 /// [`write`]: RwData::write
576 /// [`write_as`]: RwData::write_as
577 /// [`read`]: RwData::read
578 /// [`has_changed`]: RwData::has_changed
579 /// [`Text`]: crate::text::Text
580 /// [`Widget`]: crate::ui::Widget
581 /// [`needs_update`]: crate::ui::Widget::needs_update
582 pub fn has_changed(&self, pa: &Pass) -> bool {
583 self.widget.has_changed() || self.area.has_changed(pa)
584 }
585
586 /// Wether the [`RwData`] within and another point to the same
587 /// value
588 pub fn ptr_eq<T: ?Sized>(&self, other: &RwData<T>) -> bool {
589 self.widget.ptr_eq(other)
590 }
591
592 /// The [`Widget`]'s [`PrintOpts`]
593 pub fn opts(&self, pa: &Pass) -> PrintOpts {
594 self.widget.read(pa).get_print_opts()
595 }
596
597 ////////// Related Handles
598
599 /// Returns the [`Handle`] this one was pushed to, if it was
600 /// pushed to another
601 ///
602 /// Will return [`Some`] if this `self` was created by calling
603 /// [`Handle::push_outer_widget`], [`Handle::push_inner_widget`],
604 /// [`Handle::spawn_widget`], or if the [`Widget`] was [spawned]
605 /// on the master's [`Text`]
606 ///
607 /// [spawned]: crate::text::SpawnTag
608 pub fn master(&self) -> Result<&Handle<dyn Widget>, Text> {
609 self.master
610 .as_ref()
611 .map(|handle| handle.as_ref())
612 .ok_or_else(|| txt!("Widget was not pushed to another"))
613 }
614
615 /// Returns the [`Handle<Buffer>`] this one was pushed to, if it
616 /// was pushed to one
617 ///
618 /// Will return [`Some`] if this `self` was created by calling
619 /// [`Handle::push_outer_widget`], [`Handle::push_inner_widget`],
620 /// [`Handle::spawn_widget`], or if the [`Widget`] was [spawned]
621 /// on the master's [`Text`]
622 ///
623 /// [spawned]: crate::text::SpawnTag
624 pub fn buffer(&self) -> Result<Handle, Text> {
625 self.master
626 .as_ref()
627 .and_then(|handle| handle.try_downcast())
628 .ok_or_else(|| txt!("Widget was not pushed to a [a]Buffer"))
629 }
630
631 /// Reads related [`Widget`]s of type `W2`, as well as its
632 /// [`Area`]
633 ///
634 /// This can also be done by calling [`Handle::get_related`], and
635 /// [`Handle::read`], but this function should generally be
636 /// faster, since there is no cloning of [`Arc`]s going on.
637 pub fn read_related<'a, W2: Widget>(
638 &'a self,
639 pa: &'a Pass,
640 ) -> impl Iterator<Item = (&'a W2, &'a Area, WidgetRelation)> {
641 self.read_as(pa)
642 .map(|w| (w, self.area().read(pa), WidgetRelation::Main))
643 .into_iter()
644 .chain(self.related.0.read(pa).iter().filter_map(|(handle, rel)| {
645 handle
646 .read_as(pa)
647 .map(|w| (w, handle.area().read(pa), *rel))
648 }))
649 }
650
651 /// Gets related [`Handle`]s of type [`Widget`]
652 ///
653 /// If you are doing this just to read the [`Widget`] and
654 /// [`Area`], consider using [`Handle::read_related`].
655 pub fn get_related<'a, W2: Widget>(
656 &'a self,
657 pa: &'a Pass,
658 ) -> impl Iterator<Item = (Handle<W2>, WidgetRelation)> + 'a {
659 self.try_downcast()
660 .zip(Some(WidgetRelation::Main))
661 .into_iter()
662 .chain(
663 self.related
664 .0
665 .read(pa)
666 .iter()
667 .filter_map(|(handle, rel)| handle.try_downcast().zip(Some(*rel))),
668 )
669 }
670
671 /// Raw access to the related widgets
672 pub(crate) fn related(&self) -> &RwData<Vec<(Handle<dyn Widget>, WidgetRelation)>> {
673 &self.related.0
674 }
675
676 ////////// Other methods
677
678 /// Attaches a [`Searcher`] to this [`Handle`], so you can do
679 /// incremental search
680 ///
681 /// An [`Handle`] with a [`Searcher`] not only has its usual
682 /// editing capabilities, but is also able to act on requested
683 /// regex searches, like those from [`IncSearch`], in
684 /// [`duat`]. This means that a user can type up a
685 /// [prompt] to search for something, and the [`Handle`]
686 /// can use the [`Searcher`] to interpret how that search will
687 /// be utilized. Examples of this can be found in the
688 /// [`duat`] crate, as well as the [`duat-kak`] crate,
689 /// which has some more advanced usage.
690 ///
691 /// [`Searcher`]: crate::text::Searcher
692 /// [`Selection`]: crate::mode::Selection
693 /// [`Cursor`]: crate::mode::Cursor
694 /// [`IncSearch`]: https://docs.rs/duat/latest/duat/modes/struct.IncSearch.html
695 /// [`duat`]: https://docs.rs/duat/lastest/
696 /// [prompt]: https://docs.rs/duat/latest/duat/modes/trait.PromptMode.html
697 /// [`duat-kak`]: https://docs.rs/duat-kak/lastest/
698 pub fn attach_searcher(&self, searcher: Searcher) -> Handle<W, Searcher> {
699 Handle {
700 widget: self.widget.clone(),
701 area: self.area.clone(),
702 mask: self.mask.clone(),
703 related: self.related.clone(),
704 searcher: RefCell::new(searcher),
705 is_closed: self.is_closed.clone(),
706 master: self.master.clone(),
707 }
708 }
709
710 /// Pushes a [`Widget`] around this one
711 ///
712 /// This `Widget` will be placed internally, i.e., around the
713 /// [`Area`] of `self`. This is in contrast to
714 /// [`Handle::push_outer_widget`], which will push around the
715 /// "cluster master" of `self`.
716 ///
717 /// A cluster master is the collection of every `Widget` that was
718 /// pushed around a central one with [`PushSpecs::cluster`] set to
719 /// `true`.
720 ///
721 /// Both of these functions behave identically in the situation
722 /// where no other [`Widget`]s were pushed around `self`.
723 ///
724 /// However, if, for example, a [`Widget`] was previously pushed
725 /// below `self`, when pushing to the left, the following would
726 /// happen:
727 ///
728 /// ```text
729 /// ╭────────────────╮ ╭─────┬──────────╮
730 /// │ │ │ │ │
731 /// │ self │ │ new │ self │
732 /// │ │ -> │ │ │
733 /// ├────────────────┤ ├─────┴──────────┤
734 /// │ old │ │ old │
735 /// ╰────────────────╯ ╰────────────────╯
736 /// ```
737 ///
738 /// While in [`Handle::push_outer_widget`], this happens instead:
739 ///
740 /// ```text
741 /// ╭────────────────╮ ╭─────┬──────────╮
742 /// │ │ │ │ │
743 /// │ self │ │ │ self │
744 /// │ │ -> │ new │ │
745 /// ├────────────────┤ │ ├──────────┤
746 /// │ old │ │ │ old │
747 /// ╰────────────────╯ ╰─────┴──────────╯
748 /// ```
749 ///
750 /// Note that `new` was pushed _around_ other clustered widgets in
751 /// the second case, not just around `self`.
752 pub fn push_inner_widget<PW: Widget>(
753 &self,
754 pa: &mut Pass,
755 widget: PW,
756 specs: PushSpecs,
757 ) -> Handle<PW> {
758 context::windows()
759 .push_widget(pa, (&self.area, None, specs), widget, Some(&self.area))
760 .unwrap()
761 }
762
763 /// Pushes a [`Widget`] around the "cluster master" of this one
764 ///
765 /// A cluster master is the collection of every `Widget` that was
766 /// pushed around a central one with [`PushSpecs::cluster`] set to
767 /// `true`.
768 ///
769 /// This [`Widget`] will be placed externally, i.e., around every
770 /// other [`Widget`] that was pushed around `self`. This is in
771 /// contrast to [`Handle::push_inner_widget`], which will push
772 /// only around `self`.
773 ///
774 /// Both of these functions behave identically in the situation
775 /// where no other [`Widget`]s were pushed around `self`.
776 ///
777 /// However, if, for example, a [`Widget`] was previously pushed
778 /// to the left of `self`, when pushing to the left again, the
779 /// following would happen:
780 ///
781 /// ```text
782 /// ╭──────┬──────────╮ ╭─────┬─────┬──────╮
783 /// │ │ │ │ │ │ │
784 /// │ │ │ │ │ │ │
785 /// │ old │ self │ -> │ new │ old │ self │
786 /// │ │ │ │ │ │ │
787 /// │ │ │ │ │ │ │
788 /// ╰──────┴──────────╯ ╰─────┴─────┴──────╯
789 /// ```
790 ///
791 /// While in [`Handle::push_inner_widget`], this happens instead:
792 ///
793 /// ```text
794 /// ╭──────┬──────────╮ ╭─────┬─────┬──────╮
795 /// │ │ │ │ │ │ │
796 /// │ │ │ │ │ │ │
797 /// │ old │ self │ -> │ old │ new │ self │
798 /// │ │ │ │ │ │ │
799 /// │ │ │ │ │ │ │
800 /// ╰──────┴──────────╯ ╰─────┴─────┴──────╯
801 /// ```
802 ///
803 /// Note that `new` was pushed _around_ other clustered widgets in
804 /// the first case, not just around `self`.
805 pub fn push_outer_widget<PW: Widget>(
806 &self,
807 pa: &mut Pass,
808 widget: PW,
809 specs: PushSpecs,
810 ) -> Handle<PW> {
811 if let Some(master) = self.area().get_cluster_master(pa) {
812 context::windows()
813 .push_widget(pa, (&master, None, specs), widget, Some(self.area()))
814 .unwrap()
815 } else {
816 context::windows()
817 .push_widget(pa, (&self.area, None, specs), widget, Some(self.area()))
818 .unwrap()
819 }
820 }
821
822 /// Spawns a floating [`Widget`]
823 pub fn spawn_widget<SW: Widget>(
824 &self,
825 pa: &mut Pass,
826 widget: SW,
827 specs: SpawnSpecs,
828 ) -> Option<Handle<SW>> {
829 context::windows().spawn_on_widget(pa, (&self.area, specs), widget)
830 }
831
832 /// Closes this `Handle`, removing the [`Widget`] from the
833 /// [`Window`]
834 ///
835 /// [`Window`]: crate::ui::Window
836 pub fn close(&self, pa: &mut Pass) -> Result<(), Text> {
837 context::windows().close(pa, self)
838 }
839
840 /// Wether this `Handle` was already closed
841 pub fn is_closed(&self, pa: &Pass) -> bool {
842 *self.is_closed.read(pa)
843 }
844
845 /// Declares that this `Handle` has been closed
846 pub(crate) fn declare_closed(&self, pa: &mut Pass) {
847 *self.is_closed.write(pa) = true;
848 }
849}
850
851impl<W: Widget, S> Handle<W, S> {
852 /// Transforms this [`Handle`] into a [`Handle<dyn Widget>`]
853 pub fn to_dyn(&self) -> Handle<dyn Widget> {
854 Handle {
855 widget: self.widget.to_dyn_widget(),
856 // TODO: Arc wrapper, and Area: !Clone
857 area: self.area.clone(),
858 mask: self.mask.clone(),
859 related: self.related.clone(),
860 searcher: RefCell::new(()),
861 is_closed: self.is_closed.clone(),
862 master: self.master.clone(),
863 }
864 }
865}
866
867// SAFETY: The only parts that are accessible from other threads are
868// the atomic counters from the Arcs. Everything else can only be
869// acquired when there is a Pass, i.e., on the main thread.
870unsafe impl<W: Widget + ?Sized, S> Send for Handle<W, S> {}
871unsafe impl<W: Widget + ?Sized, S> Sync for Handle<W, S> {}
872
873impl<W1, W2, S1, S2> PartialEq<Handle<W2, S2>> for Handle<W1, S1>
874where
875 W1: Widget + ?Sized,
876 W2: Widget + ?Sized,
877{
878 fn eq(&self, other: &Handle<W2, S2>) -> bool {
879 self.widget().ptr_eq(other.widget())
880 }
881}
882
883impl<W: Widget + ?Sized> Clone for Handle<W> {
884 fn clone(&self) -> Self {
885 Self {
886 widget: self.widget.clone(),
887 area: self.area.clone(),
888 mask: self.mask.clone(),
889 related: self.related.clone(),
890 searcher: self.searcher.clone(),
891 is_closed: self.is_closed.clone(),
892 master: self.master.clone(),
893 }
894 }
895}
896
897impl<W: Widget + ?Sized, S> std::fmt::Debug for Handle<W, S> {
898 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
899 f.debug_struct("Handle")
900 .field("mask", &self.mask)
901 .finish_non_exhaustive()
902 }
903}
904
905#[derive(Clone)]
906struct RelatedWidgets(RwData<Vec<(Handle<dyn Widget>, WidgetRelation)>>);
907
908/// What relation this [`Widget`] has to its parent
909#[derive(Clone, Copy, Debug)]
910pub enum WidgetRelation {
911 /// The main widget of the cluster, most commonly a [`Buffer`]
912 ///
913 /// [`Buffer`]: crate::buffer::Buffer
914 Main,
915 /// A [`Widget`] that was pushed around the main `Widget`, e.g.
916 /// [`LineNumbers`]
917 ///
918 /// [`LineNumbers`]: docs.rs/duat/latest/duat/widgets/struct.LineNumbers.html
919 Pushed,
920 /// A [`Widget`] that was spawned on the `Widget`, e.g. completion
921 /// lists
922 Spawned,
923}