Files
Cagire/src/state/ui.rs

162 lines
4.3 KiB
Rust

use std::cell::RefCell;
use std::time::{Duration, Instant};
use cagire_ratatui::Sparkles;
use tachyonfx::{fx, Effect, EffectManager, Interpolation};
use crate::page::Page;
use crate::state::effects::FxId;
use crate::state::{ColorScheme, Modal};
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum MinimapMode {
#[default]
Hidden,
Timed(Instant),
Sticky,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum FlashKind {
#[default]
Success,
Error,
Info,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum DictFocus {
#[default]
Categories,
Words,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum HelpFocus {
#[default]
Topics,
Content,
}
pub struct UiState {
pub sparkles: Sparkles,
pub status_message: Option<String>,
pub flash_until: Option<Instant>,
pub flash_kind: FlashKind,
pub modal: Modal,
pub help_focus: HelpFocus,
pub help_topic: usize,
pub help_scrolls: Vec<usize>,
pub help_search_active: bool,
pub help_search_query: String,
pub dict_focus: DictFocus,
pub dict_category: usize,
pub dict_scrolls: Vec<usize>,
pub dict_search_query: String,
pub dict_search_active: bool,
pub show_title: bool,
pub runtime_highlight: bool,
pub show_completion: bool,
pub minimap: MinimapMode,
pub color_scheme: ColorScheme,
pub hue_rotation: f32,
pub effects: RefCell<EffectManager<FxId>>,
pub modal_fx: RefCell<Option<Effect>>,
pub title_fx: RefCell<Option<Effect>>,
pub prev_modal_open: bool,
pub prev_page: Page,
pub prev_show_title: bool,
}
impl Default for UiState {
fn default() -> Self {
Self {
sparkles: Sparkles::default(),
status_message: None,
flash_until: None,
flash_kind: FlashKind::Success,
modal: Modal::None,
help_focus: HelpFocus::default(),
help_topic: 0,
help_scrolls: vec![0; crate::model::docs::topic_count()],
help_search_active: false,
help_search_query: String::new(),
dict_focus: DictFocus::default(),
dict_category: 0,
dict_scrolls: vec![0; crate::model::categories::category_count()],
dict_search_query: String::new(),
dict_search_active: false,
show_title: true,
runtime_highlight: false,
show_completion: true,
minimap: MinimapMode::Hidden,
color_scheme: ColorScheme::default(),
hue_rotation: 0.0,
effects: RefCell::new(EffectManager::default()),
modal_fx: RefCell::new(None),
title_fx: RefCell::new(Some(fx::coalesce((400, Interpolation::QuadOut)))),
prev_modal_open: false,
prev_page: Page::default(),
prev_show_title: true,
}
}
}
impl UiState {
pub fn help_scroll(&self) -> usize {
self.help_scrolls[self.help_topic]
}
pub fn help_scroll_mut(&mut self) -> &mut usize {
&mut self.help_scrolls[self.help_topic]
}
pub fn dict_scroll(&self) -> usize {
self.dict_scrolls[self.dict_category]
}
pub fn dict_scroll_mut(&mut self) -> &mut usize {
&mut self.dict_scrolls[self.dict_category]
}
pub fn flash(&mut self, msg: &str, duration_ms: u64, kind: FlashKind) {
self.status_message = Some(msg.to_string());
self.flash_until = Some(Instant::now() + Duration::from_millis(duration_ms));
self.flash_kind = kind;
}
pub fn flash_kind(&self) -> Option<FlashKind> {
if self.is_flashing() {
Some(self.flash_kind)
} else {
None
}
}
pub fn set_status(&mut self, msg: String) {
self.status_message = Some(msg);
}
pub fn clear_status(&mut self) {
self.status_message = None;
}
pub fn is_flashing(&self) -> bool {
self.flash_until
.map(|t| Instant::now() < t)
.unwrap_or(false)
}
pub fn show_minimap(&self) -> bool {
match self.minimap {
MinimapMode::Hidden => false,
MinimapMode::Timed(until) => Instant::now() < until,
MinimapMode::Sticky => true,
}
}
pub fn dismiss_minimap(&mut self) {
self.minimap = MinimapMode::Hidden;
}
}