use std::f64::consts::PI;
use crate::{Color, Colorable, Point, Positionable, Range, Rect, Scalar};
use crate::draw::shape::circumference::Circumference;
use crate::position::Dimensions;
use crate::widget;
use crate::widget::primitive::shape::Style;
#[derive(Copy, Clone, Debug, WidgetCommon_)]
pub struct RoundedRectangle {
#[carbide(common_builder)]
pub common: widget::CommonBuilder,
pub style: Style,
pub radius: Scalar,
pub corner_resolution: usize,
}
widget_ids! {
struct Ids { polygon }
}
pub const DEFAULT_CORNER_RESOLUTION: usize = 12;
pub struct State {
ids: Ids,
}
impl RoundedRectangle {
pub fn styled(_dim: Dimensions, radius: Scalar, style: Style) -> Self {
RoundedRectangle {
common: widget::CommonBuilder::default(),
style: style,
radius: radius,
corner_resolution: DEFAULT_CORNER_RESOLUTION,
} }
pub fn fill(dim: Dimensions, radius: Scalar) -> Self {
RoundedRectangle::styled(dim, radius, Style::fill())
}
pub fn fill_with(dim: Dimensions, radius: Scalar, color: Color) -> Self {
RoundedRectangle::styled(dim, radius, Style::fill_with(color))
}
pub fn outline(dim: Dimensions, radius: Scalar) -> Self {
RoundedRectangle::styled(dim, radius, Style::outline())
}
pub fn outline_styled(dim: Dimensions, radius: Scalar, line_style: widget::line::Style) -> Self {
RoundedRectangle::styled(dim, radius, Style::outline_styled(line_style))
}
pub fn corner_resolution(mut self, res: usize) -> Self {
self.corner_resolution = res;
self
}
}
impl Colorable for RoundedRectangle {
fn color(mut self, color: Color) -> Self {
self.style.set_color(color);
self
}
}
#[derive(Clone)]
pub struct Points {
rect: Rect,
corner_rect: Rect,
corner_index: usize,
corner_resolution: usize,
corner_points: Circumference,
}
const CORNER_RADIANS: Scalar = PI * 0.5;
pub fn points(rect: Rect, radius: Scalar, corner_resolution: usize) -> Points {
let (r, t) = (rect.x.end, rect.y.end);
let radius_2 = radius * 2.0;
let corner_rect = Rect {
x: Range { start: r - radius_2, end: r },
y: Range { start: t - radius_2, end: t },
};
let corner = Circumference::new_section(corner_rect, corner_resolution, CORNER_RADIANS);
Points {
rect,
corner_rect,
corner_index: 0,
corner_resolution,
corner_points: corner,
}
}
impl Iterator for Points {
type Item = Point;
fn next(&mut self) -> Option<Self::Item> {
let Points {
ref mut corner_rect,
ref mut corner_index,
ref mut corner_points,
corner_resolution,
rect,
} = *self;
loop {
if let Some(point) = corner_points.next() {
return Some(point);
}
*corner_rect = match *corner_index {
0 => corner_rect.align_left_of(rect),
1 => corner_rect.align_bottom_of(rect),
2 => corner_rect.align_right_of(rect),
_ => return None,
};
*corner_index += 1;
let offset_radians = *corner_index as Scalar * CORNER_RADIANS;
*corner_points = Circumference::new_section(*corner_rect, corner_resolution, CORNER_RADIANS)
.offset_radians(offset_radians);
}
}
}
pub type Triangles = widget::polygon::Triangles<Points>;