Page navigation, CogwheelConsole

This commit is contained in:
2025-11-29 00:35:35 -06:00
parent e1502b21ad
commit c8a7ec0f09
15 changed files with 328 additions and 7 deletions

0
SessionZero/.noai Normal file
View File

View File

@@ -1,23 +1,36 @@
using System.Reflection;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Cogwheel;
using SessionZero.Cogwheel;
namespace SessionZero;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
InitCogwheel();
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
AppManager.MainWindow = new MainWindow();
desktop.MainWindow = AppManager.MainWindow;
}
base.OnFrameworkInitializationCompleted();
}
private void InitCogwheel()
{
AppManager.CommandsManager.AddAssembly(Assembly.GetAssembly(typeof(DeafultCogwheelConsole)));
AppManager.CommandsManager.AddAssembly(Assembly.GetExecutingAssembly());
COGWHEEL.Initialize(AppManager.CommandsManager, AppManager.SzConsole);
}
}

41
SessionZero/AppManager.cs Normal file
View File

@@ -0,0 +1,41 @@
using Cogwheel;
using SessionZero.Cogwheel;
namespace SessionZero;
public static class AppManager
{
public static MainWindow MainWindow { get; set; }
public static ICogwheelConsole SzConsole { get; } = new SessionZeroConsole();
public static CommandsManager CommandsManager { get; } = new();
public static ConsoleControl ConsoleControl { get; } = new();
public static void ShowConsole()
{
MainWindow.ToggleConsole(true);
}
public static void HideConsole()
{
MainWindow.ToggleConsole(false);
}
// -- Global Commands -- //
[Command(Name = "exit", Description = "Hides the console")]
public static void ExitConsole()
{
SzConsole.Exit();
}
[Command(Name = "page", Description = "Change the current page to the given value, if it exists")]
public static void ChangePage(string pageName)
{
MainWindow.ChangePage(pageName);
}
[Command(Name = "err")]
public static void ErrTest(string message)
{
COGWHEEL.LogError(message);
}
}

View File

@@ -0,0 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SessionZero.Cogwheel.ConsoleControl">
<Grid Background="Transparent" RowDefinitions="*, Auto, *" HorizontalAlignment="Stretch">
<TextBlock Grid.Row="0" Name="Output" Foreground="White" Background="#7F272727" HorizontalAlignment="Stretch" TextWrapping="Wrap"></TextBlock>
<TextBox Grid.Row="1" Name="Input" Background="#7F272727" Foreground="White" Height="30" AcceptsReturn="False" AcceptsTab="False"></TextBox>
</Grid>
</UserControl>

View File

@@ -0,0 +1,61 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Cogwheel;
namespace SessionZero.Cogwheel;
public partial class ConsoleControl : UserControl
{
private TextBlock? _output;
private TextBox? _input;
public ConsoleControl()
{
InitializeComponent();
_output = this.FindControl<TextBlock>("Output");
_input = this.FindControl<TextBox>("Input");
_input?.KeyDown += Input_OnKeyDown;
}
private void Input_OnKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var inputText = _input!.Text ?? string.Empty;
Log(inputText);
if (inputText.Length > 0) COGWHEEL.RunCommand(inputText);
_input.Text = string.Empty;
e.Handled = true;
}
}
public void Log(string text, Color? color = null)
{
if (_output == null)
return;
_output?.Inlines?.Add(new Run("> ")
{
Foreground = Brushes.LightGray
});
_output?.Inlines?.Add(new Run(text)
{
Foreground = color != null ? new SolidColorBrush(color.Value)
: Brushes.White
});
_output?.Inlines?.Add(new LineBreak());
}
public void ClearOutput()
{
_output?.Inlines?.Clear();
}
}

View File

@@ -0,0 +1,50 @@
using System;
using Avalonia.Media;
using Cogwheel;
namespace SessionZero.Cogwheel;
public class SessionZeroConsole : ICogwheelConsole
{
public string OpeningMessage { get; set; } = "SessionZero Console";
public bool IsRunning { get; set; }
public CommandsManager CommandsManager { get; set; }
public void Initialize(CommandsManager commandsManager)
{
CommandsManager = commandsManager;
}
public void Log(string message)
{
Console.WriteLine(message);
AppManager.ConsoleControl.Log(message);
}
public void LogError(string message)
{
Console.WriteLine("Error: " + message);
AppManager.ConsoleControl.Log($"Error: {message}", Colors.Red);
}
public void LogWarning(string message)
{
Console.WriteLine("Warning: " + message);
AppManager.ConsoleControl.Log($"Warning: {message}", Colors.Yellow);
}
public void Write(string message)
{
Console.Write(message);
}
public void ClearConsole()
{
AppManager.ConsoleControl.ClearOutput();
}
public void Exit()
{
AppManager.HideConsole();
}
}

View File

