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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Defines elements that can be used to select an item from a list.
use ambient_cb::Cb;
use ambient_element::{
    to_owned, use_runtime_message, use_state, Element, ElementComponent, ElementComponentExt, Hooks,
};
use ambient_guest_bridge::core::{
    layout::components::margin, messages, rect::components::border_radius,
};
use glam::{vec4, Vec4};

use crate::{
    button::{Button, ButtonStyle},
    default_theme::{tooltip_background_color, SMALL_ROUNDING, STREET},
    dropdown::Dropdown,
    layout::{FlowColumn, FlowRow},
    text::Text,
    UIExt,
};

#[derive(Debug, Clone)]
/// A dropdown select element. Presents a button next to `content` that, when clicked, shows a dropdown with the items in `items`.
pub struct DropdownSelect {
    /// The content (always shown)
    pub content: Element,
    /// The callback to call when an item is selected. Called with the index of the item.
    pub on_select: Cb<dyn Fn(usize) + Sync + Send>,
    /// The items to select from.
    pub items: Vec<Element>,
    /// Whether or not the button used for the dropdown should be inline or not.
    pub inline: bool,
}
impl ElementComponent for DropdownSelect {
    fn render(self: Box<Self>, hooks: &mut Hooks) -> Element {
        let Self {
            content,
            on_select,
            items,
            inline,
        } = *self;
        let (show, set_show) = use_state(hooks, false);
        use_runtime_message::<messages::WindowMouseInput>(hooks, {
            to_owned![set_show];
            move |_world, event| {
                if show && !event.pressed {
                    set_show(false);
                }
            }
        });
        Dropdown {
            content: Button::new(
                FlowRow(vec![
                    content,
                    Text::el("\u{f078}").with(margin(), vec4(0., 0., 0., 5.)),
                ])
                .el(),
                {
                    to_owned![set_show];
                    move |_| set_show(!show)
                },
            )
            .style(if inline {
                ButtonStyle::Inline
            } else {
                ButtonStyle::Regular
            })
            .el(),
            dropdown: FlowColumn(
                items
                    .into_iter()
                    .enumerate()
                    .map(move |(i, item)| {
                        Button::new(item, {
                            to_owned![on_select];
                            move |_| {
                                on_select.0(i);
                            }
                        })
                        .style(ButtonStyle::Card)
                        .el()
                        .with(margin(), vec4(if i != 0 { STREET } else { 0. }, 0., 0., 0.))
                    })
                    .collect(), //     vec![Bookcase(
                                //     items
                                //         .into_iter()
                                //         .enumerate()
                                //         .map(move |(i, item)| BookFile {
                                //             container: Button::new(item, closure!(clone on_select, |_, _, _| { on_select.0(i); }))
                                //             .style(ButtonStyle::Card)
                                //                 .el()
                                //                 .set(margin(), Borders::even(5.)),
                                //             book: item,
                                //         })
                                //         .collect(),
                                // )
                                // .el()
                                // .set(orientation(), Orientation::Vertical)]
            )
            .el()
            .with_padding_even(STREET)
            .with(border_radius(), Vec4::ONE * SMALL_ROUNDING)
            .with_background(tooltip_background_color().into()),
            show,
        }
        .el()
    }
}

#[derive(Debug, Clone)]
/// A [DropdownSelect] that shows the current item for you automatically.
pub struct ListSelect {
    /// The index of the currently selected item.
    pub value: usize,
    /// The callback to call when an item is selected. Called with the index of the item.
    pub on_change: Cb<dyn Fn(usize) + Sync + Send>,
    /// The items to select from.
    pub items: Vec<Element>,
    /// Whether or not the button used for the dropdown should be inline or not.
    pub inline: bool,
}
impl ElementComponent for ListSelect {
    fn render(self: Box<Self>, _: &mut Hooks) -> Element {
        let Self {
            value,
            on_change,
            items,
            inline,
        } = *self;
        DropdownSelect {
            content: FlowRow(vec![if let Some(item) = items.get(value) {
                item.clone()
            } else {
                Text::el("-")
            }])
            .el(),
            on_select: on_change,
            items,
            inline,
        }
        .el()
    }
}