From 68e49c60cd59723ac76c901cb21f15844ac7ef49 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 20 Dec 2019 18:19:22 +0000 Subject: [PATCH 01/16] Force tab container to layout children when they are shown Fixes #578 --- widget/tabcontainer.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/widget/tabcontainer.go b/widget/tabcontainer.go index a7a55f7f31..89ed9153fb 100644 --- a/widget/tabcontainer.go +++ b/widget/tabcontainer.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/canvas" "fyne.io/fyne/driver/desktop" "fyne.io/fyne/internal" + "fyne.io/fyne/internal/cache" "fyne.io/fyne/layout" "fyne.io/fyne/theme" ) @@ -88,6 +89,8 @@ func (t *TabContainer) SelectTabIndex(index int) { } } + r := cache.Renderer(t).(*tabContainerRenderer) + r.Layout(t.size) t.refresh(t) } @@ -166,7 +169,7 @@ func (t *TabContainer) buildTabBar(buttons []fyne.CanvasObject) *fyne.Container // SetTabLocation sets the location of the tab bar func (t *TabContainer) SetTabLocation(l TabLocation) { t.tabLocation = l - r := Renderer(t).(*tabContainerRenderer) + r := cache.Renderer(t).(*tabContainerRenderer) buttons := r.tabBar.Objects if fyne.CurrentDevice().IsMobile() || l == TabLocationLeading || l == TabLocationTrailing { for _, b := range buttons { From b27ad4be814246e30362483d9f2ee774851f15fc Mon Sep 17 00:00:00 2001 From: Nort Date: Thu, 19 Dec 2019 18:32:40 +0100 Subject: [PATCH 02/16] Added some dynamics to tabcontainer --- widget/tabcontainer.go | 19 +++++++++++++++++++ widget/tabcontainer_test.go | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/widget/tabcontainer.go b/widget/tabcontainer.go index 89ed9153fb..147e60255d 100644 --- a/widget/tabcontainer.go +++ b/widget/tabcontainer.go @@ -166,6 +166,25 @@ func (t *TabContainer) buildTabBar(buttons []fyne.CanvasObject) *fyne.Container return tabBar } + +// Append adds a new CanvasObject to the end of the group +func (t *TabContainer) Append(item *TabItem) { + r := Renderer(t).(*tabContainerRenderer) + t.Items = append(t.Items, item) + r.tabBar.Objects = append(r.tabBar.Objects, t.makeButton(item)) + + t.CreateRenderer().Refresh() +} + +// Remove tab by index +func (t *TabContainer) Remove(index int) { + r := Renderer(t).(*tabContainerRenderer) + t.Items = append(t.Items[:index], t.Items[index+1:]...) + r.tabBar.Objects = append(r.tabBar.Objects[:index], r.tabBar.Objects[index+1:]...) + + t.CreateRenderer().Refresh() +} + // SetTabLocation sets the location of the tab bar func (t *TabContainer) SetTabLocation(l TabLocation) { t.tabLocation = l diff --git a/widget/tabcontainer_test.go b/widget/tabcontainer_test.go index a82af9167d..3488543239 100644 --- a/widget/tabcontainer_test.go +++ b/widget/tabcontainer_test.go @@ -366,6 +366,24 @@ func TestTabContainerRenderer_Layout(t *testing.T) { } } +func TestTabContainer_DynamicTabs(t *testing.T) { + item := NewTabItem("Text1", canvas.NewCircle(theme.BackgroundColor())) + tabs := NewTabContainer(item) + r := Renderer(tabs).(*tabContainerRenderer) + + appendedItem := NewTabItem("Text2", canvas.NewCircle(theme.BackgroundColor())) + + tabs.Append(appendedItem) + assert.Equal(t, len(tabs.Items), 2) + assert.Equal(t, len(r.tabBar.Objects), 2) + assert.Equal(t, tabs.Items[1].Text, appendedItem.Text) + + tabs.Remove(1) + assert.Equal(t, len(tabs.Items), 1) + assert.Equal(t, len(r.tabBar.Objects), 1) + assert.Equal(t, tabs.Items[0].Text, item.Text) +} + func Test_tabButton_Hovered(t *testing.T) { b := &tabButton{} r := Renderer(b) @@ -397,3 +415,4 @@ func TestTabButtonRenderer_ApplyTheme(t *testing.T) { assert.NotEqual(t, textSize, customTextSize) } + From b8310d540df19adf544638b5559ad3a841d71845 Mon Sep 17 00:00:00 2001 From: Nort Date: Fri, 20 Dec 2019 20:20:32 +0100 Subject: [PATCH 03/16] Yeah, this is fix for #444, updated the code to fit requirements, sorry --- widget/tabcontainer.go | 45 ++++++++++++++++--------------------- widget/tabcontainer_test.go | 9 ++++++-- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/widget/tabcontainer.go b/widget/tabcontainer.go index 147e60255d..52b16dd8f5 100644 --- a/widget/tabcontainer.go +++ b/widget/tabcontainer.go @@ -103,26 +103,6 @@ func (t *TabContainer) makeButton(item *TabItem) *tabButton { return &tabButton{Text: item.Text, Icon: item.Icon, OnTap: func() { t.SelectTab(item) }} } -/* -// Prepend inserts a new CanvasObject at the top of the group -func (t *TabContainer) Prepend(object fyne.CanvasObject) { - t.Items = append(t.Items, item) - t.tabBar.Append(t.makeButton(item)) - t.children = append(t.children, item.Content) - - t.CreateRenderer().Refresh()} -} - -// Append adds a new CanvasObject to the end of the group -func (t *TabContainer) Append(item TabItem) { - t.Items = append(t.Items, item) -// t.tabBar.Append(t.makeButton(item)) -// t.children = append(t.children, item.Content) - - t.CreateRenderer().Refresh() -} -*/ - // CreateRenderer is a private method to Fyne which links this widget to its renderer func (t *TabContainer) CreateRenderer() fyne.WidgetRenderer { t.ExtendBaseWidget(t) @@ -166,23 +146,36 @@ func (t *TabContainer) buildTabBar(buttons []fyne.CanvasObject) *fyne.Container return tabBar } - // Append adds a new CanvasObject to the end of the group func (t *TabContainer) Append(item *TabItem) { - r := Renderer(t).(*tabContainerRenderer) + r := cache.Renderer(t).(*tabContainerRenderer) t.Items = append(t.Items, item) r.tabBar.Objects = append(r.tabBar.Objects, t.makeButton(item)) - t.CreateRenderer().Refresh() + t.Refresh() +} + +// Remove tab by value +func (t *TabContainer) Remove(item *TabItem) { + r := cache.Renderer(t).(*tabContainerRenderer) + + for index, existingItem := range t.Items { + if existingItem == item { + t.Items = append(t.Items[:index], t.Items[index+1:]...) + r.tabBar.Objects = append(r.tabBar.Objects[:index], r.tabBar.Objects[index+1:]...) + } + } + + t.Refresh() } // Remove tab by index -func (t *TabContainer) Remove(index int) { - r := Renderer(t).(*tabContainerRenderer) +func (t *TabContainer) RemoveIndex(index int) { + r := cache.Renderer(t).(*tabContainerRenderer) t.Items = append(t.Items[:index], t.Items[index+1:]...) r.tabBar.Objects = append(r.tabBar.Objects[:index], r.tabBar.Objects[index+1:]...) - t.CreateRenderer().Refresh() + t.Refresh() } // SetTabLocation sets the location of the tab bar diff --git a/widget/tabcontainer_test.go b/widget/tabcontainer_test.go index 3488543239..881d93b0e6 100644 --- a/widget/tabcontainer_test.go +++ b/widget/tabcontainer_test.go @@ -378,10 +378,16 @@ func TestTabContainer_DynamicTabs(t *testing.T) { assert.Equal(t, len(r.tabBar.Objects), 2) assert.Equal(t, tabs.Items[1].Text, appendedItem.Text) - tabs.Remove(1) + tabs.RemoveIndex(1) assert.Equal(t, len(tabs.Items), 1) assert.Equal(t, len(r.tabBar.Objects), 1) assert.Equal(t, tabs.Items[0].Text, item.Text) + + tabs.Append(appendedItem) + tabs.Remove(tabs.Items[0]) + assert.Equal(t, len(tabs.Items), 1) + assert.Equal(t, len(r.tabBar.Objects), 1) + assert.Equal(t, tabs.Items[0].Text, appendedItem.Text) } func Test_tabButton_Hovered(t *testing.T) { @@ -415,4 +421,3 @@ func TestTabButtonRenderer_ApplyTheme(t *testing.T) { assert.NotEqual(t, textSize, customTextSize) } - From 88b6dd44b0c79afe1a113abc0596533f1be9c4b8 Mon Sep 17 00:00:00 2001 From: Nort Date: Fri, 20 Dec 2019 20:26:49 +0100 Subject: [PATCH 04/16] Fixed linting errors --- widget/tabcontainer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/tabcontainer.go b/widget/tabcontainer.go index 52b16dd8f5..01b601a146 100644 --- a/widget/tabcontainer.go +++ b/widget/tabcontainer.go @@ -169,7 +169,7 @@ func (t *TabContainer) Remove(item *TabItem) { t.Refresh() } -// Remove tab by index +// RemoveIndex removes tab by index func (t *TabContainer) RemoveIndex(index int) { r := cache.Renderer(t).(*tabContainerRenderer) t.Items = append(t.Items[:index], t.Items[index+1:]...) From eb2497ffa7799c9eb26b7ef0273ceee59470ff58 Mon Sep 17 00:00:00 2001 From: Nort Date: Fri, 20 Dec 2019 23:34:21 +0100 Subject: [PATCH 05/16] Code fixes for DRY and copy paste amends:) --- widget/tabcontainer.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/widget/tabcontainer.go b/widget/tabcontainer.go index 01b601a146..0ea198164e 100644 --- a/widget/tabcontainer.go +++ b/widget/tabcontainer.go @@ -146,7 +146,7 @@ func (t *TabContainer) buildTabBar(buttons []fyne.CanvasObject) *fyne.Container return tabBar } -// Append adds a new CanvasObject to the end of the group +// Append adds a new TabItem to the rightmost side of the tab panel func (t *TabContainer) Append(item *TabItem) { r := cache.Renderer(t).(*tabContainerRenderer) t.Items = append(t.Items, item) @@ -157,16 +157,12 @@ func (t *TabContainer) Append(item *TabItem) { // Remove tab by value func (t *TabContainer) Remove(item *TabItem) { - r := cache.Renderer(t).(*tabContainerRenderer) - for index, existingItem := range t.Items { if existingItem == item { - t.Items = append(t.Items[:index], t.Items[index+1:]...) - r.tabBar.Objects = append(r.tabBar.Objects[:index], r.tabBar.Objects[index+1:]...) + t.RemoveIndex(index) + break } } - - t.Refresh() } // RemoveIndex removes tab by index From 3834dc02d636fa375e29b9e0fbea528a0e08b6a4 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 21 Dec 2019 22:16:49 +0000 Subject: [PATCH 06/16] Update Changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index acfdf3d102..5f584dd52d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ 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). +## 1.2.1 - Under development + +### Added + +* Add TouchDown, TouchUp and TouchCancel API in driver/mobile for device specific events +* Add support for adding and removing tabs from a tab container (#444) + +### Fixed + +* Issues when settings changes may not be monitored (#576) +* Layout of hidden tab container contents on mobile (#578) + + ## 1.2 - 12 December 2019 ### Added From 79d70687d4a0fb04104e8e16219ec43484c43085 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 09:52:17 +0000 Subject: [PATCH 07/16] Actually quit mobile apps, but warn about usage of this. Fixes #580 --- CHANGELOG.md | 1 + app.go | 2 ++ internal/driver/gomobile/driver.go | 12 ++++++------ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f584dd52d..2b460d0ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Issues when settings changes may not be monitored (#576) * Layout of hidden tab container contents on mobile (#578) +* Mobile apps would not quit when Quit() was called (#580) ## 1.2 - 12 December 2019 diff --git a/app.go b/app.go index ac73c28812..407f5924e6 100644 --- a/app.go +++ b/app.go @@ -31,6 +31,8 @@ type App interface { // Calling Quit on the application will cause the application to exit // cleanly, closing all open windows. + // This should be used with caution, many platforms discourage exiting an application + // from within the code and some mobile systems do not allow it. Quit() // Driver returns the driver that is rendering this application. diff --git a/internal/driver/gomobile/driver.go b/internal/driver/gomobile/driver.go index 62c7b348f5..58b6d4dd13 100644 --- a/internal/driver/gomobile/driver.go +++ b/internal/driver/gomobile/driver.go @@ -26,6 +26,7 @@ const tapSecondaryDelay = 300 * time.Millisecond type mobileDriver struct { app app.App + quit bool glctx gl.Context windows []fyne.Window @@ -70,7 +71,7 @@ func (d *mobileDriver) CanvasForObject(fyne.CanvasObject) fyne.Canvas { return nil } - // TODO figure out how we handle multiple windows... + // TODO don't just assume it refers to the topmost window return d.currentWindow().Canvas() } @@ -94,14 +95,13 @@ func (d *mobileDriver) Quit() { return } - // TODO? often mobile apps should not allow this... - d.app.Send(lifecycle.Event{From: lifecycle.StageAlive, To: lifecycle.StageDead, DrawContext: nil}) + // TODO should this be disabled for iOS? + d.quit = true } func (d *mobileDriver) Run() { app.Main(func(a app.App) { d.app = a - quit := false var currentSize size.Event for e := range a.Events() { @@ -123,7 +123,7 @@ func (d *mobileDriver) Run() { d.glctx = nil } if e.Crosses(lifecycle.StageAlive) == lifecycle.CrossOff { - quit = true + d.quit = true } case size.Event: currentSize = e @@ -157,7 +157,7 @@ func (d *mobileDriver) Run() { } } - if quit { + if d.quit { break } } From 92bbe56d9de0db4ddd3db895f03bcff8e610e71d Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 14:41:36 +0000 Subject: [PATCH 08/16] Don't push mobile devices too hard, was causing iOS renderer to freeze Fixes #584 --- internal/driver/gomobile/driver.go | 22 +++++++++++----------- internal/painter/gl/gl_gomobile.go | 4 ++++ internal/painter/gl/gl_gomobile_ios.go | 12 ------------ internal/painter/gl/gl_gomobile_other.go | 7 ------- 4 files changed, 15 insertions(+), 30 deletions(-) delete mode 100644 internal/painter/gl/gl_gomobile_ios.go delete mode 100644 internal/painter/gl/gl_gomobile_other.go diff --git a/internal/driver/gomobile/driver.go b/internal/driver/gomobile/driver.go index 58b6d4dd13..d7db3816ff 100644 --- a/internal/driver/gomobile/driver.go +++ b/internal/driver/gomobile/driver.go @@ -136,9 +136,12 @@ func (d *mobileDriver) Run() { canvas.painter.Init() // we cannot init until the context is set above } - d.freeDirtyTextures(canvas) - d.paintWindow(current, currentSize) - a.Publish() + if d.freeDirtyTextures(canvas) { + d.paintWindow(current, currentSize) + a.Publish() + } + + time.Sleep(time.Millisecond * 10) a.Send(paint.Event{}) case touch.Event: switch e.Type { @@ -165,9 +168,6 @@ func (d *mobileDriver) Run() { } func (d *mobileDriver) onStart() { - for _, win := range d.AllWindows() { - win.Canvas().(*mobileCanvas).painter.Init() // we cannot init until the context is set above - } } func (d *mobileDriver) onStop() { @@ -422,17 +422,19 @@ func (d *mobileDriver) typeUpCanvas(canvas *mobileCanvas, r rune, code key.Code) } -func (d *mobileDriver) freeDirtyTextures(canvas *mobileCanvas) { +func (d *mobileDriver) freeDirtyTextures(canvas *mobileCanvas) bool { + freed := false for { select { case object := <-canvas.refreshQueue: + freed = true freeWalked := func(obj fyne.CanvasObject, _ fyne.Position, _ fyne.Position, _ fyne.Size) bool { canvas.painter.Free(obj) return false } driver.WalkCompleteObjectTree(object, freeWalked, nil) default: - return + return freed } } } @@ -448,7 +450,5 @@ func (d *mobileDriver) Device() fyne.Device { // NewGoMobileDriver sets up a new Driver instance implemented using the Go // Mobile extension and OpenGL bindings. func NewGoMobileDriver() fyne.Driver { - driver := new(mobileDriver) - - return driver + return new(mobileDriver) } diff --git a/internal/painter/gl/gl_gomobile.go b/internal/painter/gl/gl_gomobile.go index 5aadcbbed2..a0be48ac14 100644 --- a/internal/painter/gl/gl_gomobile.go +++ b/internal/painter/gl/gl_gomobile.go @@ -179,6 +179,10 @@ func (p *glPainter) glCreateBuffer(points []float32) Buffer { return Buffer(sharedBuffer) } +func (p *glPainter) glFreeBuffer(_ Buffer) { + // we don't free a shared buffer! +} + func (p *glPainter) glDrawTexture(texture Texture, alpha float32) { ctx := p.glctx() ctx.Enable(gl.BLEND) diff --git a/internal/painter/gl/gl_gomobile_ios.go b/internal/painter/gl/gl_gomobile_ios.go deleted file mode 100644 index 8c42e88a0c..0000000000 --- a/internal/painter/gl/gl_gomobile_ios.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build ios - -package gl - -import "golang.org/x/mobile/gl" - -func (p *glPainter) glFreeBuffer(vbo Buffer) { - ctx := p.glctx() - - ctx.BindBuffer(gl.ARRAY_BUFFER, gl.Buffer(vbo)) - ctx.DeleteBuffer(gl.Buffer(vbo)) -} diff --git a/internal/painter/gl/gl_gomobile_other.go b/internal/painter/gl/gl_gomobile_other.go deleted file mode 100644 index bf44738359..0000000000 --- a/internal/painter/gl/gl_gomobile_other.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build android mobile - -package gl - -func (p *glPainter) glFreeBuffer(_ Buffer) { - // we don't free a shared buffer! -} From ff28a5d1e0251caf2daf7e42b19defc82a4482c0 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 14:42:01 +0000 Subject: [PATCH 09/16] Move all scroll demo to a single screen --- cmd/fyne_demo/screens/widget.go | 12 +++++------- widget/scroller.go | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/cmd/fyne_demo/screens/widget.go b/cmd/fyne_demo/screens/widget.go index ddc47f730b..04c098ac36 100644 --- a/cmd/fyne_demo/screens/widget.go +++ b/cmd/fyne_demo/screens/widget.go @@ -114,13 +114,12 @@ func makeScrollTab() fyne.CanvasObject { })) } - scroll := widget.NewScrollContainer(list) - scroll.Resize(fyne.NewSize(200, 300)) + horiz := widget.NewScrollContainer(list) + vert := widget.NewScrollContainer(list2) - scroll2 := widget.NewScrollContainer(list2) - scroll2.Resize(fyne.NewSize(200, 100)) - - return fyne.NewContainerWithLayout(layout.NewGridLayout(1), scroll, scroll2) + scrolls := fyne.NewContainerWithLayout(layout.NewBorderLayout(horiz, nil, nil, nil), + horiz, vert) + return fyne.NewContainerWithLayout(layout.NewAdaptiveGridLayout(2), scrolls, makeScrollBothTab()) } func makeScrollBothTab() fyne.CanvasObject { @@ -151,7 +150,6 @@ func WidgetScreen() fyne.CanvasObject { widget.NewTabItem("Progress", makeProgressTab()), widget.NewTabItem("Form", makeFormTab()), widget.NewTabItem("Scroll", makeScrollTab()), - widget.NewTabItem("Full Scroll", makeScrollBothTab()), ), ) } diff --git a/widget/scroller.go b/widget/scroller.go index 679d3fd352..54b3970985 100644 --- a/widget/scroller.go +++ b/widget/scroller.go @@ -265,7 +265,7 @@ func (r *scrollContainerRenderer) Layout(size fyne.Size) { } func (r *scrollContainerRenderer) MinSize() fyne.Size { - return fyne.NewSize(25, 25) // TODO consider the smallest useful scroll view? + return fyne.NewSize(32, 32) // TODO consider the smallest useful scroll view? } func (r *scrollContainerRenderer) Objects() []fyne.CanvasObject { From 7300663b891c418221147c8e704f6c0cedc3e529 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 14:43:40 +0000 Subject: [PATCH 10/16] Update blend state on start, it does not vary --- internal/painter/gl/gl_core.go | 2 +- internal/painter/gl/gl_es.go | 2 +- internal/painter/gl/gl_gomobile.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/painter/gl/gl_core.go b/internal/painter/gl/gl_core.go index 2f34b693e6..a3b13c9229 100644 --- a/internal/painter/gl/gl_core.go +++ b/internal/painter/gl/gl_core.go @@ -87,6 +87,7 @@ func glInit() { } gl.Disable(gl.DEPTH_TEST) + gl.Enable(gl.BLEND) } func compileShader(source string, shaderType uint32) (uint32, error) { @@ -198,7 +199,6 @@ func (p *glPainter) glFreeBuffer(vbo Buffer) { } func (p *glPainter) glDrawTexture(texture Texture, alpha float32) { - gl.Enable(gl.BLEND) // here we have to choose between blending the image alpha or fading it... // TODO find a way to support both if alpha != 1.0 { diff --git a/internal/painter/gl/gl_es.go b/internal/painter/gl/gl_es.go index 74ceaa4073..32f94f121a 100644 --- a/internal/painter/gl/gl_es.go +++ b/internal/painter/gl/gl_es.go @@ -88,6 +88,7 @@ func glInit() { } gl.Disable(gl.DEPTH_TEST) + gl.Enable(gl.BLEND) } func compileShader(source string, shaderType uint32) (uint32, error) { @@ -199,7 +200,6 @@ func (p *glPainter) glFreeBuffer(vbo Buffer) { } func (p *glPainter) glDrawTexture(texture Texture, alpha float32) { - gl.Enable(gl.BLEND) // here we have to choose between blending the image alpha or fading it... // TODO find a way to support both if alpha != 1.0 { diff --git a/internal/painter/gl/gl_gomobile.go b/internal/painter/gl/gl_gomobile.go index a0be48ac14..bf7d730e8c 100644 --- a/internal/painter/gl/gl_gomobile.go +++ b/internal/painter/gl/gl_gomobile.go @@ -126,6 +126,7 @@ const ( func (p *glPainter) Init() { p.glctx().Disable(gl.DEPTH_TEST) + p.glctx().Enable(gl.BLEND) sharedBuffer = p.glctx().CreateBuffer() vertexShader, err := p.compileShader(vertexShaderSource, gl.VERTEX_SHADER) @@ -185,7 +186,6 @@ func (p *glPainter) glFreeBuffer(_ Buffer) { func (p *glPainter) glDrawTexture(texture Texture, alpha float32) { ctx := p.glctx() - ctx.Enable(gl.BLEND) // here we have to choose between blending the image alpha or fading it... // TODO find a way to support both From 686287462b464801a4681c3fb84d7a3a1dca0d43 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 14:44:02 +0000 Subject: [PATCH 11/16] Stop using deprecated calls --- internal/painter/gl/gl_common.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/painter/gl/gl_common.go b/internal/painter/gl/gl_common.go index 6d4bba2199..dd3cff8ead 100644 --- a/internal/painter/gl/gl_common.go +++ b/internal/painter/gl/gl_common.go @@ -5,10 +5,9 @@ import ( "fyne.io/fyne" "fyne.io/fyne/canvas" + "fyne.io/fyne/internal/cache" "fyne.io/fyne/internal/painter" "fyne.io/fyne/theme" - "fyne.io/fyne/widget" - "github.com/goki/freetype" "github.com/goki/freetype/truetype" "github.com/srwiley/rasterx" @@ -84,7 +83,7 @@ func (p *glPainter) newGlLineTexture(obj fyne.CanvasObject) Texture { func (p *glPainter) newGlRectTexture(rect fyne.CanvasObject) Texture { col := theme.BackgroundColor() if wid, ok := rect.(fyne.Widget); ok { - widCol := widget.Renderer(wid).BackgroundColor() + widCol := cache.Renderer(wid).BackgroundColor() if widCol != nil { col = widCol } From 7af37bc588794f88540af5fc97325bd0f641f1a0 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 15:05:43 +0000 Subject: [PATCH 12/16] Update shadows on theme change Fixes #589 --- widget/button.go | 8 ++++++-- widget/scroller.go | 9 +++++++-- widget/shadow.go | 41 ++++++++++++++++++++++++++++++++++++++++- widget/shadow_test.go | 18 ++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/widget/button.go b/widget/button.go index 57ceea366a..6ab986d0f7 100644 --- a/widget/button.go +++ b/widget/button.go @@ -13,7 +13,7 @@ import ( type buttonRenderer struct { icon *canvas.Image label *canvas.Text - shadow fyne.CanvasObject + shadow *shadow objects []fyne.CanvasObject button *Button @@ -125,6 +125,10 @@ func (b *buttonRenderer) Refresh() { b.icon.Hide() } + if b.shadow != nil { + b.shadow.depth = theme.Padding() / 2 + } + b.Layout(b.button.Size()) canvas.Refresh(b.button) } @@ -206,7 +210,7 @@ func (b *Button) CreateRenderer() fyne.WidgetRenderer { objects := []fyne.CanvasObject{ text, } - var shadow fyne.CanvasObject + var shadow *shadow if !b.HideShadow { shadow = newShadow(shadowAround, theme.Padding()/2) objects = append(objects, shadow) diff --git a/widget/scroller.go b/widget/scroller.go index 54b3970985..685ce67b75 100644 --- a/widget/scroller.go +++ b/widget/scroller.go @@ -229,8 +229,8 @@ type scrollContainerRenderer struct { scroll *ScrollContainer vertArea *scrollBarArea horizArea *scrollBarArea - leftShadow, rightShadow fyne.CanvasObject - topShadow, bottomShadow fyne.CanvasObject + leftShadow, rightShadow *shadow + topShadow, bottomShadow *shadow objects []fyne.CanvasObject } @@ -273,6 +273,11 @@ func (r *scrollContainerRenderer) Objects() []fyne.CanvasObject { } func (r *scrollContainerRenderer) Refresh() { + r.leftShadow.depth = theme.Padding() * 2 + r.rightShadow.depth = theme.Padding() * 2 + r.topShadow.depth = theme.Padding() * 2 + r.bottomShadow.depth = theme.Padding() * 2 + r.Layout(r.scroll.Size()) } diff --git a/widget/shadow.go b/widget/shadow.go index 674d70f52d..d7003acd3d 100644 --- a/widget/shadow.go +++ b/widget/shadow.go @@ -81,6 +81,45 @@ func (r *shadowRenderer) createShadows() { } } +func updateShadowStart(g *canvas.LinearGradient) { + if g == nil { + return + } + + g.StartColor = theme.ShadowColor() + g.Refresh() +} + +func updateShadowEnd(g *canvas.LinearGradient) { + if g == nil { + return + } + + g.EndColor = theme.ShadowColor() + g.Refresh() +} + +func updateShadowRadial(g *canvas.RadialGradient) { + if g == nil { + return + } + + g.StartColor = theme.ShadowColor() + g.Refresh() +} + +func (r *shadowRenderer) refreshShadows() { + updateShadowEnd(r.l) + updateShadowStart(r.r) + updateShadowStart(r.b) + updateShadowEnd(r.t) + + updateShadowRadial(r.tl) + updateShadowRadial(r.tr) + updateShadowRadial(r.bl) + updateShadowRadial(r.br) +} + func (r *shadowRenderer) BackgroundColor() color.Color { return color.Transparent } @@ -132,5 +171,5 @@ func (r *shadowRenderer) Objects() []fyne.CanvasObject { } func (r *shadowRenderer) Refresh() { - r.createShadows() + r.refreshShadows() } diff --git a/widget/shadow_test.go b/widget/shadow_test.go index 8e41150c59..8ddcb5bf8d 100644 --- a/widget/shadow_test.go +++ b/widget/shadow_test.go @@ -5,6 +5,7 @@ import ( "testing" "fyne.io/fyne" + "fyne.io/fyne/internal/cache" "fyne.io/fyne/theme" "github.com/stretchr/testify/assert" ) @@ -119,3 +120,20 @@ func TestShadow_BackgroundColor(t *testing.T) { func TestShadow_MinSize(t *testing.T) { assert.Equal(t, fyne.NewSize(0, 0), newShadow(shadowAround, theme.Padding()).MinSize()) } + +func TestShadow_Theme(t *testing.T) { + shadow := newShadow(shadowAround, theme.Padding()) + light := theme.LightTheme() + fyne.CurrentApp().Settings().SetTheme(light) + shadow.Refresh() + assert.Equal(t, light.ShadowColor(), cache.Renderer(shadow).(*shadowRenderer).l.EndColor) + assert.Equal(t, light.ShadowColor(), cache.Renderer(shadow).(*shadowRenderer).r.StartColor) + assert.Equal(t, light.ShadowColor(), cache.Renderer(shadow).(*shadowRenderer).tr.StartColor) + + dark := theme.DarkTheme() + fyne.CurrentApp().Settings().SetTheme(dark) + shadow.Refresh() + assert.Equal(t, dark.ShadowColor(), cache.Renderer(shadow).(*shadowRenderer).r.StartColor) + assert.Equal(t, dark.ShadowColor(), cache.Renderer(shadow).(*shadowRenderer).r.StartColor) + assert.Equal(t, dark.ShadowColor(), cache.Renderer(shadow).(*shadowRenderer).tr.StartColor) +} From 11fcb2ea5dbe643848591a2a4e0d71bda45e0030 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 15:25:04 +0000 Subject: [PATCH 13/16] Log GL errors if they occur after each frame --- internal/driver/gomobile/driver.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/driver/gomobile/driver.go b/internal/driver/gomobile/driver.go index d7db3816ff..fa0b9176e0 100644 --- a/internal/driver/gomobile/driver.go +++ b/internal/driver/gomobile/driver.go @@ -1,6 +1,7 @@ package gomobile import ( + "fmt" "runtime" "strconv" "time" @@ -139,6 +140,11 @@ func (d *mobileDriver) Run() { if d.freeDirtyTextures(canvas) { d.paintWindow(current, currentSize) a.Publish() + + err := d.glctx.GetError() + if err != 0 { + fyne.LogError(fmt.Sprintf("OpenGL Error: %d", err), nil) + } } time.Sleep(time.Millisecond * 10) From e93855f3201adceb4cd86705f5545b876491bc92 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 20:08:16 +0000 Subject: [PATCH 14/16] Fix packaging on Windows And also improve to use the "build gui" flag Fixes #586 --- CHANGELOG.md | 1 + cmd/fyne/build.go | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b460d0ce8..7e6ec66fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Issues when settings changes may not be monitored (#576) * Layout of hidden tab container contents on mobile (#578) * Mobile apps would not quit when Quit() was called (#580) +* Fyne package could fail on Windows (#586) ## 1.2 - 12 December 2019 diff --git a/cmd/fyne/build.go b/cmd/fyne/build.go index 95f16a1695..03d9485370 100644 --- a/cmd/fyne/build.go +++ b/cmd/fyne/build.go @@ -17,10 +17,15 @@ func (b *builder) build() error { goos = runtime.GOOS } - cmd := exec.Command("go", "build", b.srcdir) + var cmd *exec.Cmd + if goos == "windows" { + cmd = exec.Command("go", "build", "-ldflags", "-H=windowsgui", ".") + } else { + cmd = exec.Command("go", "build", ".") + } cmd.Dir = b.srcdir env := os.Environ() - env = append(env, "GOOS=", goos) + env = append(env, "GOOS="+goos) cmd.Env = env out, err := cmd.CombinedOutput() From df27ecba71c110479710c972089cc8d1310e48ce Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 22:19:59 +0000 Subject: [PATCH 15/16] Update for release --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e6ec66fa1..553a66ff4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ More detailed release notes can be found on the [releases page](https://github.c * Issues when settings changes may not be monitored (#576) * Layout of hidden tab container contents on mobile (#578) * Mobile apps would not quit when Quit() was called (#580) +* Shadows disappeared when theme changes (#589) +* iOS apps could stop rendering after many refreshes (#584) * Fyne package could fail on Windows (#586) From 3398cb71ddc55c5bb6e6753797725c243a6dfd99 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 24 Dec 2019 22:47:27 +0000 Subject: [PATCH 16/16] Fix horizontal only scroll refresh --- CHANGELOG.md | 1 + widget/scroller.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 553a66ff4e..61d5d2bab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Shadows disappeared when theme changes (#589) * iOS apps could stop rendering after many refreshes (#584) * Fyne package could fail on Windows (#586) +* Horizontal only scroll container may not refresh using scroll wheel ## 1.2 - 12 December 2019 diff --git a/widget/scroller.go b/widget/scroller.go index 685ce67b75..9f2e56f789 100644 --- a/widget/scroller.go +++ b/widget/scroller.go @@ -320,7 +320,8 @@ func (r *scrollContainerRenderer) updatePosition() { Renderer(r.vertArea).Layout(r.scroll.size) Renderer(r.horizArea).Layout(r.scroll.size) - canvas.Refresh(r.vertArea) // this is required to force the canvas to update, we have no "Redraw()" + canvas.Refresh(r.vertArea) // this is required to force the canvas to update, we have no "Redraw()" + canvas.Refresh(r.horizArea) // this is required like above but if we are horizontal } // ScrollContainer defines a container that is smaller than the Content.