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

[Proposal] TextColorTo extension for ITextStyle #211

Closed
10 tasks done
PieEatingNinjas opened this issue Nov 29, 2021 · 8 comments
Closed
10 tasks done

[Proposal] TextColorTo extension for ITextStyle #211

PieEatingNinjas opened this issue Nov 29, 2021 · 8 comments
Assignees
Labels
approved This Proposal has been approved and is ready to be added to the Toolkit champion A member of the .NET MAUI Toolkit core team has chosen to champion this feature documentation approved proposal A fully fleshed out proposal describing a new feature in syntactic and semantic detail
Milestone

Comments

@PieEatingNinjas
Copy link
Contributor

PieEatingNinjas commented Nov 29, 2021

TextColorTo extension for ITextStyle

  • Proposed
  • Prototype
  • Implementation
    • iOS Support
    • Android Support
    • macOS Support
    • Windows Support
  • Unit Tests
  • Sample
  • Documentation

Link to Discussion

Extend ColorAnimationExtensions with 'TextColorTo' for ITextStyle

Summary

Extend the ColorAnimationExtenions class with a TextColorTo extension method on the ITextStyle interface, allowing developers to animate the color transition of the TextColor property of controls implementing ITextStyle.

Motivation

Currently the ColorAnimationExtensions class has 1 method BackgroundColorTo which helps animating the color transition of a VisualElement's BackgroundColor. Almost the exact same code can be re-used for this proposed TextColorTo extension method. Effort is low, value is pretty descent as ITextStyle is implemented by several controls.

Detailed Design

public static Task<bool> TextColorTo(this ITextStyle element, Color color, uint rate = 16u, uint length = 250u, Easing? easing = null)
{
	ArgumentNullException.ThrowIfNull(element);
	ArgumentNullException.ThrowIfNull(color);

	element.TextColor ??= Colors.Transparent;

	var animationCompletionSource = new TaskCompletionSource<bool>();

	try
	{
		new Animation
		{
			{ 0, 1, GetRedTransformAnimation(element, color.Red) },
			{ 0, 1, GetGreenTransformAnimation(element, color.Green) },
			{ 0, 1, GetBlueTransformAnimation(element, color.Blue) },
			{ 0, 1, GetAlphaTransformAnimation(element, color.Alpha) },
		}
		.Commit(element, nameof(TextColorTo), rate, length, easing, (d, b) => animationCompletionSource.SetResult(true));
	}
	catch (ArgumentException aex)
	{
		animationCompletionSource.SetResult(false);
	}

	return animationCompletionSource.Task;
}

static Animation GetRedTransformAnimation(ITextStyle element, float targetRed) =>
	new(v => element.TextColor = element.TextColor.WithRed(v), element.TextColor.Red, targetRed);

static Animation GetGreenTransformAnimation(ITextStyle element, float targetGreen) =>
	new(v => element.TextColor= element.TextColor.WithGreen(v), element.TextColor.Green, targetGreen);

static Animation GetBlueTransformAnimation(ITextStyle element, float targetBlue) =>
	new(v => element.TextColor = element.TextColor.WithBlue(v), element.TextColor.Blue, targetBlue);

static Animation GetAlphaTransformAnimation(ITextStyle element, float targetAlpha) =>
	new(v => element.TextColor = element.TextColor.WithAlpha(v), element.TextColor.Alpha, targetAlpha);

Usage Syntax

XAML Usage

N/A

C# Usage

var label = new Label();
await label.TextColorTo(Colors.Red, 16, 1500, Easing.SinIn);

var button = new TextButton();
await button.TextColorTo(Colors.Green, 16, 1500);

var entry = new Entry();
await entry.TextColorTo(Colors.Pink);
@PieEatingNinjas PieEatingNinjas added new proposal A fully fleshed out proposal describing a new feature in syntactic and semantic detail labels Nov 29, 2021
@PieEatingNinjas
Copy link
Contributor Author

Wouldn't mind doing the implementation (it's already up here 😅), testing and sample.

@brminnick
Copy link
Collaborator

Thanks @PieEatingNinjas! I'm happy to Champion this Proposal and we'll discuss it in our Monthly Standup this week!

After we vote (and assuming it it is approved by the team), I'll add the approved tag and assign it to you!

@brminnick brminnick self-assigned this Nov 29, 2021
@brminnick brminnick added the champion A member of the .NET MAUI Toolkit core team has chosen to champion this feature label Nov 29, 2021
@brminnick brminnick removed the new label Nov 29, 2021
@ghost ghost added approved This Proposal has been approved and is ready to be added to the Toolkit help wanted This proposal has been approved and is ready to be implemented labels Dec 2, 2021
@brminnick
Copy link
Collaborator

Approved!

Thanks @PieEatingNinjas! Assigned ✅

@brminnick brminnick added this to the v1.0.0 milestone Dec 6, 2021
@PieEatingNinjas
Copy link
Contributor Author

PieEatingNinjas commented Dec 17, 2021

So, there is a tiny little detail that we've overlooked...
ITextStyle does indeed have a property TextColor... but, it's readonly as it only defines a getter, it doesn't define a setter... 😔
As far as I can see, the set is only defined on the implementations themselves...
Any ideas on how we could tackle this, aside from reflection or needing to check the type and do a non-generic implementation for each of the standard MAUI types implementing ITextStyle?

Sorry I missed this...

@pictos
Copy link
Member

pictos commented Dec 17, 2021

@PieEatingNinjas on MAUI the interfaces just implement set when the value can be changed by the platform-specific code. So the implementation has the set and can use it normally. Do we need to access the setter?

@PieEatingNinjas
Copy link
Contributor Author

@PieEatingNinjas on MAUI the interfaces just implement set when the value can be changed by the platform-specific code. So the implementation has the set and can use it normally. Do we need to access the setter?

The idea was to write this code as an extension method for the ItextStyle interface. This would be perfectly possible - and easy to do - if the interface also exposed the setter. This is what I’d thought how I’d implement it.
Concrete implementations indeed have the set, but this would require me to check the type in the extension method and cast to the concrete implementation in order to access the setter. Possible, yes, but unfortunately this wouldn’t work for other (custom) controls implementing the ITextStyle interface.

@brminnick
Copy link
Collaborator

You're totally right, @PieEatingNinjas!

I decided that the best way to implement this is to use source generators. This allows us to generate a TextColorTo method for each class that implements ITextStyle. And it ensures that any new classes created by the .NET MAUI team that implement ITextStyle will also be supported.

I just opened the PR and I'd love for you to give it a review! #224

@brminnick brminnick removed the help wanted This proposal has been approved and is ready to be implemented label Dec 18, 2021
@PieEatingNinjas
Copy link
Contributor Author

You're totally right, @PieEatingNinjas!

I decided that the best way to implement this is to use source generators. This allows us to generate a TextColorTo method for each class that implements ITextStyle. And it ensures that any new classes created by the .NET MAUI team that implement ITextStyle will also be supported.

I just opened the PR and I'd love for you to give it a review! #224

I’ll be happy to take a look at it as soon as I can. Curious to see how you used source generators for this. Thanks!

@ghost ghost closed this as completed May 19, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Nov 23, 2024
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
approved This Proposal has been approved and is ready to be added to the Toolkit champion A member of the .NET MAUI Toolkit core team has chosen to champion this feature documentation approved proposal A fully fleshed out proposal describing a new feature in syntactic and semantic detail
Projects
None yet
Development

No branches or pull requests

4 participants