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