#[macro_export]
macro_rules! widget_builder {
(
name: $name:ident,
parent_type: &'a dyn WxWidget,
style_type: $style_type:ty,
fields: {
$(
$field_name:ident: $field_type:ty $(= $field_default:expr)?
),*
},
build_impl: |$self_param:ident| $build_impl:block
) => {
paste::paste! {
#[derive(Clone)]
pub struct [<$name Builder>]<'a> {
parent: &'a dyn WxWidget,
id: Id,
pos: Point,
size: Size,
style: $style_type,
$(
$field_name: $field_type,
)*
}
impl<'a> [<$name Builder>]<'a> {
pub fn new(parent: &'a dyn WxWidget) -> Self {
Self {
parent,
id: $crate::id::ID_ANY as Id,
pos: $crate::geometry::Point::DEFAULT_POSITION,
size: $crate::geometry::Size::DEFAULT_SIZE,
style: <$style_type>::default(),
$(
$field_name: $crate::__widget_builder_default!($($field_default)?),
)*
}
}
pub fn with_id(mut self, id: Id) -> Self {
self.id = id;
self
}
pub fn with_pos(mut self, pos: Point) -> Self {
self.pos = pos;
self
}
pub fn with_size(mut self, size: Size) -> Self {
self.size = size;
self
}
pub fn with_style(mut self, style: $style_type) -> Self {
self.style = style;
self
}
$(
$crate::__widget_builder_field_method!($field_name: $field_type);
)*
pub fn build(self) -> $name {
let build_fn = |$self_param: [<$name Builder>]<'a>| $build_impl;
build_fn(self)
}
}
}
};
}
#[macro_export]
macro_rules! implement_widget_traits {
($widget_name:ident, $window_field:ident) => {
impl $crate::window::WxWidget for $widget_name {
fn handle_ptr(&self) -> *mut wxdragon_sys::wxd_Window_t {
self.$window_field.handle_ptr()
}
}
impl std::ops::Deref for $widget_name {
type Target = $crate::window::Window;
fn deref(&self) -> &Self::Target {
&self.$window_field
}
}
impl std::ops::DerefMut for $widget_name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.$window_field
}
}
impl $crate::event::WxEvtHandler for $widget_name {
unsafe fn get_event_handler_ptr(&self) -> *mut wxdragon_sys::wxd_EvtHandler_t {
self.$window_field.get_event_handler_ptr()
}
}
};
}
#[macro_export]
macro_rules! implement_widget_traits_with_target {
($widget_name:ident, $window_field:ident, $target_ty:ty) => {
impl $crate::window::WxWidget for $widget_name {
fn handle_ptr(&self) -> *mut wxdragon_sys::wxd_Window_t {
self.$window_field.handle_ptr()
}
}
impl std::ops::Deref for $widget_name {
type Target = $target_ty;
fn deref(&self) -> &Self::Target {
&self.$window_field
}
}
impl std::ops::DerefMut for $widget_name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.$window_field
}
}
impl $crate::event::WxEvtHandler for $widget_name {
unsafe fn get_event_handler_ptr(&self) -> *mut wxdragon_sys::wxd_EvtHandler_t {
unsafe { self.$window_field.get_event_handler_ptr() }
}
}
impl $crate::event::MenuEvents for $widget_name {}
impl $crate::event::WindowEvents for $widget_name {}
};
}
#[macro_export]
macro_rules! widget_style_enum {
(
name: $name:ident,
doc: $doc:expr,
variants: {
$(
$variant:ident: $value:expr, $variant_doc:expr
),+
},
default_variant: $default:ident
) => {
bitflags::bitflags! {
#[doc = $doc]
#[doc = "\n\nThese flags can be combined using the bitwise OR operator (`|`)."]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $name : i64 {
$(
#[doc = $variant_doc]
const $variant = $value;
)+
}
}
impl Default for $name {
fn default() -> Self {
$name::$default
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __widget_builder_field_method {
($field_name:ident: String) => {
paste::paste! {
#[allow(non_snake_case)]
pub fn [<with_ $field_name>](mut self, $field_name: &str) -> Self {
self.$field_name = $field_name.to_string();
self
}
}
};
($field_name:ident: $field_type:ty) => {
paste::paste! {
#[allow(non_snake_case)]
pub fn [<with_ $field_name>](mut self, $field_name: $field_type) -> Self {
self.$field_name = $field_name;
self
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __widget_builder_default {
() => {
Default::default()
};
($expr:expr) => {
$expr
};
}
#[macro_export]
#[cfg(feature = "xrc")]
macro_rules! impl_xrc_support {
($widget_name:ident, { window }) => {
#[cfg(feature = "xrc")]
impl $crate::xrc::XrcSupport for $widget_name {
unsafe fn from_xrc_ptr(ptr: *mut wxdragon_sys::wxd_Window_t) -> Self {
let window = unsafe { $crate::window::Window::from_ptr(ptr) };
Self { window }
}
}
};
($widget_name:ident, { window, $($field_name:ident: $field_value:expr),* $(,)? }) => {
#[cfg(feature = "xrc")]
impl $crate::xrc::XrcSupport for $widget_name {
unsafe fn from_xrc_ptr(ptr: *mut wxdragon_sys::wxd_Window_t) -> Self {
let window = unsafe { $crate::window::Window::from_ptr(ptr) };
Self {
window,
$(
$field_name: $field_value,
)*
}
}
}
};
}
#[macro_export]
#[cfg(not(feature = "xrc"))]
macro_rules! impl_xrc_support {
($widget_name:ident, { window }) => {};
($widget_name:ident, { window, $($field_name:ident: $field_value:expr),* $(,)? }) => {};
}
#[macro_export]
macro_rules! custom_widget {
(
name: $name:ident,
fields: {
$(
$field_name:ident: $field_type:ty = $field_default:expr
),* $(,)?
},
setup_impl: |$config_param:ident, $panel_param:ident| $setup_impl:block
) => {
paste::paste! {
#[derive(Debug, Clone)]
pub struct [<$name Config>] {
$(
pub $field_name: $field_type,
)*
}
impl Default for [<$name Config>] {
fn default() -> Self {
Self {
$(
$field_name: $field_default,
)*
}
}
}
#[derive(Clone)]
pub struct [<$name Builder>]<'a> {
parent: &'a dyn $crate::window::WxWidget,
size: $crate::geometry::Size,
$(
$field_name: $field_type,
)*
}
impl<'a> [<$name Builder>]<'a> {
pub fn new(parent: &'a dyn $crate::window::WxWidget) -> Self {
Self {
parent,
size: $crate::geometry::Size::DEFAULT_SIZE,
$(
$field_name: $field_default,
)*
}
}
pub fn with_size(mut self, size: $crate::geometry::Size) -> Self {
self.size = size;
self
}
$(
paste::paste! {
pub fn [<with_ $field_name>](mut self, $field_name: $field_type) -> Self {
self.$field_name = $field_name;
self
}
}
)*
pub fn build(self) -> $name {
let panel = $crate::widgets::panel::Panel::builder(self.parent)
.with_size(self.size)
.build();
let config = [<$name Config>] {
$(
$field_name: self.$field_name,
)*
};
let widget = $name {
panel: panel.clone(),
config: config.clone(),
};
let setup_fn = |$config_param: [<$name Config>], $panel_param: $crate::widgets::panel::Panel| $setup_impl;
setup_fn(config, panel);
widget
}
}
pub struct $name {
panel: $crate::widgets::panel::Panel,
config: [<$name Config>],
}
impl $name {
pub fn config(&self) -> &[<$name Config>] {
&self.config
}
pub fn builder(parent: &dyn $crate::window::WxWidget) -> [<$name Builder>]<'_> {
[<$name Builder>]::new(parent)
}
}
impl $crate::window::WxWidget for $name {
fn handle_ptr(&self) -> *mut $crate::ffi::wxd_Window_t {
self.panel.handle_ptr()
}
}
impl std::ops::Deref for $name {
type Target = $crate::widgets::panel::Panel;
fn deref(&self) -> &Self::Target {
&self.panel
}
}
impl std::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.panel
}
}
impl $crate::event::WxEvtHandler for $name {
unsafe fn get_event_handler_ptr(&self) -> *mut $crate::ffi::wxd_EvtHandler_t {
unsafe { self.panel.get_event_handler_ptr() }
}
}
}
};
}
#[macro_export]
macro_rules! impl_widget_cast {
($widget:ident, $class_name:literal, composition) => {
impl $crate::window::FromWindowWithClassName for $widget {
fn class_name() -> &'static str {
$class_name
}
unsafe fn from_ptr(ptr: *mut wxdragon_sys::wxd_Window_t) -> Self {
let window = unsafe { $crate::window::Window::from_ptr(ptr) };
Self::new_from_composition(window, std::ptr::null_mut())
}
}
};
($widget:ident, $class_name:literal, { $field:ident }) => {
impl $crate::window::FromWindowWithClassName for $widget {
fn class_name() -> &'static str {
$class_name
}
unsafe fn from_ptr(ptr: *mut wxdragon_sys::wxd_Window_t) -> Self {
let $field = unsafe { $crate::window::Window::from_ptr(ptr) };
Self { $field }
}
}
};
}
#[macro_export]
macro_rules! impl_refcounted_object {
(@base $ty:ty, $ptr_field:ident, $ptr_ty:ty, $add_ref:path, $get_refcount:path, $release:path $(, $other_field:ident )* ) => {
impl Clone for $ty {
fn clone(&self) -> Self {
if !self.$ptr_field.is_null() {
unsafe { $add_ref(self.$ptr_field) };
}
Self {
$ptr_field: self.$ptr_field,
$( $other_field: self.$other_field.clone(), )*
}
}
}
impl Drop for $ty {
fn drop(&mut self) {
if !self.$ptr_field.is_null() {
let count = unsafe { $get_refcount(self.$ptr_field) } - 1;
let text = if count == 0 { "it destroyed" } else { "it still alive" };
log::debug!(
"{} dropped, inner object RefCount is {} now, {}.",
stringify!($ty),
count,
text
);
unsafe { $release(self.$ptr_field) };
}
}
}
impl AsRef<*mut $ptr_ty> for $ty {
fn as_ref(&self) -> &*mut $ptr_ty {
&self.$ptr_field
}
}
impl std::ops::Deref for $ty {
type Target = *mut $ptr_ty;
fn deref(&self) -> &Self::Target {
&self.$ptr_field
}
}
};
($ty:ty, $ptr_field:ident, $ptr_ty:ty, $add_ref:path, $get_refcount:path, $release:path $(, $other_field:ident )* ) => {
impl_refcounted_object!(@base $ty, $ptr_field, $ptr_ty, $add_ref, $get_refcount, $release $(, $other_field )* );
};
(send_sync $ty:ty, $ptr_field:ident, $ptr_ty:ty, $add_ref:path, $get_refcount:path, $release:path $(, $other_field:ident )* ) => {
impl_refcounted_object!(@base $ty, $ptr_field, $ptr_ty, $add_ref, $get_refcount, $release $(, $other_field )* );
unsafe impl Send for $ty {}
unsafe impl Sync for $ty {}
};
}