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