1use std::{
13 any::type_name,
14 iter::Chain,
15 sync::{Arc, Mutex},
16};
17
18use super::{Node, Widget, layout::Layout};
19use crate::{
20 buffer::{Buffer, PathKind},
21 context::{self, Handle},
22 data::{Pass, RwData},
23 hook::{self, BufferClosed, BufferSwitched, WidgetOpened, WindowOpened},
24 mode,
25 opts::PrintOpts,
26 session::UiMouseEvent,
27 text::{Text, txt},
28 ui::{Coord, DynSpawnSpecs, PushSpecs, RwArea, SpawnId, StaticSpawnSpecs, Ui},
29};
30
31pub struct Windows {
33 inner: RwData<InnerWindows>,
34 spawns_to_remove: Mutex<Vec<SpawnId>>,
35 ui: Ui,
36}
37
38struct InnerWindows {
40 layout: Box<Mutex<dyn Layout>>,
41 list: Vec<Window>,
42 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
43 cur_buffer: RwData<Handle>,
44 cur_widget: RwData<Node>,
45 cur_win: usize,
46 buffer_history: BufferHistory,
47}
48
49impl Windows {
50 pub(crate) fn initialize(
53 pa: &mut Pass,
54 buffer: Buffer,
55 layout: Box<Mutex<dyn Layout>>,
56 ui: Ui,
57 ) {
58 let new_additions = Arc::new(Mutex::default());
59 let (window, node) = Window::new(0, pa, ui, buffer, new_additions.clone());
60
61 context::set_windows(Self {
62 inner: RwData::new(InnerWindows {
63 layout,
64 list: vec![window.clone()],
65 new_additions,
66 cur_buffer: RwData::new(node.try_downcast().unwrap()),
67 cur_widget: RwData::new(node.clone()),
68 cur_win: 0,
69 buffer_history: BufferHistory::default(),
70 }),
71 spawns_to_remove: Mutex::new(Vec::new()),
72 ui,
73 });
74
75 hook::trigger(
76 pa,
77 WidgetOpened(node.handle().try_downcast::<Buffer>().unwrap()),
78 );
79 hook::trigger(pa, WindowOpened(window));
80 }
81
82 pub(crate) fn new_window(&self, pa: &mut Pass, buffer: Buffer) -> Node {
87 let win = self.inner.read(pa).list.len();
88 let new_additions = self.inner.read(pa).new_additions.clone();
89 let (window, node) = Window::new(win, pa, self.ui, buffer, new_additions);
90
91 let inner = self.inner.write(pa);
92 inner.list.push(window);
93
94 hook::trigger(pa, WindowOpened(self.inner.read(pa).list[win].clone()));
95 hook::trigger(
96 pa,
97 WidgetOpened(node.handle().try_downcast::<Buffer>().unwrap()),
98 );
99
100 node
101 }
102
103 pub(crate) fn push_widget<W: Widget>(
105 &self,
106 pa: &mut Pass,
107 (target, on_buffers, specs): (&RwArea, Option<bool>, PushSpecs),
108 widget: W,
109 master: Option<&RwArea>,
110 ) -> Option<Handle<W>> {
111 self.push(pa, (target, on_buffers, specs), widget, master)?
112 .handle()
113 .try_downcast()
114 }
115
116 pub(crate) fn spawn_on_widget<W: Widget>(
120 &self,
121 pa: &mut Pass,
122 (target, specs): (&RwArea, DynSpawnSpecs),
123 widget: W,
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()
135 .area_is_eq(pa, target)
136 .then(|| node.handle().clone())
137 });
138
139 if inner.master_area.is_master_of(pa, target) {
140 Some((win, None, master))
141 } else if let Some((_, node)) = inner
142 .spawned
143 .iter()
144 .find(|(_, node)| node.area().is_master_of(pa, target))
145 {
146 Some((win, node.area().get_cluster_master(pa), master))
147 } else {
148 None
149 }
150 })?;
151
152 let widget = RwData::new(widget);
153 let id = SpawnId::new();
154
155 let path = widget
156 .read_as::<Buffer>(pa)
157 .and_then(|buffer| buffer.path_set());
158 let spawned = cluster_master.as_ref().unwrap_or(target).spawn(
159 pa,
160 path.as_ref().map(|p| p.as_ref()),
161 id,
162 specs,
163 )?;
164
165 let node = Node::new(widget, spawned, master);
166
167 let window = self.inner.write(pa).list.remove(win);
168 window.add(pa, node.clone(), None, Location::Spawned(id));
169 self.inner.write(pa).list.insert(win, window);
170
171 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
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 ) -> Handle<W> {
185 let widget = RwData::new(widget);
186 let path = widget
187 .read_as::<Buffer>(pa)
188 .and_then(|buffer| buffer.path_set());
189 let spawned = self
190 .ui
191 .new_dyn_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
192
193 let node = Node::new(widget, spawned, Some(master));
194
195 let window = self.inner.write(pa).list.remove(win);
196 window.add(pa, node.clone(), None, Location::Spawned(id));
197 self.inner.write(pa).list.insert(win, window);
198
199 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
200
201 node.handle().try_downcast().unwrap()
202 }
203
204 fn spawn_static<W: Widget>(
205 &self,
206 pa: &mut Pass,
207 (specs, win): (StaticSpawnSpecs, usize),
208 widget: W,
209 ) -> Option<Handle<W>> {
210 let id = SpawnId::new();
211 let widget = RwData::new(widget);
212 let path = widget
213 .read_as::<Buffer>(pa)
214 .and_then(|buffer| buffer.path_set());
215 let spawned = self
216 .ui
217 .new_static_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
218
219 let node = Node::new(widget, spawned, None);
220
221 let window = self.inner.write(pa).list.remove(win);
222 window.add(pa, node.clone(), None, Location::Spawned(id));
223 self.inner.write(pa).list.insert(win, window);
224
225 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
226
227 node.handle().try_downcast()
228 }
229
230 pub(crate) fn new_buffer(&self, pa: &mut Pass, buffer: Buffer) -> Node {
237 let inner = self.inner.read(pa);
238 let (handle, specs) = inner.layout.lock().unwrap().new_buffer(pa, &inner.list);
239
240 let specs = PushSpecs { cluster: false, ..specs };
241
242 if let Some(master) = handle.area().get_cluster_master(pa) {
243 self.push(pa, (&master, Some(true), specs), buffer, None)
244 .unwrap()
245 } else {
246 self.push(pa, (&handle.area, Some(true), specs), buffer, None)
247 .unwrap()
248 }
249 }
250
251 fn push<W: Widget>(
255 &self,
256 pa: &mut Pass,
257 (target, on_buffers, mut specs): (&RwArea, Option<bool>, PushSpecs),
258 widget: W,
259 master: Option<&RwArea>,
260 ) -> Option<Node> {
261 let inner = self.inner.read(pa);
262 let win = inner
263 .list
264 .iter()
265 .position(|window| {
266 window.0.read(pa).master_area.is_master_of(pa, target)
267 || window
268 .nodes(pa)
269 .any(|node| node.area().is_master_of(pa, target))
270 })
271 .unwrap();
272
273 let inner_window = inner.list[win].0.read(pa);
274 let target_is_on_buffers = inner_window.buffers_area.is_master_of(pa, target);
275
276 let on_buffers = on_buffers.unwrap_or(target_is_on_buffers) && target_is_on_buffers;
277
278 if target_is_on_buffers && !on_buffers {
279 specs.cluster = false;
280 }
281
282 let location = if on_buffers {
283 Location::OnBuffers
284 } else if let Some((id, _)) = inner_window
285 .spawned
286 .iter()
287 .find(|(_, node)| node.area().area_is_eq(pa, target))
288 {
289 Location::Spawned(*id)
290 } else {
291 Location::Regular
292 };
293
294 let widget = RwData::new(widget);
295 let path = widget
296 .read_as::<Buffer>(pa)
297 .and_then(|buffer| buffer.path_set());
298 let (pushed, parent) =
299 target.push(pa, path.as_ref().map(|p| p.as_ref()), specs, on_buffers)?;
300
301 let master = master.and_then(|area| {
302 self.entries(pa).find_map(|(.., node)| {
303 node.area()
304 .area_is_eq(pa, area)
305 .then(|| node.handle().clone())
306 })
307 });
308
309 let node = Node::new(widget, pushed, master);
310
311 let window = self.inner.write(pa).list.remove(win);
312 window.add(pa, node.clone(), parent, location);
313 self.inner.write(pa).list.insert(win, window);
314
315 hook::trigger(pa, WidgetOpened(node.handle().try_downcast::<W>().unwrap()));
316
317 Some(node)
318 }
319
320 pub(crate) fn close<W: Widget + ?Sized>(
324 &self,
325 pa: &mut Pass,
326 handle: &Handle<W>,
327 ) -> Result<(), Text> {
328 let win = self.handle_window(pa, handle)?;
329
330 if let Some(buf_handle) = handle.try_downcast::<Buffer>() {
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_cfg: PrintOpts,
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_cfg)),
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 node_of<'a, W: Widget>(&'a self, pa: &'a Pass) -> Result<&'a Node, Text> {
607 let handle = context::current_buffer(pa);
608
609 if let Some((handle, _)) = handle.get_related::<W>(pa).next() {
610 self.entries(pa)
611 .find_map(|(.., node)| node.ptr_eq(handle.widget()).then_some(node))
612 } else {
613 let cur_win = self.inner.read(pa).cur_win;
614 let list = &self.inner.read(pa).list;
615 list[cur_win]
616 .nodes(pa)
617 .chain(list[cur_win + 1..].iter().flat_map(|win| win.nodes(pa)))
618 .chain(list[..cur_win].iter().flat_map(|win| win.nodes(pa)))
619 .find(|node| node.data_is::<W>())
620 }
621 .ok_or(txt!("No widget of type [a]{}[] found", type_name::<W>()))
622 }
623
624 pub(crate) fn entries<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = (usize, &'a Node)> {
628 self.inner
629 .read(pa)
630 .list
631 .iter()
632 .enumerate()
633 .flat_map(|(win, window)| {
634 let inner = window.0.read(pa);
635 inner
636 .nodes
637 .iter()
638 .chain(inner.spawned.iter().map(|(_, node)| node))
639 .map(move |node| (win, node))
640 })
641 }
642
643 pub(crate) fn iter_around<'a>(
645 &'a self,
646 pa: &'a Pass,
647 win: usize,
648 wid: usize,
649 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
650 let window_entries =
651 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
652
653 let windows = &self.inner.read(pa).list;
654
655 let prev_len: usize = windows
656 .iter()
657 .take(win)
658 .map(|win| win.len_widgets(pa))
659 .sum();
660
661 windows
662 .iter()
663 .enumerate()
664 .skip(win)
665 .flat_map(window_entries)
666 .skip(wid + 1)
667 .chain(
668 windows
669 .iter()
670 .enumerate()
671 .take(win + 1)
672 .flat_map(window_entries)
673 .take(prev_len + wid),
674 )
675 }
676
677 pub(crate) fn iter_around_rev<'a>(
679 &'a self,
680 pa: &'a Pass,
681 win: usize,
682 wid: usize,
683 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
684 let entries =
685 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
686
687 let windows = &self.inner.read(pa).list;
688
689 let next_len: usize = windows
690 .iter()
691 .skip(win)
692 .map(|win| win.len_widgets(pa))
693 .sum();
694
695 windows
696 .iter()
697 .enumerate()
698 .rev()
699 .skip(windows.len() - (win + 1))
700 .flat_map(move |(w, win)| entries((w, win)).rev().skip(win.len_widgets(pa) - wid))
701 .chain(
702 windows
703 .iter()
704 .enumerate()
705 .rev()
706 .take(windows.len() - win)
707 .flat_map(move |(i, win)| entries((i, win)).rev())
708 .take(next_len - (wid + 1)),
709 )
710 }
711
712 pub fn jump_buffers_by(&self, pa: &mut Pass, jumps: i32) {
719 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
720 if let Some(handle) = self.inner.write(pa).buffer_history.jump_by(current, jumps) {
721 mode::reset_to(pa, &handle);
722 } else {
723 context::warn!("No buffer [a]{jumps}[] jumps away from the current one");
724 }
725 }
726
727 pub fn last_switched_buffer(&self, pa: &mut Pass) -> Result<Handle, Text> {
731 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
732 if let Some(handle) = self.inner.write(pa).buffer_history.last(current) {
733 mode::reset_to(pa, &handle);
734 Ok(handle)
735 } else {
736 Err(txt!("No last buffer"))
737 }
738 }
739
740 pub fn size(&self) -> Coord {
747 self.ui.size()
748 }
749
750 pub fn len(&self, pa: &Pass) -> usize {
754 self.inner.read(pa).list.len()
755 }
756
757 pub fn get<'a>(&'a self, pa: &'a Pass, win: usize) -> Option<&'a Window> {
759 self.inner.read(pa).list.get(win)
760 }
761
762 pub fn iter<'a>(&'a self, pa: &'a Pass) -> std::slice::Iter<'a, Window> {
764 self.inner.read(pa).list.iter()
765 }
766
767 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = Handle<dyn Widget>> + 'a {
769 self.inner
770 .read(pa)
771 .list
772 .iter()
773 .flat_map(|w| w.nodes(pa).map(|n| n.handle().clone()))
774 }
775
776 pub fn handles_of<W: Widget>(&self, pa: &Pass) -> Vec<Handle<W>> {
778 self.inner
779 .read(pa)
780 .list
781 .iter()
782 .flat_map(|w| w.nodes(pa).filter_map(|n| n.handle().try_downcast()))
783 .collect()
784 }
785
786 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
788 self.inner
789 .read(pa)
790 .list
791 .iter()
792 .flat_map(|w| w.buffers(pa))
793 .collect()
794 }
795
796 pub fn current_window(&self, pa: &Pass) -> usize {
798 self.inner.read(pa).cur_win
799 }
800
801 pub(crate) fn current_buffer<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Handle> {
803 &self.inner.read(pa).cur_buffer
804 }
805
806 pub(crate) fn current_widget<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Node> {
808 &self.inner.read(pa).cur_widget
809 }
810
811 pub(crate) fn get_additions(&self, pa: &mut Pass) -> Option<Vec<(usize, Node)>> {
813 self.inner.write(pa).new_additions.lock().unwrap().take()
814 }
815}
816
817#[derive(Clone)]
822pub struct Window(RwData<InnerWindow>);
823
824struct InnerWindow {
825 index: usize,
826 nodes: Vec<Node>,
827 spawned: Vec<(SpawnId, Node)>,
828 buffers_area: RwArea,
829 master_area: RwArea,
830 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
831}
832
833impl Window {
834 fn new<W: Widget>(
836 index: usize,
837 pa: &mut Pass,
838 ui: Ui,
839 widget: W,
840 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
841 ) -> (Self, Node) {
842 let widget = RwData::new(widget);
843 let path = if let Some(buffer) = widget.write_as::<Buffer>(pa) {
844 buffer.layout_order = get_layout_order();
845 buffer.path_set()
846 } else {
847 None
848 };
849
850 let area = ui.new_root(path.as_ref().map(|p| p.as_ref()));
851 let node = Node::new::<W>(widget, area.clone(), None);
852
853 new_additions
854 .lock()
855 .unwrap()
856 .get_or_insert_default()
857 .push((index, node.clone()));
858
859 let window = Self(RwData::new(InnerWindow {
860 index,
861 nodes: vec![node.clone()],
862 spawned: Vec::new(),
863 buffers_area: area.clone(),
864 master_area: area.clone(),
865 new_additions,
866 }));
867
868 (window, node)
869 }
870
871 pub(crate) fn new_from_raw(
873 pa: &mut Pass,
874 index: usize,
875 master_area: RwArea,
876 nodes: Vec<Node>,
877 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
878 ) -> Self {
879 let master_area = master_area
880 .get_cluster_master(pa)
881 .unwrap_or(master_area.clone());
882
883 Self(RwData::new(InnerWindow {
884 index,
885 nodes,
886 spawned: Vec::new(),
887 buffers_area: master_area.clone(),
888 master_area,
889 new_additions,
890 }))
891 }
892
893 pub fn push_inner<W: Widget>(
931 &self,
932 pa: &mut Pass,
933 widget: W,
934 mut specs: PushSpecs,
935 ) -> Handle<W> {
936 let target = self.0.read(pa).buffers_area.clone();
937
938 specs.cluster = false;
939
940 context::windows()
941 .push_widget(pa, (&target, Some(false), specs), widget, None)
942 .unwrap()
943 }
944
945 pub fn push_outer<W: Widget>(
981 &self,
982 pa: &mut Pass,
983 widget: W,
984 mut specs: PushSpecs,
985 ) -> Handle<W> {
986 let target = self.0.read(pa).master_area.clone();
987
988 specs.cluster = false;
989
990 context::windows()
991 .push_widget(pa, (&target, Some(false), specs), widget, None)
992 .unwrap()
993 }
994
995 pub fn spawn<W: Widget>(&self, pa: &mut Pass, widget: W, specs: StaticSpawnSpecs) -> Handle<W> {
1010 context::windows()
1011 .spawn_static(pa, (specs, self.0.read(pa).index), widget)
1012 .unwrap()
1013 }
1014
1015 fn add(&self, pa: &mut Pass, node: Node, parent: Option<RwArea>, location: Location) {
1017 match location {
1018 Location::OnBuffers => {
1019 self.0.write(pa).nodes.push(node.clone());
1020 if let Some(parent) = &parent
1021 && parent.is_master_of(pa, &self.0.read(pa).buffers_area)
1022 {
1023 self.0.write(pa).buffers_area = parent.clone()
1024 }
1025 }
1026 Location::Regular => self.0.write(pa).nodes.push(node.clone()),
1027 Location::Spawned(id) => self.0.write(pa).spawned.push((id, node.clone())),
1028 }
1029
1030 if let Some(parent) = &parent
1031 && parent.is_master_of(pa, &self.0.read(pa).master_area)
1032 {
1033 self.0.write(pa).master_area = parent.clone()
1034 }
1035
1036 let inner = self.0.write(pa);
1037 inner
1038 .new_additions
1039 .lock()
1040 .unwrap()
1041 .get_or_insert_default()
1042 .push((inner.index, node.clone()));
1043 }
1044
1045 fn close<W: Widget + ?Sized>(&self, pa: &mut Pass, handle: &Handle<W>) -> bool {
1049 let handle_eq = |node: &mut Node| node.handle() == handle;
1050
1051 let inner = self.0.write(pa);
1052
1053 let node = if let Some(node) = inner.nodes.extract_if(.., handle_eq).next() {
1054 node
1055 } else if let Some((_, node)) = inner.spawned.extract_if(.., |(_, n)| handle_eq(n)).next() {
1056 node
1057 } else {
1058 unreachable!("This isn't supposed to fail");
1059 };
1060
1061 node.handle().declare_closed(pa);
1062
1063 let (do_rm_window, rm_areas) = node.area().delete(pa);
1064 if do_rm_window {
1065 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1066 handle.declare_closed(pa);
1067 }
1068 return true;
1069 }
1070
1071 let (mut nodes, mut spawned) = {
1072 let inner = self.0.write(pa);
1073 let nodes = std::mem::take(&mut inner.nodes);
1074 let spawned = std::mem::take(&mut inner.spawned);
1075 (nodes, spawned)
1076 };
1077
1078 nodes.retain(|node| {
1079 if rm_areas
1080 .iter()
1081 .any(|a| a.area_is_eq(pa, node.handle().area()))
1082 {
1083 node.handle().declare_closed(pa);
1084 false
1085 } else {
1086 true
1087 }
1088 });
1089 spawned.retain(|(_, node)| {
1090 if rm_areas
1091 .iter()
1092 .any(|a| a.area_is_eq(pa, node.handle().area()))
1093 {
1094 node.handle().declare_closed(pa);
1095 false
1096 } else {
1097 true
1098 }
1099 });
1100
1101 let inner = self.0.write(pa);
1102 inner.nodes = nodes;
1103 inner.spawned = spawned;
1104
1105 let buffers = self.buffers(pa);
1106 if buffers.len() == 1 {
1107 let handle = buffers.first().unwrap();
1108
1109 let master_area = handle
1110 .area()
1111 .get_cluster_master(pa)
1112 .unwrap_or(handle.area.clone());
1113
1114 self.0.write(pa).buffers_area = master_area;
1115 }
1116
1117 if self.buffers(pa).is_empty() {
1118 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1119 handle.declare_closed(pa);
1120 }
1121 true
1122 } else {
1123 false
1124 }
1125 }
1126
1127 fn take_with_related_nodes<W: Widget + ?Sized>(
1129 &self,
1130 pa: &mut Pass,
1131 handle: &Handle<W>,
1132 ) -> Vec<Node> {
1133 let related = handle.related();
1134
1135 let (related, inner) = pa.write_many((related, &self.0));
1136
1137 inner
1138 .nodes
1139 .extract_if(.., |node| {
1140 related.iter().any(|(handle, _)| handle == node.handle()) || node.handle() == handle
1141 })
1142 .collect()
1143 }
1144
1145 fn insert_nodes(&self, pa: &mut Pass, nodes: Vec<Node>) {
1147 self.0.write(pa).nodes.extend(nodes);
1148 }
1149
1150 pub(crate) fn nodes<'a>(&'a self, pa: &'a Pass) -> Nodes<'a> {
1154 let inner = self.0.read(pa);
1155
1156 let spawned = SpawnedNodes { iter: inner.spawned.iter() };
1157
1158 Nodes {
1159 iter: inner.nodes.iter().chain(spawned),
1160 len: inner.nodes.len() + inner.spawned.len(),
1161 taken: 0,
1162 }
1163 }
1164
1165 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = &'a Handle<dyn Widget>> {
1174 self.nodes(pa).map(|node| node.handle())
1175 }
1176
1177 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
1189 let inner = self.0.read(pa);
1190 let mut buffers: Vec<Handle> = inner
1191 .nodes
1192 .iter()
1193 .filter_map(|node| node.try_downcast())
1194 .collect();
1195
1196 buffers.sort_unstable_by_key(|buffer| buffer.read(pa).layout_order);
1197
1198 buffers.extend(
1199 inner
1200 .spawned
1201 .iter()
1202 .filter_map(|(_, node)| node.try_downcast()),
1203 );
1204
1205 buffers
1206 }
1207
1208 pub(crate) fn send_mouse_event(&self, pa: &mut Pass, mouse_event: UiMouseEvent) {
1209 let inner = self.0.read(pa);
1210 let node = inner
1211 .spawned
1212 .iter()
1213 .rev()
1214 .map(|(_, node)| node)
1215 .chain(&inner.nodes)
1216 .find(|node| {
1217 let tl = node.handle().area().top_left(pa);
1218 let br = node.handle().area().bottom_right(pa);
1219 (tl.x <= mouse_event.coord.x && tl.y <= mouse_event.coord.y)
1220 && (mouse_event.coord.x < br.x && mouse_event.coord.y < br.y)
1221 })
1222 .cloned();
1223
1224 if let Some(node) = node {
1225 node.on_mouse_event(pa, mouse_event);
1226 }
1227 }
1228
1229 pub(crate) fn len_widgets(&self, pa: &Pass) -> usize {
1231 let inner = self.0.read(pa);
1232 inner.nodes.len() + inner.spawned.len()
1233 }
1234}
1235
1236#[derive(Default)]
1237struct BufferHistory {
1238 current_i: usize,
1239 list: Vec<Handle>,
1240 last: Option<Handle>,
1241}
1242
1243impl BufferHistory {
1244 fn jump_by(&mut self, current: Handle, by: i32) -> Option<Handle> {
1246 let new_i = self
1247 .current_i
1248 .saturating_add_signed(by as isize)
1249 .min(self.list.len());
1250 let new_handle = self.list.get(new_i)?.clone();
1251
1252 self.last = Some(current);
1253 self.current_i = new_i;
1254 Some(new_handle)
1255 }
1256
1257 fn last(&mut self, current: Handle) -> Option<Handle> {
1262 if let Some(last) = self.last.as_mut() {
1263 Some(std::mem::replace(last, current))
1264 } else if let Some(last) = self.list.get(self.current_i.checked_sub(1)?) {
1265 self.last = Some(current);
1266 Some(last.clone())
1267 } else {
1268 None
1269 }
1270 }
1271
1272 fn insert(&mut self, current: Handle, handle: Handle) {
1275 if self
1276 .current_i
1277 .checked_sub(1)
1278 .is_none_or(|prev_i| self.list[prev_i] != handle)
1279 && self
1280 .list
1281 .get(self.current_i)
1282 .is_none_or(|other| *other != handle)
1283 {
1284 self.list.insert(self.current_i, handle);
1285 self.last = Some(current);
1286 self.current_i += 1;
1287 }
1288 }
1289
1290 fn remove(&mut self, handle: &Handle) {
1293 let mut i = 0;
1294 self.list.retain(|other| {
1295 if other == handle {
1296 if i < self.current_i {
1297 self.current_i -= 1;
1298 }
1299 false
1300 } else {
1301 i += 1;
1302 true
1303 }
1304 });
1305 }
1306}
1307
1308fn get_layout_order() -> usize {
1311 use std::sync::atomic::{AtomicUsize, Ordering};
1312
1313 static LAYOUT_ORDER: AtomicUsize = AtomicUsize::new(0);
1314 LAYOUT_ORDER.fetch_add(1, Ordering::Relaxed)
1315}
1316
1317enum Location {
1318 OnBuffers,
1319 Regular,
1320 Spawned(SpawnId),
1321}
1322
1323#[derive(Debug, Clone)]
1324pub(crate) struct Nodes<'a> {
1325 iter: Chain<std::slice::Iter<'a, Node>, SpawnedNodes<'a>>,
1326 len: usize,
1327 taken: usize,
1328}
1329
1330impl<'a> Iterator for Nodes<'a> {
1331 type Item = &'a Node;
1332
1333 fn next(&mut self) -> Option<Self::Item> {
1334 let next = self.iter.next();
1335 self.taken += next.is_some() as usize;
1336 next
1337 }
1338
1339 fn size_hint(&self) -> (usize, Option<usize>) {
1340 (self.len - self.taken, Some(self.len - self.taken))
1341 }
1342}
1343
1344impl<'a> DoubleEndedIterator for Nodes<'a> {
1345 fn next_back(&mut self) -> Option<Self::Item> {
1346 let next = self.iter.next_back();
1347 self.taken += next.is_some() as usize;
1348 next
1349 }
1350}
1351
1352impl ExactSizeIterator for Nodes<'_> {}
1353
1354#[derive(Debug, Clone)]
1355struct SpawnedNodes<'a> {
1356 iter: std::slice::Iter<'a, (SpawnId, Node)>,
1357}
1358
1359impl<'a> Iterator for SpawnedNodes<'a> {
1360 type Item = &'a Node;
1361
1362 fn next(&mut self) -> Option<Self::Item> {
1363 self.iter.next().map(|(_, node)| node)
1364 }
1365}
1366
1367impl DoubleEndedIterator for SpawnedNodes<'_> {
1368 fn next_back(&mut self) -> Option<Self::Item> {
1369 self.iter.next_back().map(|(_, node)| node)
1370 }
1371}