1use std::{
13 any::type_name,
14 sync::{Arc, Mutex},
15};
16
17use super::{Node, Widget, layout::Layout};
18use crate::{
19 buffer::{Buffer, PathKind},
20 context::{self, Cache, Handle},
21 data::{Pass, RwData},
22 hook::{self, BufferClosed, WidgetCreated, WindowCreated},
23 mode,
24 opts::PrintOpts,
25 text::{SpawnId, Text, txt},
26 ui::{PushSpecs, RwArea, SpawnSpecs, Ui},
27};
28
29pub struct Windows {
31 inner: RwData<InnerWindows>,
32 spawns_to_remove: Mutex<Vec<SpawnId>>,
33 ui: Ui,
34}
35
36struct InnerWindows {
38 layout: Box<Mutex<dyn Layout>>,
39 list: Vec<Window>,
40 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
41 cur_buffer: RwData<Handle>,
42 cur_widget: RwData<Node>,
43 cur_win: usize,
44 buffer_history: BufferHistory,
45}
46
47impl Windows {
48 pub(crate) fn initialize(
51 pa: &mut Pass,
52 buffer: Buffer,
53 layout: Box<Mutex<dyn Layout>>,
54 ui: Ui,
55 ) {
56 let new_additions = Arc::new(Mutex::default());
57 let (window, node) = Window::new(0, pa, ui, buffer, new_additions.clone());
58
59 context::set_windows(Self {
60 inner: RwData::new(InnerWindows {
61 layout,
62 list: vec![window.clone()],
63 new_additions,
64 cur_buffer: RwData::new(node.try_downcast().unwrap()),
65 cur_widget: RwData::new(node.clone()),
66 cur_win: 0,
67 buffer_history: BufferHistory::default(),
68 }),
69 spawns_to_remove: Mutex::new(Vec::new()),
70 ui,
71 });
72
73 hook::trigger(
74 pa,
75 WidgetCreated(node.handle().try_downcast::<Buffer>().unwrap()),
76 );
77 hook::trigger(pa, WindowCreated(window));
78 }
79
80 pub(crate) fn new_window(&self, pa: &mut Pass, buffer: Buffer) -> Node {
85 let win = self.inner.read(pa).list.len();
86 let new_additions = self.inner.read(pa).new_additions.clone();
87 let (window, node) = Window::new(win, pa, self.ui, buffer, new_additions);
88
89 let inner = self.inner.write(pa);
90 inner.list.push(window);
91
92 hook::trigger(
93 pa,
94 WidgetCreated(node.handle().try_downcast::<Buffer>().unwrap()),
95 );
96 hook::trigger(pa, WindowCreated(self.inner.read(pa).list[win].clone()));
97
98 node
99 }
100
101 pub(crate) fn push_widget<W: Widget>(
103 &self,
104 pa: &mut Pass,
105 (target, on_buffers, specs): (&RwArea, Option<bool>, PushSpecs),
106 widget: W,
107 master: Option<&RwArea>,
108 ) -> Option<Handle<W>> {
109 self.push(pa, (target, on_buffers, specs), widget, master)?
110 .handle()
111 .try_downcast()
112 }
113
114 pub(crate) fn spawn_on_widget<W: Widget>(
118 &self,
119 pa: &mut Pass,
120 (target, specs): (&RwArea, SpawnSpecs),
121 widget: W,
122 ) -> Option<Handle<W>> {
123 let (win, cluster_master, master) =
124 self.inner
125 .read(pa)
126 .list
127 .iter()
128 .enumerate()
129 .find_map(|(win, window)| {
130 let inner = window.0.read(pa);
131 let master = window.nodes(pa).find_map(|node| {
132 node.area()
133 .area_is_eq(pa, target)
134 .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);
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(
170 pa,
171 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
172 );
173
174 node.handle().try_downcast()
175 }
176
177 pub(crate) fn spawn_on_text<W: Widget>(
179 &self,
180 pa: &mut Pass,
181 (id, specs): (SpawnId, SpawnSpecs),
182 widget: W,
183 win: usize,
184 master: Handle<dyn Widget>,
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_spawned(path.as_ref().map(|p| p.as_ref()), id, specs, win);
193
194 let node = Node::new(widget, spawned, Some(master));
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(
201 pa,
202 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
203 );
204
205 node.handle().try_downcast().unwrap()
206 }
207
208 pub(crate) fn new_buffer(&self, pa: &mut Pass, buffer: Buffer) -> Node {
215 let inner = self.inner.read(pa);
216 let (handle, specs) = inner.layout.lock().unwrap().new_buffer(pa, &inner.list);
217
218 let specs = PushSpecs { cluster: false, ..specs };
219
220 if let Some(master) = handle.area().get_cluster_master(pa) {
221 self.push(pa, (&master, Some(true), specs), buffer, None)
222 .unwrap()
223 } else {
224 self.push(pa, (&handle.area, Some(true), specs), buffer, None)
225 .unwrap()
226 }
227 }
228
229 fn push<W: Widget>(
233 &self,
234 pa: &mut Pass,
235 (target, on_buffers, mut specs): (&RwArea, Option<bool>, PushSpecs),
236 widget: W,
237 master: Option<&RwArea>,
238 ) -> Option<Node> {
239 let inner = self.inner.read(pa);
240 let win = inner
241 .list
242 .iter()
243 .position(|window| {
244 window.0.read(pa).master_area.is_master_of(pa, target)
245 || window
246 .nodes(pa)
247 .any(|node| node.area().is_master_of(pa, target))
248 })
249 .unwrap();
250
251 let inner_window = inner.list[win].0.read(pa);
252 let target_is_on_buffers = inner_window.buffers_area.is_master_of(pa, target);
253
254 let on_buffers = on_buffers.unwrap_or(target_is_on_buffers) && target_is_on_buffers;
255
256 if target_is_on_buffers && !on_buffers {
257 specs.cluster = false;
258 }
259
260 let location = if on_buffers {
261 Location::OnBuffers
262 } else if let Some((id, _)) = inner_window
263 .spawned
264 .iter()
265 .find(|(_, node)| node.area().area_is_eq(pa, target))
266 {
267 Location::Spawned(*id)
268 } else {
269 Location::Regular
270 };
271
272 let widget = RwData::new(widget);
273 let path = widget
274 .read_as::<Buffer>(pa)
275 .and_then(|buffer| buffer.path_set());
276 let (pushed, parent) =
277 target.push(pa, path.as_ref().map(|p| p.as_ref()), specs, on_buffers)?;
278
279 let master = master.and_then(|area| {
280 self.entries(pa).find_map(|(.., node)| {
281 node.area()
282 .area_is_eq(pa, area)
283 .then(|| node.handle().clone())
284 })
285 });
286
287 let node = Node::new(widget, pushed, master);
288
289 let window = self.inner.write(pa).list.remove(win);
290 window.add(pa, node.clone(), parent, location);
291 self.inner.write(pa).list.insert(win, window);
292
293 hook::trigger(
294 pa,
295 WidgetCreated(node.handle().try_downcast::<W>().unwrap()),
296 );
297
298 Some(node)
299 }
300
301 pub(crate) fn close<W: Widget + ?Sized, S>(
305 &self,
306 pa: &mut Pass,
307 handle: &Handle<W, S>,
308 ) -> Result<(), Text> {
309 let win = self.handle_window(pa, handle)?;
310
311 if let Some(buf_handle) = handle.try_downcast::<Buffer>() {
314 hook::trigger(pa, BufferClosed((buf_handle.clone(), Cache::new())));
315
316 let buffers_ahead: Vec<Node> = self.inner.read(pa).list[win]
317 .nodes(pa)
318 .filter(|node| {
319 node.handle().read_as::<Buffer>(pa).is_some_and(|buffer| {
320 buffer.layout_order > buf_handle.read(pa).layout_order
321 })
322 })
323 .cloned()
324 .collect();
325
326 for buffer_ahead in buffers_ahead {
327 self.swap(pa, handle, buffer_ahead.handle())?;
328 }
329 }
330
331 let mut list = std::mem::take(&mut self.inner.write(pa).list);
333
334 if list[win].close(pa, handle) {
335 list.remove(win);
336 self.ui.remove_window(win);
337 let cur_win = context::current_win_index(pa);
338 if cur_win > win {
339 self.inner.write(pa).cur_win -= 1;
340 }
341 }
342
343 let inner = self.inner.write(pa);
344 inner.list = list;
345 inner.new_additions.lock().unwrap().get_or_insert_default();
346
347 let inner = self.inner.read(pa);
349 if handle == inner.cur_widget.read(pa).handle() || handle == inner.cur_buffer.read(pa) {
350 if let Some(handle) = handle.try_downcast::<Buffer>() {
351 self.inner.write(pa).buffer_history.remove(&handle);
352
353 let entry = self
354 .inner
355 .write(pa)
356 .buffer_history
357 .jump_by(handle.clone(), -1)
358 .or_else(|| self.buffers(pa).next())
359 .and_then(|handle| {
360 self.entries(pa).find_map(|(win, node)| {
361 (*node.handle() == handle).then(|| (win, node.clone()))
362 })
363 });
364
365 if let Some((_, node)) = entry {
366 crate::mode::reset_to(node.handle().clone());
367 } else {
368 context::sender()
370 .send(crate::session::DuatEvent::Quit)
371 .unwrap();
372 return Ok(());
373 }
374 } else {
375 crate::mode::reset_to(inner.cur_buffer.read(pa).to_dyn());
376 }
377 }
378
379 Ok(())
380 }
381
382 pub(crate) fn swap<W1: Widget + ?Sized, S1, W2: Widget + ?Sized, S2>(
384 &self,
385 pa: &mut Pass,
386 lhs: &Handle<W1, S1>,
387 rhs: &Handle<W2, S2>,
388 ) -> Result<(), Text> {
389 let lhs_win = self.handle_window(pa, lhs)?;
390 let rhs_win = self.handle_window(pa, rhs)?;
391
392 let [lhs_buffer, rhs_buffer] = [lhs.try_downcast::<Buffer>(), rhs.try_downcast()];
393
394 if let [Some(lhs), Some(rhs)] = [lhs_buffer, rhs_buffer] {
395 let lhs_lo = lhs.read(pa).layout_order;
396 let rhs_lo = std::mem::replace(&mut rhs.write(pa).layout_order, lhs_lo);
397 lhs.write(pa).layout_order = rhs_lo
398 }
399
400 let windows = std::mem::take(&mut self.inner.write(pa).list);
401
402 let lhs_nodes = windows[lhs_win].take_with_related_nodes(pa, lhs);
403 windows[rhs_win].insert_nodes(pa, lhs_nodes);
404
405 let rhs_nodes = windows[rhs_win].take_with_related_nodes(pa, rhs);
406 windows[lhs_win].insert_nodes(pa, rhs_nodes);
407
408 let wins = self.inner.write(pa);
409 wins.list = windows;
410 wins.new_additions.lock().unwrap().get_or_insert_default();
411
412 lhs.area().swap(pa, rhs.area());
413
414 let cur_buffer = context::current_buffer(pa);
415 if lhs_win != rhs_win {
416 if lhs == cur_buffer {
417 self.inner.write(pa).cur_win = lhs_win;
418 self.ui.switch_window(lhs_win);
419 } else if rhs == cur_buffer {
420 self.inner.write(pa).cur_win = rhs_win;
421 self.ui.switch_window(rhs_win);
422 }
423 }
424
425 Ok(())
426 }
427
428 pub(crate) fn open_or_move_to_new_window(
431 &self,
432 pa: &mut Pass,
433 pk: PathKind,
434 default_buffer_cfg: PrintOpts,
435 ) -> Node {
436 let node = match self.buffer_entry(pa, pk.clone()) {
437 Ok((win, handle)) if self.get(pa, win).unwrap().buffers(pa).len() > 1 => {
438 handle.write(pa).layout_order = 0;
440
441 let nodes = {
442 let old_window = self.inner.write(pa).list.remove(win);
443 let nodes = old_window.take_with_related_nodes(pa, &handle.to_dyn());
444 self.inner.write(pa).list.insert(win, old_window);
445
446 nodes
447 };
448
449 let path = handle.read(pa).path_set();
451 let new_root = self.ui.new_root(path.as_ref().map(|p| p.as_ref()));
452 handle.area().swap(pa, &new_root);
453 let window = Window::new_from_raw(
454 pa,
455 win,
456 handle.area.clone(),
457 nodes,
458 self.inner.read(pa).new_additions.clone(),
459 );
460
461 self.inner.write(pa).list.push(window.clone());
462
463 hook::trigger(pa, WindowCreated(window));
464
465 let lo = handle.read(pa).layout_order;
467
468 for handle in &self.inner.read(pa).list[win].buffers(pa)[lo..] {
469 new_root.swap(pa, handle.area());
470 }
471
472 new_root.delete(pa);
475
476 self.inner
477 .write(pa)
478 .new_additions
479 .lock()
480 .unwrap()
481 .get_or_insert_default();
482
483 Node::from_handle(handle)
484 }
485 Ok((.., handle)) => Node::from_handle(handle),
488 Err(_) => self.new_window(pa, Buffer::new(pk.as_path(), default_buffer_cfg)),
489 };
490
491 if context::current_buffer(pa).read(pa).path_kind() != pk {
492 mode::reset_to(node.handle().clone());
493 }
494
495 node
496 }
497
498 pub(crate) fn set_current_node(&self, pa: &mut Pass, node: Node) -> Result<(), Text> {
500 let internal_pass = &mut unsafe { Pass::new() };
503
504 let win = self.handle_window(pa, node.handle())?;
505 let inner = self.inner.write(pa);
506
507 if let Some(handle) = node.try_downcast::<Buffer>() {
508 let current = std::mem::replace(inner.cur_buffer.write(internal_pass), handle.clone());
509 inner.buffer_history.insert(current, handle);
510 }
511 *inner.cur_widget.write(internal_pass) = node.clone();
512 inner.cur_win = win;
513 self.ui.switch_window(win);
514
515 Ok(())
516 }
517
518 pub(crate) fn queue_close_spawned(&self, id: SpawnId) {
522 let mut spawns_to_remove = self.spawns_to_remove.lock().unwrap();
523 if !spawns_to_remove.contains(&id) {
524 spawns_to_remove.push(id)
525 }
526 }
527
528 pub(crate) fn cleanup_despawned(&self, pa: &mut Pass) {
531 let spawns_to_remove = std::mem::take(&mut *self.spawns_to_remove.lock().unwrap());
532 for id in spawns_to_remove {
533 if let Some((_, node)) = self
534 .iter(pa)
535 .flat_map(|window| &window.0.read(pa).spawned)
536 .find(|(other, _)| *other == id)
537 {
538 self.close(pa, &node.handle().clone()).unwrap();
539 }
540 }
541 }
542
543 pub(crate) fn handle_window<W: Widget + ?Sized, S>(
547 &self,
548 pa: &Pass,
549 handle: &Handle<W, S>,
550 ) -> Result<usize, Text> {
551 self.entries(pa)
552 .find_map(|(win, node)| (node.handle() == handle).then_some(win))
553 .ok_or_else(|| txt!("The Handle was already closed"))
554 }
555
556 pub(crate) fn buffer_entry(&self, pa: &Pass, pk: PathKind) -> Result<(usize, Handle), Text> {
558 self.entries(pa)
559 .find_map(|(win, node)| {
560 (node.read_as(pa).filter(|f: &&Buffer| f.path_kind() == pk))
561 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
562 })
563 .ok_or_else(|| txt!("Buffer {pk} not found"))
564 }
565
566 pub(crate) fn named_buffer_entry(
568 &self,
569 pa: &Pass,
570 name: &str,
571 ) -> Result<(usize, Handle), Text> {
572 self.entries(pa)
573 .find_map(|(win, node)| {
574 (node.read_as(pa).filter(|f: &&Buffer| f.name() == name))
575 .and_then(|_| node.try_downcast().map(|handle| (win, handle)))
576 })
577 .ok_or_else(|| txt!("Buffer [buffer]{name}[] not found"))
578 }
579
580 pub(crate) fn node_of<'a, W: Widget>(&'a self, pa: &'a Pass) -> Result<&'a Node, Text> {
585 let handle = context::current_buffer(pa);
586
587 if let Some((handle, _)) = handle.get_related::<W>(pa).next() {
588 self.entries(pa)
589 .find_map(|(.., node)| node.ptr_eq(handle.widget()).then_some(node))
590 } else {
591 let cur_win = self.inner.read(pa).cur_win;
592 let list = &self.inner.read(pa).list;
593 list[cur_win]
594 .nodes(pa)
595 .chain(list[cur_win + 1..].iter().flat_map(|win| win.nodes(pa)))
596 .chain(list[..cur_win].iter().flat_map(|win| win.nodes(pa)))
597 .find(|node| node.data_is::<W>())
598 }
599 .ok_or(txt!("No widget of type [a]{}[] found", type_name::<W>()))
600 }
601
602 pub(crate) fn entries<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = (usize, &'a Node)> {
606 self.inner
607 .read(pa)
608 .list
609 .iter()
610 .enumerate()
611 .flat_map(|(win, window)| {
612 let inner = window.0.read(pa);
613 inner
614 .nodes
615 .iter()
616 .chain(inner.spawned.iter().map(|(_, node)| node))
617 .map(move |node| (win, node))
618 })
619 }
620
621 pub(crate) fn iter_around<'a>(
623 &'a self,
624 pa: &'a Pass,
625 win: usize,
626 wid: usize,
627 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
628 let window_entries =
629 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
630
631 let windows = &self.inner.read(pa).list;
632
633 let prev_len: usize = windows
634 .iter()
635 .take(win)
636 .map(|win| win.len_widgets(pa))
637 .sum();
638
639 windows
640 .iter()
641 .enumerate()
642 .skip(win)
643 .flat_map(window_entries)
644 .skip(wid + 1)
645 .chain(
646 windows
647 .iter()
648 .enumerate()
649 .take(win + 1)
650 .flat_map(window_entries)
651 .take(prev_len + wid),
652 )
653 }
654
655 pub(crate) fn iter_around_rev<'a>(
657 &'a self,
658 pa: &'a Pass,
659 win: usize,
660 wid: usize,
661 ) -> impl Iterator<Item = (usize, &'a Node)> + 'a {
662 let entries =
663 |(w, window): (usize, &'a Window)| window.nodes(pa).map(move |node| (w, node));
664
665 let windows = &self.inner.read(pa).list;
666
667 let next_len: usize = windows
668 .iter()
669 .skip(win)
670 .map(|win| win.len_widgets(pa))
671 .sum();
672
673 windows
674 .iter()
675 .enumerate()
676 .rev()
677 .skip(windows.len() - (win + 1))
678 .flat_map(move |(w, win)| entries((w, win)).rev().skip(win.len_widgets(pa) - wid))
679 .chain(
680 windows
681 .iter()
682 .enumerate()
683 .rev()
684 .take(windows.len() - win)
685 .flat_map(move |(i, win)| entries((i, win)).rev())
686 .take(next_len - (wid + 1)),
687 )
688 }
689
690 pub fn jump_buffers_by(&self, pa: &mut Pass, jumps: i32) {
697 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
698 if let Some(handle) = self.inner.write(pa).buffer_history.jump_by(current, jumps) {
699 mode::reset_to(handle.to_dyn());
700 } else {
701 context::warn!("No buffer [a]{jumps}[] jumps away from the current one");
702 }
703 }
704
705 pub fn last_buffer(&self, pa: &mut Pass) -> Result<Handle, Text> {
709 let current = self.inner.read(pa).cur_buffer.read(pa).clone();
710 if let Some(handle) = self.inner.write(pa).buffer_history.last(current) {
711 mode::reset_to(handle.to_dyn());
712 Ok(handle)
713 } else {
714 Err(txt!("No last buffer"))
715 }
716 }
717
718 pub fn len(&self, pa: &Pass) -> usize {
724 self.inner.read(pa).list.len()
725 }
726
727 pub fn get<'a>(&'a self, pa: &'a Pass, win: usize) -> Option<&'a Window> {
729 self.inner.read(pa).list.get(win)
730 }
731
732 pub fn iter<'a>(&'a self, pa: &'a Pass) -> std::slice::Iter<'a, Window> {
734 self.inner.read(pa).list.iter()
735 }
736
737 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = &'a Handle<dyn Widget>> {
739 self.inner
740 .read(pa)
741 .list
742 .iter()
743 .flat_map(|w| w.nodes(pa).map(|n| n.handle()))
744 }
745
746 pub fn buffers<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = Handle> + 'a {
748 self.inner.read(pa).list.iter().flat_map(|w| w.buffers(pa))
749 }
750
751 pub fn current_window(&self, pa: &Pass) -> usize {
753 self.inner.read(pa).cur_win
754 }
755
756 pub(crate) fn current_buffer<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Handle> {
758 &self.inner.read(pa).cur_buffer
759 }
760
761 pub(crate) fn current_widget<'a>(&'a self, pa: &'a Pass) -> &'a RwData<Node> {
763 &self.inner.read(pa).cur_widget
764 }
765
766 pub(crate) fn get_additions(&self, pa: &mut Pass) -> Option<Vec<(usize, Node)>> {
768 self.inner.write(pa).new_additions.lock().unwrap().take()
769 }
770}
771
772#[derive(Clone)]
777pub struct Window(RwData<InnerWindow>);
778
779struct InnerWindow {
780 index: usize,
781 nodes: Vec<Node>,
782 spawned: Vec<(SpawnId, Node)>,
783 buffers_area: RwArea,
784 master_area: RwArea,
785 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
786}
787
788impl Window {
789 fn new<W: Widget>(
791 index: usize,
792 pa: &mut Pass,
793 ui: Ui,
794 widget: W,
795 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
796 ) -> (Self, Node) {
797 let widget = RwData::new(widget);
798 let path = if let Some(buffer) = widget.write_as::<Buffer>(pa) {
799 buffer.layout_order = get_layout_order();
800 buffer.path_set()
801 } else {
802 None
803 };
804
805 let area = ui.new_root(path.as_ref().map(|p| p.as_ref()));
806 let node = Node::new::<W>(widget, area.clone(), None);
807
808 new_additions
809 .lock()
810 .unwrap()
811 .get_or_insert_default()
812 .push((index, node.clone()));
813
814 let window = Self(RwData::new(InnerWindow {
815 index,
816 nodes: vec![node.clone()],
817 spawned: Vec::new(),
818 buffers_area: area.clone(),
819 master_area: area.clone(),
820 new_additions,
821 }));
822
823 (window, node)
824 }
825
826 pub(crate) fn new_from_raw(
828 pa: &mut Pass,
829 index: usize,
830 master_area: RwArea,
831 nodes: Vec<Node>,
832 new_additions: Arc<Mutex<Option<Vec<(usize, Node)>>>>,
833 ) -> Self {
834 let master_area = master_area
835 .get_cluster_master(pa)
836 .unwrap_or(master_area.clone());
837
838 Self(RwData::new(InnerWindow {
839 index,
840 nodes,
841 spawned: Vec::new(),
842 buffers_area: master_area.clone(),
843 master_area,
844 new_additions,
845 }))
846 }
847
848 pub fn push_inner<W: Widget>(
903 &self,
904 pa: &mut Pass,
905 widget: W,
906 mut specs: PushSpecs,
907 ) -> Handle<W> {
908 let target = self.0.read(pa).buffers_area.clone();
909
910 specs.cluster = false;
911
912 context::windows()
913 .push_widget(pa, (&target, Some(false), specs), widget, None)
914 .unwrap()
915 }
916
917 pub fn push_outer<W: Widget>(
919 &self,
920 pa: &mut Pass,
921 widget: W,
922 mut specs: PushSpecs,
923 ) -> Handle<W> {
924 let target = self.0.read(pa).master_area.clone();
925
926 specs.cluster = false;
927
928 context::windows()
929 .push_widget(pa, (&target, Some(false), specs), widget, None)
930 .unwrap()
931 }
932
933 fn add(&self, pa: &mut Pass, node: Node, parent: Option<RwArea>, location: Location) {
935 match location {
936 Location::OnBuffers => {
937 self.0.write(pa).nodes.push(node.clone());
938 if let Some(parent) = &parent
939 && parent.is_master_of(pa, &self.0.read(pa).buffers_area)
940 {
941 self.0.write(pa).buffers_area = parent.clone()
942 }
943 }
944 Location::Regular => self.0.write(pa).nodes.push(node.clone()),
945 Location::Spawned(id) => self.0.write(pa).spawned.push((id, node.clone())),
946 }
947
948 if let Some(parent) = &parent
949 && parent.is_master_of(pa, &self.0.read(pa).master_area)
950 {
951 self.0.write(pa).master_area = parent.clone()
952 }
953
954 let inner = self.0.write(pa);
955 inner
956 .new_additions
957 .lock()
958 .unwrap()
959 .get_or_insert_default()
960 .push((inner.index, node.clone()));
961 }
962
963 fn close<W: Widget + ?Sized, S>(&self, pa: &mut Pass, handle: &Handle<W, S>) -> bool {
967 let handle_eq = |node: &mut Node| node.handle() == handle;
968
969 let inner = self.0.write(pa);
970
971 let node = if let Some(node) = inner.nodes.extract_if(.., handle_eq).next() {
972 node
973 } else if let Some((_, node)) = inner.spawned.extract_if(.., |(_, n)| handle_eq(n)).next() {
974 node
975 } else {
976 unreachable!("This isn't supposed to fail");
977 };
978
979 node.handle().declare_closed(pa);
980
981 let (do_rm_window, rm_areas) = node.area().delete(pa);
982 if do_rm_window {
983 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
984 handle.declare_closed(pa);
985 }
986 return true;
987 }
988
989 let (mut nodes, mut spawned) = {
990 let inner = self.0.write(pa);
991 let nodes = std::mem::take(&mut inner.nodes);
992 let spawned = std::mem::take(&mut inner.spawned);
993 (nodes, spawned)
994 };
995
996 nodes.retain(|node| {
997 if rm_areas
998 .iter()
999 .any(|a| a.area_is_eq(pa, node.handle().area()))
1000 {
1001 node.handle().declare_closed(pa);
1002 false
1003 } else {
1004 true
1005 }
1006 });
1007 spawned.retain(|(_, node)| {
1008 if rm_areas
1009 .iter()
1010 .any(|a| a.area_is_eq(pa, node.handle().area()))
1011 {
1012 node.handle().declare_closed(pa);
1013 false
1014 } else {
1015 true
1016 }
1017 });
1018
1019 let inner = self.0.write(pa);
1020 inner.nodes = nodes;
1021 inner.spawned = spawned;
1022
1023 let buffers = self.buffers(pa);
1024 if buffers.len() == 1 {
1025 let handle = buffers.first().unwrap();
1026
1027 let master_area = handle
1028 .area()
1029 .get_cluster_master(pa)
1030 .unwrap_or(handle.area.clone());
1031
1032 self.0.write(pa).buffers_area = master_area;
1033 }
1034
1035 if self.buffers(pa).is_empty() {
1036 for handle in self.handles(pa).cloned().collect::<Vec<_>>() {
1037 handle.declare_closed(pa);
1038 }
1039 true
1040 } else {
1041 false
1042 }
1043 }
1044
1045 fn take_with_related_nodes<W: Widget + ?Sized, S>(
1047 &self,
1048 pa: &mut Pass,
1049 handle: &Handle<W, S>,
1050 ) -> Vec<Node> {
1051 let related = handle.related();
1052
1053 let (related, inner) = pa.read_and_write(related, &self.0);
1054
1055 inner
1056 .nodes
1057 .extract_if(.., |node| {
1058 related.iter().any(|(handle, _)| handle == node.handle()) || node.handle() == handle
1059 })
1060 .collect()
1061 }
1062
1063 fn insert_nodes(&self, pa: &mut Pass, nodes: Vec<Node>) {
1065 self.0.write(pa).nodes.extend(nodes);
1066 }
1067
1068 #[define_opaque(InnerIter)]
1072 pub(crate) fn nodes<'a>(
1073 &'a self,
1074 pa: &'a Pass,
1075 ) -> impl ExactSizeIterator<Item = &'a Node> + DoubleEndedIterator {
1076 struct InnerChain<'a>(InnerIter<'a>, usize);
1077
1078 impl<'a> Iterator for InnerChain<'a> {
1079 type Item = &'a Node;
1080
1081 fn next(&mut self) -> Option<Self::Item> {
1082 self.0.next()
1083 }
1084 }
1085
1086 impl<'a> DoubleEndedIterator for InnerChain<'a> {
1087 fn next_back(&mut self) -> Option<Self::Item> {
1088 self.0.next_back()
1089 }
1090 }
1091
1092 impl<'a> ExactSizeIterator for InnerChain<'a> {
1093 fn len(&self) -> usize {
1094 self.1
1095 }
1096 }
1097
1098 let inner = self.0.read(pa);
1099 InnerChain(
1100 inner
1101 .nodes
1102 .iter()
1103 .chain(inner.spawned.iter().map(|(_, node)| node)),
1104 inner.nodes.len() + inner.spawned.len(),
1105 )
1106 }
1107
1108 pub fn handles<'a>(&'a self, pa: &'a Pass) -> impl Iterator<Item = &'a Handle<dyn Widget>> {
1117 self.nodes(pa).map(|node| node.handle())
1118 }
1119
1120 pub fn buffers(&self, pa: &Pass) -> Vec<Handle> {
1132 let inner = self.0.read(pa);
1133 let mut buffers: Vec<Handle> = inner
1134 .nodes
1135 .iter()
1136 .filter_map(|node| node.try_downcast())
1137 .collect();
1138
1139 buffers.sort_unstable_by_key(|buffer| buffer.read(pa).layout_order);
1140
1141 buffers.extend(
1142 inner
1143 .spawned
1144 .iter()
1145 .filter_map(|(_, node)| node.try_downcast()),
1146 );
1147
1148 buffers
1149 }
1150
1151 pub(crate) fn len_widgets(&self, pa: &Pass) -> usize {
1153 let inner = self.0.read(pa);
1154 inner.nodes.len() + inner.spawned.len()
1155 }
1156}
1157
1158#[derive(Default)]
1159struct BufferHistory {
1160 current_i: usize,
1161 list: Vec<Handle>,
1162 last: Option<Handle>,
1163}
1164
1165impl BufferHistory {
1166 fn jump_by(&mut self, current: Handle, by: i32) -> Option<Handle> {
1168 let new_i = self
1169 .current_i
1170 .saturating_add_signed(by as isize)
1171 .min(self.list.len());
1172 let new_handle = self.list.get(new_i)?.clone();
1173
1174 self.last = Some(current);
1175 self.current_i = new_i;
1176 Some(new_handle)
1177 }
1178
1179 fn last(&mut self, current: Handle) -> Option<Handle> {
1184 if let Some(last) = self.last.as_mut() {
1185 Some(std::mem::replace(last, current))
1186 } else if let Some(last) = self.list.get(self.current_i.checked_sub(1)?) {
1187 self.last = Some(current);
1188 Some(last.clone())
1189 } else {
1190 None
1191 }
1192 }
1193
1194 fn insert(&mut self, current: Handle, handle: Handle) {
1197 if self
1198 .current_i
1199 .checked_sub(1)
1200 .is_none_or(|prev_i| self.list[prev_i] != handle)
1201 && self
1202 .list
1203 .get(self.current_i)
1204 .is_none_or(|other| *other != handle)
1205 {
1206 self.list.insert(self.current_i, handle);
1207 self.last = Some(current);
1208 self.current_i += 1;
1209 }
1210 }
1211
1212 fn remove(&mut self, handle: &Handle) {
1215 let mut i = 0;
1216 self.list.retain(|other| {
1217 if other == handle {
1218 if i < self.current_i {
1219 self.current_i -= 1;
1220 }
1221 false
1222 } else {
1223 i += 1;
1224 true
1225 }
1226 });
1227 }
1228}
1229
1230fn get_layout_order() -> usize {
1233 use std::sync::atomic::{AtomicUsize, Ordering};
1234
1235 static LAYOUT_ORDER: AtomicUsize = AtomicUsize::new(0);
1236 LAYOUT_ORDER.fetch_add(1, Ordering::Relaxed)
1237}
1238
1239enum Location {
1240 OnBuffers,
1241 Regular,
1242 Spawned(SpawnId),
1243}
1244
1245type InnerIter<'a> = impl DoubleEndedIterator<Item = &'a Node>;