From 8955049bd210f580b9c0cc0c2c0b3b165183a5b1 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 8 Nov 2023 08:42:51 -0800 Subject: [PATCH 1/6] add myself to github sponsors --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 3eaff5b70d..20db0f4412 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: [fyne-io, andydotxyz, toaster, Jacalz, changkun] +github: [fyne-io, andydotxyz, toaster, Jacalz, changkun, dweymouth] From a09bbd790b98120bc406a064f80aeafb4ca97656 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 24 Dec 2023 12:49:04 +0000 Subject: [PATCH 2/6] Fix merge glitch --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e016b4f2..0c2231c0ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,6 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -<<<<<<< HEAD ## 2.4.3 - 23 December 2023 ### Fixed From 0ace38672951e9e2879334aa058878e2c0f63233 Mon Sep 17 00:00:00 2001 From: Luca Corbo Date: Tue, 30 Jan 2024 19:33:19 +0100 Subject: [PATCH 3/6] add myself to github sponsors --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 20db0f4412..779eb235a9 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: [fyne-io, andydotxyz, toaster, Jacalz, changkun, dweymouth] +github: [fyne-io, andydotxyz, toaster, Jacalz, changkun, dweymouth, lucor] From ea865ab24f243afd3177961018b4bebdb8b1cedd Mon Sep 17 00:00:00 2001 From: m-rei Date: Tue, 5 Mar 2024 22:57:02 +0100 Subject: [PATCH 4/6] Scrolling via home/end/page up/page down in list/table/tree --- widget/list.go | 33 ++++++++++++++++ widget/list_test.go | 20 ++++++++++ widget/table.go | 38 ++++++++++++++++++ widget/table_test.go | 66 ++++++++++++++++++++++++++++++++ widget/tree.go | 41 ++++++++++++++++++++ widget/tree_internal_test.go | 74 ++++++++++++++++++++++++++++++++++++ 6 files changed, 272 insertions(+) diff --git a/widget/list.go b/widget/list.go index 23636edbb2..89060d311e 100644 --- a/widget/list.go +++ b/widget/list.go @@ -257,11 +257,44 @@ func (l *List) ScrollToTop() { l.Refresh() } +// scrollByOnePage scrolls down or up by list height +func (l *List) scrollByOnePage(down bool) { + if l.scroller == nil { + return + } + + if down { + l.scroller.Offset.Y += l.size.Height + } else { + l.scroller.Offset.Y -= l.size.Height + } + l.offsetUpdated(l.scroller.Offset) + l.Refresh() +} + +// ScrollUpOnePage scrolls up one page (table height) +func (l *List) ScrollUpOnePage() { + l.scrollByOnePage(false) +} + +// ScrollDownOnePage scrolls down one page (table height) +func (l *List) ScrollDownOnePage() { + l.scrollByOnePage(true) +} + // TypedKey is called if a key event happens while this List is focused. // // Implements: fyne.Focusable func (l *List) TypedKey(event *fyne.KeyEvent) { switch event.Name { + case fyne.KeyHome: + l.ScrollToTop() + case fyne.KeyPageUp: + l.ScrollUpOnePage() + case fyne.KeyPageDown: + l.ScrollDownOnePage() + case fyne.KeyEnd: + l.ScrollToBottom() case fyne.KeySpace: l.Select(l.currentFocus) case fyne.KeyDown: diff --git a/widget/list_test.go b/widget/list_test.go index 9f109f6550..f3fb10c782 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -652,3 +652,23 @@ func TestList_RefreshUpdatesAllItems(t *testing.T) { list.Refresh() assert.Equal(t, "0.0.", printOut) } + +func TestList_ScrollDownOnePage(t *testing.T) { + list := createList(1100) + + offset := 1000 + list.ScrollDownOnePage() + assert.Equal(t, offset, int(list.offsetY)) + assert.Equal(t, offset, int(list.scroller.Offset.Y)) +} + +func TestList_ScrollUpOnePage(t *testing.T) { + list := createList(1100) + list.ScrollDownOnePage() + list.ScrollDownOnePage() + + offset := 1000 + list.ScrollUpOnePage() + assert.Equal(t, offset, int(list.offsetY)) + assert.Equal(t, offset, int(list.scroller.Offset.Y)) +} diff --git a/widget/table.go b/widget/table.go index 41b8c15e99..1eb148f182 100644 --- a/widget/table.go +++ b/widget/table.go @@ -324,6 +324,17 @@ func (t *Table) TouchCancel(*mobile.TouchEvent) { // Implements: fyne.Focusable func (t *Table) TypedKey(event *fyne.KeyEvent) { switch event.Name { + case fyne.KeyHome: + t.ScrollToTop() + t.Refresh() + case fyne.KeyPageUp: + t.ScrollUpOnePage() + t.Refresh() + case fyne.KeyPageDown: + t.ScrollDownOnePage() + case fyne.KeyEnd: + t.ScrollToBottom() + t.Refresh() case fyne.KeySpace: t.Select(t.currentFocus) case fyne.KeyDown: @@ -521,6 +532,33 @@ func (t *Table) ScrollToTop() { t.finishScroll() } +// scrollByOnePage scrolls down or up by table height +func (t *Table) scrollByOnePage(down bool) { + if t.Length == nil || t.content == nil { + return + } + + if down { + t.content.Offset.Y += t.size.Height + } else { + t.content.Offset.Y -= t.size.Height + } + t.offset.Y = t.content.Offset.Y + + t.content.Refresh() + t.finishScroll() +} + +// ScrollUpOnePage scrolls up one page (table height) +func (t *Table) ScrollUpOnePage() { + t.scrollByOnePage(false) +} + +// ScrollDownOnePage scrolls down one page (table height) +func (t *Table) ScrollDownOnePage() { + t.scrollByOnePage(true) +} + // ScrollToTrailing scrolls horizontally to the trailing edge of the table // // Since: 2.1 diff --git a/widget/table_test.go b/widget/table_test.go index 8ed6eb5cae..27ac6a3ebe 100644 --- a/widget/table_test.go +++ b/widget/table_test.go @@ -515,6 +515,38 @@ func TestTable_ScrollToBottom(t *testing.T) { assert.Equal(t, want, table.content.Offset) } +func TestTable_ScrollDownOnePage(t *testing.T) { + test.NewApp() + defer test.NewApp() + test.ApplyTheme(t, test.NewTheme()) + + const ( + maxRows int = 20 + maxCols int = 5 + width float32 = 50 + height float32 = 50 + ) + + templ := canvas.NewRectangle(color.Gray16{}) + templ.SetMinSize(fyne.NewSize(width, height)) + + table := NewTable( + func() (int, int) { return maxRows, maxCols }, + func() fyne.CanvasObject { return templ }, + func(TableCellID, fyne.CanvasObject) {}) + + w := test.NewWindow(table) + defer w.Close() + + w.Resize(fyne.NewSize(200, 200)) + + want := fyne.Position{X: 0, Y: 180} + table.ScrollDownOnePage() + + assert.Equal(t, want, table.offset) + assert.Equal(t, want, table.content.Offset) +} + func TestTable_ScrollToLeading(t *testing.T) { test.NewApp() defer test.NewApp() @@ -573,6 +605,40 @@ func TestTable_ScrollToTop(t *testing.T) { assert.Equal(t, want, table.content.Offset) } +func TestTable_ScrollUpOnePage(t *testing.T) { + test.NewApp() + defer test.NewApp() + test.ApplyTheme(t, test.NewTheme()) + + const ( + maxRows int = 20 + maxCols int = 5 + width float32 = 50 + height float32 = 50 + ) + + templ := canvas.NewRectangle(color.Gray16{}) + templ.SetMinSize(fyne.NewSize(width, height)) + + table := NewTable( + func() (int, int) { return maxRows, maxCols }, + func() fyne.CanvasObject { return templ }, + func(TableCellID, fyne.CanvasObject) {}) + + w := test.NewWindow(table) + defer w.Close() + + w.Resize(fyne.NewSize(200, 200)) + table.ScrollDownOnePage() + table.ScrollDownOnePage() + + want := fyne.Position{X: 0, Y: 180} + table.ScrollUpOnePage() + + assert.Equal(t, want, table.offset) + assert.Equal(t, want, table.content.Offset) +} + func TestTable_ScrollToTrailing(t *testing.T) { test.NewApp() defer test.NewApp() diff --git a/widget/tree.go b/widget/tree.go index bd71c2efb7..b3f4bdae08 100644 --- a/widget/tree.go +++ b/widget/tree.go @@ -300,6 +300,39 @@ func (t *Tree) ScrollToTop() { t.Refresh() } +// scrollByOnePage scrolls down or up by tree height +func (t *Tree) scrollByOnePage(down bool) { + if t.scroller == nil { + return + } + + if down { + t.scroller.Offset.Y += t.size.Height + y, size := t.findBottom() + max := y + size.Height - t.scroller.Size().Height + if t.scroller.Offset.Y > max { + t.scroller.Offset.Y = max + } + } else { + t.scroller.Offset.Y -= t.size.Height + if t.scroller.Offset.Y < 0 { + t.scroller.Offset.Y = 0 + } + } + t.offsetUpdated(t.scroller.Offset) + t.Refresh() +} + +// ScrollUpOnePage scrolls down or up by tree height +func (t *Tree) ScrollUpOnePage() { + t.scrollByOnePage(false) +} + +// ScrollDownOnePage scrolls down or up by tree height +func (t *Tree) ScrollDownOnePage() { + t.scrollByOnePage(true) +} + // Select marks the specified node to be selected. func (t *Tree) Select(uid TreeNodeID) { if len(t.selected) > 0 { @@ -331,6 +364,14 @@ func (t *Tree) ToggleBranch(uid string) { // Implements: fyne.Focusable func (t *Tree) TypedKey(event *fyne.KeyEvent) { switch event.Name { + case fyne.KeyHome: + t.ScrollToTop() + case fyne.KeyPageUp: + t.ScrollUpOnePage() + case fyne.KeyPageDown: + t.ScrollDownOnePage() + case fyne.KeyEnd: + t.ScrollToBottom() case fyne.KeySpace: t.Select(t.currentFocus) case fyne.KeyDown: diff --git a/widget/tree_internal_test.go b/widget/tree_internal_test.go index 2107b4c982..37dcf52ece 100644 --- a/widget/tree_internal_test.go +++ b/widget/tree_internal_test.go @@ -628,6 +628,42 @@ func TestTree_ScrollToBottom(t *testing.T) { assert.Equal(t, want, tree.scroller.Offset.Y) } +func TestTree_ScrollDownOnePage(t *testing.T) { + test.NewApp() + defer test.NewApp() + test.ApplyTheme(t, test.NewTheme()) + + data := make(map[string][]string) + addTreePath(data, "A") + addTreePath(data, "B", "C") + addTreePath(data, "D", "E", "F") + tree := NewTreeWithStrings(data) + tree.OpenBranch("B") + tree.OpenBranch("D") + tree.OpenBranch("E") + + w := test.NewWindow(tree) + defer w.Close() + + var ( + min = getLeaf(t, tree, "A").MinSize() + sep = theme.Padding() + ) + + // Resize tall enough to display two nodes and the separater between them + treeHeight := 2*(min.Height) + sep + w.Resize(fyne.Size{ + Width: 400, + Height: treeHeight + 2*theme.Padding(), + }) + + tree.ScrollDownOnePage() + + want := treeHeight + assert.Equal(t, want, tree.offset.Y) + assert.Equal(t, want, tree.scroller.Offset.Y) +} + func TestTree_ScrollToSelection(t *testing.T) { data := make(map[string][]string) addTreePath(data, "A") @@ -685,6 +721,44 @@ func TestTree_ScrollToTop(t *testing.T) { assert.Equal(t, float32(0), tree.scroller.Offset.Y) } +func TestTree_ScrollUpOnePage(t *testing.T) { + test.NewApp() + defer test.NewApp() + test.ApplyTheme(t, test.NewTheme()) + + data := make(map[string][]string) + addTreePath(data, "A") + addTreePath(data, "B", "C") + addTreePath(data, "D", "E", "F") + tree := NewTreeWithStrings(data) + tree.OpenBranch("B") + tree.OpenBranch("D") + tree.OpenBranch("E") + + w := test.NewWindow(tree) + defer w.Close() + + var ( + min = getLeaf(t, tree, "A").MinSize() + sep = theme.Padding() + ) + + // Resize tall enough to display two nodes and the separater between them + treeHeight := 2*(min.Height) + sep + w.Resize(fyne.Size{ + Width: 400, + Height: treeHeight + 2*theme.Padding(), + }) + + tree.ScrollDownOnePage() + tree.ScrollDownOnePage() + tree.ScrollUpOnePage() + + want := treeHeight + assert.Equal(t, want, tree.offset.Y) + assert.Equal(t, want, tree.scroller.Offset.Y) +} + func TestTree_Tap(t *testing.T) { t.Run("Branch", func(t *testing.T) { data := make(map[string][]string) From 8457816028bdf9d5e2180491b4da1110a044f054 Mon Sep 17 00:00:00 2001 From: m-rei Date: Thu, 7 Mar 2024 20:25:58 +0100 Subject: [PATCH 5/6] Refresh fixed --- widget/table.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/widget/table.go b/widget/table.go index 1eb148f182..c13d822833 100644 --- a/widget/table.go +++ b/widget/table.go @@ -326,15 +326,12 @@ func (t *Table) TypedKey(event *fyne.KeyEvent) { switch event.Name { case fyne.KeyHome: t.ScrollToTop() - t.Refresh() case fyne.KeyPageUp: t.ScrollUpOnePage() - t.Refresh() case fyne.KeyPageDown: t.ScrollDownOnePage() case fyne.KeyEnd: t.ScrollToBottom() - t.Refresh() case fyne.KeySpace: t.Select(t.currentFocus) case fyne.KeyDown: @@ -503,6 +500,7 @@ func (t *Table) ScrollToBottom() { t.content.Offset.Y = y t.offset.Y = y + t.content.Refresh() t.finishScroll() } @@ -529,6 +527,7 @@ func (t *Table) ScrollToTop() { t.content.Offset.Y = 0 t.offset.Y = 0 + t.content.Refresh() t.finishScroll() } From 9698952aab69a5dc8f9f8243345471d10db0e225 Mon Sep 17 00:00:00 2001 From: m-rei Date: Thu, 7 Mar 2024 20:46:18 +0100 Subject: [PATCH 6/6] Height referencing changed, adjusted it --- widget/list.go | 5 +++-- widget/table.go | 5 +++-- widget/tree.go | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/widget/list.go b/widget/list.go index 853a51f71a..1b23fa4054 100644 --- a/widget/list.go +++ b/widget/list.go @@ -263,10 +263,11 @@ func (l *List) scrollByOnePage(down bool) { return } + height := l.size.Load().Height if down { - l.scroller.Offset.Y += l.size.Height + l.scroller.Offset.Y += height } else { - l.scroller.Offset.Y -= l.size.Height + l.scroller.Offset.Y -= height } l.offsetUpdated(l.scroller.Offset) l.Refresh() diff --git a/widget/table.go b/widget/table.go index 9a5e76dccd..f451db2db8 100644 --- a/widget/table.go +++ b/widget/table.go @@ -557,10 +557,11 @@ func (t *Table) scrollByOnePage(down bool) { return } + height := t.size.Load().Height if down { - t.content.Offset.Y += t.size.Height + t.content.Offset.Y += height } else { - t.content.Offset.Y -= t.size.Height + t.content.Offset.Y -= height } t.offset.Y = t.content.Offset.Y diff --git a/widget/tree.go b/widget/tree.go index 082688cef4..44b55e006a 100644 --- a/widget/tree.go +++ b/widget/tree.go @@ -300,15 +300,16 @@ func (t *Tree) scrollByOnePage(down bool) { return } + height := t.size.Load().Height if down { - t.scroller.Offset.Y += t.size.Height + t.scroller.Offset.Y += height y, size := t.findBottom() max := y + size.Height - t.scroller.Size().Height if t.scroller.Offset.Y > max { t.scroller.Offset.Y = max } } else { - t.scroller.Offset.Y -= t.size.Height + t.scroller.Offset.Y -= height if t.scroller.Offset.Y < 0 { t.scroller.Offset.Y = 0 }