github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/rty/render.go (about) 1 package rty 2 3 import ( 4 "github.com/gdamore/tcell" 5 ) 6 7 func NewRTY(screen tcell.Screen, handler ErrorHandler) RTY { 8 return &rty{ 9 screen: screen, 10 state: make(renderState), 11 handler: handler, 12 } 13 } 14 15 type rty struct { 16 screen tcell.Screen 17 state renderState 18 handler ErrorHandler 19 } 20 21 type renderState map[string]interface{} 22 23 func (r *rty) Render(c Component) { 24 g := &renderGlobals{ 25 prev: r.state, 26 next: make(renderState), 27 } 28 f := renderFrame{ 29 canvas: newScreenCanvas(r.screen, r.handler), 30 globals: g, 31 handler: r.handler, 32 } 33 34 f.RenderChild(c) 35 r.screen.Show() 36 r.state = g.next 37 } 38 39 func (r *rty) RegisterElementScroll(name string, children []string) (l *ElementScrollLayout, selectedChild string) { 40 r.state[name], selectedChild = adjustElementScroll(r.state[name], children) 41 return &ElementScrollLayout{ 42 name: name, 43 }, selectedChild 44 } 45 46 func (r *rty) ElementScroller(name string) ElementScroller { 47 st, ok := r.state[name] 48 if !ok { 49 st = &ElementScrollState{} 50 r.state[name] = st 51 } 52 53 return &ElementScrollController{state: st.(*ElementScrollState)} 54 } 55 56 func (r *rty) TextScroller(name string) TextScroller { 57 st, ok := r.state[name] 58 if !ok { 59 st = &TextScrollState{} 60 r.state[name] = st 61 } 62 63 return &TextScrollController{state: st.(*TextScrollState)} 64 } 65 66 type renderGlobals struct { 67 prev renderState 68 next renderState 69 } 70 71 func (g *renderGlobals) Get(key string) interface{} { 72 return g.prev[key] 73 } 74 75 func (g *renderGlobals) Set(key string, d interface{}) { 76 g.next[key] = d 77 } 78 79 type renderFrame struct { 80 canvas Canvas 81 82 style tcell.Style 83 84 globals *renderGlobals 85 86 handler ErrorHandler 87 } 88 89 var _ Writer = renderFrame{} 90 91 func (f renderFrame) SetContent(x int, y int, mainc rune, combc []rune) { 92 if mainc == 0 { 93 mainc = ' ' 94 } 95 f.canvas.SetContent(x, y, mainc, combc, f.style) 96 } 97 98 func (f renderFrame) Fill() (Writer, error) { 99 width, height := f.canvas.Size() 100 var err error 101 f.canvas, err = newSubCanvas(f.canvas, 0, 0, width, height, f.style, f.handler) 102 if err != nil { 103 return nil, err 104 } 105 return f, nil 106 } 107 108 func (f renderFrame) Divide(x, y, width, height int) (Writer, error) { 109 var err error 110 f.canvas, err = newSubCanvas(f.canvas, x, y, width, height, f.style, f.handler) 111 if err != nil { 112 return nil, err 113 } 114 return f, nil 115 } 116 117 func (f renderFrame) Foreground(c tcell.Color) Writer { 118 f.style = f.style.Foreground(c) 119 return f 120 } 121 122 func (f renderFrame) Background(c tcell.Color) Writer { 123 f.style = f.style.Background(c) 124 return f 125 } 126 127 func (f renderFrame) Invert() Writer { 128 f.style = f.style.Reverse(true) 129 return f 130 } 131 132 func (f renderFrame) error(err error) { 133 f.handler.Errorf("%v", err) 134 } 135 136 func (f renderFrame) RenderChild(c Component) int { 137 width, height := f.canvas.Size() 138 if err := c.Render(f, width, height); err != nil { 139 f.error(err) 140 } 141 142 _, height = f.canvas.Close() 143 return height 144 } 145 146 func (f renderFrame) RenderChildInTemp(c Component) Canvas { 147 width, _ := f.canvas.Size() 148 tmp := newTempCanvas(width, GROW, f.style, f.handler) 149 f.canvas = tmp 150 151 if err := c.Render(f, width, GROW); err != nil { 152 f.error(err) 153 } 154 tmp.Close() 155 return tmp 156 } 157 158 func (f renderFrame) Embed(src Canvas, srcY int, srcHeight int) error { 159 width, destLines := f.canvas.Size() 160 161 numLines := destLines 162 if srcHeight < destLines { 163 numLines = srcHeight 164 } 165 166 for i := 0; i < numLines; i++ { 167 for j := 0; j < width; j++ { 168 mainc, combc, style, _ := src.GetContent(j, srcY+i) 169 f.canvas.SetContent(j, i, mainc, combc, style) 170 } 171 } 172 173 return nil 174 } 175 176 func (f renderFrame) RenderStateful(c StatefulComponent, name string) { 177 prev := f.globals.Get(name) 178 179 width, height := f.canvas.Size() 180 next, err := c.RenderStateful(f, prev, width, height) 181 if err != nil { 182 f.error(err) 183 } 184 185 f.globals.Set(name, next) 186 }