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.new 102 103 let control = Rectangle 104 color@obs = background@obs 105 Splitter 106 ratio = 1 107 Margin 108 left = 18 109 up = 3 110 down = 3 111 text_block 112 text@obs = header@obs 113 color@obs = foreground@obs 114 Margin 115 right = 6 116 figure 117 kind = FigureKind/Cross 118 align_v = AlignV/Center 119 color = Colors.tab_item_close 120 is_clickable = true 121 is_visible = false 122 run@ set_fixed_width 16 123 run@ set_fixed_height 16 124 125 child = control 126 127 subscribe { _, event -> 128 if event ? FlagEvent/IsHovered x then 129 figure.is_visible = x && can_close 130 else if event.is_mouse_press then 131 let tab_control = find_parent self { _ is TabControl } as TabControl 132 tab_control.select self } 133 134 figure.subscribe { _, event -> if event.is_mouse_release then 135 let tab_control = find_parent self { _ is TabControl } as TabControl 136 if tab_control.on_closing.is_none then 137 tab_control.close_tab self 138 else 139 let args = TabClosing tab_control self 140 let f = tab_control.on_closing.unwrap 141 f args 142 if not args.is_cancelled then 143 tab_control.close_tab self } 144 145 is_receive_hover = true 146 is_clickable = true 147