// 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;
}
}
}
}