From 56db81e7d4891b278209295f2a7c9e0bbdedb01c Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 4 Jul 2023 10:55:20 +0100 Subject: [PATCH 1/2] Avoid possible re-draw requests when our content has not changed --- widget/textgrid.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/widget/textgrid.go b/widget/textgrid.go index c4ae3a5699..6204424780 100644 --- a/widget/textgrid.go +++ b/widget/textgrid.go @@ -337,6 +337,7 @@ type textGridRenderer struct { cellSize fyne.Size objects []fyne.CanvasObject + current fyne.Canvas } func (t *textGridRenderer) appendTextCell(str rune) { @@ -369,9 +370,12 @@ func (t *textGridRenderer) setCellRune(str rune, pos int, style, rowStyle TextGr } else if rowStyle != nil && rowStyle.TextColor() != nil { fg = rowStyle.TextColor() } - text.Text = string(str) - text.Color = fg - canvas.Refresh(text) + newStr := string(str) + if text.Text != newStr || text.Color != fg { + text.Text = newStr + text.Color = fg + canvas.Refresh(text) + } rect := t.objects[pos*2].(*canvas.Rectangle) bg := color.Color(color.Transparent) @@ -380,8 +384,10 @@ func (t *textGridRenderer) setCellRune(str rune, pos int, style, rowStyle TextGr } else if rowStyle != nil && rowStyle.BackgroundColor() != nil { bg = rowStyle.BackgroundColor() } - rect.FillColor = bg - canvas.Refresh(rect) + if rect.FillColor != bg { + rect.FillColor = bg + canvas.Refresh(rect) + } } func (t *textGridRenderer) addCellsIfRequired() { From 47cac54531bddc619baf35f57450256253bd4d90 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 4 Jul 2023 10:56:59 +0100 Subject: [PATCH 2/2] Cache the canvas lookup for huge speedup We could be calling this 100s or 1000s of times if the entire text grid was refreshed (up to twice for each cell, possibly faster than refresh rate because this in the event thread not draw). Result is huge boost (see fyneterm usage for example) --- widget/textgrid.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/widget/textgrid.go b/widget/textgrid.go index 6204424780..0e28c9e94e 100644 --- a/widget/textgrid.go +++ b/widget/textgrid.go @@ -374,7 +374,7 @@ func (t *textGridRenderer) setCellRune(str rune, pos int, style, rowStyle TextGr if text.Text != newStr || text.Color != fg { text.Text = newStr text.Color = fg - canvas.Refresh(text) + t.refresh(text) } rect := t.objects[pos*2].(*canvas.Rectangle) @@ -386,7 +386,7 @@ func (t *textGridRenderer) setCellRune(str rune, pos int, style, rowStyle TextGr } if rect.FillColor != bg { rect.FillColor = bg - canvas.Refresh(rect) + t.refresh(rect) } } @@ -527,6 +527,11 @@ func (t *textGridRenderer) MinSize() fyne.Size { } func (t *textGridRenderer) Refresh() { + // we may be on a new canvas, so just update it to be sure + if fyne.CurrentApp() != nil && fyne.CurrentApp().Driver() != nil { + t.current = fyne.CurrentApp().Driver().CanvasForObject(t.text) + } + // theme could change text size t.updateCellSize() @@ -545,6 +550,21 @@ func (t *textGridRenderer) Objects() []fyne.CanvasObject { func (t *textGridRenderer) Destroy() { } +func (t *textGridRenderer) refresh(obj fyne.CanvasObject) { + if t.current == nil { + if fyne.CurrentApp() != nil && fyne.CurrentApp().Driver() != nil { + // cache canvas for this widget, so we don't look it up many times for every cell/row refresh! + t.current = fyne.CurrentApp().Driver().CanvasForObject(t.text) + } + + if t.current == nil { + return // not yet set up perhaps? + } + } + + t.current.Refresh(obj) +} + func (t *textGridRenderer) updateCellSize() { size := fyne.MeasureText("M", theme.TextSize(), fyne.TextStyle{Monospace: true})