From e97629839ebad419a56f03c93a3aea3a55388637 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Fri, 24 Apr 2020 15:05:21 -0700 Subject: [PATCH] Add Application.SetBeforeFocusFunc and Application.SetAfterFocusFunc --- CHANGELOG | 1 + application.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 506a56e..70d4b85 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ v1.4.5 (WIP) - Add multithreading support - Add ContextMenu (initially supported by List) - Add List.Transform and TreeView.Transform +- Add Application.SetBeforeFocusFunc and Application.SetAfterFocusFunc - Merge upstream mouse support v1.4.4 (2020-02-24) diff --git a/application.go b/application.go index efe1ada..c360d16 100644 --- a/application.go +++ b/application.go @@ -90,6 +90,14 @@ type Application struct { // is drawn. afterResize func(width int, height int) + // An optional callback function which is invoked before the application's + // focus changes. + beforeFocus func(p Primitive) bool + + // An optional callback function which is invoked after the application's + // focus changes. + afterFocus func(p Primitive) + // An optional callback function which is invoked just before the root // primitive is drawn. beforeDraw func(screen tcell.Screen) bool @@ -738,14 +746,34 @@ func (a *Application) GetAfterResizeFunc() func(width int, height int) { // called on the new primitive. func (a *Application) SetFocus(p Primitive) *Application { a.Lock() + + if a.beforeFocus != nil { + a.Unlock() + ok := a.beforeFocus(p) + if !ok { + return a + } + a.Lock() + } + if a.focus != nil { a.focus.Blur() } + a.focus = p + if a.screen != nil { a.screen.HideCursor() } - a.Unlock() + + if a.afterFocus != nil { + a.Unlock() + + a.afterFocus(p) + } else { + a.Unlock() + } + if p != nil { p.Focus(func(p Primitive) { a.SetFocus(p) @@ -764,6 +792,30 @@ func (a *Application) GetFocus() Primitive { return a.focus } +// SetBeforeFocusFunc installs a callback function which is invoked before the +// application's focus changes. Return false to maintain the current focus. +// +// Provide nil to uninstall the callback function. +func (a *Application) SetBeforeFocusFunc(handler func(p Primitive) bool) *Application { + a.Lock() + defer a.Unlock() + + a.beforeFocus = handler + return a +} + +// SetAfterFocusFunc installs a callback function which is invoked after the +// application's focus changes. +// +// Provide nil to uninstall the callback function. +func (a *Application) SetAfterFocusFunc(handler func(p Primitive)) *Application { + a.Lock() + defer a.Unlock() + + a.afterFocus = handler + return a +} + // QueueUpdate queues a function to be executed as part of the event loop. // // Note that Draw() is not implicitly called after the execution of f as that diff --git a/go.mod b/go.mod index d8bcd0a..72ade8a 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,6 @@ require ( github.com/lucasb-eyer/go-colorful v1.0.3 github.com/mattn/go-runewidth v0.0.9 github.com/rivo/uniseg v0.1.0 - golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect + golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f // indirect golang.org/x/text v0.3.2 // indirect ) diff --git a/go.sum b/go.sum index 00ee510..1e62ae9 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY= -golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=