My personal-knowledge-system, with deeply integrated task tracking and long term goal planning capabilities.
1use crossterm::event::{KeyEvent, MouseEvent};
2use ratatui::{
3 Frame,
4 layout::{Rect, Size},
5};
6use tokio::sync::mpsc::UnboundedSender;
7
8use crate::{config::Config, signal::Signal, tui::Event};
9
10/// `Component` is a trait that represents a visual and interactive element of the user interface.
11///
12/// Implementers of this trait can be registered with the main application loop and will be able to
13/// receive events, update state, and be rendered on the screen.
14pub trait Component: Send {
15 /// Register a signal handler that can send signals for processing if necessary.
16 ///
17 /// # Arguments
18 ///
19 /// * `tx` - An unbounded sender that can send signals.
20 ///
21 /// # Returns
22 ///
23 /// * [`color_eyre::Result<()>`] - An Ok result or an error.
24 fn register_signal_handler(&mut self, tx: UnboundedSender<Signal>) -> color_eyre::Result<()> {
25 let _ = tx; // to appease clippy
26 Ok(())
27 }
28 /// Register a configuration handler that provides configuration settings if necessary.
29 ///
30 /// # Arguments
31 ///
32 /// * `config` - Configuration settings.
33 ///
34 /// # Returns
35 ///
36 /// * [`color_eyre::Result<()>`] - An Ok result or an error.
37 fn register_config_handler(&mut self, config: Config) -> color_eyre::Result<()> {
38 let _ = config; // to appease clippy
39 Ok(())
40 }
41 /// Initialize the component with a specified area if necessary.
42 ///
43 /// # Arguments
44 ///
45 /// * `area` - Rectangular area to initialize the component within.
46 ///
47 /// # Returns
48 ///
49 /// * [`color_eyre::Result<()>`] - An Ok result or an error.
50 fn init(&mut self, area: Size) -> color_eyre::Result<()> {
51 let _ = area; // to appease clippy
52 Ok(())
53 }
54 /// Handle incoming events and produce signals if necessary.
55 ///
56 /// # Arguments
57 ///
58 /// * `event` - An optional event to be processed.
59 ///
60 /// # Returns
61 ///
62 /// * [`color_eyre::Result<Option<signal>>`] - A signal to be processed or none.
63 fn handle_events(&mut self, event: Option<Event>) -> color_eyre::Result<Option<Signal>> {
64 let signal = match event {
65 Some(Event::Key(key_event)) => self.handle_key_event(key_event)?,
66 Some(Event::Mouse(mouse_event)) => self.handle_mouse_event(mouse_event)?,
67 _ => None,
68 };
69 Ok(signal)
70 }
71 /// Handle key events and produce signals if necessary.
72 ///
73 /// # Arguments
74 ///
75 /// * `key` - A key event to be processed.
76 ///
77 /// # Returns
78 ///
79 /// * [`color_eyre::Result<Option<signal>>`] - A signal to be processed or none.
80 fn handle_key_event(&mut self, key: KeyEvent) -> color_eyre::Result<Option<Signal>> {
81 let _ = key; // to appease clippy
82 Ok(None)
83 }
84 /// Handle mouse events and produce signals if necessary.
85 ///
86 /// # Arguments
87 ///
88 /// * `mouse` - A mouse event to be processed.
89 ///
90 /// # Returns
91 ///
92 /// * [`color_eyre::Result<Option<signal>>`] - A signal to be processed or none.
93 fn handle_mouse_event(&mut self, mouse: MouseEvent) -> color_eyre::Result<Option<Signal>> {
94 let _ = mouse; // to appease clippy
95 Ok(None)
96 }
97 /// Update the state of the component based on a received signal. (REQUIRED)
98 ///
99 /// # Arguments
100 ///
101 /// * `signal` - A signal that may modify the state of the component.
102 ///
103 /// # Returns
104 ///
105 /// * [`color_eyre::Result<Option<signal>>`] - A signal to be processed or none.
106 fn update(&mut self, signal: Signal) -> color_eyre::Result<Option<Signal>>;
107
108 /// Render the component on the screen. (REQUIRED)
109 ///
110 /// # Arguments
111 ///
112 /// * `f` - A frame used for rendering.
113 /// * `area` - The area in which the component should be drawn.
114 ///
115 /// # Returns
116 ///
117 /// * [`color_eyre::Result<()>`] - An Ok result or an error.
118 fn draw(&mut self, frame: &mut Frame, area: Rect) -> color_eyre::Result<()>;
119}