rivo / tview

Terminal UI library with rich, interactive widgets — written in Golang
MIT License
11.17k stars 574 forks source link

Focus callback not called when a form receives focus? #869

Open adrianludwin opened 1 year ago

adrianludwin commented 1 year ago

Hi, I have a form in a grid layout, and I'd like the form to be highlighted when it has focus. For Lists, I was able to set the Focus/Blur callback to change the background colour, but this didn't seem to work for the Form. I believe this is because, while Box.Focus() calls the callback, Form.Focus() does not.

Would it be possible/advisable to call the callback in the form before passing the focus to the FormItem? After all, Form.HasFocus() returns true if any of its items have focus, so it might make sense for the callback to be called too. But I don't know what the implications of this are, or whether Blur() would be called properly as well.

carpii commented 1 year ago

Facing a similar issue with flex too #870

I'll keep mine open for now, just because it contains some sample code to repro

digitallyserviced commented 1 year ago

@carpii @adrianludwin

Hi guys, so this is another one of those things that you come across that the base framework just doesn't have a good way to handle.

I want to point you at the fork of mine that would provide a way to handle any case of focus changing, among many other additions, which may or may not be helpful.

https://github.com/digitallyserviced/tview/blob/611a26b9bad195005135a6ce0215280c68d57903/application.go#L939-L956

// 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) {
    a.Lock()
    defer a.Unlock()
    a.beforeFocus = handler
}
// 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)) {
    a.Lock()
    defer a.Unlock()
    a.afterFocus = handler
}

So these functions allow additional handlers to be defined for when focus within your app changes. You can then use the handler to invoke/manipulate whatever is in it's scope. You can use this to force an invocation of Focus onto the form's Box, or anything else that you can stuff into what your handler should do.

These functions are just for show, but also require more code that is in application.go you can see in the link.

Hopefully this can get you guys into a better position for what you are trying to do. My fork also has many more additions that I believe were missing within the base tview.

Any questions or additional assistance can be directed at my twitter/discord in my profile.

https://github.com/digitallyserviced/tview/tree/digitally