use std::rc::{Rc, Weak};
use_RefCell!();
use crate::{
node_interface::NodeLocal, ExpandedNode, RuntimeContext, RuntimePropertiesStackFrame,
TransformAndBounds,
};
use pax_runtime_api::math::Point2;
pub use pax_runtime_api::*;
#[cfg(feature = "designtime")]
use {
crate::node_interface::NodeInterface, crate::HandlerLocation,
pax_designtime::DesigntimeManager, pax_manifest::UniqueTemplateNodeIdentifier,
};
#[derive(Clone)]
pub struct NodeContext {
pub slot_index: Property<Option<usize>>,
pub(crate) local_stack_frame: Rc<RuntimePropertiesStackFrame>,
pub(crate) component_origin: Weak<ExpandedNode>,
pub frames_elapsed: Property<u64>,
pub bounds_parent: Property<(f64, f64)>,
pub bounds_self: Property<(f64, f64)>,
pub platform: Platform,
pub os: OS,
pub slot_children_count: Property<usize>,
pub(crate) runtime_context: Rc<RuntimeContext>,
pub(crate) node_transform_and_bounds: TransformAndBounds<NodeLocal, Window>,
#[cfg(feature = "designtime")]
pub designtime: Rc<RefCell<DesigntimeManager>>,
}
impl NodeContext {
pub fn push_local_store<T: Store>(&self, store: T) {
self.local_stack_frame.insert_stack_local_store(store);
}
pub fn peek_local_store<T: Store, V>(&self, f: impl FnOnce(&mut T) -> V) -> Result<V, String> {
self.local_stack_frame.peek_stack_local_store(f)
}
pub fn local_point(&self, p: Point2<Window>) -> Point2<NodeLocal> {
self.node_transform_and_bounds.as_transform().inverse() * p
}
pub fn navigate_to(&self, url: &str, target: NavigationTarget) {
self.runtime_context
.enqueue_native_message(NativeMessage::Navigate(NavigationPatch {
url: url.to_string(),
target: match target {
NavigationTarget::Current => "current",
NavigationTarget::New => "new",
}
.to_string(),
}))
}
pub fn dispatch_event(&self, identifier: &'static str) -> Result<(), String> {
let component_origin = self
.component_origin
.upgrade()
.ok_or_else(|| "can't dispatch from root component".to_owned())?;
{
let component_origin_instance = borrow!(component_origin.instance_node);
let registry = component_origin_instance
.base()
.handler_registry
.as_ref()
.ok_or_else(|| "no registry present".to_owned())?;
borrow!(registry).handlers.get(identifier).ok_or_else(|| {
format!("no registered handler with name \"{}\" exists", identifier)
})?;
}
self.runtime_context
.queue_custom_event(Rc::clone(&component_origin), identifier);
Ok(())
}
}
#[cfg(feature = "designtime")]
impl NodeContext {
pub fn raycast(&self, point: Point2<Window>, hit_invisible: bool) -> Vec<NodeInterface> {
let expanded_nodes =
self.runtime_context
.get_elements_beneath_ray(point, false, vec![], hit_invisible);
expanded_nodes
.into_iter()
.map(Into::<NodeInterface>::into)
.collect()
}
pub fn get_nodes_by_global_id(&self, uni: UniqueTemplateNodeIdentifier) -> Vec<NodeInterface> {
let expanded_nodes = self.runtime_context.get_expanded_nodes_by_global_ids(&uni);
expanded_nodes
.into_iter()
.map(Into::<NodeInterface>::into)
.collect()
}
pub fn get_userland_root_expanded_node(&self) -> NodeInterface {
#[cfg(feature = "designtime")]
let expanded_node = self
.runtime_context
.get_userland_root_expanded_node()
.unwrap();
#[cfg(not(feature = "designtime"))]
let expanded_node = self.runtime_context.get_root_expanded_node().unwrap();
expanded_node.into()
}
pub fn get_root_expanded_node(&self) -> NodeInterface {
let expanded_node = self.runtime_context.get_root_expanded_node().unwrap();
expanded_node.into()
}
pub fn get_nodes_by_id(&self, id: &str) -> Vec<NodeInterface> {
let expanded_nodes = self.runtime_context.get_expanded_nodes_by_id(id);
expanded_nodes
.into_iter()
.map(Into::<NodeInterface>::into)
.collect()
}
}