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