[GH-ISSUE #279] Support widget overflowing #214

Closed
opened 2026-03-04 01:03:03 +03:00 by kerem · 5 comments
Owner

Originally created by @diamondburned on GitHub (Apr 26, 2019).
Original GitHub issue: https://github.com/rivo/tview/issues/279

Is there any plans for flex or grid boxes to overflow widgets properly? An example would be adding so many widgets vertically, it cuts properly and not render the rest. Arrow keys and methods can be bound to keys for scrolling in them. Perhaps that, or a specific Scrolling primitive?

Originally created by @diamondburned on GitHub (Apr 26, 2019). Original GitHub issue: https://github.com/rivo/tview/issues/279 Is there any plans for flex or grid boxes to overflow widgets properly? An example would be adding so many widgets vertically, it cuts properly and not render the rest. Arrow keys and methods can be bound to keys for scrolling in them. Perhaps that, or a specific Scrolling primitive?
kerem closed this issue 2026-03-04 01:03:03 +03:00
Author
Owner

@rivo commented on GitHub (May 14, 2019):

Can you send me a screenshot of an example where the current handling causes problems?

<!-- gh-comment-id:492307488 --> @rivo commented on GitHub (May 14, 2019): Can you send me a screenshot of an example where the current handling causes problems?
Author
Owner

@diamondburned commented on GitHub (May 15, 2019):

https://gitlab.com/diamondburned/tview-grid-overflow-example

A simple go run . will do.

<!-- gh-comment-id:492518460 --> @diamondburned commented on GitHub (May 15, 2019): https://gitlab.com/diamondburned/tview-grid-overflow-example A simple `go run .` will do.
Author
Owner

@rivo commented on GitHub (Jun 30, 2019):

When clicking on your link, I'm seeing this:

image

Could you post some code here or in a gist here on GitHub, please?

<!-- gh-comment-id:507059408 --> @rivo commented on GitHub (Jun 30, 2019): When clicking on your link, I'm seeing this: ![image](https://user-images.githubusercontent.com/480930/60400929-769ba680-9b72-11e9-893d-e7944ce1aec2.png) Could you post some code here or in a gist here on GitHub, please?
Author
Owner

@diamondburned commented on GitHub (Jul 2, 2019):

carousel.go

package main

import (
	"fmt"

	"github.com/gdamore/tcell"
	"github.com/rivo/tview"
)

// Lines of a template
const templateLines = 3

// Carousel implements tview's Grid for videos
type Carousel struct {
	*tview.Grid

	videoElements []*tview.TextView

	focus         int
	customHandler func(*tcell.EventKey) *tcell.EventKey
}

// New initiates a new carousel
func New() *Carousel {
	var grid = tview.NewGrid()

	c := &Carousel{
		Grid:          grid,
		videoElements: make([]*tview.TextView, 30),
	}

	grid.SetColumns(0)
	grid.SetBorders(false)
	grid.SetInputCapture(c.DefaultInputHandler)
	grid.SetGap(1, 1)

	var rows = make([]int, 30)
	for i := 0; i < 30; i++ {
		rows[i] = templateLines

		tv := tview.NewTextView()
		tv.SetText(fmt.Sprint("a multiline text\n", i, "widget\n"+"3rd line"))

		grid.AddItem(tv, i, 0, 1, templateLines, 0, 0, false)
		c.videoElements[i] = tv
	}

	grid.SetRows(rows...)

	return c
}

// DefaultInputHandler is the default input handler
func (c *Carousel) DefaultInputHandler(ev *tcell.EventKey) *tcell.EventKey {
	old := c.focus
	switch ev.Key() {
	case tcell.KeyUp:
		if c.focus == 0 {
			return ev
		}

		c.focus--

	case tcell.KeyDown:
		if c.focus == len(c.videoElements)-1 {
			return ev
		}

		c.focus++

	default:
		if c.customHandler != nil {
			return c.customHandler(ev)
		}

		return ev
	}

	c.videoElements[old].SetBackgroundColor(tcell.ColorBlack)
	c.videoElements[old].SetTextColor(tcell.ColorWhite)

	c.videoElements[c.focus].SetBackgroundColor(tcell.ColorWhite)
	c.videoElements[c.focus].SetTextColor(tcell.ColorBlack)

	c.SetOffset(c.focus-1, 0)

	return nil
}

// SetInputHandler sets a custom input capture
// Keys like Up/Down/Enter are swallowed
func (c *Carousel) SetInputHandler(f func(*tcell.EventKey) *tcell.EventKey) {
	c.customHandler = f
}

main.go

package main

import "github.com/rivo/tview"

func main() {
	tv := tview.NewTextView()
	tv.SetText(`watch
as
the
grid
takes
over
this
primitive
when you scroll with the arrow keys`)

	f := tview.NewFlex()
	f.SetDirection(tview.FlexRow)
	f.AddItem(tv, 0, 1, false)
	f.AddItem(New(), 0, 1, true)

	if err := tview.NewApplication().SetRoot(f, true).Run(); err != nil {
		panic(err)
	}

Solution is to just wrap tcell.Screen around a Painter, have the Painter methods check for out of bounds and draw.

<!-- gh-comment-id:507485887 --> @diamondburned commented on GitHub (Jul 2, 2019): carousel.go ```go package main import ( "fmt" "github.com/gdamore/tcell" "github.com/rivo/tview" ) // Lines of a template const templateLines = 3 // Carousel implements tview's Grid for videos type Carousel struct { *tview.Grid videoElements []*tview.TextView focus int customHandler func(*tcell.EventKey) *tcell.EventKey } // New initiates a new carousel func New() *Carousel { var grid = tview.NewGrid() c := &Carousel{ Grid: grid, videoElements: make([]*tview.TextView, 30), } grid.SetColumns(0) grid.SetBorders(false) grid.SetInputCapture(c.DefaultInputHandler) grid.SetGap(1, 1) var rows = make([]int, 30) for i := 0; i < 30; i++ { rows[i] = templateLines tv := tview.NewTextView() tv.SetText(fmt.Sprint("a multiline text\n", i, "widget\n"+"3rd line")) grid.AddItem(tv, i, 0, 1, templateLines, 0, 0, false) c.videoElements[i] = tv } grid.SetRows(rows...) return c } // DefaultInputHandler is the default input handler func (c *Carousel) DefaultInputHandler(ev *tcell.EventKey) *tcell.EventKey { old := c.focus switch ev.Key() { case tcell.KeyUp: if c.focus == 0 { return ev } c.focus-- case tcell.KeyDown: if c.focus == len(c.videoElements)-1 { return ev } c.focus++ default: if c.customHandler != nil { return c.customHandler(ev) } return ev } c.videoElements[old].SetBackgroundColor(tcell.ColorBlack) c.videoElements[old].SetTextColor(tcell.ColorWhite) c.videoElements[c.focus].SetBackgroundColor(tcell.ColorWhite) c.videoElements[c.focus].SetTextColor(tcell.ColorBlack) c.SetOffset(c.focus-1, 0) return nil } // SetInputHandler sets a custom input capture // Keys like Up/Down/Enter are swallowed func (c *Carousel) SetInputHandler(f func(*tcell.EventKey) *tcell.EventKey) { c.customHandler = f } ``` main.go ```go package main import "github.com/rivo/tview" func main() { tv := tview.NewTextView() tv.SetText(`watch as the grid takes over this primitive when you scroll with the arrow keys`) f := tview.NewFlex() f.SetDirection(tview.FlexRow) f.AddItem(tv, 0, 1, false) f.AddItem(New(), 0, 1, true) if err := tview.NewApplication().SetRoot(f, true).Run(); err != nil { panic(err) } ``` Solution is to just wrap `tcell.Screen` around a Painter, have the Painter methods check for out of bounds and draw.
Author
Owner

@rivo commented on GitHub (Jul 17, 2019):

So this should be fixed now. The whole handling of the offset values in Grid was buggy so I rewrote that part.

<!-- gh-comment-id:512362433 --> @rivo commented on GitHub (Jul 17, 2019): So this should be fixed now. The whole handling of the offset values in `Grid` was buggy so I rewrote that part.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#214
No description provided.