1 type TabItem @mut = 2 inherit Indirect 3 4 var obs header = "" 5 var obs can_close = true 6 var obs foreground = Vector3.new 7 var obs background = Vector3.new 8 var obs is_selected = false 9 var obs content : Option<Control> @dst = None 10 11 type TabControl @mut = 12 inherit Wrapper 13 14 val set_foreground @param = true 15 var obs foreground = Vector3.color "333333" 16 var obs background = Vector3.color "C8C8C8" 17 var obs selected_foreground = Vector3.color "DDDDDD" 18 var obs selected_background = Vector3.color "444444" 19 var obs selected_tab_item : Option<TabItem> = None 20 var obs selected_content : Option<Control> = None 21 22 val tab_items = obs/List<TabItem>.new 23 24 let hide_selection (tab_item : TabItem) = 25 if set_foreground then 26 tab_item.foreground = foreground 27 28 tab_item.background = background 29 is_selected = false 30 31 def select (tab_item : TabItem) = 32 let maybe_prev_item = selected_tab_item 33 if maybe_prev_item <> Some tab_item then 34 selected_content = tab_item.content 35 selected_tab_item = Some tab_item 36 37 if set_foreground then 38 tab_item.foreground = selected_foreground 39 40 tab_item.background = selected_background 41 is_selected = true 42 43 if maybe_prev_item ? Some prev_item then 44 hide_selection prev_item 45 46 tab_items.bind 47 { _ tab_item -> 48 tab_item.foreground = foreground 49 background = background 50 51 if selected_tab_item.is_none then 52 select tab_item } 53 54 { _ tab_item -> 55 if selected_tab_item == Some tab_item then 56 hide_selection tab_item 57 selected_tab_item = None 58 selected_content = None } 59 |> push_token 60 61 let wrap_panel = WrapPanel.new 62 val presenter = Presenter.new 63 let splitter = Splitter 64 ratio = 0 65 is_vertical = true 66 wrap_panel 67 distance = 10 68 presenter 69 content@obs = selected_content@obs 70 71 content = splitter 72 73 tab_items.bind { i x -> wrap_panel.items.add i x } 74 { i x -> wrap_panel.items.remove i x } 75 |> wrap_panel.push_token 76 77 type TabClosing = 78 val tab_control : TabControl 79 val tab_item : TabItem 80 var is_cancelled @mut = false 81 82 type TabControl 83 var on_closing : Option<TabClosing -> Unit> = None 84 var on_closed : Option<TabItem -> Unit> = None 85 86 def close_tab (tab_item : TabItem) = 87 if tab_item.is_selected && tab_items.size > 1 then 88 let index = tab_items.index_of tab_item 89 let next_index = if index == 0 then 1 else index - 1 90 let next_tab_item = tab_items[next_index] 91 select next_tab_item 92 93 tab_items.remove tab_item 94 95 if on_closed ? Some f then 96 f tab_item 97 98 type TabItem 99 let rectangle = Rectangle.new 100 let text_block = TextBlock 101 is_clickable = true 102 103 can_close@atom.bind { rectangle.is_visible = _ } 104 |> push_token 105 106 let splitter = Splitter 107 ratio = 1 108 Rectangle 109 color@obs = background@obs 110 text_block 111 text@obs = header@obs 112 color@obs = foreground@obs 113 rectangle 114 color = Vector3.color "777777" 115 min_width = text_block.char_margins_height 116 min_height = text_block.char_margins_height 117 is_clickable = true 118 119 child = splitter 120 121 text_block.subscribe { _, event -> if event.is_mouse_press then 122 let tab_control = find_parent self { _ is TabControl } as TabControl 123 tab_control.select self } 124 125 rectangle.subscribe { _, event -> if event.is_mouse_release then 126 let tab_control = find_parent self { _ is TabControl } as TabControl 127 if tab_control.on_closing.is_none then 128 tab_control.close_tab self 129 else 130 let args = TabClosing tab_control self 131 let f = tab_control.on_closing.unwrap 132 f args 133 if not args.is_cancelled then 134 tab_control.close_tab self } 135