namespace Sandbox.UI;
public partial class Panel
{
///
/// A list of CSS classes applied to this panel.
///
[Hide]
public IEnumerable Class => _class ?? Enumerable.Empty();
///
internal HashSet _class;
internal string _classes;
///
/// All CSS classes applied to this panel, separated with spaces.
///
[Property]
public string Classes
{
get
{
if ( _classes == null )
_classes = string.Join( " ", Class );
return _classes;
}
set
{
_class?.Clear();
AddClass( value );
}
}
///
/// Adds CSS class(es) separated by spaces to this panel.
///
public void AddClass( string classname )
{
if ( string.IsNullOrWhiteSpace( classname ) )
return;
if ( classname.Contains( ' ' ) )
{
AddClasses( classname );
return;
}
classname = classname.ToLowerInvariant();
_class ??= new HashSet( StringComparer.OrdinalIgnoreCase );
if ( _class.Contains( classname ) ) return;
_class.Add( classname );
_classes = null;
// Adding a class changes the selector so children
// may have rules that now match - need to update those too.
StyleSelectorsChanged( true, true );
}
///
/// Sets a specific CSS class active or not.
///
public void SetClass( string classname, bool active )
{
if ( string.IsNullOrWhiteSpace( classname ) )
return;
if ( active ) AddClass( classname );
else RemoveClass( classname );
}
///
/// Add a class for a set amount of seconds. If called multiple times, we will stomp the earlier call.
///
public void FlashClass( string classname, float seconds )
{
if ( string.IsNullOrWhiteSpace( classname ) )
return;
AddClass( classname );
InvokeOnce( $"FlashClass;{classname}", seconds, () => RemoveClass( classname ) );
}
///
/// Add a class if we don't have it, remove a class if we do have it
///
public void ToggleClass( string classname )
{
if ( string.IsNullOrWhiteSpace( classname ) )
return;
SetClass( classname, !HasClass( classname ) );
}
///
/// Add multiple CSS classes separated by spaces to this panel.
///
void AddClasses( string classname )
{
if ( string.IsNullOrWhiteSpace( classname ) )
return;
foreach ( var cname in classname.Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ) )
{
AddClass( cname );
}
}
///
/// Removes given CSS class from this panel.
///
public void RemoveClass( string classname )
{
if ( _class == null ) return;
if ( string.IsNullOrWhiteSpace( classname ) ) return;
if ( classname.Contains( ' ' ) )
{
foreach ( var cname in classname.Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ) )
{
RemoveClass( cname );
}
return;
}
classname = classname.ToLowerInvariant();
if ( _class.Remove( classname ) )
{
// Removing a class changes the selector so children
// may have rules that now match - need to update those too.
StyleSelectorsChanged( true, true );
_classes = null;
}
}
///
/// Whether we have the given CSS class or not.
///
public bool HasClass( string classname )
{
if ( _class == null ) return false;
if ( string.IsNullOrWhiteSpace( classname ) ) return false;
if ( _class.Contains( classname ) ) return true;
return false;
}
///
/// Whether if we have all of these CSS classes.
///
internal bool HasClasses( string[] classes )
{
if ( _class == null ) return false;
for ( int i = 0; i < classes.Length; i++ )
{
if ( !_class.Contains( classes[i] ) )
return false;
}
return true;
}
///
/// Dirty the styles on this panel
///
internal void DirtyStylesRecursive()
{
StyleSelectorsChanged( true, true );
Style.InvalidateBroadphase();
}
///
/// Dirty the styles of this class and its children recursively.
///
internal void DirtyStylesWithStyle( Styles withStyles, bool skipTransitions = false )
{
if ( Style.ContainsStyle( withStyles ) )
{
Style.UnderlyingStyleHasChanged();
StyleSelectorsChanged( false, false );
if ( skipTransitions )
SkipTransitions();
}
foreach ( var child in Children )
{
child.DirtyStylesWithStyle( withStyles, skipTransitions );
}
}
Dictionary> classBinds;
///
/// Switch the class on or off depending on the value of the bool.
///
public void BindClass( string className, Func func )
{
classBinds ??= new();
classBinds[className] = func;
}
private void RunClassBinds()
{
if ( classBinds is null ) return;
foreach ( var c in classBinds )
{
SetClass( c.Key, c.Value() );
}
}
}