use gpui::prelude::FluentBuilder;
use gpui::*;
use crate::theme::*;
use crate::components::basic::icon::{Icon, IconName};
#[derive(Clone, Debug)]
pub enum CheckboxEvent {
Changed(bool),
}
impl EventEmitter<CheckboxEvent> for Checkbox {}
pub struct Checkbox {
label: Option<String>,
checked: bool,
disabled: bool,
size: ComponentSize,
custom_text_color: Option<Rgba>,
}
impl Checkbox {
pub fn new(_cx: &mut Context<Self>) -> Self {
Self {
label: None,
checked: false,
disabled: false,
size: ComponentSize::Medium,
custom_text_color: None,
}
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn checked(mut self, checked: bool) -> Self {
self.checked = checked;
self
}
pub fn disabled(mut self, disabled: bool) -> Self {
self.disabled = disabled;
self
}
pub fn size(mut self, size: ComponentSize) -> Self {
self.size = size;
self
}
pub fn text_color(mut self, color: Rgba) -> Self {
self.custom_text_color = Some(color);
self
}
fn toggle(&mut self, cx: &mut Context<Self>) {
if !self.disabled {
self.checked = !self.checked;
cx.emit(CheckboxEvent::Changed(self.checked));
cx.notify();
}
}
fn box_size(&self) -> Pixels {
match self.size {
ComponentSize::XSmall => px(14.0),
ComponentSize::Small => px(16.0),
ComponentSize::Medium => px(18.0),
ComponentSize::Large => px(20.0),
ComponentSize::XLarge => px(22.0),
}
}
}
impl Render for Checkbox {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let theme = Theme::default();
let checked = self.checked;
let disabled = self.disabled;
let label = self.label.clone();
let box_size = self.box_size();
let text_size = self.size.font_size();
div()
.id("checkbox")
.flex()
.items_center()
.gap_2()
.cursor(if disabled { CursorStyle::Arrow } else { CursorStyle::PointingHand })
.when(disabled, |this| {
this.opacity(0.64)
})
.on_mouse_down(MouseButton::Left, cx.listener(|this, _event: &MouseDownEvent, _window, cx| {
this.toggle(cx);
}))
.child(
div()
.flex()
.items_center()
.justify_center()
.size(box_size)
.rounded(px(4.))
.border_1()
.border_color(if checked {
theme.colors.primary
} else {
theme.colors.border
})
.bg(if checked {
theme.colors.primary
} else {
rgb(0xFFFFFF)
})
.when(checked, |this| {
this.child(
Icon::new(IconName::Check)
.size(crate::components::basic::icon::IconSize::Small)
.color(rgb(0xFFFFFF))
)
})
)
.when_some(label, |this, label| {
this.child(
div()
.text_size(text_size)
.text_color(self.custom_text_color.unwrap_or(theme.colors.text))
.child(label)
)
})
}
}