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

SelectableTextBlock does not update theme correctly if it contains a LineBreak #12404

Open
SamVanheer opened this issue Jul 31, 2023 · 5 comments

Comments

@SamVanheer
Copy link

Describe the bug
If you have a SelectableTextBlock with a LineBreak in it, changing the application theme using Application.Current.RequestedThemeVariant does not update the text block theme. It only updates when the block is clicked on.

To Reproduce
Create a window containing this XAML:

<SelectableTextBlock>
    Foo bar<LineBreak/>
    baz
</SelectableTextBlock>

Add a method of changing the theme at runtime, build and run and change the theme.

Expected behavior
The theme updates immediately when changed.

Screenshots
image

Desktop (please complete the following information):

  • OS: Windows 10
  • Version 11.0.2

Additional context
A minimal reproduction can be found here: https://github.com/SamVanheer/AvaloniaSelectableTextBlockBug

@SamVanheer
Copy link
Author

I tested this again and it looks like what's actually happening is the text color is using the opposite color of what it should be. When switching to light theme the text color is white, when switching to dark theme the text color is black. So this might just be a case of the wrong color being used to update the text color?

I don't see any XAML definition for TextBlock and SelectableTextBlock doesn't specify a color for the foreground color so maybe it's inheriting the background color here?

Assuming i understand themes correctly:
TextBox defines the foreground color in this file: https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml
And SelectableTextBlock doesn't define that color here: https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Themes.Fluent/Controls/SelectableTextBlock.xaml
There is no TextBlock version.

Would adding a definition in the relevant XAML file fix this?

@timunie
Copy link
Contributor

timunie commented Oct 17, 2023

@SamVanheer you can give it a try by cloning the source and add a test case into src/samples/Sandbox. Then add the xaml as suggested and test if that fixes the issue. If yes, a PR is welcome imo.

@SamVanheer
Copy link
Author

I tried that, it's not the XAML that's at fault.

I traced through the code to see what's happening and i think i've found the problem.

This is where the color is passed into the TextLayout object that actually renders the text:

protected virtual TextLayout CreateTextLayout(string? text)
{
var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
var defaultProperties = new GenericTextRunProperties(
typeface,
FontSize,
TextDecorations,
Foreground);
var paragraphProperties = new GenericTextParagraphProperties(FlowDirection, TextAlignment, true, false,
defaultProperties, TextWrapping, LineHeight, 0, LetterSpacing)
{
LineSpacing = LineSpacing
};
ITextSource textSource;
if (_textRuns != null)
{
textSource = new InlinesTextSource(_textRuns);
}
else
{
textSource = new SimpleTextSource(text ?? "", defaultProperties);
}
return new TextLayout(
textSource,
paragraphProperties,
TextTrimming,
_constraint.Width,
_constraint.Height,
MaxLines);
}

If a LineBreak or other such element exists in the text then _textRuns is not null, so the existing runs are used. If it's null then the new color is passed in along with the default properties object.

What needs to happen here is the _textRuns objects need their color to be updated. Where exactly this should happen i don't know since i'm not familiar with how theme changes ripple through the codebase.

@timunie
Copy link
Contributor

timunie commented Oct 19, 2023

@SamVanheer thx for looking into. Maybe this helps @Gillibald to find the root cause here

@SamVanheer
Copy link
Author

I've managed to find a workaround that involves doing this after changing the theme:

Dispatcher.UIThread.Post(() =>
        {
            DescriptionText.IsVisible = false;
            DescriptionText.IsVisible = true;
        });

Obviously this isn't a great way to deal with the problem but as a temporary workaround it should suffice.

I think this works because the element redraws itself before it updates itself. For some reason the update doesn't trigger another redraw operation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants