Files
sbox-public/game/addons/tools/Code/Editor/ExpandGroup.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

196 lines
3.8 KiB
C#

using System;
namespace Editor;
public class ExpandGroup : Widget
{
Widget widget;
public string Title { get; set; } = "Untitled Group";
public string Icon { get; set; }
protected int headerSize;
public Action OnCreateWidget { get; set; }
bool openState;
public ExpandGroup( Widget parent ) : base( parent )
{
SetHeaderSize( (int)(Theme.RowHeight * 1.5f) );
}
public void SetWidget( Widget w )
{
widget?.Destroy();
widget = w;
widget.Parent = this;
widget.Position = new Vector2( 0, headerSize );
widget.AdjustSize();
widget.Width = Width;
Update();
DoLayout();
}
public void SetHeaderSize( int height )
{
headerSize = height;
MinimumSize = height;
if ( widget.IsValid() )
widget.Position = new Vector2( 0, headerSize );
}
protected override void DoLayout()
{
base.DoLayout();
if ( widget.IsValid() )
{
widget.AdjustSize();
widget.Width = Width;
if ( !Animate.IsActive( this ) )
FixedHeight = IdealHeight;
}
}
protected override void OnPaint()
{
bool isExpanded = openState;
var headerRect = new Rect( 0, 0, Width, headerSize );
headerRect.Bottom--;
Paint.ClearPen();
Paint.SetBrush( Theme.ButtonBackground.WithAlpha( 0.1f ) );
Paint.DrawRect( LocalRect.Shrink( 0, 1 ), 4.0f );
Paint.ClearBrush();
var rect = new Rect( 0, Size );
rect.Height = headerSize;
Paint.SetPen( Theme.Text.WithAlpha( isExpanded ? 0.5f : 0.2f ) );
Paint.DrawIcon( headerRect.Shrink( 4, 0 ), isExpanded ? "arrow_drop_down" : "arrow_right", 24, TextFlag.RightCenter );
rect.Left += 14;
if ( !string.IsNullOrWhiteSpace( Icon ) )
{
Paint.SetPen( Theme.Text.WithAlpha( isExpanded ? 0.8f : 0.4f ) );
Paint.DrawIcon( headerRect.Shrink( rect.Left, 0, 0, 0 ), Icon, 18, TextFlag.LeftCenter );
rect.Left += 34;
}
Paint.SetDefaultFont( 8, 400 );
Paint.SetPen( Theme.Text.WithAlpha( isExpanded ? 1.0f : 0.4f ) );
Paint.DrawText( headerRect.Shrink( rect.Left, 0, 0, 0 ), Title, TextFlag.LeftCenter );
if ( !isExpanded )
return;
var bodyRect = new Rect( 0, headerSize, Width, Height - headerSize );
bodyRect.Bottom--;
bodyRect.Right--;
}
public virtual void SetOpenState( bool state )
{
if ( openState == state )
return;
openState = state;
if ( !state && !widget.IsValid() )
return;
if ( state && !widget.IsValid() )
{
if ( OnCreateWidget != null )
{
OnCreateWidget?.Invoke();
BindSystem.Tick();
}
OnOpenStateChanged( true );
return;
}
OnOpenStateChanged( state );
}
protected override void OnDoubleClick( MouseEvent e )
{
}
protected override void OnMousePress( MouseEvent e )
{
base.OnMousePress( e );
if ( e.LeftMouseButton && e.LocalPosition.y < headerSize )
{
var oldHeight = Height;
SetOpenState( !openState );
Animate.CancelAll( this, true );
if ( openState ) Animate.Add( this, 0.5f, oldHeight, IdealHeight, x => { FixedHeight = x; }, "bounce-out" );
else Animate.Add( this, 0.2f, oldHeight, IdealHeight, x => { FixedHeight = x; }, "ease-out" );
}
}
protected virtual void OnOpenStateChanged( bool newState )
{
if ( !string.IsNullOrEmpty( StateCookieName ) )
{
ProjectCookie.Set( StateCookieName, newState );
}
if ( newState && widget.IsValid() )
widget.Visible = true;
}
float IdealHeight
{
get
{
float height = headerSize;
if ( widget.IsValid() && openState )
{
height += widget.Height;
}
return height;
}
}
public void SetHeight()
{
Animate.CancelAll( this, true );
FixedHeight = IdealHeight;
Update();
}
string _stateCookieName;
public string StateCookieName
{
get => _stateCookieName;
set
{
if ( _stateCookieName == value ) return;
_stateCookieName = value;
var state = ProjectCookie.Get( _stateCookieName, openState );
SetOpenState( state );
SetHeight();
}
}
}