use std::collections::HashMap;
use std::iter;
use std::rc::Rc;
use_RefCell!();
use crate::api::{CommonProperties, RenderContext};
use pax_manifest::UniqueTemplateNodeIdentifier;
use pax_message::NativeInterrupt;
use pax_runtime_api::pax_value::PaxAny;
use pax_runtime_api::{borrow, use_RefCell, Variable};
use piet::{Color, StrokeStyle};
use crate::api::{Layer, Scroll};
use crate::{ExpandedNode, HandlerRegistry, RuntimeContext, RuntimePropertiesStackFrame};
pub type InstanceNodePtr = Rc<dyn InstanceNode>;
pub type InstanceNodePtrList = RefCell<Vec<InstanceNodePtr>>;
pub struct InstantiationArgs {
pub prototypical_common_properties_factory: Box<
dyn Fn(
Rc<RuntimePropertiesStackFrame>,
Option<Rc<ExpandedNode>>,
) -> Option<Rc<RefCell<CommonProperties>>>,
>,
pub prototypical_properties_factory: Box<
dyn Fn(
Rc<RuntimePropertiesStackFrame>,
Option<Rc<ExpandedNode>>,
) -> Option<Rc<RefCell<PaxAny>>>,
>,
pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
pub children: Option<InstanceNodePtrList>,
pub component_template: Option<InstanceNodePtrList>,
pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
pub properties_scope_factory:
Option<Box<dyn Fn(Rc<RefCell<PaxAny>>) -> HashMap<String, Variable>>>,
}
pub struct ReusableInstanceNodeArgs {
pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
pub children: InstanceNodePtrList,
pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
}
impl ReusableInstanceNodeArgs {
pub fn new(base: &BaseInstance) -> Self {
ReusableInstanceNodeArgs {
handler_registry: base.handler_registry.clone(),
children: base.instance_children.clone(),
template_node_identifier: base.template_node_identifier.clone(),
}
}
}
#[derive(Clone)]
pub enum NodeType {
Component,
Primitive,
}
impl std::fmt::Debug for dyn InstanceNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.resolve_debug(f, None)
}
}
pub trait InstanceNode {
fn base(&self) -> &BaseInstance;
fn instantiate(args: InstantiationArgs) -> Rc<Self>
where
Self: Sized;
fn resolve_debug(
&self,
f: &mut std::fmt::Formatter,
expanded_node: Option<&ExpandedNode>,
) -> std::fmt::Result;
fn update(self: Rc<Self>, _expanded_node: &Rc<ExpandedNode>, _context: &Rc<RuntimeContext>) {}
#[allow(unused_variables)]
fn handle_pre_render(
&self,
expanded_node: &ExpandedNode,
context: &Rc<RuntimeContext>,
rcs: &mut dyn RenderContext,
) {
}
#[allow(unused_variables)]
fn render(
&self,
expanded_node: &ExpandedNode,
context: &Rc<RuntimeContext>,
rcs: &mut dyn RenderContext,
) {
}
#[allow(unused_variables)]
fn handle_post_render(
&self,
expanded_node: &ExpandedNode,
context: &Rc<RuntimeContext>,
rcs: &mut dyn RenderContext,
) {
}
#[allow(unused_variables)]
fn handle_mount(
self: Rc<Self>,
expanded_node: &Rc<ExpandedNode>,
context: &Rc<RuntimeContext>,
) {
let env = Rc::clone(&expanded_node.stack);
let children = borrow!(self.base().get_instance_children());
let children_with_envs = children.iter().cloned().zip(iter::repeat(env));
let new_children = expanded_node.generate_children(
children_with_envs,
context,
&expanded_node.parent_frame,
true,
);
expanded_node.children.set(new_children);
}
#[allow(unused_variables)]
fn handle_unmount(&self, expanded_node: &Rc<ExpandedNode>, context: &Rc<RuntimeContext>) {
}
#[allow(unused_variables)]
fn handle_scroll(&self, args_scroll: Scroll) {
}
fn get_template(&self) -> Option<&InstanceNodePtrList> {
None
}
fn clips_content(&self, _expanded_node: &ExpandedNode) -> bool {
false
}
fn handle_native_interrupt(
&self,
_expanded_node: &Rc<ExpandedNode>,
_interrupt: &NativeInterrupt,
) {
}
fn handle_control_flow_node_expansion(
self: Rc<Self>,
_expanded_node: &Rc<ExpandedNode>,
_context: &Rc<RuntimeContext>,
) {
}
fn handle_setup_slot_children(
self: Rc<Self>,
_expanded_node: &Rc<ExpandedNode>,
_context: &Rc<RuntimeContext>,
) {
}
}
pub struct BaseInstance {
pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
pub instance_prototypical_properties_factory: Box<
dyn Fn(
Rc<RuntimePropertiesStackFrame>,
Option<Rc<ExpandedNode>>,
) -> Option<Rc<RefCell<PaxAny>>>,
>,
pub instance_prototypical_common_properties_factory: Box<
dyn Fn(
Rc<RuntimePropertiesStackFrame>,
Option<Rc<ExpandedNode>>,
) -> Option<Rc<RefCell<CommonProperties>>>,
>,
pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
pub properties_scope_factory:
Option<Box<dyn Fn(Rc<RefCell<PaxAny>>) -> HashMap<String, Variable>>>,
instance_children: InstanceNodePtrList,
flags: InstanceFlags,
}
#[derive(Clone)]
pub struct InstanceFlags {
pub invisible_to_slot: bool,
pub invisible_to_raycasting: bool,
pub layer: Layer,
pub is_component: bool,
pub is_slot: bool,
}
impl BaseInstance {
pub fn new(args: InstantiationArgs, flags: InstanceFlags) -> Self {
BaseInstance {
handler_registry: args.handler_registry,
instance_prototypical_common_properties_factory: args
.prototypical_common_properties_factory,
instance_prototypical_properties_factory: args.prototypical_properties_factory,
instance_children: args.children.unwrap_or_default(),
flags,
template_node_identifier: args.template_node_identifier,
properties_scope_factory: args.properties_scope_factory,
}
}
pub fn get_handler_registry(&self) -> Option<Rc<RefCell<HandlerRegistry>>> {
match &self.handler_registry {
Some(registry) => Some(Rc::clone(registry)),
_ => None,
}
}
pub fn get_instance_children(&self) -> &InstanceNodePtrList {
&self.instance_children
}
pub fn flags(&self) -> &InstanceFlags {
&self.flags
}
}
pub struct StrokeInstance {
pub color: Color,
pub width: f64,
pub style: StrokeStyle,
}