web UI
This commit is contained in:
18
VisionBuilder.UI.Blazor.Uno/Components/App.razor
Normal file
18
VisionBuilder.UI.Blazor.Uno/Components/App.razor
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="/" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||
<link href="_content/VisionBuilder.UI.Blazor/css/visionbuilder.css" rel="stylesheet" />
|
||||
<link href="css/app.css" rel="stylesheet" />
|
||||
<HeadOutlet @rendermode="InteractiveServer" />
|
||||
</head>
|
||||
<body>
|
||||
<Routes @rendermode="InteractiveServer" />
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
@inherits LayoutComponentBase
|
||||
@using MudBlazor
|
||||
@using VisionBuilder.UI.Common.ViewModel
|
||||
@using VisionBuilder.UI.Common.Services
|
||||
@using VisionBuilder.UI.Common
|
||||
@inject MainWindowVM MainWindowVm
|
||||
@inject IPasswordInputService PasswordInputService
|
||||
@implements IDisposable
|
||||
|
||||
<MudThemeProvider Theme="@_currentTheme" />
|
||||
<MudPopoverProvider />
|
||||
<MudDialogProvider />
|
||||
<MudSnackbarProvider />
|
||||
|
||||
<div class="app-root @(_testMode ? "test-mode" : "")">
|
||||
<div class="app-content">
|
||||
@Body
|
||||
</div>
|
||||
<div class="app-divider"></div>
|
||||
<div class="app-toolbar">
|
||||
<div class="toolbar-buttons">
|
||||
@if (_showTestModeButton)
|
||||
{
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Primary" Class="toolbar-btn" OnClick="ToggleTestMode">Test Mode</MudButton>
|
||||
}
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Primary" Class="toolbar-btn" OnClick="OnSettings">Settings</MudButton>
|
||||
</div>
|
||||
<span class="toolbar-version">@_version</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,103 @@
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
using VisionBuilder.UI.Blazor.Services;
|
||||
using VisionBuilder.UI.Common;
|
||||
using VisionBuilder.UI.Common.Services;
|
||||
using VisionBuilder.UI.Common.ViewModel;
|
||||
using VisionBuilder.UI.Common.ViewModel.Interfaces.UI;
|
||||
using Ninject;
|
||||
|
||||
namespace VisionBuilder.UI.Blazor.Uno.Components.Layout;
|
||||
|
||||
public partial class MainLayout : IDisposable
|
||||
{
|
||||
[Microsoft.AspNetCore.Components.Inject] private IDialogService DialogService { get; set; } = null!;
|
||||
[Microsoft.AspNetCore.Components.Inject] private IKernel Kernel { get; set; } = null!;
|
||||
|
||||
private bool _testMode;
|
||||
private bool _showTestModeButton;
|
||||
private string _version = "";
|
||||
|
||||
private readonly MudTheme _inspectronTheme = new()
|
||||
{
|
||||
PaletteLight = new PaletteLight
|
||||
{
|
||||
Primary = "#d32f2f",
|
||||
AppbarBackground = "#37474f"
|
||||
},
|
||||
LayoutProperties = new LayoutProperties
|
||||
{
|
||||
DefaultBorderRadius = "0px"
|
||||
}
|
||||
};
|
||||
|
||||
private readonly MudTheme _testModeTheme = new()
|
||||
{
|
||||
PaletteLight = new PaletteLight
|
||||
{
|
||||
Primary = "#2e7d32",
|
||||
AppbarBackground = "#2e7d32"
|
||||
},
|
||||
LayoutProperties = new LayoutProperties
|
||||
{
|
||||
DefaultBorderRadius = "0px"
|
||||
}
|
||||
};
|
||||
|
||||
private MudTheme _currentTheme = null!;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_currentTheme = _inspectronTheme;
|
||||
_version = $"v{Assembly.GetEntryAssembly()?.GetName().Version?.ToString(3) ?? "0.0.0"}";
|
||||
|
||||
var uiConfig = Kernel.Get<UIConfiguration>();
|
||||
_showTestModeButton = uiConfig.ShowTestModeButton;
|
||||
|
||||
MainWindowVm.PropertyChanged += OnPropertyChanged;
|
||||
|
||||
// Wire up dialog services
|
||||
if (Kernel.Get<IRecipeSelectionDialogService>() is BlazorRecipeSelectionDialogService recipeService)
|
||||
recipeService.SetDialogService(DialogService);
|
||||
if (Kernel.Get<IImagePreviewService>() is BlazorImagePreviewService imageService)
|
||||
imageService.SetDialogService(DialogService);
|
||||
if (Kernel.Get<IPasswordInputService>() is BlazorPasswordInputService passwordService)
|
||||
passwordService.SetDialogService(DialogService);
|
||||
if (Kernel.Get<ISettingsService>() is BlazorSettingsService settingsService)
|
||||
settingsService.SetDialogService(DialogService);
|
||||
}
|
||||
|
||||
private async void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(MainWindowVM.TestMode))
|
||||
{
|
||||
_testMode = MainWindowVm.TestMode;
|
||||
_currentTheme = _testMode ? _testModeTheme : _inspectronTheme;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleTestMode()
|
||||
{
|
||||
MainWindowVm.ToggleTestModeCommand.Execute(null);
|
||||
}
|
||||
|
||||
private async Task OnSettings()
|
||||
{
|
||||
var uiConfig = Kernel.Get<UIConfiguration>();
|
||||
if (uiConfig.ProtectSettingsWithPassword)
|
||||
{
|
||||
var password = await PasswordInputService.GetPasswordAsync();
|
||||
if (password != uiConfig.AdminPassword)
|
||||
return;
|
||||
}
|
||||
MainWindowVm.SettingsCommand.Execute(null);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
MainWindowVm.PropertyChanged -= OnPropertyChanged;
|
||||
}
|
||||
}
|
||||
7
VisionBuilder.UI.Blazor.Uno/Components/Routes.razor
Normal file
7
VisionBuilder.UI.Blazor.Uno/Components/Routes.razor
Normal file
@@ -0,0 +1,7 @@
|
||||
<Router AppAssembly="typeof(Program).Assembly"
|
||||
AdditionalAssemblies="new[] { typeof(VisionBuilder.UI.Blazor.Components.SingleCameraControl).Assembly }">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
9
VisionBuilder.UI.Blazor.Uno/Pages/Home.razor
Normal file
9
VisionBuilder.UI.Blazor.Uno/Pages/Home.razor
Normal file
@@ -0,0 +1,9 @@
|
||||
@page "/"
|
||||
@using VisionBuilder.UI.Blazor.Components
|
||||
@using VisionBuilder.UI.Common
|
||||
@using VisionBuilder.UI.Common.ViewModel
|
||||
@inject MainWindowVM MainWindowVm
|
||||
|
||||
<PageTitle>VisionBuilder</PageTitle>
|
||||
|
||||
<SingleCameraControl ViewModel="@MainWindowVm.SingleCameraVms[0]" />
|
||||
104
VisionBuilder.UI.Blazor.Uno/Program.cs
Normal file
104
VisionBuilder.UI.Blazor.Uno/Program.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using Inspectron.Settings;
|
||||
using Lindt.Colorballs.Duo.Utils;
|
||||
using MudBlazor.Services;
|
||||
using Ninject;
|
||||
using Ninject.Extensions.ChildKernel;
|
||||
using VisionBuilder.UI.Blazor;
|
||||
using VisionBuilder.UI.Common;
|
||||
using VisionBuilder.UI.Common.Plugins;
|
||||
using VisionBuilder.UI.Common.Processing;
|
||||
using VisionBuilder.UI.Common.ViewModel;
|
||||
using VisionBuilder.UI.Console;
|
||||
using VisionBuilder.UI.IOCommander;
|
||||
using VisionBuilder.UI.Recipes.HawkeyeRecipe;
|
||||
using VisionBuilder.UI.Ringbuffer;
|
||||
using VisionBuilder.UI.Statistics;
|
||||
|
||||
const string CAMERA1 = "Camera 1";
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
builder.Services.AddMudServices();
|
||||
|
||||
// Parse command line args
|
||||
CommandLineParser commandLineParser = new CommandLineParser(args);
|
||||
|
||||
// Setup settings
|
||||
InspectronSettings settings = new InspectronSettings("..\\Data\\Config");
|
||||
|
||||
var mainKernel = VisionBuilder.UI.Common.VisionBuilder.CreateMainKernel(settings);
|
||||
|
||||
var profile = commandLineParser.GetStringArgument("profile", 'p');
|
||||
mainKernel.UsePlugins(profile);
|
||||
|
||||
mainKernel
|
||||
.UseConsole()
|
||||
.UseIOCommander([CAMERA1])
|
||||
.UseBlazorServices()
|
||||
.RegisterGlobalPlugins();
|
||||
|
||||
mainKernel.Get<ILoadingService>().StartLoading("Camera initialization");
|
||||
|
||||
// CAMERA 1 //
|
||||
ChildKernel kernelCamera1 = new ChildKernel(mainKernel);
|
||||
|
||||
kernelCamera1
|
||||
.RegisterCamera(CAMERA1)
|
||||
.UseStatistics(CAMERA1)
|
||||
.UseRingbuffer(CAMERA1)
|
||||
.UseHawkeyeRecipes(CAMERA1)
|
||||
.UseCameraIOCommander(CAMERA1)
|
||||
.RegisterCameraPlugins(CAMERA1);
|
||||
|
||||
// LOAD SETTINGS //
|
||||
mainKernel.RegisterSettings();
|
||||
kernelCamera1.RegisterSettings();
|
||||
settings.LoadSettings();
|
||||
|
||||
// Create camera and bind it (must be after settings are loaded)
|
||||
kernelCamera1.UseCamera();
|
||||
|
||||
// Initialize modules
|
||||
mainKernel.InitializeModules();
|
||||
kernelCamera1.InitializeModules();
|
||||
|
||||
mainKernel.Get<ILoadingService>().StopLoading("Camera initialization");
|
||||
|
||||
var mainWindowVm = mainKernel.Get<MainWindowVM>();
|
||||
mainWindowVm.SingleCameraVms =
|
||||
[
|
||||
kernelCamera1.Get<SingleCameraVM>()
|
||||
];
|
||||
|
||||
settings.LoadSettings();
|
||||
|
||||
// Bridge Ninject → ASP.NET Core DI
|
||||
builder.Services.AddSingleton(mainKernel);
|
||||
builder.Services.AddSingleton(mainWindowVm);
|
||||
builder.Services.AddSingleton(kernelCamera1.Get<SingleCameraVM>());
|
||||
builder.Services.AddSingleton(mainKernel.Get<VisionBuilder.UI.Common.Services.IPasswordInputService>());
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
}
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapRazorComponents<VisionBuilder.UI.Blazor.Uno.Components.App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(VisionBuilder.UI.Blazor.Components.SingleCameraControl).Assembly);
|
||||
|
||||
mainWindowVm.OnProgramStarted();
|
||||
|
||||
app.Lifetime.ApplicationStopping.Register(() =>
|
||||
{
|
||||
mainWindowVm.OnProgramClosed();
|
||||
});
|
||||
|
||||
app.Run();
|
||||
12
VisionBuilder.UI.Blazor.Uno/Properties/launchSettings.json
Normal file
12
VisionBuilder.UI.Blazor.Uno/Properties/launchSettings.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"profiles": {
|
||||
"VisionBuilder.UI.Blazor.Uno": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Data\**" />
|
||||
<Content Remove="Data\**" />
|
||||
<EmbeddedResource Remove="Data\**" />
|
||||
<None Remove="Data\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MudBlazor" Version="8.0.0" />
|
||||
<PackageReference Include="Ninject.Extensions.ChildKernel" Version="3.3.0" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.6.0.20220608" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\framework\Inspectron.Settings\Inspectron.Settings.csproj" />
|
||||
<ProjectReference Include="..\Hawkeye.VisionBuilder.UI.Sources.Emulation\Hawkeye.VisionBuilder.UI.Sources.Emulation.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Camera\VisionBuilder.UI.Camera.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Common\VisionBuilder.UI.Common.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Console\VisionBuilder.UI.Console.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.IOCommander\VisionBuilder.UI.IOCommander.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Recipes.HawkeyeRecipe\VisionBuilder.UI.Recipes.HawkeyeRecipe.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Ringbuffer\VisionBuilder.UI.Ringbuffer.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Statistics\VisionBuilder.UI.Statistics.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Blazor\VisionBuilder.UI.Blazor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
10
VisionBuilder.UI.Blazor.Uno/_Imports.razor
Normal file
10
VisionBuilder.UI.Blazor.Uno/_Imports.razor
Normal file
@@ -0,0 +1,10 @@
|
||||
@using System.Net.Http
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using MudBlazor
|
||||
@using VisionBuilder.UI.Blazor.Uno
|
||||
@using VisionBuilder.UI.Blazor.Uno.Components
|
||||
8
VisionBuilder.UI.Blazor.Uno/appsettings.Development.json
Normal file
8
VisionBuilder.UI.Blazor.Uno/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
VisionBuilder.UI.Blazor.Uno/appsettings.json
Normal file
9
VisionBuilder.UI.Blazor.Uno/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
65
VisionBuilder.UI.Blazor.Uno/wwwroot/css/app.css
Normal file
65
VisionBuilder.UI.Blazor.Uno/wwwroot/css/app.css
Normal file
@@ -0,0 +1,65 @@
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Main app layout */
|
||||
.app-root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.app-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.app-divider {
|
||||
height: 1px;
|
||||
background-color: #37474f;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.app-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 16px;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
min-height: 56px;
|
||||
}
|
||||
|
||||
.toolbar-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.toolbar-btn {
|
||||
min-width: 140px !important;
|
||||
height: 48px !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 0.85rem !important;
|
||||
}
|
||||
|
||||
.toolbar-version {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
font-size: 0.75rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Test mode: green toolbar tint */
|
||||
.app-root.test-mode .app-toolbar {
|
||||
background-color: #e8f5e9;
|
||||
}
|
||||
|
||||
.app-root.test-mode .app-divider {
|
||||
background-color: #2e7d32;
|
||||
}
|
||||
Reference in New Issue
Block a user