XGUI/XGUIPanel.cs
using Sandbox;
using Sandbox.UI;
using System.Linq;
namespace XGUI;
/// <summary>
/// A themeable panel designed to be at the root of the XGUI hierarchy. For example, windows, popups, etc.
/// </summary>
public class XGUIPanel : Panel
{
public string CurrentTheme = "";
public XGUIPanel()
{
AddClass( "xgui-panel" );
}
protected override void OnAfterTreeRender( bool firstTime )
{
base.OnAfterTreeRender( firstTime );
if ( firstTime )
{
// Set the initial theme
if ( CurrentTheme == "" ) SetTheme( Scene.GetSystem<XGUISystem>().GlobalTheme );
}
}
public void SetTheme( string theme )
{
var parent = this.Parent;
// Remove existing style sheets (except .razor.scss ones)
foreach ( var style in AllStyleSheets.ToList() )
{
if ( !style.FileName.EndsWith( ".razor.scss" ) && !style.FileName.EndsWith( ".cs.scss" ) )
{
//Log.Info( style.FileName );
StyleSheet.Remove( style.FileName );
}
}
CurrentTheme = theme;
var styleToApply = Sandbox.UI.StyleSheet.FromFile( theme );
// Apply the new style
StyleSheet.Add( styleToApply );
// Force immediate style update
Style.Dirty();
// Force a complete rebuild by temporarily removing from parent and re-adding
// This is more aggressive but guarantees a full refresh
Parent = null;
Parent = parent;
// Force layout recalculation - traverse child hierarchy
ForceStyleUpdateRecursive( this );
}
private void ForceStyleUpdateRecursive( Panel panel )
{
// Mark this panel's style as dirty to force recalculation
panel.Style.Dirty();
// Update all immediate children
foreach ( var child in panel.Children )
{
if ( child == null || !child.IsValid() ) continue;
// Mark the child's style as dirty
child.Style.Dirty();
// Recursively update this child's children
ForceStyleUpdateRecursive( child );
}
}
}