@@ -13,19 +13,19 @@
<Svg Path="/Assets/Images/sessionzero-icon.svg" Width="30"></Svg>
</Border>
<Button HorizontalAlignment="Stretch">
<Button Name="HomeButton" HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal">
<Label Classes="icon" Content="&#xe2c2;"></Label>
<Label Content="Home"></Label>
</StackPanel>
</Button>
<Button HorizontalAlignment="Stretch">
<Button Name="SessionsButton" HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal">
<Label Classes="icon" Content="&#xe26e;"></Label>
<Label Content="Sessions"></Label>
</StackPanel>
</Button>
<Button HorizontalAlignment="Stretch">
<Button Name="LibraryButton" HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal">
<Label Classes="icon" Content="&#xe758;"></Label>
<Label Content="Library"></Label>
@@ -33,14 +33,17 @@
</Button>
</StackPanel>
<Button Classes="icon-only" Grid.Row="1">
<Button Name="SettingsButton" Classes="icon-only" Grid.Row="1">
<Label Classes="icon-only" Content="&#xe270;"></Label>
</Button>
</Grid>
</Border>
<Border Grid.Column="1" Margin="15">
<ContentControl Content="tmp"></ContentControl>
<ContentControl Name="MainContentControl" Content="tmp"></ContentControl>
</Border>
<ContentControl Grid.Column="0" Name="Overlay" Grid.ColumnSpan="2" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Background="#80000000" IsVisible="False"/>
</Grid>
</Window>

View File

@@ -1,11 +1,90 @@
using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Input;
using Cogwheel;
using SessionZero.Cogwheel;
using SessionZero.Pages;
namespace SessionZero;
public partial class MainWindow : Window
{
private Dictionary<string, IPageBase> _pages = new();
private ContentControl? _mainContentControl;
private ContentControl? _overlayContentControl;
private Button? _homeButton;
private Button? _sessionsButton;
private Button? _libraryButton;
private Button? _settingsButton;
public MainWindow()
{
InitializeComponent();
InitControls();
InitPages();
KeyDownEvent.AddClassHandler<TopLevel>(OnKeyDown, handledEventsToo: true);
ChangePage("Home");
}
}
public void ChangePage(string pageName)
{
if (_pages.TryGetValue(pageName.ToLower(), out var page))
{
_mainContentControl?.Content = page;
}
else
{
COGWHEEL.LogError($"Page {pageName} does not exist");
}
}
public void ToggleOverlay(bool visible)
{
_overlayContentControl?.IsVisible = visible;
_overlayContentControl?.IsHitTestVisible = visible;
}
public void ToggleConsole(bool visible)
{
ToggleOverlay(visible);
_overlayContentControl?.Content = visible ? AppManager.ConsoleControl : null;
}
private void OnKeyDown(TopLevel topLevel, KeyEventArgs keyEventArgs)
{
if (keyEventArgs.Key == Key.OemTilde)
ToggleConsole(!_overlayContentControl.IsVisible);
}
private void InitControls()
{
_mainContentControl = this.FindControl<ContentControl>("MainContentControl");
_overlayContentControl = this.FindControl<ContentControl>("Overlay");
_homeButton = this.FindControl<Button>("HomeButton");
_sessionsButton = this.FindControl<Button>("SessionsButton");
_libraryButton = this.FindControl<Button>("LibraryButton");
_settingsButton = this.FindControl<Button>("SettingsButton");
SetupButtonEvents();
}
private void InitPages()
{
var homePage = new HomePage();
_pages.Add(homePage.PageName.ToLower(), homePage);
var sessionsPage = new SessionsPage();
_pages.Add(sessionsPage.PageName.ToLower(), sessionsPage);
}
private void SetupButtonEvents()
{
_homeButton?.Click += (_, _) => ChangePage("Home");
_sessionsButton?.Click += (_, _) => ChangePage("Sessions");
_libraryButton?.Click += (_, _) => ChangePage("Library");
_settingsButton?.Click += (_, _) => ChangePage("Settings");
}
}

View File

@@ -0,0 +1,10 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SessionZero.Pages.HomePage">
<StackPanel>
<Label FontSize="20">Home</Label>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,16 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace SessionZero.Pages;
public partial class HomePage : UserControl, IPageBase
{
public string PageName { get; set; } = "Home";
public HomePage()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,6 @@
namespace SessionZero.Pages;
public interface IPageBase
{
public string PageName { get; set; }
}

View File

@@ -0,0 +1,10 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SessionZero.Pages.SessionsPage">
<StackPanel>
<Label FontSize="20">Sessions</Label>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,15 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace SessionZero.Pages;
public partial class SessionsPage : UserControl, IPageBase
{
public string PageName { get; set; } = "Sessions";
public SessionsPage()
{
InitializeComponent();
}
}

View File

@@ -6,11 +6,13 @@
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Folder Include="Assets" />
<AvaloniaResource Include="Assets/**" />
<Folder Include="Controls\" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACOGWHEEL_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fchris_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2ee8efbdf4144b7e9741475fab7c883d5800_003Fa0_003F83e60bea_003FCOGWHEEL_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AICogwheelConsole_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fchris_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2ee8efbdf4144b7e9741475fab7c883d5800_003F77_003Fe0eaad3c_003FICogwheelConsole_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMethodBaseInvoker_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fchris_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fd6b757e154dd7f8c23e0e785431c97a76e4b9c6bdae38b978238421dbab55d_003FMethodBaseInvoker_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>