Files
pages-tui/src/orchestrator/router.rs
filipriec_vm ad9bb78fc8 orchestrator
2026-01-12 00:59:05 +01:00

257 lines
6.7 KiB
Rust

// path_from_the_root: src/orchestrator/router.rs
extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
#[cfg(feature = "alloc")]
use hashbrown::HashMap;
use crate::component::Component;
use crate::focus::{FocusError, FocusManager};
#[derive(Debug, Clone)]
pub enum RouterEvent {
Navigated { from: Option<String>, to: String },
Back { to: String },
Forward { to: String },
}
pub struct Router<C: Component> {
#[cfg(feature = "alloc")]
pages: HashMap<String, C>,
#[cfg(not(feature = "alloc"))]
pages: Vec<(String, C)>,
current: Option<String>,
history: Vec<String>,
future: Vec<String>,
focus: FocusManager<C::Focus>,
}
impl<C: Component> Default for Router<C> {
fn default() -> Self {
Self::new()
}
}
impl<C: Component> Router<C> {
pub fn new() -> Self {
Self {
#[cfg(feature = "alloc")]
pages: HashMap::new(),
#[cfg(not(feature = "alloc"))]
pages: Vec::new(),
current: None,
history: Vec::new(),
future: Vec::new(),
focus: FocusManager::new(),
}
}
pub fn register(&mut self, id: String, mut page: C) {
#[cfg(feature = "alloc")]
{
if self.current.as_ref() == Some(&id) {
let _ = page.on_enter();
let targets = page.targets();
self.focus.set_targets(targets.to_vec());
}
self.pages.insert(id, page);
}
#[cfg(not(feature = "alloc"))]
{
if self.current.as_ref() == Some(&id) {
let _ = page.on_enter();
let targets = page.targets();
self.focus.set_targets(targets.to_vec());
}
self.pages.push((id, page));
}
}
fn get_page_mut(&mut self, id: &str) -> Option<&mut C> {
#[cfg(feature = "alloc")]
{
self.pages.get_mut(id)
}
#[cfg(not(feature = "alloc"))]
{
self.pages
.iter_mut()
.find(|(page_id, _)| page_id == id)
.map(|(_, page)| page)
}
}
fn get_page(&self, id: &str) -> Option<&C> {
#[cfg(feature = "alloc")]
{
self.pages.get(id)
}
#[cfg(not(feature = "alloc"))]
{
self.pages
.iter()
.find(|(page_id, _)| page_id == id)
.map(|(_, page)| page)
}
}
pub fn navigate(&mut self, id: String) -> Result<Option<RouterEvent>, FocusError> {
let result = if let Some(current_id) = self.current.take() {
if let Some(current_page) = self.get_page_mut(&current_id) {
let _ = current_page.on_exit();
}
self.history.push(current_id.clone());
self.future.clear();
Some(RouterEvent::Navigated {
from: Some(current_id),
to: id.clone(),
})
} else {
Some(RouterEvent::Navigated {
from: None,
to: id.clone(),
})
};
let targets = if let Some(page) = self.get_page_mut(&id) {
let _ = page.on_enter();
Some(page.targets().to_vec())
} else {
None
};
if let Some(targets) = targets {
self.focus.set_targets(targets);
}
self.current = Some(id);
Ok(result)
}
pub fn back(&mut self) -> Result<Option<RouterEvent>, FocusError> {
if let Some(current) = self.current.take() {
if let Some(from) = self.history.pop() {
self.future.push(current.clone());
let to = from.clone();
if let Some(current_page) = self.get_page_mut(&current) {
let _ = current_page.on_exit();
}
self.current = Some(to.clone());
let targets = if let Some(page) = self.get_page_mut(&to) {
let _ = page.on_enter();
Some(page.targets().to_vec())
} else {
None
};
if let Some(targets) = targets {
self.focus.set_targets(targets);
}
Ok(Some(RouterEvent::Back { to }))
} else {
self.current = Some(current);
Ok(None)
}
} else {
Ok(None)
}
}
pub fn forward(&mut self) -> Result<Option<RouterEvent>, FocusError> {
if let Some(current) = self.current.take() {
if let Some(from) = self.future.pop() {
self.history.push(current.clone());
let to = from.clone();
if let Some(current_page) = self.get_page_mut(&current) {
let _ = current_page.on_exit();
}
self.current = Some(to.clone());
let targets = if let Some(page) = self.get_page_mut(&to) {
let _ = page.on_enter();
Some(page.targets().to_vec())
} else {
None
};
if let Some(targets) = targets {
self.focus.set_targets(targets);
}
Ok(Some(RouterEvent::Forward { to }))
} else {
self.current = Some(current);
Ok(None)
}
} else {
Ok(None)
}
}
pub fn current(&self) -> Option<&C> {
self.current.as_ref().and_then(|id| self.get_page(id))
}
pub fn current_mut(&mut self) -> Option<&mut C> {
if let Some(id) = self.current.clone() {
self.get_page_mut(&id)
} else {
None
}
}
pub fn current_id(&self) -> Option<&String> {
self.current.as_ref()
}
pub fn focus_manager(&self) -> &FocusManager<C::Focus> {
&self.focus
}
pub fn focus_manager_mut(&mut self) -> &mut FocusManager<C::Focus> {
&mut self.focus
}
pub fn history(&self) -> &[String] {
&self.history
}
pub fn future(&self) -> &[String] {
&self.future
}
pub fn page_count(&self) -> usize {
#[cfg(feature = "alloc")]
{
self.pages.len()
}
#[cfg(not(feature = "alloc"))]
{
self.pages.len()
}
}
pub fn has_page(&self, id: &str) -> bool {
#[cfg(feature = "alloc")]
{
self.pages.contains_key(id)
}
#[cfg(not(feature = "alloc"))]
{
self.pages.iter().any(|(page_id, _)| page_id == id)
}
}
}