Skip to content

Commit

Permalink
feat: allow block the system behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
richerfu committed Nov 12, 2024
1 parent 4f1cf26 commit 128cd78
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 139 deletions.
21 changes: 15 additions & 6 deletions crates/arkui/src/api/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ohos_arkui_sys::{
ArkUI_DialogDismissEvent, ArkUI_NativeAPIVariantKind_ARKUI_NATIVE_DIALOG,
ArkUI_NativeDialogAPI_1, ArkUI_NativeDialogHandle, ArkUI_NodeHandle,
OH_ArkUI_DialogDismissEvent_GetDismissReason, OH_ArkUI_DialogDismissEvent_GetUserData,
OH_ArkUI_QueryModuleInterfaceByName,
OH_ArkUI_DialogDismissEvent_SetShouldBlockDismiss, OH_ArkUI_QueryModuleInterfaceByName,
};

use crate::{
Expand Down Expand Up @@ -252,13 +252,22 @@ unsafe extern "C" fn dialog_dismiss_callback(event: *mut ArkUI_DialogDismissEven
#[cfg(debug_assertions)]
assert!(!user_data.is_null(), "user_data is NULL");

let data = &*(user_data as *const InnerDialogDismissData);
let user_data_rc: &Rc<RefCell<InnerDialogDismissData>> =
&*(user_data as *const Rc<RefCell<InnerDialogDismissData>>);

let data = user_data_rc.borrow_mut();

if let Some(handle) = data.dismiss_handle.as_ref() {
let reason = OH_ArkUI_DialogDismissEvent_GetDismissReason(event) as u32;
let cb = handle.as_ref().borrow();
(*cb)(DialogDismissData {

let ret = handle(DialogDismissData {
dismiss_reason: reason.into(),
data: data.data.clone(),
})
data: data.data,
});
if let Some(block) = ret {
if block {
OH_ArkUI_DialogDismissEvent_SetShouldBlockDismiss(event, block);
}
}
}
}
265 changes: 133 additions & 132 deletions crates/arkui/src/dialog/mod.rs
Original file line number Diff line number Diff line change
@@ -1,132 +1,133 @@
use std::{cell::RefCell, os::raw::c_void, rc::Rc};

use crate::{Alignment, ArkUINode, ArkUIResult, DismissReason, ARK_UI_NATIVE_DIALOG_API_1};

use ohos_arkui_sys::ArkUI_NativeDialogHandle;

pub(crate) struct InnerDialogDismissData {
pub dismiss_handle: Option<Rc<RefCell<fn(DialogDismissData) -> ()>>>,
pub data: Option<Rc<RefCell<*mut c_void>>>,
}

/// OnDismiss callback data
pub struct DialogDismissData {
/// dismiss reason
pub dismiss_reason: DismissReason,
/// User custom data,if not and it will be None
pub data: Option<Rc<RefCell<*mut c_void>>>,
}

pub struct Dialog {
pub(crate) raw: ArkUI_NativeDialogHandle,
pub(crate) inner_dismiss_data: Rc<RefCell<InnerDialogDismissData>>,
}

impl Dialog {
pub fn new() -> ArkUIResult<Self> {
let dialog_controller = ARK_UI_NATIVE_DIALOG_API_1.create()?;
Ok(Dialog {
raw: dialog_controller,
inner_dismiss_data: Rc::new(RefCell::new(InnerDialogDismissData {
dismiss_handle: None,
data: None,
})),
})
}

pub fn set_content<T: Into<ArkUINode>>(&self, content: T) -> ArkUIResult<()> {
let node: ArkUINode = content.into();
ARK_UI_NATIVE_DIALOG_API_1.set_content(self.raw, node.raw())?;
Ok(())
}

pub fn show(&self) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.show(self.raw, false)?;
Ok(())
}

pub fn show_with_sub_window(&self) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.show(self.raw, true)?;
Ok(())
}

pub fn close(&self) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.close(self.raw)?;
Ok(())
}

pub fn set_modal_mode(&self, modal_mode: bool) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_modal_mode(self.raw, modal_mode)?;
Ok(())
}

pub fn set_auto_cancel(&self, auto_cancel: bool) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_auto_cancel(self.raw, auto_cancel)?;
Ok(())
}

pub fn set_background_color(&self, color: u32) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_background_color(self.raw, color)?;
Ok(())
}

/// Set content alignment, offset_x and offset_y will be set with 0.0
pub fn set_content_alignment(&self, alignment: Alignment) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_content_alignment(self.raw, alignment, 0.0, 0.0)?;
Ok(())
}

/// Set content alignment with offset_x and offset_y.
pub fn set_content_alignment_with_offset(
&self,
alignment: Alignment,
offset_x: f32,
offset_y: f32,
) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1
.set_content_alignment(self.raw, alignment, offset_x, offset_y)?;
Ok(())
}

pub fn set_corner_radius(
&self,
top_left: f32,
top_right: f32,
bottom_left: f32,
bottom_right: f32,
) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_corner_radius(
self.raw,
top_left,
top_right,
bottom_left,
bottom_right,
)?;
Ok(())
}

pub fn on_will_dismiss(&self, callback: fn(DialogDismissData) -> ()) -> ArkUIResult<()> {
self.inner_dismiss_data.borrow_mut().dismiss_handle = Some(Rc::new(RefCell::new(callback)));

ARK_UI_NATIVE_DIALOG_API_1.register_dismiss(self.raw, self.inner_dismiss_data.clone())?;
Ok(())
}

