freya_core/
custom_attributes.rs

1use std::{
2    any::Any,
3    fmt::{
4        Debug,
5        Display,
6    },
7    ops::Div,
8    sync::{
9        Arc,
10        Mutex,
11    },
12};
13
14use accesskit::NodeId as AccessibilityId;
15use bytes::Bytes;
16use dioxus_core::AttributeValue;
17use freya_engine::prelude::*;
18use freya_native_core::node::FromAnyValue;
19use tokio::sync::{
20    mpsc::UnboundedSender,
21    watch,
22};
23use torin::geometry::{
24    Area,
25    Size2D,
26};
27use uuid::Uuid;
28
29/// Image Reference
30#[derive(Clone, Debug)]
31pub struct ImageReference(pub Arc<Mutex<Option<Bytes>>>);
32
33impl PartialEq for ImageReference {
34    fn eq(&self, _other: &Self) -> bool {
35        true
36    }
37}
38
39impl Display for ImageReference {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        f.debug_struct("ImageReference").finish_non_exhaustive()
42    }
43}
44
45/// Layout info of a certain Node, used by `use_node`.
46#[derive(Clone, Debug, Default, PartialEq)]
47pub struct NodeReferenceLayout {
48    pub area: Area,
49    pub inner: Size2D,
50}
51
52impl NodeReferenceLayout {
53    pub fn div(&mut self, rhs: f32) {
54        self.area = self.area.div(rhs);
55        self.inner = self.inner.div(rhs);
56    }
57}
58
59/// Messages emitted from the layout library to the Nodes. Used in `use_editable`.
60#[derive(Debug)]
61pub enum CursorLayoutResponse {
62    CursorPosition { position: usize, id: usize },
63    TextSelection { from: usize, to: usize, id: usize },
64}
65
66/// Node Reference
67#[derive(Debug, Clone)]
68pub struct NodeReference(pub Arc<watch::Sender<NodeReferenceLayout>>);
69
70impl PartialEq for NodeReference {
71    fn eq(&self, other: &Self) -> bool {
72        Arc::ptr_eq(&self.0, &other.0)
73    }
74}
75
76impl Display for NodeReference {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        f.debug_struct("NodeReference").finish_non_exhaustive()
79    }
80}
81
82pub struct CanvasRunnerContext<'a> {
83    pub canvas: &'a Canvas,
84    pub font_collection: &'a mut FontCollection,
85    pub area: Area,
86    pub scale_factor: f32,
87}
88
89pub type CanvasRunner = dyn FnMut(&mut CanvasRunnerContext) + Sync + Send + 'static;
90
91/// Canvas Reference
92#[derive(Clone)]
93pub struct CanvasReference {
94    pub runner: Arc<Mutex<CanvasRunner>>,
95}
96
97impl PartialEq for CanvasReference {
98    fn eq(&self, other: &Self) -> bool {
99        Arc::ptr_eq(&self.runner, &other.runner)
100    }
101}
102
103impl Debug for CanvasReference {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        f.debug_struct("CanvasReference").finish_non_exhaustive()
106    }
107}
108
109/// Cursor reference
110#[derive(Clone, Debug)]
111pub struct CursorReference {
112    pub text_id: Uuid,
113    pub cursor_sender: UnboundedSender<CursorLayoutResponse>,
114}
115
116impl PartialEq for CursorReference {
117    fn eq(&self, other: &Self) -> bool {
118        self.text_id == other.text_id
119    }
120}
121
122impl Display for CursorReference {
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        f.debug_struct("CursorReference").finish_non_exhaustive()
125    }
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub enum AttributesBytes {
130    Dynamic(Bytes),
131    Static(&'static [u8]),
132}
133
134impl AttributesBytes {
135    pub fn as_slice(&self) -> &[u8] {
136        match self {
137            Self::Dynamic(bytes) => bytes.as_ref(),
138            Self::Static(bytes) => bytes,
139        }
140    }
141}
142
143/// Group all the custom attribute types
144#[derive(Clone, PartialEq)]
145pub enum CustomAttributeValues {
146    Reference(NodeReference),
147    CursorReference(CursorReference),
148    Bytes(AttributesBytes),
149    ImageReference(ImageReference),
150    AccessibilityId(AccessibilityId),
151    TextHighlights(Vec<(usize, usize)>),
152    Canvas(CanvasReference),
153}
154
155impl Debug for CustomAttributeValues {
156    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157        match self {
158            Self::Reference(_) => f.debug_tuple("Reference").finish(),
159            Self::CursorReference(_) => f.debug_tuple("CursorReference").finish(),
160            Self::Bytes(_) => f.debug_tuple("Bytes").finish(),
161            Self::ImageReference(_) => f.debug_tuple("ImageReference").finish(),
162            Self::AccessibilityId(_) => f.debug_tuple("AccessibilityId").finish(),
163            Self::TextHighlights(_) => f.debug_tuple("TextHighlights").finish(),
164            Self::Canvas(_) => f.debug_tuple("Canvas").finish(),
165        }
166    }
167}
168
169impl FromAnyValue for CustomAttributeValues {
170    fn from_any_value(b: &dyn Any) -> Self {
171        b.downcast_ref::<CustomAttributeValues>().unwrap().clone()
172    }
173}
174
175/// Transform some dynamic bytes (e.g: remote image fetched at runtime) into an attribute
176pub fn dynamic_bytes(bytes: impl Into<Bytes>) -> AttributeValue {
177    AttributeValue::any_value(CustomAttributeValues::Bytes(AttributesBytes::Dynamic(
178        bytes.into(),
179    )))
180}
181
182/// Transform some static bytes (e.g: statically linked images or SVGs) into an attribute
183pub fn static_bytes(bytes: &'static [u8]) -> AttributeValue {
184    AttributeValue::any_value(CustomAttributeValues::Bytes(AttributesBytes::Static(bytes)))
185}