1    local text_position_to_y (text_display : TextDisplay) (position : TextPos) =
2        let up = position.line * text_display.line_height
3        let down = up + text_display.line_height + text_display.margin.up
4        (up, down)
5    
6    type MultilineTextBox
7        let selection_color = Vector3.gray 0.89
8        local (selection_start, selection_middle, selection_end) =
9            let args = (color = selection_color
10                       is_visible = false)
11   
12           (Rectangle f@ args
13            Rectangle f@ args
14            Rectangle f@ args)
15   
16       local text_display = TextDisplay.new
17       local numbers_display = TextDisplay.new
18       local scroller = Scroller.new
19       let numbers_border = Border.new
20       local scissor_control = ScissorControl.new
21   
22       local canvas = Canvas
23           exclude_width <- selection_start
24                            selection_middle
25                            selection_end
26                            text_display
27   
28       show_line_numbers@atom.bind { numbers_border.is_visible = _ }
29       |> push_token
30   
31       let rectangle = Rectangle
32           color@obs = background@obs
33           scroller
34               Splitter
35                   ratio = 0
36                   numbers_border
37                       right = 1
38                       color = Vector3.gray 0.6
39                       Rectangle
40                           color = selection_color
41                           Margin
42                               right = 24
43                               numbers_display
44                   scissor_control
45                       canvas
46                           selection_start
47                           selection_middle
48                           selection_end
49                           text_display
50   
51       content = rectangle
52       offset_controls.add text_display
53                       add selection_start
54                       add selection_middle
55                       add selection_end
56   
57       def update_colors (from : u32) (to : u32) =
58           if update_colors ? Some f then
59               f display_text from to
60   
61       def update_colors (index : u32) =
62           update_colors index index
63   
64       def show self (position : TextPos) =
65           let scroller = self.scroller
66   
67           let scroll_to (y : u32) =
68               scroller/move_to scroller None -y.as<i32>
69   
70           let text_memory = self.text_display
71           let (up, down) = text_position_to_y text_memory position
72           if scroller.visible_y.down - text_memory.line_height < down then
73               let y = down + text_memory.line_height
74                       + scroller.visible_y.up - scroller.visible_y.down
75   
76               scroll_to y
77   
78           else if scroller.visible_y.up + text_memory.line_height > up then
79               let y = if up > text_memory.line_height
80                       then up - text_memory.line_height
81                       else 0
82   
83               scroll_to y
84