2using System.Collections.Generic;
4using System.Reflection;
5using System.Diagnostics;
8using Microsoft.Xna.Framework;
9using Microsoft.Xna.Framework.Input;
10using Microsoft.Xna.Framework.Graphics;
18 public enum PaletteOrder { Primary, Secondary, Tertiary, Quaternary }
20 public record PaletteExtractResult(
bool Ok,
string Value =
null);
24 public class CUIPalette
26 internal static void InitStatic()
28 CUI.OnInit += () => Initialize();
29 CUI.OnDispose += () => LoadedPalettes.Clear();
32 public override string ToString() => $
"CUIPalette {Name}";
33 public static string PaletteSetsPath => Path.Combine(CUI.PalettesPath,
"Sets");
37 public static string DefaultPalette =
"Blue";
43 public static bool NotifyExcessivePropStyles {
get;
set; } =
false;
47 public static bool NotifiMissingPropStyles {
get;
set; } =
true;
49 public Dictionary<string, string> Values = BackupPalette;
51 public string Name =
"???";
52 public string BaseColor {
get;
set; } =
"";
54 public static Dictionary<string, CUIPalette> LoadedPalettes =
new();
55 public static CUIPalette Empty =>
new CUIPalette();
56 public static Dictionary<string, string> BackupPalette =>
new Dictionary<string, string>()
58 [
"Frame.Background"] =
"0,0,0,200",
59 [
"Frame.Border"] =
"0,0,127,227",
60 [
"Frame.Text"] =
"229,229,255,255",
61 [
"Header.Background"] =
"0,0,76,216",
62 [
"Header.Border"] =
"0,0,102,222",
63 [
"Header.Text"] =
"229,229,255,255",
64 [
"Nav.Background"] =
"0,0,51,211",
65 [
"Nav.Border"] =
"0,0,76,216",
66 [
"Nav.Text"] =
"204,204,255,255",
67 [
"Main.Background"] =
"0,0,25,205",
68 [
"Main.Border"] =
"0,0,51,211",
69 [
"Main.Text"] =
"204,204,255,255",
70 [
"Component.Background"] =
"0,0,0,0",
71 [
"Component.Border"] =
"0,0,0,0",
72 [
"Component.Text"] =
"204,204,255,255",
73 [
"Button.Background"] =
"0,0,255,255",
74 [
"Button.Border"] =
"0,0,127,227",
75 [
"Button.Disabled"] =
"12,12,63,255",
76 [
"CloseButton.Background"] =
"51,51,255,255",
77 [
"DDOption.Background"] =
"0,0,76,216",
78 [
"DDOption.Border"] =
"0,0,51,211",
79 [
"DDOption.Hover"] =
"0,0,127,227",
80 [
"DDOption.Text"] =
"204,204,255,255",
81 [
"Handle.Background"] =
"51,51,152,232",
82 [
"Handle.Grabbed"] =
"51,51,255,255",
83 [
"Slider"] =
"178,178,255,255",
84 [
"Input.Background"] =
"0,0,51,211",
85 [
"Input.Border"] =
"0,0,76,216",
86 [
"Input.Text"] =
"204,204,255,255",
87 [
"Input.Focused"] =
"0,0,255,255",
88 [
"Input.Invalid"] =
"255,0,0,255",
89 [
"Input.Valid"] =
"0,255,0,255",
90 [
"Input.Selection"] =
"178,178,255,127",
91 [
"Input.Caret"] =
"178,178,255,127",
95 private static CUIPalette primary =
new CUIPalette();
96 public static CUIPalette Primary
101 if (value ==
null)
return;
103 CUIGlobalStyleResolver.OnPaletteChange(primary);
107 private static CUIPalette secondary =
new CUIPalette();
108 public static CUIPalette Secondary
113 if (value ==
null)
return;
115 CUIGlobalStyleResolver.OnPaletteChange(secondary);
119 private static CUIPalette tertiary =
new CUIPalette();
120 public static CUIPalette Tertiary
125 if (value ==
null)
return;
127 CUIGlobalStyleResolver.OnPaletteChange(tertiary);
131 private static CUIPalette quaternary =
new CUIPalette();
132 public static CUIPalette Quaternary
137 if (value ==
null)
return;
139 CUIGlobalStyleResolver.OnPaletteChange(quaternary);
145 public static void Initialize()
147 if (CUI.PalettesPath ==
null)
return;
148 Stopwatch sw = Stopwatch.StartNew();
152 LoadedPalettes.Clear();
153 LoadPalettes(CUI.PalettesPath);
154 LoadSet(Path.Combine(PaletteSetsPath, DefaultPalette +
".xml"));
158 catch (Exception e) { CUI.Warning(e); }
160 CUIDebug.Log($
"CUIPalette.Initialize took {sw.ElapsedMilliseconds}ms");
163 public static PaletteExtractResult Extract(
string nestedName, PaletteOrder order)
165 CUIPalette palette = order
switch
167 PaletteOrder.Primary => Primary,
168 PaletteOrder.Secondary => Secondary,
169 PaletteOrder.Tertiary => Tertiary,
170 PaletteOrder.Quaternary => Quaternary,
173 if (!palette.Values.ContainsKey(nestedName))
return new PaletteExtractResult(
false);
174 return new PaletteExtractResult(
true, palette.Values[nestedName]);
177 public static void LoadPalettes(
string path)
179 foreach (
string file
in Directory.GetFiles(path,
"*.xml"))
181 CUIPalette palette = LoadFrom(file);
182 LoadedPalettes[palette.Name] = palette;
186 public static CUIPalette FromXML(XElement root)
188 CUIPalette palette =
new CUIPalette();
190 palette.Name = root.Attribute(
"Name")?.Value.ToString();
192 foreach (XElement element
in root.Elements())
194 foreach (XAttribute attribute
in element.Attributes())
196 palette.Values[$
"{element.Name}.{attribute.Name}"] = attribute.Value;
199 if (element.Value !=
"")
201 palette.Values[$
"{element.Name}"] = element.Value;
208 public static CUIPalette LoadFrom(
string path)
210 CUIPalette palette =
new CUIPalette();
213 XDocument xdoc = XDocument.Load(path);
214 XElement root = xdoc.Root;
216 palette = CUIPalette.FromXML(root);
217 palette.Name ??= Path.GetFileNameWithoutExtension(path);
221 CUI.Warning($
"Failed to load palette from {path}");
228 public XElement ToXML()
230 XElement root =
new XElement(
"Palette");
231 root.Add(
new XAttribute(
"Name", Name));
232 root.Add(
new XAttribute(
"BaseColor", BaseColor));
234 foreach (
string key
in Values.Keys)
236 string component = key.Split(
'.').ElementAtOrDefault(0);
237 string prop = key.Split(
'.').ElementAtOrDefault(1);
239 if (component ==
null)
continue;
241 if (root.Element(component) ==
null) root.Add(
new XElement(component));
245 root.Element(component).Add(
new XAttribute(prop, Values[key]));
249 root.Element(component).Value = Values[key];
254 public void SaveTo(
string path)
258 XDocument xdoc =
new XDocument();
259 xdoc.Add(this.ToXML());
264 CUI.Warning($
"Failed to save palette to {path}");
270 public static void PaletteDemo()
272 if (CUI.AssetsPath ==
null)
274 CUI.Warning($
"Can't load PaletteDemo, CUI.AssetsPath is null");
278 void loadFrame(Vector2 offset, PaletteOrder order)
280 CUIFrame frame = CUIComponent.LoadFromFile<CUIFrame>(Path.Combine(CUI.AssetsPath, $
"PaletteDemo.xml"));
281 frame.DeepPalette = order;
282 frame.Absolute = frame.Absolute with { Position = offset };
283 frame.AddCommand(
"Close", (o) => frame.RemoveSelf());
284 CUI.TopMain.Append(frame);
287 loadFrame(
new Vector2(0, 0), PaletteOrder.Primary);
288 loadFrame(
new Vector2(180, 0), PaletteOrder.Secondary);
289 loadFrame(
new Vector2(360, 0), PaletteOrder.Tertiary);
290 loadFrame(
new Vector2(540, 0), PaletteOrder.Quaternary);
293 public static CUIPalette CreatePaletteFromColors(
string name, Color colorA, Color? colorb =
null)
295 CUIPalette palette =
new CUIPalette()
298 BaseColor = CUIExtensions.ColorToString(colorA),
301 Color colorB = colorb ?? Color.Black;
303 Dictionary<string, Color> colors =
new();
305 colors[
"Frame.Background"] = colorA.To(colorB, 1.0f);
306 colors[
"Header.Background"] = colorA.To(colorB, 0.7f);
307 colors[
"Nav.Background"] = colorA.To(colorB, 0.8f);
308 colors[
"Main.Background"] = colorA.To(colorB, 0.9f);
310 colors[
"Frame.Border"] = colorA.To(colorB, 0.5f);
311 colors[
"Header.Border"] = colorA.To(colorB, 0.6f);
312 colors[
"Nav.Border"] = colorA.To(colorB, 0.7f);
313 colors[
"Main.Border"] = colorA.To(colorB, 0.8f);
315 colors[
"Frame.Text"] = colorA.To(Color.White, 0.9f);
316 colors[
"Header.Text"] = colorA.To(Color.White, 0.9f);
317 colors[
"Nav.Text"] = colorA.To(Color.White, 0.8f);
318 colors[
"Main.Text"] = colorA.To(Color.White, 0.8f);
320 colors[
"Component.Background"] = Color.Transparent;
321 colors[
"Component.Border"] = Color.Transparent;
322 colors[
"Component.Text"] = colors[
"Main.Text"];
323 colors[
"Button.Background"] = colorA.To(colorB, 0.0f);
324 colors[
"Button.Border"] = colorA.To(colorB, 0.5f);
325 colors[
"Button.Disabled"] = colorA.To(
new Color(16, 16, 16), 0.8f);
326 colors[
"CloseButton.Background"] = colorA.To(Color.White, 0.2f);
327 colors[
"DDOption.Background"] = colors[
"Header.Background"];
328 colors[
"DDOption.Border"] = colors[
"Main.Border"];
329 colors[
"DDOption.Hover"] = colorA.To(colorB, 0.5f);
330 colors[
"DDOption.Text"] = colors[
"Main.Text"];
331 colors[
"Handle.Background"] = colorA.To(colorB, 0.5f).To(Color.White, 0.2f);
332 colors[
"Handle.Grabbed"] = colorA.To(colorB, 0.0f).To(Color.White, 0.2f);
333 colors[
"Slider"] = colorA.To(Color.White, 0.7f);
334 colors[
"Input.Background"] = colors[
"Nav.Background"];
335 colors[
"Input.Border"] = colors[
"Nav.Border"];
336 colors[
"Input.Text"] = colors[
"Main.Text"];
337 colors[
"Input.Focused"] = colorA;
338 colors[
"Input.Invalid"] = Color.Red;
339 colors[
"Input.Valid"] = Color.Lime;
340 colors[
"Input.Selection"] = colorA.To(Color.White, 0.7f) * 0.5f;
341 colors[
"Input.Caret"] = colorA.To(Color.White, 0.7f) * 0.5f;
343 foreach (var (key, cl) in colors)
345 palette.Values[key] = CUIExtensions.ColorToString(cl);
348 palette.SaveTo(Path.Combine(CUI.PalettesPath, $
"{name}.xml"));
349 LoadedPalettes[name] = palette;
350 CUI.Log($
"Created {name} palette and saved it to {Path.Combine(CUI.PalettesPath, $"{name}.xml
")}");
358 public static void SaveSet(
string setName,
string primary =
"",
string secondary =
"",
string tertiary =
"",
string quaternary =
"")
360 if (setName ==
null || setName ==
"")
return;
362 string savePath = Path.Combine(PaletteSetsPath, $
"{setName}.xml");
366 XDocument xdoc =
new XDocument(
new XElement(
"PaletteSet"));
367 XElement root = xdoc.Root;
369 root.Add(
new XAttribute(
"Name", setName));
371 root.Add((LoadedPalettes.GetValueOrDefault(primary ??
"") ?? Primary).ToXML());
372 root.Add((LoadedPalettes.GetValueOrDefault(secondary ??
"") ?? Secondary).ToXML());
373 root.Add((LoadedPalettes.GetValueOrDefault(tertiary ??
"") ?? Tertiary).ToXML());
374 root.Add((LoadedPalettes.GetValueOrDefault(quaternary ??
"") ?? Quaternary).ToXML());
378 CUI.Log($
"Created {setName} palette set and saved it to {savePath}");
383 CUI.Warning($
"Failed to save palette set to {savePath}");
388 public static void LoadSet(
string path)
390 if (path ==
null || path ==
"")
392 CUI.Warning($
"Can't load CUIPalette set: path is empty");
395 if (!File.Exists(path))
397 CUI.Warning($
"Couldn't find {Path.GetFileName(path)} CUIPalette set");
403 XDocument xdoc = XDocument.Load(path);
404 XElement root = xdoc.Root;
406 List<CUIPalette> palettes =
new();
408 foreach (XElement element
in root.Elements(
"Palette"))
410 palettes.Add(CUIPalette.FromXML(element));
413 Primary = palettes.ElementAtOrDefault(0) ?? Empty;
414 Secondary = palettes.ElementAtOrDefault(1) ?? Empty;
415 Tertiary = palettes.ElementAtOrDefault(2) ?? Empty;
416 Quaternary = palettes.ElementAtOrDefault(3) ?? Empty;
420 CUI.Warning($
"Failed to load palette set from {path}");
428 public static void TransformToBackup(CUIPalette palette)
430 using (StreamWriter writer =
new StreamWriter(Path.Combine(CUI.PalettesPath,
"backup.txt"),
false))
432 writer.WriteLine(
"{");
433 foreach (var (key, value) in palette.Values)
435 writer.WriteLine($
" [\"{key}\"] = \"{value}\",");
437 writer.WriteLine(
"}");