1use crate::{ObjectType, Ref, StyledElement, Upcast};
4use std::rc::Rc;
5
6pub trait INamed {
10 fn name(&self) -> Option<String>;
12
13 #[doc(hidden)]
15 fn reference_id(&self) -> *const () {
16 self as *const Self as *const ()
17 }
18}
19
20impl PartialEq for dyn INamed {
24 #[inline]
25 fn eq(&self, other: &Self) -> bool {
26 self.reference_id() == other.reference_id()
27 }
28}
29
30struct StyledElementNamed(Ref<StyledElement>);
32
33impl INamed for StyledElementNamed {
34 fn name(&self) -> Option<String> {
35 self.0.name()
36 }
37
38 fn reference_id(&self) -> *const () {
39 &*self.0 as *const StyledElement as *const ()
40 }
41}
42
43impl<T: ObjectType + Upcast<StyledElement>> From<Ref<T>> for Rc<dyn INamed> {
44 fn from(value: Ref<T>) -> Self {
45 Rc::new(StyledElementNamed(value.upcast()))
46 }
47}
48
49impl<T: ObjectType + Upcast<StyledElement>> From<&Ref<T>> for Rc<dyn INamed> {
50 fn from(value: &Ref<T>) -> Self {
51 Rc::new(StyledElementNamed(value.clone().upcast()))
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use crate::data::core::{ValueType, ValueTypes};
59 use crate::BoxedValue;
60
61 #[test]
62 fn styled_elements_are_named() {
63 let element = StyledElement::new();
64 element.set_name(Some("root".to_string()));
65 let named: Rc<dyn INamed> = (&element).into();
66 assert_eq!(named.name().as_deref(), Some("root"));
67
68 let again: Rc<dyn INamed> = element.clone().into();
69 let other: Rc<dyn INamed> = StyledElement::new().into();
70 assert!(*named == *again);
71 assert!(*named != *other);
72 }
73
74 #[test]
75 fn the_handle_of_a_styled_element_casts_to_the_contract() {
76 let element = StyledElement::new();
77 assert!(StyledElement::TYPE.interfaces().iter().any(|i| i() == ValueType::of::<Rc<dyn INamed>>()));
78 let boxed: BoxedValue = Rc::new(element.clone());
79 let cast = ValueTypes::try_cast(&boxed, ValueType::of::<Rc<dyn INamed>>()).expect("the cast is declared");
80 assert!(cast.downcast_ref::<Rc<dyn INamed>>().is_some());
81 }
82}