Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Text Wrapping #712

Merged
merged 11 commits into from
Mar 31, 2020
Merged

Support Text Wrapping #712

merged 11 commits into from
Mar 31, 2020

Conversation

stuartmscott
Copy link
Member

@stuartmscott stuartmscott commented Feb 25, 2020

Support Text Wrapping

Fixes #332

Applies to Label, Hyperlink, and Entry

There are three text wrapping modes;

  • TextWrapOff (default)
    • Widgets are expanded to fit the text.
    • Consistent with previous behaviour.
  • TextTruncate
    • Text longer than the widget's width is not displayed.
    • An elipse is NOT added if text gets truncated, although this
      should be considered for future.
  • TextWrapOn
    • Text longer than the widget's width is wrapped onto the next line.
    • A hyphen is NOT added if a word gets broken, although this
      should be considered for future (perhaps TextWrapOnHypenate).

This commit has some issues and is therefore not yet ready to merge;

  • Truncation doesn't work with Selection;
    • Cursor position overflows row boundary and gets set to 0,0.
    • Select All only selects visible text.
  • Truncation doesn't work with Scrollers;
    • Text does not get truncated, scroller just keeps expanding.
  • Cursor moves to the wrong position after wrapping.
  • Unclear how to handle Entry.multiline=false with TextWrapOn;
    • Maybe fallback to TextTruncate?.
  • Test execution result in;
    • Warnings about multiple methods names 'center'
    • Warnings about the use of deprecated NSOpenGLContext

@stuartmscott
Copy link
Member Author

Seeing sporadic failures:

$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.476s
ok  	fyne.io/fyne/app	0.288s
ok  	fyne.io/fyne/canvas	0.444s
ok  	fyne.io/fyne/cmd/fyne	0.254s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.209s
ok  	fyne.io/fyne/driver/desktop	0.205s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.335s
ok  	fyne.io/fyne/internal/app	0.265s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.232s
2020/02/26 08:55:27 Fyne error:  Failed to decode image for window icon
2020/02/26 08:55:27   Cause: image: unknown format
2020/02/26 08:55:27   At: /Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:213
--- FAIL: TestWindow_Focus (0.12s)
    window_test.go:667: 
        	Error Trace:	window_test.go:667
        	Error:      	Not equal: 
        	            	expected: "abcd"
        	            	actual  : "bcd"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1 +1 @@
        	            	-abcd
        	            	+bcd
        	Test:       	TestWindow_Focus
FAIL
FAIL	fyne.io/fyne/internal/driver/glfw	4.445s
ok  	fyne.io/fyne/internal/driver/gomobile	0.799s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.640s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.270s
ok  	fyne.io/fyne/test	0.215s
ok  	fyne.io/fyne/theme	0.192s
ok  	fyne.io/fyne/tools/modvendor	0.151s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.312s
FAIL
$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.430s
ok  	fyne.io/fyne/app	0.320s
ok  	fyne.io/fyne/canvas	0.361s
ok  	fyne.io/fyne/cmd/fyne	0.198s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.188s
ok  	fyne.io/fyne/driver/desktop	0.130s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.183s
ok  	fyne.io/fyne/internal/app	0.266s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.243s
ok  	fyne.io/fyne/internal/driver/glfw	4.892s
ok  	fyne.io/fyne/internal/driver/gomobile	0.635s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.298s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.375s
ok  	fyne.io/fyne/test	0.166s
ok  	fyne.io/fyne/theme	0.111s
ok  	fyne.io/fyne/tools/modvendor	0.107s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.308s
$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.179s
ok  	fyne.io/fyne/app	0.281s
ok  	fyne.io/fyne/canvas	0.289s
ok  	fyne.io/fyne/cmd/fyne	0.215s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.210s
ok  	fyne.io/fyne/driver/desktop	0.140s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.145s
ok  	fyne.io/fyne/internal/app	0.220s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.173s
--- FAIL: TestGlCanvas_Resize (0.25s)
    canvas_test.go:42: 
        	Error Trace:	canvas_test.go:42
        	Error:      	Not equal: 
        	            	expected: fyne.Size{Width:100, Height:100}
        	            	actual  : fyne.Size{Width:0, Height:0}
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,4 +1,4 @@
        	            	 (fyne.Size) {
        	            	- Width: (int) 100,
        	            	- Height: (int) 100
        	            	+ Width: (int) 0,
        	            	+ Height: (int) 0
        	            	 }
        	Test:       	TestGlCanvas_Resize
2020/02/26 08:56:52 Fyne error:  Failed to decode image for window icon
2020/02/26 08:56:52   Cause: image: unknown format
2020/02/26 08:56:52   At: /Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:213
--- FAIL: TestWindow_Focus (0.09s)
    window_test.go:667: 
        	Error Trace:	window_test.go:667
        	Error:      	Not equal: 
        	            	expected: "abcd"
        	            	actual  : "bcd"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1 +1 @@
        	            	-abcd
        	            	+bcd
        	Test:       	TestWindow_Focus
