perspective_viewer/components/
filter_dropdown.rs1use web_sys::*;
14use yew::prelude::*;
15
16use super::modal::*;
17use crate::utils::WeakScope;
18
19static CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/css/filter-dropdown.css"));
20
21pub enum FilterDropDownMsg {
22 SetValues(Vec<String>),
23 SetCallback(Callback<String>),
24 ItemDown,
25 ItemUp,
26 ItemSelect,
27}
28
29pub struct FilterDropDown {
30 values: Option<Vec<String>>,
31 selected: usize,
32 on_select: Option<Callback<String>>,
33}
34
35#[derive(Properties, PartialEq)]
36pub struct FilterDropDownProps {
37 #[prop_or_default]
38 pub weak_link: WeakScope<FilterDropDown>,
39}
40
41impl ModalLink<FilterDropDown> for FilterDropDownProps {
42 fn weak_link(&self) -> &'_ WeakScope<FilterDropDown> {
43 &self.weak_link
44 }
45}
46
47impl Component for FilterDropDown {
48 type Message = FilterDropDownMsg;
49 type Properties = FilterDropDownProps;
50
51 fn create(ctx: &Context<Self>) -> Self {
52 ctx.set_modal_link();
53 Self {
54 values: Some(vec![]),
55 selected: 0,
56 on_select: None,
57 }
58 }
59
60 fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
61 match msg {
62 FilterDropDownMsg::SetCallback(callback) => {
63 self.on_select = Some(callback);
64 false
65 },
66 FilterDropDownMsg::SetValues(values) => {
67 self.values = Some(values);
68 self.selected = 0;
69 true
70 },
71 FilterDropDownMsg::ItemSelect => {
72 if let Some(ref values) = self.values {
73 match values.get(self.selected) {
74 None => {
75 console::error_1(&"Selected out-of-bounds".into());
76 false
77 },
78 Some(x) => {
79 self.on_select.as_ref().unwrap().emit(x.clone());
80 false
81 },
82 }
83 } else {
84 console::error_1(&"No Values".into());
85 false
86 }
87 },
88 FilterDropDownMsg::ItemDown => {
89 self.selected += 1;
90 if let Some(ref values) = self.values
91 && self.selected >= values.len()
92 {
93 self.selected = 0;
94 };
95
96 true
97 },
98 FilterDropDownMsg::ItemUp => {
99 if let Some(ref values) = self.values
100 && self.selected < 1
101 {
102 self.selected = values.len();
103 }
104
105 self.selected -= 1;
106 true
107 },
108 }
109 }
110
111 fn changed(&mut self, _ctx: &Context<Self>, _old: &Self::Properties) -> bool {
112 false
113 }
114
115 fn view(&self, _ctx: &Context<Self>) -> Html {
116 let body = html! {
117 if let Some(ref values) = self.values {
118 if !values.is_empty() {
119 { for values
120 .iter()
121 .enumerate()
122 .map(|(idx, value)| {
123 let click = self.on_select.as_ref().unwrap().reform({
124 let value = value.clone();
125 move |_: MouseEvent| value.clone()
126 });
127
128 html! {
129 if idx == self.selected {
130 <span onmousedown={ click } class="selected">{ value }</span>
131 } else {
132 <span onmousedown={ click }>{ value }</span>
133 }
134 }
135 }) }
136 } else {
137 <span class="no-results">{ "No Completions" }</span>
138 }
139 }
140 };
141
142 html! { <><style>{ &CSS }</style>{ body }</> }
143 }
144}