ori_core/views/
checkbox.rs1use glam::Vec2;
2use ori_graphics::{TextAlign, TextSection};
3use ori_macro::Build;
4
5use crate::{
6 BoxConstraints, Context, DrawContext, Event, EventContext, LayoutContext, PointerEvent, Scope,
7 SharedSignal, Signal, Style, View,
8};
9
10#[derive(Default, Build)]
11pub struct Checkbox {
12 #[bind]
13 checked: SharedSignal<bool>,
14}
15
16impl Checkbox {
17 const CHECKMARK: &'static str = "\u{e876}";
18
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn checked(self, checked: bool) -> Self {
24 self.checked.set(checked);
25 self
26 }
27
28 pub fn bind_checked<'a>(self, cx: Scope<'a>, binding: &'a Signal<bool>) -> Self {
29 let signal = cx.alloc(self.checked.clone());
30 cx.bind(signal, binding);
31 self
32 }
33}
34
35impl View for Checkbox {
36 type State = ();
37
38 fn build(&self) -> Self::State {}
39
40 fn style(&self) -> Style {
41 Style::new("checkbox")
42 }
43
44 fn event(&self, _: &mut Self::State, cx: &mut EventContext, event: &Event) {
45 cx.state.active = self.checked.cloned_untracked();
46
47 if event.is_handled() || !cx.hovered() {
48 return;
49 }
50
51 if let Some(pointer_event) = event.get::<PointerEvent>() {
52 if pointer_event.is_press() {
53 self.checked.set(!self.checked.cloned());
54 event.handle();
55 cx.request_redraw();
56 }
57 }
58 }
59
60 fn layout(&self, _state: &mut Self::State, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
61 cx.state.active = self.checked.cloned_untracked();
62
63 let width = cx.style_range("width", bc.width());
64 let height = cx.style_range("height", bc.height());
65 bc.constrain(Vec2::new(width, height))
66 }
67
68 fn draw(&self, _state: &mut Self::State, cx: &mut DrawContext) {
69 cx.state.active = self.checked.cloned_untracked();
70
71 cx.draw_quad();
72
73 if *self.checked.get() {
74 let section = TextSection {
75 rect: cx.rect(),
76 scale: cx.rect().size().min_element() * 0.8,
77 h_align: TextAlign::Center,
78 v_align: TextAlign::Center,
79 text: String::from(Self::CHECKMARK),
80 font: Some(String::from("icon")),
81 color: cx.style("color"),
82 ..Default::default()
83 };
84
85 cx.draw(section);
86 }
87 }
88}