mod interaction;
mod layout;
mod semantics;
mod shadow;
mod visual;
use tessera_ui::{Color, DimensionValue, Dp, Modifier, Px, use_context};
use crate::shape_def::Shape;
use interaction::{
modifier_block_touch_propagation, modifier_clickable, modifier_selectable, modifier_toggleable,
};
use layout::{
modifier_constraints, modifier_minimum_interactive_size, modifier_offset, modifier_padding,
};
use visual::{modifier_alpha, modifier_background, modifier_border, modifier_clip_to_bounds};
pub use interaction::{
ClickableArgs, InteractionState, PointerEventContext, SelectableArgs, ToggleableArgs,
};
pub use layout::{MinimumInteractiveComponentEnforcement, Padding};
pub use semantics::SemanticsArgs;
pub use shadow::ShadowArgs;
pub trait ModifierExt {
fn padding(self, padding: Padding) -> Modifier;
fn padding_all(self, padding: Dp) -> Modifier;
fn padding_symmetric(self, horizontal: Dp, vertical: Dp) -> Modifier;
fn offset(self, x: Dp, y: Dp) -> Modifier;
fn alpha(self, alpha: f32) -> Modifier;
fn clip_to_bounds(self) -> Modifier;
fn background(self, color: Color) -> Modifier;
fn background_with_shape(self, color: Color, shape: Shape) -> Modifier;
fn border(self, width: Dp, color: Color) -> Modifier;
fn border_with_shape(self, width: Dp, color: Color, shape: Shape) -> Modifier;
fn shadow(self, args: impl Into<ShadowArgs>) -> Modifier;
fn size(self, width: Dp, height: Dp) -> Modifier;
fn width(self, width: Dp) -> Modifier;
fn height(self, height: Dp) -> Modifier;
fn size_in(
self,
min_width: Option<Dp>,
max_width: Option<Dp>,
min_height: Option<Dp>,
max_height: Option<Dp>,
) -> Modifier;
fn constrain(self, width: Option<DimensionValue>, height: Option<DimensionValue>) -> Modifier;
fn fill_max_width(self) -> Modifier;
fn fill_max_height(self) -> Modifier;
fn fill_max_size(self) -> Modifier;
fn minimum_interactive_component_size(self) -> Modifier;
fn block_touch_propagation(self) -> Modifier;
fn semantics(self, args: SemanticsArgs) -> Modifier;
fn clear_and_set_semantics(self, args: SemanticsArgs) -> Modifier;
fn clickable(self, args: ClickableArgs) -> Modifier;
fn toggleable(self, args: ToggleableArgs) -> Modifier;
fn selectable(self, args: SelectableArgs) -> Modifier;
}
impl ModifierExt for Modifier {
fn padding(self, padding: Padding) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_padding(padding, || {
child();
});
}
})
}
fn padding_all(self, padding: Dp) -> Modifier {
self.padding(Padding::all(padding))
}
fn padding_symmetric(self, horizontal: Dp, vertical: Dp) -> Modifier {
self.padding(Padding::symmetric(horizontal, vertical))
}
fn offset(self, x: Dp, y: Dp) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_offset(x, y, || {
child();
});
}
})
}
fn alpha(self, alpha: f32) -> Modifier {
let alpha = alpha.clamp(0.0, 1.0);
if (alpha - 1.0).abs() <= f32::EPSILON {
return self;
}
self.push_wrapper(move |child| {
move || {
modifier_alpha(alpha, || {
child();
});
}
})
}
fn clip_to_bounds(self) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_clip_to_bounds(|| {
child();
});
}
})
}
fn background(self, color: Color) -> Modifier {
self.background_with_shape(color, Shape::RECTANGLE)
}
fn background_with_shape(self, color: Color, shape: Shape) -> Modifier {
if color.a <= 0.0 {
return self;
}
self.push_wrapper(move |child| {
move || {
modifier_background(color, shape, || {
child();
});
}
})
}
fn border(self, width: Dp, color: Color) -> Modifier {
self.border_with_shape(width, color, Shape::RECTANGLE)
}
fn border_with_shape(self, width: Dp, color: Color, shape: Shape) -> Modifier {
if width.0 <= 0.0 || color.a <= 0.0 {
return self;
}
self.push_wrapper(move |child| {
move || {
modifier_border(width, color, shape, || {
child();
});
}
})
}
fn shadow(self, args: impl Into<ShadowArgs>) -> Modifier {
shadow::apply_shadow_modifier(self, args.into())
}
fn size(self, width: Dp, height: Dp) -> Modifier {
let width_px: Px = width.into();
let height_px: Px = height.into();
self.push_wrapper(move |child| {
move || {
modifier_constraints(
Some(DimensionValue::Wrap {
min: Some(width_px),
max: Some(width_px),
}),
Some(DimensionValue::Wrap {
min: Some(height_px),
max: Some(height_px),
}),
|| {
child();
},
);
}
})
}
fn width(self, width: Dp) -> Modifier {
let width_px: Px = width.into();
self.push_wrapper(move |child| {
move || {
modifier_constraints(
Some(DimensionValue::Wrap {
min: Some(width_px),
max: Some(width_px),
}),
None,
|| {
child();
},
);
}
})
}
fn height(self, height: Dp) -> Modifier {
let height_px: Px = height.into();
self.push_wrapper(move |child| {
move || {
modifier_constraints(
None,
Some(DimensionValue::Wrap {
min: Some(height_px),
max: Some(height_px),
}),
|| {
child();
},
);
}
})
}
fn size_in(
self,
min_width: Option<Dp>,
max_width: Option<Dp>,
min_height: Option<Dp>,
max_height: Option<Dp>,
) -> Modifier {
let width = DimensionValue::Wrap {
min: min_width.map(Into::into),
max: max_width.map(Into::into),
};
let height = DimensionValue::Wrap {
min: min_height.map(Into::into),
max: max_height.map(Into::into),
};
self.push_wrapper(move |child| {
move || {
modifier_constraints(Some(width), Some(height), || {
child();
});
}
})
}
fn constrain(self, width: Option<DimensionValue>, height: Option<DimensionValue>) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_constraints(width, height, || {
child();
});
}
})
}
fn fill_max_width(self) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_constraints(Some(DimensionValue::FILLED), None, || {
child();
});
}
})
}
fn fill_max_height(self) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_constraints(None, Some(DimensionValue::FILLED), || {
child();
});
}
})
}
fn fill_max_size(self) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_constraints(
Some(DimensionValue::FILLED),
Some(DimensionValue::FILLED),
|| {
child();
},
);
}
})
}
fn minimum_interactive_component_size(self) -> Modifier {
if !use_context::<MinimumInteractiveComponentEnforcement>()
.map(|e| e.get().enabled)
.unwrap_or_else(|| MinimumInteractiveComponentEnforcement::default().enabled)
{
return self;
}
self.push_wrapper(move |child| {
move || {
modifier_minimum_interactive_size(|| {
child();
});
}
})
}
fn block_touch_propagation(self) -> Modifier {
self.push_wrapper(move |child| {
move || {
modifier_block_touch_propagation(|| {
child();
});
}
})
}
fn semantics(self, args: SemanticsArgs) -> Modifier {
self.push_wrapper(move |child| {
let args = args.clone();
move || {
semantics::modifier_semantics(args.clone(), || {
child();
});
}
})
}
fn clear_and_set_semantics(self, mut args: SemanticsArgs) -> Modifier {
args.merge_descendants = false;
self.semantics(args)
}
fn clickable(self, args: ClickableArgs) -> Modifier {
self.push_wrapper(move |child| {
let args = args.clone();
move || {
modifier_clickable(args, || {
child();
});
}
})
}
fn toggleable(self, args: ToggleableArgs) -> Modifier {
self.push_wrapper(move |child| {
let args = args.clone();
move || {
modifier_toggleable(args, || {
child();
});
}
})
}
fn selectable(self, args: SelectableArgs) -> Modifier {
self.push_wrapper(move |child| {
let args = args.clone();
move || {
modifier_selectable(args, || {
child();
});
}
})
}
}