1use std::{
13 iter::Chain,
14 path::Path,
15 sync::{Arc, Mutex},
16};
17
18use super::{Node, Widget, layout::Layout};
19use crate::{
20 buffer::{Buffer, BufferOpts, PathKind},
21 context::{self, Handle},
22 data::{Pass, RwData},
23 hook::{self, BufferClosed, BufferSwitched, BufferUnloaded, WidgetOpened, WindowOpened},
24 mode,
25 session::UiMouseEvent,
26 text::{Text, txt},
27 ui::{Coord, DynSpawnSpecs, PushSpecs, RwArea, SpawnId, StaticSpawnSpecs, Ui},
28};
29
30pub struct Windows {
32 inner: RwData<InnerWindows>,
33 spawns_to_remove: Mutex<Vec<SpawnId>>,
34 ui: Ui,
35}
36
37struct InnerWindows {
39 layout: Box<Mutex<dyn Layout>>,
40 list: Vec<Window>,
41 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
42 cur_buffer: RwData<Handle>,
43 cur_widget: RwData<Node>,
44 cur_win: usize,
45 buffer_history: BufferHistory,
46}
47
48impl Windows {
49 pub(crate) fn initialize(
52 pa: &mut Pass,
53 buffer: Buffer,
54 layout: Box<Mutex<dyn Layout>>,
55 ui: Ui,
56 ) {
57 let new_additions = Arc::new(Mutex::default());
58 let (window, node) = Window::new(0, pa, ui, buffer, new_additions.clone());
59
60 context::set_windows(Self {
61 inner: RwData::new(InnerWindows {
62 layout,
63 list: vec![window.clone()],
64 new_additions,
65 cur_buffer: RwData::new(node.try_downcast().unwrap()),
66 cur_widget: RwData::new(node.clone()),
67 cur_win: 0,
68 buffer_history: BufferHistory::default(),
69 }),
70 spawns_to_remove: Mutex::new(Vec::new()),
71 ui,
72 });
73
74 hook::trigger(
75 pa,
76 WidgetOpened(node.handle().try_downcast::<Buffer>().unwrap()),
77 );
78 hook::trigger(pa, WindowOpened(window));
79 }
80
81 pub(crate) fn new_window(&self, pa: &mut Pass, buffer: Buffer) -> Node {
86 let win = self.inner.read(pa).list.len();
87 let new_additions = self.inner.read(pa).new_additions.clone();
88 let (window, node) = Window::new(win, pa, self.ui, buffer, new_additions);
89
90 let inner = self.inner.write(pa);
91 inner.list.push(window);
92
93 hook::trigger(pa, WindowOpened(self.inner.read(pa).list[win].clone()));
94 hook::trigger(
95 pa,
96 WidgetOpened(node.handle().try_downcast::<Buffer>().unwrap()),
97 );
98
99 node
100 }
101
102 pub(crate) fn push_widget<W: Widget>(
104 &self,
105 pa: &mut Pass,
106 (target, on_buffers, specs): (&RwArea, Option<bool>, PushSpecs),
107 widget: W,
108 master: Option<&RwArea>,
109 ) -> Option<Handle<W>> {
110 self.push(pa, (target, on_buffers, specs), widget, master)?
111 .handle()
112 .try_downcast()
113 }
114
115 pub(crate) fn spawn_on_widget<W: Widget>(
119 &self,
120 pa: &mut Pass,
121 (target, specs): (&RwArea, DynSpawnSpecs),
122 widget: W,
123 ) -> Option<Handle<W>> {
124 let (win, cluster_master, master) =
125 self.inner
126 .read(pa)
127 .list
128 .iter()
129 .enumerate()
130 .find_map(|(win, window)| {
131 let inner = window.0.read(pa);
132 let master = window.nodes(pa).find_map(|node| {
133 node.area()
134 .area_is_eq(pa, target)
135 .then(|| node.handle().clone())
136 });
137
138 if inner.master_area.is_master_of(pa, target) {
139 Some((win, None, master))
140 } else if let Some((_, node)) = inner
141 .spawned
142 .iter()
143 .find(|(_, node)| node.area().is_master_of(pa, target))
144 {
145 Some((win, node.area().get_cluster_master(pa), master))
146 } else {
147 None
148 }
149 })?;
150
151 let widget = RwData::new(widget);
152 let id = SpawnId::new();
153
154 let path = widget
155 .read_as::<Buffer>(pa)
156 .and_then(|buffer| buffer.path_set());
157 let spawned = cluster_master.as_ref().unwrap_or(target).spawn(
158 pa,
159 path.as_ref().map(|p| p.as_ref()),
160 id,
161 specs,
162 )?;
163
164 let node = Node::new(widget, spawned, master);
165
166 let window = self.inner.write(pa).list.remove(win);
167 window.add(pa, node.clone(), None, Location::Spawned(id));
168 self.inner.write(pa).list.insert(win, window);
169
170 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
171
172 node.handle().try_downcast()
173 }
174
175 pub(crate) fn spawn_on_text<W: Widget>(
177 &self,
178 pa: &mut Pass,
179 (id, specs): (SpawnId, DynSpawnSpecs),
180 widget: W,
181 win: usize,
182 master: Handle<dyn Widget>,
183 ) -> Handle<W> {
184 let widget = RwData::new(widget);
185 let path = widget
186 .read_as::<Buffer>(pa)
187 .and_then(|buffer| buffer.path_set());
188 let spawned = self
189 .ui
190 .new_dyn_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
191
192 let node = Node::new(widget, spawned, Some(master));
193
194 let window = self.inner.write(pa).list.remove(win);
195 window.add(pa, node.clone(), None, Location::Spawned(id));
196 self.inner.write(pa).list.insert(win, window);
197
198 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
199
200 node.handle().try_downcast().unwrap()
201 }
202
203 fn spawn_static<W: Widget>(
204 &self,
205 pa: &mut Pass,
206 (specs, win): (StaticSpawnSpecs, usize),
207 widget: W,
208 ) -> Option<Handle<W>> {
209 let id = SpawnId::new();
210 let widget = RwData::new(widget);
211 let path = widget
212 .read_as::<Buffer>(pa)
213 .and_then(|buffer| buffer.path_set());
214 let spawned = self
215 .ui
216 .new_static_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
217
218 let node = Node::new(widget, spawned, None);
219
220 let window = self.inner.write(pa).list.remove(win);
221 window.add(pa, node.clone(), None, Location::Spawned(id));
222 self.inner.write(pa).list.insert(win, window);
223
224 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
225
226 node.handle().try_downcast()
227 }
228
229 pub(crate) fn new_buffer(&self, pa: &mut Pass, buffer: Buffer) -> Node {
236 let inner = self.inner.read(pa);
237 let (handle, specs) = inner.layout.lock().unwrap().new_buffer(pa, &inner.list);
238
239 let specs = PushSpecs { cluster: false, ..specs };
240
241 if let Some(master) = handle.area().get_cluster_master(pa) {
242 self.push(pa, (&master, Some(true), specs), buffer, None)
243 .unwrap()
244 } else {
245 self.push(pa, (&handle.area, Some(true), specs), buffer, None)
246 .unwrap()
247 }
248 }
249
250 fn push<W: Widget>(
254 &self,
255 pa: &mut Pass,
256 (target, on_buffers, mut specs): (&RwArea, Option<bool>, PushSpecs),
257 widget: W,
258 master: Option<&RwArea>,
259 ) -> Option<Node> {
260 let inner = self.inner.read(pa);
261 let win = inner
262 .list
263 .iter()
264 .position(|window| {
265 window.0.read(pa).master_area.is_master_of(pa, target)
266 || window
267 .nodes(pa)
268 .any(|node| node.area().is_master_of(pa, target))
269 })
270 .unwrap();
271
272 let inner_window = inner.list[win].0.read(pa);
273 let target_is_on_buffers = inner_window.buffers_area.is_master_of(pa, target);
274
275 let on_buffers = on_buffers.unwrap_or(target_is_on_buffers) && target_is_on_buffers;
276
277 if target_is_on_buffers && !on_buffers {
278 specs.cluster = false;
279 }
280
281 let location = if on_buffers {
282 Location::OnBuffers
283 } else if let Some((id, _)) = inner_window
284 .spawned
285 .iter()
286 .find(|(_, node)| node.area().area_is_eq(pa, target))
287 {
288 Location::Spawned(*id)
289 } else {
290 Location::Regular
291 };
292
293 let widget = RwData::new(widget);
294 let path = widget
295 .read_as::<Buffer>(pa)
296 .and_then(|buffer| buffer.path_set());
297 let (pushed, parent) =
298 target.push(pa, path.as_ref().map(|p| p.as_ref()), specs, on_buffers)?;
299
300 let master = master.and_then(|area| {
301 self.entries(pa).find_map(|(.., node)| {
302 node.area()
303 .area_is_eq(pa, area)
304 .then(|| node.handle().clone())
305 })
306 });
307
308 let node = Node::new(widget, pushed, master);
309
310 let window = self.inner.write(pa).list.remove(win);
311 window.add(pa, node.clone(), parent, location);
312 self.inner.write(pa).list.insert(win, window);
313
314 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
315
316 Some(node)
317 }
318
319 pub(crate) fn close<W: Widget + ?Sized>(
323 &self,
324 pa: &mut Pass,
325 handle: &Handle<W>,
326 ) -> Result<(), Text> {
327 let win = self.handle_window(pa, handle)?;
328
329 if let Some(buf_handle) = handle.try_downcast::<Buffer>() {
332 hook::trigger(pa, BufferUnloaded(buf_handle.clone()));
333 hook::trigger(pa, BufferClosed(buf_handle.clone()));
334
335 let buffers_ahead: Vec<Node> = self.inner.read(pa).list[win]
336 .nodes(pa)
337 .filter(|node| {
338 node.handle().read_as::<Buffer>(pa).is_some_and(|buffer| {
339 buffer.layout_order > buf_handle.read(pa).layout_order
340 })
341 })
342 .cloned()
343 .collect();
344
345 for buffer_ahead in buffers_ahead {
346 self.swap(pa, handle, buffer_ahead.handle())?;
347 }
348 }
349
350 let mut list = std::mem::take(&mut self.inner.write(pa).list);
352
353 if list[win].close(pa, handle) {
354 list.remove(win);
355 self.ui.remove_window(win);
356 let cur_win = context::current_win_index(pa);
357 if cur_win > win {
358 self.inner.write(pa).cur_win -= 1;
359 }
360 }
361
362 let inner = self.inner.write(pa);
363 inner.list = list;
364 inner.new_additions.lock().unwrap().get_or_insert_default();
365
366 let inner = self.inner.read(pa);
368 if handle == inner.cur_widget.read(pa).handle() || handle == inner.cur_buffer.read(pa) {
369 if let Some(handle) = handle.try_downcast::<Buffer>() {
370 self.inner.write(pa).buffer_history.remove(&handle);
371
372 let entry = self
373 .inner
374 .write(pa)
375 .buffer_history
376 .jump_by(handle.clone(), -1)
377 .or_else(|| self.buffers(pa).first().cloned())
378 .and_then(|handle| {
379 self.entries(pa).find_map(|(win, node)| {
380 (*node.handle() == handle).then(|| (win, node.clone()))
381 })
382 });
383
384 if let Some((_, node)) = entry {
385 crate::mode::reset_to(pa, node.handle());
386 } else {
387 context::sender().send(crate::session::DuatEvent::Quit);
389 return Ok(());
390 }
391 } else {
392 crate::mode::reset_to(pa, &inner.cur_buffer.read(pa).clone());
393 }
394 }
395
396 Ok(())
397 }
398
399 pub(crate) fn swap<W1: Widget + ?Sized, W2: Widget + ?Sized>(
401 &self,
402 pa: &mut Pass,
403 lhs: &Handle<W1>,
404 rhs: &Handle<W2>,
405 ) -> Result<(), Text> {
406 let lhs_win = self.handle_window(pa, lhs)?;
407 let rhs_win = self.handle_window(pa, rhs)?;
408
409 let [lhs_buffer, rhs_buffer] = [lhs.try_downcast::<Buffer>(), rhs.try_downcast()];
410
411 if let [Some(lhs), Some(rhs)] = [lhs_buffer, rhs_buffer] {
412 let lhs_lo = lhs.read(pa).layout_order;
413 let rhs_lo = std::mem::replace(&mut rhs.write(pa).layout_order, lhs_lo);
414 lhs.write(pa).layout_order = rhs_lo
415 }
416
417 let windows = std::mem::take(&mut self.inner.write(pa).list);
418
419 let lhs_nodes = windows[lhs_win].take_with_related_nodes(pa, lhs);
420 windows[rhs_win].insert_nodes(pa, lhs_nodes);
421
422 let rhs_nodes = windows[rhs_win].take_with_related_nodes(pa, rhs);
423 windows[lhs_win].insert_nodes(pa, rhs_nodes);
424
425 let wins = self.inner.write(pa);
426 wins.list = windows;
427 wins.new_additions.lock().unwrap().get_or_insert_default();
428
429 lhs.area().swap(pa, rhs.area());
430
431 let cur_buffer = context::current_buffer(pa);
432 if lhs_win != rhs_win {
433 if *lhs == cur_buffer {
434 self.inner.write(pa).cur_win = lhs_win;
435 self.ui.switch_window(lhs_win);
436 } else if *rhs == cur_buffer {
437 self.inner.write(pa).cur_win = rhs_win;
438 self.ui.switch_window(rhs_win);
439 }
440 }
441
442 Ok(())
443 }
444
445 pub(crate) fn open_or_move_to_new_window(
448 &self,
449 pa: &mut Pass,
450 pk: PathKind,
451 default_buffer_opts: BufferOpts,
452 ) -> Node {
453 let node = match self.buffer_entry(pa, pk.clone()) {
454 Ok((win, handle)) if self.get(pa, win).unwrap().buffers(pa).len() > 1 => {
455 handle.write(pa).layout_order = 0;
457
458 let nodes = {
459 let old_window = self.inner.write(pa).list.remove(win);
460 let nodes = old_window.take_with_related_nodes(pa, &handle.to_dyn());
461 self.inner.write(pa).list.insert(win, old_window);
462
463 nodes
464 };
465
466 let path = handle.read(pa).path_set();
468 let new_root = self.ui.new_root(path.as_ref().map(|p| p.as_ref()));
469 handle.area().swap(pa, &new_root);
470 let window = Window::new_from_raw(
471 pa,
472 win,
473 handle.area.clone(),
474 nodes,
475 self.inner.read(pa).new_additions.clone(),
476 );
477
478 self.inner.write(pa).list.push(window.clone());
479
480 hook::trigger(pa, WindowOpened(window));
481
482 let lo = handle.read(pa).layout_order;
484
485 for handle in &self.inner.read(pa).list[win].buffers(pa)[lo..] {
486 new_root.swap(pa, handle.area());
487 }
488
489 new_root.delete(pa);
492
493 self.inner
494 .write(pa)
495 .new_additions
496 .lock()
497 .unwrap()
498 .get_or_insert_default();
499
500 Node::from_handle(handle)
501 }
502 Ok((.., handle)) => Node::from_handle(handle),
505 Err(_) => self.new_window(pa, Buffer::new(pk.as_path(), default_buffer_opts)),
506 };
507
508 if context::current_buffer(pa).read(pa).path_kind() != pk {
509 mode::reset_to(pa, node.handle());
510 }
511
512 node
513 }
514
515 #[track_caller]
517 pub(crate) fn set_current_node(&self, pa: &mut Pass, node: Node) -> Result<(), Text> {
518 let internal_pass = &mut unsafe { Pass::new() };
521
522 let win = self.handle_window(pa, node.handle())?;
523 let inner = self.inner.write(pa);
524
525 if let Some(current) = node.try_downcast::<Buffer>() {
526 let former = std::mem::replace(inner.cur_buffer.write(internal_pass), current.clone());
527 inner.buffer_history.insert(former.clone(), current.clone());
528
529 hook::trigger(pa, BufferSwitched((former, current)));
530 }
531
532 let inner = self.inner.write(pa);
533 *inner.cur_widget.write(internal_pass) = node.clone();
534 inner.cur_win = win;
535 self.ui.switch_window(win);
536
537 Ok(())
538 }
539
540 pub(crate) fn queue_close_spawned(&self, id: SpawnId) {
544 let mut spawns_to_remove = self.spawns_to_remove.lock().unwrap();
545 if !spawns_to_remove.contains(&id) {
546 spawns_to_remove.push(id)
547 }
548 }
549
550 pub(crate) fn cleanup_despawned(&self, pa: &mut Pass) {
553 let spawns_to_remove = std::mem::take(&mut *self.spawns_to_remove.lock().unwrap());
554 for id in spawns_to_remove {
555 if let Some((_, node)) = self
556 .iter(pa)
557 .flat_map(|window| &window.0.read(pa).spawned)
558 .find(|(other, _)| *other == id)
559 {
560 self.close(pa, &node.handle().clone()).unwrap();
561 }
562 }
563 }
564
565 pub(crate) fn handle_window<W: Widget + ?Sized>(
569 &self,
570 pa: &Pass,
571 handle: &Handle<W>,
572 ) -> Result<usize, Text> {
573 self.entries(pa)
574 .find_map(|(win, node)| (node.handle() == handle).then_some(win))
575 .ok_or_else(|| txt!("The Handle was already closed"))
576 }
577
578 pub(crate) fn buffer_entry(&self, pa: &Pass, pk: PathKind) -> Result<(usize, Handle), Text> {
580 self.entries(pa)
581 .find_map(|(win, node)| {
582 (node.read_as(pa).filter(|f: &&Buffer| f.path_kind() == pk))
583 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
584 })
585 .ok_or_else(|| txt!("Buffer {pk} not found"))
586 }
587
588 pub(crate) fn named_buffer_entry(
590 &self,
591 pa: &Pass,
592 name: &str,
593 ) -> Result<(usize, Handle), Text> {
594 self.entries(pa)
595 .find_map(|(win, node)| {
596 (node.read_as(pa).filter(|f: &&Buffer| f.name() == name))
597 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
598 })
599 .ok_or_else(|| txt!("Buffer [buffer]{name}[] not found"))
600 }
601
602 pub(crate) fn path_buffer_entry(
604 &self,
605 pa: &Pass,
606 path: &Path,
607 ) -> Result<(usize, Handle), Text> {
608 self.entries(pa)
609 .find_map(|(win, node)| {
610 (node
611 .read_as(pa)
612 .filter(|f: &&Buffer| f.path_kind().as_path().is_some_and(|p| p == path)))
613 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
614 })
615 .ok_or_else(|| txt!("Buffer [buffer]{path}[] not found"))
616 }
617
618 pub(crate) fn node_of<'a, W: Widget>(&'a self, pa: &'a Pass) -> Result<&'a Node, Text> {
623 let handle = context::current_buffer(pa);
624
625 if let Some((handle, _)) = handle.get_related::<W>(pa).next() {
626 self.entries(pa)
627 .find_map(|(.., node)| node.ptr_eq(handle.widget()).then_some(node))
628 } else {
629 let cur_win = self.inner.read(pa).cur_win;
630 let list = &self.inner.read(pa).list;
631 list[cur_win]
632 .nodes(pa)
633 .chain(list[cur_win + 1..].iter().flat_map(|win| win.nodes(pa)))
634 .chain(list[..cur_win].iter().flat_map(|win| win.nodes(pa)))
635 .find(|node| node.data_is::<W>())
636 }
637 .ok_or(txt!(
638 "No widget of type [a]{}[] found",
639 std::any::type_name::<W>()
640 ))
641 }
642
643 pub(crate) fn entries<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = (usize, &'a Node)> {
647 self.inner
648 .read(pa)
649 .list
650 .iter()
651 .enumerate()
652 .flat_map(|(win, window)| {
653 let inner = window.0.read(pa);
654 inner
655 .nodes
656 .iter()
657 .chain(inner.spawned.iter().map(|(_, node)| node))
658 .map(move |node| (win, node))
659 })
660 }
661
662 pub(crate) fn iter_around<'a>(
664 &'a self,
665 pa: &'a Pass,
666 win: usize,
667 wid: usize,
668 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
669 let window_entries =
670 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
671
672 let windows = &self.inner.read(pa).list;
673
674 let prev_len: usize = windows
675 .iter()
676 .take(win)
677 .map(|win| win.len_widgets(pa))
678 .sum();
679
680 windows
681 .iter()
682 .enumerate()
683 .skip(win)
684 .flat_map(window_entries)
685 .skip(wid + 1)
686 .chain(
687 windows
688 .iter()
689 .enumerate()
690 .take(win + 1)
691 .flat_map(window_entries)
692 .take(prev_len + wid),
693 )
694 }
695
696 pub(crate) fn iter_around_rev<'a>(
698 &'a self,
699 pa: &'a Pass,
700 win: usize,
701 wid: usize,
702 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
703 let entries =
704 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
705
706 let windows = &self.inner.read(pa).list;
707
708 let next_len: usize = windows
709 .iter()
710 .skip(win)
711 .map(|win| win.len_widgets(pa))
712 .sum();
713
714 windows
715 .iter()
716 .enumerate()
717 .rev()
718 .skip(windows.len() - (win + 1))
719 .flat_map(move |(w, win)| entries((w, win)).rev().skip(win.len_widgets(pa) - wid))
720 .chain(
721 windows
722 .iter()
723 .enumerate()
724 .rev()
725 .take(windows.len() - win)
726 .flat_map(move |(i, win)| entries((i, win)).rev())
727 .take(next_len - (wid + 1)),
728 )
729 }
730
731 pub fn jump_buffers_by(&self, pa: &mut Pass, jumps: i32) {
738 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
739 if let Some(handle) = self.inner.write(pa).buffer_history.jump_by(current, jumps) {
740 mode::reset_to(pa, &handle);
741 } else {
742 context::warn!("No buffer [a]{jumps}[] jumps away from the current one");
743 }
744 }
745
746 pub fn last_switched_buffer(&self, pa: &mut Pass) -> Result<Handle, Text> {
750 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
751 if let Some(handle) = self.inner.write(pa).buffer_history.last(current) {
752 mode::reset_to(pa, &handle);
753 Ok(handle)
754 } else {
755 Err(txt!("No last buffer"))
756 }
757 }
758
759 pub fn size(&self) -> Coord {
766 self.ui.size()
767 }
768
769 pub fn len(&self, pa: &Pass) -> usize {
773 self.inner.read(pa).list.len()
774 }
775
776 pub fn get<'a>(&'a self, pa: &'a Pass, win: usize) -> Option<&'a Window> {
778 self.inner.read(pa).list.get(win)
779 }
780
781 pub fn iter<'a>(&'a self, pa: &'a Pass) -> std::slice::Iter<'a, Window> {
783 self.inner.read(pa).list.iter()
784 }
785
786 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = Handle<dyn Widget>> + 'a {
788 self.inner
789 .read(pa)
790 .list
791 .iter()
792 .flat_map(|w| w.nodes(pa).map(|n| n.handle().clone()))
793 }
794
795 pub fn handles_of<W: Widget>(&self, pa: &Pass) -> Vec<Handle<W>> {
797 self.inner
798 .read(pa)
799 .list
800 .iter()
801 .flat_map(|w| w.nodes(pa).filter_map(|n| n.handle().try_downcast()))
802 .collect()
803 }
804
805 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
807 self.inner
808 .read(pa)
809 .list
810 .iter()
811 .flat_map(|w| w.buffers(pa))
812 .collect()
813 }
814
815 pub fn current_window(&self, pa: &Pass) -> usize {
817 self.inner.read(pa).cur_win
818 }
819
820 pub(crate) fn current_buffer<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Handle> {
822 &self.inner.read(pa).cur_buffer
823 }
824
825 pub(crate) fn current_widget<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Node> {
827 &self.inner.read(pa).cur_widget
828 }
829
830 pub(crate) fn get_additions(&self, pa: &mut Pass) -> Option<Vec<(usize, Node)>> {
832 self.inner.write(pa).new_additions.lock().unwrap().take()
833 }
834}
835
836#[derive(Clone)]
841pub struct Window(RwData<InnerWindow>);
842
843struct InnerWindow {
844 index: usize,
845 nodes: Vec<Node>,
846 spawned: Vec<(SpawnId, Node)>,
847 buffers_area: RwArea,
848 master_area: RwArea,
849 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
850}
851
852impl Window {
853 fn new<W: Widget>(
855 index: usize,
856 pa: &mut Pass,
857 ui: Ui,
858 widget: W,
859 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
860 ) -> (Self, Node) {
861 let widget = RwData::new(widget);
862 let path = if let Some(buffer) = widget.write_as::<Buffer>(pa) {
863 buffer.layout_order = get_layout_order();
864 buffer.path_set()
865 } else {
866 None
867 };
868
869 let area = ui.new_root(path.as_ref().map(|p| p.as_ref()));
870 let node = Node::new::<W>(widget, area.clone(), None);
871
872 new_additions
873 .lock()
874 .unwrap()
875 .get_or_insert_default()
876 .push((index, node.clone()));
877
878 let window = Self(RwData::new(InnerWindow {
879 index,
880 nodes: vec![node.clone()],
881 spawned: Vec::new(),
882 buffers_area: area.clone(),
883 master_area: area.clone(),
884 new_additions,
885 }));
886
887 (window, node)
888 }
889
890 pub(crate) fn new_from_raw(
892 pa: &mut Pass,
893 index: usize,
894 master_area: RwArea,
895 nodes: Vec<Node>,
896 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
897 ) -> Self {
898 let master_area = master_area
899 .get_cluster_master(pa)
900 .unwrap_or(master_area.clone());
901
902 Self(RwData::new(InnerWindow {
903 index,
904 nodes,
905 spawned: Vec::new(),
906 buffers_area: master_area.clone(),
907 master_area,
908 new_additions,
909 }))
910 }
911
912 pub fn push_inner<W: Widget>(
950 &self,
951 pa: &mut Pass,
952 widget: W,
953 mut specs: PushSpecs,
954 ) -> Handle<W> {
955 let target = self.0.read(pa).buffers_area.clone();
956
957 specs.cluster = false;
958
959 context::windows()
960 .push_widget(pa, (&target, Some(false), specs), widget, None)
961 .unwrap()
962 }
963
964 pub fn push_outer<W: Widget>(
1000 &self,
1001 pa: &mut Pass,
1002 widget: W,
1003 mut specs: PushSpecs,
1004 ) -> Handle<W> {
1005 let target = self.0.read(pa).master_area.clone();
1006
1007 specs.cluster = false;
1008
1009 context::windows()
1010 .push_widget(pa, (&target, Some(false), specs), widget, None)
1011 .unwrap()
1012 }
1013
1014 pub fn spawn<W: Widget>(&self, pa: &mut Pass, widget: W, specs: StaticSpawnSpecs) -> Handle<W> {
1029 context::windows()
1030 .spawn_static(pa, (specs, self.0.read(pa).index), widget)
1031 .unwrap()
1032 }
1033
1034 fn add(&self, pa: &mut Pass, node: Node, parent: Option<RwArea>, location: Location) {
1036 match location {
1037 Location::OnBuffers => {
1038 self.0.write(pa).nodes.push(node.clone());
1039 if let Some(parent) = &parent
1040 && parent.is_master_of(pa, &self.0.read(pa).buffers_area)
1041 {
1042 self.0.write(pa).buffers_area = parent.clone()
1043 }
1044 }
1045 Location::Regular => self.0.write(pa).nodes.push(node.clone()),
1046 Location::Spawned(id) => self.0.write(pa).spawned.push((id, node.clone())),
1047 }
1048
1049 if let Some(parent) = &parent
1050 && parent.is_master_of(pa, &self.0.read(pa).master_area)
1051 {
1052 self.0.write(pa).master_area = parent.clone()
1053 }
1054
1055 let inner = self.0.write(pa);
1056 inner
1057 .new_additions
1058 .lock()
1059 .unwrap()
1060 .get_or_insert_default()
1061 .push((inner.index, node.clone()));
1062 }
1063
1064 fn close<W: Widget + ?Sized>(&self, pa: &mut Pass, handle: &Handle<W>) -> bool {
1068 let handle_eq = |node: &mut Node| node.handle() == handle;
1069
1070 let inner = self.0.write(pa);
1071
1072 let node = if let Some(node) = inner.nodes.extract_if(.., handle_eq).next() {
1073 node
1074 } else if let Some((_, node)) = inner.spawned.extract_if(.., |(_, n)| handle_eq(n)).next() {
1075 node
1076 } else {
1077 unreachable!("This isn't supposed to fail");
1078 };
1079
1080 node.handle().declare_closed(pa);
1081
1082 let (do_rm_window, rm_areas) = node.area().delete(pa);
1083 if do_rm_window {
1084 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1085 handle.declare_closed(pa);
1086 }
1087 return true;
1088 }
1089
1090 let (mut nodes, mut spawned) = {
1091 let inner = self.0.write(pa);
1092 let nodes = std::mem::take(&mut inner.nodes);
1093 let spawned = std::mem::take(&mut inner.spawned);
1094 (nodes, spawned)
1095 };
1096
1097 nodes.retain(|node| {
1098 if rm_areas
1099 .iter()
1100 .any(|a| a.area_is_eq(pa, node.handle().area()))
1101 {
1102 node.handle().declare_closed(pa);
1103 false
1104 } else {
1105 true
1106 }
1107 });
1108 spawned.retain(|(_, node)| {
1109 if rm_areas
1110 .iter()
1111 .any(|a| a.area_is_eq(pa, node.handle().area()))
1112 {
1113 node.handle().declare_closed(pa);
1114 false
1115 } else {
1116 true
1117 }
1118 });
1119
1120 let inner = self.0.write(pa);
1121 inner.nodes = nodes;
1122 inner.spawned = spawned;
1123
1124 let buffers = self.buffers(pa);
1125 if buffers.len() == 1 {
1126 let handle = buffers.first().unwrap();
1127
1128 let master_area = handle
1129 .area()
1130 .get_cluster_master(pa)
1131 .unwrap_or(handle.area.clone());
1132
1133 self.0.write(pa).buffers_area = master_area;
1134 }
1135
1136 if self.buffers(pa).is_empty() {
1137 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1138 handle.declare_closed(pa);
1139 }
1140 true
1141 } else {
1142 false
1143 }
1144 }
1145
1146 fn take_with_related_nodes<W: Widget + ?Sized>(
1148 &self,
1149 pa: &mut Pass,
1150 handle: &Handle<W>,
1151 ) -> Vec<Node> {
1152 let related = handle.related();
1153
1154 let (related, inner) = pa.write_many((related, &self.0));
1155
1156 inner
1157 .nodes
1158 .extract_if(.., |node| {
1159 related.iter().any(|(handle, _)| handle == node.handle()) || node.handle() == handle
1160 })
1161 .collect()
1162 }
1163
1164 fn insert_nodes(&self, pa: &mut Pass, nodes: Vec<Node>) {
1166 self.0.write(pa).nodes.extend(nodes);
1167 }
1168
1169 pub(crate) fn nodes<'a>(&'a self, pa: &'a Pass) -> Nodes<'a> {
1173 let inner = self.0.read(pa);
1174
1175 let spawned = SpawnedNodes { iter: inner.spawned.iter() };
1176
1177 Nodes {
1178 iter: inner.nodes.iter().chain(spawned),
1179 len: inner.nodes.len() + inner.spawned.len(),
1180 taken: 0,
1181 }
1182 }
1183
1184 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = &'a Handle<dyn Widget>> {
1193 self.nodes(pa).map(|node| node.handle())
1194 }
1195
1196 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
1208 let inner = self.0.read(pa);
1209 let mut buffers: Vec<Handle> = inner
1210 .nodes
1211 .iter()
1212 .filter_map(|node| node.try_downcast())
1213 .collect();
1214
1215 buffers.sort_unstable_by_key(|buffer| buffer.read(pa).layout_order);
1216
1217 buffers.extend(
1218 inner
1219 .spawned
1220 .iter()
1221 .filter_map(|(_, node)| node.try_downcast()),
1222 );
1223
1224 buffers
1225 }
1226
1227 pub(crate) fn send_mouse_event(&self, pa: &mut Pass, mouse_event: UiMouseEvent) {
1228 let inner = self.0.read(pa);
1229 let node = inner
1230 .spawned
1231 .iter()
1232 .rev()
1233 .map(|(_, node)| node)
1234 .chain(&inner.nodes)
1235 .find(|node| {
1236 let tl = node.handle().area().top_left(pa);
1237 let br = node.handle().area().bottom_right(pa);
1238 (tl.x <= mouse_event.coord.x && tl.y <= mouse_event.coord.y)
1239 && (mouse_event.coord.x < br.x && mouse_event.coord.y < br.y)
1240 })
1241 .cloned();
1242
1243 if let Some(node) = node {
1244 node.on_mouse_event(pa, mouse_event);
1245 }
1246 }
1247
1248 pub(crate) fn len_widgets(&self, pa: &Pass) -> usize {
1250 let inner = self.0.read(pa);
1251 inner.nodes.len() + inner.spawned.len()
1252 }
1253}
1254
1255#[derive(Default)]
1256struct BufferHistory {
1257 current_i: usize,
1258 list: Vec<Handle>,
1259 last: Option<Handle>,
1260}
1261
1262impl BufferHistory {
1263 fn jump_by(&mut self, current: Handle, by: i32) -> Option<Handle> {
1265 let new_i = self
1266 .current_i
1267 .saturating_add_signed(by as isize)
1268 .min(self.list.len());
1269 let new_handle = self.list.get(new_i)?.clone();
1270
1271 self.last = Some(current);
1272 self.current_i = new_i;
1273 Some(new_handle)
1274 }
1275
1276 fn last(&mut self, current: Handle) -> Option<Handle> {
1281 if let Some(last) = self.last.as_mut() {
1282 Some(std::mem::replace(last, current))
1283 } else if let Some(last) = self.list.get(self.current_i.checked_sub(1)?) {
1284 self.last = Some(current);
1285 Some(last.clone())
1286 } else {
1287 None
1288 }
1289 }
1290
1291 fn insert(&mut self, current: Handle, handle: Handle) {
1294 if self
1295 .current_i
1296 .checked_sub(1)
1297 .is_none_or(|prev_i| self.list[prev_i] != handle)
1298 && self
1299 .list
1300 .get(self.current_i)
1301 .is_none_or(|other| *other != handle)
1302 {
1303 self.list.insert(self.current_i, handle);
1304 self.last = Some(current);
1305 self.current_i += 1;
1306 }
1307 }
1308
1309 fn remove(&mut self, handle: &Handle) {
1312 let mut i = 0;
1313 self.list.retain(|other| {
1314 if other == handle {
1315 if i < self.current_i {
1316 self.current_i -= 1;
1317 }
1318 false
1319 } else {
1320 i += 1;
1321 true
1322 }
1323 });
1324 }
1325}
1326
1327fn get_layout_order() -> usize {
1330 use std::sync::atomic::{AtomicUsize, Ordering};
1331
1332 static LAYOUT_ORDER: AtomicUsize = AtomicUsize::new(0);
1333 LAYOUT_ORDER.fetch_add(1, Ordering::Relaxed)
1334}
1335
1336enum Location {
1337 OnBuffers,
1338 Regular,
1339 Spawned(SpawnId),
1340}
1341
1342#[derive(Debug, Clone)]
1343pub(crate) struct Nodes<'a> {
1344 iter: Chain<std::slice::Iter<'a, Node>, SpawnedNodes<'a>>,
1345 len: usize,
1346 taken: usize,
1347}
1348
1349impl<'a> Iterator for Nodes<'a> {
1350 type Item = &'a Node;
1351
1352 fn next(&mut self) -> Option<Self::Item> {
1353 let next = self.iter.next();
1354 self.taken += next.is_some() as usize;
1355 next
1356 }
1357
1358 fn size_hint(&self) -> (usize, Option<usize>) {
1359 (self.len - self.taken, Some(self.len - self.taken))
1360 }
1361}
1362
1363impl<'a> DoubleEndedIterator for Nodes<'a> {
1364 fn next_back(&mut self) -> Option<Self::Item> {
1365 let next = self.iter.next_back();
1366 self.taken += next.is_some() as usize;
1367 next
1368 }
1369}
1370
1371impl ExactSizeIterator for Nodes<'_> {}
1372
1373#[derive(Debug, Clone)]
1374struct SpawnedNodes<'a> {
1375 iter: std::slice::Iter<'a, (SpawnId, Node)>,
1376}
1377
1378impl<'a> Iterator for SpawnedNodes<'a> {
1379 type Item = &'a Node;
1380
1381 fn next(&mut self) -> Option<Self::Item> {
1382 self.iter.next().map(|(_, node)| node)
1383 }
1384}
1385
1386impl DoubleEndedIterator for SpawnedNodes<'_> {
1387 fn next_back(&mut self) -> Option<Self::Item> {
1388 self.iter.next_back().map(|(_, node)| node)
1389 }
1390}