Skip to content
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 support for env variable TEXTUAL_ANIMATIONS #4062

Merged
merged 17 commits into from
Feb 19, 2024

Conversation

rodrigogiraoserrao
Copy link
Contributor

Adds support for the environment variable TEXTUAL_ANIMATIONS, which dictates which animations take place in Textual apps.
(Kind of like a log level but for animations.)

Fixes #3992.

Go over 'all' (as far as I can tell) animations in Textual. Most of them should only run when the env variable TEXTUAL_ANIMATIONS is set to FULL.
A few animations may run on the level BASIC, which are animations that don't delay content appearing:
 - indeterminate progress bars
 - loading indicators
 - button presses
 - tab underlines
 - switch toggles
 - all (?) types of scrolling.

These animations are completely disabled when the env var is NONE.

The indeterminate progress bar displays a full, static bar and the loading indicator displays a string 'Loading...'.

Many animation-related methods also grew a keyword parameter 'animate_on_level' that establishes the minimum level for said animation to take place.
@rodrigogiraoserrao rodrigogiraoserrao changed the title Textual animations Add support for env variable TEXTUAL_ANIMATIONS Jan 23, 2024
By using 'constants.SHOW_ANIMATIONS' instead of importing the constant directly we make it easier to patch for testing.

See: https://mathspp.com/blog/til/patching-module-globals-with-pytest
The original issue (#3992) asked for a property on 'App' that allows controlling whether that app's animations should be played or not.
Check that animations that should happen on the BASIC level do happen at that level and don't happen on the NONE level.
@rodrigogiraoserrao rodrigogiraoserrao marked this pull request as ready for review January 25, 2024 18:35
Copy link
Collaborator

@willmcgugan willmcgugan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you animate something, you only really need to tell the animation system if it is a basic animation that doesn't slow down the UI, or a more gratuitous animation that is just because it looks cool.

This makes having a bool with 3 values seem superfluous.

I would think that when calling animate, you would specify "basic" or "full".

Something like.

self.animate("x", 50, level="basic")

Where the default would be "full".

Note that I don't think we should use Enums in the public interface (see comments in the code).

src/textual/_animator.py Outdated Show resolved Hide resolved
src/textual/constants.py Outdated Show resolved Hide resolved

def __call__(self, time: float) -> bool:
if self.duration == 0:
if (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where we need the app.show_animations. Could we pass it to __call__ ?

Alternatively, do we even need to do this logic here? The animator calls this method. Could we not perform this logic from the animator? The animator has a reference to the app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could perform the logic there but I think it's cleaner here.
If we do it on the animator, then we also need to set the attribute to its value in the animator and I think it'll look clunky there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to elaborate on "cleaner" and "clunky" which are quite subjective terms.

It does feel like it is the animators job to decide if to animate something. Perhaps an Animation object should grow a finalize method which sets the attribute to its final stage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While addressing your other remarks I think this stopped being a problem.

src/textual/app.py Outdated Show resolved Hide resolved
src/textual/css/scalar_animation.py Outdated Show resolved Hide resolved
src/textual/widgets/_tabs.py Outdated Show resolved Hide resolved
src/textual/_animator.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@willmcgugan willmcgugan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few suggestions

src/textual/css/scalar_animation.py Outdated Show resolved Hide resolved
factor = min(1.0, (time - self.start_time) / self.duration)
eased_factor = self.easing(factor)

if eased_factor >= 1:
if (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this sets the value to its final position, but what is to prevent the animator calling it multiple times? Anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. The return True tells the animator the animation was completed, which means that the animation will have its "on complete callback" called (if there's any) and then the animator gets rid of the animation:

animation_complete = animation(animation_time)
if animation_complete:
del self._animations[animation_key]
if animation.on_complete is not None:
animation.on_complete()

src/textual/widgets/_button.py Outdated Show resolved Hide resolved
src/textual/widgets/_loading_indicator.py Show resolved Hide resolved
@rodrigogiraoserrao
Copy link
Contributor Author

A few suggestions

@willmcgugan addressed 👌

@rodrigogiraoserrao rodrigogiraoserrao merged commit 0fabb97 into main Feb 19, 2024
20 checks passed
@rodrigogiraoserrao rodrigogiraoserrao deleted the textual-animations branch February 19, 2024 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Env var to modify animation
2 participants