rivo / tview

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

Mount/Unmount Hooks: is there something or some way to do this? #875

Open verdverm opened 1 year ago

verdverm commented 1 year ago

Context, I have "components" and pages where I'd like to only run some data / net intensive things when they are visible.

Is there some mechanism to know if/when a UI element is mounted or visible?

digitallyserviced commented 1 year ago

@verdverm

So I end up often pointing people to my fork of tview for certain things people ask about and are not actually impl'd in the vanilla tview.

You mention pages so I am going to suggest my Pages features I have expanded upon to include a set of hooks/callbacks that can be impl'd as an interface on your views for getting these sort of lifecycle events. See this link for my Page primitives interface and the.

https://github.com/digitallyserviced/tview/blob/611a26b9bad195005135a6ce0215280c68d57903/primitive.go#L92-L108


type PageChangeType int

const(
  Front PageChangeType = iota
  Back
  Refresh
  Removed
  Drawn
  Focused 
)

type Paged interface {
  Name() string
  Shown(*Pages)
  Hidden(*Pages)
  Changed(*Page, *Pages, PageChangeType)
}

Here is an example of the changes done to the methods in the Pages primitive to invoke handlers on Paged implementing primitives. You will also note in my Pages changes, the making public of the Page type, as well as changes to how the AddPage works.

AddPage has a way to add an already existing Page object or the same way as always worked with the (primitive, name, resize, visible)

https://github.com/digitallyserviced/tview/blob/611a26b9bad195005135a6ce0215280c68d57903/pages.go#L197-L214

func (p *Pages) HidePage(name string) *Pages {
    for _, page := range p.pages {
        if page.Name == name {
            page.Visible = false
      if page.Page != nil {
        page.Page.Hidden(p)
      }
            if p.changed != nil {
                p.changed()
            }
            break
        }
    }
    if p.HasFocus() {
        p.Focus(p.setFocus)
    }
    return p
}
verdverm commented 1 year ago

I actually forked tview 5 years ago to do this, adding Mount/Unmount throughout all the components.

I updated it this week and moved it here: https://github.com/hofstadter-io/hof/tree/_dev/lib/tui

Lots of extra stuff too, like a global event bus, two-way dependency injection (so modules are easy to hook up), base layout with logging & error consoles that can be shown as needed, a command bar (like bloomberd terminal) for fast access to anything... I forgot about it until just after making this issue, glad I did some archaeology!

digitallyserviced commented 1 year ago

@verdverm awesome, love seeing what people hack into to tailor stuff for their needs.

I always try to push people to not be scared to edit/hack at frameworks/libs/modules they include from other sources. Otherwise you are left to use hacky workarounds, or alter the ways to go about doing things because of the lack of the specifics needed for their use cases.

Love the charting, and other widgets you have here! I @'d you on twitter... DM me! @DevHegemony

Here is a rundown of all the things I added into my app/tview implementations...

https://github.com/rivo/tview/issues/872#issuecomment-1697571726

I will definitely check out this fork and changes, I've done quite a lot of customization to be able to get my apps working/looking the way I want them to.

demo-nvim-script