2021-12-21 11:39:29 +01:00
using System ;
2019-11-05 13:28:41 +01:00
using System.Collections.Generic ;
2020-05-22 17:02:24 +02:00
using MLEM.Ui.Elements ;
2019-11-05 13:28:41 +01:00
2019-10-14 21:28:12 +02:00
namespace MLEM.Ui.Style {
2020-05-22 17:02:24 +02:00
/// <summary>
/// A struct used by <see cref="Element"/> to store style properties.
/// This is a helper struct that allows default style settings from <see cref="UiStyle"/> to be overridden by custom user settings easily.
/// Note that <c>T</c> implicitly converts to <c>StyleProp{T}</c> and vice versa.
/// </summary>
/// <typeparam name="T">The type of style setting that this property stores</typeparam>
2021-12-21 11:54:32 +01:00
public readonly struct StyleProp < T > : IEquatable < StyleProp < T > > {
/// <summary>
/// The empty style property, with no <see cref="Value"/> and a priority of 0.
/// </summary>
public static StyleProp < T > None = > default ;
2019-10-14 21:28:12 +02:00
2020-05-22 17:02:24 +02:00
/// <summary>
/// The currently applied style
/// </summary>
2021-12-21 11:54:32 +01:00
public readonly T Value ;
private readonly byte priority ;
2019-10-14 21:28:12 +02:00
2020-05-22 17:02:24 +02:00
/// <summary>
2021-12-21 11:39:29 +01:00
/// Creates a new style property with the given custom style and a priority of <see cref="byte.MaxValue"/>.
2021-12-21 11:54:32 +01:00
/// To create a style property with a lower priority, use <see cref="OrStyle(T,byte)"/> on an existing priority, or use <see cref="None"/>.
2020-05-22 17:02:24 +02:00
/// </summary>
/// <param name="value">The custom style to apply</param>
2021-12-21 11:54:32 +01:00
public StyleProp ( T value ) : this ( value , byte . MaxValue ) {
}
private StyleProp ( T value , byte priority ) {
2019-11-05 13:28:41 +01:00
this . Value = value ;
2021-12-21 11:54:32 +01:00
this . priority = priority ;
2019-11-05 13:28:41 +01:00
}
2020-05-22 17:02:24 +02:00
/// <summary>
2021-12-21 11:54:32 +01:00
/// Creates a copy of this style property and sets its value and marks it as being set by a <see cref="UiStyle"/> if it doesn't have a custom value yet.
2021-12-21 00:01:57 +01:00
/// This allows this property to be overridden by custom style settings using <see cref="StyleProp{T}(T)"/> or a higher <paramref name="priority"/>.
2020-05-22 17:02:24 +02:00
/// </summary>
/// <param name="value">The style to apply</param>
2021-12-21 11:54:32 +01:00
/// <param name="priority">The priority that the style value has. Higher priority style values will override lower priority style values.</param>
/// <returns>The style with the higher priority</returns>
public StyleProp < T > OrStyle ( T value , byte priority = 0 ) {
return this . OrStyle ( new StyleProp < T > ( value , priority ) ) ;
2019-10-14 21:28:12 +02:00
}
2020-05-22 17:02:24 +02:00
/// <summary>
2021-12-21 11:54:32 +01:00
/// Chooses and returns the style property with the higher priority, out of this value and <paramref name="other"/>.
/// This allows this property to be overridden by custom style settings using <see cref="StyleProp{T}(T)"/> or a higher priority.
2020-05-22 17:02:24 +02:00
/// </summary>
2021-12-21 11:54:32 +01:00
/// <param name="other">The style property to compare with</param>
/// <returns>The style property with the higher priority</returns>
public StyleProp < T > OrStyle ( StyleProp < T > other ) {
return other . priority > = this . priority ? other : this ;
2019-10-14 21:28:12 +02:00
}
2020-05-22 17:02:24 +02:00
/// <summary>
/// Returns the current style value or, if <see cref="HasValue"/> is false, the given default value.
/// </summary>
/// <param name="def">The default to return if this style property has no value</param>
/// <returns>The current value, or the default</returns>
2019-11-05 13:28:41 +01:00
public T OrDefault ( T def ) {
2020-02-06 17:36:51 +01:00
return this . HasValue ( ) ? this . Value : def ;
}
2020-05-22 17:02:24 +02:00
/// <summary>
2021-12-21 11:54:32 +01:00
/// Returns whether this style property has a value assigned to it using <see cref="OrStyle(StyleProp{T})"/> or <see cref="StyleProp{T}(T)"/>.
2020-05-22 17:02:24 +02:00
/// </summary>
/// <returns>Whether this style property has a value</returns>
2020-02-06 17:36:51 +01:00
public bool HasValue ( ) {
return ! EqualityComparer < T > . Default . Equals ( this . Value , default ) ;
2019-11-05 13:28:41 +01:00
}
2021-12-21 11:39:29 +01:00
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other">other</paramref> parameter; otherwise, false.</returns>
public bool Equals ( StyleProp < T > other ) {
return EqualityComparer < T > . Default . Equals ( this . Value , other . Value ) ;
}
/// <summary>Indicates whether this instance and a specified object are equal.</summary>
/// <param name="obj">The object to compare with the current instance.</param>
/// <returns>true if <paramref name="obj">obj</paramref> and this instance are the same type and represent the same value; otherwise, false.</returns>
public override bool Equals ( object obj ) {
return obj is StyleProp < T > other & & this . Equals ( other ) ;
}
/// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode ( ) {
return EqualityComparer < T > . Default . GetHashCode ( this . Value ) ;
}
2021-11-30 11:46:06 +01:00
/// <summary>Returns the fully qualified type name of this instance.</summary>
/// <returns>The fully qualified type name.</returns>
2021-10-29 23:33:15 +02:00
public override string ToString ( ) {
2021-10-30 15:33:38 +02:00
return this . Value ? . ToString ( ) ;
2021-10-29 23:33:15 +02:00
}
2020-05-22 17:02:24 +02:00
/// <summary>
/// Implicitly converts a style property to its value.
/// </summary>
/// <param name="prop">The property to convert</param>
/// <returns>The style that the style property holds</returns>
2019-10-14 21:28:12 +02:00
public static implicit operator T ( StyleProp < T > prop ) {
return prop . Value ;
}
2020-05-22 17:02:24 +02:00
/// <summary>
/// Implicitly converts a style to a style property.
/// </summary>
/// <param name="prop">The property to convert</param>
/// <returns>A style property with the given style value</returns>
2019-11-05 13:28:41 +01:00
public static implicit operator StyleProp < T > ( T prop ) {
return new StyleProp < T > ( prop ) ;
}
2021-12-21 11:39:29 +01:00
/// <summary>
/// Compares the two style properties and returns whether they are equal using <see cref="Equals(MLEM.Ui.Style.StyleProp{T})"/>.
/// </summary>
/// <param name="left">The left style property.</param>
/// <param name="right">The right style property.</param>
/// <returns>Whether the two style properties are equal.</returns>
public static bool operator = = ( StyleProp < T > left , StyleProp < T > right ) {
return left . Equals ( right ) ;
}
/// <summary>
/// Compares the two style properties and returns whether they are not equal using <see cref="Equals(MLEM.Ui.Style.StyleProp{T})"/>.
/// </summary>
/// <param name="left">The left style property.</param>
/// <param name="right">The right style property.</param>
/// <returns>Whether the two style properties are not equal.</returns>
public static bool operator ! = ( StyleProp < T > left , StyleProp < T > right ) {
return ! left . Equals ( right ) ;
}
2019-10-14 21:28:12 +02:00
}
}