ohos_arkui_binding/api/
node_content.rs1use std::{os::raw::c_void, ptr::NonNull};
4
5use ohos_arkui_sys::{
6 ArkUI_NodeContentEvent, ArkUI_NodeContentHandle, OH_ArkUI_NodeContentEvent_GetEventType,
7 OH_ArkUI_NodeContentEvent_GetNodeContentHandle, OH_ArkUI_NodeContent_GetUserData,
8 OH_ArkUI_NodeContent_RegisterCallback, OH_ArkUI_NodeContent_SetUserData,
9};
10
11use crate::{check_arkui_status, ArkUINode, ArkUIResult};
12
13fn non_null_or_panic<T>(ptr: *mut T, name: &'static str) -> NonNull<T> {
14 NonNull::new(ptr).unwrap_or_else(|| panic!("{name} pointer is null"))
15}
16
17pub struct NodeContentEvent {
19 raw: NonNull<ArkUI_NodeContentEvent>,
20}
21
22impl NodeContentEvent {
23 fn from_raw(raw: *mut ArkUI_NodeContentEvent) -> Option<Self> {
24 NonNull::new(raw).map(|raw| Self { raw })
25 }
26
27 fn raw(&self) -> *mut ArkUI_NodeContentEvent {
28 self.raw.as_ptr()
29 }
30
31 pub fn event_type(&self) -> crate::NodeContentEventType {
33 unsafe { OH_ArkUI_NodeContentEvent_GetEventType(self.raw()).into() }
34 }
35
36 pub fn node_content_handle(&self) -> Option<crate::ArkUIHandle> {
38 let handle = unsafe { OH_ArkUI_NodeContentEvent_GetNodeContentHandle(self.raw()) };
39 crate::ArkUIHandle::from_raw(handle)
40 }
41}
42
43struct NodeContentCallbackContext {
44 callback: Box<dyn Fn(&mut NodeContentEvent)>,
45}
46
47pub struct NodeContent {
49 handle: crate::ArkUIHandle,
50 callback_context: Option<NonNull<NodeContentCallbackContext>>,
51}
52
53impl NodeContent {
54 pub fn from_handle(handle: crate::ArkUIHandle) -> Self {
56 Self {
57 handle,
58 callback_context: None,
59 }
60 }
61
62 pub(crate) fn from_raw(raw: ArkUI_NodeContentHandle) -> Option<Self> {
63 crate::ArkUIHandle::from_raw(raw).map(Self::from_handle)
64 }
65
66 #[cfg(feature = "napi")]
67 pub fn from_napi_handle(handle: &crate::ArkUIHandle) -> Option<Self> {
68 Some(Self::from_handle(*handle))
69 }
70
71 pub fn handle(&self) -> crate::ArkUIHandle {
73 self.handle
74 }
75
76 pub fn add_node(&self, node: &ArkUINode) -> ArkUIResult<()> {
78 self.handle.add_node(node)
79 }
80
81 pub fn remove_node(&self, node: &ArkUINode) -> ArkUIResult<()> {
83 self.handle.remove_node(node)
84 }
85
86 pub fn insert_node(&self, node: &ArkUINode, position: i32) -> ArkUIResult<()> {
88 self.handle.insert_node(node, position)
89 }
90
91 pub fn register_callback<T: Fn(&mut NodeContentEvent) + 'static>(
93 &mut self,
94 callback: T,
95 ) -> ArkUIResult<()> {
96 self.clear_callback()?;
97 let context = Box::into_raw(Box::new(NodeContentCallbackContext {
98 callback: Box::new(callback),
99 }));
100 let context = non_null_or_panic(context, "NodeContentCallbackContext");
101 if let Err(err) = self
102 .handle
103 .set_node_content_user_data(context.as_ptr().cast())
104 {
105 unsafe {
106 drop(Box::from_raw(context.as_ptr()));
107 }
108 return Err(err);
109 }
110 let register_result = self
111 .handle
112 .register_node_content_callback(Some(node_content_callback_trampoline));
113 if let Err(err) = register_result {
114 let _ = self.handle.set_node_content_user_data(std::ptr::null_mut());
115 unsafe {
116 drop(Box::from_raw(context.as_ptr()));
117 }
118 return Err(err);
119 }
120 self.callback_context = Some(context);
121 Ok(())
122 }
123
124 pub fn clear_callback(&mut self) -> ArkUIResult<()> {
126 let unregister_result = self.handle.register_node_content_callback(None);
127 let clear_data_result = self.handle.set_node_content_user_data(std::ptr::null_mut());
128
129 if unregister_result.is_ok() || clear_data_result.is_ok() {
130 if let Some(context) = self.callback_context.take() {
131 unsafe {
132 drop(Box::from_raw(context.as_ptr()));
133 }
134 }
135 }
136
137 unregister_result?;
138 clear_data_result?;
139 Ok(())
140 }
141}
142
143impl crate::ArkUIHandle {
144 pub(crate) fn register_node_content_callback(
145 &self,
146 callback: Option<unsafe extern "C" fn(event: *mut ArkUI_NodeContentEvent)>,
147 ) -> ArkUIResult<()> {
148 unsafe { check_arkui_status!(OH_ArkUI_NodeContent_RegisterCallback(self.raw(), callback)) }
149 }
150
151 pub(crate) fn set_node_content_user_data(&self, user_data: *mut c_void) -> ArkUIResult<()> {
152 unsafe { check_arkui_status!(OH_ArkUI_NodeContent_SetUserData(self.raw(), user_data)) }
153 }
154
155 pub(crate) fn node_content_user_data(&self) -> *mut c_void {
156 unsafe { OH_ArkUI_NodeContent_GetUserData(self.raw()) }
157 }
158}
159
160unsafe extern "C" fn node_content_callback_trampoline(event: *mut ArkUI_NodeContentEvent) {
161 let Some(mut event) = NodeContentEvent::from_raw(event) else {
162 return;
163 };
164 let Some(content_handle) = event.node_content_handle() else {
165 return;
166 };
167 let user_data = content_handle.node_content_user_data();
168 if user_data.is_null() {
169 return;
170 }
171 let callback = unsafe { &*(user_data as *mut NodeContentCallbackContext) };
172 (callback.callback)(&mut event);
173}