1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
use std::sync::{
Arc,
Mutex,
};
use dioxus_core::AttributeValue;
use dioxus_hooks::{
use_memo,
use_reactive,
Dependency,
};
use dioxus_signals::{
Memo,
Readable,
};
use freya_core::custom_attributes::{
CanvasReference,
CanvasRunner,
CanvasRunnerContext,
CustomAttributeValues,
};
/// Holds a rendering hook callback that allows to render to the Canvas.
#[derive(PartialEq, Clone)]
pub struct UseCanvas {
runner: Memo<UseCanvasRunner>,
}
#[derive(Clone)]
pub struct UseCanvasRunner(pub Arc<Mutex<CanvasRunner>>);
impl PartialEq for UseCanvasRunner {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl UseCanvas {
pub fn attribute(&self) -> AttributeValue {
AttributeValue::any_value(CustomAttributeValues::Canvas(CanvasReference {
runner: self.runner.read().0.clone(),
}))
}
}
/// Register a rendering hook to gain access to the Canvas.
/// Reactivity managed through signals.
///
/// ## Usage
/// ```rust,no_run
/// # use freya::prelude::*;
/// fn app() -> Element {
/// let (reference, size) = use_node_signal();
/// let mut value = use_signal(|| 0);
/// let platform = use_platform();
///
/// let canvas = use_canvas(move || {
/// let curr = value();
/// platform.invalidate_drawing_area(size.peek().area);
/// platform.request_animation_frame();
/// move |ctx| {
/// // Draw using the canvas !
/// // use `curr`
/// }
/// });
///
/// rsx!(rect {
/// onclick: move |_| {
/// value += 1;
/// },
/// canvas_reference: canvas.attribute(),
/// reference,
/// width: "fill",
/// height: "fill",
/// })
/// }
/// ```
pub fn use_canvas<T: FnMut(&mut CanvasRunnerContext) + Sync + Send + 'static>(
mut renderer_cb: impl FnMut() -> T + 'static,
) -> UseCanvas {
let runner = use_memo(move || UseCanvasRunner(Arc::new(Mutex::new(renderer_cb()))));
UseCanvas { runner }
}
/// Register a rendering hook to gain access to the Canvas.
/// Reactivity managed with manual dependencies.
///
/// ## Usage
/// ```rust,no_run
/// # use freya::prelude::*;
/// fn app() -> Element {
/// let (reference, size) = use_node_signal();
/// let mut value = use_signal(|| 0);
/// let platform = use_platform();
///
/// let canvas = use_canvas_with_deps(&value(), move |curr| {
/// platform.invalidate_drawing_area(size.peek().area);
/// platform.request_animation_frame();
/// move |ctx| {
/// // Draw using the canvas !
/// // use `curr`
/// }
/// });
///
/// rsx!(rect {
/// onclick: move |_| {
/// value += 1;
/// },
/// canvas_reference: canvas.attribute(),
/// reference,
/// width: "fill",
/// height: "fill",
/// })
/// }
/// ```
pub fn use_canvas_with_deps<
D: Dependency,
T: FnMut(&mut CanvasRunnerContext) + Sync + Send + 'static,
>(
dependencies: D,
mut renderer_cb: impl FnMut(D::Out) -> T + 'static,
) -> UseCanvas
where
D::Out: 'static,
{
let runner = use_memo(use_reactive(dependencies, move |dependencies| {
UseCanvasRunner(Arc::new(Mutex::new(renderer_cb(dependencies))))
}));
UseCanvas { runner }
}