// Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using System.Collections.Generic; using System.Linq; using Perspex.Collections; namespace Perspex.Controls { /// /// Holds a collection of style classes for an . /// /// /// Similar to CSS, each control may have any number of styling classes applied. /// public class Classes : PerspexList, IPseudoClasses { /// /// Initializes a new instance of the class. /// public Classes() { } /// /// Initializes a new instance of the class. /// /// The initial items. public Classes(IEnumerable items) : base(items) { } /// /// Initializes a new instance of the class. /// /// The initial items. public Classes(params string[] items) : base(items) { } /// /// Adds a style class to the collection. /// /// The class name. /// /// Only standard classes may be added via this method. To add pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override void Add(string name) { ThrowIfPseudoclass(name, "added"); if (!Contains(name)) { base.Add(name); } } /// /// Adds a style classes to the collection. /// /// The class names. /// /// Only standard classes may be added via this method. To add pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override void AddRange(IEnumerable names) { var c = new List(); foreach (var name in names) { ThrowIfPseudoclass(name, "added"); if (!Contains(name)) { c.Add(name); } } base.AddRange(c); } /// /// Inserts a style class into the collection. /// /// The index to insert the class at. /// The class name. /// /// Only standard classes may be added via this method. To add pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override void Insert(int index, string name) { ThrowIfPseudoclass(name, "added"); if (!Contains(name)) { base.Insert(index, name); } } /// /// Inserts style classes into the collection. /// /// The index to insert the class at. /// The class names. /// /// Only standard classes may be added via this method. To add pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override void InsertRange(int index, IEnumerable names) { var c = new List(); foreach (var name in names) { ThrowIfPseudoclass(name, "added"); if (!Contains(name)) { c.Add(name); } } base.InsertRange(index, c); } /// /// Removes a style class from the collection. /// /// The class name. /// /// Only standard classes may be removed via this method. To remove pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override bool Remove(string name) { ThrowIfPseudoclass(name, "removed"); return base.Remove(name); } /// /// Removes style classes from the collection. /// /// The class name. /// /// Only standard classes may be removed via this method. To remove pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override void RemoveAll(IEnumerable names) { var c = new List(); foreach (var name in names) { ThrowIfPseudoclass(name, "removed"); if (!Contains(name)) { c.Add(name); } } base.RemoveAll(c); } /// /// Removes a style class from the collection. /// /// The index of the class in the collection. /// /// Only standard classes may be removed via this method. To remove pseudoclasses (classes /// beginning with a ':' character) use the protected /// property. /// public override void RemoveAt(int index) { var name = this[index]; ThrowIfPseudoclass(name, "removed"); base.RemoveAt(index); } /// /// Removes style classes from the collection. /// /// The first index to remove. /// The number of items to remove. public override void RemoveRange(int index, int count) { var names = GetRange(index, count); base.RemoveRange(index, count); } /// /// Removes all non-pseudoclasses in the collection and adds a new set. /// /// The new contents of the collection. public void Replace(IList source) { var toRemove = new List(); foreach (var name in source) { ThrowIfPseudoclass(name, "added"); } foreach (var name in this) { if (!name.StartsWith(":")) { toRemove.Add(name); } } base.RemoveAll(toRemove); base.AddRange(source); } /// void IPseudoClasses.Add(string name) { if (!Contains(name)) { base.Add(name); } } /// bool IPseudoClasses.Remove(string name) { return base.Remove(name); } private void ThrowIfPseudoclass(string name, string operation) { if (name.StartsWith(":")) { throw new ArgumentException( $"The pseudoclass '{name}' may only be {operation} by the control itself."); } } } }