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 = Colors.tab_item_foreground 16 var obs background = Colors.tab_item_background 17 var obs selected_foreground = Colors.tab_item_selected_foreground 18 var obs selected_background = Colors.tab_item_selected_background 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 Rectangle 67 color = Colors.tab_item_background 68 wrap_panel 69 presenter 70 content@obs = selected_content@obs 71 72 content = splitter 73 74 tab_items.bind { i x -> wrap_panel.items.add i x } 75 { i x -> wrap_panel.items.remove i x } 76 |> wrap_panel.push_token 77 78 type TabClosing = 79 val tab_control : TabControl 80 val tab_item : TabItem 81 var is_cancelled @mut = false 82 83 type TabControl 84 var on_closing : Option<TabClosing -> Unit> = None 85 var on_closed : Option<TabItem -> Unit> = None 86 87 def close_tab (tab_item : TabItem) = 88 if tab_item.is_selected && tab_items.size > 1 then 89 let index = tab_items.index_of tab_item 90 let next_index = if index == 0 then 1 else index - 1 91 let next_tab_item = tab_items[next_index] 92 select next_tab_item 93 94 tab_items.remove tab_item 95 96 if on_closed ? Some f then 97 f tab_item 98 99 type TabItem 100 let figure = Figure.new 101 let text_block = TextBlock 102 is_clickable = true 103 104 can_close@atom.bind { figure.is_visible = _ } 105 |> push_token 106 107 let control = Rectangle 108 color@obs = background@obs 109 Splitter 110 ratio = 1 111 Margin 112 left = 18 113 text_block 114 text@obs = header@obs 115 color@obs = foreground@obs 116 Margin 117 right = 6 118 figure 119 kind = FigureKind/Cross 120 align_v = AlignV/Center 121 color = Colors.tab_item_close 122 is_clickable = true 123 is_visible = false 124 run@ set_fixed_width 16 125 run@ set_fixed_height 16 126 127 child = control 128 129 text_block.subscribe { _, event -> if event.is_mouse_press then 130 let tab_control = find_parent self { _ is TabControl } as TabControl 131 tab_control.select self } 132 133 figure.subscribe { _, event -> if event.is_mouse_release then 134 let tab_control = find_parent self { _ is TabControl } as TabControl 135 if tab_control.on_closing.is_none then 136 tab_control.close_tab self 137 else 138 let args = TabClosing tab_control self 139 let f = tab_control.on_closing.unwrap 140 f args 141 if not args.is_cancelled then 142 tab_control.close_tab self } 143 144 subscribe { _, event -> if event ? FlagEvent/IsHovered x then 145 figure.is_visible = x } 146 147 is_receive_hover = true 148