Repository: fyne-io/fyne
File: widget/textgrid.go (Go)

Code before:
func (t *TextGrid) MinSize() fyne.Size {
	t.ExtendBaseWidget(t)
	return t.BaseWidget.MinSize()
}

// Resize is called when this widget changes size. We should make sure that we refresh cells.
func (t *TextGrid) Resize(size fyne.Size) {
	t.BaseWidget.Resize(size)
	t.Refresh()
}

// SetText updates the buffer of this textgrid to contain the specified text.
// New lines and columns will be added as required. Lines are separated by '\n'.
// The grid will use default text style and any previous content and style will be removed.
// Tab characters are padded with spaces to the next tab stop.
func (t *TextGrid) SetText(text string) {
	rows := t.parseRows(text)

	oldRowsLen := len(t.Rows)
	t.Rows = rows

	// Update scroll position if new text is shorter than previous text
	if t.Scroll != fyne.ScrollNone && len(rows) < oldRowsLen {
		offset := t.PositionForCursorLocation(len(rows), 0)
		t.scroll.ScrollToOffset(fyne.NewPos(offset.X, t.scroll.Offset.Y))
		t.scroll.Refresh()
	}

	t.Refresh()
}

// Text returns the contents of the buffer as a single string (with no style information).
// It reconstructs the lines by joining with a `\n` character.
// Tab characters have padded spaces removed.
func (t *TextGrid) Text() string {
	count := len(t.Rows) - 1 // newlines
	for _, row := range t.Rows {
		count += len(row.Cells)
	}

	if count <= 0 {
		return ""
	}

	runes := make([]rune, 0, count)

	for i, row := range t.Rows {
		next := 0
		for col, cell := range row.Cells {
			if col < next {
				continue

Review comment (suggestion):
I think the fact that you had to add a Refresh to the test is because of here, where `t.scroll` will be nil if the widget has not yet been rendered. I think adding a `&& t.scroll != nil` to the if conditions here should avoid this issue.

Code after:
func (t *TextGrid) MinSize() fyne.Size {
	t.ExtendBaseWidget(t)
	return t.BaseWidget.MinSize()
}

// Resize is called when this widget changes size. We should make sure that we refresh cells.
func (t *TextGrid) Resize(size fyne.Size) {
	t.BaseWidget.Resize(size)
	t.Refresh()
}

// SetText updates the buffer of this textgrid to contain the specified text.
// New lines and columns will be added as required. Lines are separated by '\n'.
// The grid will use default text style and any previous content and style will be removed.
// Tab characters are padded with spaces to the next tab stop.
func (t *TextGrid) SetText(text string) {
	rows := t.parseRows(text)

	oldRowsLen := len(t.Rows)
	t.Rows = rows

	// If we don't update the scroll offset when the text is shorter,
	// we may end up with no text displayed or text appearing partially cut off
	if t.scroll != nil && t.Scroll != fyne.ScrollNone && len(rows) < oldRowsLen && t.scroll.Content != nil {
		offset := t.PositionForCursorLocation(len(rows), 0)
		t.scroll.ScrollToOffset(fyne.NewPos(offset.X, t.scroll.Offset.Y))
		t.scroll.Refresh()
	}

	t.Refresh()
}

// Text returns the contents of the buffer as a single string (with no style information).
// It reconstructs the lines by joining with a `\n` character.
// Tab characters have padded spaces removed.
func (t *TextGrid) Text() string {
	count := len(t.Rows) - 1 // newlines
	for _, row := range t.Rows {
		count += len(row.Cells)
	}

	if count <= 0 {
		return ""
	}

	runes := make([]rune, 0, count)

	for i, row := range t.Rows {
		next := 0
		for col, cell := range row.Cells {
			if col < next {