Skip to content

Commit eca5e0a

Browse files
committed
Theme Source Generator
Made this so we can make a theme in the application and easily make it an built-in theme :D Also added some safety for parts that try to load in assets from a theme and added a THEME_EDIT Constant to make it easier for editing built-in themes without messing up naming
1 parent 69fce5b commit eca5e0a

File tree

19 files changed

+1130
-101
lines changed

19 files changed

+1130
-101
lines changed
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
#define BUILDTASK
2+
//Added this into the project as we would need to manually pull in a lot of Avalonia projects, it's more simple to just contain these files in the source gen
3+
//From https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Visuals/Media/Color.cs
4+
5+
using System;
6+
using System.Globalization;
7+
#if !BUILDTASK
8+
using Avalonia.Animation.Animators;
9+
#endif
10+
11+
namespace Avalonia.Media
12+
{
13+
/// <summary>
14+
/// An ARGB color.
15+
/// </summary>
16+
public readonly struct Color : IEquatable<Color>
17+
{
18+
static Color()
19+
{
20+
#if !BUILDTASK
21+
Animation.Animation.RegisterAnimator<ColorAnimator>(prop => typeof(Color).IsAssignableFrom(prop.PropertyType));
22+
#endif
23+
}
24+
25+
/// <summary>
26+
/// Gets the Alpha component of the color.
27+
/// </summary>
28+
public byte A { get; }
29+
30+
/// <summary>
31+
/// Gets the Red component of the color.
32+
/// </summary>
33+
public byte R { get; }
34+
35+
/// <summary>
36+
/// Gets the Green component of the color.
37+
/// </summary>
38+
public byte G { get; }
39+
40+
/// <summary>
41+
/// Gets the Blue component of the color.
42+
/// </summary>
43+
public byte B { get; }
44+
45+
public Color(byte a, byte r, byte g, byte b)
46+
{
47+
A = a;
48+
R = r;
49+
G = g;
50+
B = b;
51+
}
52+
53+
/// <summary>
54+
/// Creates a <see cref="Color"/> from alpha, red, green and blue components.
55+
/// </summary>
56+
/// <param name="a">The alpha component.</param>
57+
/// <param name="r">The red component.</param>
58+
/// <param name="g">The green component.</param>
59+
/// <param name="b">The blue component.</param>
60+
/// <returns>The color.</returns>
61+
public static Color FromArgb(byte a, byte r, byte g, byte b)
62+
{
63+
return new Color(a, r, g, b);
64+
}
65+
66+
/// <summary>
67+
/// Creates a <see cref="Color"/> from red, green and blue components.
68+
/// </summary>
69+
/// <param name="r">The red component.</param>
70+
/// <param name="g">The green component.</param>
71+
/// <param name="b">The blue component.</param>
72+
/// <returns>The color.</returns>
73+
public static Color FromRgb(byte r, byte g, byte b)
74+
{
75+
return new Color(0xff, r, g, b);
76+
}
77+
78+
/// <summary>
79+
/// Creates a <see cref="Color"/> from an integer.
80+
/// </summary>
81+
/// <param name="value">The integer value.</param>
82+
/// <returns>The color.</returns>
83+
public static Color FromUInt32(uint value)
84+
{
85+
return new Color(
86+
(byte)((value >> 24) & 0xff),
87+
(byte)((value >> 16) & 0xff),
88+
(byte)((value >> 8) & 0xff),
89+
(byte)(value & 0xff)
90+
);
91+
}
92+
93+
/// <summary>
94+
/// Parses a color string.
95+
/// </summary>
96+
/// <param name="s">The color string.</param>
97+
/// <returns>The <see cref="Color"/>.</returns>
98+
public static Color Parse(string s)
99+
{
100+
if (s is null)
101+
{
102+
throw new ArgumentNullException(nameof(s));
103+
}
104+
105+
if (TryParse(s, out Color color))
106+
{
107+
return color;
108+
}
109+
110+
throw new FormatException($"Invalid color string: '{s}'.");
111+
}
112+
113+
/// <summary>
114+
/// Parses a color string.
115+
/// </summary>
116+
/// <param name="s">The color string.</param>
117+
/// <returns>The <see cref="Color"/>.</returns>
118+
public static Color Parse(ReadOnlySpan<char> s)
119+
{
120+
if (TryParse(s, out Color color))
121+
{
122+
return color;
123+
}
124+
125+
throw new FormatException($"Invalid color string: '{s.ToString()}'.");
126+
}
127+
128+
/// <summary>
129+
/// Parses a color string.
130+
/// </summary>
131+
/// <param name="s">The color string.</param>
132+
/// <param name="color">The parsed color</param>
133+
/// <returns>The status of the operation.</returns>
134+
public static bool TryParse(string s, out Color color)
135+
{
136+
color = default;
137+
138+
if (s is null)
139+
{
140+
return false;
141+
}
142+
143+
if (s.Length == 0)
144+
{
145+
return false;
146+
}
147+
148+
if (s[0] == '#' && TryParseInternal(s.AsSpan(), out color))
149+
{
150+
return true;
151+
}
152+
153+
var knownColor = KnownColors.GetKnownColor(s);
154+
155+
if (knownColor != KnownColor.None)
156+
{
157+
color = knownColor.ToColor();
158+
159+
return true;
160+
}
161+
162+
return false;
163+
}
164+
165+
/// <summary>
166+
/// Parses a color string.
167+
/// </summary>
168+
/// <param name="s">The color string.</param>
169+
/// <param name="color">The parsed color</param>
170+
/// <returns>The status of the operation.</returns>
171+
public static bool TryParse(ReadOnlySpan<char> s, out Color color)
172+
{
173+
if (s.Length == 0)
174+
{
175+
color = default;
176+
177+
return false;
178+
}
179+
180+
if (s[0] == '#')
181+
{
182+
return TryParseInternal(s, out color);
183+
}
184+
185+
var knownColor = KnownColors.GetKnownColor(s.ToString());
186+
187+
if (knownColor != KnownColor.None)
188+
{
189+
color = knownColor.ToColor();
190+
191+
return true;
192+
}
193+
194+
color = default;
195+
196+
return false;
197+
}
198+
199+
private static bool TryParseInternal(ReadOnlySpan<char> s, out Color color)
200+
{
201+
static bool TryParseCore(ReadOnlySpan<char> input, ref Color color)
202+
{
203+
var alphaComponent = 0u;
204+
205+
if (input.Length == 6)
206+
{
207+
alphaComponent = 0xff000000;
208+
}
209+
else if (input.Length != 8)
210+
{
211+
return false;
212+
}
213+
214+
// TODO: (netstandard 2.1) Can use allocation free parsing.
215+
if (!uint.TryParse(input.ToString(), NumberStyles.HexNumber, CultureInfo.InvariantCulture,
216+
out var parsed))
217+
{
218+
return false;
219+
}
220+
221+
color = FromUInt32(parsed | alphaComponent);
222+
223+
return true;
224+
}
225+
226+
color = default;
227+
228+
ReadOnlySpan<char> input = s.Slice(1);
229+
230+
// Handle shorthand cases like #FFF (RGB) or #FFFF (ARGB).
231+
if (input.Length == 3 || input.Length == 4)
232+
{
233+
var extendedLength = 2 * input.Length;
234+
235+
#if !BUILDTASK
236+
Span<char> extended = stackalloc char[extendedLength];
237+
#else
238+
char[] extended = new char[extendedLength];
239+
#endif
240+
241+
for (int i = 0; i < input.Length; i++)
242+
{
243+
extended[2 * i + 0] = input[i];
244+
extended[2 * i + 1] = input[i];
245+
}
246+
247+
return TryParseCore(extended, ref color);
248+
}
249+
250+
return TryParseCore(input, ref color);
251+
}
252+
253+
/// <summary>
254+
/// Returns the string representation of the color.
255+
/// </summary>
256+
/// <returns>
257+
/// The string representation of the color.
258+
/// </returns>
259+
public override string ToString()
260+
{
261+
uint rgb = ToUint32();
262+
return KnownColors.GetKnownColorName(rgb) ?? $"#{rgb:x8}";
263+
}
264+
265+
/// <summary>
266+
/// Returns the integer representation of the color.
267+
/// </summary>
268+
/// <returns>
269+
/// The integer representation of the color.
270+
/// </returns>
271+
public uint ToUint32()
272+
{
273+
return ((uint)A << 24) | ((uint)R << 16) | ((uint)G << 8) | (uint)B;
274+
}
275+
276+
/// <summary>
277+
/// Check if two colors are equal.
278+
/// </summary>
279+
public bool Equals(Color other)
280+
{
281+
return A == other.A && R == other.R && G == other.G && B == other.B;
282+
}
283+
284+
public override bool Equals(object obj)
285+
{
286+
return obj is Color other && Equals(other);
287+
}
288+
289+
public override int GetHashCode()
290+
{
291+
unchecked
292+
{
293+
int hashCode = A.GetHashCode();
294+
hashCode = (hashCode * 397) ^ R.GetHashCode();
295+
hashCode = (hashCode * 397) ^ G.GetHashCode();
296+
hashCode = (hashCode * 397) ^ B.GetHashCode();
297+
return hashCode;
298+
}
299+
}
300+
301+
public static bool operator ==(Color left, Color right)
302+
{
303+
return left.Equals(right);
304+
}
305+
306+
public static bool operator !=(Color left, Color right)
307+
{
308+
return !left.Equals(right);
309+
}
310+
}
311+
}

0 commit comments

Comments
 (0)