santui_core/event.rs
1use std::collections::VecDeque;
2
3/// Events that can be published through the application's [`EventBus`].
4#[derive(Clone, Debug, PartialEq)]
5pub enum Event {
6 /// The active theme changed (plugins should refresh their colours).
7 ThemeChanged,
8 /// The current user signed in or out (plugins should refresh their state).
9 UserUpdated,
10 /// Plugin-to-plugin message. `from` and `to` are plugin ids.
11 PluginMessage {
12 from: String,
13 to: String,
14 action: String,
15 data: String,
16 },
17}
18
19/// A simple in-app event bus for decoupling components.
20///
21/// Components emit events via [`EventBus::emit`] and the main loop drains the
22/// pending queue via [`EventBus::drain`] once per frame, forwarding them to
23/// [`PluginManager::process_events`](crate::app::plugin_manager::PluginManager).
24///
25/// The pending queue is capped at [`MAX_PENDING`] entries. If full, the oldest
26/// event is dropped to make room for the newest, ensuring the bus never grows
27/// without bound.
28#[derive(Debug, Default)]
29pub struct EventBus {
30 pending: VecDeque<Event>,
31}
32
33const MAX_PENDING: usize = 1024;
34
35impl EventBus {
36 pub fn new() -> Self {
37 Self {
38 pending: VecDeque::new(),
39 }
40 }
41
42 /// Push an event onto the pending queue.
43 ///
44 /// If the queue is at capacity the oldest event is dropped.
45 pub fn emit(&mut self, event: Event) {
46 if self.pending.len() >= MAX_PENDING {
47 self.pending.pop_front();
48 }
49 self.pending.push_back(event);
50 }
51
52 /// Drain all pending events.
53 pub fn drain(&mut self) -> Vec<Event> {
54 self.pending.drain(..).collect()
55 }
56}