kui_core/runtime/fills.rs
1//! Slots on the core's side:
2//! declaring one (`begin_slot`), and the bounded, namespaced fill an
3//! extension draws into (`fill`). The loop over extensions is
4//! `crate::slot`'s; what is here is what only the core can do, because
5//! it owns the node stack and the keys.
6
7use super::*;
8use crate::slot::Slot;
9
10impl Core {
11 /// Declares a slot under its full name at the cursor and returns its
12 /// key — `parent.str(name)`, recorded for `key_of` — or `None` when it
13 /// cannot be declared: outside a frame, or a second time in one
14 /// frame, which is the `duplicate-slot` warning.
15 ///
16 /// An extension may declare one too, and its key nests under the slot
17 /// the extension is itself filling, like any of its nodes. Names stay
18 /// frame-wide because namespaces are: there is one extension called
19 /// `todos` however deep the thing that loaded it sat, so `todos/panel`
20 /// is one slot and declaring it twice is the same warning wherever
21 /// the two declarations came from.
22 pub fn begin_slot(&mut self, name: &str) -> Option<Key> {
23 if self.tree.is_empty() {
24 return None;
25 }
26 if self.slot_labels.find(name).next().is_some() {
27 self.diag.raise(crate::diag::duplicate_slot(name));
28 return None;
29 }
30 let key = self.parent_key().str(name);
31 self.slot_labels.push(key, name, self.origin);
32 self.key_labels.push(key, name, self.origin);
33 Some(key)
34 }
35
36 /// Whether the full name `name` was declared this frame so far — or
37 /// is the slot of a devtools tab declared this frame, which counts
38 /// whether or not the panel mounted it, so a plugin whose only slot
39 /// is a tab is quiet with the panel off.
40 pub fn slot_declared(&self, name: &str) -> bool {
41 self.slot_labels.find(name).next().is_some() || self.devtools_tab_slot(name)
42 }
43
44 /// Runs `f` as the fill of `slot` under `origin`: every node it opens
45 /// is tagged `origin`, keyed as a child of `slot.key` (an extension's keys depend on the slot's
46 /// full name, which the host's namespace makes its own, and on
47 /// nothing the host built around them), counted from zero, and
48 /// closed for it if it returns with any open (decision 5, with the
49 /// `unbalanced-extension` warning). The host's origin, counter and
50 /// namespace are what they were when `f` returns, so the host's next
51 /// child is keyed as if the fill had not happened.
52 pub fn fill(&mut self, slot: &Slot<'_>, origin: OriginId, f: impl FnOnce(&mut Ui<'_>)) {
53 self.fill_within(slot, origin, None, f);
54 }
55
56 /// `fill`, with `filler` answering the slots the fill itself declares
57 /// — what `Extensions::fill_one` hands in, so an extension can host
58 /// extensions of its own (see `crate::slot`). `None` is plain `fill`:
59 /// nothing answers, so a slot declared inside draws nothing.
60 pub fn fill_within(
61 &mut self,
62 slot: &Slot<'_>,
63 origin: OriginId,
64 filler: Option<&mut dyn crate::slot::Fill>,
65 f: impl FnOnce(&mut Ui<'_>),
66 ) {
67 if self.tree.is_empty() {
68 return;
69 }
70 let depth = self.stack.len();
71 let saved_counter = self.counters.last().copied().unwrap_or(0);
72 if let Some(c) = self.counters.last_mut() {
73 *c = 0;
74 }
75 let saved_origin = self.origin;
76 let saved_ns = (self.ns_depth, self.ns_key);
77 self.origin = origin;
78 self.ns_depth = depth;
79 self.ns_key = slot.key;
80 let first = self.tree.len() as u32;
81
82 match filler {
83 Some(filler) => f(&mut Ui::with_filler(self, filler)),
84 None => f(&mut Ui::new(self)),
85 }
86 // After the fills inside it, so the innermost is found first.
87 self.tree
88 .fills
89 .push((slot.key, first, self.tree.len() as u32));
90
91 if self.stack.len() > depth {
92 let open = self.stack.len() - depth;
93 self.diag.raise(crate::diag::unbalanced_extension(
94 &slot.full_name(),
95 slot.key,
96 open,
97 ));
98 self.stack.truncate(depth);
99 self.counters.truncate(depth);
100 }
101 if let Some(c) = self.counters.last_mut() {
102 *c = saved_counter;
103 }
104 self.origin = saved_origin;
105 (self.ns_depth, self.ns_key) = saved_ns;
106 }
107}