diff --git a/widget/list.go b/widget/list.go index f9dcd680d3..3ab9498941 100644 --- a/widget/list.go +++ b/widget/list.go @@ -3,6 +3,7 @@ package widget import ( "fmt" "math" + "sync" "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" @@ -78,12 +79,12 @@ func (l *List) CreateRenderer() fyne.WidgetRenderer { l.itemMin = newListItem(f(), nil).MinSize() } } - layout := fyne.NewContainerWithLayout(newListLayout(l)) - layout.Resize(layout.MinSize()) + layout := &fyne.Container{} l.scroller = widget.NewVScroll(layout) + layout.Layout = newListLayout(l) + layout.Resize(layout.MinSize()) objects := []fyne.CanvasObject{l.scroller} lr := newListRenderer(objects, l, l.scroller, layout) - l.offsetUpdated = lr.offsetUpdated return lr } @@ -148,92 +149,20 @@ var _ fyne.WidgetRenderer = (*listRenderer)(nil) type listRenderer struct { widget.BaseRenderer - list *List - scroller *widget.Scroll - layout *fyne.Container - itemPool *syncPool - children []fyne.CanvasObject - size fyne.Size - visibleItemCount int - firstItemIndex ListItemID - lastItemIndex ListItemID - previousOffsetY float32 + list *List + scroller *widget.Scroll + layout *fyne.Container + size fyne.Size } func newListRenderer(objects []fyne.CanvasObject, l *List, scroller *widget.Scroll, layout *fyne.Container) *listRenderer { lr := &listRenderer{BaseRenderer: widget.NewBaseRenderer(objects), list: l, scroller: scroller, layout: layout} - lr.scroller.OnScrolled = lr.offsetUpdated + lr.scroller.OnScrolled = l.offsetUpdated return lr } func (l *listRenderer) Layout(size fyne.Size) { - length := 0 - if f := l.list.Length; f != nil { - length = f() - } - if length <= 0 { - if len(l.children) > 0 { - for _, child := range l.children { - l.itemPool.Release(child) - } - l.previousOffsetY = 0 - l.firstItemIndex = 0 - l.lastItemIndex = 0 - l.visibleItemCount = 0 - l.list.offsetY = 0 - l.layout.Layout.(*listLayout).layoutEndY = 0 - l.children = nil - l.layout.Objects = nil - l.list.Refresh() - } - return - } - if size != l.size { - if size.Width != l.size.Width { - for _, child := range l.children { - child.Resize(fyne.NewSize(size.Width, l.list.itemMin.Height)) - } - } - l.scroller.Resize(size) - l.size = size - } - if l.itemPool == nil { - l.itemPool = &syncPool{} - } - - // Relayout What Is Visible - no scroll change - initial layout or possibly from a resize. - l.visibleItemCount = int(math.Ceil(float64(l.scroller.Size().Height) / float64(l.list.itemMin.Height+theme.SeparatorThicknessSize()))) - if l.visibleItemCount <= 0 { - return - } - min := int(fyne.Min(float32(length), float32(l.visibleItemCount))) - if length < len(l.children) { - l.firstItemIndex = 0 - l.list.offsetY = 0 - l.visibleItemCount = min - } - if len(l.children) > min { - for i := len(l.children); i >= min; i-- { - l.itemPool.Release(l.children[i-1]) - } - l.children = l.children[:min-1] - } - for i := len(l.children) + l.firstItemIndex; len(l.children) <= l.visibleItemCount && i < length; i++ { - l.appendItem(i) - } - l.layout.Layout.(*listLayout).children = l.children - l.layout.Layout.Layout(l.children, l.list.itemMin) - l.layout.Objects = l.layout.Layout.(*listLayout).getObjects() - l.lastItemIndex = l.firstItemIndex + len(l.children) - 1 - - i := l.firstItemIndex - for _, child := range l.children { - if f := l.list.UpdateItem; f != nil { - f(i, child.(*listItem).child) - } - l.setupListItem(child, i) - i++ - } + l.scroller.Resize(size) } func (l *listRenderer) MinSize() fyne.Size { @@ -249,125 +178,6 @@ func (l *listRenderer) Refresh() { canvas.Refresh(l.list.super()) } -func (l *listRenderer) appendItem(id ListItemID) { - item := l.getItem() - l.children = append(l.children, item) - l.setupListItem(item, id) - l.layout.Layout.(*listLayout).children = l.children - l.layout.Layout.(*listLayout).appendedItem(l.children) - l.layout.Objects = l.layout.Layout.(*listLayout).getObjects() -} - -func (l *listRenderer) getItem() fyne.CanvasObject { - item := l.itemPool.Obtain() - if item == nil { - if f := l.list.CreateItem; f != nil { - item = newListItem(f(), nil) - } - } - return item -} - -func (l *listRenderer) offsetChanged() { - offsetChange := float32(math.Abs(float64(l.previousOffsetY - l.list.offsetY))) - - if l.previousOffsetY < l.list.offsetY { - // Scrolling Down. - l.scrollDown(offsetChange) - } else if l.previousOffsetY > l.list.offsetY { - // Scrolling Up. - l.scrollUp(offsetChange) - } - l.layout.Layout.(*listLayout).updateDividers() -} - -func (l *listRenderer) prependItem(id ListItemID) { - item := l.getItem() - l.children = append([]fyne.CanvasObject{item}, l.children...) - l.setupListItem(item, id) - l.layout.Layout.(*listLayout).children = l.children - l.layout.Layout.(*listLayout).prependedItem(l.children) - l.layout.Objects = l.layout.Layout.(*listLayout).getObjects() -} - -func (l *listRenderer) scrollDown(offsetChange float32) { - itemChange := 0 - separatorThickness := theme.SeparatorThicknessSize() - layoutEndY := l.children[len(l.children)-1].Position().Y + l.list.itemMin.Height + separatorThickness - scrollerEndY := l.scroller.Offset.Y + l.scroller.Size().Height - if layoutEndY < scrollerEndY { - itemChange = int(math.Ceil(float64(scrollerEndY-layoutEndY) / float64(l.list.itemMin.Height+separatorThickness))) - } else if offsetChange < l.list.itemMin.Height+separatorThickness { - return - } else { - itemChange = int(math.Floor(float64(offsetChange) / float64(l.list.itemMin.Height+separatorThickness))) - } - l.previousOffsetY = l.list.offsetY - length := 0 - if f := l.list.Length; f != nil { - length = f() - } - if length == 0 { - return - } - for i := 0; i < itemChange && l.lastItemIndex != length-1; i++ { - l.itemPool.Release(l.children[0]) - l.children = l.children[1:] - l.firstItemIndex++ - l.lastItemIndex++ - l.appendItem(l.lastItemIndex) - } -} - -func (l *listRenderer) scrollUp(offsetChange float32) { - itemChange := 0 - layoutStartY := l.children[0].Position().Y - separatorThickness := theme.SeparatorThicknessSize() - if layoutStartY > l.scroller.Offset.Y { - itemChange = int(math.Ceil(float64(layoutStartY-l.scroller.Offset.Y) / float64(l.list.itemMin.Height+separatorThickness))) - } else if offsetChange < l.list.itemMin.Height+separatorThickness { - return - } else { - itemChange = int(math.Floor(float64(offsetChange) / float64(l.list.itemMin.Height+separatorThickness))) - } - l.previousOffsetY = l.list.offsetY - for i := 0; i < itemChange && l.firstItemIndex != 0; i++ { - l.itemPool.Release(l.children[len(l.children)-1]) - l.children = l.children[:len(l.children)-1] - l.firstItemIndex-- - l.lastItemIndex-- - l.prependItem(l.firstItemIndex) - } -} - -func (l *listRenderer) setupListItem(item fyne.CanvasObject, id ListItemID) { - li := item.(*listItem) - previousIndicator := li.selected - li.selected = false - for _, s := range l.list.selected { - if id == s { - li.selected = true - } - } - if previousIndicator != li.selected { - item.Refresh() - } - if f := l.list.UpdateItem; f != nil { - f(id, li.child) - } - li.onTapped = func() { - l.list.Select(id) - } -} - -func (l *listRenderer) offsetUpdated(pos fyne.Position) { - if l.list.offsetY == pos.Y { - return - } - l.list.offsetY = pos.Y - l.offsetChanged() -} - // Declare conformity with interfaces. var _ fyne.Widget = (*listItem)(nil) var _ fyne.Tappable = (*listItem)(nil) @@ -485,28 +295,23 @@ type listLayout struct { list *List dividers []fyne.CanvasObject children []fyne.CanvasObject - layoutEndY float32 + + itemPool *syncPool + visible map[ListItemID]*listItem + renderLock sync.Mutex } func newListLayout(list *List) fyne.Layout { - return &listLayout{list: list} + l := &listLayout{list: list, itemPool: &syncPool{}, visible: make(map[ListItemID]*listItem)} + list.offsetUpdated = l.offsetUpdated + return l } -func (l *listLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { - if l.list.offsetY != 0 { - return - } - y := float32(0) - for _, child := range l.children { - child.Move(fyne.NewPos(0, y)) - y += l.list.itemMin.Height + theme.SeparatorThicknessSize() - child.Resize(fyne.NewSize(l.list.size.Width, l.list.itemMin.Height)) - } - l.layoutEndY = y - l.updateDividers() +func (l *listLayout) Layout([]fyne.CanvasObject, fyne.Size) { + l.updateList() } -func (l *listLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { +func (l *listLayout) MinSize([]fyne.CanvasObject) fyne.Size { if f := l.list.Length; f != nil { separatorThickness := theme.SeparatorThicknessSize() return fyne.NewSize(l.list.itemMin.Width, @@ -515,24 +320,97 @@ func (l *listLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { return fyne.NewSize(0, 0) } -func (l *listLayout) getObjects() []fyne.CanvasObject { - objects := l.children - objects = append(objects, l.dividers...) - return objects +func (l *listLayout) getItem() *listItem { + item := l.itemPool.Obtain() + if item == nil { + if f := l.list.CreateItem; f != nil { + item = newListItem(f(), nil) + } + } + return item.(*listItem) } -func (l *listLayout) appendedItem(objects []fyne.CanvasObject) { - if len(objects) > 1 { - objects[len(objects)-1].Move(fyne.NewPos(0, objects[len(objects)-2].Position().Y+l.list.itemMin.Height+theme.SeparatorThicknessSize())) - } else { - objects[len(objects)-1].Move(fyne.NewPos(0, 0)) +func (l *listLayout) offsetUpdated(pos fyne.Position) { + if l.list.offsetY == pos.Y { + return } - objects[len(objects)-1].Resize(fyne.NewSize(l.list.size.Width, l.list.itemMin.Height)) + l.list.offsetY = pos.Y + l.updateList() } -func (l *listLayout) prependedItem(objects []fyne.CanvasObject) { - objects[0].Move(fyne.NewPos(0, objects[1].Position().Y-l.list.itemMin.Height-theme.SeparatorThicknessSize())) - objects[0].Resize(fyne.NewSize(l.list.size.Width, l.list.itemMin.Height)) +func (l *listLayout) setupListItem(item fyne.CanvasObject, id ListItemID) { + li := item.(*listItem) + previousIndicator := li.selected + li.selected = false + for _, s := range l.list.selected { + if id == s { + li.selected = true + } + } + if previousIndicator != li.selected { + item.Refresh() + } + if f := l.list.UpdateItem; f != nil { + f(id, li.child) + } + li.onTapped = func() { + l.list.Select(id) + } +} + +func (l *listLayout) updateList() { + l.renderLock.Lock() + defer l.renderLock.Unlock() + separatorThickness := theme.SeparatorThicknessSize() + width := l.list.Size().Width + length := 0 + if f := l.list.Length; f != nil { + length = f() + } + visibleItemCount := int(math.Ceil(float64(l.list.scroller.Size().Height)/float64(l.list.itemMin.Height+theme.SeparatorThicknessSize()))) + 1 + offY := l.list.offsetY - float32(int(l.list.offsetY)%int(l.list.itemMin.Height+separatorThickness)) + minRow := ListItemID(offY / (l.list.itemMin.Height + separatorThickness)) + maxRow := ListItemID(fyne.Min(float32(minRow+visibleItemCount), float32(length))) + + updateItem := l.list.UpdateItem + if updateItem == nil { + fyne.LogError("Missing UpdateCell callback required for Table", nil) + } + + wasVisible := l.visible + l.visible = make(map[ListItemID]*listItem) + var cells []fyne.CanvasObject + y := offY + size := fyne.NewSize(width, l.list.itemMin.Height) + for row := minRow; row < maxRow; row++ { + c, ok := wasVisible[row] + if !ok { + c = l.getItem() + if c == nil { + continue + } + } + + c.Move(fyne.NewPos(0, y)) + c.Resize(size) + l.setupListItem(c, row) + + y += l.list.itemMin.Height + separatorThickness + l.visible[row] = c + cells = append(cells, c) + } + + for id, old := range wasVisible { + if _, ok := l.visible[id]; !ok { + l.itemPool.Release(old) + } + } + l.children = cells + l.updateDividers() + + objects := l.children + objects = append(objects, l.dividers...) + l.list.scroller.Content.(*fyne.Container).Objects = objects } func (l *listLayout) updateDividers() { diff --git a/widget/list_test.go b/widget/list_test.go index d00768e6b6..51a029ffc9 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -3,7 +3,6 @@ package widget import ( "fmt" "image/color" - "math" "testing" "time" @@ -21,15 +20,11 @@ func TestNewList(t *testing.T) { list := createList(1000) template := newListItem(fyne.NewContainerWithLayout(layout.NewHBoxLayout(), NewIcon(theme.DocumentIcon()), NewLabel("Template Object")), nil) - firstItemIndex := test.WidgetRenderer(list).(*listRenderer).firstItemIndex - lastItemIndex := test.WidgetRenderer(list).(*listRenderer).lastItemIndex - visibleCount := len(test.WidgetRenderer(list).(*listRenderer).children) assert.Equal(t, 1000, list.Length()) assert.GreaterOrEqual(t, list.MinSize().Width, template.MinSize().Width) assert.Equal(t, list.MinSize(), template.MinSize().Max(test.WidgetRenderer(list).(*listRenderer).scroller.MinSize())) - assert.Equal(t, 0, firstItemIndex) - assert.Equal(t, visibleCount, lastItemIndex-firstItemIndex+1) + assert.Equal(t, float32(0), list.offsetY) } func TestList_MinSize(t *testing.T) { @@ -63,27 +58,12 @@ func TestList_MinSize(t *testing.T) { func TestList_Resize(t *testing.T) { defer test.NewApp() list, w := setupList(t) - template := newListItem(fyne.NewContainerWithLayout(layout.NewHBoxLayout(), NewIcon(theme.DocumentIcon()), NewLabel("Template Object")), nil) - firstItemIndex := test.WidgetRenderer(list).(*listRenderer).firstItemIndex - lastItemIndex := test.WidgetRenderer(list).(*listRenderer).lastItemIndex - visibleCount := len(test.WidgetRenderer(list).(*listRenderer).children) - assert.Equal(t, 0, firstItemIndex) - assert.Equal(t, visibleCount, lastItemIndex-firstItemIndex+1) + assert.Equal(t, float32(0), list.offsetY) w.Resize(fyne.NewSize(200, 600)) - indexChange := int(math.Floor(float64(200) / float64(template.MinSize().Height))) - - newFirstItemIndex := test.WidgetRenderer(list).(*listRenderer).firstItemIndex - newLastItemIndex := test.WidgetRenderer(list).(*listRenderer).lastItemIndex - newVisibleCount := len(test.WidgetRenderer(list).(*listRenderer).children) - - assert.Equal(t, firstItemIndex, newFirstItemIndex) - assert.NotEqual(t, lastItemIndex, newLastItemIndex) - assert.Equal(t, newLastItemIndex, lastItemIndex+indexChange) - assert.NotEqual(t, visibleCount, newVisibleCount) - assert.Equal(t, newVisibleCount, newLastItemIndex-newFirstItemIndex+1) + assert.Equal(t, float32(0), list.offsetY) test.AssertRendersToMarkup(t, "list/resized.xml", w.Canvas()) } @@ -94,36 +74,19 @@ func TestList_OffsetChange(t *testing.T) { list := createList(1000) w := test.NewWindow(list) w.Resize(fyne.NewSize(200, 400)) - template := newListItem(fyne.NewContainerWithLayout(layout.NewHBoxLayout(), NewIcon(theme.DocumentIcon()), NewLabel("Template Object")), nil) - firstItemIndex := test.WidgetRenderer(list).(*listRenderer).firstItemIndex - lastItemIndex := test.WidgetRenderer(list).(*listRenderer).lastItemIndex - visibleCount := test.WidgetRenderer(list).(*listRenderer).visibleItemCount - - assert.Equal(t, 0, firstItemIndex) - assert.Equal(t, visibleCount, lastItemIndex-firstItemIndex) + assert.Equal(t, float32(0), list.offsetY) scroll := test.WidgetRenderer(list).(*listRenderer).scroller scroll.Scrolled(&fyne.ScrollEvent{Scrolled: fyne.NewDelta(0, -280)}) - indexChange := int(math.Floor(float64(300) / float64(template.MinSize().Height))) - - newFirstItemIndex := test.WidgetRenderer(list).(*listRenderer).firstItemIndex - newLastItemIndex := test.WidgetRenderer(list).(*listRenderer).lastItemIndex - newVisibleCount := test.WidgetRenderer(list).(*listRenderer).visibleItemCount - - assert.NotEqual(t, firstItemIndex, newFirstItemIndex) - assert.Equal(t, newFirstItemIndex, firstItemIndex+indexChange-1) - assert.NotEqual(t, lastItemIndex, newLastItemIndex) - assert.Equal(t, newLastItemIndex, lastItemIndex+indexChange-1) - assert.Equal(t, visibleCount, newVisibleCount) - assert.Equal(t, newVisibleCount, newLastItemIndex-newFirstItemIndex) + assert.NotEqual(t, 0, list.offsetY) test.AssertRendersToMarkup(t, "list/offset_changed.xml", w.Canvas()) } func TestList_Hover(t *testing.T) { list := createList(1000) - children := test.WidgetRenderer(list).(*listRenderer).children + children := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children for i := 0; i < 2; i++ { assert.False(t, children[i].(*listItem).statusIndicator.Visible()) @@ -136,7 +99,7 @@ func TestList_Hover(t *testing.T) { func TestList_Selection(t *testing.T) { list := createList(1000) - children := test.WidgetRenderer(list).(*listRenderer).children + children := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children assert.False(t, children[0].(*listItem).statusIndicator.Visible()) children[0].(*listItem).Tapped(&fyne.PointEvent{}) @@ -153,39 +116,52 @@ func TestList_Selection(t *testing.T) { } func TestList_Select(t *testing.T) { - list := createList(1000) + list := NewList( + func() int { + return 5 + }, + func() fyne.CanvasObject { + return NewLabel("") + }, + func(id ListItemID, item fyne.CanvasObject) { + }, + ) + list.Resize(fyne.NewSize(20, 20)) + list.Select(3) - assert.Equal(t, test.WidgetRenderer(list).(*listRenderer).firstItemIndex, 0) + list = createList(1000) + + assert.Equal(t, float32(0), list.offsetY) list.Select(50) - assert.Equal(t, test.WidgetRenderer(list).(*listRenderer).lastItemIndex, 50) - children := test.WidgetRenderer(list).(*listRenderer).children - assert.Equal(t, children[len(children)-1].(*listItem).statusIndicator.FillColor, theme.PrimaryColor()) - assert.True(t, children[len(children)-1].(*listItem).statusIndicator.Visible()) + assert.Equal(t, float32(1345), list.offsetY) + visible := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible + assert.Equal(t, visible[50].statusIndicator.FillColor, theme.PrimaryColor()) + assert.True(t, visible[50].statusIndicator.Visible()) list.Select(5) - assert.Equal(t, test.WidgetRenderer(list).(*listRenderer).firstItemIndex, 5) - children = test.WidgetRenderer(list).(*listRenderer).children - assert.Equal(t, children[0].(*listItem).statusIndicator.FillColor, theme.PrimaryColor()) - assert.True(t, children[0].(*listItem).statusIndicator.Visible()) + assert.Equal(t, float32(230), list.offsetY) + visible = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible + assert.Equal(t, visible[5].statusIndicator.FillColor, theme.FocusColor()) + assert.True(t, visible[5].statusIndicator.Visible()) list.Select(6) - assert.Equal(t, test.WidgetRenderer(list).(*listRenderer).firstItemIndex, 5) - children = test.WidgetRenderer(list).(*listRenderer).children - assert.False(t, children[0].(*listItem).statusIndicator.Visible()) - assert.Equal(t, children[1].(*listItem).statusIndicator.FillColor, theme.PrimaryColor()) - assert.True(t, children[1].(*listItem).statusIndicator.Visible()) + assert.Equal(t, float32(230), list.offsetY) + visible = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible + assert.False(t, visible[5].statusIndicator.Visible()) + assert.Equal(t, visible[6].statusIndicator.FillColor, theme.FocusColor()) + assert.True(t, visible[6].statusIndicator.Visible()) } func TestList_Unselect(t *testing.T) { list := createList(1000) list.Select(10) - children := test.WidgetRenderer(list).(*listRenderer).children - assert.Equal(t, children[10].(*listItem).statusIndicator.FillColor, theme.PrimaryColor()) + children := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children + assert.Equal(t, children[10].(*listItem).statusIndicator.FillColor, theme.FocusColor()) assert.True(t, children[10].(*listItem).statusIndicator.Visible()) list.Unselect(10) - children = test.WidgetRenderer(list).(*listRenderer).children + children = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children assert.False(t, children[10].(*listItem).statusIndicator.Visible()) assert.Nil(t, list.selected) } @@ -195,12 +171,12 @@ func TestList_DataChange(t *testing.T) { defer test.NewApp() list, w := setupList(t) - children := test.WidgetRenderer(list).(*listRenderer).children + 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.Refresh() - children = test.WidgetRenderer(list).(*listRenderer).children + 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()) } @@ -239,13 +215,13 @@ func TestList_SmallList(t *testing.T) { w := test.NewWindow(list) w.Resize(fyne.NewSize(200, 400)) - visibleCount := len(test.WidgetRenderer(list).(*listRenderer).children) + visibleCount := len(list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children) assert.Equal(t, visibleCount, 1) data = append(data, "Test Item 1") list.Refresh() - visibleCount = len(test.WidgetRenderer(list).(*listRenderer).children) + visibleCount = len(list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children) assert.Equal(t, visibleCount, 2) test.AssertRendersToMarkup(t, "list/small.xml", w.Canvas()) @@ -256,18 +232,12 @@ func TestList_ClearList(t *testing.T) { list, w := setupList(t) assert.Equal(t, 1000, list.Length()) - firstItemIndex := test.WidgetRenderer(list).(*listRenderer).firstItemIndex - lastItemIndex := test.WidgetRenderer(list).(*listRenderer).lastItemIndex - visibleCount := len(test.WidgetRenderer(list).(*listRenderer).children) - - assert.Equal(t, visibleCount, lastItemIndex-firstItemIndex+1) - list.Length = func() int { return 0 } list.Refresh() - visibleCount = len(test.WidgetRenderer(list).(*listRenderer).children) + visibleCount := len(list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children) assert.Equal(t, visibleCount, 0) @@ -297,13 +267,13 @@ func TestList_RemoveItem(t *testing.T) { w := test.NewWindow(list) w.Resize(fyne.NewSize(200, 400)) - visibleCount := len(test.WidgetRenderer(list).(*listRenderer).children) + visibleCount := len(list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children) assert.Equal(t, visibleCount, 3) data = data[:len(data)-1] list.Refresh() - visibleCount = len(test.WidgetRenderer(list).(*listRenderer).children) + visibleCount = len(list.scroller.Content.(*fyne.Container).Layout.(*listLayout).children) assert.Equal(t, visibleCount, 2) test.AssertRendersToMarkup(t, "list/item_removed.xml", w.Canvas()) } @@ -331,21 +301,19 @@ func TestList_ScrollThenShrink(t *testing.T) { w := test.NewWindow(list) w.Resize(fyne.NewSize(300, 300)) - visibles := test.WidgetRenderer(list).(*listRenderer).children - visibleCount := len(visibles) - assert.Equal(t, visibleCount, 8) + visibles := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible + assert.Equal(t, len(visibles), 8) list.scroller.ScrollToBottom() - visibles = test.WidgetRenderer(list).(*listRenderer).children - assert.Equal(t, "Data 19", visibles[len(visibles)-1].(*listItem).child.(*Label).Text) + visibles = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible + assert.Equal(t, "Data 19", visibles[19].child.(*Label).Text) data = data[:1] assert.NotPanics(t, func() { list.Refresh() }) - visibles = test.WidgetRenderer(list).(*listRenderer).children - visibleCount = len(visibles) - assert.Equal(t, visibleCount, 1) - assert.Equal(t, "Data 0", visibles[0].(*listItem).child.(*Label).Text) + visibles = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible + assert.Equal(t, len(visibles), 1) + assert.Equal(t, "Data 0", visibles[0].child.(*Label).Text) } func TestList_NoFunctionsSet(t *testing.T) { diff --git a/widget/testdata/list/initial.xml b/widget/testdata/list/initial.xml index 9d8a9abd85..c839fe98b1 100644 --- a/widget/testdata/list/initial.xml +++ b/widget/testdata/list/initial.xml @@ -28,8 +28,8 @@ - - Test Item 2 + + Test Item 2 @@ -38,8 +38,8 @@ - - Test Item 3 + + Test Item 3 @@ -48,8 +48,8 @@ - - Test Item 4 + + Test Item 4 @@ -58,8 +58,8 @@ - - Test Item 5 + + Test Item 5 @@ -68,8 +68,8 @@ - - Test Item 6 + + Test Item 6 @@ -78,8 +78,8 @@ - - Test Item 7 + + Test Item 7 @@ -88,8 +88,8 @@ - - Test Item 8 + + Test Item 8 diff --git a/widget/testdata/list/new_data.xml b/widget/testdata/list/new_data.xml index 052173c1ca..ddbf69f4de 100644 --- a/widget/testdata/list/new_data.xml +++ b/widget/testdata/list/new_data.xml @@ -28,8 +28,8 @@ - - c + + c @@ -48,8 +48,8 @@ - - e + + e @@ -88,8 +88,8 @@ - - i + + i @@ -98,8 +98,8 @@ - - j + + j diff --git a/widget/testdata/list/offset_changed.xml b/widget/testdata/list/offset_changed.xml index 2671f26b12..ce0fd3683b 100644 --- a/widget/testdata/list/offset_changed.xml +++ b/widget/testdata/list/offset_changed.xml @@ -3,23 +3,13 @@ - - - - - - - Test Item 5 - - - - - Test Item 6 + + Test Item 6 @@ -28,8 +18,8 @@ - - Test Item 7 + + Test Item 7 @@ -38,8 +28,8 @@ - - Test Item 8 + + Test Item 8 @@ -48,8 +38,8 @@ - - Test Item 9 + + Test Item 9 @@ -58,8 +48,8 @@ - - Test Item 10 + + Test Item 10 @@ -68,8 +58,8 @@ - - Test Item 11 + + Test Item 11 @@ -78,8 +68,8 @@ - - Test Item 12 + + Test Item 12 @@ -98,17 +88,24 @@ - - Test Item 14 + + Test Item 14 + + + + + + + + + + Test Item 15 - - - @@ -133,6 +130,9 @@ + + + diff --git a/widget/testdata/list/resized.xml b/widget/testdata/list/resized.xml index 29c3b9cf7f..7bf93b9fd8 100644 --- a/widget/testdata/list/resized.xml +++ b/widget/testdata/list/resized.xml @@ -28,8 +28,8 @@ - - Test Item 2 + + Test Item 2 @@ -38,8 +38,8 @@ - - Test Item 3 + + Test Item 3 @@ -48,8 +48,8 @@ - - Test Item 4 + + Test Item 4 @@ -68,8 +68,8 @@ - - Test Item 6 + + Test Item 6 @@ -78,8 +78,8 @@ - - Test Item 7 + + Test Item 7 @@ -108,8 +108,8 @@ - - Test Item 10 + + Test Item 10 diff --git a/widget/testdata/list/small.xml b/widget/testdata/list/small.xml index 107e8de667..5b7a21e6f8 100644 --- a/widget/testdata/list/small.xml +++ b/widget/testdata/list/small.xml @@ -18,8 +18,8 @@ - - Test Item 1 + + Test Item 1