mirror of
https://github.com/rivo/tview.git
synced 2026-04-26 13:25:51 +03:00
[GH-ISSUE #225] Feature request: add title or text Spinner (example included) #174
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/tview#174
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @dguendisch on GitHub (Jan 16, 2019).
Original GitHub issue: https://github.com/rivo/tview/issues/225
Would be cool to have a title or text Spinner for e.g. a
Boxindicating that a (potentially long) operation is currently being executed. Maybe a more basic primitive would be even more suitable (e.g. to have Spinner in a status bar, etc).I currently get by myself with this simple function:
@Sacules commented on GitHub (Jan 18, 2019):
I'd be very interested in something like this :)
@rivo commented on GitHub (Jan 22, 2019):
There was a similar request previously for a progress bar, see #83, but it sounds like this is not what you are looking for.
I agree this would be useful. I'm just not yet sure what this should look like. I don't think it should become part of the title as in your example. Maybe the bottom of a box frame could be used to display the status?
Any suggestions?
@dguendisch commented on GitHub (Jan 22, 2019):
Yeah, it's just a busy indicator (e.g. doing a network request and waiting for the result), so a progress bar would be hard to "progress" and overkill in terms of screen size :)
I saw that title spinner here and liked it pretty much, but I wouldn't mind where it is placed, but should be specific to some box (to indicate that this part of the screen is working hard / awaiting updates)
Your idea about the bottom box frame points me to another question (mostly about efficiently using the screen space): is it possible to customize that bottom part? E.g. I would love to be able to place some short status information there to avoid adding an extra line for this.
@Sacules commented on GitHub (Feb 2, 2019):
I am using a flex with a
TextFieldat the bottom as a status bar of sorts, and works fine by sending messages from other goroutines. The only gotcha is that it calls toApplication.Drawdirectly instead of wrapping the messages withQueueUpdateDraw, since doing so blocks the screen when other queue events are present and draws everything at once, which can sometimes delete messages or make them appear later than they should have.@diamondburned commented on GitHub (Apr 22, 2019):
I've tried doing this, and it's a lot harder than it seems, going with the "proper implementation" of using a Primitive. The issue is, you can't manually call Draw() as the Primitive, which means you can't periodically redraw the Primitive with the proper loading animation. Maybe a
Start(screen tcell.Screen)method would do, but I decided to stop.@mpictor commented on GitHub (May 15, 2020):
I believe when I've seen text spinners in the past, they've been at the end of a line of text.
That's how I implemented it on an LCD (not that you have much choice on a 2x20 char display...)
If curious, that code is here.
@ghostsquad commented on GitHub (Jun 17, 2020):
I'm interested in the finer details of the concurrency issues that are involved here. I'm new to using this package and I'm starting down a similar path. Here's the relevant code bits I'm playing with (just as a test):
@Sacules can you describe more about the problem you mentioned?
@diamondburned can you go into more detail here?
@diamondburned commented on GitHub (Jun 17, 2020):
The issue is precisely this:
In this code, the caller must explicitly set up the control flow of the spinner, which in your case, is a background loop to draw (which isn't implemented correctly.
A good hack around this would be to have Spinner take its own reference on draw:
@ghostsquad commented on GitHub (Jun 17, 2020):
Interesting. I'm not sure how a background loop to cause the app to redraw is a problem.
In your snippet, what happens when the terminal is resized? or some other event changes the layout?
@diamondburned commented on GitHub (Jun 17, 2020):
It's a problem, because unlike other widgets which you add to a container and not have to worry about when it will be drawn, you have to explicitly state when this widget should be drawn.
I don't see an issue here. The library already updates the widget layouts accordingly using other callbacks that are in
tview.Primitive, andDrawonly reads them.@ghostsquad commented on GitHub (Jun 18, 2020):
So what if you set the text, and use the OnChanged of textview to redraw?
@ghostsquad commented on GitHub (Jun 18, 2020):
Oh because setText isn't thread safe
@diamondburned commented on GitHub (Jun 18, 2020):
Nothing is thread-safe except for the Draw call, really, so my code wouldn't work either. There should be a way to trigger a draw in a thread-safe way otherwise.
Another option would probably be to make tview redraw even when it doesn't have to (or it doesn't know that it has to, since there's no explicit call), but this sounds wasteful.
@ghostsquad commented on GitHub (Jun 19, 2020):
Ya, ok, so I think I understand now. Basically, the problem is that by forcing the application to redraw in a goroutine, and by not having much in the way of thread safety, it impedes the ability for other parts of the application to "setup" some set of changes that they want to display, without drawing until it's done it's operation. A redraw part way through that "setup" would definitely cause some weird behavior to occur.
So, I was thinking more on this, and had a thought experiment where, what if you didn't need to tell the whole application to redraw (except when the terminal was resized, or on other specific events). You only needed to tell specific sub-components to redraw. This is similar to like the virtual-dom used by React in browsers.
@diamondburned commented on GitHub (Jun 19, 2020):
That's what my snippet above does. Except it's harder in a terminal environment. Technically, the code above has a possible race condition, for example when the primitive is asked to set a new size while it's being drawn inside that loop.
It's hard to make a comparison to browser DOM APIs, as they already abstracted all that for you. React's virtual DOM is to get the difference between DOM nodes; it doesn't differentiate pixels to draw on the screen. The browser does that for you.
@SamWhited commented on GitHub (Nov 23, 2024):
I was working on implementing something that needed a progress indicator in tview today and found this issue while searching to see if a solution already existed.
It's worth noting that ascii-art and unicode-based progress spinners are often read incorrectly by screen readers and are inaccessible to many users [1]. It may be good to do this as a plain text progress indicator, or with a plain text fallback if we really want the fancy animation, ie. something that actually says "50%" or something along those lines that can be read by screen readers.
1: https://dl.acm.org/doi/fullHtml/10.1145/3411764.3445544#sec-28