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