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  }