1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::{api::prelude::*, proc_macros::*};

/// The `SelectionBehaviorState` handles the `SelectionBehavior` widget.
#[derive(Default, AsAny)]
pub struct SelectionBehaviorState {
    toggle_selection: bool,
    selected: bool,
}

impl SelectionBehaviorState {
    fn toggle_selection(&mut self) {
        self.toggle_selection = true;
    }
}

impl State for SelectionBehaviorState {
    fn init(&mut self, _: &mut Registry, ctx: &mut Context) {
        self.selected = *selection_behavior(ctx.widget()).selected();
        let target = *ctx.widget().get::<u32>("target");
        toggle_flag("selected", &mut ctx.get_widget(Entity(target)));
        ctx.get_widget(Entity(target)).update(false);
    }

    fn update(&mut self, _: &mut Registry, ctx: &mut Context) {
        let selected = *selection_behavior(ctx.widget()).selected();
        let target: Entity = (*selection_behavior(ctx.widget()).target()).into();

        if self.selected == selected && !self.toggle_selection {
            return;
        }

        if *selection_behavior(ctx.widget()).enabled() && self.toggle_selection {
            ctx.get_widget(target).set("selected", !selected);
        }

        self.toggle_selection = false;
        self.selected = *selection_behavior(ctx.widget()).selected();

        toggle_flag("selected", &mut ctx.get_widget(target));

        ctx.get_widget(target).update(false);
    }
}

widget!(
    /// The `SelectionBehavior` widget is used to handle internal the pressed behavior of a widget.
    ///
    /// **style:** `check-box`
    SelectionBehavior<SelectionBehaviorState>: MouseHandler {
        /// Sets or shares the target of the behavior.
        target: u32,

        /// Sets or shares the selected property.
        selected: bool,

        /// Sets the parent id.
        parent: u32
    }
);

impl Template for SelectionBehavior {
    fn template(self, id: Entity, _: &mut BuildContext) -> Self {
        self.name("SelectionBehavior")
            .selected(true)
            .on_click(move |states, _| {
                states
                    .get_mut::<SelectionBehaviorState>(id)
                    .toggle_selection();
                false
            })
    }
}