use iced::widget::{column, container}; use iced::{Length, Theme}; use crate::interpreter::{Document, Element, Interpreter, RheiContext, Value}; use crate::renderer::render_element; use crate::Message; pub struct GlintApp { pub doc: Document<'static>, pub vdom_roots: Vec>, pub rhei: RheiContext, } impl GlintApp { pub fn title(&self) -> String { "Glint Runtime - Native Renderer".to_string() } pub fn update(&mut self, message: Message) -> iced::Task { match message { Message::WindowScrolled(y) => { let var = "__scroll_y".to_string(); self.doc.variables.insert(var.clone(), Value::Float(y as f64)); self.doc.tracker.on_variable_changed(&var); } Message::EventTriggered(script) => { if !script.is_empty() { let old_vars: Vec = self.doc.variables.keys().cloned().collect(); self.rhei.execute_action(&script, &mut self.doc.variables); let new_vars: Vec = self.doc.variables.keys().cloned().collect(); for v in &new_vars { if !old_vars.contains(v) || self.doc.variables.get(v) != old_vars.iter().find_map(|k| if k == v { self.doc.variables.get(k) } else { None }) { self.doc.tracker.on_variable_changed(v); } } } } Message::InputChanged(Some(var), val) => { self.doc.variables.insert(var.clone(), Value::from(val)); self.doc.tracker.on_variable_changed(&var); } Message::ToggleChanged(Some(var), val) => { self.doc.variables.insert(var.clone(), Value::Bool(val)); self.doc.tracker.on_variable_changed(&var); } Message::SliderChanged(Some(var), val) => { self.doc.variables.insert(var.clone(), Value::Float(val)); self.doc.tracker.on_variable_changed(&var); if var == "volume_level" { self.doc.variables.insert("age".to_string(), Value::Float(val)); self.doc.tracker.on_variable_changed("age"); } } _ => {} } let dirty_set = self.doc.tracker.take_dirty_set(); let root_refs: Vec<&Element<'static>> = self.doc.roots.iter().collect(); self.vdom_roots = Interpreter::evaluate_vdom_incr( &root_refs, &mut self.doc.variables, &self.doc.components, &self.rhei, &self.doc.stylesheet, &[], &dirty_set, ); iced::Task::none() } pub fn view(&self) -> iced::Element<'_, Message, Theme, iced::Renderer> { let mut content = column![] .width(Length::Fill) .height(Length::Fill); let mut global_fixed_layers = Vec::new(); let mut global_abs_layers = Vec::new(); let mut global_sticky_layers = Vec::new(); let _scroll_y = self.doc.variables.get("__scroll_y") .and_then(|v| if let Value::Float(f) = v { Some(*f as f32) } else { None }) .unwrap_or(0.0); for root in &self.vdom_roots { if let Some(el) = render_element(root, None, None, None, &mut global_fixed_layers, &mut global_abs_layers, &mut global_sticky_layers, &self.doc.stylesheet) { content = content.push(el); } } let layout = column![ content, iced::widget::rule::horizontal(1), ] .width(Length::Fill) .height(Length::Fill); let main_flow = container(layout) .width(Length::Fill) .height(Length::Fill); let has_abs = !global_abs_layers.is_empty(); let has_sticky = !global_sticky_layers.is_empty(); let has_fixed = !global_fixed_layers.is_empty(); if !has_abs && !has_sticky && !has_fixed { main_flow.into() } else { let mut stack_widget = iced::widget::stack![main_flow]; for layer in global_abs_layers { stack_widget = stack_widget.push(layer); } for layer in global_sticky_layers { stack_widget = stack_widget.push(layer); } for layer in global_fixed_layers { stack_widget = stack_widget.push(layer); } stack_widget.into() } } }