cfg_if::cfg_if! {
if #[cfg(windows)] {
#[derive(Clone, Copy)]
enum BorrowedWidgetInner<'a> {
#[cfg(feature = "win32")]
Win32(windows_sys::Win32::Foundation::HWND, std::marker::PhantomData<&'a ()>),
#[cfg(feature = "winui")]
WinUI(&'a winui3::Microsoft::UI::Xaml::FrameworkElement),
#[cfg(not(any(feature = "win32", feature = "winui")))]
Dummy(std::convert::Infallible, std::marker::PhantomData<&'a ()>),
}
} else if #[cfg(target_os = "macos")] {
use objc2::rc::Retained;
type BorrowedWidgetInner<'a> = &'a Retained<objc2_app_kit::NSView>;
} else if #[cfg(target_os = "android")] {
use jni::objects::JObject;
type BorrowedWidgetInner<'a> = &'a JObject<'static>;
} else if #[cfg(target_os = "ios")] {
use objc2::rc::Retained;
type BorrowedWidgetInner<'a> = &'a Retained<objc2_ui_kit::UIView>;
} else if #[cfg(target_vendor = "apple")] {
compile_error!("Other Apple platforms (like watchOS and tvOS) are not supported yet.");
} else {
#[derive(Clone, Copy)]
enum BorrowedWidgetInner<'a> {
#[cfg(feature = "qt")]
Qt(*mut core::ffi::c_void, std::marker::PhantomData<&'a ()>),
#[cfg(feature = "gtk")]
Gtk(&'a gtk4::Widget),
#[cfg(not(any(feature = "qt", feature = "gtk")))]
Dummy(std::convert::Infallible, std::marker::PhantomData<&'a ()>),
}
}
}
#[derive(Clone, Copy)]
pub struct BorrowedWidget<'a>(BorrowedWidgetInner<'a>);
#[allow(unreachable_patterns)]
#[cfg(windows)]
impl<'a> BorrowedWidget<'a> {
#[cfg(feature = "win32")]
pub unsafe fn win32(hwnd: windows_sys::Win32::Foundation::HWND) -> Self {
Self(BorrowedWidgetInner::Win32(hwnd, std::marker::PhantomData))
}
#[cfg(feature = "winui")]
pub fn winui(element: &'a winui3::Microsoft::UI::Xaml::FrameworkElement) -> Self {
Self(BorrowedWidgetInner::WinUI(element))
}
#[cfg(feature = "win32")]
pub fn as_win32(&self) -> windows_sys::Win32::Foundation::HWND {
match &self.0 {
BorrowedWidgetInner::Win32(hwnd, ..) => *hwnd,
_ => panic!("unsupported handle type"),
}
}
#[cfg(feature = "winui")]
pub fn as_winui(&self) -> &winui3::Microsoft::UI::Xaml::FrameworkElement {
match &self.0 {
BorrowedWidgetInner::WinUI(e) => e,
_ => panic!("unsupported handle type"),
}
}
}
#[cfg(target_os = "macos")]
impl<'a> BorrowedWidget<'a> {
pub fn app_kit(view: &'a Retained<objc2_app_kit::NSView>) -> Self {
Self(view)
}
pub fn as_app_kit(&self) -> &'a Retained<objc2_app_kit::NSView> {
self.0
}
}
#[cfg(target_os = "ios")]
impl<'a> BorrowedWidget<'a> {
pub fn ui_kit(view: &'a Retained<objc2_ui_kit::UIView>) -> Self {
Self(view)
}
pub fn as_ui_kit(&self) -> &'a Retained<objc2_ui_kit::UIView> {
self.0
}
}
#[allow(unreachable_patterns)]
#[cfg(not(any(windows, target_vendor = "apple", target_os = "android")))]
impl<'a> BorrowedWidget<'a> {
#[cfg(feature = "qt")]
pub unsafe fn qt<T>(widget: *mut T) -> Self {
Self(BorrowedWidgetInner::Qt(
widget.cast(),
std::marker::PhantomData,
))
}
#[cfg(feature = "gtk")]
pub fn gtk(widget: &'a gtk4::Widget) -> Self {
Self(BorrowedWidgetInner::Gtk(widget))
}
#[cfg(feature = "qt")]
pub fn as_qt<T>(&self) -> *mut T {
match &self.0 {
BorrowedWidgetInner::Qt(w, ..) => (*w).cast(),
_ => panic!("unsupported handle type"),
}
}
#[cfg(feature = "gtk")]
pub fn to_gtk(&self) -> &'a gtk4::Widget {
match &self.0 {
BorrowedWidgetInner::Gtk(w) => w,
_ => panic!("unsupported handle type"),
}
}
}
#[cfg(target_os = "android")]
impl<'a> BorrowedWidget<'a> {
pub unsafe fn android(j_obj: &'a JObject<'static>) -> Self {
BorrowedWidget(j_obj)
}
pub fn to_android(&self) -> &'a JObject<'static> {
self.0
}
}
pub trait AsWidget {
fn as_widget(&self) -> BorrowedWidget<'_>;
}
impl AsWidget for BorrowedWidget<'_> {
fn as_widget(&self) -> BorrowedWidget<'_> {
*self
}
}
impl<T: AsWidget + ?Sized> AsWidget for &T {
#[inline]
fn as_widget(&self) -> BorrowedWidget<'_> {
T::as_widget(self)
}
}
impl<'a, T: AsWidget + ?Sized> From<&'a T> for BorrowedWidget<'a> {
fn from(value: &'a T) -> Self {
value.as_widget()
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_as_widget {
($t:ty, $inner:ident) => {
impl $crate::AsWidget for $t {
fn as_widget(&self) -> $crate::BorrowedWidget<'_> {
self.$inner.as_widget()
}
}
};
}