// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. using System; using System.Globalization; using System.Runtime.Serialization; using System.Security.Permissions; using System.Text; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Utils; namespace ICSharpCode.AvalonEdit.Highlighting { /// /// A highlighting color is a set of font properties and foreground and background color. /// [Serializable] public class HighlightingColor : ISerializable, IFreezable, ICloneable, IEquatable { internal static readonly HighlightingColor Empty = FreezableHelper.FreezeAndReturn(new HighlightingColor()); string name; FontWeight? fontWeight; FontStyle? fontStyle; HighlightingBrush foreground; HighlightingBrush background; bool frozen; /// /// Gets/Sets the name of the color. /// public string Name { get { return name; } set { if (frozen) throw new InvalidOperationException(); name = value; } } /// /// Gets/sets the font weight. Null if the highlighting color does not change the font weight. /// public FontWeight? FontWeight { get { return fontWeight; } set { if (frozen) throw new InvalidOperationException(); fontWeight = value; } } /// /// Gets/sets the font style. Null if the highlighting color does not change the font style. /// public FontStyle? FontStyle { get { return fontStyle; } set { if (frozen) throw new InvalidOperationException(); fontStyle = value; } } /// /// Gets/sets the foreground color applied by the highlighting. /// public HighlightingBrush Foreground { get { return foreground; } set { if (frozen) throw new InvalidOperationException(); foreground = value; } } /// /// Gets/sets the background color applied by the highlighting. /// public HighlightingBrush Background { get { return background; } set { if (frozen) throw new InvalidOperationException(); background = value; } } /// /// Creates a new HighlightingColor instance. /// public HighlightingColor() { } /// /// Deserializes a HighlightingColor. /// protected HighlightingColor(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); this.Name = info.GetString("Name"); if (info.GetBoolean("HasWeight")) this.FontWeight = System.Windows.FontWeight.FromOpenTypeWeight(info.GetInt32("Weight")); if (info.GetBoolean("HasStyle")) this.FontStyle = (FontStyle?)new FontStyleConverter().ConvertFromInvariantString(info.GetString("Style")); this.Foreground = (HighlightingBrush)info.GetValue("Foreground", typeof(HighlightingBrush)); this.Background = (HighlightingBrush)info.GetValue("Background", typeof(HighlightingBrush)); } /// /// Serializes this HighlightingColor instance. /// #if DOTNET4 [System.Security.SecurityCritical] #else [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] #endif public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); info.AddValue("Name", this.Name); info.AddValue("HasWeight", this.FontWeight.HasValue); if (this.FontWeight.HasValue) info.AddValue("Weight", this.FontWeight.Value.ToOpenTypeWeight()); info.AddValue("HasStyle", this.FontStyle.HasValue); if (this.FontStyle.HasValue) info.AddValue("Style", this.FontStyle.Value.ToString()); info.AddValue("Foreground", this.Foreground); info.AddValue("Background", this.Background); } /// /// Gets CSS code for the color. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "CSS usually uses lowercase, and all possible values are English-only")] public virtual string ToCss() { StringBuilder b = new StringBuilder(); if (Foreground != null) { Color? c = Foreground.GetColor(null); if (c != null) { b.AppendFormat(CultureInfo.InvariantCulture, "color: #{0:x2}{1:x2}{2:x2}; ", c.Value.R, c.Value.G, c.Value.B); } } if (FontWeight != null) { b.Append("font-weight: "); b.Append(FontWeight.Value.ToString().ToLowerInvariant()); b.Append("; "); } if (FontStyle != null) { b.Append("font-style: "); b.Append(FontStyle.Value.ToString().ToLowerInvariant()); b.Append("; "); } return b.ToString(); } /// public override string ToString() { return "[" + GetType().Name + " " + (string.IsNullOrEmpty(this.Name) ? ToCss() : this.Name) + "]"; } /// /// Prevent further changes to this highlighting color. /// public virtual void Freeze() { frozen = true; } /// /// Gets whether this HighlightingColor instance is frozen. /// public bool IsFrozen { get { return frozen; } } /// /// Clones this highlighting color. /// If this color is frozen, the clone will be unfrozen. /// public virtual HighlightingColor Clone() { HighlightingColor c = (HighlightingColor)MemberwiseClone(); c.frozen = false; return c; } object ICloneable.Clone() { return Clone(); } /// public override sealed bool Equals(object obj) { return Equals(obj as HighlightingColor); } /// public virtual bool Equals(HighlightingColor other) { if (other == null) return false; return this.name == other.name && this.fontWeight == other.fontWeight && this.fontStyle == other.fontStyle && object.Equals(this.foreground, other.foreground) && object.Equals(this.background, other.background); } /// public override int GetHashCode() { int hashCode = 0; unchecked { if (name != null) hashCode += 1000000007 * name.GetHashCode(); hashCode += 1000000009 * fontWeight.GetHashCode(); hashCode += 1000000021 * fontStyle.GetHashCode(); if (foreground != null) hashCode += 1000000033 * foreground.GetHashCode(); if (background != null) hashCode += 1000000087 * background.GetHashCode(); } return hashCode; } /// /// Overwrites the properties in this HighlightingColor with those from the given color; /// but maintains the current values where the properties of the given color return null. /// public void MergeWith(HighlightingColor color) { FreezableHelper.ThrowIfFrozen(this); if (color.fontWeight != null) this.fontWeight = color.fontWeight; if (color.fontStyle != null) this.fontStyle = color.fontStyle; if (color.foreground != null) this.foreground = color.foreground; if (color.background != null) this.background = color.background; } internal bool IsEmptyForMerge { get { return fontWeight == null && fontStyle == null && foreground == null && background == null; } } } }