macro_rules! id_newtype {
($(#[$meta:meta])* $vis:vis $Name:ident) => {
$(#[$meta])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
$vis struct $Name(u32);
impl $Name {
pub fn from_raw(raw: u32) -> Self {
Self(raw)
}
pub fn raw(self) -> u32 {
self.0
}
}
impl std::fmt::Display for $Name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
};
}
pub(crate) use id_newtype;
macro_rules! builder_setters {
($( $(#[$doc:meta])* $field:ident ($param:ident : $ty:ty) );+ $(;)?) => {
$(
$(#[$doc])*
pub fn $field(mut self, $param: $ty) -> Self {
self.$field = $param;
self
}
)+
};
}
macro_rules! builder_mapped_setters {
($( $(#[$doc:meta])* $method:ident ($param:ident : $ty:ty) -> $field:ident = $val:expr );+ $(;)?) => {
$(
$(#[$doc])*
pub fn $method(mut self, $param: $ty) -> Self {
self.$field = $val;
self
}
)+
};
}
macro_rules! builder_flag_setters {
($( $(#[$doc:meta])* $method:ident -> $field:ident = $val:expr );+ $(;)?) => {
$(
$(#[$doc])*
pub fn $method(mut self) -> Self {
self.$field = $val;
self
}
)+
};
}
pub(crate) use builder_flag_setters;
pub(crate) use builder_mapped_setters;
pub(crate) use builder_setters;
#[macro_export]
macro_rules! layout {
(row(gap: $gap:expr) { $($children:tt)* }) => {
$crate::layout!(@root_gap row_gap [$gap] $($children)*)
};
(row { $($children:tt)* }) => {
$crate::layout!(@root row $($children)*)
};
(col(gap: $gap:expr) { $($children:tt)* }) => {
$crate::layout!(@root_gap col_gap [$gap] $($children)*)
};
(col { $($children:tt)* }) => {
$crate::layout!(@root col $($children)*)
};
(grid($($config:tt)*) { $($children:tt)* }) => {
$crate::Layout::build_grid(
$crate::layout!(@grid_config $($config)*),
|__gctx| { $crate::layout!(@grid_children __gctx $($children)*); },
)
};
(@root $dir:ident $($children:tt)*) => {
(|| -> ::core::result::Result<$crate::Layout, $crate::PaneError> {
let mut __builder = $crate::LayoutBuilder::new();
__builder.$dir(|__ctx| {
$crate::layout!(@children __ctx $($children)*);
})?;
__builder.build()
})()
};
(@root_gap $dir:ident [$gap:expr] $($children:tt)*) => {
(|| -> ::core::result::Result<$crate::Layout, $crate::PaneError> {
let mut __builder = $crate::LayoutBuilder::new();
__builder.$dir($gap, |__ctx| {
$crate::layout!(@children __ctx $($children)*);
})?;
__builder.build()
})()
};
(@children $ctx:ident) => {};
(@children $ctx:ident panel($kind:expr, grow: $val:expr, $($mods:tt)+) $($rest:tt)*) => {
$ctx.panel_with($kind, $crate::layout!(@apply $crate::grow($val), $($mods)+));
$crate::layout!(@children $ctx $($rest)*);
};
(@children $ctx:ident panel($kind:expr, grow: $val:expr) $($rest:tt)*) => {
$ctx.panel_with($kind, $crate::grow($val));
$crate::layout!(@children $ctx $($rest)*);
};
(@children $ctx:ident panel($kind:expr, fixed: $val:expr, $($mods:tt)+) $($rest:tt)*) => {
$ctx.panel_with($kind, $crate::layout!(@apply $crate::fixed($val), $($mods)+));
$crate::layout!(@children $ctx $($rest)*);
};
(@children $ctx:ident panel($kind:expr, fixed: $val:expr) $($rest:tt)*) => {
$ctx.panel_with($kind, $crate::fixed($val));
$crate::layout!(@children $ctx $($rest)*);
};
(@children $ctx:ident panel($kind:expr) $($rest:tt)*) => {
$ctx.panel($kind);
$crate::layout!(@children $ctx $($rest)*);
};
(@children $ctx:ident grid($($config:tt)*) { $($inner:tt)* } $($rest:tt)*) => {
$ctx.grid($crate::layout!(@grid_config $($config)*), |__gctx| {
$crate::layout!(@grid_children __gctx $($inner)*);
});
$crate::layout!(@children $ctx $($rest)*);
};
(@children $ctx:ident row(gap: $gap:expr) { $($inner:tt)* } $($rest:tt)*) => {
$crate::layout!(@nested_gap $ctx row_gap [$gap] { $($inner)* } $($rest)*);
};
(@children $ctx:ident row { $($inner:tt)* } $($rest:tt)*) => {
$crate::layout!(@nested $ctx row { $($inner)* } $($rest)*);
};
(@children $ctx:ident col(gap: $gap:expr) { $($inner:tt)* } $($rest:tt)*) => {
$crate::layout!(@nested_gap $ctx col_gap [$gap] { $($inner)* } $($rest)*);
};
(@children $ctx:ident col { $($inner:tt)* } $($rest:tt)*) => {
$crate::layout!(@nested $ctx col { $($inner)* } $($rest)*);
};
(@nested $ctx:ident $dir:ident { $($inner:tt)* } $($rest:tt)*) => {
$ctx.$dir(|__ctx| {
$crate::layout!(@children __ctx $($inner)*);
});
$crate::layout!(@children $ctx $($rest)*);
};
(@nested_gap $ctx:ident $dir:ident [$gap:expr] { $($inner:tt)* } $($rest:tt)*) => {
$ctx.$dir($gap, |__ctx| {
$crate::layout!(@children __ctx $($inner)*);
});
$crate::layout!(@children $ctx $($rest)*);
};
(@apply $c:expr, min: $v:expr, $($rest:tt)+) => {
$crate::layout!(@apply $c.min($v), $($rest)+)
};
(@apply $c:expr, min: $v:expr) => { $c.min($v) };
(@apply $c:expr, max: $v:expr, $($rest:tt)+) => {
$crate::layout!(@apply $c.max($v), $($rest)+)
};
(@apply $c:expr, max: $v:expr) => { $c.max($v) };
(@apply $c:expr, min_width: $v:expr, $($rest:tt)+) => {
$crate::layout!(@apply $c.min_width($v), $($rest)+)
};
(@apply $c:expr, min_width: $v:expr) => { $c.min_width($v) };
(@apply $c:expr, max_width: $v:expr, $($rest:tt)+) => {
$crate::layout!(@apply $c.max_width($v), $($rest)+)
};
(@apply $c:expr, max_width: $v:expr) => { $c.max_width($v) };
(@apply $c:expr, min_height: $v:expr, $($rest:tt)+) => {
$crate::layout!(@apply $c.min_height($v), $($rest)+)
};
(@apply $c:expr, min_height: $v:expr) => { $c.min_height($v) };
(@apply $c:expr, max_height: $v:expr, $($rest:tt)+) => {
$crate::layout!(@apply $c.max_height($v), $($rest)+)
};
(@apply $c:expr, max_height: $v:expr) => { $c.max_height($v) };
(@apply $c:expr, align: $v:ident, $($rest:tt)+) => {
$crate::layout!(@apply $c.align($crate::layout!(@align $v)), $($rest)+)
};
(@apply $c:expr, align: $v:ident) => { $c.align($crate::layout!(@align $v)) };
(@apply $c:expr, size_mode: $v:ident, $($rest:tt)+) => {
$crate::layout!(@apply $c.size_mode($crate::layout!(@size_mode $v)), $($rest)+)
};
(@apply $c:expr, size_mode: $v:ident) => { $c.size_mode($crate::layout!(@size_mode $v)) };
(@apply $c:expr, size_mode: fit_content($v:expr), $($rest:tt)+) => {
$crate::layout!(@apply $c.size_mode($crate::SizeMode::FitContent($v)), $($rest)+)
};
(@apply $c:expr, size_mode: fit_content($v:expr)) => { $c.size_mode($crate::SizeMode::FitContent($v)) };
(@grid_config columns: $n:expr $(, $($rest:tt)*)?) => {
$crate::layout!(@grid_apply $crate::Grid::columns($n) $(, $($rest)*)?)
};
(@grid_config auto_fit: $w:expr $(, $($rest:tt)*)?) => {
$crate::layout!(@grid_apply $crate::Grid::auto_fit($w) $(, $($rest)*)?)
};
(@grid_config auto_fill: $w:expr $(, $($rest:tt)*)?) => {
$crate::layout!(@grid_apply $crate::Grid::auto_fill($w) $(, $($rest)*)?)
};
(@grid_apply $g:expr) => { $g };
(@grid_apply $g:expr, gap: $v:expr $(, $($rest:tt)*)?) => {
$crate::layout!(@grid_apply $g.gap($v) $(, $($rest)*)?)
};
(@grid_apply $g:expr, auto_rows: true $(, $($rest:tt)*)?) => {
$crate::layout!(@grid_apply $g.auto_rows() $(, $($rest)*)?)
};
(@grid_children $gctx:ident) => {};
(@grid_children $gctx:ident panel($kind:expr, span: $n:expr) $($rest:tt)*) => {
$gctx.panel_span($kind, $crate::CardSpan::Columns($n));
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident panel($kind:expr, full_width: true) $($rest:tt)*) => {
$gctx.panel_span($kind, $crate::CardSpan::FullWidth);
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident panel($kind:expr, grow: $val:expr) $($rest:tt)*) => {
$gctx.panel_with($kind, $crate::grow($val));
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident panel($kind:expr, fixed: $val:expr) $($rest:tt)*) => {
$gctx.panel_with($kind, $crate::fixed($val));
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident panel($kind:expr) $($rest:tt)*) => {
$gctx.panel($kind);
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident row(gap: $gap:expr) { $($inner:tt)* } $($rest:tt)*) => {
$gctx.row_gap($gap, |__ctx| {
$crate::layout!(@children __ctx $($inner)*);
});
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident row { $($inner:tt)* } $($rest:tt)*) => {
$gctx.row(|__ctx| {
$crate::layout!(@children __ctx $($inner)*);
});
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident col(gap: $gap:expr) { $($inner:tt)* } $($rest:tt)*) => {
$gctx.col_gap($gap, |__ctx| {
$crate::layout!(@children __ctx $($inner)*);
});
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident col { $($inner:tt)* } $($rest:tt)*) => {
$gctx.col(|__ctx| {
$crate::layout!(@children __ctx $($inner)*);
});
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@grid_children $gctx:ident grid($($config:tt)*) { $($inner:tt)* } $($rest:tt)*) => {
$gctx.grid($crate::layout!(@grid_config $($config)*), |__gctx| {
$crate::layout!(@grid_children __gctx $($inner)*);
});
$crate::layout!(@grid_children $gctx $($rest)*);
};
(@align start) => { $crate::Align::Start };
(@align center) => { $crate::Align::Center };
(@align end) => { $crate::Align::End };
(@align stretch) => { $crate::Align::Stretch };
(@size_mode min_content) => { $crate::SizeMode::MinContent };
(@size_mode max_content) => { $crate::SizeMode::MaxContent };
}
#[macro_export]
macro_rules! impl_adapter {
(
rect: $target_rect:ty,
origin: $origin_ty:ty,
convert_fn: $convert:expr,
convert_at_fn: $convert_at:expr $(,)?
) => {
pub fn convert(
resolved: &$crate::ResolvedLayout,
) -> $crate::__FxHashMap<$crate::PanelId, $target_rect> {
resolved
.iter()
.map(|(pid, r)| (pid, ($convert)(r)))
.collect()
}
pub fn panels(
resolved: &$crate::ResolvedLayout,
) -> impl Iterator<Item = $crate::PanelEntry<'_, $target_rect>> {
resolved.panels().map(|e| e.map_rect($convert))
}
pub fn panels_at(
resolved: &$crate::ResolvedLayout,
origin: $origin_ty,
) -> impl Iterator<Item = $crate::PanelEntry<'_, $target_rect>> {
resolved
.panels()
.map(move |e| e.map_rect(|r| ($convert_at)(r, origin)))
}
pub fn overlays(
resolved: &$crate::ResolvedLayout,
) -> impl Iterator<Item = $crate::OverlayEntry<'_, $target_rect>> {
resolved.overlays().map(|e| e.map_rect($convert))
}
pub fn overlays_at(
resolved: &$crate::ResolvedLayout,
origin: $origin_ty,
) -> impl Iterator<Item = $crate::OverlayEntry<'_, $target_rect>> {
resolved
.overlays()
.map(move |e| e.map_rect(|r| ($convert_at)(r, origin)))
}
};
}