1 type ListItem = 2 inherit Wrapper 3 4 var obs text = "" 5 var obs foreground = Vector3.new 6 var obs background = Vector3.new 7 var obs is_selected = false 8 var obs data : Option<DataItem> = None 9 10 let rectangle = Rectangle.new 11 12 is_selected@atom.bind { rectangle.is_visible = _ } 13 |> push_token 14 15 let aligner = Aligner 16 rectangle 17 color@obs = background@obs 18 TextBlock 19 text@obs = text@obs 20 color@obs = foreground@obs 21 align_h = AlignH/Center 22 23 content = aligner 24 25 type ListBox = 26 inherit Wrapper 27 28 var obs foreground = Vector3.color "333333" 29 var obs selected_foreground = Vector3.color "DDDDDD" 30 var obs selected_background = Vector3.color "444444" 31 var obs selected_background_unfocused = Vector3.color "AFAFAF" 32 var obs selected_item : Option<DataItem> = None 33 var obs selected_list_item : Option<ListItem> = None 34 35 val items = obs/List<DataItem>.new 36 let stack = Stack.new 37 38 is_focusable = true 39 content = stack 40 41 let hide_selection (list_item : ListItem) = 42 list_item.foreground = foreground 43 is_selected = false 44 45 let select (list_item : ListItem) = 46 let maybe_prev_item = selected_list_item 47 if maybe_prev_item <> Some list_item then 48 selected_item = list_item.data 49 selected_list_item = Some list_item 50 51 list_item.foreground = selected_foreground 52 is_selected = true 53 background = if is_focused 54 then selected_background 55 else selected_background_unfocused 56 57 if maybe_prev_item ? Some prev_item then 58 hide_selection prev_item 59 60 let data_list_items = Map.new 61 let token = items 62 |> Obs.map { item -> 63 let list_item = ListItem 64 text = item.name 65 data = item 66 foreground = foreground 67 background = selected_background 68 69 let name_token = item.name@atom.bind { list_item.text = _ } 70 list_item.push_token name_token 71 72 list_item } 73 74 |> bind { index list_item -> 75 let data_item = list_item.data.unwrap 76 data_list_items.add data_item list_item 77 stack.items.add index list_item } 78 79 { index list_item -> 80 stack.items.remove_at index 81 let data_item = list_item.data.unwrap 82 data_list_items.remove data_item } 83 84 let selected_item_token = selected_item@atom.bind 85 { maybe_item -> case maybe_item of 86 None -> if selected_list_item ? Some list_item then 87 selected_list_item = None 88 selected_item = None 89 hide_selection list_item 90 91 Some item -> 92 let list_item = data_list_items[item] 93 select list_item } 94 95 push_token token 96 push_token selected_item_token 97 98 def find_parent (control : Control) (f : Control -> bool) : Control = 99 if f control 100 then control 101 else find_parent control.parent.unwrap f 102 103 type ListItem 104 subscribe { _, event -> if event.is_mouse_press then 105 let list_box = find_parent self { _ is ListBox } as ListBox 106 list_box.select self } 107