guise/input/
radiogroup.rs1use std::rc::Rc;
8
9use gpui::prelude::*;
10use gpui::{div, px, App, IntoElement, SharedString, Window};
11
12use super::Radio;
13use crate::theme::{theme, ColorName, Size};
14
15type GroupHandler = Rc<dyn Fn(usize, &mut Window, &mut App) + 'static>;
16
17#[derive(IntoElement)]
19pub struct RadioGroup {
20 options: Vec<SharedString>,
21 value: Option<usize>,
22 color: ColorName,
23 size: Size,
24 label: Option<SharedString>,
25 on_change: Option<GroupHandler>,
26}
27
28impl RadioGroup {
29 pub fn new() -> Self {
30 RadioGroup {
31 options: Vec::new(),
32 value: None,
33 color: ColorName::Blue,
34 size: Size::Sm,
35 label: None,
36 on_change: None,
37 }
38 }
39
40 pub fn options<I, S>(mut self, options: I) -> Self
41 where
42 I: IntoIterator<Item = S>,
43 S: Into<SharedString>,
44 {
45 self.options = options.into_iter().map(Into::into).collect();
46 self
47 }
48
49 pub fn value(mut self, value: usize) -> Self {
51 self.value = Some(value);
52 self
53 }
54
55 pub fn color(mut self, color: ColorName) -> Self {
56 self.color = color;
57 self
58 }
59
60 pub fn size(mut self, size: Size) -> Self {
61 self.size = size;
62 self
63 }
64
65 pub fn label(mut self, label: impl Into<SharedString>) -> Self {
66 self.label = Some(label.into());
67 self
68 }
69
70 pub fn on_change(mut self, handler: impl Fn(usize, &mut Window, &mut App) + 'static) -> Self {
72 self.on_change = Some(Rc::new(handler));
73 self
74 }
75}
76
77impl Default for RadioGroup {
78 fn default() -> Self {
79 RadioGroup::new()
80 }
81}
82
83impl RenderOnce for RadioGroup {
84 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
85 let t = theme(cx);
86 let gap = t.spacing(Size::Xs);
87 let text = t.text().hsla();
88 let font = t.font_size(Size::Sm);
89
90 let mut column = div().flex().flex_col().gap(px(gap));
91 if let Some(label) = self.label.clone() {
92 column = column.child(div().text_size(px(font)).text_color(text).child(label));
93 }
94
95 for (i, option) in self.options.iter().enumerate() {
96 let mut radio = Radio::new(("guise-radiogroup", i))
97 .label(option.clone())
98 .checked(self.value == Some(i))
99 .color(self.color)
100 .size(self.size);
101 if let Some(handler) = self.on_change.clone() {
102 radio = radio.on_change(move |_ev, window, cx| handler(i, window, cx));
103 }
104 column = column.child(radio);
105 }
106 column
107 }
108}