1use std::{
13 iter::Chain,
14 path::Path,
15 sync::{Arc, Mutex, atomic::AtomicBool},
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, 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(pa, WindowOpened(window));
75 hook::trigger(
76 pa,
77 WidgetOpened(node.handle().try_downcast::<Buffer>().unwrap()),
78 );
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 callback: impl FnOnce(&mut Pass, Handle<dyn Widget>),
124 ) -> Option<Handle<W>> {
125 let (win, cluster_master, master) =
126 self.inner
127 .read(pa)
128 .list
129 .iter()
130 .enumerate()
131 .find_map(|(win, window)| {
132 let inner = window.0.read(pa);
133 let master = window.nodes(pa).find_map(|node| {
134 node.area().is_eq(pa, target).then(|| node.handle().clone())
135 });
136
137 if inner.master_area.is_master_of(pa, target) {
138 Some((win, None, master))
139 } else if let Some((_, node)) = inner
140 .spawned
141 .iter()
142 .find(|(_, node)| node.area().is_master_of(pa, target))
143 {
144 Some((win, node.area().get_cluster_master(pa), master))
145 } else {
146 None
147 }
148 })?;
149
150 let widget = RwData::new(widget);
151 let id = SpawnId::new();
152
153 let path = widget
154 .read_as::<Buffer>(pa)
155 .and_then(|buffer| buffer.path_set());
156 let spawned = cluster_master.as_ref().unwrap_or(target).spawn(
157 pa,
158 path.as_ref().map(|p| p.as_ref()),
159 id,
160 specs,
161 )?;
162
163 let node = Node::new(widget, spawned, master, Arc::new(AtomicBool::new(false)));
164
165 let window = self.inner.write(pa).list.remove(win);
166 window.add(pa, node.clone(), None, Location::Spawned(id));
167 self.inner.write(pa).list.insert(win, window);
168
169 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
170
171 callback(pa, node.handle().clone());
172
173 node.handle().try_downcast()
174 }
175
176 pub(crate) fn spawn_on_text<W: Widget>(
178 &self,
179 pa: &mut Pass,
180 (id, specs): (SpawnId, DynSpawnSpecs),
181 widget: W,
182 win: usize,
183 master: Handle<dyn Widget>,
184 is_closed: Arc<AtomicBool>,
185 ) -> Handle<W> {
186 let widget = RwData::new(widget);
187 let path = widget
188 .read_as::<Buffer>(pa)
189 .and_then(|buffer| buffer.path_set());
190 let spawned = self
191 .ui
192 .new_dyn_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
193
194 let node = Node::new(widget, spawned, Some(master), is_closed);
195
196 let window = self.inner.write(pa).list.remove(win);
197 window.add(pa, node.clone(), None, Location::Spawned(id));
198 self.inner.write(pa).list.insert(win, window);
199
200 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
201
202 node.handle().try_downcast().unwrap()
203 }
204
205 fn spawn_static<W: Widget>(
207 &self,
208 pa: &mut Pass,
209 (specs, win): (StaticSpawnSpecs, usize),
210 widget: W,
211 ) -> Option<Handle<W>> {
212 let id = SpawnId::new();
213 let widget = RwData::new(widget);
214 let path = widget
215 .read_as::<Buffer>(pa)
216 .and_then(|buffer| buffer.path_set());
217 let spawned = self
218 .ui
219 .new_static_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
220
221 let node = Node::new(widget, spawned, None, Arc::new(AtomicBool::new(false)));
222
223 let window = self.inner.write(pa).list.remove(win);
224 window.add(pa, node.clone(), None, Location::Spawned(id));
225 self.inner.write(pa).list.insert(win, window);
226
227 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
228
229 node.handle().try_downcast()
230 }
231
232 pub(crate) fn new_buffer(&self, pa: &mut Pass, buffer: Buffer) -> Node {
239 let inner = self.inner.read(pa);
240 let (handle, specs) = inner.layout.lock().unwrap().new_buffer(pa, &inner.list);
241
242 let specs = PushSpecs { cluster: false, ..specs };
243
244 if let Some(master) = handle.area().get_cluster_master(pa) {
245 self.push(pa, (&master, Some(true), specs), buffer, None)
246 .unwrap()
247 } else {
248 self.push(pa, (&handle.area, Some(true), specs), buffer, None)
249 .unwrap()
250 }
251 }
252
253 fn push<W: Widget>(
259 &self,
260 pa: &mut Pass,
261 (target, on_buffers, mut specs): (&RwArea, Option<bool>, PushSpecs),
262 widget: W,
263 master: Option<&RwArea>,
264 ) -> Option<Node> {
265 let inner = self.inner.read(pa);
266 let win = inner
267 .list
268 .iter()
269 .position(|window| {
270 window.0.read(pa).master_area.is_master_of(pa, target)
271 || window
272 .nodes(pa)
273 .any(|node| node.area().is_master_of(pa, target))
274 })
275 .unwrap();
276
277 let inner_window = inner.list[win].0.read(pa);
278 let target_is_on_buffers = inner_window.buffers_area.is_master_of(pa, target);
279
280 let on_buffers = on_buffers.unwrap_or(target_is_on_buffers) && target_is_on_buffers;
281
282 if target_is_on_buffers && !on_buffers {
283 specs.cluster = false;
284 }
285
286 let location = if on_buffers {
287 Location::OnBuffers
288 } else if let Some((id, _)) = inner_window
289 .spawned
290 .iter()
291 .find(|(_, node)| node.area().is_eq(pa, target))
292 {
293 Location::Spawned(*id)
294 } else {
295 Location::Regular
296 };
297
298 let widget = RwData::new(widget);
299 let path = widget
300 .read_as::<Buffer>(pa)
301 .and_then(|buffer| buffer.path_set());
302 let (pushed, parent) =
303 target.push(pa, path.as_ref().map(|p| p.as_ref()), specs, on_buffers)?;
304
305 let master = master.and_then(|area| {
306 self.entries(pa)
307 .find_map(|(.., node)| node.area().is_eq(pa, area).then(|| node.handle().clone()))
308 });
309
310 let node = Node::new(widget, pushed, master, Arc::new(AtomicBool::new(false)));
311
312 let window = self.inner.write(pa).list.remove(win);
313 window.add(pa, node.clone(), parent, location);
314 self.inner.write(pa).list.insert(win, window);
315
316 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
317
318 Some(node)
319 }
320
321 pub(crate) fn close<W: Widget + ?Sized>(
325 &self,
326 pa: &mut Pass,
327 handle: &Handle<W>,
328 ) -> Result<(), Text> {
329 let win = self.handle_window(pa, handle)?;
330
331 if let Some(buf_handle) = handle.try_downcast::<Buffer>() {
334 hook::trigger(pa, BufferClosed(buf_handle.clone()));
335
336 let buffers_ahead: Vec<Node> = self.inner.read(pa).list[win]
337 .nodes(pa)
338 .filter(|node| {
339 node.handle().read_as::<Buffer>(pa).is_some_and(|buffer| {
340 buffer.layout_order > buf_handle.read(pa).layout_order
341 })
342 })
343 .cloned()
344 .collect();
345
346 for buffer_ahead in buffers_ahead {
347 self.swap(pa, handle, buffer_ahead.handle())?;
348 }
349 }
350
351 let mut list = std::mem::take(&mut self.inner.write(pa).list);
353
354 if list[win].close(pa, handle) {
355 list.remove(win);
356 self.ui.remove_window(win);
357 let cur_win = context::current_win_index(pa);
358 if cur_win > win {
359 self.inner.write(pa).cur_win -= 1;
360 }
361 }
362
363 let inner = self.inner.write(pa);
364 inner.list = list;
365 inner.new_additions.lock().unwrap().get_or_insert_default();
366
367 let inner = self.inner.read(pa);
369 if handle == inner.cur_widget.read(pa).handle() || handle == inner.cur_buffer.read(pa) {
370 if let Some(handle) = handle.try_downcast::<Buffer>() {
371 self.inner.write(pa).buffer_history.remove(&handle);
372
373 let entry = self
374 .inner
375 .write(pa)
376 .buffer_history
377 .jump_by(handle.clone(), -1)
378 .or_else(|| self.buffers(pa).first().cloned())
379 .and_then(|handle| {
380 self.entries(pa).find_map(|(win, node)| {
381 (*node.handle() == handle).then(|| (win, node.clone()))
382 })
383 });
384
385 if let Some((_, node)) = entry {
386 crate::mode::reset_to(pa, node.handle());
387 } else {
388 context::sender().send(crate::session::DuatEvent::Quit);
390 return Ok(());
391 }
392 } else {
393 crate::mode::reset_to(pa, &inner.cur_buffer.read(pa).clone());
394 }
395 }
396
397 Ok(())
398 }
399
400 pub(crate) fn swap<W1: Widget + ?Sized, W2: Widget + ?Sized>(
402 &self,
403 pa: &mut Pass,
404 lhs: &Handle<W1>,
405 rhs: &Handle<W2>,
406 ) -> Result<(), Text> {
407 let lhs_win = self.handle_window(pa, lhs)?;
408 let rhs_win = self.handle_window(pa, rhs)?;
409
410 let [lhs_buffer, rhs_buffer] = [lhs.try_downcast::<Buffer>(), rhs.try_downcast()];
411
412 if let [Some(lhs), Some(rhs)] = [lhs_buffer, rhs_buffer] {
413 let lhs_lo = lhs.read(pa).layout_order;
414 let rhs_lo = std::mem::replace(&mut rhs.write(pa).layout_order, lhs_lo);
415 lhs.write(pa).layout_order = rhs_lo
416 }
417
418 let windows = std::mem::take(&mut self.inner.write(pa).list);
419
420 let lhs_nodes = windows[lhs_win].take_with_related_nodes(pa, lhs);
421 windows[rhs_win].insert_nodes(pa, lhs_nodes);
422
423 let rhs_nodes = windows[rhs_win].take_with_related_nodes(pa, rhs);
424 windows[lhs_win].insert_nodes(pa, rhs_nodes);
425
426 let wins = self.inner.write(pa);
427 wins.list = windows;
428 wins.new_additions.lock().unwrap().get_or_insert_default();
429
430 lhs.area().swap(pa, rhs.area());
431
432 let cur_buffer = context::current_buffer(pa);
433 if lhs_win != rhs_win {
434 if *lhs == cur_buffer {
435 self.inner.write(pa).cur_win = lhs_win;
436 self.ui.switch_window(lhs_win);
437 } else if *rhs == cur_buffer {
438 self.inner.write(pa).cur_win = rhs_win;
439 self.ui.switch_window(rhs_win);
440 }
441 }
442
443 Ok(())
444 }
445
446 pub(crate) fn open_or_move_to_new_window(
449 &self,
450 pa: &mut Pass,
451 pk: PathKind,
452 default_buffer_opts: BufferOpts,
453 ) -> Node {
454 let node = match self.buffer_entry(pa, pk.clone()) {
455 Ok((win, handle)) if self.get(pa, win).unwrap().buffers(pa).len() > 1 => {
456 handle.write(pa).layout_order = 0;
458
459 let nodes = {
460 let old_window = self.inner.write(pa).list.remove(win);
461 let nodes = old_window.take_with_related_nodes(pa, &handle.to_dyn());
462 self.inner.write(pa).list.insert(win, old_window);
463
464 nodes
465 };
466
467 let path = handle.read(pa).path_set();
469 let new_root = self.ui.new_root(path.as_ref().map(|p| p.as_ref()));
470 handle.area().swap(pa, &new_root);
471 let window = Window::new_from_raw(
472 pa,
473 win,
474 handle.area.clone(),
475 nodes,
476 self.inner.read(pa).new_additions.clone(),
477 );
478
479 self.inner.write(pa).list.push(window.clone());
480
481 hook::trigger(pa, WindowOpened(window));
482
483 let lo = handle.read(pa).layout_order;
485
486 for handle in &self.inner.read(pa).list[win].buffers(pa)[lo..] {
487 new_root.swap(pa, handle.area());
488 }
489
490 new_root.delete(pa);
493
494 self.inner
495 .write(pa)
496 .new_additions
497 .lock()
498 .unwrap()
499 .get_or_insert_default();
500
501 Node::from_handle(handle)
502 }
503 Ok((.., handle)) => Node::from_handle(handle),
506 Err(_) => self.new_window(pa, Buffer::new(pk.as_path(), default_buffer_opts)),
507 };
508
509 if context::current_buffer(pa).read(pa).path_kind() != pk {
510 mode::reset_to(pa, node.handle());
511 }
512
513 node
514 }
515
516 #[track_caller]
518 pub(crate) fn set_current_node(&self, pa: &mut Pass, node: Node) -> Result<(), Text> {
519 let internal_pass = &mut unsafe { Pass::new() };
522
523 let win = self.handle_window(pa, node.handle())?;
524 let inner = self.inner.write(pa);
525
526 if let Some(current) = node.try_downcast::<Buffer>() {
527 let former = std::mem::replace(inner.cur_buffer.write(internal_pass), current.clone());
528 inner.buffer_history.insert(former.clone(), current.clone());
529
530 hook::trigger(pa, BufferSwitched((former, current)));
531 }
532
533 let inner = self.inner.write(pa);
534 *inner.cur_widget.write(internal_pass) = node.clone();
535 inner.cur_win = win;
536 self.ui.switch_window(win);
537
538 Ok(())
539 }
540
541 pub(crate) fn queue_close_spawned(&self, id: SpawnId) {
545 let mut spawns_to_remove = self.spawns_to_remove.lock().unwrap();
546 if !spawns_to_remove.contains(&id) {
547 spawns_to_remove.push(id)
548 }
549 }
550
551 pub(crate) fn cleanup_despawned(&self, pa: &mut Pass) {
554 let spawns_to_remove = std::mem::take(&mut *self.spawns_to_remove.lock().unwrap());
555 for id in spawns_to_remove {
556 if let Some((_, node)) = self
557 .iter(pa)
558 .flat_map(|window| &window.0.read(pa).spawned)
559 .find(|(other, _)| *other == id)
560 {
561 self.close(pa, &node.handle().clone()).unwrap();
562 }
563 }
564 }
565
566 pub(crate) fn handle_window<W: Widget + ?Sized>(
570 &self,
571 pa: &Pass,
572 handle: &Handle<W>,
573 ) -> Result<usize, Text> {
574 self.entries(pa)
575 .find_map(|(win, node)| (node.handle() == handle).then_some(win))
576 .ok_or_else(|| txt!("The Handle was already closed"))
577 }
578
579 pub(crate) fn buffer_entry(&self, pa: &Pass, pk: PathKind) -> Result<(usize, Handle), Text> {
581 self.entries(pa)
582 .find_map(|(win, node)| {
583 (node.read_as(pa).filter(|f: &&Buffer| f.path_kind() == pk))
584 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
585 })
586 .ok_or_else(|| txt!("Buffer {pk} not found"))
587 }
588
589 pub(crate) fn named_buffer_entry(&self, pa: &Pass, name: &str) -> Option<(usize, Handle)> {
591 self.entries(pa).find_map(|(win, node)| {
592 (node.read_as(pa).filter(|f: &&Buffer| f.name() == name))
593 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
594 })
595 }
596
597 pub(crate) fn path_buffer_entry(&self, pa: &Pass, path: &Path) -> Option<(usize, Handle)> {
599 self.entries(pa).find_map(|(win, node)| {
600 (node
601 .read_as(pa)
602 .filter(|f: &&Buffer| f.path_kind().as_path().is_some_and(|p| p == path)))
603 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
604 })
605 }
606
607 pub(crate) fn node_of<'a, W: Widget>(&'a self, pa: &'a Pass) -> Result<&'a Node, Text> {
612 let buffer = context::current_buffer(pa);
613
614 if let Some((handle, _)) = buffer.get_related::<W>(pa).first() {
615 self.entries(pa)
616 .find_map(|(.., node)| node.ptr_eq(handle.widget()).then_some(node))
617 } else {
618 let cur_win = self.inner.read(pa).cur_win;
619 let list = &self.inner.read(pa).list;
620 list[cur_win]
621 .nodes(pa)
622 .chain(list[cur_win + 1..].iter().flat_map(|win| win.nodes(pa)))
623 .chain(list[..cur_win].iter().flat_map(|win| win.nodes(pa)))
624 .find(|node| node.data_is::<W>())
625 }
626 .ok_or(txt!(
627 "No widget of type [a]{}[] found",
628 std::any::type_name::<W>()
629 ))
630 }
631
632 pub(crate) fn entries<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = (usize, &'a Node)> {
636 self.inner
637 .read(pa)
638 .list
639 .iter()
640 .enumerate()
641 .flat_map(|(win, window)| {
642 let inner = window.0.read(pa);
643 inner
644 .nodes
645 .iter()
646 .chain(inner.spawned.iter().map(|(_, node)| node))
647 .map(move |node| (win, node))
648 })
649 }
650
651 pub(crate) fn iter_around<'a>(
653 &'a self,
654 pa: &'a Pass,
655 win: usize,
656 wid: usize,
657 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
658 let window_entries =
659 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
660
661 let windows = &self.inner.read(pa).list;
662
663 let prev_len: usize = windows
664 .iter()
665 .take(win)
666 .map(|win| win.len_widgets(pa))
667 .sum();
668
669 windows
670 .iter()
671 .enumerate()
672 .skip(win)
673 .flat_map(window_entries)
674 .skip(wid + 1)
675 .chain(
676 windows
677 .iter()
678 .enumerate()
679 .take(win + 1)
680 .flat_map(window_entries)
681 .take(prev_len + wid),
682 )
683 }
684
685 pub(crate) fn iter_around_rev<'a>(
687 &'a self,
688 pa: &'a Pass,
689 win: usize,
690 wid: usize,
691 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
692 let entries =
693 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
694
695 let windows = &self.inner.read(pa).list;
696
697 let next_len: usize = windows
698 .iter()
699 .skip(win)
700 .map(|win| win.len_widgets(pa))
701 .sum();
702
703 windows
704 .iter()
705 .enumerate()
706 .rev()
707 .skip(windows.len() - (win + 1))
708 .flat_map(move |(w, win)| entries((w, win)).rev().skip(win.len_widgets(pa) - wid))
709 .chain(
710 windows
711 .iter()
712 .enumerate()
713 .rev()
714 .take(windows.len() - win)
715 .flat_map(move |(i, win)| entries((i, win)).rev())
716 .take(next_len - (wid + 1)),
717 )
718 }
719
720 pub fn jump_buffers_by(&self, pa: &mut Pass, jumps: i32) {
727 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
728 if let Some(handle) = self.inner.write(pa).buffer_history.jump_by(current, jumps) {
729 mode::reset_to(pa, &handle);
730 } else {
731 context::warn!("No buffer [a]{jumps}[] jumps away from the current one");
732 }
733 }
734
735 pub fn last_switched_buffer(&self, pa: &mut Pass) -> Result<Handle, Text> {
740 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
741 if let Some(handle) = self.inner.write(pa).buffer_history.last(current) {
742 mode::reset_to(pa, &handle);
743 Ok(handle)
744 } else {
745 Err(txt!("No last buffer"))
746 }
747 }
748
749 pub fn size(&self) -> Coord {
756 self.ui.size()
757 }
758
759 pub fn len(&self, pa: &Pass) -> usize {
763 self.inner.read(pa).list.len()
764 }
765
766 pub fn get<'a>(&'a self, pa: &'a Pass, win: usize) -> Option<&'a Window> {
768 self.inner.read(pa).list.get(win)
769 }
770
771 pub fn iter<'a>(&'a self, pa: &'a Pass) -> std::slice::Iter<'a, Window> {
773 self.inner.read(pa).list.iter()
774 }
775
776 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = Handle<dyn Widget>> + 'a {
778 self.inner
779 .read(pa)
780 .list
781 .iter()
782 .flat_map(|w| w.nodes(pa).map(|n| n.handle().clone()))
783 }
784
785 pub fn handles_of<W: Widget>(&self, pa: &Pass) -> Vec<Handle<W>> {
787 self.inner
788 .read(pa)
789 .list
790 .iter()
791 .flat_map(|w| w.nodes(pa).filter_map(|n| n.handle().try_downcast()))
792 .collect()
793 }
794
795 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
797 self.inner
798 .read(pa)
799 .list
800 .iter()
801 .flat_map(|w| w.buffers(pa))
802 .collect()
803 }
804
805 pub fn current_window(&self, pa: &Pass) -> usize {
807 self.inner.read(pa).cur_win
808 }
809
810 pub(crate) fn current_buffer<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Handle> {
812 &self.inner.read(pa).cur_buffer
813 }
814
815 pub(crate) fn current_widget<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Node> {
817 &self.inner.read(pa).cur_widget
818 }
819
820 pub(crate) fn get_additions(&self, pa: &mut Pass) -> Option<Vec<(usize, Node)>> {
822 self.inner.write(pa).new_additions.lock().unwrap().take()
823 }
824}
825
826#[derive(Clone)]
831pub struct Window(RwData<InnerWindow>);
832
833struct InnerWindow {
834 index: usize,
835 nodes: Vec<Node>,
836 spawned: Vec<(SpawnId, Node)>,
837 buffers_area: RwArea,
838 master_area: RwArea,
839 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
840}
841
842impl Window {
843 fn new<W: Widget>(
845 index: usize,
846 pa: &mut Pass,
847 ui: Ui,
848 widget: W,
849 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
850 ) -> (Self, Node) {
851 let widget = RwData::new(widget);
852 let path = if let Some(buffer) = widget.write_as::<Buffer>(pa) {
853 buffer.layout_order = get_layout_order();
854 buffer.path_set()
855 } else {
856 None
857 };
858
859 let area = ui.new_root(path.as_ref().map(|p| p.as_ref()));
860 let node = Node::new::<W>(widget, area.clone(), None, Arc::new(AtomicBool::new(false)));
861
862 new_additions
863 .lock()
864 .unwrap()
865 .get_or_insert_default()
866 .push((index, node.clone()));
867
868 let window = Self(RwData::new(InnerWindow {
869 index,
870 nodes: vec![node.clone()],
871 spawned: Vec::new(),
872 buffers_area: area.clone(),
873 master_area: area.clone(),
874 new_additions,
875 }));
876
877 (window, node)
878 }
879
880 pub(crate) fn new_from_raw(
882 pa: &mut Pass,
883 index: usize,
884 master_area: RwArea,
885 nodes: Vec<Node>,
886 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
887 ) -> Self {
888 let master_area = master_area
889 .get_cluster_master(pa)
890 .unwrap_or(master_area.clone());
891
892 Self(RwData::new(InnerWindow {
893 index,
894 nodes,
895 spawned: Vec::new(),
896 buffers_area: master_area.clone(),
897 master_area,
898 new_additions,
899 }))
900 }
901
902 pub fn push_inner<W: Widget>(
940 &self,
941 pa: &mut Pass,
942 widget: W,
943 mut specs: PushSpecs,
944 ) -> Handle<W> {
945 let target = self.0.read(pa).buffers_area.clone();
946
947 specs.cluster = false;
948
949 context::windows()
950 .push_widget(pa, (&target, Some(false), specs), widget, None)
951 .unwrap()
952 }
953
954 pub fn push_outer<W: Widget>(
990 &self,
991 pa: &mut Pass,
992 widget: W,
993 mut specs: PushSpecs,
994 ) -> Handle<W> {
995 let target = self.0.read(pa).master_area.clone();
996
997 specs.cluster = false;
998
999 context::windows()
1000 .push_widget(pa, (&target, Some(false), specs), widget, None)
1001 .unwrap()
1002 }
1003
1004 pub fn spawn<W: Widget>(&self, pa: &mut Pass, widget: W, specs: StaticSpawnSpecs) -> Handle<W> {
1019 context::windows()
1020 .spawn_static(pa, (specs, self.0.read(pa).index), widget)
1021 .unwrap()
1022 }
1023
1024 fn add(&self, pa: &mut Pass, node: Node, parent: Option<RwArea>, location: Location) {
1026 match location {
1027 Location::OnBuffers => {
1028 self.0.write(pa).nodes.push(node.clone());
1029 if let Some(parent) = &parent
1030 && parent.is_master_of(pa, &self.0.read(pa).buffers_area)
1031 {
1032 self.0.write(pa).buffers_area = parent.clone()
1033 }
1034 }
1035 Location::Regular => self.0.write(pa).nodes.push(node.clone()),
1036 Location::Spawned(id) => self.0.write(pa).spawned.push((id, node.clone())),
1037 }
1038
1039 if let Some(parent) = &parent
1040 && parent.is_master_of(pa, &self.0.read(pa).master_area)
1041 {
1042 self.0.write(pa).master_area = parent.clone()
1043 }
1044
1045 let inner = self.0.write(pa);
1046 inner
1047 .new_additions
1048 .lock()
1049 .unwrap()
1050 .get_or_insert_default()
1051 .push((inner.index, node.clone()));
1052 }
1053
1054 fn close<W: Widget + ?Sized>(&self, pa: &mut Pass, handle: &Handle<W>) -> bool {
1058 let handle_eq = |node: &mut Node| node.handle() == handle;
1059
1060 let inner = self.0.write(pa);
1061
1062 let node = if let Some(node) = inner.nodes.extract_if(.., handle_eq).next() {
1063 node
1064 } else if let Some((_, node)) = inner.spawned.extract_if(.., |(_, n)| handle_eq(n)).next() {
1065 node
1066 } else {
1067 unreachable!("This isn't supposed to fail");
1068 };
1069
1070 node.handle().declare_closed();
1071
1072 let (do_rm_window, rm_areas) = node.area().delete(pa);
1073 if do_rm_window {
1074 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1075 handle.declare_closed();
1076 }
1077 return true;
1078 }
1079
1080 let (mut nodes, mut spawned) = {
1081 let inner = self.0.write(pa);
1082 let nodes = std::mem::take(&mut inner.nodes);
1083 let spawned = std::mem::take(&mut inner.spawned);
1084 (nodes, spawned)
1085 };
1086
1087 nodes.retain(|node| {
1088 if rm_areas.iter().any(|a| a.is_eq(pa, node.handle().area())) {
1089 node.handle().declare_closed();
1090 false
1091 } else {
1092 true
1093 }
1094 });
1095 spawned.retain(|(_, node)| {
1096 if rm_areas.iter().any(|a| a.is_eq(pa, node.handle().area())) {
1097 node.handle().declare_closed();
1098 false
1099 } else {
1100 true
1101 }
1102 });
1103
1104 let inner = self.0.write(pa);
1105 inner.nodes = nodes;
1106 inner.spawned = spawned;
1107
1108 let buffers = self.buffers(pa);
1109 if buffers.len() == 1 {
1110 let handle = buffers.first().unwrap();
1111
1112 let master_area = handle
1113 .area()
1114 .get_cluster_master(pa)
1115 .unwrap_or(handle.area.clone());
1116
1117 self.0.write(pa).buffers_area = master_area;
1118 }
1119
1120 if self.buffers(pa).is_empty() {
1121 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1122 handle.declare_closed();
1123 }
1124 true
1125 } else {
1126 false
1127 }
1128 }
1129
1130 fn take_with_related_nodes<W: Widget + ?Sized>(
1132 &self,
1133 pa: &mut Pass,
1134 handle: &Handle<W>,
1135 ) -> Vec<Node> {
1136 let related = handle.related();
1137
1138 let (related, inner) = pa.write_many((related, &self.0));
1139
1140 inner
1141 .nodes
1142 .extract_if(.., |node| {
1143 related.iter().any(|(handle, _)| handle == node.handle()) || node.handle() == handle
1144 })
1145 .collect()
1146 }
1147
1148 fn insert_nodes(&self, pa: &mut Pass, nodes: Vec<Node>) {
1150 self.0.write(pa).nodes.extend(nodes);
1151 }
1152
1153 pub(crate) fn nodes<'a>(&'a self, pa: &'a Pass) -> Nodes<'a> {
1157 let inner = self.0.read(pa);
1158
1159 let spawned = SpawnedNodes { iter: inner.spawned.iter() };
1160
1161 Nodes {
1162 iter: inner.nodes.iter().chain(spawned),
1163 len: inner.nodes.len() + inner.spawned.len(),
1164 taken: 0,
1165 }
1166 }
1167
1168 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = &'a Handle<dyn Widget>> {
1177 self.nodes(pa).map(|node| node.handle())
1178 }
1179
1180 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
1192 let inner = self.0.read(pa);
1193 let mut buffers: Vec<Handle> = inner
1194 .nodes
1195 .iter()
1196 .filter_map(|node| node.try_downcast())
1197 .collect();
1198
1199 buffers.sort_unstable_by_key(|buffer| buffer.read(pa).layout_order);
1200
1201 buffers.extend(
1202 inner
1203 .spawned
1204 .iter()
1205 .filter_map(|(_, node)| node.try_downcast()),
1206 );
1207
1208 buffers
1209 }
1210
1211 pub(crate) fn send_mouse_event(&self, pa: &mut Pass, mouse_event: UiMouseEvent) {
1212 let inner = self.0.read(pa);
1213 let node = inner
1214 .spawned
1215 .iter()
1216 .rev()
1217 .map(|(_, node)| node)
1218 .chain(&inner.nodes)
1219 .find(|node| {
1220 let tl = node.handle().area().top_left(pa);
1221 let br = node.handle().area().bottom_right(pa);
1222 (tl.x <= mouse_event.coord.x && tl.y <= mouse_event.coord.y)
1223 && (mouse_event.coord.x < br.x && mouse_event.coord.y < br.y)
1224 })
1225 .cloned();
1226
1227 if let Some(node) = node {
1228 node.on_mouse_event(pa, mouse_event);
1229 }
1230 }
1231
1232 pub(crate) fn len_widgets(&self, pa: &Pass) -> usize {
1234 let inner = self.0.read(pa);
1235 inner.nodes.len() + inner.spawned.len()
1236 }
1237
1238 pub fn width(&self) -> f32 {
1240 crate::context::windows().ui.size().x
1241 }
1242
1243 pub fn height(&self) -> f32 {
1245 crate::context::windows().ui.size().y
1246 }
1247}
1248
1249#[derive(Default)]
1250struct BufferHistory {
1251 current_i: usize,
1252 list: Vec<Handle>,
1253 last: Option<Handle>,
1254}
1255
1256impl BufferHistory {
1257 fn jump_by(&mut self, current: Handle, by: i32) -> Option<Handle> {
1259 let new_i = self
1260 .current_i
1261 .saturating_add_signed(by as isize)
1262 .min(self.list.len());
1263 let new_handle = self.list.get(new_i)?.clone();
1264
1265 self.last = Some(current);
1266 self.current_i = new_i;
1267 Some(new_handle)
1268 }
1269
1270 fn last(&mut self, current: Handle) -> Option<Handle> {
1275 if let Some(last) = self.last.as_mut() {
1276 Some(std::mem::replace(last, current))
1277 } else if let Some(last) = self.list.get(self.current_i.checked_sub(1)?) {
1278 self.last = Some(current);
1279 Some(last.clone())
1280 } else {
1281 None
1282 }
1283 }
1284
1285 fn insert(&mut self, current: Handle, handle: Handle) {
1288 if self
1289 .current_i
1290 .checked_sub(1)
1291 .is_none_or(|prev_i| self.list[prev_i] != handle)
1292 && self
1293 .list
1294 .get(self.current_i)
1295 .is_none_or(|other| *other != handle)
1296 {
1297 self.list.insert(self.current_i, handle);
1298 self.last = Some(current);
1299 self.current_i += 1;
1300 }
1301 }
1302
1303 fn remove(&mut self, handle: &Handle) {
1306 let mut i = 0;
1307 self.list.retain(|other| {
1308 if other == handle {
1309 if i < self.current_i {
1310 self.current_i -= 1;
1311 }
1312 false
1313 } else {
1314 i += 1;
1315 true
1316 }
1317 });
1318 }
1319}
1320
1321fn get_layout_order() -> usize {
1324 use std::sync::atomic::{AtomicUsize, Ordering};
1325
1326 static LAYOUT_ORDER: AtomicUsize = AtomicUsize::new(0);
1327 LAYOUT_ORDER.fetch_add(1, Ordering::Relaxed)
1328}
1329
1330enum Location {
1331 OnBuffers,
1332 Regular,
1333 Spawned(SpawnId),
1334}
1335
1336#[derive(Debug, Clone)]
1337pub(crate) struct Nodes<'a> {
1338 iter: Chain<std::slice::Iter<'a, Node>, SpawnedNodes<'a>>,
1339 len: usize,
1340 taken: usize,
1341}
1342
1343impl<'a> Iterator for Nodes<'a> {
1344 type Item = &'a Node;
1345
1346 fn next(&mut self) -> Option<Self::Item> {
1347 let next = self.iter.next();
1348 self.taken += next.is_some() as usize;
1349 next
1350 }
1351
1352 fn size_hint(&self) -> (usize, Option<usize>) {
1353 (self.len - self.taken, Some(self.len - self.taken))
1354 }
1355}
1356
1357impl<'a> DoubleEndedIterator for Nodes<'a> {
1358 fn next_back(&mut self) -> Option<Self::Item> {
1359 let next = self.iter.next_back();
1360 self.taken += next.is_some() as usize;
1361 next
1362 }
1363}
1364
1365impl ExactSizeIterator for Nodes<'_> {}
1366
1367#[derive(Debug, Clone)]
1368struct SpawnedNodes<'a> {
1369 iter: std::slice::Iter<'a, (SpawnId, Node)>,
1370}
1371
1372impl<'a> Iterator for SpawnedNodes<'a> {
1373 type Item = &'a Node;
1374
1375 fn next(&mut self) -> Option<Self::Item> {
1376 self.iter.next().map(|(_, node)| node)
1377 }
1378}
1379
1380impl DoubleEndedIterator for SpawnedNodes<'_> {
1381 fn next_back(&mut self) -> Option<Self::Item> {
1382 self.iter.next_back().map(|(_, node)| node)
1383 }
1384}