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, Cache, Handle},
22 data::{Pass, RwData},
23 hook::{self, BufferClosed, WidgetCreated, WindowCreated},
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 WidgetCreated(node.handle().try_downcast::<Buffer>().unwrap()),
78 );
79 hook::trigger(pa, WindowCreated(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(
95 pa,
96 WidgetCreated(node.handle().try_downcast::<Buffer>().unwrap()),
97 );
98 hook::trigger(pa, WindowCreated(self.inner.read(pa).list[win].clone()));
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(
172 pa,
173 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
174 );
175
176 node.handle().try_downcast()
177 }
178
179 pub(crate) fn spawn_on_text<W: Widget>(
181 &self,
182 pa: &mut Pass,
183 (id, specs): (SpawnId, DynSpawnSpecs),
184 widget: W,
185 win: usize,
186 master: Handle<dyn Widget>,
187 ) -> Handle<W> {
188 let widget = RwData::new(widget);
189 let path = widget
190 .read_as::<Buffer>(pa)
191 .and_then(|buffer| buffer.path_set());
192 let spawned = self
193 .ui
194 .new_dyn_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
195
196 let node = Node::new(widget, spawned, Some(master));
197
198 let window = self.inner.write(pa).list.remove(win);
199 window.add(pa, node.clone(), None, Location::Spawned(id));
200 self.inner.write(pa).list.insert(win, window);
201
202 hook::trigger(
203 pa,
204 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
205 );
206
207 node.handle().try_downcast().unwrap()
208 }
209
210 fn spawn_static<W: Widget>(
211 &self,
212 pa: &mut Pass,
213 (specs, win): (StaticSpawnSpecs, usize),
214 widget: W,
215 ) -> Option<Handle<W>> {
216 let id = SpawnId::new();
217 let widget = RwData::new(widget);
218 let path = widget
219 .read_as::<Buffer>(pa)
220 .and_then(|buffer| buffer.path_set());
221 let spawned = self
222 .ui
223 .new_static_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
224
225 let node = Node::new(widget, spawned, None);
226
227 let window = self.inner.write(pa).list.remove(win);
228 window.add(pa, node.clone(), None, Location::Spawned(id));
229 self.inner.write(pa).list.insert(win, window);
230
231 hook::trigger(
232 pa,
233 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
234 );
235
236 node.handle().try_downcast()
237 }
238
239 pub(crate) fn new_buffer(&self, pa: &mut Pass, buffer: Buffer) -> Node {
246 let inner = self.inner.read(pa);
247 let (handle, specs) = inner.layout.lock().unwrap().new_buffer(pa, &inner.list);
248
249 let specs = PushSpecs { cluster: false, ..specs };
250
251 if let Some(master) = handle.area().get_cluster_master(pa) {
252 self.push(pa, (&master, Some(true), specs), buffer, None)
253 .unwrap()
254 } else {
255 self.push(pa, (&handle.area, Some(true), specs), buffer, None)
256 .unwrap()
257 }
258 }
259
260 fn push<W: Widget>(
264 &self,
265 pa: &mut Pass,
266 (target, on_buffers, mut specs): (&RwArea, Option<bool>, PushSpecs),
267 widget: W,
268 master: Option<&RwArea>,
269 ) -> Option<Node> {
270 let inner = self.inner.read(pa);
271 let win = inner
272 .list
273 .iter()
274 .position(|window| {
275 window.0.read(pa).master_area.is_master_of(pa, target)
276 || window
277 .nodes(pa)
278 .any(|node| node.area().is_master_of(pa, target))
279 })
280 .unwrap();
281
282 let inner_window = inner.list[win].0.read(pa);
283 let target_is_on_buffers = inner_window.buffers_area.is_master_of(pa, target);
284
285 let on_buffers = on_buffers.unwrap_or(target_is_on_buffers) && target_is_on_buffers;
286
287 if target_is_on_buffers && !on_buffers {
288 specs.cluster = false;
289 }
290
291 let location = if on_buffers {
292 Location::OnBuffers
293 } else if let Some((id, _)) = inner_window
294 .spawned
295 .iter()
296 .find(|(_, node)| node.area().area_is_eq(pa, target))
297 {
298 Location::Spawned(*id)
299 } else {
300 Location::Regular
301 };
302
303 let widget = RwData::new(widget);
304 let path = widget
305 .read_as::<Buffer>(pa)
306 .and_then(|buffer| buffer.path_set());
307 let (pushed, parent) =
308 target.push(pa, path.as_ref().map(|p| p.as_ref()), specs, on_buffers)?;
309
310 let master = master.and_then(|area| {
311 self.entries(pa).find_map(|(.., node)| {
312 node.area()
313 .area_is_eq(pa, area)
314 .then(|| node.handle().clone())
315 })
316 });
317
318 let node = Node::new(widget, pushed, master);
319
320 let window = self.inner.write(pa).list.remove(win);
321 window.add(pa, node.clone(), parent, location);
322 self.inner.write(pa).list.insert(win, window);
323
324 hook::trigger(
325 pa,
326 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
327 );
328
329 Some(node)
330 }
331
332 pub(crate) fn close<W: Widget + ?Sized, S>(
336 &self,
337 pa: &mut Pass,
338 handle: &Handle<W, S>,
339 ) -> Result<(), Text> {
340 let win = self.handle_window(pa, handle)?;
341
342 if let Some(buf_handle) = handle.try_downcast::<Buffer>() {
345 hook::trigger(pa, BufferClosed((buf_handle.clone(), Cache::new())));
346
347 let buffers_ahead: Vec<Node> = self.inner.read(pa).list[win]
348 .nodes(pa)
349 .filter(|node| {
350 node.handle().read_as::<Buffer>(pa).is_some_and(|buffer| {
351 buffer.layout_order > buf_handle.read(pa).layout_order
352 })
353 })
354 .cloned()
355 .collect();
356
357 for buffer_ahead in buffers_ahead {
358 self.swap(pa, handle, buffer_ahead.handle())?;
359 }
360 }
361
362 let mut list = std::mem::take(&mut self.inner.write(pa).list);
364
365 if list[win].close(pa, handle) {
366 list.remove(win);
367 self.ui.remove_window(win);
368 let cur_win = context::current_win_index(pa);
369 if cur_win > win {
370 self.inner.write(pa).cur_win -= 1;
371 }
372 }
373
374 let inner = self.inner.write(pa);
375 inner.list = list;
376 inner.new_additions.lock().unwrap().get_or_insert_default();
377
378 let inner = self.inner.read(pa);
380 if handle == inner.cur_widget.read(pa).handle() || handle == inner.cur_buffer.read(pa) {
381 if let Some(handle) = handle.try_downcast::<Buffer>() {
382 self.inner.write(pa).buffer_history.remove(&handle);
383
384 let entry = self
385 .inner
386 .write(pa)
387 .buffer_history
388 .jump_by(handle.clone(), -1)
389 .or_else(|| self.buffers(pa).next())
390 .and_then(|handle| {
391 self.entries(pa).find_map(|(win, node)| {
392 (*node.handle() == handle).then(|| (win, node.clone()))
393 })
394 });
395
396 if let Some((_, node)) = entry {
397 crate::mode::reset_to(node.handle().clone());
398 } else {
399 context::sender()
401 .send(crate::session::DuatEvent::Quit)
402 .unwrap();
403 return Ok(());
404 }
405 } else {
406 crate::mode::reset_to(inner.cur_buffer.read(pa).to_dyn());
407 }
408 }
409
410 Ok(())
411 }
412
413 pub(crate) fn swap<W1: Widget + ?Sized, S1, W2: Widget + ?Sized, S2>(
415 &self,
416 pa: &mut Pass,
417 lhs: &Handle<W1, S1>,
418 rhs: &Handle<W2, S2>,
419 ) -> Result<(), Text> {
420 let lhs_win = self.handle_window(pa, lhs)?;
421 let rhs_win = self.handle_window(pa, rhs)?;
422
423 let [lhs_buffer, rhs_buffer] = [lhs.try_downcast::<Buffer>(), rhs.try_downcast()];
424
425 if let [Some(lhs), Some(rhs)] = [lhs_buffer, rhs_buffer] {
426 let lhs_lo = lhs.read(pa).layout_order;
427 let rhs_lo = std::mem::replace(&mut rhs.write(pa).layout_order, lhs_lo);
428 lhs.write(pa).layout_order = rhs_lo
429 }
430
431 let windows = std::mem::take(&mut self.inner.write(pa).list);
432
433 let lhs_nodes = windows[lhs_win].take_with_related_nodes(pa, lhs);
434 windows[rhs_win].insert_nodes(pa, lhs_nodes);
435
436 let rhs_nodes = windows[rhs_win].take_with_related_nodes(pa, rhs);
437 windows[lhs_win].insert_nodes(pa, rhs_nodes);
438
439 let wins = self.inner.write(pa);
440 wins.list = windows;
441 wins.new_additions.lock().unwrap().get_or_insert_default();
442
443 lhs.area().swap(pa, rhs.area());
444
445 let cur_buffer = context::current_buffer(pa);
446 if lhs_win != rhs_win {
447 if lhs == cur_buffer {
448 self.inner.write(pa).cur_win = lhs_win;
449 self.ui.switch_window(lhs_win);
450 } else if rhs == cur_buffer {
451 self.inner.write(pa).cur_win = rhs_win;
452 self.ui.switch_window(rhs_win);
453 }
454 }
455
456 Ok(())
457 }
458
459 pub(crate) fn open_or_move_to_new_window(
462 &self,
463 pa: &mut Pass,
464 pk: PathKind,
465 default_buffer_cfg: PrintOpts,
466 ) -> Node {
467 let node = match self.buffer_entry(pa, pk.clone()) {
468 Ok((win, handle)) if self.get(pa, win).unwrap().buffers(pa).len() > 1 => {
469 handle.write(pa).layout_order = 0;
471
472 let nodes = {
473 let old_window = self.inner.write(pa).list.remove(win);
474 let nodes = old_window.take_with_related_nodes(pa, &handle.to_dyn());
475 self.inner.write(pa).list.insert(win, old_window);
476
477 nodes
478 };
479
480 let path = handle.read(pa).path_set();
482 let new_root = self.ui.new_root(path.as_ref().map(|p| p.as_ref()));
483 handle.area().swap(pa, &new_root);
484 let window = Window::new_from_raw(
485 pa,
486 win,
487 handle.area.clone(),
488 nodes,
489 self.inner.read(pa).new_additions.clone(),
490 );
491
492 self.inner.write(pa).list.push(window.clone());
493
494 hook::trigger(pa, WindowCreated(window));
495
496 let lo = handle.read(pa).layout_order;
498
499 for handle in &self.inner.read(pa).list[win].buffers(pa)[lo..] {
500 new_root.swap(pa, handle.area());
501 }
502
503 new_root.delete(pa);
506
507 self.inner
508 .write(pa)
509 .new_additions
510 .lock()
511 .unwrap()
512 .get_or_insert_default();
513
514 Node::from_handle(handle)
515 }
516 Ok((.., handle)) => Node::from_handle(handle),
519 Err(_) => self.new_window(pa, Buffer::new(pk.as_path(), default_buffer_cfg)),
520 };
521
522 if context::current_buffer(pa).read(pa).path_kind() != pk {
523 mode::reset_to(node.handle().clone());
524 }
525
526 node
527 }
528
529 pub(crate) fn set_current_node(&self, pa: &mut Pass, node: Node) -> Result<(), Text> {
531 let internal_pass = &mut unsafe { Pass::new() };
534
535 let win = self.handle_window(pa, node.handle())?;
536 let inner = self.inner.write(pa);
537
538 if let Some(handle) = node.try_downcast::<Buffer>() {
539 let current = std::mem::replace(inner.cur_buffer.write(internal_pass), handle.clone());
540 inner.buffer_history.insert(current, handle);
541 }
542 *inner.cur_widget.write(internal_pass) = node.clone();
543 inner.cur_win = win;
544 self.ui.switch_window(win);
545
546 Ok(())
547 }
548
549 pub(crate) fn queue_close_spawned(&self, id: SpawnId) {
553 let mut spawns_to_remove = self.spawns_to_remove.lock().unwrap();
554 if !spawns_to_remove.contains(&id) {
555 spawns_to_remove.push(id)
556 }
557 }
558
559 pub(crate) fn cleanup_despawned(&self, pa: &mut Pass) {
562 let spawns_to_remove = std::mem::take(&mut *self.spawns_to_remove.lock().unwrap());
563 for id in spawns_to_remove {
564 if let Some((_, node)) = self
565 .iter(pa)
566 .flat_map(|window| &window.0.read(pa).spawned)
567 .find(|(other, _)| *other == id)
568 {
569 self.close(pa, &node.handle().clone()).unwrap();
570 }
571 }
572 }
573
574 pub(crate) fn handle_window<W: Widget + ?Sized, S>(
578 &self,
579 pa: &Pass,
580 handle: &Handle<W, S>,
581 ) -> Result<usize, Text> {
582 self.entries(pa)
583 .find_map(|(win, node)| (node.handle() == handle).then_some(win))
584 .ok_or_else(|| txt!("The Handle was already closed"))
585 }
586
587 pub(crate) fn buffer_entry(&self, pa: &Pass, pk: PathKind) -> Result<(usize, Handle), Text> {
589 self.entries(pa)
590 .find_map(|(win, node)| {
591 (node.read_as(pa).filter(|f: &&Buffer| f.path_kind() == pk))
592 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
593 })
594 .ok_or_else(|| txt!("Buffer {pk} not found"))
595 }
596
597 pub(crate) fn named_buffer_entry(
599 &self,
600 pa: &Pass,
601 name: &str,
602 ) -> Result<(usize, Handle), Text> {
603 self.entries(pa)
604 .find_map(|(win, node)| {
605 (node.read_as(pa).filter(|f: &&Buffer| f.name() == name))
606 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
607 })
608 .ok_or_else(|| txt!("Buffer [buffer]{name}[] not found"))
609 }
610
611 pub(crate) fn node_of<'a, W: Widget>(&'a self, pa: &'a Pass) -> Result<&'a Node, Text> {
616 let handle = context::current_buffer(pa);
617
618 if let Some((handle, _)) = handle.get_related::<W>(pa).next() {
619 self.entries(pa)
620 .find_map(|(.., node)| node.ptr_eq(handle.widget()).then_some(node))
621 } else {
622 let cur_win = self.inner.read(pa).cur_win;
623 let list = &self.inner.read(pa).list;
624 list[cur_win]
625 .nodes(pa)
626 .chain(list[cur_win + 1..].iter().flat_map(|win| win.nodes(pa)))
627 .chain(list[..cur_win].iter().flat_map(|win| win.nodes(pa)))
628 .find(|node| node.data_is::<W>())
629 }
630 .ok_or(txt!("No widget of type [a]{}[] found", type_name::<W>()))
631 }
632
633 pub(crate) fn entries<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = (usize, &'a Node)> {
637 self.inner
638 .read(pa)
639 .list
640 .iter()
641 .enumerate()
642 .flat_map(|(win, window)| {
643 let inner = window.0.read(pa);
644 inner
645 .nodes
646 .iter()
647 .chain(inner.spawned.iter().map(|(_, node)| node))
648 .map(move |node| (win, node))
649 })
650 }
651
652 pub(crate) fn iter_around<'a>(
654 &'a self,
655 pa: &'a Pass,
656 win: usize,
657 wid: usize,
658 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
659 let window_entries =
660 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
661
662 let windows = &self.inner.read(pa).list;
663
664 let prev_len: usize = windows
665 .iter()
666 .take(win)
667 .map(|win| win.len_widgets(pa))
668 .sum();
669
670 windows
671 .iter()
672 .enumerate()
673 .skip(win)
674 .flat_map(window_entries)
675 .skip(wid + 1)
676 .chain(
677 windows
678 .iter()
679 .enumerate()
680 .take(win + 1)
681 .flat_map(window_entries)
682 .take(prev_len + wid),
683 )
684 }
685
686 pub(crate) fn iter_around_rev<'a>(
688 &'a self,
689 pa: &'a Pass,
690 win: usize,
691 wid: usize,
692 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
693 let entries =
694 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
695
696 let windows = &self.inner.read(pa).list;
697
698 let next_len: usize = windows
699 .iter()
700 .skip(win)
701 .map(|win| win.len_widgets(pa))
702 .sum();
703
704 windows
705 .iter()
706 .enumerate()
707 .rev()
708 .skip(windows.len() - (win + 1))
709 .flat_map(move |(w, win)| entries((w, win)).rev().skip(win.len_widgets(pa) - wid))
710 .chain(
711 windows
712 .iter()
713 .enumerate()
714 .rev()
715 .take(windows.len() - win)
716 .flat_map(move |(i, win)| entries((i, win)).rev())
717 .take(next_len - (wid + 1)),
718 )
719 }
720
721 pub fn jump_buffers_by(&self, pa: &mut Pass, jumps: i32) {
728 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
729 if let Some(handle) = self.inner.write(pa).buffer_history.jump_by(current, jumps) {
730 mode::reset_to(handle.to_dyn());
731 } else {
732 context::warn!("No buffer [a]{jumps}[] jumps away from the current one");
733 }
734 }
735
736 pub fn last_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(handle.to_dyn());
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 = &'a Handle<dyn Widget>> {
778 self.inner
779 .read(pa)
780 .list
781 .iter()
782 .flat_map(|w| w.nodes(pa).map(|n| n.handle()))
783 }
784
785 pub fn handles_of<'a, W: Widget>(
787 &'a self,
788 pa: &'a Pass,
789 ) -> impl Iterator<Item = Handle<W>> + 'a {
790 self.inner
791 .read(pa)
792 .list
793 .iter()
794 .flat_map(|w| w.nodes(pa).filter_map(|n| n.handle().try_downcast()))
795 }
796
797 pub fn buffers<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = Handle> + 'a {
799 self.inner.read(pa).list.iter().flat_map(|w| w.buffers(pa))
800 }
801
802 pub fn current_window(&self, pa: &Pass) -> usize {
804 self.inner.read(pa).cur_win
805 }
806
807 pub(crate) fn current_buffer<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Handle> {
809 &self.inner.read(pa).cur_buffer
810 }
811
812 pub(crate) fn current_widget<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Node> {
814 &self.inner.read(pa).cur_widget
815 }
816
817 pub(crate) fn get_additions(&self, pa: &mut Pass) -> Option<Vec<(usize, Node)>> {
819 self.inner.write(pa).new_additions.lock().unwrap().take()
820 }
821}
822
823#[derive(Clone)]
828pub struct Window(RwData<InnerWindow>);
829
830struct InnerWindow {
831 index: usize,
832 nodes: Vec<Node>,
833 spawned: Vec<(SpawnId, Node)>,
834 buffers_area: RwArea,
835 master_area: RwArea,
836 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
837}
838
839impl Window {
840 fn new<W: Widget>(
842 index: usize,
843 pa: &mut Pass,
844 ui: Ui,
845 widget: W,
846 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
847 ) -> (Self, Node) {
848 let widget = RwData::new(widget);
849 let path = if let Some(buffer) = widget.write_as::<Buffer>(pa) {
850 buffer.layout_order = get_layout_order();
851 buffer.path_set()
852 } else {
853 None
854 };
855
856 let area = ui.new_root(path.as_ref().map(|p| p.as_ref()));
857 let node = Node::new::<W>(widget, area.clone(), None);
858
859 new_additions
860 .lock()
861 .unwrap()
862 .get_or_insert_default()
863 .push((index, node.clone()));
864
865 let window = Self(RwData::new(InnerWindow {
866 index,
867 nodes: vec![node.clone()],
868 spawned: Vec::new(),
869 buffers_area: area.clone(),
870 master_area: area.clone(),
871 new_additions,
872 }));
873
874 (window, node)
875 }
876
877 pub(crate) fn new_from_raw(
879 pa: &mut Pass,
880 index: usize,
881 master_area: RwArea,
882 nodes: Vec<Node>,
883 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
884 ) -> Self {
885 let master_area = master_area
886 .get_cluster_master(pa)
887 .unwrap_or(master_area.clone());
888
889 Self(RwData::new(InnerWindow {
890 index,
891 nodes,
892 spawned: Vec::new(),
893 buffers_area: master_area.clone(),
894 master_area,
895 new_additions,
896 }))
897 }
898
899 pub fn push_inner<W: Widget>(
937 &self,
938 pa: &mut Pass,
939 widget: W,
940 mut specs: PushSpecs,
941 ) -> Handle<W> {
942 let target = self.0.read(pa).buffers_area.clone();
943
944 specs.cluster = false;
945
946 context::windows()
947 .push_widget(pa, (&target, Some(false), specs), widget, None)
948 .unwrap()
949 }
950
951 pub fn push_outer<W: Widget>(
987 &self,
988 pa: &mut Pass,
989 widget: W,
990 mut specs: PushSpecs,
991 ) -> Handle<W> {
992 let target = self.0.read(pa).master_area.clone();
993
994 specs.cluster = false;
995
996 context::windows()
997 .push_widget(pa, (&target, Some(false), specs), widget, None)
998 .unwrap()
999 }
1000
1001 pub fn spawn<W: Widget>(&self, pa: &mut Pass, widget: W, specs: StaticSpawnSpecs) -> Handle<W> {
1016 context::windows()
1017 .spawn_static(pa, (specs, self.0.read(pa).index), widget)
1018 .unwrap()
1019 }
1020
1021 fn add(&self, pa: &mut Pass, node: Node, parent: Option<RwArea>, location: Location) {
1023 match location {
1024 Location::OnBuffers => {
1025 self.0.write(pa).nodes.push(node.clone());
1026 if let Some(parent) = &parent
1027 && parent.is_master_of(pa, &self.0.read(pa).buffers_area)
1028 {
1029 self.0.write(pa).buffers_area = parent.clone()
1030 }
1031 }
1032 Location::Regular => self.0.write(pa).nodes.push(node.clone()),
1033 Location::Spawned(id) => self.0.write(pa).spawned.push((id, node.clone())),
1034 }
1035
1036 if let Some(parent) = &parent
1037 && parent.is_master_of(pa, &self.0.read(pa).master_area)
1038 {
1039 self.0.write(pa).master_area = parent.clone()
1040 }
1041
1042 let inner = self.0.write(pa);
1043 inner
1044 .new_additions
1045 .lock()
1046 .unwrap()
1047 .get_or_insert_default()
1048 .push((inner.index, node.clone()));
1049 }
1050
1051 fn close<W: Widget + ?Sized, S>(&self, pa: &mut Pass, handle: &Handle<W, S>) -> bool {
1055 let handle_eq = |node: &mut Node| node.handle() == handle;
1056
1057 let inner = self.0.write(pa);
1058
1059 let node = if let Some(node) = inner.nodes.extract_if(.., handle_eq).next() {
1060 node
1061 } else if let Some((_, node)) = inner.spawned.extract_if(.., |(_, n)| handle_eq(n)).next() {
1062 node
1063 } else {
1064 unreachable!("This isn't supposed to fail");
1065 };
1066
1067 node.handle().declare_closed(pa);
1068
1069 let (do_rm_window, rm_areas) = node.area().delete(pa);
1070 if do_rm_window {
1071 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1072 handle.declare_closed(pa);
1073 }
1074 return true;
1075 }
1076
1077 let (mut nodes, mut spawned) = {
1078 let inner = self.0.write(pa);
1079 let nodes = std::mem::take(&mut inner.nodes);
1080 let spawned = std::mem::take(&mut inner.spawned);
1081 (nodes, spawned)
1082 };
1083
1084 nodes.retain(|node| {
1085 if rm_areas
1086 .iter()
1087 .any(|a| a.area_is_eq(pa, node.handle().area()))
1088 {
1089 node.handle().declare_closed(pa);
1090 false
1091 } else {
1092 true
1093 }
1094 });
1095 spawned.retain(|(_, node)| {
1096 if rm_areas
1097 .iter()
1098 .any(|a| a.area_is_eq(pa, node.handle().area()))
1099 {
1100 node.handle().declare_closed(pa);
1101 false
1102 } else {
1103 true
1104 }
1105 });
1106
1107 let inner = self.0.write(pa);
1108 inner.nodes = nodes;
1109 inner.spawned = spawned;
1110
1111 let buffers = self.buffers(pa);
1112 if buffers.len() == 1 {
1113 let handle = buffers.first().unwrap();
1114
1115 let master_area = handle
1116 .area()
1117 .get_cluster_master(pa)
1118 .unwrap_or(handle.area.clone());
1119
1120 self.0.write(pa).buffers_area = master_area;
1121 }
1122
1123 if self.buffers(pa).is_empty() {
1124 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1125 handle.declare_closed(pa);
1126 }
1127 true
1128 } else {
1129 false
1130 }
1131 }
1132
1133 fn take_with_related_nodes<W: Widget + ?Sized, S>(
1135 &self,
1136 pa: &mut Pass,
1137 handle: &Handle<W, S>,
1138 ) -> Vec<Node> {
1139 let related = handle.related();
1140
1141 let (related, inner) = pa.read_and_write(related, &self.0);
1142
1143 inner
1144 .nodes
1145 .extract_if(.., |node| {
1146 related.iter().any(|(handle, _)| handle == node.handle()) || node.handle() == handle
1147 })
1148 .collect()
1149 }
1150
1151 fn insert_nodes(&self, pa: &mut Pass, nodes: Vec<Node>) {
1153 self.0.write(pa).nodes.extend(nodes);
1154 }
1155
1156 pub(crate) fn nodes<'a>(&'a self, pa: &'a Pass) -> Nodes<'a> {
1160 let inner = self.0.read(pa);
1161
1162 let spawned = SpawnedNodes { iter: inner.spawned.iter() };
1163
1164 Nodes {
1165 iter: inner.nodes.iter().chain(spawned),
1166 len: inner.nodes.len() + inner.spawned.len(),
1167 taken: 0,
1168 }
1169 }
1170
1171 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = &'a Handle<dyn Widget>> {
1180 self.nodes(pa).map(|node| node.handle())
1181 }
1182
1183 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
1195 let inner = self.0.read(pa);
1196 let mut buffers: Vec<Handle> = inner
1197 .nodes
1198 .iter()
1199 .filter_map(|node| node.try_downcast())
1200 .collect();
1201
1202 buffers.sort_unstable_by_key(|buffer| buffer.read(pa).layout_order);
1203
1204 buffers.extend(
1205 inner
1206 .spawned
1207 .iter()
1208 .filter_map(|(_, node)| node.try_downcast()),
1209 );
1210
1211 buffers
1212 }
1213
1214 pub(crate) fn send_mouse_event(&self, pa: &mut Pass, mouse_event: UiMouseEvent) {
1215 let inner = self.0.read(pa);
1216 let node = inner
1217 .spawned
1218 .iter()
1219 .rev()
1220 .map(|(_, node)| node)
1221 .chain(&inner.nodes)
1222 .find(|node| {
1223 let tl = node.handle().area().top_left(pa);
1224 let br = node.handle().area().bottom_right(pa);
1225 (tl.x <= mouse_event.coord.x && tl.y <= mouse_event.coord.y)
1226 && (mouse_event.coord.x < br.x && mouse_event.coord.y < br.y)
1227 })
1228 .cloned();
1229
1230 if let Some(node) = node {
1231 node.on_mouse_event(pa, mouse_event);
1232 }
1233 }
1234
1235 pub(crate) fn len_widgets(&self, pa: &Pass) -> usize {
1237 let inner = self.0.read(pa);
1238 inner.nodes.len() + inner.spawned.len()
1239 }
1240}
1241
1242#[derive(Default)]
1243struct BufferHistory {
1244 current_i: usize,
1245 list: Vec<Handle>,
1246 last: Option<Handle>,
1247}
1248
1249impl BufferHistory {
1250 fn jump_by(&mut self, current: Handle, by: i32) -> Option<Handle> {
1252 let new_i = self
1253 .current_i
1254 .saturating_add_signed(by as isize)
1255 .min(self.list.len());
1256 let new_handle = self.list.get(new_i)?.clone();
1257
1258 self.last = Some(current);
1259 self.current_i = new_i;
1260 Some(new_handle)
1261 }
1262
1263 fn last(&mut self, current: Handle) -> Option<Handle> {
1268 if let Some(last) = self.last.as_mut() {
1269 Some(std::mem::replace(last, current))
1270 } else if let Some(last) = self.list.get(self.current_i.checked_sub(1)?) {
1271 self.last = Some(current);
1272 Some(last.clone())
1273 } else {
1274 None
1275 }
1276 }
1277
1278 fn insert(&mut self, current: Handle, handle: Handle) {
1281 if self
1282 .current_i
1283 .checked_sub(1)
1284 .is_none_or(|prev_i| self.list[prev_i] != handle)
1285 && self
1286 .list
1287 .get(self.current_i)
1288 .is_none_or(|other| *other != handle)
1289 {
1290 self.list.insert(self.current_i, handle);
1291 self.last = Some(current);
1292 self.current_i += 1;
1293 }
1294 }
1295
1296 fn remove(&mut self, handle: &Handle) {
1299 let mut i = 0;
1300 self.list.retain(|other| {
1301 if other == handle {
1302 if i < self.current_i {
1303 self.current_i -= 1;
1304 }
1305 false
1306 } else {
1307 i += 1;
1308 true
1309 }
1310 });
1311 }
1312}
1313
1314fn get_layout_order() -> usize {
1317 use std::sync::atomic::{AtomicUsize, Ordering};
1318
1319 static LAYOUT_ORDER: AtomicUsize = AtomicUsize::new(0);
1320 LAYOUT_ORDER.fetch_add(1, Ordering::Relaxed)
1321}
1322
1323enum Location {
1324 OnBuffers,
1325 Regular,
1326 Spawned(SpawnId),
1327}
1328
1329#[derive(Debug, Clone)]
1330pub(crate) struct Nodes<'a> {
1331 iter: Chain<std::slice::Iter<'a, Node>, SpawnedNodes<'a>>,
1332 len: usize,
1333 taken: usize,
1334}
1335
1336impl<'a> Iterator for Nodes<'a> {
1337 type Item = &'a Node;
1338
1339 fn next(&mut self) -> Option<Self::Item> {
1340 let next = self.iter.next();
1341 self.taken += next.is_some() as usize;
1342 next
1343 }
1344
1345 fn size_hint(&self) -> (usize, Option<usize>) {
1346 (self.len - self.taken, Some(self.len - self.taken))
1347 }
1348}
1349
1350impl<'a> DoubleEndedIterator for Nodes<'a> {
1351 fn next_back(&mut self) -> Option<Self::Item> {
1352 let next = self.iter.next_back();
1353 self.taken += next.is_some() as usize;
1354 next
1355 }
1356}
1357
1358impl ExactSizeIterator for Nodes<'_> {}
1359
1360#[derive(Debug, Clone)]
1361struct SpawnedNodes<'a> {
1362 iter: std::slice::Iter<'a, (SpawnId, Node)>,
1363}
1364
1365impl<'a> Iterator for SpawnedNodes<'a> {
1366 type Item = &'a Node;
1367
1368 fn next(&mut self) -> Option<Self::Item> {
1369 self.iter.next().map(|(_, node)| node)
1370 }
1371}
1372
1373impl DoubleEndedIterator for SpawnedNodes<'_> {
1374 fn next_back(&mut self) -> Option<Self::Item> {
1375 self.iter.next_back().map(|(_, node)| node)
1376 }
1377}