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