cfg_if::cfg_if! {
if #[cfg(windows)] {
#[derive(Clone, Copy)]
enum BorrowedContainerInner<'a> {
#[cfg(feature = "win32")]
Win32(windows_sys::Win32::Foundation::HWND, std::marker::PhantomData<&'a ()>),
#[cfg(feature = "winui")]
WinUI(&'a winui3::Microsoft::UI::Xaml::Controls::Canvas),
#[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 BorrowedContainerInner<'a> = &'a Retained<objc2_app_kit::NSView>;
} else if #[cfg(target_os = "ios")] {
use objc2::rc::Retained;
type BorrowedContainerInner<'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 if #[cfg(target_os = "android")] {
use jni::objects::JObject;
type BorrowedContainerInner<'a> = &'a JObject<'static>;
} else {
#[derive(Clone, Copy)]
enum BorrowedContainerInner<'a> {
#[cfg(feature = "qt")]
Qt(*mut core::ffi::c_void, std::marker::PhantomData<&'a ()>),
#[cfg(feature = "gtk")]
Gtk(&'a gtk4::Fixed),
#[cfg(not(any(feature = "qt", feature = "gtk")))]
Dummy(std::convert::Infallible, std::marker::PhantomData<&'a ()>),
}
}
}
#[derive(Clone, Copy)]
pub struct BorrowedContainer<'a>(BorrowedContainerInner<'a>);
#[allow(unreachable_patterns)]
#[cfg(windows)]
impl<'a> BorrowedContainer<'a> {
#[cfg(feature = "win32")]
pub unsafe fn win32(hwnd: windows_sys::Win32::Foundation::HWND) -> Self {
Self(BorrowedContainerInner::Win32(
hwnd,
std::marker::PhantomData,
))
}
#[cfg(feature = "winui")]
pub fn winui(container: &'a winui3::Microsoft::UI::Xaml::Controls::Canvas) -> Self {
Self(BorrowedContainerInner::WinUI(container))
}
#[cfg(feature = "win32")]
pub fn as_win32(&self) -> windows_sys::Win32::Foundation::HWND {
match &self.0 {
BorrowedContainerInner::Win32(hwnd, ..) => *hwnd,
_ => panic!("unsupported handle type"),
}
}
#[cfg(feature = "winui")]
pub fn as_winui(&self) -> &winui3::Microsoft::UI::Xaml::Controls::Canvas {
match &self.0 {
BorrowedContainerInner::WinUI(container) => container,
_ => panic!("unsupported handle type"),
}
}
}
#[cfg(target_os = "macos")]
impl<'a> BorrowedContainer<'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> BorrowedContainer<'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> BorrowedContainer<'a> {
#[cfg(feature = "qt")]
pub unsafe fn qt<T>(widget: *mut T) -> Self {
Self(BorrowedContainerInner::Qt(
widget.cast(),
std::marker::PhantomData,
))
}
#[cfg(feature = "gtk")]
pub fn gtk(fixed: &'a gtk4::Fixed) -> Self {
Self(BorrowedContainerInner::Gtk(fixed))
}
#[cfg(feature = "qt")]
pub fn as_qt<T>(&self) -> *mut T {
match &self.0 {
BorrowedContainerInner::Qt(w, ..) => (*w).cast(),
_ => panic!("unsupported handle type"),
}
}
#[cfg(feature = "gtk")]
pub fn to_gtk(&self) -> &'a gtk4::Fixed {
match &self.0 {
BorrowedContainerInner::Gtk(w) => w,
_ => panic!("unsupported handle type"),
}
}
}
#[cfg(target_os = "android")]
impl<'a> BorrowedContainer<'a> {
pub unsafe fn android(j_obj: &'a JObject<'static>) -> Self {
BorrowedContainer(j_obj)
}
pub fn to_android(&self) -> &'a JObject<'static> {
self.0
}
}
pub trait AsContainer {
fn as_container(&self) -> BorrowedContainer<'_>;
}
impl AsContainer for BorrowedContainer<'_> {
fn as_container(&self) -> BorrowedContainer<'_> {
*self
}
}
impl<T: AsContainer + ?Sized> AsContainer for &T {
#[inline]
fn as_container(&self) -> BorrowedContainer<'_> {
T::as_container(self)
}
}
impl<'a, T: AsContainer + ?Sized> From<&'a T> for BorrowedContainer<'a> {
fn from(value: &'a T) -> Self {
value.as_container()
}
}
#[doc(hidden)]
pub struct MaybeBorrowedContainer<'a>(pub Option<BorrowedContainer<'a>>);
impl<'a, T: Into<BorrowedContainer<'a>>> From<T> for MaybeBorrowedContainer<'a> {
fn from(value: T) -> Self {
Self(Some(value.into()))
}
}
impl<'a, T: Into<BorrowedContainer<'a>>> From<Option<T>> for MaybeBorrowedContainer<'a> {
fn from(value: Option<T>) -> Self {
Self(value.map(|v| v.into()))
}
}
impl From<()> for MaybeBorrowedContainer<'_> {
fn from(_: ()) -> Self {
Self(None)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_as_container {
($t:ty, $inner:ident) => {
impl $crate::AsContainer for $t {
fn as_container(&self) -> $crate::BorrowedContainer<'_> {
self.$inner.as_container()
}
}
};
}