using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using Barotrauma; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Graphics; using System.Xml; using System.Xml.Linq; namespace QICrabUI { /// /// In Fact just an observable dict /// public partial class CUIStyle : IEnumerable>, ICloneable { public static CUIStyle DefaultFor(Type T) => CUITypeMetaData.Get(T).DefaultStyle; public static CUIStyle DefaultFor() where T : CUIComponent => CUITypeMetaData.Get(typeof(T)).DefaultStyle; IEnumerator> IEnumerable>.GetEnumerator() => Props.GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => Props.GetEnumerator(); public void Add(string key, string value) { Props[key] = value; OnPropChanged?.Invoke(key, value); } public void Clear() => Props.Clear(); /// /// Prop name -> value /// public Dictionary Props = new(); public event Action OnPropChanged; public event Action OnUse; public virtual string this[string name] { get => Props.ContainsKey(name) ? Props[name] : ""; set => Add(name, value); } public object Clone() { CUIStyle style = new CUIStyle(); style.Props = new Dictionary(Props); return style; } public static CUIStyle Merge(CUIStyle baseStyle, CUIStyle addedStyle) { CUIStyle result = new CUIStyle(); if (baseStyle != null) { foreach (string key in baseStyle.Props.Keys) { result[key] = baseStyle.Props[key]; } } if (addedStyle != null) { foreach (string key in addedStyle.Props.Keys) { result[key] = addedStyle.Props[key]; } } return result; } public void Use(CUIStyle source) { Props = new Dictionary(source.Props); OnUse?.Invoke(this); } public void UseString(string raw) { Clear(); try { string content = raw.Split('{', '}')[1]; if (content.Trim() == "") return; var pairs = content.Split(',').Select(s => s.Split(':').Select(sub => sub.Trim()).ToArray()); foreach (var pair in pairs) { Props[pair[0]] = pair[1]; } } catch (Exception e) { CUI.Warning($"Style.UseString failed: {e.Message}"); } OnUse?.Invoke(this); } public void UseXML(XElement element) { Clear(); foreach (XElement prop in element.Elements()) { Props[prop.Name.ToString()] = prop.Value; } OnUse?.Invoke(this); } public static CUIStyle FromXML(XElement element) { CUIStyle style = new CUIStyle(); style.UseXML(element); return style; } public override string ToString() { return "{ " + String.Join(", ", Props.Select(kvp => $"{kvp.Key} : {kvp.Value}")) + " }"; } public static CUIStyle Parse(string raw) { CUIStyle style = new CUIStyle(); style.UseString(raw); return style; } public override bool Equals(object obj) { if (!(obj is CUIStyle styleB)) return false; CUIStyle styleA = this; if (styleA is null && styleB is null) return true; if (styleA is null || styleB is null) return false; if (styleA.Props is null || styleB.Props is null) return false; if (styleA.Props.Count != styleB.Props.Count) return false; foreach (var (key, value) in styleA.Props) { if (!styleB.Props.ContainsKey(key)) return false; if (styleA[key] != styleB[key]) return false; } return true; } public static CUIStyle operator +(CUIStyle styleA, CUIStyle styleB) => Merge(styleA, styleB); public static bool operator ==(CUIStyle styleA, CUIStyle styleB) { if (styleA is null && styleB is null) return true; if (styleA is null || styleB is null) return false; if (styleA.Props is null || styleB.Props is null) return false; if (styleA.Props.Count != styleB.Props.Count) return false; foreach (var (key, value) in styleA.Props) { if (!styleB.Props.ContainsKey(key)) return false; if (styleA[key] != styleB[key]) return false; } return true; } public static bool operator !=(CUIStyle styleA, CUIStyle styleB) { if (styleA is null && styleB is null) return false; if (styleA is null || styleB is null) return true; if (styleA.Props is null || styleB.Props is null) return true; if (styleA.Props.Count != styleB.Props.Count) return true; foreach (var (key, value) in styleA.Props) { if (!styleB.Props.ContainsKey(key)) return true; if (styleA[key] != styleB[key]) return true; } return false; } } }