-
Notifications
You must be signed in to change notification settings - Fork 815
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
Add style variations to the progress bar widget #3143
Conversation
Hi @petertalaber Any chance of some screenshots of the variants? |
Adding @rodrigogiraoserrao |
Just to be clear, does the rainbow variant change colours as the progress increases, or are the colours changing regardless of the progress advancing? |
It will change colors as the progress increases. In the example above it will start from blue via cyan, green, orange up to red according to the color circle in counterclockwise direction. The starting and ending color can be configured and this range is divided proportional to the percentage to show the proper color. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your work!
I've left some questions and remarks, mostly about style – so that this code fits with the rest of the code base.
Feel free to ping me or re-request a review when you are done going through my comments.
src/textual/widgets/_progress_bar.py
Outdated
) | ||
return colorscheme | ||
|
||
def validate_thickness(self, thickness: int) -> int: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you create the literal type for valid thicknesses and the set of valid options, they can be used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I said "it can be used here", I also meant in the typing sense; something like
def validate_thickness(self, thickness: int) -> int: | |
def validate_thickness(self, thickness: int) -> BarThickness: |
src/textual/widgets/_progress_bar.py
Outdated
self._colorscheme = colorscheme | ||
self._thickness = thickness |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docstrings, please.
Also, how do you feel of making these attributes reactives?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it enough for those to be reactive only in Bar class and be normal variables in ProgressBar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If they're normal variables in the progress bar, then if someone does something like progress_bar.thickness = 2
, that won't updated automatically the thickness of the progress bar because Textual has no way of knowing that it should also update the thickness of the bar renderable.
644ce92
to
10a8bde
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work on implementing the changes, thanks.
I have a couple of follow-up questions.
src/textual/widgets/_progress_bar.py
Outdated
) | ||
return colorscheme | ||
|
||
def validate_thickness(self, thickness: int) -> int: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I said "it can be used here", I also meant in the typing sense; something like
def validate_thickness(self, thickness: int) -> int: | |
def validate_thickness(self, thickness: int) -> BarThickness: |
src/textual/widgets/_progress_bar.py
Outdated
@@ -59,9 +79,15 @@ class Bar(Widget, can_focus=False): | |||
"""The percentage of progress that has been completed.""" | |||
_start_time: float | None | |||
"""The time when the widget started tracking progress.""" | |||
color_scheme = reactive(_DEFAULT_BAR_COLOR_SCHEME) | |||
"""The color scheme of the widget.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""The color scheme of the widget.""" | |
"""The color scheme of the rule.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope you don't mind me sticking my nose in, but shouldn't this be "bar" rather than "rule"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bar is OK.
src/textual/widgets/_progress_bar.py
Outdated
color_scheme = reactive(_DEFAULT_BAR_COLOR_SCHEME) | ||
"""The color scheme of the widget.""" | ||
thickness = reactive(_DEFAULT_BAR_THICKNESS) | ||
"""The thickness of the widget.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""The thickness of the widget.""" | |
"""The thickness of the rule.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto #3143 (comment)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
if color_scheme is None: | ||
color_scheme = _DEFAULT_BAR_COLOR_SCHEME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the idea is that setting to None
falls back to the default value? (And same thing for the thickness
?)
If so, I think you should mention that in the docstrings for the reactives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It is easier to use I guess if we don't have to deal with default constants around the code. If not set Bar will turn None into the default value.
I'll see if I can get someone else from the team to review this. |
Sure. That Textual on the web seems cool. Don't bother with this. You will check this patch when you have time again. |
- Rainbow scheme will update bar color based on percentage starting from .bar--bar.color up to .bar--complete.color in counterclockwise direction. - Bar thickness can have 3 styles: thin, normal or thick.
I'm giving this an initial review, and I'm a wee bit confused by the files being used for the docs, especially when it comes to the stylesheets. There seems to be some tcss files that contain things that aren't illustrated in the example screenshot/code, and there also seems to be at least one instance of a stylesheet missing: There's no screenshot in this, just code, and no stylesheet. Would it be possible to get a once over of the state of the files in the documentation, and perhaps be sure that each of the files just contain what's necessary to show off what's being illustrated. As an aside, there looks to be a couple of files named with a trailing underscore; is there a reason for that? |
def key_9(self) -> None: | ||
self._action_common_keypress(90) | ||
|
||
def _action_common_keypress(self, progress: int) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit of a nit-pick, but given that this is intended for the docs, I think I'd be tempted to write this as slightly more idiomatic Textual code, using BINDINGS
and calling on the action.
def key_2(self) -> None: | ||
self._action_common_keypress(2) | ||
|
||
def _action_common_keypress(self, thickness: int) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in another file: I think I'd be tempted to do this with BINDINGS
and the action, it feels like it would be more "normal" for Textual code.
## Styling the Progress Bar | ||
|
||
The progress bar is composed of three sub-widgets that can be styled independently: | ||
|
||
| Widget name | ID | Description | | ||
| ------------------ | ------------- | ---------------------------------------------------------------- | | ||
| `Bar` | `#bar` | The bar that visually represents the progress made. | | ||
| `Bar` | `#bar` | Bar that visually represents the progress made. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there a specific reason for changing this? I feel it reads better before the change.
@@ -125,9 +188,9 @@ The progress bar is composed of three sub-widgets that can be styled independent | |||
|
|||
| Name | Type | Default | Description | | |||
| ------------ | ------- | ------- | ------------------------------------------------------------------------------------------------------- | | |||
| `percentage` | `float | None` | The read-only percentage of progress that has been made. This is `None` if the `total` hasn't been set. | | |||
| `percentage` | `float` | `None` | The read-only percentage of progress that has been made. This is `None` if the `total` hasn't been set. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type looks to be wrong here, if percentage
can be None
then the type should be float | None
.
| `progress` | `float` | `0` | The number of steps of progress already made. | | ||
| `total` | `float | None` | The total number of steps that we are keeping track of. | | ||
| `total` | `float` | `None` | The total number of steps that we are keeping track of. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type looks wrong here, of total
can be None
then the type should be float | None
.
|
||
Args: | ||
destination: Another color. | ||
factor: A blend factor, -1 -> 1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: I'd spell out that it's "between -1 and 1", and perhaps make clear if it's exclusive or inclusive.
@davep the trailing underscores are there on purpose: Does this make sense? Do you have a better idea of how this can be accomplished? |
Ahh hah! Okay, that makes more sense. |
I think this is probably too large of a change for too little benefit. Closing, with apologies to @petertalaber . Thanks for your hard work. |
Fixes #2920.