ohos-arkui-binding 0.2.0

OpenHarmony's arkui binding for rust
Documentation
//! Dialog builder and lifecycle callback wrappers.

use std::{cell::RefCell, os::raw::c_void, rc::Rc};

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

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>,
}

/// High-level dialog wrapper for creating and controlling native dialogs.
pub struct Dialog {
    pub(crate) raw: ArkUI_NativeDialogHandle,
    pub(crate) inner_dismiss_data: Rc<RefCell<InnerDialogDismissData>>,
}

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

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

    /// Show the dialog in current window.
    pub fn show(&self) -> ArkUIResult<()> {
        ARK_UI_NATIVE_DIALOG_API_1.with(|api| api.show(self.raw, false))?;
        Ok(())
    }

    /// Show the dialog in sub-window mode.
    pub fn show_with_sub_window(&self) -> ArkUIResult<()> {
        ARK_UI_NATIVE_DIALOG_API_1.with(|api| api.show(self.raw, true))?;
        Ok(())
    }

    /// Close the dialog.
    pub fn close(&self) -> ArkUIResult<()> {
        ARK_UI_NATIVE_DIALOG_API_1.with(|api| api.close(self.raw))?;
        Ok(())
    }

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

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

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

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

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

    pub fn corner_radius(
        &self,
        top_left: f32,
        top_right: f32,
        bottom_left: f32,
        bottom_right: f32,
    ) -> ArkUIResult<()> {
        ARK_UI_NATIVE_DIALOG_API_1.with(|api| {
            api.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
            .with(|api| api.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
            .with(|api| api.register_dismiss(self.raw, self.inner_dismiss_data.clone()))?;
        Ok(())
    }
}