/// For user custom data, you can use this method
/// And you need to convert raw pointer to your data type after callback
pub fn on_will_dismiss_with_data<T: 'static>(
&self,
data: T,
callback: fn(data: DialogDismissData) -> (),
) -> ArkUIResult<()> {
self.inner_dismiss_data.borrow_mut().dismiss_handle = Some(Rc::new(RefCell::new(callback)));

self.inner_dismiss_data.borrow_mut().data = Some(Rc::new(RefCell::new(Box::into_raw(
Box::new(data),
)
as *mut c_void)));

ARK_UI_NATIVE_DIALOG_API_1.register_dismiss(self.raw, self.inner_dismiss_data.clone())?;
Ok(())
}
}
use std::{cell::RefCell, os::raw::c_void, rc::Rc};

use crate::{Alignment, ArkUINode, ArkUIResult, DismissReason, ARK_UI_NATIVE_DIALOG_API_1};

use ohos_arkui_sys::ArkUI_NativeDialogHandle;

pub(crate) struct InnerDialogDismissData {
pub dismiss_handle: Option<fn(DialogDismissData) -> Option<bool>>,
pub data: Option<*mut c_void>,
}

/// OnDismiss callback data
pub struct DialogDismissData {
/// dismiss reason
pub dismiss_reason: DismissReason,
/// User custom data,if not and it will be None
pub data: Option<*mut c_void>,
}

pub struct Dialog {
pub(crate) raw: ArkUI_NativeDialogHandle,
pub(crate) inner_dismiss_data: Rc<RefCell<InnerDialogDismissData>>,
}

impl Dialog {
pub fn new() -> ArkUIResult<Self> {
let dialog_controller = ARK_UI_NATIVE_DIALOG_API_1.create()?;
Ok(Dialog {
raw: dialog_controller,
inner_dismiss_data: Rc::new(RefCell::new(InnerDialogDismissData {
dismiss_handle: None,
data: None,
})),
})
}

pub fn set_content<T: Into<ArkUINode>>(&self, content: T) -> ArkUIResult<()> {
let node: ArkUINode = content.into();
ARK_UI_NATIVE_DIALOG_API_1.set_content(self.raw, node.raw())?;
Ok(())
}

pub fn show(&self) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.show(self.raw, false)?;
Ok(())
}

pub fn show_with_sub_window(&self) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.show(self.raw, true)?;
Ok(())
}

pub fn close(&self) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.close(self.raw)?;
Ok(())
}

pub fn set_modal_mode(&self, modal_mode: bool) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_modal_mode(self.raw, modal_mode)?;
Ok(())
}

pub fn set_auto_cancel(&self, auto_cancel: bool) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_auto_cancel(self.raw, auto_cancel)?;
Ok(())
}

pub fn set_background_color(&self, color: u32) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_background_color(self.raw, color)?;
Ok(())
}

/// Set content alignment, offset_x and offset_y will be set with 0.0
pub fn set_content_alignment(&self, alignment: Alignment) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_content_alignment(self.raw, alignment, 0.0, 0.0)?;
Ok(())
}

/// Set content alignment with offset_x and offset_y.
pub fn set_content_alignment_with_offset(
&self,
alignment: Alignment,
offset_x: f32,
offset_y: f32,
) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1
.set_content_alignment(self.raw, alignment, offset_x, offset_y)?;
Ok(())
}

pub fn set_corner_radius(
&self,
top_left: f32,
top_right: f32,
bottom_left: f32,
bottom_right: f32,
) -> ArkUIResult<()> {
ARK_UI_NATIVE_DIALOG_API_1.set_corner_radius(
self.raw,
top_left,
top_right,
bottom_left,
bottom_right,
)?;
Ok(())
}

pub fn on_will_dismiss(
&self,
callback: fn(DialogDismissData) -> Option<bool>,
) -> ArkUIResult<()> {
self.inner_dismiss_data.borrow_mut().dismiss_handle = Some(callback);

ARK_UI_NATIVE_DIALOG_API_1.register_dismiss(self.raw, self.inner_dismiss_data.clone())?;
Ok(())
}

/// For user custom data, you can use this method
/// And you need to convert raw pointer to your data type after callback
pub fn on_will_dismiss_with_data<T: 'static>(
&self,
data: T,
callback: fn(data: DialogDismissData) -> Option<bool>,
) -> ArkUIResult<()> {
self.inner_dismiss_data.borrow_mut().dismiss_handle = Some(callback);

self.inner_dismiss_data.borrow_mut().data =
Some(Box::into_raw(Box::new(data)) as *mut c_void);

ARK_UI_NATIVE_DIALOG_API_1.register_dismiss(self.raw, self.inner_dismiss_data.clone())?;
Ok(())
}
}
5 changes: 4 additions & 1 deletion examples/arkui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ impl MyApp {
dialog.set_content(text)?;
dialog.set_auto_cancel(true)?;

dialog.on_will_dismiss(|_| hilog_info!("ohos-rs: dialog will dismiss"))?;
dialog.on_will_dismiss(|_| {
hilog_info!("ohos-rs: dialog will dismiss");
Some(true)
})?;

dialog.show()?;

Expand Down

0 comments on commit 128cd78

Please sign in to comment.