FAIL
FAIL	fyne.io/fyne/internal/driver/glfw	4.597s
ok  	fyne.io/fyne/internal/driver/gomobile	0.803s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.643s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.505s
ok  	fyne.io/fyne/test	0.161s
ok  	fyne.io/fyne/theme	0.107s
ok  	fyne.io/fyne/tools/modvendor	0.099s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.436s
FAIL
$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.125s
ok  	fyne.io/fyne/app	0.295s
ok  	fyne.io/fyne/canvas	0.271s
ok  	fyne.io/fyne/cmd/fyne	0.215s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.359s
ok  	fyne.io/fyne/driver/desktop	0.366s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.347s
ok  	fyne.io/fyne/internal/app	0.271s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.208s
ok  	fyne.io/fyne/internal/driver/glfw	4.770s
ok  	fyne.io/fyne/internal/driver/gomobile	0.635s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.259s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.229s
ok  	fyne.io/fyne/test	0.153s
ok  	fyne.io/fyne/theme	0.147s
ok  	fyne.io/fyne/tools/modvendor	0.092s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.380s
$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.141s
ok  	fyne.io/fyne/app	0.319s
ok  	fyne.io/fyne/canvas	0.205s
ok  	fyne.io/fyne/cmd/fyne	0.239s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.313s
ok  	fyne.io/fyne/driver/desktop	0.245s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.331s
ok  	fyne.io/fyne/internal/app	0.219s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.296s
SIGABRT: abort
PC=0x7fff6c7857fa m=0 sigcode=0
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x43a1710, 0xc000153cc8, 0x437069a)
	/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc000153c98 sp=0xc000153c60 pc=0x4005e5b
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw._Cfunc_glfwInit(0x0)
	_cgo_gotypes.go:1066 +0x49 fp=0xc000153cc8 sp=0xc000153c98 pc=0x4357979
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw.Init(0x0, 0x0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw.go:33 +0x22 fp=0xc000153d08 sp=0xc000153cc8 pc=0x435a9b2
fyne.io/fyne/internal/driver/glfw.(*gLDriver).initGLFW(0xc000095410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:51 +0x22 fp=0xc000153d38 sp=0xc000153d08 pc=0x4374a92
fyne.io/fyne/internal/driver/glfw.(*gLDriver).runGL(0xc000095410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:68 +0xfd fp=0xc000153eb8 sp=0xc000153d38 pc=0x4374bed
fyne.io/fyne/internal/driver/glfw.(*gLDriver).Run(0xc000095410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/driver.go:66 +0x2b fp=0xc000153ed0 sp=0xc000153eb8 pc=0x43747ab
fyne.io/fyne/internal/driver/glfw.TestMain(0xc00012e100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:37 +0x57 fp=0xc000153ef8 sp=0xc000153ed0 pc=0x437e6e7
main.main()
	_testmain.go:98 +0x135 fp=0xc000153f60 sp=0xc000153ef8 pc=0x4394f25
runtime.main()
	/usr/local/go/src/runtime/proc.go:203 +0x21e fp=0xc000153fe0 sp=0xc000153f60 pc=0x403343e
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc000153fe8 sp=0xc000153fe0 pc=0x4060a81

goroutine 19 [sleep]:
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:310
time.Sleep(0x22ecb25c00)
	/usr/local/go/src/runtime/time.go:105 +0x157
fyne.io/fyne/internal/painter.svgCacheJanitor.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:51 +0x116
sync.(*Once).doSlow(0x4ac85d8, 0xc0000ae2d0)
	/usr/local/go/src/sync/once.go:66 +0xe3
sync.(*Once).Do(0x4ac85d8, 0xc0000ae2d0)
	/usr/local/go/src/sync/once.go:57 +0x45
created by fyne.io/fyne/internal/painter.svgCacheJanitor
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:49 +0x9b

goroutine 20 [chan receive]:
fyne.io/fyne/test.NewApp.func1(0xc000082240, 0xc0000953b0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:105 +0x3d
created by fyne.io/fyne/test.NewApp
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:103 +0x1ce

goroutine 21 [chan receive]:
testing.(*T).Run(0xc000168100, 0x44cf948, 0x14, 0x44eb938, 0x40aeb36)
	/usr/local/go/src/testing/testing.go:961 +0x377
testing.runTests.func1(0xc000168000)
	/usr/local/go/src/testing/testing.go:1202 +0x78
testing.tRunner(0xc000168000, 0xc000057e80)
	/usr/local/go/src/testing/testing.go:909 +0xc9
testing.runTests(0xc00000e060, 0x4a8e4c0, 0x1d, 0x1d, 0x0)
	/usr/local/go/src/testing/testing.go:1200 +0x2a7
testing.(*M).Run(0xc00012e100, 0x0)
	/usr/local/go/src/testing/testing.go:1117 +0x176
fyne.io/fyne/internal/driver/glfw.TestMain.func1(0xc00012e100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:35 +0x2b
created by fyne.io/fyne/internal/driver/glfw.TestMain
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:34 +0x3f

goroutine 6 [syscall]:
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw._Cfunc_glfwInit(0x0)
	_cgo_gotypes.go:1066 +0x49
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw.Init(0x404eacb, 0x47db3f4)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw.go:33 +0x22
fyne.io/fyne/internal/driver/glfw.(*gLDriver).initGLFW(0xc000095410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:51 +0x22
sync.(*Once).doSlow(0x4ac85c8, 0xc000041670)
	/usr/local/go/src/sync/once.go:66 +0xe3
sync.(*Once).Do(...)
	/usr/local/go/src/sync/once.go:57
fyne.io/fyne/internal/driver/glfw.(*gLDriver).CreateWindow.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1036 +0x8d5
fyne.io/fyne/internal/driver/glfw.runOnMain(0xc0000200f0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:41 +0xab
fyne.io/fyne/internal/driver/glfw.(*gLDriver).CreateWindow(0xc000095410, 0x44c2802, 0x4, 0x40510e8, 0x290996250efe2)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1035 +0x99
fyne.io/fyne/internal/driver/glfw.TestGlCanvas_Content(0xc000168100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/canvas_test.go:18 +0x68
testing.tRunner(0xc000168100, 0x44eb938)
	/usr/local/go/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:960 +0x350

rax    0x0
rbx    0xbf68dc0
rcx    0x7ffeefbff1b8
rdx    0x0
rdi    0x307
rsi    0x6
rbp    0x7ffeefbff1e0
rsp    0x7ffeefbff1b8
r8     0x0
r9     0x0
r10    0xbf68dc0
r11    0x246
r12    0x307
r13    0x13c
r14    0x6
r15    0x16
rip    0x7fff6c7857fa
rflags 0x246
cs     0x7
fs     0x0
gs     0x0
FAIL	fyne.io/fyne/internal/driver/glfw	0.320s
ok  	fyne.io/fyne/internal/driver/gomobile	0.912s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.298s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.533s
ok  	fyne.io/fyne/test	0.177s
ok  	fyne.io/fyne/theme	0.107s
ok  	fyne.io/fyne/tools/modvendor	0.106s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.645s
FAIL
$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.139s
ok  	fyne.io/fyne/app	0.273s
ok  	fyne.io/fyne/canvas	0.169s
ok  	fyne.io/fyne/cmd/fyne	0.201s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.271s
ok  	fyne.io/fyne/driver/desktop	0.308s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.491s
ok  	fyne.io/fyne/internal/app	0.260s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.314s
ok  	fyne.io/fyne/internal/driver/glfw	4.849s
ok  	fyne.io/fyne/internal/driver/gomobile	1.035s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.224s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.551s
ok  	fyne.io/fyne/test	0.167s
ok  	fyne.io/fyne/theme	0.162s
ok  	fyne.io/fyne/tools/modvendor	0.104s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.355s
$ go test -count=1 fyne.io/fyne/...
# fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw
In file included from ../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go:8:
../../../fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/src/cocoa_window.m:989:9: warning: multiple methods named 'center' found [-Wobjc-multiple-method-names]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCollectionViewCompositionalLayout.h:601:19: note: using
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:312:1: note: also found
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne	0.140s
ok  	fyne.io/fyne/app	0.306s
ok  	fyne.io/fyne/canvas	0.234s
ok  	fyne.io/fyne/cmd/fyne	0.298s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.214s
ok  	fyne.io/fyne/driver/desktop	0.140s
?   	fyne.io/fyne/driver/mobile	[no test files]
# fyne.io/fyne/internal/driver/glfw
fyne.io/fyne/internal/driver/glfw/gl_darwinfix.go:10:5: warning: 'NSOpenGLContext' is deprecated: first deprecated in macOS 10.14 - Please use Metal or MetalKit. [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSOpenGL.h:193:12: note: 'NSOpenGLContext' has been explicitly marked deprecated here
ok  	fyne.io/fyne/internal	0.153s
ok  	fyne.io/fyne/internal/app	0.328s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.152s
ok  	fyne.io/fyne/internal/driver/glfw	5.802s
ok  	fyne.io/fyne/internal/driver/gomobile	0.852s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.231s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.241s
ok  	fyne.io/fyne/test	0.165s
ok  	fyne.io/fyne/theme	0.112s
ok  	fyne.io/fyne/tools/modvendor	0.092s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	4.054s

@andydotxyz
Copy link
Member

Thanks for your work on this - it's really promising. Many of the issues you see in test failures are to do with the old glfw3.2 on develop we have upgraded to 3.3. Work of this size should be based off develop anyway, so if you could please rebase your work then re-running the tests should be far more favourable.

From what you have described it seems like the selection issues should be easily addressed - probably the new boundary code is not respected by cursor movement?

The WrapLineLimit API that I proposed was not intended to limit the line length, but the number of lines that we wrap over (I guess like CSS "-webkit-line-clamp" - so we can code simply a "3 line preview" for example - like wrap turned on with the last line truncating).

I wonder if TextWrapOn is a little ambiguous. Essentially we could have TextWrapWord or TextWrapBreak where it defines whether or not words should be broken - I think you have implemented the latter, but by calling it just "TextWrapOn" then adding the nuance could be a bit unclear.

I hope that helps. I thought it would be good to chat through these points before doing an in-depth review of the PR.

@stuartmscott
Copy link
Member Author

No worries :-)
I rebased onto develop but am still seeing some flakey tests;

  • canvas_test.go:42
$ go test -count=1 fyne.io/fyne/...
ok  	fyne.io/fyne	0.131s
ok  	fyne.io/fyne/app	0.272s
ok  	fyne.io/fyne/canvas	0.279s
ok  	fyne.io/fyne/cmd/fyne	0.202s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.212s
ok  	fyne.io/fyne/driver/desktop	0.181s
?   	fyne.io/fyne/driver/mobile	[no test files]
ok  	fyne.io/fyne/internal	0.219s
ok  	fyne.io/fyne/internal/app	0.220s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.341s
--- FAIL: TestGlCanvas_Resize (0.28s)
    canvas_test.go:42: 
        	Error Trace:	canvas_test.go:42
        	Error:      	Not equal: 
        	            	expected: fyne.Size{Width:100, Height:100}
        	            	actual  : fyne.Size{Width:0, Height:0}
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,4 +1,4 @@
        	            	 (fyne.Size) {
        	            	- Width: (int) 100,
        	            	- Height: (int) 100
        	            	+ Width: (int) 0,
        	            	+ Height: (int) 0
        	            	 }
        	Test:       	TestGlCanvas_Resize
2020/02/26 16:18:13 Fyne error:  Failed to decode image for window icon
2020/02/26 16:18:13   Cause: image: unknown format
2020/02/26 16:18:13   At: /Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:211
FAIL
FAIL	fyne.io/fyne/internal/driver/glfw	5.290s
ok  	fyne.io/fyne/internal/driver/gomobile	0.682s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.209s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.258s
ok  	fyne.io/fyne/test	0.226s
ok  	fyne.io/fyne/theme	0.177s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.539s
FAIL
  • canvas_test.go:18 / window_test.go:35 / window_test.go:37
$ go test -count=1 fyne.io/fyne/...
ok  	fyne.io/fyne	0.141s
ok  	fyne.io/fyne/app	0.266s
ok  	fyne.io/fyne/canvas	0.246s
ok  	fyne.io/fyne/cmd/fyne	0.249s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.201s
ok  	fyne.io/fyne/driver/desktop	0.280s
?   	fyne.io/fyne/driver/mobile	[no test files]
ok  	fyne.io/fyne/internal	0.197s
ok  	fyne.io/fyne/internal/app	0.354s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.290s
2020-02-26 16:18:31.213 glfw.test[69354:3356491] *** Assertion failure in -[NSApplication run], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1894.30.142/AppKit.subproj/NSApplication.m:3313
2020-02-26 16:18:31.214 glfw.test[69354:3356491] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSApp with wrong _running count'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff350168ab __exceptionPreprocess + 250
	1   libobjc.A.dylib                     0x00007fff6b2d0805 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff3503fd10 +[NSException raise:format:arguments:] + 88
	3   Foundation                          0x00007fff37738241 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
	4   AppKit                              0x00007fff3214f1fb -[NSApplication run] + 1007
	5   glfw.test                           0x00000000043a3b4d _glfwPlatformCreateWindow + 77
	6   glfw.test                           0x000000000439cd55 glfwCreateWindow + 485
	7   glfw.test                           0x00000000043a9b2b _cgo_8d6b35894ada_Cfunc_glfwCreateWindow + 43
	8   glfw.test                           0x000000000405f350 runtime.asmcgocall + 112
)
libc++abi.dylib: terminating with uncaught exception of type NSException
SIGABRT: abort
PC=0x7fff6c7857fa m=0 sigcode=0
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x43a9b00, 0xc000169bc0, 0x400ea08)
	/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc000169b90 sp=0xc000169b58 pc=0x4004f8b
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw._Cfunc_glfwCreateWindow(0xa0000000a, 0x4d17970, 0x0, 0x0, 0x0)
	_cgo_gotypes.go:630 +0x4e fp=0xc000169bc0 sp=0xc000169b90 pc=0x43571ae
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw.CreateWindow.func2(0xa, 0xa, 0x4d17970, 0x0, 0x0, 0xc00439d096)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw/window.go:348 +0xab fp=0xc000169bf8 sp=0xc000169bc0 pc=0x435e83b
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw.CreateWindow(0xa, 0xa, 0x44cc502, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw/window.go:348 +0xff fp=0xc000169c98 sp=0xc000169bf8 pc=0x435c6bf
fyne.io/fyne/internal/driver/glfw.(*gLDriver).createWindow.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1052 +0x103 fp=0xc000169d38 sp=0xc000169c98 pc=0x4391b83
fyne.io/fyne/internal/driver/glfw.(*gLDriver).runGL(0xc0000a5410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:77 +0x4d6 fp=0xc000169eb8 sp=0xc000169d38 pc=0x43752e6
fyne.io/fyne/internal/driver/glfw.(*gLDriver).Run(0xc0000a5410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/driver.go:66 +0x2b fp=0xc000169ed0 sp=0xc000169eb8 pc=0x4374acb
fyne.io/fyne/internal/driver/glfw.TestMain(0xc00013e100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:37 +0x57 fp=0xc000169ef8 sp=0xc000169ed0 pc=0x437f4d7
main.main()
	_testmain.go:110 +0x135 fp=0xc000169f60 sp=0xc000169ef8 pc=0x4396395
runtime.main()
	/usr/local/go/src/runtime/proc.go:203 +0x21e fp=0xc000169fe0 sp=0xc000169f60 pc=0x403256e
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc000169fe8 sp=0xc000169fe0 pc=0x405fbb1

goroutine 19 [sleep]:
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:310
time.Sleep(0x22ecb25c00)
	/usr/local/go/src/runtime/time.go:105 +0x157
fyne.io/fyne/internal/painter.svgCacheJanitor.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:51 +0x116
sync.(*Once).doSlow(0x4af3ff8, 0xc0000be2d0)
	/usr/local/go/src/sync/once.go:66 +0xe3
sync.(*Once).Do(0x4af3ff8, 0xc0000be2d0)
	/usr/local/go/src/sync/once.go:57 +0x45
created by fyne.io/fyne/internal/painter.svgCacheJanitor
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:49 +0x9b

goroutine 20 [chan receive]:
fyne.io/fyne/test.NewApp.func1(0xc000098240, 0xc0000a53b0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:105 +0x3d
created by fyne.io/fyne/test.NewApp
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:103 +0x1ce

goroutine 21 [chan receive]:
testing.(*T).Run(0xc00018e100, 0x44d96ea, 0x14, 0x44f57e8, 0x40adc66)
	/usr/local/go/src/testing/testing.go:961 +0x377
testing.runTests.func1(0xc00018e000)
	/usr/local/go/src/testing/testing.go:1202 +0x78
testing.tRunner(0xc00018e000, 0xc00016ce80)
	/usr/local/go/src/testing/testing.go:909 +0xc9
testing.runTests(0xc00018a000, 0x4ab9200, 0x23, 0x23, 0x0)
	/usr/local/go/src/testing/testing.go:1200 +0x2a7
testing.(*M).Run(0xc00013e100, 0x0)
	/usr/local/go/src/testing/testing.go:1117 +0x176
fyne.io/fyne/internal/driver/glfw.TestMain.func1(0xc00013e100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:35 +0x2b
created by fyne.io/fyne/internal/driver/glfw.TestMain
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:34 +0x3f

goroutine 51 [chan receive]:
fyne.io/fyne/internal/driver/glfw.runOnMain(0xc00017c0c0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:46 +0x97
fyne.io/fyne/internal/driver/glfw.(*gLDriver).createWindow(0xc0000a5410, 0x44cc502, 0x4, 0x4498101, 0x404ea01, 0xc000184050)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1040 +0xcb
fyne.io/fyne/internal/driver/glfw.(*gLDriver).CreateWindow(0xc0000a5410, 0x44cc502, 0x4, 0x4050218, 0x2a5dbceb4f783)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1032 +0x44
fyne.io/fyne/internal/driver/glfw.TestGlCanvas_Content(0xc00018e100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/canvas_test.go:18 +0x68
testing.tRunner(0xc00018e100, 0x44f57e8)
	/usr/local/go/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:960 +0x350

rax    0x0
rbx    0x567adc0
rcx    0x7ffeefbfdb18
rdx    0x0
rdi    0x307
rsi    0x6
rbp    0x7ffeefbfdb40
rsp    0x7ffeefbfdb18
r8     0x7ffeefbfd9e0
r9     0x7ffeefbfdbb0
r10    0x567adc0
r11    0x246
r12    0x307
r13    0x3000000008
r14    0x6
r15    0x16
rip    0x7fff6c7857fa
rflags 0x246
cs     0x7
fs     0x0
gs     0x0
FAIL	fyne.io/fyne/internal/driver/glfw	0.672s
ok  	fyne.io/fyne/internal/driver/gomobile	0.848s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.498s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.381s
ok  	fyne.io/fyne/test	0.156s
ok  	fyne.io/fyne/theme	0.108s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.461s
FAIL
  • All tests pass
$ go test -count=1 fyne.io/fyne/...
ok  	fyne.io/fyne	0.133s
ok  	fyne.io/fyne/app	0.322s
ok  	fyne.io/fyne/canvas	0.320s
ok  	fyne.io/fyne/cmd/fyne	0.230s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.287s
ok  	fyne.io/fyne/driver/desktop	0.236s
?   	fyne.io/fyne/driver/mobile	[no test files]
ok  	fyne.io/fyne/internal	0.140s
ok  	fyne.io/fyne/internal/app	0.280s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.231s
ok  	fyne.io/fyne/internal/driver/glfw	5.788s
ok  	fyne.io/fyne/internal/driver/gomobile	0.754s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.267s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.508s
ok  	fyne.io/fyne/test	0.214s
ok  	fyne.io/fyne/theme	0.115s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.636s

Perhaps it would be useful if I added the different wrapping modes to fyne_demo, both inside and without a scroller for devs to see how they behave for labels, hyperlinks, and entries?

How about WrapMaxLines or WrapLineCountLimit?

Yup I agree that splitting TextWrapOn into multiple types makes it clearer. Right now it implements TextWrapBreak, and I could take a swing at TextWrapWord, but I think there should also be TextWrapHypenate which behaves like TextWrapBreak but will add a '-' to the end of a word broken by the wrapping. I purposely did not implement this in this PR as it is a lot of work to do well - you cant just hyphenate words at any old place;

hello w-
orld

hello wo-
rld

hello wor-
ld

Each word has places where it is acceptable to hyphenate and others where it is not, and this varies between publishing house, dialects, enUK/enUS, and that's without thinking about internationalization. Suffice to say it is a tough problem and I think it makes sense to leave it out of this PR and we can revisit later (probably after i18n support).

@stuartmscott stuartmscott changed the base branch from master to develop February 27, 2020 00:44
@andydotxyz
Copy link
Member

Re: tests - yes you are right. That canvas test is flakey and needs improved. The "_running count" seems to be something strange in the latest macOS that only manifests in the test suite, not yet tracked down.

@andydotxyz
Copy link
Member

Thanks for the work on this, your thoughts all seem to be going in the right direction. WrapMaxLines seems clearer than the longer form to me. I agree that adding examples to fyne_demo would be really helpful - maybe on the "Buttons" tab (as it has Label) and possibly it should have a clearer name anyhow.

I'm happy to consider merging this in with just TextWrapBreak, then add TextWrapWord a little later if it helps. Also happy about not writing TextWrapHyphenate any time soon ;). However I do wonder if we should have the ellipsis on by default for truncate, it seems clearer - if required in the future there could always be a mode with no added character? indicating that something has been truncated is likely more useful than hiding that fact. Sorry if this isn't what I said before!

@stuartmscott
Copy link
Member Author

I agree that ellipsis are a good idea as they make it obvious text has been truncated, however it will be a bigger change (see below). Would it be better to remove Truncation from this PR and implement it properly later?

The current implementation uses "t.rowBounds [][2]int" to hold the start and end indicies of each line of text in "t.buffer", however this is not sufficient to hold all the information about the line such as whether it was truncated and should have ellipsis added. It doesn't make sense to insert the ellipsis into "t.buffer" as this at the model level and ellipsis are at the presentation level. To implement truncation properly I would change "t.rowBounds [][2]int" to "t.lines []*line" where line is;

type line struct {
	lowBound, highBound int
	text []rune
}

This gives the presentation layer a place to store the text to present that is separate from the model storage, and gives the flexibility to add a suffix for truncation '...', or hyphenation '-'. It also affords some future projects;

I also noticed that Fyne doesn't support a text alignment of "justified". This is another part of typesetting that is difficult to do well, but it is something I have recently implemented as part of https://github.com/AletheiaWareLLC/pdfgo which is a PDF generator written in Go. It supports;

  • Left
  • Center
  • Right
  • JustifiedLeft
  • JustifiedCenter
  • JustifiedRight

The reason there are three types of Justification is all about how the last sentence in a paragraph is displayed - you don't want to stretch the sentence to full justification as this will be unreadable. Instead the bulk of the paragraph is fully justified and the last paragraph is either left, center, or right aligned.

The way I implemented this was with;

  • character spacing - aka tracking - space between individual characters.
  • word spacing - space between words ie how wide the ' ' character is.
  • indent - distance from the start of the line.

With this information all the text alignments above can be implemented, eg. right alignment just means that the indent is set to widget.width - text.width, center alignment just means that the indent is set to half widget.width - text.width. Justification uses a combination of spacing and indentation to balance the line in the widget.

type line struct {
	lowBound, highBound int
	text []rune
	characterSpacing float64
	wordSpacing float64
	indent float64
}

Implementing the above would negate the need for canvas/text.go and internal/painter/gl/draw.go to know about alignment. internal/painter/gl/gl_common.go newGlTextTexture would advance the dot by the indent and, for each character, the relevant spacing.

Obviously this is a much bigger change and would also need to be mirrored to mobile, thus way outside the scope of this PR, but it is worth thinking about now. I think it would be better to implement truncation properly in a later PR rather than some quick hack in this one.

@andydotxyz
Copy link
Member

These are good observations, though I would be very careful before extending the bounds code - that is model level, but the wrap and truncate is render level (as you said). So perhaps the new info is in the renderer matching the indexes of the bounds slice? (and you're right there is no way that we should insert ellipses). But as the output is a list of canvas Text objects then it's a case of whether or not we append one in the render output so it shouldn't have to touch the model.
We could land this without truncation if you think that is easier - I will normally support smaller, more frequent PRs :)

Feel free to add an issue for the missing "Justified" alignment - but are you sure all 3 types are needed? most places really only have 1. I appreciate that it could remove some code from the driver, but we need to consider speed here as well and having a whole line rendered in 1 go is a lot faster than rendering 1 character at a time (I think). let's discuss this in another issue though.

@andydotxyz
Copy link
Member

One other observation on the code as is - that's a lot of new public APIs at the top level.
We tend to be very careful and only add a public API if it is required by end users. And we try to scope them appropriately. Can you discuss the decision to add these all, or do they belong in something like "internal/text/" instead?

@stuartmscott
Copy link
Member Author

It is possible to add ellipsis (truncate) and hyphens (wrap w/ break) in the canvas Text objects but then they will need to know whether their text has been truncated or wrapped w/ break so either way "rowBounds [2]int" is insufficient.

I appreciate that it could remove some code from the driver, but we need to consider speed here as well and having a whole line rendered in 1 go is a lot faster than rendering 1 character at a time (I think).

Looking at the code that renders the line (https://github.com/golang/image/blob/58c23975cae11f062d4b3b0c143fe248faac195d/font/font.go#L165) it just loops through each character in the line anyway, so moving this loop into fyne would give us the flexibility and control without compromising the performance.

I'll leave justification for now, it can be implemented in a future PR.

This PR now includes an addition to fyne_demo which showcases text alignment and wrapping, could you take a look and let me know what you think?

There is still a bug here because Entry was hardcoded to TextAlignLeading and the code handling Cursor assumes the line always starts at theme.Padding(). So if you change the Entry's alignment to "Center" or "Trailing" and try to place the Cursor you will see some weird behaviour.

@stuartmscott stuartmscott force-pushed the wrapping branch 2 times, most recently from 4ddcadb to 58a41b2 Compare March 21, 2020 00:51
@stuartmscott
Copy link
Member Author

stuartmscott commented Mar 21, 2020

Seeing some test failures, gomobile/canvas_test.go TestCanvas_TappedSecondary is failing, the rest appear flakey;

$ go test -count=1 fyne.io/fyne/...
ok  	fyne.io/fyne	0.175s
ok  	fyne.io/fyne/app	0.261s
ok  	fyne.io/fyne/canvas	0.250s
ok  	fyne.io/fyne/cmd/fyne	0.207s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.239s
ok  	fyne.io/fyne/driver/desktop	0.148s
?   	fyne.io/fyne/driver/mobile	[no test files]
ok  	fyne.io/fyne/internal	0.198s
ok  	fyne.io/fyne/internal/app	0.234s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.223s
2020-03-20 17:48:55.662 glfw.test[85489:6062843] *** Assertion failure in -[NSApplication run], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1894.30.142/AppKit.subproj/NSApplication.m:3313
2020-03-20 17:48:55.663 glfw.test[85489:6062843] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSApp with wrong _running count'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff350168ab __exceptionPreprocess + 250
	1   libobjc.A.dylib                     0x00007fff6b2d0805 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff3503fd10 +[NSException raise:format:arguments:] + 88
	3   Foundation                          0x00007fff37738241 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
	4   AppKit                              0x00007fff3214f1fb -[NSApplication run] + 1007
	5   glfw.test                           0x00000000043ab4ad _glfwPlatformCreateWindow + 77
	6   glfw.test                           0x00000000043a46b5 glfwCreateWindow + 485
	7   glfw.test                           0x00000000043b148b _cgo_8d6b35894ada_Cfunc_glfwCreateWindow + 43
	8   glfw.test                           0x000000000405f490 runtime.asmcgocall + 112
)
libc++abi.dylib: terminating with uncaught exception of type NSException
SIGABRT: abort
PC=0x7fff6c7857fa m=0 sigcode=0
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x43b1460, 0xc00015dbc0, 0x400eb48)
	/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc00015db90 sp=0xc00015db58 pc=0x40050cb
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw._Cfunc_glfwCreateWindow(0xa0000000a, 0x4f367a0, 0x0, 0x0, 0x0)
	_cgo_gotypes.go:630 +0x4e fp=0xc00015dbc0 sp=0xc00015db90 pc=0x4358e8e
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw.CreateWindow.func2(0xa, 0xa, 0x4f367a0, 0x0, 0x0, 0xc0043a49f6)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw/window.go:348 +0xab fp=0xc00015dbf8 sp=0xc00015dbc0 pc=0x436051b
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw.CreateWindow(0xa, 0xa, 0x44d552c, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw/window.go:348 +0xff fp=0xc00015dc98 sp=0xc00015dbf8 pc=0x435e39f
fyne.io/fyne/internal/driver/glfw.(*gLDriver).createWindow.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1082 +0x103 fp=0xc00015dd38 sp=0xc00015dc98 pc=0x4399213
fyne.io/fyne/internal/driver/glfw.(*gLDriver).runGL(0xc00009d410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:87 +0x4e2 fp=0xc00015deb8 sp=0xc00015dd38 pc=0x4377e92
fyne.io/fyne/internal/driver/glfw.(*gLDriver).Run(0xc00009d410)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/driver.go:61 +0x2b fp=0xc00015ded0 sp=0xc00015deb8 pc=0x43775fb
fyne.io/fyne/internal/driver/glfw.TestMain(0xc000136100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:37 +0x57 fp=0xc00015def8 sp=0xc00015ded0 pc=0x4385ad7
main.main()
	_testmain.go:122 +0x135 fp=0xc00015df60 sp=0xc00015def8 pc=0x439dcf5
runtime.main()
	/usr/local/go/src/runtime/proc.go:203 +0x21e fp=0xc00015dfe0 sp=0xc00015df60 pc=0x40326ae
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc00015dfe8 sp=0xc00015dfe0 pc=0x405fcf1

goroutine 19 [sleep]:
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:310
time.Sleep(0x22ecb25c00)
	/usr/local/go/src/runtime/time.go:105 +0x157
fyne.io/fyne/internal/painter.svgCacheJanitor.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:51 +0x116
sync.(*Once).doSlow(0x4b030b8, 0xc0000b62d0)
	/usr/local/go/src/sync/once.go:66 +0xe3
sync.(*Once).Do(0x4b030b8, 0xc0000b62d0)
	/usr/local/go/src/sync/once.go:57 +0x45
created by fyne.io/fyne/internal/painter.svgCacheJanitor
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:49 +0x9b

goroutine 20 [chan receive]:
fyne.io/fyne/test.NewApp.func1(0xc00008a240, 0xc00009d3b0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:105 +0x3d
created by fyne.io/fyne/test.NewApp
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:103 +0x1ce

goroutine 21 [chan receive]:
testing.(*T).Run(0xc000192100, 0x44e283c, 0x14, 0x44feba0, 0x40adda6)
	/usr/local/go/src/testing/testing.go:961 +0x377
testing.runTests.func1(0xc000192000)
	/usr/local/go/src/testing/testing.go:1202 +0x78
testing.tRunner(0xc000192000, 0xc000174e80)
	/usr/local/go/src/testing/testing.go:909 +0xc9
testing.runTests(0xc000186000, 0x4ac8240, 0x29, 0x29, 0x0)
	/usr/local/go/src/testing/testing.go:1200 +0x2a7
testing.(*M).Run(0xc000136100, 0x0)
	/usr/local/go/src/testing/testing.go:1117 +0x176
fyne.io/fyne/internal/driver/glfw.TestMain.func1(0xc000136100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:35 +0x2b
created by fyne.io/fyne/internal/driver/glfw.TestMain
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:34 +0x3f

goroutine 35 [chan receive]:
fyne.io/fyne/internal/driver/glfw.runOnMain(0xc0001780c0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:46 +0x97
fyne.io/fyne/internal/driver/glfw.(*gLDriver).createWindow(0xc00009d410, 0x44d552c, 0x4, 0x44a0301, 0x404eb01, 0xc000180050)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1070 +0xcb
fyne.io/fyne/internal/driver/glfw.(*gLDriver).CreateWindow(0xc00009d410, 0x44d552c, 0x4, 0x4050358, 0x4938cadf3c4fc)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1062 +0x44
fyne.io/fyne/internal/driver/glfw.TestGlCanvas_Content(0xc000192100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/canvas_test.go:19 +0x68
testing.tRunner(0xc000192100, 0x44feba0)
	/usr/local/go/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:960 +0x350

rax    0x0
rbx    0x10fbddc0
rcx    0x7ffeefbfdb18
rdx    0x0
rdi    0x307
rsi    0x6
rbp    0x7ffeefbfdb40
rsp    0x7ffeefbfdb18
r8     0x7ffeefbfd9e0
r9     0x7ffeefbfdbb0
r10    0x10fbddc0
r11    0x246
r12    0x307
r13    0x3000000008
r14    0x6
r15    0x16
rip    0x7fff6c7857fa
rflags 0x246
cs     0x7
fs     0x0
gs     0x0
FAIL	fyne.io/fyne/internal/driver/glfw	0.684s
--- FAIL: TestCanvas_TappedSecondary (0.31s)
    canvas_test.go:108: 
        	Error Trace:	canvas_test.go:108
        	Error:      	Should be true
        	Test:       	TestCanvas_TappedSecondary
        	Messages:   	tap secondary
    canvas_test.go:109: 
        	Error Trace:	canvas_test.go:109
        	Error:      	Not equal: 
        	            	expected: *gomobile.tappableLabel(&gomobile.tappableLabel{Label:widget.Label{textProvider:widget.textProvider{BaseWidget:widget.BaseWidget{size:fyne.Size{Width:0, Height:0}, position:fyne.Position{X:3, Y:3}, Hidden:false, impl:(*widget.Label)(0xc00005a000)}, presenter:(*widget.Label)(0xc00005a000), buffer:[]int32{}, rowBounds:[][2]int{[2]int{0, 0}}}, Text:"", Alignment:0, Wrapping:0, TextStyle:fyne.TextStyle{Bold:false, Italic:false, Monospace:false}, MaxDisplayedLines:0, MinDisplayedLines:0}, tap:false, altTap:false})
        	            	actual  : <nil>(<nil>)
        	Test:       	TestCanvas_TappedSecondary
    canvas_test.go:110: 
        	Error Trace:	canvas_test.go:110
        	Error:      	Expected value not to be nil.
        	Test:       	TestCanvas_TappedSecondary
FAIL
FAIL	fyne.io/fyne/internal/driver/gomobile	0.719s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.463s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.455s
ok  	fyne.io/fyne/test	0.167s
ok  	fyne.io/fyne/theme	0.107s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	3.923s
FAIL
$ go test -count=1 fyne.io/fyne/...
ok  	fyne.io/fyne	0.178s
ok  	fyne.io/fyne/app	0.271s
ok  	fyne.io/fyne/canvas	0.228s
ok  	fyne.io/fyne/cmd/fyne	0.231s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.286s
ok  	fyne.io/fyne/driver/desktop	0.356s
?   	fyne.io/fyne/driver/mobile	[no test files]
ok  	fyne.io/fyne/internal	0.195s
ok  	fyne.io/fyne/internal/app	0.290s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.215s
--- FAIL: TestGlCanvas_ResizeWithOtherOverlay (0.12s)
    canvas_test.go:85: 
        	Error Trace:	canvas_test.go:85
        	Error:      	Not equal: 
        	            	expected: fyne.Size{Width:100, Height:100}
        	            	actual  : fyne.Size{Width:0, Height:0}
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,4 +1,4 @@
        	            	 (fyne.Size) {
        	            	- Width: (int) 100,
        	            	- Height: (int) 100
        	            	+ Width: (int) 0,
        	            	+ Height: (int) 0
        	            	 }
        	Test:       	TestGlCanvas_ResizeWithOtherOverlay
        	Messages:   	canvas overlay is resized
2020/03/20 17:49:23 Fyne error:  Failed to decode image for window icon
2020/03/20 17:49:23   Cause: image: unknown format
2020/03/20 17:49:23   At: /Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:215
FAIL
FAIL	fyne.io/fyne/internal/driver/glfw	5.723s
--- FAIL: TestCanvas_TappedSecondary (0.31s)
    canvas_test.go:108: 
        	Error Trace:	canvas_test.go:108
        	Error:      	Should be true
        	Test:       	TestCanvas_TappedSecondary
        	Messages:   	tap secondary
    canvas_test.go:109: 
        	Error Trace:	canvas_test.go:109
        	Error:      	Not equal: 
        	            	expected: *gomobile.tappableLabel(&gomobile.tappableLabel{Label:widget.Label{textProvider:widget.textProvider{BaseWidget:widget.BaseWidget{size:fyne.Size{Width:0, Height:0}, position:fyne.Position{X:3, Y:3}, Hidden:false, impl:(*widget.Label)(0xc00006c000)}, presenter:(*widget.Label)(0xc00006c000), buffer:[]int32{}, rowBounds:[][2]int{[2]int{0, 0}}}, Text:"", Alignment:0, Wrapping:0, TextStyle:fyne.TextStyle{Bold:false, Italic:false, Monospace:false}, MaxDisplayedLines:0, MinDisplayedLines:0}, tap:false, altTap:false})
        	            	actual  : <nil>(<nil>)
        	Test:       	TestCanvas_TappedSecondary
    canvas_test.go:110: 
        	Error Trace:	canvas_test.go:110
        	Error:      	Expected value not to be nil.
        	Test:       	TestCanvas_TappedSecondary
FAIL
FAIL	fyne.io/fyne/internal/driver/gomobile	0.604s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.389s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.419s
ok  	fyne.io/fyne/test	0.220s
ok  	fyne.io/fyne/theme	0.161s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	4.296s
FAIL
$ go test -count=1 fyne.io/fyne/...
ok  	fyne.io/fyne	0.142s
ok  	fyne.io/fyne/app	0.255s
ok  	fyne.io/fyne/canvas	0.181s
ok  	fyne.io/fyne/cmd/fyne	0.206s
?   	fyne.io/fyne/cmd/fyne/internal/mobile	[no test files]
?   	fyne.io/fyne/cmd/fyne/internal/mobile/binres	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_demo/screens	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/data	[no test files]
?   	fyne.io/fyne/cmd/fyne_settings/settings	[no test files]
?   	fyne.io/fyne/cmd/hello	[no test files]
ok  	fyne.io/fyne/dialog	0.247s
ok  	fyne.io/fyne/driver/desktop	0.159s
?   	fyne.io/fyne/driver/mobile	[no test files]
ok  	fyne.io/fyne/internal	0.183s
ok  	fyne.io/fyne/internal/app	0.244s
?   	fyne.io/fyne/internal/cache	[no test files]
ok  	fyne.io/fyne/internal/driver	0.192s
2020-03-20 17:49:52.612 glfw.test[85705:6065544] *** Assertion failure in -[NSApplication run], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1894.30.142/AppKit.subproj/NSApplication.m:3313
2020-03-20 17:49:52.613 glfw.test[85705:6065544] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSApp with wrong _running count'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff350168ab __exceptionPreprocess + 250
	1   libobjc.A.dylib                     0x00007fff6b2d0805 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff3503fd10 +[NSException raise:format:arguments:] + 88
	3   Foundation                          0x00007fff37738241 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
	4   AppKit                              0x00007fff3214f1fb -[NSApplication run] + 1007
	5   glfw.test                           0x00000000043ab4ad _glfwPlatformCreateWindow + 77
	6   glfw.test                           0x00000000043a46b5 glfwCreateWindow + 485
	7   glfw.test                           0x00000000043b148b _cgo_8d6b35894ada_Cfunc_glfwCreateWindow + 43
	8   glfw.test                           0x000000000405f490 runtime.asmcgocall + 112
)
libc++abi.dylib: terminating with uncaught exception of type NSException
SIGABRT: abort
PC=0x7fff6c7857fa m=0 sigcode=0
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x43b1460, 0xc000135bc0, 0x400eb48)
	/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc000135b90 sp=0xc000135b58 pc=0x40050cb
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw._Cfunc_glfwCreateWindow(0xa0000000a, 0x4d19ce0, 0x0, 0x0, 0x0)
	_cgo_gotypes.go:630 +0x4e fp=0xc000135bc0 sp=0xc000135b90 pc=0x4358e8e
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw.CreateWindow.func2(0xa, 0xa, 0x4d19ce0, 0x0, 0x0, 0xc0043a49f6)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw/window.go:348 +0xab fp=0xc000135bf8 sp=0xc000135bc0 pc=0x436051b
fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw.CreateWindow(0xa, 0xa, 0x44d552c, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/vendor/github.com/go-gl/glfw/v3.3/glfw/window.go:348 +0xff fp=0xc000135c98 sp=0xc000135bf8 pc=0x435e39f
fyne.io/fyne/internal/driver/glfw.(*gLDriver).createWindow.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1082 +0x103 fp=0xc000135d38 sp=0xc000135c98 pc=0x4399213
fyne.io/fyne/internal/driver/glfw.(*gLDriver).runGL(0xc000021440)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:87 +0x4e2 fp=0xc000135eb8 sp=0xc000135d38 pc=0x4377e92
fyne.io/fyne/internal/driver/glfw.(*gLDriver).Run(0xc000021440)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/driver.go:61 +0x2b fp=0xc000135ed0 sp=0xc000135eb8 pc=0x43775fb
fyne.io/fyne/internal/driver/glfw.TestMain(0xc00010a100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:37 +0x57 fp=0xc000135ef8 sp=0xc000135ed0 pc=0x4385ad7
main.main()
	_testmain.go:122 +0x135 fp=0xc000135f60 sp=0xc000135ef8 pc=0x439dcf5
runtime.main()
	/usr/local/go/src/runtime/proc.go:203 +0x21e fp=0xc000135fe0 sp=0xc000135f60 pc=0x40326ae
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc000135fe8 sp=0xc000135fe0 pc=0x405fcf1

goroutine 6 [sleep]:
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:310
time.Sleep(0x22ecb25c00)
	/usr/local/go/src/runtime/time.go:105 +0x157
fyne.io/fyne/internal/painter.svgCacheJanitor.func1()
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:51 +0x116
sync.(*Once).doSlow(0x4b030b8, 0xc000028320)
	/usr/local/go/src/sync/once.go:66 +0xe3
sync.(*Once).Do(0x4b030b8, 0xc000028320)
	/usr/local/go/src/sync/once.go:57 +0x45
created by fyne.io/fyne/internal/painter.svgCacheJanitor
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/painter/svg_cache.go:49 +0x9b

goroutine 7 [chan receive]:
fyne.io/fyne/test.NewApp.func1(0xc00002e2a0, 0xc0000213e0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:105 +0x3d
created by fyne.io/fyne/test.NewApp
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/test/testapp.go:103 +0x1ce

goroutine 8 [chan receive]:
testing.(*T).Run(0xc000168100, 0x44e283c, 0x14, 0x44feba0, 0x40adda6)
	/usr/local/go/src/testing/testing.go:961 +0x377
testing.runTests.func1(0xc000168000)
	/usr/local/go/src/testing/testing.go:1202 +0x78
testing.tRunner(0xc000168000, 0xc00014ce80)
	/usr/local/go/src/testing/testing.go:909 +0xc9
testing.runTests(0xc00015c000, 0x4ac8240, 0x29, 0x29, 0x0)
	/usr/local/go/src/testing/testing.go:1200 +0x2a7
testing.(*M).Run(0xc00010a100, 0x0)
	/usr/local/go/src/testing/testing.go:1117 +0x176
fyne.io/fyne/internal/driver/glfw.TestMain.func1(0xc00010a100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:35 +0x2b
created by fyne.io/fyne/internal/driver/glfw.TestMain
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window_test.go:34 +0x3f

goroutine 35 [chan receive]:
fyne.io/fyne/internal/driver/glfw.runOnMain(0xc0001500c0)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/loop.go:46 +0x97
fyne.io/fyne/internal/driver/glfw.(*gLDriver).createWindow(0xc000021440, 0x44d552c, 0x4, 0x44a0301, 0x404eb01, 0xc000158050)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1070 +0xcb
fyne.io/fyne/internal/driver/glfw.(*gLDriver).CreateWindow(0xc000021440, 0x44d552c, 0x4, 0x4050358, 0x49399e8d82a89)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/window.go:1062 +0x44
fyne.io/fyne/internal/driver/glfw.TestGlCanvas_Content(0xc000168100)
	/Users/stuartscott/Documents/Projects/Go/src/fyne.io/fyne/internal/driver/glfw/canvas_test.go:19 +0x68
testing.tRunner(0xc000168100, 0x44feba0)
	/usr/local/go/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:960 +0x350

rax    0x0
rbx    0x141acdc0
rcx    0x7ffeefbfdb18
rdx    0x0
rdi    0x307
rsi    0x6
rbp    0x7ffeefbfdb40
rsp    0x7ffeefbfdb18
r8     0x7ffeefbfd9e0
r9     0x7ffeefbfdbb0
r10    0x141acdc0
r11    0x246
r12    0x307
r13    0x3000000008
r14    0x6
r15    0x16
rip    0x7fff6c7857fa
rflags 0x246
cs     0x7
fs     0x0
gs     0x0
FAIL	fyne.io/fyne/internal/driver/glfw	0.655s
--- FAIL: TestCanvas_TappedSecondary (0.31s)
    canvas_test.go:108: 
        	Error Trace:	canvas_test.go:108
        	Error:      	Should be true
        	Test:       	TestCanvas_TappedSecondary
        	Messages:   	tap secondary
    canvas_test.go:109: 
        	Error Trace:	canvas_test.go:109
        	Error:      	Not equal: 
        	            	expected: *gomobile.tappableLabel(&gomobile.tappableLabel{Label:widget.Label{textProvider:widget.textProvider{BaseWidget:widget.BaseWidget{size:fyne.Size{Width:0, Height:0}, position:fyne.Position{X:3, Y:3}, Hidden:false, impl:(*widget.Label)(0xc00005a000)}, presenter:(*widget.Label)(0xc00005a000), buffer:[]int32{}, rowBounds:[][2]int{[2]int{0, 0}}}, Text:"", Alignment:0, Wrapping:0, TextStyle:fyne.TextStyle{Bold:false, Italic:false, Monospace:false}, MaxDisplayedLines:0, MinDisplayedLines:0}, tap:false, altTap:false})
        	            	actual  : <nil>(<nil>)
        	Test:       	TestCanvas_TappedSecondary
    canvas_test.go:110: 
        	Error Trace:	canvas_test.go:110
        	Error:      	Expected value not to be nil.
        	Test:       	TestCanvas_TappedSecondary
FAIL
FAIL	fyne.io/fyne/internal/driver/gomobile	1.069s
?   	fyne.io/fyne/internal/painter	[no test files]
ok  	fyne.io/fyne/internal/painter/gl	0.525s
?   	fyne.io/fyne/internal/painter/software	[no test files]
ok  	fyne.io/fyne/layout	0.289s
ok  	fyne.io/fyne/test	0.155s
ok  	fyne.io/fyne/theme	0.182s
?   	fyne.io/fyne/tools/playground	[no test files]
ok  	fyne.io/fyne/widget	4.521s
FAIL

@andydotxyz
Copy link
Member

Intermittent failures due to 'NSApp with wrong _running count' are a new issue with Catalina - not yet figured out the cause or the fix.

@andydotxyz
Copy link
Member

It is possible to add ellipsis (truncate) and hyphens (wrap w/ break) in the canvas Text objects but then they will need to know whether their text has been truncated or wrapped w/ break so either way "rowBounds [2]int" is insufficient.

canvas.Text is a single string of runes painted - so I'm not sure that hyphenating automatically makes sense as there is an implied second line in that instance. I suggested that ellipsis could be put there because it could adjust based on the object size and does not imply any overflow. Therefore it could be switched on and the result forgotten - if used carefully.

Looking at the code that renders the line (https://github.com/golang/image/blob/58c23975cae11f062d4b3b0c143fe248faac195d/font/font.go#L165) it just loops through each character in the line anyway, so moving this loop into fyne would give us the flexibility and control without compromising the performance.

By rendering I meant the OpenGL texture code. Internally it may paint characters one at a time but this is passed to the graphics card, and cached appropriately, as one texture.

There is still a bug here because Entry was hardcoded to TextAlignLeading and the code handling Cursor assumes the line always starts at theme.Padding().

I don't think this is necessary to expose alignment in Entry at this stage - it's the wrapping that this is all about :)

Fixes fyne-io#332

Applies to Label, Hyperlink, and Entry

There are three text wrapping modes;
- TextWrapOff (default)
  - Widgets are expanded to fit the text.
  - Consistent with previous behaviour.
- TextTruncate
  - Text longer than the widget's width is not displayed.
  - An ellipsis is NOT added if text gets truncated, although this
    should be considered for future (perhaps TextTruncateEllipsis).
- TextWrapBreak
  - Text longer than the widget's width is wrapped onto the next line.
  - A hyphen is NOT added if a word gets broken, although this
    should be considered for future (perhaps TextWrapOnHypenate).
- TextWrapWord
  - Text longer than the widget's width is wrapped onto the next line.
  - Text is broken on word boundaries (spaces) to avoid breaking words.
  - Text without word boundaries is broken the same as TextWrapBreak.

Added new tab to demo showcasing different wrapping modes.
@stuartmscott
Copy link
Member Author

The latest Travis run (https://travis-ci.org/github/fyne-io/fyne/builds/665231013) failed on OSX with;

An error occurred while generating the build script.

How would canvas.Text know whether to add ellipsis or not? When MinSize is called it return the minimum of the whole string of runes, are you suggesting that canvas.Text will add ellipsis if Resize is called with size.Width less than MinSize.Width?

The approach I would take is to keep canvas.Text simple - it just takes the string, size, style, x, y and renderers the text. glPainter.drawText should not be calculating the dot. The layers above, eg. textRenderer or Entry, are responsible for chopping up the text into lines and aligning them.

The canvas.Texts are cached by the textRenderer, but these get their text updated and are redraw each time the text changes.

Internally it may paint characters one at a time but this is passed to the graphics card, and cached appropriately, as one texture.

We should cache the texture, I'm talking about what happens before that, where the texture is generated and Drawer.drawString is called to render each character, instead we move that loop into glPainter.newGlTextTexture so that we iterate each character and advance the dot to space the words and characters to achieve proper text justification (not part of this PR, but a future one).

I don't think this is necessary to expose alignment in Entry at this stage - it's the wrapping that this is all about :)

Agreed, removed from this PR.

Copy link
Member Author

@stuartmscott stuartmscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review @andydotxyz

text.go Outdated

// SplitLines accepts a slice of runes and returns a slice containing the
// start and end indicies of each line delimited by the newline character.
func SplitLines(text []rune) [][2]int {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, I'll unexport it - its signature will change in future anyway with the rest of the text improvements.

text.go Outdated

// LineBounds accepts a slice of runes, a wrapping mode, a maximum line width and a function to measure line width.
// LineBounds returns a slice containing the start and end indicies of each line with the given wrapping applied.
func LineBounds(text []rune, wrap TextWrap, maxWidth int, measurer func([]rune) int) [][2]int {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, will simplify.

text.go Outdated
lines := SplitLines(text)
switch wrap {
case TextTruncate:
if maxWidth > 0 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack

text.go Outdated
for _, l := range lines {
low := l[0]
high := l[1]
if low == high {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, and that pattern can be applied to the other cases too.

@@ -21,15 +21,15 @@ func TestLabel_MinSize(t *testing.T) {
}

func TestLabel_Text(t *testing.T) {
label := &Label{Text: "Test"}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andy, supporting both NewX() and &X{} is great, the problem is with "ExtendBaseWidget". If you support &X{} then basically all "func (x *X)" need to call "x.ExtendBaseWidget(x)" which is a code smell.

I'll revert these back to &X{} for this PR.

@@ -24,15 +24,16 @@ func TestHyperlink_MinSize(t *testing.T) {
}

func TestHyperlink_Alignment(t *testing.T) {
hyperlink := &Hyperlink{Text: "Test", Alignment: fyne.TextAlignTrailing}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below

@@ -180,7 +179,7 @@ func TestEntry_OnKeyDown_Insert(t *testing.T) {
}

func TestEntry_OnKeyDown_Newline(t *testing.T) {
entry := &Entry{MultiLine: true}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below

@stuartmscott stuartmscott mentioned this pull request Mar 26, 2020
5 tasks
Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks pretty slick now. Just a few niggles on the error reporting and I think we are good to go!

widget/entry.go Outdated Show resolved Hide resolved
widget/entry.go Outdated Show resolved Hide resolved
andydotxyz
andydotxyz previously approved these changes Mar 27, 2020
@andydotxyz
Copy link
Member

Travis approves, honest: https://travis-ci.org/github/fyne-io/fyne/builds/667814891

@andydotxyz
Copy link
Member

Before I merge I wanted to check, did you feel that you wanted this to be squashed?
We normally prefer merge branches for complex stuff like this, but I can see here that lots of methods were added then moved etc so wanted to offer you the choice @stuartmscott :)

@stuartmscott
Copy link
Member Author

Thanks for asking. Now that the scroller changes are in, I am going to merge 'develop' into 'wrapping' and use the new widget.NewVerticalScrollContainer for the Lorem Ipsum Multiline Entry. Once that is pushed (and reviewed) we can either squash it into one (most of the info is in the first commit anyway), or merge all of them. I have a minor preference toward the former just to keep git history neat.

@andydotxyz
Copy link
Member

Nice idea thanks. I have run it locally and (performance aside) seems pretty slick.
Two small thoughts about the demo...

If you turn off wrap (or use truncate) the size of the window becomes absolutely huge... Is it worth using slightly shorter lorem lines so that it can be sized back down if people want?

Also perhaps the multiline entry could be expanded by the layout - for example:

	fixedText := widget.NewVBox(
		widget.NewHBox(
			radioAlign,
			layout.NewSpacer(),
			radioWrap,
		),
		label,
		hyperlink,
		entry,
		entryDisabled,
		entryMultiLine,
	)
	return fyne.NewContainerWithLayout(layout.NewBorderLayout(fixedText, nil, nil, nil),
		fixedText, entryLoremIpsumScroller)

@stuartmscott
Copy link
Member Author

You're welcome! Do you see any obvious ways to improve the performance issues from the code? Splitting the text and wrapping it is quite a chunk of work - lots of text measure calls and slice operations, but not that many memory allocations - but perhaps it is getting called too many times unnecessarily.

Lol yeah sure I'll shorten them.

Sure, although it still feels hacky to use a borderlayout to force content to take up all the space.

@andydotxyz
Copy link
Member

Sure, although it still feels hacky to use a borderlayout to force content to take up all the space.

Layouts control the size and position of objects in their containers. Some layouts expand objects, others collapse them - most do a bit of both. I'm not sure what is hacky?

@andydotxyz
Copy link
Member

Do you see any obvious ways to improve the performance issues from the code?

In the main codepaths we cache calculations that involve text measurement (by caching the result of MinSize(). Anything that can be done to measure things less is probably a good plan. I'll look into the code later on and see if I have more concrete suggestions.

@stuartmscott
Copy link
Member Author

I'm not sure what is hacky?

I just mean that a borderlayout is all about a centerpiece with other cardinal pieces, like an editor and toolbars/sidebars. But in this case it is a vertical stack of elements and so it feels like using a hammer as a screwdriver.

I'll look into the code later on and see if I have more concrete suggestions.

Cool thanks! Caching the text measurements is a good idea, but before that we should write some benchmark tests to make sure our changes are improving the performance.

@andydotxyz
Copy link
Member

I just mean that a borderlayout is all about a centerpiece with other cardinal pieces, like an editor and toolbars/sidebars. But in this case it is a vertical stack of elements and so it feels like using a hammer as a screwdriver.

Yes I see your point. Maybe we lack a layout with the type of flexiility that folk want (i.e. #4)?

@stuartmscott
Copy link
Member Author

Yeah maybe, anyway borderlayout is fyne for this demo :P

@andydotxyz
Copy link
Member

I'm happy with this and think it's good to merge, thanks. Let's work on performance though

@andydotxyz andydotxyz merged commit 467d1aa into fyne-io:develop Mar 31, 2020
@stuartmscott stuartmscott deleted the wrapping branch March 31, 2020 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add text wrap support to widget.textProvider
2 participants