//! Taking a component's structure from its source file while the app runs. //! //! The interpreter lives above this crate, so the tree cannot own a dev mount //! directly. It owns this trait instead: something that, when polled, may //! rebuild the tree from a file that changed. The shell polls it on every //! wake, which is the whole of the plumbing an application needs — no branch //! in `main`, no per-frame call to remember. use crate::widget::WidgetTree; /// A source of live structure, polled by the shell. pub trait LiveReload: 'static { /// Apply any pending source change. Returns true if the tree was rebuilt. fn poll(&mut self, tree: &mut WidgetTree) -> bool; /// Install the callback that wakes the event loop from whatever thread /// notices a change. Without one, a reload waits for the next natural /// wakeup — input, a resize — instead of appearing as you save. fn set_waker(&mut self, wake: Box); } impl WidgetTree { /// Take structure from `source` as well as from whatever is already /// installed. /// /// Plural on purpose. A tree can hold more than one mounted component — /// a sidebar and a panel from two different files is an ordinary shape — /// and each takes its structure from its own source. A single slot would /// mean the second mount silently stopped the first from reloading, which /// is a trap rather than a policy. pub fn set_live_reload(&mut self, source: impl LiveReload) { self.live.push(Box::new(source)); } /// Whether this tree is taking its structure from any live source. pub fn is_live(&self) -> bool { !self.live.is_empty() } /// How many live sources this tree holds — one per live mount. pub fn live_sources(&self) -> usize { self.live.len() } /// Apply any pending source change; true if the tree was rebuilt. /// /// The hooks are moved out for the call, because rebuilding needs the /// whole tree and they are part of it — the same borrow dance event /// handlers do. Hooks installed *during* a poll are kept: a reload that /// mounts something live is the newer truth, not a thing to discard. pub fn poll_live_reload(&mut self) -> bool { if self.live.is_empty() { return false; } let mut hooks = std::mem::take(&mut self.live); let mut reloaded = false; for hook in &mut hooks { reloaded |= hook.poll(self); } hooks.append(&mut self.live); self.live = hooks; reloaded } /// Give every live source a way to wake the event loop. pub fn connect_live_waker(&mut self, wake: impl Fn() + Send + Clone + 'static) { for live in &mut self.live { live.set_waker(Box::new(wake.clone())); } } }