use std::collections::HashMap;
use iced::{Task, Theme, window};
use toddy_core::extensions::ExtensionDispatcher;
use toddy_core::message::Message;
use toddy_core::protocol::OutgoingEvent;
use super::constants::*;
use super::emitters;
use super::window_map;
pub(super) fn validate_scale_factor(sf: f32) -> f32 {
if sf <= 0.0 || !sf.is_finite() {
log::warn!("invalid scale_factor {sf}, using 1.0");
1.0
} else {
sf
}
}
pub(super) struct App {
pub(super) core: toddy_core::engine::Core,
pub(super) theme: Theme,
pub(super) pending_tasks: Vec<Task<Message>>,
pub(super) windows: window_map::WindowMap,
pub(super) image_registry: toddy_core::image_registry::ImageRegistry,
pub(super) system_theme: Theme,
pub(super) theme_follows_system: bool,
pub(super) scale_factor: f32,
pub(super) last_slide_values: HashMap<String, f64>,
pub(super) dispatcher: ExtensionDispatcher,
}
impl App {
pub(super) fn new(dispatcher: ExtensionDispatcher) -> Self {
Self {
core: toddy_core::engine::Core::new(),
theme: DEFAULT_THEME,
pending_tasks: Vec::new(),
windows: window_map::WindowMap::new(),
image_registry: toddy_core::image_registry::ImageRegistry::new(),
system_theme: DEFAULT_THEME,
theme_follows_system: false,
scale_factor: 1.0,
last_slide_values: HashMap::new(),
dispatcher,
}
}
pub(super) fn title_for_window(&self, window_id: window::Id) -> String {
if let Some(toddy_id) = self.windows.get_toddy(&window_id)
&& let Some(node) = self.core.tree.find_window(toddy_id)
&& let Some(title) = node.props.get("title").and_then(|v| v.as_str())
{
return title.chars().filter(|c| !c.is_control()).collect();
}
DEFAULT_WINDOW_TITLE.to_string()
}
pub(super) fn theme_for_window(&self, window_id: window::Id) -> Theme {
self.theme_ref_for_window(window_id).clone()
}
pub(super) fn theme_ref_for_window(&self, window_id: window::Id) -> &Theme {
if let Some(toddy_id) = self.windows.get_toddy(&window_id)
&& let Some(cached) = self.windows.cached_theme(toddy_id)
{
return cached;
}
if self.theme_follows_system {
&self.system_theme
} else {
&self.theme
}
}
pub(super) fn scale_factor_for_window(&self, window_id: window::Id) -> f32 {
let sf = self
.windows
.get_toddy(&window_id)
.and_then(|jid| self.core.tree.find_window(jid))
.and_then(|node| node.props.get("scale_factor"))
.and_then(|v| v.as_f64())
.map(|v| v as f32)
.unwrap_or(self.scale_factor);
validate_scale_factor(sf)
}
pub(super) fn emit_subscription(
&self,
key: &str,
captured: bool,
event_fn: impl FnOnce(String) -> OutgoingEvent,
) -> Task<Message> {
let tag = self
.core
.active_subscriptions
.get(key)
.or_else(|| self.core.active_subscriptions.get(SUB_EVENT));
if let Some(tag) = tag {
emitters::emit_or_exit(event_fn(tag.clone()).with_captured(captured))
} else {
Task::none()
}
}
}