Code/InteractiveComputer/Apps/SettingsApp.cs
using System;
using System.Linq;
using Sandbox.UI;
namespace PaneOS.InteractiveComputer.Apps;
[ComputerApp( "system.settings", "Control Panel", Icon = "CP", SortOrder = 5 )]
public sealed class SettingsApp : IComputerApp
{
public ComputerAppSession Run( ComputerAppContext context )
{
return new ComputerAppSession
{
Title = "Control Panel",
Icon = "CP",
Content = new SettingsPanel( context )
};
}
}
[StyleSheet( "InteractiveComputerApps.scss" )]
public sealed class SettingsPanel : ComputerWarmupPanel
{
private readonly ComputerAppContext context;
private int lastVersion = -1;
public SettingsPanel( ComputerAppContext context )
{
this.context = context;
AddClass( "settings-app app-document" );
Rebuild();
}
public override void Tick()
{
base.Tick();
if ( lastVersion == context.Runtime.Version )
return;
Rebuild();
}
protected override void WarmupRefresh()
{
Rebuild();
}
private void Rebuild()
{
lastVersion = context.Runtime.Version;
DeleteChildren( true );
new Label( "Control Panel" ) { Parent = this }.AddClass( "app-heading" );
BuildHardwareSection();
BuildWallpaperSection();
BuildBrowserSection();
BuildSystemSection();
BuildAppSettingsSection();
}
private void BuildHardwareSection()
{
var section = CreateSection( "Hardware" );
CreateSettingRow( section, $"Screen saver delay: {context.Runtime.State.ScreenSaver.DelaySeconds:0}s",
("-15s", () => AdjustScreenSaverDelay( -15f )),
("+15s", () => AdjustScreenSaverDelay( 15f )) );
}
private void BuildWallpaperSection()
{
var section = CreateSection( "Wallpaper" );
CreateSettingRow( section, $"Current wallpaper: {context.Runtime.State.DesktopWallpaper}",
("Default", () => SetWallpaper( "default" )),
("Blue", () => SetWallpaper( "blue" )),
("Sunset", () => SetWallpaper( "sunset" )) );
}
private void BuildBrowserSection()
{
var section = CreateSection( "Ridge" );
var homeUrl = context.Runtime.LoadAppSetting( "system.ridge", "home_url" ) ?? "paneos://default";
CreateSettingRow( section, $"Home page: {homeUrl}",
("Poodle", () => SetRidgeHome( "paneos://default" )),
("Blank", () => SetRidgeHome( "paneos://home" )),
("Custom...", PromptForCustomHome) );
}
private void BuildAppSettingsSection()
{
new Label( "App Settings" ) { Parent = this }.AddClass( "settings-section-title" );
foreach ( var app in ComputerAppRegistry.Apps
.Where( x => x.ShowInControlPanel && !x.IsBackgroundProcess )
.OrderBy( x => x.SortOrder )
.ThenBy( x => x.Title, StringComparer.OrdinalIgnoreCase ) )
{
new Label( app.Title ) { Parent = this }.AddClass( "settings-app-title" );
var section = new Panel { Parent = this };
section.AddClass( "settings-section" );
var installed = context.Runtime.IsAppInstalled( app.Id );
if ( app.HasWindow && app.AllowControlPanelWindowSizing )
{
var width = LoadWindowSetting( app.Id, "window_width", app.DefaultWindowWidth ?? 560 );
var height = LoadWindowSetting( app.Id, "window_height", app.DefaultWindowHeight ?? 380 );
CreateSettingRow(
section,
$"Default window size: {width} x {height}",
("-W", () => AdjustWindowSetting( app, "window_width", width, -20, 260, 1600 )),
("+W", () => AdjustWindowSetting( app, "window_width", width, 20, 260, 1600 )),
("-H", () => AdjustWindowSetting( app, "window_height", height, -20, 180, 1200 )),
("+H", () => AdjustWindowSetting( app, "window_height", height, 20, 180, 1200 )),
("Reset", () => ResetWindowSettings( app )) );
}
if ( app.CanUninstallFromControlPanel )
{
CreateSettingRow(
section,
$"Installed: {(installed ? "Yes" : "No")}",
(installed ? "Uninstall" : "Install", () =>
{
if ( installed )
context.Runtime.UninstallApp( app.Id );
else
context.Runtime.InstallApp( app.Id );
}) );
}
}
}
private void BuildSystemSection()
{
var section = CreateSection( "System" );
CreateSettingRow( section, "PaneOS maintenance and install flows",
("Check Updates", () => context.Runtime.RunSystemUpdateScan()),
("Install Codec", () => context.Runtime.RunPackageInstall( "Media Codec Pack" )),
("Install Tools", () => context.Runtime.RunPackageInstall( "Gamer Tools" )) );
CreateSettingRow( section, $"Dark mode: {(context.Runtime.State.DarkModeEnabled ? "On" : "Off")}",
(context.Runtime.State.DarkModeEnabled ? "Disable" : "Enable", ToggleDarkMode) );
}
private Panel CreateSection( string title )
{
new Label( title ) { Parent = this }.AddClass( "settings-section-title" );
var section = new Panel { Parent = this };
section.AddClass( "settings-section" );
return section;
}
private static void CreateSettingRow( Panel section, string label, params (string Label, Action Handler)[] buttons )
{
var row = new Panel { Parent = section };
row.AddClass( "settings-row" );
new Label( label ) { Parent = row }.AddClass( "settings-row-label" );
var actions = new Panel { Parent = row };
actions.AddClass( "settings-actions" );
foreach ( var buttonDef in buttons )
{
var button = new Button( buttonDef.Label ) { Parent = actions };
button.AddClass( "settings-button" );
button.AddEventListener( "onclick", buttonDef.Handler );
}
}
private void AdjustScreenSaverDelay( float delta )
{
context.Runtime.State.ScreenSaver.DelaySeconds = MathF.Max( 5f, context.Runtime.State.ScreenSaver.DelaySeconds + delta );
context.Runtime.MarkChanged();
}
private void SetWallpaper( string wallpaper )
{
context.Runtime.State.DesktopWallpaper = wallpaper;
context.Runtime.MarkChanged();
}
private void SetRidgeHome( string url )
{
context.Runtime.SaveAppSetting( "system.ridge", "home_url", url );
}
private void ToggleDarkMode()
{
context.Runtime.State.DarkModeEnabled = !context.Runtime.State.DarkModeEnabled;
context.Runtime.MarkChanged();
}
private int LoadWindowSetting( string appId, string key, int fallback )
{
var value = context.Runtime.LoadAppSetting( appId, key );
return int.TryParse( value, out var parsed ) ? parsed : fallback;
}
private void AdjustWindowSetting( ComputerAppDescriptor app, string key, int currentValue, int delta, int min, int max )
{
var nextValue = Math.Clamp( currentValue + delta, min, max );
context.Runtime.SaveAppSetting( app.Id, key, nextValue.ToString() );
}
private void ResetWindowSettings( ComputerAppDescriptor app )
{
if ( app.DefaultWindowWidth.HasValue )
context.Runtime.SaveAppSetting( app.Id, "window_width", app.DefaultWindowWidth.Value.ToString() );
if ( app.DefaultWindowHeight.HasValue )
context.Runtime.SaveAppSetting( app.Id, "window_height", app.DefaultWindowHeight.Value.ToString() );
}
private void PromptForCustomHome()
{
context.ShowMessageBox(
new ComputerMessageBoxOptions
{
Title = "Custom Home Page",
Message = "Enter a URL or a local PaneOS address.",
Icon = "RG",
HasTextInput = true,
TextInputValue = context.Runtime.LoadAppSetting( "system.ridge", "home_url" ) ?? "paneos://default",
TextInputPlaceholder = "https://example.com or paneos://default",
Buttons = new[] { "Save", "Cancel" }
},
result =>
{
if ( !result.ButtonPressed.Equals( "Save", StringComparison.OrdinalIgnoreCase ) )
return;
SetRidgeHome( string.IsNullOrWhiteSpace( result.TextValue ) ? "paneos://default" : result.TextValue.Trim() );
} );
}
}