use crate::{Color, Colorable, FontSize, Labelable};
use crate::image;
use crate::position::{self, Align, Rect, Scalar};
use crate::text;
use crate::widget;
#[derive(Clone, WidgetCommon_)]
pub struct Button<'a, S> {
#[carbide(common_builder)]
common: widget::CommonBuilder,
maybe_label: Option<&'a str>,
pub show: S,
pub style: Style,
enabled: bool,
}
#[derive(Copy, Clone, Debug, Default, PartialEq, WidgetStyle_)]
pub struct Style {
#[carbide(default = "theme.shape_color")]
pub color: Option<Color>,
#[carbide(default = "theme.border_width")]
pub border: Option<Scalar>,
#[carbide(default = "theme.border_color")]
pub border_color: Option<Color>,
#[carbide(default = "theme.label_color")]
pub label_color: Option<Color>,
#[carbide(default = "theme.font_size_medium")]
pub label_font_size: Option<FontSize>,
#[carbide(default = "theme.font_id")]
pub label_font_id: Option<Option<text::font::Id>>,
#[carbide(default = "text::Justify::Center")]
pub label_justify: Option<text::Justify>,
#[carbide(default = "position::Relative::Align(Align::Middle)")]
pub label_x: Option<position::Relative>,
#[carbide(default = "position::Relative::Align(Align::Middle)")]
pub label_y: Option<position::Relative>,
}
widget_ids! {
#[allow(missing_docs, missing_copy_implementations)]
pub struct FlatIds {
rectangle,
label,
}
}
widget_ids! {
#[allow(missing_docs, missing_copy_implementations)]
pub struct ImageIds {
image,
label,
}
}
#[derive(Copy, Clone, Default, PartialEq, Debug)]
pub struct Flat {
pub hover_color: Option<Color>,
pub press_color: Option<Color>,
}
#[derive(Copy, Clone)]
pub struct Image {
pub image_id: image::Id,
pub hover_image_id: Option<image::Id>,
pub press_image_id: Option<image::Id>,
pub color: ImageColor,
pub src_rect: Option<Rect>,
}
#[derive(Copy, Clone, Debug)]
pub enum ImageColor {
Normal(Color),
WithFeedback(Color),
None,
}
#[derive(Copy, Clone)]
enum Interaction { Idle, Hover, Press }
#[derive(Clone, Debug)]
#[allow(missing_copy_implementations)]
pub struct TimesClicked(pub u16);
impl TimesClicked {
pub fn was_clicked(self) -> bool { self.0 > 0 }
}
impl Iterator for TimesClicked {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
if self.0 > 0 {
self.0 -= 1;
Some(())
} else {
None
}
}
}
impl<'a> Button<'a, Image> {
pub fn image(image_id: image::Id) -> Self {
let image = Image {
image_id: image_id,
hover_image_id: None,
press_image_id: None,
src_rect: None,
color: ImageColor::None,
};
Self::new_internal(image)
}
pub fn source_rectangle(mut self, rect: Rect) -> Self {
self.show.src_rect = Some(rect);
self
}
pub fn image_color(mut self, color: Color) -> Self {
self.show.color = ImageColor::Normal(color);
self
}
pub fn image_color_with_feedback(mut self, color: Color) -> Self {
self.show.color = ImageColor::WithFeedback(color);
self
}
pub fn hover_image(mut self, id: image::Id) -> Self {
self.show.hover_image_id = Some(id);
self
}
pub fn press_image(mut self, id: image::Id) -> Self {
self.show.press_image_id = Some(id);
self
}
}
impl<'a> Button<'a, Flat> {
pub fn new() -> Self {
Self::new_internal(Flat::default())
}
pub fn with_style(mut self, s: Style) -> Self {
self.style = s;
self
}
pub fn hover_color(mut self, color: Color) -> Self {
self.show.hover_color = Some(color);
self
}
pub fn press_color(mut self, color: Color) -> Self {
self.show.press_color = Some(color);
self
}
}
impl<'a, S> Button<'a, S> {
fn new_internal(show: S) -> Self {
Button {
common: widget::CommonBuilder::default(),
show: show,
maybe_label: None,
style: Style::default(),
enabled: true,
}
}
pub fn label_font_id(mut self, font_id: text::font::Id) -> Self {
self.style.label_font_id = Some(Some(font_id));
self
}
pub fn left_justify_label(mut self) -> Self {
self.style.label_justify = Some(text::Justify::Left);
self
}
pub fn center_justify_label(mut self) -> Self {
self.style.label_justify = Some(text::Justify::Center);
self
}
pub fn right_justify_label(mut self) -> Self {
self.style.label_justify = Some(text::Justify::Right);
self
}
pub fn label_x(mut self, x: position::Relative) -> Self {
self.style.label_x = Some(x);
self
}
pub fn label_y(mut self, y: position::Relative) -> Self {
self.style.label_y = Some(y);
self
}
builder_methods!{
pub enabled { enabled = bool }
}
}
impl<'a, S> Colorable for Button<'a, S> {
builder_method!(color { style.color = Some(Color) });
}
impl<'a, S> Borderable for Button<'a, S> {
builder_methods!{
border { style.border = Some(Scalar) }
border_color { style.border_color = Some(Color) }
}
}
impl<'a, S> Labelable<'a> for Button<'a, S> {
builder_methods!{
label { maybe_label = Some(&'a str) }
label_color { style.label_color = Some(Color) }
label_font_size { style.label_font_size = Some(FontSize) }
}
}