123 lines
4.5 KiB
Rust
123 lines
4.5 KiB
Rust
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<Element<'static>>,
|
|
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<Message> {
|
|
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<String> = self.doc.variables.keys().cloned().collect();
|
|
self.rhei.execute_action(&script, &mut self.doc.variables);
|
|
let new_vars: Vec<String> = 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()
|
|
}
|
|
}
|
|
}
|