diff --git a/SessionZero/AppManager.cs b/SessionZero/AppManager.cs index 496a096..41814b7 100644 --- a/SessionZero/AppManager.cs +++ b/SessionZero/AppManager.cs @@ -9,6 +9,7 @@ public static class AppManager public static ICogwheelConsole SzConsole { get; } = new SessionZeroConsole(); public static CommandsManager CommandsManager { get; } = new(); public static ConsoleControl ConsoleControl { get; } = new(); + public static AppSettings Settings { get; } = new(); public static void ShowConsole() { @@ -27,4 +28,10 @@ public static class AppManager { MainWindow.ChangePage(pageName); } + + [Command(Name = "test")] + private static void Test() + { + COGWHEEL.LogWarning($"Trim size is: {ConsoleControl.OutputTrimSize}"); + } } \ No newline at end of file diff --git a/SessionZero/AppSettings.cs b/SessionZero/AppSettings.cs new file mode 100644 index 0000000..b8f6061 --- /dev/null +++ b/SessionZero/AppSettings.cs @@ -0,0 +1,326 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Avalonia.Media; +using Cogwheel; + +namespace SessionZero; + +public class AppSettings +{ + public string SettingsFilePath { get; set; } = ""; + public Dictionary Settings { get; set; } = new(); + + public AppSetting CreateSetting(string settingName, Type settingType) + { + return new AppSetting(settingName, settingType); + } + + public void AddSetting(AppSetting setting) + { + if (!Settings.TryAdd(setting.SettingName, setting)) + { + COGWHEEL.LogError($"Cannot add setting: '{setting.SettingName}'. Setting already exists."); + } + } + + public AppSetting? GetSetting(string settingName) + { + if (!Settings.TryGetValue(settingName, out var setting)) + { + COGWHEEL.LogError($"Cannot get setting: '{settingName}'. Setting does not exist."); + return null; + } + + return setting; + } + + public void RemoveSetting(string settingName) + { + if (!Settings.Remove(settingName)) + { + COGWHEEL.LogError($"Cannot remove setting: '{settingName}. It may not exist."); + } + } + + public bool SetSettingValue(string settingName, T value) + { + if (Settings.TryGetValue(settingName, out var setting)) + { + return setting.SetValue(value); + } + + COGWHEEL.LogError($"Cannot set setting: '{settingName}'. Setting does not exist."); + return false; + } + + public bool SetSettingValue(string settingName, string value) + { + if (Settings.TryGetValue(settingName, out var setting)) + { + return setting.SetValue(value); + } + + COGWHEEL.LogError($"Cannot set setting: '{settingName}'. Setting does not exist."); + return false; + } + + public T? GetValue(string settingName) + { + if (Settings.TryGetValue(settingName, out var setting)) + { + return setting.GetValue(); + } + + return default; + } + + public string GetValueAsString(string settingName) + { + if (!Settings.TryGetValue(settingName, out var setting) || setting == null) + { + COGWHEEL.LogError($"Cannot get setting '{settingName}'. Setting does not exist."); + return string.Empty; + } + + var type = setting.SettingType; + + try + { + var method = typeof(AppSetting).GetMethod(nameof(AppSetting.GetValue))!; + var generic = method.MakeGenericMethod(type); + + var valueObj = generic.Invoke(setting, null); + + if (valueObj == null) + return string.Empty; + + if (type == typeof(string)) + return (string)valueObj; + + if (type.IsPrimitive || type.IsEnum || type == typeof(decimal)) + return Convert.ToString(valueObj) ?? string.Empty; + + return valueObj.ToString() ?? string.Empty; + } + catch (Exception ex) + { + COGWHEEL.LogError($"Failed to get setting '{settingName}' as string: {ex.Message}"); + return string.Empty; + } + } + + public void SaveToFile() {} + public void LoadFromFile() {} +} + +public class AppSetting(string settingName, Type settingType) +{ + public string SettingName { get; } = settingName; + public Type SettingType { get; } = settingType; + + private object? _settingValue; + + public T GetValue() + { + if (typeof(T) != SettingType) + { + COGWHEEL.LogError($"Cannot get value of setting '{SettingName}': Setting is type '{SettingType.Name}' but GetValue was called with type '{typeof(T).Name}'.'"); + } + + return _settingValue is null ? default! : (T)_settingValue; + } + + + public bool SetValue(T value) + { + if (typeof(T) != SettingType) + { + COGWHEEL.LogError($"Cannot set value of setting '{SettingName}': Setting is type '{SettingType.Name}' but SetValue was called with type '{typeof(T).Name}'.'"); + return false; + } + + _settingValue = value!; + return true; + } + + public bool SetValue(object? value) + { + if (value == null) + { + _settingValue = null; + return true; + } + + if (SettingType.IsInstanceOfType(value)) + { + _settingValue = value; + return true; + } + + try + { + var converted = Convert.ChangeType(value, SettingType); + _settingValue = converted; + return true; + } + catch + { + COGWHEEL.LogError($"Cannot convert value '{value}' to {SettingType.Name} for setting '{SettingName}'."); + return false; + } + } + + public bool SetValue(string valueString) + { + try + { + object? parsedValue = null; + + if (SettingType == typeof(string)) + { + parsedValue = valueString; + } + else if (SettingType == typeof(int)) + { + if (!int.TryParse(valueString, out var i)) + { + COGWHEEL.LogError($"Cannot parse '{valueString}' as int for setting '{SettingName}'."); + return false; + } + parsedValue = i; + } + else if (SettingType == typeof(float)) + { + if (!float.TryParse(valueString, out var f)) + { + COGWHEEL.LogError($"Cannot parse '{valueString}' as float for setting '{SettingName}'."); + return false; + } + parsedValue = f; + } + else if (SettingType == typeof(bool)) + { + if (!bool.TryParse(valueString, out var b)) + { + COGWHEEL.LogError($"Cannot parse '{valueString}' as bool for setting '{SettingName}'."); + return false; + } + parsedValue = b; + } + else + { + COGWHEEL.LogError( + $"Unsupported setting type '{SettingType.Name}' in SetValue(string) for setting '{SettingName}'."); + return false; + } + + _settingValue = parsedValue; + return true; + } + catch (Exception ex) + { + COGWHEEL.LogError($"Failed to set setting '{SettingName}' to '{valueString}': {ex.Message}"); + return false; + } + } +} + +static class AppSettingsCommands +{ + [Command(Name = "setsetting")] + public static void SetSetting(string settingName, string value) + { + if (AppManager.Settings.SetSettingValue(settingName, value)) + { + COGWHEEL.Log($"Setting '{settingName}' set to '{value}'."); + } + // else + // { + // COGWHEEL.LogError($"Could not set setting '{settingName}' to '{value}'."); + // } + } + + [Command(Name = "getsetting")] + public static void GetSetting(string settingName) + { + var value = AppManager.Settings.GetValueAsString(settingName); + COGWHEEL.Log($"Setting '{settingName}' value is: ({AppManager.Settings.GetSetting(settingName)?.SettingType.Name}){value}."); + } + + [Command(Name = "listsettings")] + public static void ListSettings(string settingName = "") + { + var outputString = $"-- Settings --\n"; + if (string.IsNullOrEmpty(settingName)) + { + foreach (var setting in AppManager.Settings.Settings) + { + outputString += + $"{setting.Value.SettingName}: {setting.Value.SettingType.Name} = {AppManager.Settings.GetValueAsString(setting.Key)}\n"; + } + + AppManager.ConsoleControl.Log(outputString, Colors.CadetBlue); + } + else + { + COGWHEEL.LogWarning($"Searching for settings is not implemented yet."); + } + } + + + // TODO: Go update Cogwheel to accept array arguments somehow + // [Command(Name = "setting")] + // public static void SettingCommand(string[] args) + // { + // if (args.Length == 0) + // { + // COGWHEEL.LogError("No arguments supplied. Usage: 'setting '"); + // } + // + // var action = args[0]; + // List actionArgs = new(); + // for (int i = 1; i < args.Length; i++) + // { + // actionArgs.Add(args[i]); + // } + // + // switch (action) + // { + // case "set": + // if (actionArgs.Count == 2) + // { + // var settingName = args[0]; + // var settingValue = args[1]; + // + // if (AppManager.Settings.SetSettingValue(settingName, settingValue)) + // { + // COGWHEEL.Log($"Setting '{settingName}' successfully set to '{settingValue}'."); + // } + // } + // else + // { + // COGWHEEL.LogError($"Invalid number of arguments for '{action}'. Usage: 'setting set '"); + // } + // break; + // case "get": + // if (actionArgs.Count == 1) + // { + // var val = AppManager.Settings.GetValueAsString(args[0]); + // COGWHEEL.Log($"Value of Setting '{args[0]}' is '{val}'."); + // } + // else + // { + // COGWHEEL.LogError($"Invalid number of arguments for '{action}'. Usage: 'setting get '"); + // } + // break; + // case "add": + // break; + // case "remove": + // break; + // default: + // COGWHEEL.LogError($"Unknown argument '{action}' for 'setting' command. Options are 'set, get, add, remove'."); + // break; + // } + // } +} \ No newline at end of file diff --git a/SessionZero/Cogwheel/ConsoleControl.axaml b/SessionZero/Cogwheel/ConsoleControl.axaml index 33f9293..0be36de 100644 --- a/SessionZero/Cogwheel/ConsoleControl.axaml +++ b/SessionZero/Cogwheel/ConsoleControl.axaml @@ -5,7 +5,9 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SessionZero.Cogwheel.ConsoleControl"> - + + + diff --git a/SessionZero/Cogwheel/ConsoleControl.axaml.cs b/SessionZero/Cogwheel/ConsoleControl.axaml.cs index 66e2991..a59f31a 100644 --- a/SessionZero/Cogwheel/ConsoleControl.axaml.cs +++ b/SessionZero/Cogwheel/ConsoleControl.axaml.cs @@ -10,8 +10,11 @@ namespace SessionZero.Cogwheel; public partial class ConsoleControl : UserControl { + public int OutputTrimSize { get; set; } = 200; + private TextBlock? _output; private TextBox? _input; + private ScrollViewer? _outputScrollViewer; public ConsoleControl() { @@ -19,6 +22,7 @@ public partial class ConsoleControl : UserControl _output = this.FindControl("Output"); _input = this.FindControl("Input"); + _outputScrollViewer = this.FindControl("OutputScrollView"); _input?.KeyDown += Input_OnKeyDown; } @@ -27,14 +31,37 @@ public partial class ConsoleControl : UserControl { if (e.Key == Key.Enter) { - var inputText = _input!.Text ?? string.Empty; - Log(inputText); - if (inputText.Length > 0) COGWHEEL.RunCommand(inputText); - _input.Text = string.Empty; + SubmitInput(); e.Handled = true; } } + private void SubmitInput() + { + var inputText = _input!.Text ?? string.Empty; + Log(inputText); + if (inputText.Length > 0) COGWHEEL.RunCommand(inputText); + _input.Text = string.Empty; + TrimOutput(); + ScrollToEnd(); + } + + private void TrimOutput() + { + var maxInLines = OutputTrimSize * 3; + while (_output?.Inlines?.Count > maxInLines) + { + if (_output?.Inlines?.Count >= 3) + { + _output?.Inlines?.RemoveRange(0,3); + } + else + { + _output?.Inlines?.RemoveAt(0); + } + } + } + public void Log(string text, Color? color = null) { if (_output == null) @@ -58,4 +85,9 @@ public partial class ConsoleControl : UserControl { _output?.Inlines?.Clear(); } + + public void ScrollToEnd() + { + _outputScrollViewer?.ScrollToEnd(); + } } \ No newline at end of file diff --git a/SessionZero/MainWindow.axaml.cs b/SessionZero/MainWindow.axaml.cs index 35fc19a..cb6c5bf 100644 --- a/SessionZero/MainWindow.axaml.cs +++ b/SessionZero/MainWindow.axaml.cs @@ -28,6 +28,9 @@ public partial class MainWindow : Window KeyDownEvent.AddClassHandler(OnKeyDown, handledEventsToo: true); ChangePage("Home"); + + AppManager.Settings.AddSetting(new AppSetting("test", typeof(int))); + AppManager.Settings.SetSettingValue("test", 1); } public void ChangePage(string pageName) diff --git a/SessionZero/Pages/SettingsPage.axaml b/SessionZero/Pages/SettingsPage.axaml index 71924bd..21c0cc8 100644 --- a/SessionZero/Pages/SettingsPage.axaml +++ b/SessionZero/Pages/SettingsPage.axaml @@ -6,5 +6,15 @@ x:Class="SessionZero.Pages.SettingsPage"> + + + + + 10 + + + + + diff --git a/SessionZero/Pages/SettingsPage.axaml.cs b/SessionZero/Pages/SettingsPage.axaml.cs index 821243e..5a06a49 100644 --- a/SessionZero/Pages/SettingsPage.axaml.cs +++ b/SessionZero/Pages/SettingsPage.axaml.cs @@ -1,5 +1,6 @@ using Avalonia; using Avalonia.Controls; +using Avalonia.Controls.Primitives; using Avalonia.Markup.Xaml; namespace SessionZero.Pages; @@ -8,10 +9,28 @@ public partial class SettingsPage : UserControl, IPageBase { public string PageName { get; set; } = "Settings"; + private Slider? _consoleTrimSlider; + private TextBlock? _consoleTrimSliderLabel; + public SettingsPage() { InitializeComponent(); + + _consoleTrimSlider = this.FindControl("ConsoleTrimSlider"); + _consoleTrimSliderLabel = this.FindControl("ConsoleTrimSliderValue"); + + _consoleTrimSlider?.ValueChanged += ConsoleTrimSliderOnValueChanged; + } + + private void ConsoleTrimSliderOnValueChanged(object? sender, RangeBaseValueChangedEventArgs e) + { + AppManager.ConsoleControl.OutputTrimSize = (int)e.NewValue; + _consoleTrimSliderLabel?.Text = AppManager.ConsoleControl.OutputTrimSize.ToString(); + } + + public void Refresh() + { + _consoleTrimSlider?.Value = AppManager.ConsoleControl.OutputTrimSize; + _consoleTrimSliderLabel?.Text = AppManager.ConsoleControl.OutputTrimSize.ToString(); } - - public void Refresh() { } } \ No newline at end of file diff --git a/SessionZero/SessionZero.sln.DotSettings.user b/SessionZero/SessionZero.sln.DotSettings.user index 6368e8e..22c5325 100644 --- a/SessionZero/SessionZero.sln.DotSettings.user +++ b/SessionZero/SessionZero.sln.DotSettings.user @@ -2,4 +2,5 @@ ForceIncluded ForceIncluded ForceIncluded - ForceIncluded \ No newline at end of file + ForceIncluded + ForceIncluded \ No newline at end of file