116 lines · 3.7 KB · Rust
RawDownload
mod checkbox_with_label; pub use checkbox_with_label::*; use gpui::{div, prelude::*, ElementId, IntoElement, Styled, WindowContext}; use crate::prelude::*;use crate::{Color, Icon, IconName, Selection}; /// # Checkbox////// Checkboxes are used for multiple choices, not for mutually exclusive choices./// Each checkbox works independently from other checkboxes in the list,/// therefore checking an additional box does not affect any other selections.#[derive(IntoElement)]pub struct Checkbox {    id: ElementId,    checked: Selection,    disabled: bool,    on_click: Option<Box<dyn Fn(&Selection, &mut WindowContext) + 'static>>,} impl Checkbox {    pub fn new(id: impl Into<ElementId>, checked: Selection) -> Self {        Self {            id: id.into(),            checked,            disabled: false,            on_click: None,        }    }     pub fn disabled(mut self, disabled: bool) -> Self {        self.disabled = disabled;        self    }     pub fn on_click(mut self, handler: impl Fn(&Selection, &mut WindowContext) + 'static) -> Self {        self.on_click = Some(Box::new(handler));        self    }} impl RenderOnce for Checkbox {    fn render(self, cx: &mut WindowContext) -> impl IntoElement {        let group_id = format!("checkbox_group_{:?}", self.id);         let icon = match self.checked {            Selection::Selected => Some(Icon::new(IconName::Check).size(IconSize::Small).color(                if self.disabled {                    Color::Disabled                } else {                    Color::Selected                },            )),            Selection::Indeterminate => Some(                Icon::new(IconName::Dash)                    .size(IconSize::Small)                    .color(if self.disabled {                        Color::Disabled                    } else {                        Color::Selected                    }),            ),            Selection::Unselected => None,        };         let selected =            self.checked == Selection::Selected || self.checked == Selection::Indeterminate;         let (bg_color, border_color) = match (self.disabled, selected) {            (true, _) => (                cx.theme().colors().ghost_element_disabled,                cx.theme().colors().border_disabled,            ),            (false, true) => (                cx.theme().colors().element_selected,                cx.theme().colors().border,            ),            (false, false) => (                cx.theme().colors().element_background,                cx.theme().colors().border,            ),        };         h_flex()            .id(self.id)            .justify_center()            .items_center()            .size(crate::styles::custom_spacing(cx, 20.))            .group(group_id.clone())            .child(                div()                    .flex()                    .flex_none()                    .justify_center()                    .items_center()                    .m(Spacing::Small.px(cx))                    .size(crate::styles::custom_spacing(cx, 16.))                    .rounded_sm()                    .bg(bg_color)                    .border_1()                    .border_color(border_color)                    .when(!self.disabled, |this| {                        this.group_hover(group_id.clone(), |el| {                            el.bg(cx.theme().colors().element_hover)                        })                    })                    .children(icon),            )            .when_some(                self.on_click.filter(|_| !self.disabled),                |this, on_click| this.on_click(move |_, cx| on_click(&self.checked.inverse(), cx)),            )    }}