use std::sync::Arc;
use derive_builder::Builder;
use tessera_ui::{Color, DimensionValue, Dp, tessera};
use crate::{
fluid_glass::{FluidGlassArgsBuilder, GlassBorder, fluid_glass},
ripple_state::RippleState,
shape_def::Shape,
};
#[derive(Builder, Clone, Default)]
#[builder(pattern = "owned", setter(into, strip_option), default)]
pub struct GlassButtonArgs {
#[builder(setter(strip_option, into = false))]
pub on_click: Option<Arc<dyn Fn() + Send + Sync>>,
#[builder(default = "Color::from_rgb(1.0, 1.0, 1.0)")]
pub ripple_color: Color,
#[builder(default = "Dp(12.0)")]
pub padding: Dp,
#[builder(default = "DimensionValue::WRAP", setter(into))]
pub width: DimensionValue,
#[builder(default = "DimensionValue::WRAP", setter(into))]
pub height: DimensionValue,
#[builder(default = "Color::new(0.5, 0.5, 0.5, 0.1)")]
pub tint_color: Color,
#[builder(
default = "Shape::RoundedRectangle { top_left: Dp(25.0), top_right: Dp(25.0), bottom_right: Dp(25.0), bottom_left: Dp(25.0), g2_k_value: 3.0 }"
)]
pub shape: Shape,
#[builder(default = "Dp(0.0)")]
pub blur_radius: Dp,
#[builder(default = "Dp(25.0)")]
pub dispersion_height: Dp,
#[builder(default = "1.1")]
pub chroma_multiplier: f32,
#[builder(default = "Dp(24.0)")]
pub refraction_height: Dp,
#[builder(default = "32.0")]
pub refraction_amount: f32,
#[builder(default = "0.0")]
pub noise_amount: f32,
#[builder(default = "1.0")]
pub noise_scale: f32,
#[builder(default = "0.0")]
pub time: f32,
#[builder(default, setter(strip_option))]
pub contrast: Option<f32>,
#[builder(default, setter(strip_option))]
pub border: Option<GlassBorder>,
#[builder(default, setter(strip_option, into))]
pub accessibility_label: Option<String>,
#[builder(default, setter(strip_option, into))]
pub accessibility_description: Option<String>,
#[builder(default)]
pub accessibility_focusable: bool,
}
impl GlassButtonArgs {
pub fn primary(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
GlassButtonArgsBuilder::default()
.on_click(on_click)
.tint_color(Color::new(0.2, 0.5, 0.8, 0.2)) .border(GlassBorder::new(Dp(1.0).into()))
.build()
.unwrap()
}
pub fn secondary(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
GlassButtonArgsBuilder::default()
.on_click(on_click)
.tint_color(Color::new(0.6, 0.6, 0.6, 0.2)) .border(GlassBorder::new(Dp(1.0).into()))
.build()
.unwrap()
}
pub fn success(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
GlassButtonArgsBuilder::default()
.on_click(on_click)
.tint_color(Color::new(0.1, 0.7, 0.3, 0.2)) .border(GlassBorder::new(Dp(1.0).into()))
.build()
.unwrap()
}
pub fn danger(on_click: Arc<dyn Fn() + Send + Sync>) -> Self {
GlassButtonArgsBuilder::default()
.on_click(on_click)
.tint_color(Color::new(0.8, 0.2, 0.2, 0.2)) .border(GlassBorder::new(Dp(1.0).into()))
.build()
.unwrap()
}
}
#[tessera]
pub fn glass_button(
args: impl Into<GlassButtonArgs>,
ripple_state: RippleState,
child: impl FnOnce() + Send + Sync + 'static,
) {
let args: GlassButtonArgs = args.into();
let mut glass_args_builder = FluidGlassArgsBuilder::default();
if let Some((progress, center)) = ripple_state.get_animation_progress() {
let ripple_alpha = (1.0 - progress) * 0.3; glass_args_builder = glass_args_builder
.ripple_center(center)
.ripple_radius(progress)
.ripple_alpha(ripple_alpha)
.ripple_strength(progress);
}
if let Some(contrast) = args.contrast {
glass_args_builder = glass_args_builder.contrast(contrast);
}
let mut glass_args = glass_args_builder
.tint_color(args.tint_color)
.shape(args.shape)
.blur_radius(args.blur_radius)
.dispersion_height(args.dispersion_height)
.chroma_multiplier(args.chroma_multiplier)
.refraction_height(args.refraction_height)
.refraction_amount(args.refraction_amount)
.noise_amount(args.noise_amount)
.noise_scale(args.noise_scale)
.width(args.width)
.height(args.height)
.time(args.time)
.padding(args.padding);
if let Some(on_click) = args.on_click {
glass_args = glass_args.on_click(on_click);
}
if let Some(border) = args.border {
glass_args = glass_args.border(border);
}
if let Some(label) = args.accessibility_label {
glass_args = glass_args.accessibility_label(label);
}
if let Some(description) = args.accessibility_description {
glass_args = glass_args.accessibility_description(description);
}
if args.accessibility_focusable {
glass_args = glass_args.accessibility_focusable(true);
}
let glass_args = glass_args.build().unwrap();
fluid_glass(glass_args, Some(ripple_state), child);
}