Skip to content

Commit a346c1e

Browse files
committed
feat: improve MainWindow gradient
refactor: improve ColorUtils refactor: refactor ThemeColor
1 parent cef0d2b commit a346c1e

6 files changed

Lines changed: 66 additions & 110 deletions

File tree

src/ByteSync.Client/Business/Themes/ColorScheme.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,7 @@ public ColorScheme(ThemeModes themeMode)
7979
public SolidColorBrush StatusMainBackGroundBrush { get; set; }
8080
public SolidColorBrush StatusSecondaryBackGroundBrush { get; set; }
8181
public SolidColorBrush VeryLightGrayBrush { get; set; }
82+
83+
public Color MainWindowTopColor { get; set; }
84+
public Color MainWindowBottomColor { get; set; }
8285
}

src/ByteSync.Client/Business/Themes/ThemeColor.cs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
namespace ByteSync.Business.Themes;
1+
using ByteSync.Helpers;
2+
3+
namespace ByteSync.Business.Themes;
24

35
public class ThemeColor
46
{
57
public ThemeColor(string hexaColor)
68
{
79
HexaColor = hexaColor;
8-
SystemColor = ColorUtils.FromHex(HexaColor);
9-
AvaloniaColor = FromSystemColor(SystemColor);
10+
AvaloniaColor = ColorUtils.FromHex(HexaColor);
1011
InitializeHSV();
1112
}
1213

13-
public ThemeColor(System.Drawing.Color systemColor)
14+
public ThemeColor(Avalonia.Media.Color color)
1415
{
15-
SystemColor = systemColor;
16-
HexaColor = ColorUtils.ToHex(systemColor);
17-
AvaloniaColor = FromSystemColor(SystemColor);
16+
HexaColor = ColorUtils.ToHex(color);
17+
AvaloniaColor = color;
1818
InitializeHSV();
1919
}
2020

2121
private void InitializeHSV()
2222
{
23-
ColorUtils.ColorToHSV(SystemColor, out double hue, out double saturation, out double value);
23+
ColorUtils.ColorToHsv(AvaloniaColor, out double hue, out double saturation, out double value);
2424
Hue = hue;
2525
Saturation = saturation;
2626
Value = value;
@@ -30,29 +30,23 @@ private void InitializeHSV()
3030

3131
public Avalonia.Media.Color AvaloniaColor { get; }
3232

33-
public System.Drawing.Color SystemColor { get; }
34-
3533
public double Hue { get; private set; }
3634

3735
public double Saturation { get; private set; }
3836

3937
public double Value { get; private set; }
4038

41-
42-
private Avalonia.Media.Color FromSystemColor(System.Drawing.Color color)
43-
{
44-
return Avalonia.Media.Color.FromArgb(color.A, color.R, color.G, color.B);
45-
}
39+
4640

4741
public ThemeColor WithHue(double hue)
4842
{
49-
var newSystemColor = ColorUtils.ColorFromHSV(hue, this.Saturation, this.Value);
43+
var newSystemColor = ColorUtils.ColorFromHsv(hue, this.Saturation, this.Value);
5044
return new ThemeColor(newSystemColor);
5145
}
5246

5347
public ThemeColor WithSaturationValue(double saturation, double value)
5448
{
55-
var newSystemColor = ColorUtils.ColorFromHSV(this.Hue, saturation, value);
49+
var newSystemColor = ColorUtils.ColorFromHsv(this.Hue, saturation, value);
5650
return new ThemeColor(newSystemColor);
5751
}
5852

@@ -61,7 +55,7 @@ public ThemeColor AdjustSaturationValue(double saturationPercent, double valuePe
6155
double newSaturation = ComputeAdjustedValue(this.Saturation, saturationPercent);
6256
double newValue = ComputeAdjustedValue(this.Value, valuePercent);
6357

64-
var newSystemColor = ColorUtils.ColorFromHSV(this.Hue, newSaturation, newValue);
58+
var newSystemColor = ColorUtils.ColorFromHsv(this.Hue, newSaturation, newValue);
6559
return new ThemeColor(newSystemColor);
6660
}
6761

Lines changed: 40 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
using System;
2-
using System.Drawing;
1+
using Avalonia.Media;
32

4-
namespace ByteSync.Common.Helpers;
3+
namespace ByteSync.Helpers;
54

65
public static class ColorUtils
76
{
@@ -25,7 +24,7 @@ public static Color FromHex(string hexColor)
2524
Color color;
2625
if (bytes.Length == 3)
2726
{
28-
color = Color.FromArgb(bytes[0], bytes[1], bytes[2]);
27+
color = Color.FromArgb(255, bytes[0], bytes[1], bytes[2]);
2928
}
3029
else if (bytes.Length == 4)
3130
{
@@ -47,17 +46,9 @@ public static string ToHex(Color color)
4746
public static int GetHexVal(char hex)
4847
{
4948
int val = (int)hex;
50-
//For uppercase A-F letters:
51-
//return val - (val < 58 ? 48 : 55);
52-
//For lowercase a-f letters:
53-
//return val - (val < 58 ? 48 : 87);
54-
//Or the two combined, but a bit slower:
5549
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
5650
}
5751

58-
59-
// http://csharphelper.com/blog/2016/08/convert-between-rgb-and-hls-color-models-in-c/
60-
6152
public static void RgbToHls(Color color, out double h, out double l, out double s)
6253
{
6354
RgbToHls(color.R, color.G, color.B, out h, out l, out s);
@@ -104,19 +95,6 @@ public static void RgbToHls(int r, int g, int b, out double h, out double l, out
10495
}
10596
}
10697

107-
public static Color HlsToRgb(double h, double l, double s)
108-
{
109-
byte r;
110-
byte g;
111-
byte b;
112-
113-
HlsToRgb(h, l, s, out r, out g, out b);
114-
115-
Color color = Color.FromArgb(r, g, b);
116-
117-
return color;
118-
}
119-
12098
// Convert an HLS value into an RGB value.
12199
public static void HlsToRgb(double h, double l, double s, out byte r, out byte g, out byte b)
122100
{
@@ -156,69 +134,49 @@ private static double QqhToRgb(double q1, double q2, double hue)
156134
return q1;
157135
}
158136

159-
// https://stackoverflow.com/questions/3722307/is-there-an-easy-way-to-blend-two-system-drawing-color-values
160-
/// <summary>Blends the specified colors together.</summary>
161-
/// <param name="color">Color to blend onto the background color.</param>
162-
/// <param name="backColor">Color to blend the other color onto.</param>
163-
/// <param name="amount">How much of <paramref name="color"/> to keep,
164-
/// “on top of” <paramref name="backColor"/>.</param>
165-
/// <returns>The blended colors.</returns>
166-
public static Color Blend(Color color, Color backColor, double amount)
137+
public static Color BlendWithTransparency(Color baseColor, Color overlayColor, double opacity)
167138
{
168-
byte r = (byte) (color.R * amount + backColor.R * (1 - amount));
169-
byte g = (byte) (color.G * amount + backColor.G * (1 - amount));
170-
byte b = (byte) (color.B * amount + backColor.B * (1 - amount));
171-
return Color.FromArgb(r, g, b);
172-
}
139+
opacity = Math.Clamp(opacity, 0, 1);
173140

174-
/// <summary>
175-
/// Creates color with corrected brightness.
176-
/// </summary>
177-
/// <param name="color">Color to correct.</param>
178-
/// <param name="correctionFactor">The brightness correction factor. Must be between -1 and 1.
179-
/// Negative values produce darker colors.</param>
180-
/// <returns>
181-
/// Corrected <see cref="Color"/> structure.
182-
/// </returns>
183-
public static Color ChangeColorBrightness(Color color, float correctionFactor)
184-
{
185-
https://stackoverflow.com/questions/801406/c-create-a-lighter-darker-color-based-on-a-system-color
186-
187-
float red = (float)color.R;
188-
float green = (float)color.G;
189-
float blue = (float)color.B;
190-
191-
if (correctionFactor < 0)
192-
{
193-
correctionFactor = 1 + correctionFactor;
194-
red *= correctionFactor;
195-
green *= correctionFactor;
196-
blue *= correctionFactor;
197-
}
198-
else
199-
{
200-
red = (255 - red) * correctionFactor + red;
201-
green = (255 - green) * correctionFactor + green;
202-
blue = (255 - blue) * correctionFactor + blue;
203-
}
204-
205-
return Color.FromArgb(color.A, (int)red, (int)green, (int)blue);
206-
}
141+
// Normalize RGB values between 0 and 1
142+
double baseR = baseColor.R / 255.0;
143+
double baseG = baseColor.G / 255.0;
144+
double baseB = baseColor.B / 255.0;
145+
146+
double overlayR = overlayColor.R / 255.0;
147+
double overlayG = overlayColor.G / 255.0;
148+
double overlayB = overlayColor.B / 255.0;
207149

208-
// Testé le 13/12/2022 : https://stackoverflow.com/questions/359612/how-to-convert-rgb-color-to-hsv
209-
// Même résultat qu'avec Gimp
150+
// Apply the blending formula with transparency
151+
// For each component: result = base + (overlay - base) * opacity
152+
double resultR = baseR + (overlayR - baseR) * opacity;
153+
double resultG = baseG + (overlayG - baseG) * opacity;
154+
double resultB = baseB + (overlayB - baseB) * opacity;
210155

211-
public static void ColorToHSV(Color color, out double hue, out double saturation, out double value)
156+
// Convert to values 0-255
157+
byte r = (byte)(resultR * 255);
158+
byte g = (byte)(resultG * 255);
159+
byte b = (byte)(resultB * 255);
160+
161+
return Color.FromArgb(baseColor.A, r, g, b);
162+
}
163+
164+
public static void ColorToHsv(Color color, out double hue, out double saturation, out double value)
212165
{
213166
int max = Math.Max(color.R, Math.Max(color.G, color.B));
214167
int min = Math.Min(color.R, Math.Min(color.G, color.B));
215168

216-
hue = color.GetHue();
169+
hue = color.ToSystemColor().GetHue();
217170
saturation = (max == 0) ? 0 : 1d - (1d * min / max);
218171
value = max / 255d;
219172
}
220173

221-
public static Color ColorFromHSV(double hue, double saturation, double value)
174+
public static System.Drawing.Color ToSystemColor(this Color color)
175+
{
176+
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B);
177+
}
178+
179+
public static Color ColorFromHsv(double hue, double saturation, double value)
222180
{
223181
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
224182
double f = hue / 60 - Math.Floor(hue / 60);
@@ -230,16 +188,16 @@ public static Color ColorFromHSV(double hue, double saturation, double value)
230188
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
231189

232190
if (hi == 0)
233-
return Color.FromArgb(255, v, t, p);
191+
return Color.FromArgb(255, (byte) v, (byte) t, (byte) p);
234192
else if (hi == 1)
235-
return Color.FromArgb(255, q, v, p);
193+
return Color.FromArgb(255, (byte) q, (byte) v, (byte) p);
236194
else if (hi == 2)
237-
return Color.FromArgb(255, p, v, t);
195+
return Color.FromArgb(255, (byte) p, (byte) v, (byte) t);
238196
else if (hi == 3)
239-
return Color.FromArgb(255, p, q, v);
197+
return Color.FromArgb(255, (byte) p, (byte) q, (byte) v);
240198
else if (hi == 4)
241-
return Color.FromArgb(255, t, p, v);
199+
return Color.FromArgb(255, (byte) t, (byte) p, (byte) v);
242200
else
243-
return Color.FromArgb(255, v, p, q);
201+
return Color.FromArgb(255, (byte) v, (byte) p, (byte) q);
244202
}
245203
}

src/ByteSync.Client/Services/Themes/ThemeFactory.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Avalonia.Media;
22
using ByteSync.Business.Themes;
3+
using ByteSync.Helpers;
34
using ByteSync.Interfaces.Controls.Themes;
45

56
namespace ByteSync.Services.Themes;
@@ -38,7 +39,7 @@ private void BuildThemes(string themeName, string primaryColorHex)
3839
private void BuildAndRegisterThemes(string themeName, ThemeColor themeColor, double secondaryColorHue, string primaryColorHex)
3940
{
4041
// Create secondary theme color with given hue but same saturation/value as primary
41-
var secondarySystemColor = ColorUtils.ColorFromHSV(secondaryColorHue, themeColor.Saturation, themeColor.Value);
42+
var secondarySystemColor = ColorUtils.ColorFromHsv(secondaryColorHue, themeColor.Saturation, themeColor.Value);
4243
ThemeColor secondaryThemeColor = new ThemeColor(secondarySystemColor);
4344

4445
// Create light theme
@@ -130,6 +131,9 @@ private ColorScheme BuildColorScheme(Theme theme, ThemeColor themeColor, double
130131
colorScheme.Gray8 = Color.FromArgb(0xFF, 0x27, 0x27, 0x27);
131132
colorScheme.SettingsHeaderColor = Color.FromArgb(0xFF, 0x30, 0x30, 0x30);
132133
colorScheme.BlockBackColor = Color.FromArgb(0xFF, 0x1F, 0x1F, 0x1F);
134+
135+
colorScheme.MainWindowTopColor = ColorUtils.BlendWithTransparency(colorScheme.VeryLightGray, colorScheme.MainAccentColor.AvaloniaColor, 0.05);
136+
colorScheme.MainWindowBottomColor = ColorUtils.BlendWithTransparency(Color.FromArgb(0xFF, 0x04, 0x04, 0x04), colorScheme.MainAccentColor.AvaloniaColor, 0.05);
133137

134138
ComputeSecondaryColors(colorScheme, secondaryColorHue);
135139

@@ -212,6 +216,9 @@ private ColorScheme BuildColorScheme(Theme theme, ThemeColor themeColor, double
212216
colorScheme.SettingsHeaderColor = Color.FromArgb(0xFF, 0xE6, 0xE6, 0xE6);
213217
colorScheme.BlockBackColor = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
214218

219+
colorScheme.MainWindowTopColor = ColorUtils.BlendWithTransparency(colorScheme.VeryLightGray, colorScheme.MainAccentColor.AvaloniaColor, 0.05);
220+
colorScheme.MainWindowBottomColor = ColorUtils.BlendWithTransparency(Color.FromArgb(0xFF, 0xEF, 0xEF, 0xEF), colorScheme.MainAccentColor.AvaloniaColor, 0.05);
221+
215222
ComputeSecondaryColors(colorScheme, secondaryColorHue);
216223

217224
colorScheme.StatusMainBackGroundBrush = new SolidColorBrush(colorScheme.StatusMainBackGround.AvaloniaColor);

src/ByteSync.Client/Views/Headers/HeaderView.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
<Grid Height="60">
1616
<Border BorderThickness="0 0 0 1" BorderBrush="{DynamicResource SystemBaseMediumLowColor}">
17-
<Grid Background="{DynamicResource VeryLightGray}">
17+
<Grid>
1818
<Grid.ColumnDefinitions>
1919
<ColumnDefinition Width="*"></ColumnDefinition>
2020
<ColumnDefinition Width="Auto"></ColumnDefinition>

src/ByteSync.Client/Views/MainWindow.axaml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
<Window.Background>
1616
<LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%">
17-
<GradientStop Offset="0" Color="{DynamicResource SystemAltHighColor}" /> <!-- SystemAltHighColor SystemChromeLowColor SystemChromeMediumColor -->
18-
<GradientStop Offset="1" Color="{DynamicResource SystemChromeMediumColor}" />
17+
<GradientStop Offset="0" Color="{DynamicResource MainWindowTopColor}" />
18+
<GradientStop Offset="1" Color="{DynamicResource MainWindowBottomColor}" />
1919
</LinearGradientBrush>
2020
</Window.Background>
2121

@@ -28,12 +28,6 @@
2828
</LayoutTransformControl.LayoutTransform>
2929

3030
<Grid RowDefinitions="Auto,Auto,*" >
31-
<Grid.Background>
32-
<LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%" Opacity="0.05">
33-
<GradientStop Offset="0" Color="{DynamicResource SystemAltHighColor}" />
34-
<GradientStop Offset="1" Color="{DynamicResource SystemAccentColor}" />
35-
</LinearGradientBrush>
36-
</Grid.Background>
3731

3832
<Border Grid.Row="0" x:Name="FocusSink"
3933
IsVisible="True"

0 commit comments

Comments
 (0)