MahApps / MahApps.Metro

A framework that allows developers to cobble together a better UI for their own WPF applications with minimal effort.
https://mahapps.com
MIT License
9.32k stars 2.45k forks source link

BackgroundToForegroundConverter and AccentColor #2081

Open superlloyd opened 9 years ago

superlloyd commented 9 years ago

Somewhere that is using a BackgroundToForegroundConverter to find the text color I am using an AccentColorBrush4 for the background.

Unfortunately AccentColor is dark but brush 4 is very transparent. It ends up with white text on whitish color

Shouldn't BackgroundToForegroundConverter consider the Backround's .Alpha value to calculate the foreground color?!

Evangelink commented 5 years ago

I was first thinking to say that if the alpha channel is beneath some value we could force the black color but doing so only solve part of the problem. Because of the transparency what matters is actually the color of the element behind...

Let's take an example, assuming you use the following code:

<Grid x:Name="MyGrid" Background="{DynamicResource AccentColorBrush4}">
    <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit." VerticalAlignment="Center" HorizontalAlignment="Center"
               Foreground="{Binding ElementName=MyGrid, Path=Background, Converter={x:Static Converters:BackgroundToForegroundConverter.Instance}}" />
</Grid>

Here are the rendered views:

Dark theme: dark theme

Light theme: light theme

Evangelink commented 5 years ago

@punker76 Do you have any tip on how I could retrieve the control on which the color is applied? This would help me walk up the visual tree until I find a not so transparent background to take a decision.

Alternatively, we could say that if the color is transparent we decide about white or black based on the theme. Obviously this isn't ideal neither but it might solve a few more cases than the current implementation.

timunie commented 5 years ago

Just a thougt:

if we change the way the accentcolor is generated to a solid shader like M$ Office does it, we can determin the brightness of the color and decide which foregroundcolor is needed. I found a way to create different color shades, see: https://github.com/MahApps/MahApps.Metro/issues/2805#issuecomment-509602334

Happy coding Tim

punker76 commented 5 years ago

@timunie I have my thoughts here https://github.com/MahApps/MahApps.Metro/commit/3098dca1c364226c312343ea59e6f6d02c183711?diff=unified This is only a test for my final solution. I will create a behavior which can be used on any element. This behavior will look for a non alpha background or will use a property which can be set.

timunie commented 5 years ago

@punker76 just for my understanding, is there a benefit using transparent Brushes over calculating a brighter / lighter AccentColor? (Except that we would need to change all the themes... I would help with this ...).

Your code for calculating the CompositeColor seems to work quite well 😄 : image

@punker76 If you want to I could upload my test app.

Happy coding Tim

punker76 commented 5 years ago

@timunie That's the main reason that we must respect the alpha channel, because all accent brushes and colors are transparent, except the AccentBaseColor and HighlightColor.

timunie commented 5 years ago

@punker76 but what is the reason not to change the way the AccentColors are calculated?

timunie commented 5 years ago

I will try a few things and let you know if it works or not :-)

timunie commented 5 years ago

@punker76 We can use your CompositeColor to calculate the AccentBrushes For the first try I did it that way:

        public SolidColorBrush NewAccent1 => new SolidColorBrush(CompositeColor((Color)App.Current.FindResource("WhiteColor"), (Color)App.Current.FindResource("AccentColor")));
        public SolidColorBrush NewAccent2 => new SolidColorBrush(CompositeColor((Color)App.Current.FindResource("WhiteColor"), (Color)App.Current.FindResource("AccentColor2")));
        public SolidColorBrush NewAccent3 => new SolidColorBrush(CompositeColor((Color)App.Current.FindResource("WhiteColor"), (Color)App.Current.FindResource("AccentColor3")));
        public SolidColorBrush NewAccent4 => new SolidColorBrush(CompositeColor((Color)App.Current.FindResource("WhiteColor"), (Color)App.Current.FindResource("AccentColor4")));

It works for Dark (Left side: current Brushes, right side: new Brushes): image

And Light (Left side: current Brushes, right side: new Brushes):: image

I will use this way in my App, beacause it solves a couple of Problems I have with the current transparent Brushes. Thank you for sharing your idea!

I could also update my PR #3515 if you want me to.

Happy coding Tim

amkuchta commented 5 years ago

Out of curiosity, has this been given any more thought? And what if we took an easier way out?

With the new GeneratorParameters.json file under \Styles\Themes\, what if we denoted Dark and Light versions of each accent there, then called the proper accent based on the currently loaded theme?

"ColorSchemes": [{
  "Name": "Amber",
    "Values": {
      "MahApps.Colors.AccentBase.Dark": "",
      "MahApps.Colors.AccentBase.Light": "",
      "MahApps.Colors.Accent.Dark": ",
      "MahApps.Colors.Accent.Light": ",
      "MahApps.Colors.Accent2.Dark": "",
      "MahApps.Colors.Accent2.Light": "",
      "MahApps.Colors.Accent3.Dark": "",
      "MahApps.Colors.Accent3.Light": "",
      "MahApps.Colors.Accent4.Dark": "",
      "MahApps.Colors.Accent4.Light": "",
      "MahApps.Colors.Highlight.Dark": ""
      "MahApps.Colors.Highlight.Light": ""
      }
    },

The only downside I see for this is that users will have to define their own set of accent values for custom themes, but they could easy just copy the provided accents and renamed them (e.g. if I am creating a Black theme, I could copy MahApps.Colors.AccentBase.Dark and rename it to MahApps.Colors.AccentBase.Black, keeping the same value.

Just a thought!

timunie commented 5 years ago

Hello @amkuchta I think that this will lead to much work because you cannot (as far as I know) easily get a lighter or darker color, except if you alter the alpha value. You have to calculate all the values.

I myself use my own implementation of the Thememanager where I calculate the AccentColors by one color of users choise and a boolean value UseDarkMode. I would share my code or update this PR #3515 if I were ask to do.

Happy coding Tim

amkuchta commented 5 years ago

@timunie it would definitely be a lot of work up-front, but my thought is as follows:

  1. Open MetroDemo
  2. Select the Light theme
  3. Navigate to the Colors Tab
  4. Use a ColorPicker with an eyedropper selection tool to extract the non-alpha interpretation of each Accent brush
  5. Select a new accent color, repeat step 4
  6. Select the Dark Theme, repeat Steps 4 and 5

Realistically, the entire dictionary could be built in about an hour or so - I might be able to knock it out tonight as a proof-of-concept, if you'd like to see what I have in mind (that is, get the new GeneratorParameters.json file generated as a proof-of-concept, not the entire solution - that would take a bit longer)

timunie commented 5 years ago

@amkuchta you don't need to provide a sample for me. I understand what you are talking about. In my mind it is the best way of calculating the accents when they are needed. It is fast and as far as i can tell from my app quite stable and, for me the most important thing, really individual if you want it. You can also use a predifined list of colors.

Together with a color picker my useres like it. I am working on a color picker, too (see #3520 ). Maybe it will be integrated someday in MahApps (@punker76 will decide this after releasing of v2)

Happy coding Tim