forked from Mirrors/bubbletea
Cmds for scrolling + handle renderer msgs in a renderer method
This commit is contained in:
parent
a492302609
commit
4dc6992767
169
renderer.go
169
renderer.go
|
@ -14,62 +14,6 @@ const (
|
|||
defaultFramerate = time.Second / 60
|
||||
)
|
||||
|
||||
// RendererIgnoreLinesMsg tells the renderer to skip rendering for the given
|
||||
// range of lines.
|
||||
type ignoreLinesMsg struct {
|
||||
From int
|
||||
To int
|
||||
}
|
||||
|
||||
// IgnoreLines produces command that sets a range of lines to be ignored
|
||||
// by the renderer. The general use case here is that those lines would be
|
||||
// rendered separately for performance reasons.
|
||||
func IgnoreLines(from int, to int) Cmd {
|
||||
return func() Msg {
|
||||
return ignoreLinesMsg{From: from, To: to}
|
||||
}
|
||||
}
|
||||
|
||||
type resetIgnoreLinesMsg struct {
|
||||
from int
|
||||
to int
|
||||
}
|
||||
|
||||
// ResetIngoredLines produces a command that clears any lines set to be ignored
|
||||
// and the sets new ones by the renderer. This is probably a more common use
|
||||
// case than the IgnoreLines command.
|
||||
func ResetIgnoredLines(from int, to int) Cmd {
|
||||
return func() Msg {
|
||||
return resetIgnoreLinesMsg{from: from, to: to}
|
||||
}
|
||||
}
|
||||
|
||||
// ClearIgnoredLinesMsg has the renderer allows the renderer to commence rendering
|
||||
// any lines previously set to be ignored.
|
||||
type clearIgnoredLinesMsg struct{}
|
||||
|
||||
// RendererIgnoreLines is a command that sets a range of lines to be
|
||||
// ignored by the renderer.
|
||||
func ClearIgnoredLines() Msg {
|
||||
return clearIgnoredLinesMsg{}
|
||||
}
|
||||
|
||||
// ScrollDownMsg is experiemental. There are no guarantees about it persisting
|
||||
// in a future API. It's exposed for high performance scrolling.
|
||||
type ScrollUpMsg struct {
|
||||
NewLines []string
|
||||
TopBoundary int
|
||||
BottomBoundary int
|
||||
}
|
||||
|
||||
// ScrollDownMsg is experiemental. There are no guarantees about it persisting
|
||||
// in a future API. It's exposed for high performance scrolling.
|
||||
type ScrollDownMsg struct {
|
||||
NewLines []string
|
||||
TopBoundary int
|
||||
BottomBoundary int
|
||||
}
|
||||
|
||||
// renderer is a timer-based renderer, updating the view at a given framerate
|
||||
// to avoid overloading the terminal emulator.
|
||||
//
|
||||
|
@ -239,6 +183,8 @@ func (r *renderer) clearIgnoredLines() {
|
|||
// area designated to be a scrollable region, pushing everything else down.
|
||||
// This is roughly how ncurses does it.
|
||||
//
|
||||
// To call this function use command ScrollUp().
|
||||
//
|
||||
// For this to work renderer.ignoreLines must be set to ignore the scrollable
|
||||
// region since we are bypassing the normal Bubble Tea renderer here.
|
||||
//
|
||||
|
@ -272,11 +218,10 @@ func (r *renderer) insertTop(lines []string, topBoundary, bottomBoundary int) {
|
|||
// a given area designated to be a scrollable region, pushing everything else
|
||||
// up. This is roughly how ncurses does it.
|
||||
//
|
||||
// For this to work renderer.ignoreLines must be set to ignore the scrollable
|
||||
// region since we are bypassing the normal Bubble Tea renderer here.
|
||||
// To call this function use the command ScrollDown().
|
||||
//
|
||||
// See note in insertTop() on how this function only makes sense for
|
||||
// full-window applications and how it differs from the noraml way we do
|
||||
// See note in insertTop() for caveats, how this function only makes sense for
|
||||
// full-window applications, and how it differs from the noraml way we do
|
||||
// rendering in Bubble Tea.
|
||||
func (r *renderer) insertBottom(lines []string, topBoundary, bottomBoundary int) {
|
||||
r.mtx.Lock()
|
||||
|
@ -293,3 +238,107 @@ func (r *renderer) insertBottom(lines []string, topBoundary, bottomBoundary int)
|
|||
|
||||
r.out.Write(b.Bytes())
|
||||
}
|
||||
|
||||
// handleMessages handles internal messages for the renderer. It belongs in the
|
||||
// main update loop at the program level.
|
||||
func (r *renderer) handleMessages(msg Msg) {
|
||||
switch msg := msg.(type) {
|
||||
case WindowSizeMsg:
|
||||
r.width = msg.Width
|
||||
r.height = msg.Height
|
||||
|
||||
case ignoreLinesMsg:
|
||||
r.setIgnoredLines(msg.from, msg.to)
|
||||
|
||||
case replaceIgnoredLinesMsg:
|
||||
r.clearIgnoredLines()
|
||||
r.setIgnoredLines(msg.from, msg.to)
|
||||
|
||||
case clearIgnoredLinesMsg:
|
||||
r.clearIgnoredLines()
|
||||
|
||||
case scrollUpMsg:
|
||||
r.insertTop(msg.lines, msg.topBoundary, msg.bottomBoundary)
|
||||
|
||||
case scrollDownMsg:
|
||||
r.insertTop(msg.lines, msg.topBoundary, msg.bottomBoundary)
|
||||
}
|
||||
}
|
||||
|
||||
// HIGH-PERFORMANCE RENDERING STUFF
|
||||
|
||||
// ignoreLinesMsg tells the renderer to skip rendering for the given
|
||||
// range of lines.
|
||||
type ignoreLinesMsg struct {
|
||||
from int
|
||||
to int
|
||||
}
|
||||
|
||||
// IgnoreLines produces command that sets a range of lines to be ignored
|
||||
// by the renderer. The general use case here is that those lines would be
|
||||
// rendered separately for performance reasons.
|
||||
func IgnoreLines(from int, to int) Cmd {
|
||||
return func() Msg {
|
||||
return ignoreLinesMsg{from: from, to: to}
|
||||
}
|
||||
}
|
||||
|
||||
type replaceIgnoredLinesMsg struct {
|
||||
from int
|
||||
to int
|
||||
}
|
||||
|
||||
// ReplaceIngoredLines produces a command that clears any lines set to be ignored
|
||||
// and the sets new ones by the renderer. This is probably a more common use
|
||||
// case than the IgnoreLines command.
|
||||
func ReplaceIgnoredLines(from int, to int) Cmd {
|
||||
return func() Msg {
|
||||
return replaceIgnoredLinesMsg{from: from, to: to}
|
||||
}
|
||||
}
|
||||
|
||||
// ClearIgnoredLinesMsg has the renderer allows the renderer to commence rendering
|
||||
// any lines previously set to be ignored.
|
||||
type clearIgnoredLinesMsg struct{}
|
||||
|
||||
// RendererIgnoreLines is a command that sets a range of lines to be
|
||||
// ignored by the renderer.
|
||||
func ClearIgnoredLines() Msg {
|
||||
return clearIgnoredLinesMsg{}
|
||||
}
|
||||
|
||||
// scrollDownMsg is experiemental. There are no guarantees about it persisting
|
||||
// in a future API. It's exposed for high performance scrolling.
|
||||
type scrollUpMsg struct {
|
||||
lines []string
|
||||
topBoundary int
|
||||
bottomBoundary int
|
||||
}
|
||||
|
||||
func ScrollUp(newLines []string, topBoundary, bottomBoundary int) Cmd {
|
||||
return func() Msg {
|
||||
return scrollUpMsg{
|
||||
lines: newLines,
|
||||
topBoundary: topBoundary,
|
||||
bottomBoundary: bottomBoundary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scrollDownMsg is experiemental. There are no guarantees about it persisting
|
||||
// in a future API. It's exposed for high performance scrolling.
|
||||
type scrollDownMsg struct {
|
||||
lines []string
|
||||
topBoundary int
|
||||
bottomBoundary int
|
||||
}
|
||||
|
||||
func ScrollDown(newLines []string, topBoundary, bottomBoundary int) Cmd {
|
||||
return func() Msg {
|
||||
return scrollDownMsg{
|
||||
lines: newLines,
|
||||
topBoundary: topBoundary,
|
||||
bottomBoundary: bottomBoundary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
28
tea.go
28
tea.go
|
@ -171,32 +171,8 @@ func (p *Program) Start() error {
|
|||
continue
|
||||
}
|
||||
|
||||
// Report resizes to the renderer. Only necessary for special,
|
||||
// performance-based rendering.
|
||||
if size, ok := msg.(WindowSizeMsg); ok {
|
||||
mrRenderer.width = size.Width
|
||||
mrRenderer.height = size.Height
|
||||
}
|
||||
|
||||
// Handle messages telling the main rendering routine to ignore
|
||||
// ranges of lines. Useful for performance-based rendering.
|
||||
if lineRange, ok := msg.(ignoreLinesMsg); ok {
|
||||
mrRenderer.setIgnoredLines(lineRange.from, lineRange.to)
|
||||
}
|
||||
|
||||
// Handle messages telling the main rendering routine to clear
|
||||
// ranges of lines previously ignored and set a new range of
|
||||
// ignored lines. For use in high-performance rendering.
|
||||
if lineRange, ok := msg.(resetIgnoreLinesMsg); ok {
|
||||
mrRenderer.clearIgnoredLines()
|
||||
mrRenderer.setIgnoredLines(lineRange.from, lineRange.to)
|
||||
}
|
||||
|
||||
// Handle messages telling the main rendering to stop ignoring
|
||||
// lines. Useful when disabling any performance-based rendering.
|
||||
if _, ok := msg.(clearIgnoredLinesMsg); ok {
|
||||
mrRenderer.clearIgnoredLines()
|
||||
}
|
||||
// Process any internal messages for the renderer
|
||||
mrRenderer.handleMessages(msg)
|
||||
|
||||
model, cmd = p.update(msg, model) // run update
|
||||
cmds <- cmd // process command (if any)
|
||||
|
|
Loading…
Reference in New Issue