freya_components/
radio_item.rs1use freya_core::prelude::*;
2use torin::prelude::*;
3
4use crate::{
5 get_theme,
6 theming::component_themes::{
7 RadioItemTheme,
8 RadioItemThemePartial,
9 },
10};
11
12#[cfg_attr(feature = "docs",
47 doc = embed_doc_image::embed_image!("radio", "images/gallery_radio.png")
48)]
49#[derive(Clone, PartialEq)]
50pub struct RadioItem {
51 pub(crate) theme: Option<RadioItemThemePartial>,
52 key: DiffKey,
53 selected: bool,
54 size: f32,
55}
56
57impl Default for RadioItem {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl RadioItem {
64 pub fn new() -> Self {
65 Self {
66 selected: false,
67 theme: None,
68 key: DiffKey::None,
69 size: 20.,
70 }
71 }
72
73 pub fn selected(mut self, selected: bool) -> Self {
74 self.selected = selected;
75 self
76 }
77
78 pub fn theme(mut self, theme: RadioItemThemePartial) -> Self {
79 self.theme = Some(theme);
80 self
81 }
82
83 pub fn key(mut self, key: impl Into<DiffKey>) -> Self {
84 self.key = key.into();
85 self
86 }
87
88 pub fn size(mut self, size: impl Into<f32>) -> Self {
89 self.size = size.into();
90 self
91 }
92}
93
94impl Render for RadioItem {
95 fn render(&self) -> impl IntoElement {
96 let focus = use_focus();
97 let focus_status = use_focus_status(focus);
98 let RadioItemTheme {
99 unselected_fill,
100 selected_fill,
101 border_fill,
102 } = get_theme!(&self.theme, radio);
103
104 let fill = if self.selected {
105 selected_fill
106 } else {
107 unselected_fill
108 };
109
110 let border = Border::new()
111 .fill(fill)
112 .width(2.)
113 .alignment(BorderAlignment::Inner);
114
115 let focused_border = (focus_status() == FocusStatus::Keyboard).then(|| {
116 Border::new()
117 .fill(border_fill)
118 .width((self.size * 0.15).ceil())
119 .alignment(BorderAlignment::Outer)
120 });
121
122 rect()
123 .a11y_id(focus.a11y_id())
124 .a11y_focusable(Focusable::Enabled)
125 .width(Size::px(self.size))
126 .height(Size::px(self.size))
127 .border(border)
128 .border(focused_border)
129 .padding(Gaps::new_all(4.0))
130 .main_align(Alignment::center())
131 .cross_align(Alignment::center())
132 .corner_radius(CornerRadius::new_all(99.))
133 .on_key_down(move |e: Event<KeyboardEventData>| {
134 if !Focus::is_pressed(&e) {
135 e.stop_propagation();
136 }
137 })
138 .maybe_child(self.selected.then(|| {
139 rect()
140 .width(Size::px((self.size * 0.55).floor()))
141 .height(Size::px((self.size * 0.55).floor()))
142 .background(fill)
143 .corner_radius(CornerRadius::new_all(99.))
144 }))
145 }
146
147 fn render_key(&self) -> DiffKey {
148 self.key.clone().or(self.default_key())
149 }
150}
151
152pub fn radio() -> RadioItem {
153 RadioItem::new()
154}