From 38462d078c4759d9cc9ab3aea94553eef6ab25e1 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sat, 1 Jul 2023 23:04:57 -0400 Subject: [PATCH 01/18] add check for previous visible items --- widget/list.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/widget/list.go b/widget/list.go index f9b3c69e75..15b033456e 100644 --- a/widget/list.go +++ b/widget/list.go @@ -559,7 +559,7 @@ func (l *listLayout) offsetUpdated(pos fyne.Position) { l.updateList(false) } -func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool) { +func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool, update bool) { previousIndicator := li.selected li.selected = false for _, s := range l.list.selected { @@ -575,7 +575,7 @@ func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool) { li.hovered = false li.Refresh() } - if f := l.list.UpdateItem; f != nil { + if f := l.list.UpdateItem; f != nil && update { f(id, li.child) } li.onTapped = func() { @@ -654,8 +654,9 @@ func (l *listLayout) updateList(refresh bool) { l.list.scroller.Content.(*fyne.Container).Objects = objects l.renderLock.Unlock() // user code should not be locked - for row, obj := range visible { - l.setupListItem(obj, row, focused == obj) + for cId, vItem := range visible { + _, wasVisible := wasVisible[cId] + l.setupListItem(vItem, cId, focused == vItem, !wasVisible) } } From 298f5a2088beef44afb7de2b1fd0748822de8482 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 00:15:33 -0400 Subject: [PATCH 02/18] test WIP --- widget/list_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/widget/list_test.go b/widget/list_test.go index e24de240f0..7146f31d58 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -578,3 +578,13 @@ func setupList(t *testing.T) (*List, fyne.Window) { test.AssertRendersToMarkup(t, "list/initial.xml", w.Canvas()) return list, w } + +func TestList_LimitUpdateItem(t *testing.T) { + updateItemCalls := 0 + list := createList(20) + list.UpdateItem = func(id ListItemID, item fyne.CanvasObject) { + updateItemCalls++ + } + assert.Equal(t, 1, updateItemCalls) + +} From ccafeac00396fa325bc016c15b855cbc5b341ebb Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 01:23:43 -0400 Subject: [PATCH 03/18] test to check for limit --- widget/list_test.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/widget/list_test.go b/widget/list_test.go index 7146f31d58..de78425fbb 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -580,11 +580,25 @@ func setupList(t *testing.T) (*List, fyne.Window) { } func TestList_LimitUpdateItem(t *testing.T) { + app := test.NewApp() + w := app.NewWindow("") + w.Resize(fyne.NewSize(500, 500)) updateItemCalls := 0 - list := createList(20) - list.UpdateItem = func(id ListItemID, item fyne.CanvasObject) { - updateItemCalls++ - } - assert.Equal(t, 1, updateItemCalls) - + list := NewList( + func() int { + return 20 + }, + func() fyne.CanvasObject { + return NewLabel("") + }, + func(id ListItemID, item fyne.CanvasObject) { + updateItemCalls++ + }, + ) + w.SetContent(list) + w.ShowAndRun() + list.scrollTo(10) + list.scrollTo(20) + time.Sleep(2 * time.Second) + assert.Equal(t, 3, updateItemCalls) } From f75ab9d65fa1c085b6e51eaf683268a218ec79f2 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 17:47:45 -0400 Subject: [PATCH 04/18] create List Refresh --- widget/list.go | 24 ++++++++++++++++++++++++ widget/list_test.go | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/widget/list.go b/widget/list.go index 15b033456e..4e633cdf82 100644 --- a/widget/list.go +++ b/widget/list.go @@ -9,6 +9,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -93,6 +94,29 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } +func (l *List) Refresh() { + if l.scroller != nil { + impl := l.super() + if impl == nil { + return + } + + render := cache.Renderer(impl) + render.Refresh() + + lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) + visible := lo.visible + canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) + var focused fyne.Focusable + if canvas != nil { + focused = canvas.Focused() + } + for id, item := range visible { + lo.setupListItem(item, id, focused == item, true) + } + } +} + // SetItemHeight supports changing the height of the specified list item. Items normally take the height of the template // returned from the CreateItem callback. The height parameter uses the same units as a fyne.Size type and refers // to the internal content height not including the divider size. diff --git a/widget/list_test.go b/widget/list_test.go index de78425fbb..c9ea112ae8 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -302,7 +302,7 @@ func TestList_DataChange(t *testing.T) { test.NewApp() defer test.NewApp() - list, w := setupList(t) + list, _ := setupList(t) children := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children assert.Equal(t, children[0].(*listItem).child.(*fyne.Container).Objects[1].(*Label).Text, "Test Item 0") @@ -310,7 +310,7 @@ func TestList_DataChange(t *testing.T) { list.Refresh() children = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children assert.Equal(t, children[0].(*listItem).child.(*fyne.Container).Objects[1].(*Label).Text, "a") - test.AssertRendersToMarkup(t, "list/new_data.xml", w.Canvas()) + // test.AssertRendersToMarkup(t, "list/new_data.xml", w.Canvas()) } func TestList_ThemeChange(t *testing.T) { From 6a54bbcd2dad684cc1da0c5cfadcce025ba58df7 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 18:01:11 -0400 Subject: [PATCH 05/18] reuse --- widget/list.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/widget/list.go b/widget/list.go index 4e633cdf82..a2ec3a571c 100644 --- a/widget/list.go +++ b/widget/list.go @@ -9,7 +9,6 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" - "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -96,14 +95,7 @@ func (l *List) MinSize() fyne.Size { func (l *List) Refresh() { if l.scroller != nil { - impl := l.super() - if impl == nil { - return - } - - render := cache.Renderer(impl) - render.Refresh() - + l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) visible := lo.visible canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) From 6cd553bd4efde74ecc7f996d905296befd574462 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 23:00:02 -0400 Subject: [PATCH 06/18] revert test --- widget/list_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widget/list_test.go b/widget/list_test.go index c9ea112ae8..de78425fbb 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -302,7 +302,7 @@ func TestList_DataChange(t *testing.T) { test.NewApp() defer test.NewApp() - list, _ := setupList(t) + list, w := setupList(t) children := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children assert.Equal(t, children[0].(*listItem).child.(*fyne.Container).Objects[1].(*Label).Text, "Test Item 0") @@ -310,7 +310,7 @@ func TestList_DataChange(t *testing.T) { list.Refresh() children = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children assert.Equal(t, children[0].(*listItem).child.(*fyne.Container).Objects[1].(*Label).Text, "a") - // test.AssertRendersToMarkup(t, "list/new_data.xml", w.Canvas()) + test.AssertRendersToMarkup(t, "list/new_data.xml", w.Canvas()) } func TestList_ThemeChange(t *testing.T) { From 9de66c964cbcf098a86e3429cb223c56b98fabac Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 23:20:08 -0400 Subject: [PATCH 07/18] WIP - calls reduced. Selection no worky --- widget/list.go | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/widget/list.go b/widget/list.go index a2ec3a571c..a3be1a4c46 100644 --- a/widget/list.go +++ b/widget/list.go @@ -93,7 +93,7 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } -func (l *List) Refresh() { +func (l *List) RefreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { if l.scroller != nil { l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) @@ -103,7 +103,22 @@ func (l *List) Refresh() { if canvas != nil { focused = canvas.Focused() } - for id, item := range visible { + return lo, visible, focused + } + return nil, nil, nil +} + +func (l *List) Refresh() { + lo, visible, focused := l.RefreshBase() + for id, item := range visible { + lo.setupListItem(item, id, focused == item, true) + } +} + +func (l *List) RefreshItem(id ListItemID) { + lo, visible, focused := l.RefreshBase() + for vId, item := range visible { + if id == vId { lo.setupListItem(item, id, focused == item, true) } } @@ -126,7 +141,7 @@ func (l *List) SetItemHeight(id ListItemID, height float32) { l.propertyLock.Unlock() if refresh { - l.Refresh() + l.RefreshItem(id) } } @@ -389,6 +404,10 @@ func newListItem(child fyne.CanvasObject, tapped func()) *listItem { return li } +func (li *listItem) Refresh() { + return +} + // CreateRenderer is a private method to Fyne which links this widget to its renderer. func (li *listItem) CreateRenderer() fyne.WidgetRenderer { li.ExtendBaseWidget(li) @@ -524,7 +543,7 @@ func newListLayout(list *List) fyne.Layout { } func (l *listLayout) Layout([]fyne.CanvasObject, fyne.Size) { - l.updateList(true) + l.updateList(false) } func (l *listLayout) MinSize([]fyne.CanvasObject) fyne.Size { From 4d29639351137f230f56bfc2edd700c8437d4efe Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 2 Jul 2023 23:54:31 -0400 Subject: [PATCH 08/18] moved tracking of update to itemList --- widget/list.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/widget/list.go b/widget/list.go index a3be1a4c46..f85f3c72fa 100644 --- a/widget/list.go +++ b/widget/list.go @@ -111,7 +111,8 @@ func (l *List) RefreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { func (l *List) Refresh() { lo, visible, focused := l.RefreshBase() for id, item := range visible { - lo.setupListItem(item, id, focused == item, true) + item.updated = false + lo.setupListItem(item, id, focused == item) } } @@ -119,7 +120,7 @@ func (l *List) RefreshItem(id ListItemID) { lo, visible, focused := l.RefreshBase() for vId, item := range visible { if id == vId { - lo.setupListItem(item, id, focused == item, true) + lo.setupListItem(item, id, focused == item) } } } @@ -392,22 +393,20 @@ type listItem struct { background *canvas.Rectangle child fyne.CanvasObject hovered, selected bool + updated bool } func newListItem(child fyne.CanvasObject, tapped func()) *listItem { li := &listItem{ child: child, onTapped: tapped, + updated: false, } li.ExtendBaseWidget(li) return li } -func (li *listItem) Refresh() { - return -} - // CreateRenderer is a private method to Fyne which links this widget to its renderer. func (li *listItem) CreateRenderer() fyne.WidgetRenderer { li.ExtendBaseWidget(li) @@ -543,7 +542,7 @@ func newListLayout(list *List) fyne.Layout { } func (l *listLayout) Layout([]fyne.CanvasObject, fyne.Size) { - l.updateList(false) + l.updateList(true) } func (l *listLayout) MinSize([]fyne.CanvasObject) fyne.Size { @@ -594,7 +593,7 @@ func (l *listLayout) offsetUpdated(pos fyne.Position) { l.updateList(false) } -func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool, update bool) { +func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool) { previousIndicator := li.selected li.selected = false for _, s := range l.list.selected { @@ -610,8 +609,11 @@ func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool, upda li.hovered = false li.Refresh() } - if f := l.list.UpdateItem; f != nil && update { - f(id, li.child) + if _, ok := l.visible[id]; ok { + if f := l.list.UpdateItem; f != nil && !l.visible[id].updated { + l.visible[id].updated = true + f(id, li.child) + } } li.onTapped = func() { l.list.Select(id) @@ -674,6 +676,7 @@ func (l *listLayout) updateList(refresh bool) { } for id, old := range wasVisible { if _, ok := l.visible[id]; !ok { + wasVisible[id].updated = false if focused == old { canvas.Focus(nil) } @@ -690,8 +693,7 @@ func (l *listLayout) updateList(refresh bool) { l.renderLock.Unlock() // user code should not be locked for cId, vItem := range visible { - _, wasVisible := wasVisible[cId] - l.setupListItem(vItem, cId, focused == vItem, !wasVisible) + l.setupListItem(vItem, cId, focused == vItem) } } From 891384857b428373328bd9d586a166ecc7907c06 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Mon, 3 Jul 2023 00:15:23 -0400 Subject: [PATCH 09/18] derp it's a map --- widget/list.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/widget/list.go b/widget/list.go index f85f3c72fa..e6db150cb4 100644 --- a/widget/list.go +++ b/widget/list.go @@ -118,10 +118,8 @@ func (l *List) Refresh() { func (l *List) RefreshItem(id ListItemID) { lo, visible, focused := l.RefreshBase() - for vId, item := range visible { - if id == vId { - lo.setupListItem(item, id, focused == item) - } + if item, ok := visible[id]; ok { + lo.setupListItem(item, id, focused == item) } } From c80e2efda0b25ba4b46eef16f9b300ce84c7238f Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Mon, 3 Jul 2023 00:40:28 -0400 Subject: [PATCH 10/18] add test to detect refresh updating items --- widget/list_test.go | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/widget/list_test.go b/widget/list_test.go index de78425fbb..c6851ea31a 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -582,23 +582,45 @@ func setupList(t *testing.T) (*List, fyne.Window) { func TestList_LimitUpdateItem(t *testing.T) { app := test.NewApp() w := app.NewWindow("") - w.Resize(fyne.NewSize(500, 500)) - updateItemCalls := 0 + printOut := "" list := NewList( func() int { - return 20 + return 5 }, func() fyne.CanvasObject { - return NewLabel("") + return NewLabel("Test") }, func(id ListItemID, item fyne.CanvasObject) { - updateItemCalls++ + printOut += fmt.Sprintf("%d.", id) }, ) w.SetContent(list) w.ShowAndRun() - list.scrollTo(10) - list.scrollTo(20) + list.scrollTo(1) + list.scrollTo(2) time.Sleep(2 * time.Second) - assert.Equal(t, 3, updateItemCalls) + assert.Equal(t, "0.1.2.", printOut) +} + +func TestList_RefreshUpdatesAllItems(t *testing.T) { + app := test.NewApp() + w := app.NewWindow("") + printOut := "" + list := NewList( + func() int { + return 1 + }, + func() fyne.CanvasObject { + return NewLabel("Test") + }, + func(id ListItemID, item fyne.CanvasObject) { + printOut += fmt.Sprintf("%d.", id) + }, + ) + w.SetContent(list) + w.ShowAndRun() + assert.Equal(t, "0.", printOut) + + list.Refresh() + assert.Equal(t, "0.0.", printOut) } From 023d46fa25ce5d7f130af1fdb18eab0b52c185d2 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Mon, 3 Jul 2023 00:47:47 -0400 Subject: [PATCH 11/18] update test --- widget/list_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/list_test.go b/widget/list_test.go index c6851ea31a..5186288bc8 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -588,7 +588,7 @@ func TestList_LimitUpdateItem(t *testing.T) { return 5 }, func() fyne.CanvasObject { - return NewLabel("Test") + return NewLabel("") }, func(id ListItemID, item fyne.CanvasObject) { printOut += fmt.Sprintf("%d.", id) From 7484dd97a1a1fc5af2b9be96f2e6a3961fea39cf Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Mon, 3 Jul 2023 08:50:50 -0400 Subject: [PATCH 12/18] make base refresh private --- widget/list.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widget/list.go b/widget/list.go index e6db150cb4..ca21a3dea8 100644 --- a/widget/list.go +++ b/widget/list.go @@ -93,7 +93,7 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } -func (l *List) RefreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { +func (l *List) refreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { if l.scroller != nil { l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) @@ -109,7 +109,7 @@ func (l *List) RefreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { } func (l *List) Refresh() { - lo, visible, focused := l.RefreshBase() + lo, visible, focused := l.refreshBase() for id, item := range visible { item.updated = false lo.setupListItem(item, id, focused == item) @@ -117,7 +117,7 @@ func (l *List) Refresh() { } func (l *List) RefreshItem(id ListItemID) { - lo, visible, focused := l.RefreshBase() + lo, visible, focused := l.refreshBase() if item, ok := visible[id]; ok { lo.setupListItem(item, id, focused == item) } From cdb15d1cb55abe7cccc41c24d53cd26b05e939f0 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Thu, 6 Jul 2023 21:05:04 -0400 Subject: [PATCH 13/18] reworked --- widget/list.go | 52 +++++++++++++++++---------------------------- widget/list_test.go | 5 +++-- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/widget/list.go b/widget/list.go index ca21a3dea8..72642bf470 100644 --- a/widget/list.go +++ b/widget/list.go @@ -93,7 +93,7 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } -func (l *List) refreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { +func (l *List) RefreshItem(id ListItemID) { if l.scroller != nil { l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) @@ -103,23 +103,9 @@ func (l *List) refreshBase() (*listLayout, map[int]*listItem, fyne.Focusable) { if canvas != nil { focused = canvas.Focused() } - return lo, visible, focused - } - return nil, nil, nil -} - -func (l *List) Refresh() { - lo, visible, focused := l.refreshBase() - for id, item := range visible { - item.updated = false - lo.setupListItem(item, id, focused == item) - } -} - -func (l *List) RefreshItem(id ListItemID) { - lo, visible, focused := l.refreshBase() - if item, ok := visible[id]; ok { - lo.setupListItem(item, id, focused == item) + if item, ok := visible[id]; ok { + lo.setupListItem(item, id, focused == item) + } } } @@ -182,7 +168,7 @@ func (l *List) Resize(s fyne.Size) { } l.offsetUpdated(l.scroller.Offset) - l.scroller.Content.(*fyne.Container).Layout.(*listLayout).updateList(true) + l.scroller.Content.(*fyne.Container).Layout.(*listLayout).updateList(false) } // Select add the item identified by the given ID to the selection. @@ -374,7 +360,7 @@ func (l *listRenderer) Refresh() { } l.Layout(l.list.Size()) l.scroller.Refresh() - l.layout.Layout.(*listLayout).updateList(true) + l.layout.Layout.(*listLayout).updateList(false) canvas.Refresh(l.list.super()) } @@ -391,14 +377,12 @@ type listItem struct { background *canvas.Rectangle child fyne.CanvasObject hovered, selected bool - updated bool } func newListItem(child fyne.CanvasObject, tapped func()) *listItem { li := &listItem{ child: child, onTapped: tapped, - updated: false, } li.ExtendBaseWidget(li) @@ -588,7 +572,7 @@ func (l *listLayout) offsetUpdated(pos fyne.Position) { return } l.list.offsetY = pos.Y - l.updateList(false) + l.updateList(true) } func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool) { @@ -607,18 +591,15 @@ func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool) { li.hovered = false li.Refresh() } - if _, ok := l.visible[id]; ok { - if f := l.list.UpdateItem; f != nil && !l.visible[id].updated { - l.visible[id].updated = true - f(id, li.child) - } + if f := l.list.UpdateItem; f != nil { + f(id, li.child) } li.onTapped = func() { l.list.Select(id) } } -func (l *listLayout) updateList(refresh bool) { +func (l *listLayout) updateList(newOnly bool) { l.renderLock.Lock() separatorThickness := theme.Padding() width := l.list.Size().Width @@ -674,7 +655,6 @@ func (l *listLayout) updateList(refresh bool) { } for id, old := range wasVisible { if _, ok := l.visible[id]; !ok { - wasVisible[id].updated = false if focused == old { canvas.Focus(nil) } @@ -690,8 +670,16 @@ func (l *listLayout) updateList(refresh bool) { l.list.scroller.Content.(*fyne.Container).Objects = objects l.renderLock.Unlock() // user code should not be locked - for cId, vItem := range visible { - l.setupListItem(vItem, cId, focused == vItem) + if newOnly { + for nId, nItem := range visible { + if _, ok := wasVisible[nId]; !ok { + l.setupListItem(nItem, nId, focused == nItem) + } + } + } else { + for row, obj := range visible { + l.setupListItem(obj, row, focused == obj) + } } } diff --git a/widget/list_test.go b/widget/list_test.go index 5186288bc8..1967d79b68 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -596,10 +596,11 @@ func TestList_LimitUpdateItem(t *testing.T) { ) w.SetContent(list) w.ShowAndRun() + assert.Equal(t, "0.0.", printOut) list.scrollTo(1) + assert.Equal(t, "0.0.1.", printOut) list.scrollTo(2) - time.Sleep(2 * time.Second) - assert.Equal(t, "0.1.2.", printOut) + assert.Equal(t, "0.0.1.2.", printOut) } func TestList_RefreshUpdatesAllItems(t *testing.T) { From c36887b20ab1adfddd1f3b844d5037bd71212ba3 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Thu, 6 Jul 2023 23:14:42 -0400 Subject: [PATCH 14/18] add test for RefreshItem --- widget/list_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/widget/list_test.go b/widget/list_test.go index 1967d79b68..e61e9b51d8 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -313,6 +313,19 @@ func TestList_DataChange(t *testing.T) { test.AssertRendersToMarkup(t, "list/new_data.xml", w.Canvas()) } +func TestList_ItemDataChange(t *testing.T) { + test.NewApp() + defer test.NewApp() + + list, _ := setupList(t) + children := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children + assert.Equal(t, children[0].(*listItem).child.(*fyne.Container).Objects[1].(*Label).Text, "Test Item 0") + changeData(list) + list.RefreshItem(0) + children = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children + assert.Equal(t, children[0].(*listItem).child.(*fyne.Container).Objects[1].(*Label).Text, "a") +} + func TestList_ThemeChange(t *testing.T) { defer test.NewApp() list, w := setupList(t) From 78f06fe3d474702c0460ae17e6e05dfe9ca45a6a Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 9 Jul 2023 01:01:09 -0400 Subject: [PATCH 15/18] conforming to coding standards --- widget/list.go | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/widget/list.go b/widget/list.go index 72642bf470..7b0c8640da 100644 --- a/widget/list.go +++ b/widget/list.go @@ -93,19 +93,23 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } +// RefreshItem refreshes a single item, specified by the item ID passed in. +// +// Since 2.4 func (l *List) RefreshItem(id ListItemID) { if l.scroller != nil { - l.BaseWidget.Refresh() - lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible := lo.visible - canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) - var focused fyne.Focusable - if canvas != nil { - focused = canvas.Focused() - } - if item, ok := visible[id]; ok { - lo.setupListItem(item, id, focused == item) - } + return + } + l.BaseWidget.Refresh() + lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) + visible := lo.visible + canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) + var focused fyne.Focusable + if canvas != nil { + focused = canvas.Focused() + } + if item, ok := visible[id]; ok { + lo.setupListItem(item, id, focused == item) } } @@ -671,9 +675,9 @@ func (l *listLayout) updateList(newOnly bool) { l.renderLock.Unlock() // user code should not be locked if newOnly { - for nId, nItem := range visible { - if _, ok := wasVisible[nId]; !ok { - l.setupListItem(nItem, nId, focused == nItem) + for row, obj := range visible { + if _, ok := wasVisible[row]; !ok { + l.setupListItem(obj, row, focused == obj) } } } else { From c775ba52fe7bb33967b5f45301dec9c67fa86342 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 9 Jul 2023 01:03:48 -0400 Subject: [PATCH 16/18] Revert "conforming to coding standards" This reverts commit 78f06fe3d474702c0460ae17e6e05dfe9ca45a6a. --- widget/list.go | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/widget/list.go b/widget/list.go index 7b0c8640da..72642bf470 100644 --- a/widget/list.go +++ b/widget/list.go @@ -93,23 +93,19 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } -// RefreshItem refreshes a single item, specified by the item ID passed in. -// -// Since 2.4 func (l *List) RefreshItem(id ListItemID) { if l.scroller != nil { - return - } - l.BaseWidget.Refresh() - lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible := lo.visible - canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) - var focused fyne.Focusable - if canvas != nil { - focused = canvas.Focused() - } - if item, ok := visible[id]; ok { - lo.setupListItem(item, id, focused == item) + l.BaseWidget.Refresh() + lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) + visible := lo.visible + canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) + var focused fyne.Focusable + if canvas != nil { + focused = canvas.Focused() + } + if item, ok := visible[id]; ok { + lo.setupListItem(item, id, focused == item) + } } } @@ -675,9 +671,9 @@ func (l *listLayout) updateList(newOnly bool) { l.renderLock.Unlock() // user code should not be locked if newOnly { - for row, obj := range visible { - if _, ok := wasVisible[row]; !ok { - l.setupListItem(obj, row, focused == obj) + for nId, nItem := range visible { + if _, ok := wasVisible[nId]; !ok { + l.setupListItem(nItem, nId, focused == nItem) } } } else { From a95be4663ad76c6287d513494e299a6e80bc072e Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 9 Jul 2023 01:12:18 -0400 Subject: [PATCH 17/18] fix refactor error --- widget/list.go | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/widget/list.go b/widget/list.go index 72642bf470..5455c0d1a6 100644 --- a/widget/list.go +++ b/widget/list.go @@ -93,19 +93,23 @@ func (l *List) MinSize() fyne.Size { return l.BaseWidget.MinSize() } +// RefreshItem refreshes a single item, specified by the item ID passed in. +// +// Since 2.4 func (l *List) RefreshItem(id ListItemID) { - if l.scroller != nil { - l.BaseWidget.Refresh() - lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible := lo.visible - canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) - var focused fyne.Focusable - if canvas != nil { - focused = canvas.Focused() - } - if item, ok := visible[id]; ok { - lo.setupListItem(item, id, focused == item) - } + if l.scroller == nil { + return + } + l.BaseWidget.Refresh() + lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) + visible := lo.visible + canvas := fyne.CurrentApp().Driver().CanvasForObject(lo.list) + var focused fyne.Focusable + if canvas != nil { + focused = canvas.Focused() + } + if item, ok := visible[id]; ok { + lo.setupListItem(item, id, focused == item) } } @@ -671,9 +675,9 @@ func (l *listLayout) updateList(newOnly bool) { l.renderLock.Unlock() // user code should not be locked if newOnly { - for nId, nItem := range visible { - if _, ok := wasVisible[nId]; !ok { - l.setupListItem(nItem, nId, focused == nItem) + for row, obj := range visible { + if _, ok := wasVisible[row]; !ok { + l.setupListItem(obj, row, focused == obj) } } } else { From c7bafe1f26a0b6474520ddcc6b670aa6a8711335 Mon Sep 17 00:00:00 2001 From: Sayem Quazi Date: Sun, 9 Jul 2023 09:29:10 -0400 Subject: [PATCH 18/18] Update widget/list.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jacob Alzén --- widget/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/list.go b/widget/list.go index 5455c0d1a6..3d4e805b7a 100644 --- a/widget/list.go +++ b/widget/list.go @@ -95,7 +95,7 @@ func (l *List) MinSize() fyne.Size { // RefreshItem refreshes a single item, specified by the item ID passed in. // -// Since 2.4 +// Since: 2.4 func (l *List) RefreshItem(id ListItemID) { if l.scroller == nil { return