Editor/HotCodeEditor/Settings/HotCodeSettingsWindow.cs
using Sandbox;
using Editor;
using System;

/// <summary>
/// HotCode's settings, laid out like s&amp;box's own Editor Settings: pages down the left, and a
/// ControlSheet of properties on each page. Changes save and apply straight away.
/// </summary>
public class HotCodeSettingsWindow : Window
{
	private static HotCodeSettingsWindow _open;

	/// <summary>
	/// Opens the settings, or brings the already-open window to the front.
	/// </summary>
	public static void Open()
	{
		if ( _open.IsValid() )
		{
			_open.Raise();
			_open.Focus( false );
			return;
		}

		_open = new HotCodeSettingsWindow();
	}

	[Menu( "Editor", "HotCode/Settings", HotCodeLogo.IconName )]
	public static void OpenFromEditorMenu() => Open();

	private HotCodeSettingsWindow()
	{
		WindowTitle = "HotCode Settings";
		SetWindowIcon( HotCodeLogo.WindowIcon );
		DeleteOnClose = true;
		Size = new Vector2( 860, 620 );
		MinimumSize = new Vector2( 640, 420 );

		Canvas = new Widget( this );
		Canvas.Layout = Layout.Column();
		Canvas.Layout.Margin = 4;
		Canvas.Layout.Spacing = 4;

		var nav = Canvas.Layout.Add( new NavigationView( Canvas ), 1 );
		nav.AddSectionHeader( "HotCode" );
		nav.AddPage( "Editor", "edit_note", Page( "Editor", sheet =>
		{
			sheet.AddProperty( () => HotCodeSettings.FontSize );
			sheet.AddProperty( () => HotCodeSettings.FontFamily );
			sheet.AddProperty( () => HotCodeSettings.LineSpacing );
			sheet.AddProperty( () => HotCodeSettings.TabSize );
			sheet.AddProperty( () => HotCodeSettings.IndentWithSpaces );
			sheet.AddProperty( () => HotCodeSettings.WordWrap );
		} ) );
		nav.AddPage( "Appearance", "palette", Page( "Appearance", sheet =>
		{
			sheet.AddProperty( () => HotCodeSettings.CodeColors );
			sheet.AddProperty( () => HotCodeSettings.ShowLineNumbers );
			sheet.AddProperty( () => HotCodeSettings.HighlightCurrentLine );
			sheet.AddProperty( () => HotCodeSettings.CursorBlink );
		} ) );
		nav.AddPage( "Code Help", "auto_awesome", Page( "Code Help", sheet =>
		{
			sheet.AddProperty( () => HotCodeSettings.SuggestWhileTyping );
			sheet.AddProperty( () => HotCodeSettings.ParameterHints );
			sheet.AddProperty( () => HotCodeSettings.AutoCloseBrackets );
			sheet.AddProperty( () => HotCodeSettings.UnderlineErrors );
		} ) );
		nav.AddPage( "Files", "save", Page( "Files", sheet =>
		{
			sheet.AddProperty( () => HotCodeSettings.AutoSave );
			sheet.AddProperty( () => HotCodeSettings.AutoSaveDelay );
			sheet.AddProperty( () => HotCodeSettings.TrimTrailingWhitespace );
			sheet.AddProperty( () => HotCodeSettings.InsertFinalNewline );
			sheet.AddProperty( () => HotCodeSettings.ReloadChangedFiles );
		} ) );

		// Footer
		Canvas.Layout.AddSeparator( 1, Theme.Border );
		var footer = Canvas.Layout.AddRow();
		footer.Margin = new Sandbox.UI.Margin( 8, 4, 8, 6 );
		footer.Spacing = 8;

		var note = footer.Add( new Label( "Changes save and apply immediately.", Canvas ) );
		note.SetStyles( $"color: {Theme.TextLight.Hex};" );
		footer.AddStretchCell();

		footer.Add( new Button( "Reset to Defaults", "settings_backup_restore", Canvas )
		{
			Clicked = () => Dialog.AskConfirm( () =>
			{
				HotCodeSettings.ResetToDefaults();
				_open = null;
				Close();
				Open();
			}, "Reset every HotCode setting to its default?", "Reset Settings", "Reset", "Cancel" )
		} );
		footer.Add( new Button.Primary( "Done", "done", Canvas ) { Clicked = () => Close() } );

		Show();
	}

	/// <summary>
	/// A settings page: a heading and a property sheet, padded like s&amp;box's preference pages.
	/// </summary>
	private Widget Page( string title, Action<ControlSheet> fill )
	{
		var page = new Widget( this );
		page.Layout = Layout.Column();
		page.Layout.Margin = 32;
		page.Layout.Spacing = 8;

		var heading = page.Layout.AddRow();
		heading.Spacing = 10;
		heading.Add( new LogoWidget( page, 22, badge: false ) );
		heading.Add( new Label.Subtitle( title, page ) );
		heading.AddStretchCell();

		var sheet = new ControlSheet();
		fill( sheet );
		page.Layout.Add( sheet );
		page.Layout.AddStretchCell();

		return page;
	}
}