Draft: Resolve "Migrate app to use Godot for the UI" #93

Open
thorsten wants to merge 34 commits from 58-migrate-app-to-use-godot-for-the-ui into main
137 changed files with 7 additions and 11048 deletions
Showing only changes of commit 58b7c37295 - Show all commits

View File

@ -7,7 +7,4 @@
<inspection_tool class="SubjectLimit" enabled="true" level="ERROR" enabled_by_default="true" /> <inspection_tool class="SubjectLimit" enabled="true" level="ERROR" enabled_by_default="true" />
</profile> </profile>
</component> </component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project> </project>

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>

View File

@ -5,11 +5,9 @@ VisualStudioVersion = 17.3.32519.111
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Processor", "Processor\Processor.csproj", "{E24B7026-05BE-434D-9481-7CA5785BC7A8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Processor", "Processor\Processor.csproj", "{E24B7026-05BE-434D-9481-7CA5785BC7A8}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UI WinForms", "UI WinForms\UI WinForms.csproj", "{5AE84E7C-3141-46CA-B390-4E42878B6195}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataModel", "DataModel\DataModel.csproj", "{D18DD193-3F93-4D21-92DC-BA0E26B0342A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataModel", "DataModel\DataModel.csproj", "{D18DD193-3F93-4D21-92DC-BA0E26B0342A}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UI MAUI", "UI MAUI\UI MAUI.csproj", "{BA8BE958-0DCC-4054-B731-DF911AECC429}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "App\App.csproj", "{CA2AB6BD-472A-4906-BF5A-84263EF345B6}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -21,20 +19,14 @@ Global
{E24B7026-05BE-434D-9481-7CA5785BC7A8}.Debug|Any CPU.Build.0 = Debug|Any CPU {E24B7026-05BE-434D-9481-7CA5785BC7A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E24B7026-05BE-434D-9481-7CA5785BC7A8}.Release|Any CPU.ActiveCfg = Release|Any CPU {E24B7026-05BE-434D-9481-7CA5785BC7A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E24B7026-05BE-434D-9481-7CA5785BC7A8}.Release|Any CPU.Build.0 = Release|Any CPU {E24B7026-05BE-434D-9481-7CA5785BC7A8}.Release|Any CPU.Build.0 = Release|Any CPU
{5AE84E7C-3141-46CA-B390-4E42878B6195}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5AE84E7C-3141-46CA-B390-4E42878B6195}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5AE84E7C-3141-46CA-B390-4E42878B6195}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5AE84E7C-3141-46CA-B390-4E42878B6195}.Release|Any CPU.Build.0 = Release|Any CPU
{D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Debug|Any CPU.Build.0 = Debug|Any CPU {D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Release|Any CPU.ActiveCfg = Release|Any CPU {D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Release|Any CPU.Build.0 = Release|Any CPU {D18DD193-3F93-4D21-92DC-BA0E26B0342A}.Release|Any CPU.Build.0 = Release|Any CPU
{BA8BE958-0DCC-4054-B731-DF911AECC429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA2AB6BD-472A-4906-BF5A-84263EF345B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA8BE958-0DCC-4054-B731-DF911AECC429}.Debug|Any CPU.Build.0 = Debug|Any CPU {CA2AB6BD-472A-4906-BF5A-84263EF345B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA8BE958-0DCC-4054-B731-DF911AECC429}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {CA2AB6BD-472A-4906-BF5A-84263EF345B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA8BE958-0DCC-4054-B731-DF911AECC429}.Release|Any CPU.ActiveCfg = Release|Any CPU {CA2AB6BD-472A-4906-BF5A-84263EF345B6}.Release|Any CPU.Build.0 = Release|Any CPU
{BA8BE958-0DCC-4054-B731-DF911AECC429}.Release|Any CPU.Build.0 = Release|Any CPU
{BA8BE958-0DCC-4054-B731-DF911AECC429}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UI_MAUI"
x:Class="UI_MAUI.App">
<Application.Resources>
<ResourceDictionary>
<Color x:Key="PageBackgroundColor">#512bdf</Color>
<Color x:Key="PrimaryTextColor">White</Color>
<Style TargetType="Label">
<Setter Property="TextColor" Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="BackgroundColor" Value="#2b0b98" />
<Setter Property="Padding" Value="14,10" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -1,10 +0,0 @@
namespace UI_MAUI;
public partial class App : Application
{
public App()
{
this.InitializeComponent();
this.MainPage = new MainPage();
}
}

View File

@ -1,17 +0,0 @@
<div class="offcanvas offcanvas-bottom" tabindex="-1" id="@this.Name" aria-labelledby="@this.Name-Header" style="@this.AssistantHeight">
<div class="offcanvas-header">
<h4 class="offcanvas-title d-flex align-items-center" id="@this.Name-Header">
@if (this.IsIconAvailable)
{
<Icon Filename="@this.IconName" Size="35" Classes="me-2" AltText="@this.HeaderIconAltText"/>
}
@this.HeaderText
</h4>
<button class="btn btn-secondary" type="button" data-bs-toggle="offcanvas" data-bs-target="#@this.Name">
Cancel
</button>
</div>
<div class="offcanvas-body">
@this.ChildContent
</div>
</div>

View File

@ -1,32 +0,0 @@
using Microsoft.AspNetCore.Components;
namespace UI_MAUI.Components;
public partial class Assistant : ComponentBase
{
[Parameter]
public string HeaderText { get; set; } = string.Empty;
[Parameter]
public string Name { get; set; } = "Assistant";
[Parameter]
public string IconName { get; set; } = string.Empty;
[Parameter]
public Height BaseHeight { get; set; } = new(60, 40, 50);
public readonly record struct Height(int Phone, int Desktop, int Tablet);
[Parameter]
public RenderFragment ChildContent { get; set; }
private string AssistantHeight =>
DeviceInfo.Idiom == DeviceIdiom.Phone ? $"--bs-offcanvas-height: {this.BaseHeight.Phone}vh;" :
DeviceInfo.Idiom == DeviceIdiom.Tablet ? $"--bs-offcanvas-height: {this.BaseHeight.Tablet}vh;" :
$"--bs-offcanvas-height: {this.BaseHeight.Desktop}vh;";
private string HeaderIconAltText => $"Icon: {this.HeaderText}";
private bool IsIconAvailable => !string.IsNullOrWhiteSpace(this.IconName);
}

View File

@ -1 +0,0 @@
<img src="icons/@this.Filename" class="d-inline-block @this.Classes" width="@this.Size" height="@this.Size" alt="@this.AltText" />

View File

@ -1,18 +0,0 @@
using Microsoft.AspNetCore.Components;
namespace UI_MAUI.Components;
public partial class Icon : ComponentBase
{
[Parameter]
public string Filename { get; set; } = string.Empty;
[Parameter]
public string AltText { get; set; } = string.Empty;
[Parameter]
public ushort Size { get; set; } = 35;
[Parameter]
public string Classes { get; set; } = string.Empty;
}

View File

@ -1,22 +0,0 @@
<li class="nav-item">
@if (DeviceInfo.Idiom == DeviceIdiom.Desktop || DeviceInfo.Idiom == DeviceIdiom.Tablet)
{
<a class="nav-link active" aria-current="page" href="@this.Route">
@if (this.ShowIcon)
{
<Icon Filename="@this.IconFilename" Size="25" AltText="@this.AltText" />
}
<span class="ms-1 align-middle">@this.Text</span>
</a>
}
else
{
<a class="nav-link active" aria-current="page" href="@this.Route" @onclick="@this.Navigate" data-bs-toggle="collapse" data-bs-target="#navbarContent">
@if (this.ShowIcon)
{
<Icon Filename="@this.IconFilename" Size="25" AltText="@this.AltText" />
}
<span class="ms-1 align-middle">@this.Text</span>
</a>
}
</li>

View File

@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Components;
namespace UI_MAUI.Components;
public partial class NavItem : ComponentBase
{
[Parameter]
public string Route { get; set; }
[Parameter]
public string Text { get; set; }
[Parameter]
public bool ShowIcon { get; set; } = false;
[Parameter]
public string IconFilename { get; set; } = string.Empty;
[Inject]
public NavigationManager NavigationManager { get; set; }
private string AltText => $"Navigation: {this.Text}";
private void Navigate() => this.NavigationManager.NavigateTo(this.Route);
}

View File

@ -1,11 +0,0 @@
<Router AppAssembly="@typeof(Main).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UI_MAUI"
x:Class="UI_MAUI.MainPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>

View File

@ -1,9 +0,0 @@
namespace UI_MAUI;
public partial class MainPage : ContentPage
{
public MainPage()
{
this.InitializeComponent();
}
}

View File

@ -1,51 +0,0 @@
using DataModel.Database.Common;
using Microsoft.Maui.LifecycleEvents;
#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
#endif
namespace UI_MAUI;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>();
builder.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
#if WINDOWS
builder.ConfigureLifecycleEvents(events =>
{
events.AddWindows(wndLifeCycleBuilder =>
{
wndLifeCycleBuilder.OnWindowCreated(window =>
{
var nativeWindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(window);
var win32WindowsId = Win32Interop.GetWindowIdFromWindow(nativeWindowHandle);
var appWindow = AppWindow.GetFromWindowId(win32WindowsId);
const int width = 1366;
const int height = 768;
appWindow.ResizeClient(new SizeInt32(width, height));
});
});
});
#endif
builder.Services.AddMauiBlazorWebView();
builder.Services.AddSingleton<DataContextFactory>();
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
#endif
return builder.Build();
}
}

View File

@ -1,15 +0,0 @@
namespace UI_MAUI;
public readonly record struct NavigationTarget(string Text, string Route, string IconFilename)
{
private static readonly NavigationTarget SETTINGS = new("Project settings", "settings", "settings.svg");
private static readonly NavigationTarget TRANSLATION = new("Translation", "translation", "translation.svg");
private static readonly NavigationTarget LOAD_PROJECT = new("Load Project", "load", "load.svg");
public static IEnumerable<NavigationTarget> GetAll()
{
yield return LOAD_PROJECT;
yield return SETTINGS;
yield return TRANSLATION;
}
};

View File

@ -1,42 +0,0 @@
@page "/"
@page "/load"
<h1>Load a Project</h1>
<ul>
@foreach (var recentProject in this.recentProjects)
{
<li>@recentProject.Path</li>
}
</ul>
<div>
<button class="btn btn-secondary me-2 mb-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#Assistant">
<Icon Filename="add-project.svg" Size="25" AltText="Icon: Create new project"/>
Create new project
</button>
<button class="btn btn-secondary me-2 mb-2" type="button">
<Icon Filename="load.svg" Size="25" AltText="Icon: Open project"/>
Open project
</button>
</div>
<Assistant HeaderText="Create new project" IconName="add-project.svg" BaseHeight="new Assistant.Height(40, 55, 40)">
<div class="mb-3">
<label for="projectName" class="form-label fw-bold">Project Name:</label>
<input type="text" class="form-control" id="projectName" placeholder="Type a project name" @bind="this.newProjectName" @bind:event="oninput" @onkeydown="this.ReevaluateState">
</div>
@if (DeviceInfo.Idiom == DeviceIdiom.Desktop)
{
<div class="mb-3">
<label for="projectPath" class="form-label fw-bold">Project destination:</label>
<div class="input-group" id="projectPath">
<button class="btn btn-primary" type="button" @onclick="@this.ChooseProjectDestination">Choose destination</button>
<input type="text" class="form-control" value="@this.newProjectDestination" aria-label="The chosen project path" disabled readonly>
</div>
</div>
}
<button class="btn btn-secondary" type="button" @onclick="this.CreateProject" disabled="@this.CannotCreateProject()">Create project</button>
</Assistant>

View File

@ -1,88 +0,0 @@
using System.Text;
using System.Text.Json.Serialization;
using DataModel.Database.Common;
using Microsoft.AspNetCore.Components;
namespace UI_MAUI.Pages;
public partial class LoadProject
{
private readonly List<RecentProject> recentProjects = new();
[Inject]
public DataContextFactory DataContextFactory { get; set; }
private string newProjectName = string.Empty;
private string newProjectDestination = string.Empty;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await this.LoadRecentProjects();
}
#endregion
private readonly record struct RecentProject(string Path, string Name, bool Available);
private async Task LoadRecentProjects()
{
var appDataDirectory = FileSystem.Current.AppDataDirectory;
var recentProjectsFile = Path.Join(appDataDirectory, "recentProjects.json");
if (!File.Exists(recentProjectsFile))
await File.WriteAllTextAsync(recentProjectsFile, string.Empty, Encoding.UTF8);
// Read the JSON data from that file & decode it to an array of recent projects:
}
private async Task WriteRecentProjects()
{
}
private Task ChooseProjectDestination()
{
try
{
#if WINDOWS
return this.ChooseProjectDestinationWindows();
#elif MACCATALYST
return this.ChooseProjectDestinationMacOS();
#else
return Task.CompletedTask;
#endif
}
finally
{
this.StateHasChanged();
}
}
private Task CreateProject()
{
// TODO: Need to wait for the project to be created. Afterwards, we need to close the dialog. Meanwhile, we need to show a loading indicator.
#warning TODO: Create project
#if WINDOWS
return this.CreateProjectWindows();
#elif MACCATALYST
return Task.CompletedTask;
#else
return Task.CompletedTask;
#endif
}
private bool CannotCreateProject()
{
if (DeviceInfo.Idiom == DeviceIdiom.Desktop)
return string.IsNullOrWhiteSpace(this.newProjectName) || string.IsNullOrWhiteSpace(this.newProjectDestination);
else if (DeviceInfo.Idiom == DeviceIdiom.Phone || DeviceInfo.Idiom == DeviceIdiom.Tablet)
return string.IsNullOrWhiteSpace(this.newProjectName);
else
return true;
}
private void ReevaluateState() => this.StateHasChanged();
}

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/app" android:roundIcon="@mipmap/app_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -1,10 +0,0 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
namespace UI_MAUI;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
}

View File

@ -1,14 +0,0 @@
using Android.App;
using Android.Runtime;
namespace UI_MAUI;
[Application]
public class MainApplication : MauiApplication
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership)
{
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

View File

@ -1,9 +0,0 @@
#if ANDROID
namespace UI_MAUI.Pages;
public partial class LoadProject
{
}
#endif

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#512BD4</color>
<color name="colorPrimaryDark">#2B0B98</color>
<color name="colorAccent">#2B0B98</color>
</resources>

View File

@ -1,9 +0,0 @@
using Foundation;
namespace UI_MAUI;
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
</dict>
</plist>

View File

@ -1,13 +0,0 @@
#if MACCATALYST
namespace UI_MAUI.Pages;
public partial class LoadProject
{
private Task ChooseProjectDestinationMacOS()
{
return Task.CompletedTask;
}
}
#endif

View File

@ -1,15 +0,0 @@
using ObjCRuntime;
using UIKit;
namespace UI_MAUI;
public class Program
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));
}
}

View File

@ -1,8 +0,0 @@
<maui:MauiWinUIApplication
x:Class="UI_MAUI.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maui="using:Microsoft.Maui"
xmlns:local="using:UI_MAUI.WinUI">
</maui:MauiWinUIApplication>

View File

@ -1,18 +0,0 @@
namespace UI_MAUI.WinUI;
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : MauiWinUIApplication
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
<Properties>
<DisplayName>$placeholder$</DisplayName>
<PublisherDisplayName>User Name</PublisherDisplayName>
<Logo>$placeholder$.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="$placeholder$"
Description="$placeholder$"
Square150x150Logo="$placeholder$.png"
Square44x44Logo="$placeholder$.png"
BackgroundColor="transparent">
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
<uap:SplashScreen Image="$placeholder$.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View File

@ -1,38 +0,0 @@
#if WINDOWS
namespace UI_MAUI.Pages;
using Windows.Storage.Pickers;
using WindowsSavePicker = Windows.Storage.Pickers.FileSavePicker;
public partial class LoadProject
{
private async Task ChooseProjectDestinationWindows()
{
var saveDialog = new WindowsSavePicker
{
CommitButtonText = "Create the project here",
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
FileTypeChoices =
{
new KeyValuePair<string, IList<string>>("I18N Commander Projects", new List<string> { ".i18nc" }),
}
};
var hwnd = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;
WinRT.Interop.InitializeWithWindow.Initialize(saveDialog, hwnd);
var result = await saveDialog.PickSaveFileAsync();
if(result is null)
return;
this.newProjectDestination = result.Path;
}
private async Task CreateProjectWindows() => await Task.Run(() =>
{
this.DataContextFactory.CreateDataContext(this.newProjectDestination);
});
}
#endif

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="UI MAUI.WinUI.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- The combination of below two tags have the following effect:
1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update
-->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>

View File

@ -1,9 +0,0 @@
using Foundation;
namespace UI_MAUI;
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
</dict>
</plist>

View File

@ -1,9 +0,0 @@
#if IOS
namespace UI_MAUI.Pages;
public partial class LoadProject
{
}
#endif

View File

@ -1,15 +0,0 @@
using ObjCRuntime;
using UIKit;
namespace UI_MAUI;
public class Program
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));
}
}

View File

@ -1,8 +0,0 @@
{
"profiles": {
"Windows Machine": {
"commandName": "MsixPackage",
"nativeDebugging": false
}
}
}

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 12 48 30" width="512px" height="512px"><linearGradient id="gCW9sGJUkBnBLRc40wQXGa" x1="25.447" x2="44.728" y1="4.921" y2="36.29" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#42a3f2"/><stop offset="1" stop-color="#42a4eb"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGa)" d="M42,8H19l11,30h12c1.105,0,2-0.895,2-2V10C44,8.895,43.105,8,42,8z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGb" x1="3.865" x2="23.412" y1="9.86" y2="41.663" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1d59b3"/><stop offset="1" stop-color="#195bbc"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGb)" d="M19,8H6c-1.105,0-2,0.895-2,2v26c0,1.105,0.895,2,2,2h8v7.998 c0,0.891,1.077,1.337,1.707,0.707L24.412,38H30L19,8z"/><path fill="#fff" d="M12,25h6v2h-6V25z"/><path fill="#fff" d="M12.109,29L15,20l2.906,9h2.11L16,17h-2l-4,12H12.109z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGc" x1="29.064" x2="38.79" y1="23.554" y2="23.554" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGc)" d="M29.064,27.223c0.061-0.031,4.994-3.219,7.936-9.115L38.79,19 c-3.082,6.25-7.457,9.292-8.509,10L29.064,27.223z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGd" x1="28" x2="40" y1="23.5" y2="23.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGd)" d="M38,29c0,0-5-2.583-7.769-6.998L32,21c2.333,3.833,6.981,6.26,6.981,6.26L38,29z M28,18h12v2 H28V18z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGe" x1="33" x2="35" y1="18" y2="18" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGe)" d="M33,16h2v4h-2V16z"/></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,15 +0,0 @@
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories). Deployment of the asset to your application
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
These files will be deployed with you package and will be accessible using Essentials:
async Task LoadMauiAsset()
{
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
}

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="512px" height="512px"><linearGradient id="gCW9sGJUkBnBLRc40wQXGa" x1="25.447" x2="44.728" y1="4.921" y2="36.29" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#42a3f2"/><stop offset="1" stop-color="#42a4eb"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGa)" d="M42,8H19l11,30h12c1.105,0,2-0.895,2-2V10C44,8.895,43.105,8,42,8z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGb" x1="3.865" x2="23.412" y1="9.86" y2="41.663" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1d59b3"/><stop offset="1" stop-color="#195bbc"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGb)" d="M19,8H6c-1.105,0-2,0.895-2,2v26c0,1.105,0.895,2,2,2h8v7.998 c0,0.891,1.077,1.337,1.707,0.707L24.412,38H30L19,8z"/><path fill="#fff" d="M12,25h6v2h-6V25z"/><path fill="#fff" d="M12.109,29L15,20l2.906,9h2.11L16,17h-2l-4,12H12.109z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGc" x1="29.064" x2="38.79" y1="23.554" y2="23.554" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGc)" d="M29.064,27.223c0.061-0.031,4.994-3.219,7.936-9.115L38.79,19 c-3.082,6.25-7.457,9.292-8.509,10L29.064,27.223z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGd" x1="28" x2="40" y1="23.5" y2="23.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGd)" d="M38,29c0,0-5-2.583-7.769-6.998L32,21c2.333,3.833,6.981,6.26,6.981,6.26L38,29z M28,18h12v2 H28V18z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGe" x1="33" x2="35" y1="18" y2="18" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGe)" d="M33,16h2v4h-2V16z"/></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Color x:Key="Primary">#512BD4</Color>
<Color x:Key="Secondary">#DFD8F7</Color>
<Color x:Key="Tertiary">#2B0B98</Color>
<Color x:Key="White">White</Color>
<Color x:Key="Black">Black</Color>
<Color x:Key="Gray100">#E1E1E1</Color>
<Color x:Key="Gray200">#C8C8C8</Color>
<Color x:Key="Gray300">#ACACAC</Color>
<Color x:Key="Gray400">#919191</Color>
<Color x:Key="Gray500">#6E6E6E</Color>
<Color x:Key="Gray600">#404040</Color>
<Color x:Key="Gray900">#212121</Color>
<Color x:Key="Gray950">#141414</Color>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
<Color x:Key="Yellow100Accent">#F7B548</Color>
<Color x:Key="Yellow200Accent">#FFD590</Color>
<Color x:Key="Yellow300Accent">#FFE5B9</Color>
<Color x:Key="Cyan100Accent">#28C2D1</Color>
<Color x:Key="Cyan200Accent">#7BDDEF</Color>
<Color x:Key="Cyan300Accent">#C3F2F4</Color>
<Color x:Key="Blue100Accent">#3E8EED</Color>
<Color x:Key="Blue200Accent">#72ACF1</Color>
<Color x:Key="Blue300Accent">#A7CBF6</Color>
</ResourceDictionary>

View File

@ -1,384 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Style TargetType="ActivityIndicator">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="IndicatorView">
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
</Style>
<Style TargetType="Border">
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="StrokeShape" Value="Rectangle"/>
<Setter Property="StrokeThickness" Value="1"/>
</Style>
<Style TargetType="BoxView">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="14,10"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="DatePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Editor">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Frame">
<Setter Property="HasShadow" Value="False" />
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="CornerRadius" Value="8" />
</Style>
<Style TargetType="ImageButton">
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderColor" Value="Transparent"/>
<Setter Property="BorderWidth" Value="0"/>
<Setter Property="CornerRadius" Value="0"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Opacity" Value="0.5" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ListView">
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="Picker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ProgressBar">
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RefreshView">
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="SearchBar">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SearchHandler">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Shadow">
<Setter Property="Radius" Value="15" />
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Offset" Value="10,10" />
</Style>
<Style TargetType="Slider">
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SwipeItem">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style TargetType="Switch">
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="ThumbColor" Value="{StaticResource White}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Off">
<VisualState.Setters>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="TimePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Page" ApplyToDerivedTypes="True">
<Setter Property="Padding" Value="0"/>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style TargetType="Shell" ApplyToDerivedTypes="True">
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}" />
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
<Setter Property="Shell.NavBarHasShadow" Value="False" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="TabbedPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style>
</ResourceDictionary>

View File

@ -1,25 +0,0 @@
@inherits LayoutComponentBase
<nav class="navbar navbar-dark bg-dark navbar-expand-sm p-0">
<div class="container-fluid ps-1">
<div class="navbar-brand p-0">
<Icon Filename="translation.svg" Size="35" AltText="App Icon" />
<span class="fw-bold">I18N</span> <span class="fs-6">Commander</span>
</div>
<button class="navbar-toggler p-0 my-1" type="button" data-bs-toggle="collapse" data-bs-target="#navbarContent" aria-controls="navbarContent" aria-expanded="false" aria-label="Toggle navigation">
<Icon Filename="nav-toggle.svg" AltText="Toggles menu" Size="35" />
</button>
<div class="collapse navbar-collapse" id="navbarContent">
<ul class="navbar-nav me-auto">
@foreach (var (text, route, iconFilename) in NavigationTarget.GetAll())
{
<NavItem Text="@text" Route="@route" ShowIcon="@(!string.IsNullOrWhiteSpace(iconFilename))" IconFilename="@iconFilename" />
}
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
@Body
</div>

View File

@ -1,52 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks>
<OutputType>Exe</OutputType>
<AssemblyName>I18N Commander</AssemblyName>
<RootNamespace>UI_MAUI</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<EnableDefaultCssItems>false</EnableDefaultCssItems>
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
<!-- Display name -->
<ApplicationTitle>I18N Commander</ApplicationTitle>
<!-- App Identifier -->
<ApplicationId>org.tsommer.i18n-commander</ApplicationId>
<ApplicationIdGuid>6D8A5F75-4C32-4807-AC75-CD934671D139</ApplicationIdGuid>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">23.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\app.svg" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" BaseSize="128,128" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DataModel\DataModel.csproj" />
<ProjectReference Include="..\Processor\Processor.csproj" />
</ItemGroup>
</Project>

View File

@ -1,9 +0,0 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using UI_MAUI
@using UI_MAUI.Shared
@using UI_MAUI.Components;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="512px" height="512px"><linearGradient id="PJGLEK~gN3IlHg2NgKbnSa" x1="24" x2="24" y1="654.016" y2="645.747" gradientTransform="matrix(1 0 0 -1 0 660.724)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#eba600"/><stop offset="1" stop-color="#c28200"/></linearGradient><path fill="url(#PJGLEK~gN3IlHg2NgKbnSa)" d="M24.414,10.414l-2.536-2.536C21.316,7.316,20.553,7,19.757,7H5C3.895,7,3,7.895,3,9v30 c0,1.105,0.895,2,2,2h38c1.105,0,2-0.895,2-2V13c0-1.105-0.895-2-2-2H25.828C25.298,11,24.789,10.789,24.414,10.414z"/><linearGradient id="PJGLEK~gN3IlHg2NgKbnSb" x1="24" x2="24" y1="649.87" y2="619.741" gradientTransform="matrix(1 0 0 -1 0 660.724)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffd869"/><stop offset="1" stop-color="#fec52b"/></linearGradient><path fill="url(#PJGLEK~gN3IlHg2NgKbnSb)" d="M21.586,14.414l3.268-3.268C24.947,11.053,25.074,11,25.207,11H43c1.105,0,2,0.895,2,2v26 c0,1.105-0.895,2-2,2H5c-1.105,0-2-0.895-2-2V15.5C3,15.224,3.224,15,3.5,15h16.672C20.702,15,21.211,14.789,21.586,14.414z"/><linearGradient id="PJGLEK~gN3IlHg2NgKbnSc" x1="28" x2="48" y1="409.276" y2="409.276" gradientTransform="translate(0 -371.276)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#21ad64"/><stop offset="1" stop-color="#088242"/></linearGradient><circle cx="38" cy="38" r="10" fill="url(#PJGLEK~gN3IlHg2NgKbnSc)"/><path fill="#fff" d="M38.5,43h-1c-0.276,0-0.5-0.224-0.5-0.5v-9c0-0.276,0.224-0.5,0.5-0.5h1c0.276,0,0.5,0.224,0.5,0.5 v9C39,42.776,38.776,43,38.5,43z"/><path fill="#fff" d="M33,38.5v-1c0-0.276,0.224-0.5,0.5-0.5h9c0.276,0,0.5,0.224,0.5,0.5v1c0,0.276-0.224,0.5-0.5,0.5h-9 C33.224,39,33,38.776,33,38.5z"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="512px" height="512px"><path fill="#ffa000" d="M40,12H22l-4-4H8c-2.199,0-4,1.801-4,4v8h40v-4C44,13.801,42.199,12,40,12z"/><path fill="#ffca28" d="M40,12H8c-2.199,0-4,1.801-4,4v20c0,2.199,1.801,4,4,4h32c2.199,0,4-1.801,4-4V16 C44,13.801,42.199,12,40,12z"/><rect width="2" height="14.142" x="28" y="22.929" fill="#616161" transform="rotate(-45.001 29 30)"/><rect width="2" height="4.243" x="31.5" y="31.379" fill="#37474f" transform="rotate(-45.001 32.5 33.5)"/><path fill="#616161" d="M31,25c0,3.866-3.134,7-7,7s-7-3.134-7-7s3.134-7,7-7S31,21.134,31,25z"/><path fill="#64b5f6" d="M29,25c0,2.761-2.239,5-5,5s-5-2.239-5-5s2.239-5,5-5S29,22.239,29,25z"/></svg>

Before

Width:  |  Height:  |  Size: 723 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="512px" height="512px"><path fill="#546E7A" d="M6 14H42V18H6zM6 22H42V26H6zM6 30H42V34H6z"/><path fill="#2196F3" d="M24,45l-7-6.976h14L24,45z"/></svg>

Before

Width:  |  Height:  |  Size: 217 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="480px" height="480px"><path fill="#607D8B" d="M39.6,27.2c0.1-0.7,0.2-1.4,0.2-2.2s-0.1-1.5-0.2-2.2l4.5-3.2c0.4-0.3,0.6-0.9,0.3-1.4L40,10.8c-0.3-0.5-0.8-0.7-1.3-0.4l-5,2.3c-1.2-0.9-2.4-1.6-3.8-2.2l-0.5-5.5c-0.1-0.5-0.5-0.9-1-0.9h-8.6c-0.5,0-1,0.4-1,0.9l-0.5,5.5c-1.4,0.6-2.7,1.3-3.8,2.2l-5-2.3c-0.5-0.2-1.1,0-1.3,0.4l-4.3,7.4c-0.3,0.5-0.1,1.1,0.3,1.4l4.5,3.2c-0.1,0.7-0.2,1.4-0.2,2.2s0.1,1.5,0.2,2.2L4,30.4c-0.4,0.3-0.6,0.9-0.3,1.4L8,39.2c0.3,0.5,0.8,0.7,1.3,0.4l5-2.3c1.2,0.9,2.4,1.6,3.8,2.2l0.5,5.5c0.1,0.5,0.5,0.9,1,0.9h8.6c0.5,0,1-0.4,1-0.9l0.5-5.5c1.4-0.6,2.7-1.3,3.8-2.2l5,2.3c0.5,0.2,1.1,0,1.3-0.4l4.3-7.4c0.3-0.5,0.1-1.1-0.3-1.4L39.6,27.2z M24,35c-5.5,0-10-4.5-10-10c0-5.5,4.5-10,10-10c5.5,0,10,4.5,10,10C34,30.5,29.5,35,24,35z"/><path fill="#455A64" d="M24,13c-6.6,0-12,5.4-12,12c0,6.6,5.4,12,12,12s12-5.4,12-12C36,18.4,30.6,13,24,13z M24,30c-2.8,0-5-2.2-5-5c0-2.8,2.2-5,5-5s5,2.2,5,5C29,27.8,26.8,30,24,30z"/></svg>

Before

Width:  |  Height:  |  Size: 990 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="512px" height="512px"><linearGradient id="gCW9sGJUkBnBLRc40wQXGa" x1="25.447" x2="44.728" y1="4.921" y2="36.29" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#42a3f2"/><stop offset="1" stop-color="#42a4eb"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGa)" d="M42,8H19l11,30h12c1.105,0,2-0.895,2-2V10C44,8.895,43.105,8,42,8z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGb" x1="3.865" x2="23.412" y1="9.86" y2="41.663" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1d59b3"/><stop offset="1" stop-color="#195bbc"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGb)" d="M19,8H6c-1.105,0-2,0.895-2,2v26c0,1.105,0.895,2,2,2h8v7.998 c0,0.891,1.077,1.337,1.707,0.707L24.412,38H30L19,8z"/><path fill="#fff" d="M12,25h6v2h-6V25z"/><path fill="#fff" d="M12.109,29L15,20l2.906,9h2.11L16,17h-2l-4,12H12.109z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGc" x1="29.064" x2="38.79" y1="23.554" y2="23.554" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGc)" d="M29.064,27.223c0.061-0.031,4.994-3.219,7.936-9.115L38.79,19 c-3.082,6.25-7.457,9.292-8.509,10L29.064,27.223z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGd" x1="28" x2="40" y1="23.5" y2="23.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGd)" d="M38,29c0,0-5-2.583-7.769-6.998L32,21c2.333,3.833,6.981,6.26,6.981,6.26L38,29z M28,18h12v2 H28V18z"/><linearGradient id="gCW9sGJUkBnBLRc40wQXGe" x1="33" x2="35" y1="18" y2="18" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#11408a"/><stop offset="1" stop-color="#103f8f"/></linearGradient><path fill="url(#gCW9sGJUkBnBLRc40wQXGe)" d="M33,16h2v4h-2V16z"/></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>I18N Commander</title>
<base href="/" />
<link rel="stylesheet" href="css/bootstrap.min.css" />
<link rel="stylesheet" href="css/app.css" />
</head>
<body>
<div id="app">Loading...</div>
<script src="js/bootstrap.bundle.min.js"></script>
<script src="_framework/blazor.webview.js" autostart="false"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,76 +0,0 @@
using DataModel.Database;
namespace UI_WinForms;
internal static class AppEvents
{
static AppEvents()
{
AppEvents.AddSomethingHandlers();
}
internal static void ResetAllSubscriptions()
{
WhenSettingsChanged = null;
WhenSectionChanged = null;
WhenTextElementChanged = null;
WhenTranslationChanged = null;
AppEvents.AddSomethingHandlers();
}
#region Event: Settings changed
internal static event EventHandler? WhenSettingsChanged;
internal static void SettingsChanged() => WhenSettingsChanged?.Invoke(null, EventArgs.Empty);
#endregion
#region Event: Section was changed
// Section changed event which can be subscribed:
internal static event EventHandler<Section>? WhenSectionChanged;
// Method to raise the section changed event:
internal static void SectionChanged(Section section) => WhenSectionChanged?.Invoke(null, section);
#endregion
#region Event: Text element was changed
// Text element changed event which can be subscribed:
internal static event EventHandler<TextElement?>? WhenTextElementChanged;
// Method to raise the text element changed event:
internal static void TextElementChanged(TextElement? textElement) => WhenTextElementChanged?.Invoke(null, textElement);
#endregion
#region Translation was changed
// Translation changed event which can be subscribed:
internal static event EventHandler<Translation?>? WhenTranslationChanged;
// Method to raise the translation changed event:
internal static void TranslationChanged(Translation? translation) => WhenTranslationChanged?.Invoke(null, translation);
#endregion
#region Event: Something was changed
internal static event EventHandler? WhenSomethingChanged;
internal static void SomethingChanged() => WhenSomethingChanged?.Invoke(null, EventArgs.Empty);
private static void AddSomethingHandlers()
{
// Raise the something event when any of the other change-events are raised:
WhenSectionChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
WhenTextElementChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
WhenTranslationChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
WhenSettingsChanged += (sender, args) => WhenSomethingChanged?.Invoke(sender, EventArgs.Empty);
}
#endregion
}

View File

@ -1,185 +0,0 @@
namespace UI_WinForms.Components
{
partial class LoaderStart
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.pictureBox = new System.Windows.Forms.PictureBox();
this.labelTitle = new System.Windows.Forms.Label();
this.flowLayoutButtons = new System.Windows.Forms.FlowLayoutPanel();
this.buttonNew = new System.Windows.Forms.Button();
this.buttonOpen = new System.Windows.Forms.Button();
this.labelVersion = new System.Windows.Forms.Label();
this.contextMenuRecentProjects = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.tableLayout.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
this.flowLayoutButtons.SuspendLayout();
this.contextMenuRecentProjects.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 4;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 128F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 360F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayout.Controls.Add(this.pictureBox, 1, 1);
this.tableLayout.Controls.Add(this.labelTitle, 2, 1);
this.tableLayout.Controls.Add(this.flowLayoutButtons, 1, 2);
this.tableLayout.Controls.Add(this.labelVersion, 1, 3);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 5;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 128F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayout.Size = new System.Drawing.Size(937, 465);
this.tableLayout.TabIndex = 0;
//
// pictureBox
//
this.pictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox.Image = global::UI_WinForms.Resources.Icons.icons8_language_512;
this.pictureBox.Location = new System.Drawing.Point(227, 118);
this.pictureBox.Name = "pictureBox";
this.pictureBox.Size = new System.Drawing.Size(122, 122);
this.pictureBox.TabIndex = 0;
this.pictureBox.TabStop = false;
//
// labelTitle
//
this.labelTitle.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelTitle.Font = new System.Drawing.Font("Segoe UI", 28F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.labelTitle.Location = new System.Drawing.Point(355, 115);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(354, 128);
this.labelTitle.TabIndex = 1;
this.labelTitle.Text = "I18N Commander";
this.labelTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// flowLayoutButtons
//
this.tableLayout.SetColumnSpan(this.flowLayoutButtons, 2);
this.flowLayoutButtons.Controls.Add(this.buttonNew);
this.flowLayoutButtons.Controls.Add(this.buttonOpen);
this.flowLayoutButtons.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutButtons.Location = new System.Drawing.Point(224, 243);
this.flowLayoutButtons.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutButtons.Name = "flowLayoutButtons";
this.flowLayoutButtons.Size = new System.Drawing.Size(488, 66);
this.flowLayoutButtons.TabIndex = 2;
//
// buttonNew
//
this.buttonNew.Image = global::UI_WinForms.Resources.Icons.icons8_new_window_512;
this.buttonNew.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonNew.Location = new System.Drawing.Point(3, 3);
this.buttonNew.Name = "buttonNew";
this.buttonNew.Size = new System.Drawing.Size(200, 60);
this.buttonNew.TabIndex = 0;
this.buttonNew.Text = "New Project";
this.buttonNew.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.buttonNew.UseVisualStyleBackColor = true;
this.buttonNew.Click += new System.EventHandler(this.buttonNew_Click);
//
// buttonOpen
//
this.buttonOpen.Image = global::UI_WinForms.Resources.Icons.icons8_open_file_under_cursor_512;
this.buttonOpen.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonOpen.Location = new System.Drawing.Point(209, 3);
this.buttonOpen.Name = "buttonOpen";
this.buttonOpen.Size = new System.Drawing.Size(259, 60);
this.buttonOpen.TabIndex = 1;
this.buttonOpen.Text = "Open Recent Project";
this.buttonOpen.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.buttonOpen.UseVisualStyleBackColor = true;
this.buttonOpen.Click += new System.EventHandler(this.buttonOpen_Click);
//
// labelVersion
//
this.labelVersion.AutoSize = true;
this.labelVersion.BackColor = System.Drawing.Color.LightGray;
this.tableLayout.SetColumnSpan(this.labelVersion, 2);
this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelVersion.Location = new System.Drawing.Point(227, 309);
this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(482, 40);
this.labelVersion.TabIndex = 3;
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// contextMenuRecentProjects
//
this.contextMenuRecentProjects.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.contextMenuRecentProjects.ImageScalingSize = new System.Drawing.Size(20, 20);
this.contextMenuRecentProjects.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem1});
this.contextMenuRecentProjects.Name = "contextMenuRecentProjects";
this.contextMenuRecentProjects.Size = new System.Drawing.Size(73, 26);
this.contextMenuRecentProjects.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.contextMenuRecentProjects_Closing);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(72, 22);
//
// LoaderStart
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "LoaderStart";
this.Size = new System.Drawing.Size(937, 465);
this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
this.flowLayoutButtons.ResumeLayout(false);
this.contextMenuRecentProjects.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private PictureBox pictureBox;
private Label labelTitle;
private FlowLayoutPanel flowLayoutButtons;
private Button buttonNew;
private Button buttonOpen;
private ContextMenuStrip contextMenuRecentProjects;
private ToolStripMenuItem toolStripMenuItem1;
private Label labelVersion;
}
}

View File

@ -1,206 +0,0 @@
using System.ComponentModel;
using Microsoft.Win32;
using Version = Processor.Version;
namespace UI_WinForms.Components;
[DefaultEvent(nameof(LoadProject))]
public partial class LoaderStart : UserControl
{
private bool areRecentProjectsVisible = false;
public LoaderStart()
{
this.InitializeComponent();
this.labelVersion.Text = Version.Text;
}
#region Recent Projects
private static RegistryKey I18NCommanderKey => Registry.CurrentUser.OpenSubKey("Software", RegistryKeyPermissionCheck.ReadWriteSubTree)!.CreateSubKey("I18N Commander", RegistryKeyPermissionCheck.ReadWriteSubTree);
/// <summary>
/// Gets or sets the list of recent projects without any extras e.g. it does not prune the list of projects.
/// </summary>
private static List<string> RecentProjects
{
get
{
using var regKey = LoaderStart.I18NCommanderKey;
var recentProjectsValue = regKey.GetValue("recentProjects");
return recentProjectsValue switch
{
string[] list => new List<string>(list),
_ => new List<string>(),
};
}
set
{
using var regKey = LoaderStart.I18NCommanderKey;
regKey.SetValue("recentProjects", value.ToArray(), RegistryValueKind.MultiString);
}
}
private static void UpdateRecentProjectsWithPruning(string latestUsedProjectPath)
{
var previousRecentList = LoaderStart.RecentProjects;
// Check, if the latest project is identical to the next project we open. In that case, we don't add it to the list.
if (previousRecentList.Any() && previousRecentList[0] == latestUsedProjectPath)
return;
// Add the next project to the list:
previousRecentList.Insert(0, latestUsedProjectPath);
// Prune the list:
if (previousRecentList.Count > 6)
previousRecentList = previousRecentList.Take(6).ToList();
LoaderStart.RecentProjects = previousRecentList;
}
#endregion
// Opens the recent projects dropdown menu.
private void buttonOpen_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
if(this.areRecentProjectsVisible)
{
this.areRecentProjectsVisible = false;
this.contextMenuRecentProjects.Close();
return;
}
var recentProjects = LoaderStart.RecentProjects;
this.contextMenuRecentProjects.Items.Clear();
this.contextMenuRecentProjects.Items.Add("Browse for project...", Resources.Icons.icons8_browse_folder_512, (innerSender, args) => this.BrowseForProject());
foreach (var recentProject in recentProjects)
{
var fileInfo = new FileInfo(recentProject);
// Split the file's path into each folder's name:
var folderNames = fileInfo.DirectoryName!.Split(Path.DirectorySeparatorChar);
// Distinguish between I18N Commander projects and JSON imports:
if (fileInfo.Extension == ".i18nc")
{
// Render this entry:
var item = this.contextMenuRecentProjects.Items.Add($"{folderNames.Last()}: {fileInfo.Name}", Resources.Icons.icons8_document_512, (innerSender, args) => this.OpenRecentProject(innerSender, LoaderAction.LOAD_PROJECT));
item.Tag = recentProject;
}
else if (fileInfo.Extension == ".json")
{
// Render this entry:
var item = this.contextMenuRecentProjects.Items.Add($"{folderNames.Last()}: {fileInfo.Name}", Resources.Icons.icons8_git, (innerSender, args) => this.OpenRecentProject(innerSender, LoaderAction.IMPORT_JSON));
item.Tag = recentProject;
}
}
var button = (sender as Button)!;
this.contextMenuRecentProjects.Show(button, 0, button.Height);
this.areRecentProjectsVisible = true;
}
private void buttonNew_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
var saveDialog = new SaveFileDialog
{
AddExtension = true,
CheckPathExists = true,
CheckFileExists = false,
CreatePrompt = false,
OverwritePrompt = true,
DereferenceLinks = true,
DefaultExt = ".i18nc",
Filter = "I18N Commander Files (*.i18nc)|*.i18nc",
RestoreDirectory = true,
Title = "Create a new I18N Commander file",
};
var dialogResult = saveDialog.ShowDialog(this);
if (dialogResult != DialogResult.OK)
return;
var destinationFilePath = saveDialog.FileName;
// When the user chose an existing file, we delete it:
// (note: the user already accepts overwriting the file)
if (File.Exists(destinationFilePath))
File.Delete(destinationFilePath);
LoaderStart.UpdateRecentProjectsWithPruning(destinationFilePath);
this.OpenProject(LoaderAction.CREATE_NEW_PROJECT, destinationFilePath);
}
private void BrowseForProject()
{
var openDialog = new OpenFileDialog
{
AddExtension = true,
CheckPathExists = true,
CheckFileExists = true,
DereferenceLinks = true,
DefaultExt = ".i18nc",
// I18N Commander files (*.i18nc) or JSON files (*.json):
Filter = "I18N Commander Files (*.i18nc)|*.i18nc|JSON Files (*.json)|*.json",
Multiselect = false,
RestoreDirectory = true,
Title = "Open an I18N Commander file or Import a JSON file",
};
var dialogResult = openDialog.ShowDialog(this);
if (dialogResult != DialogResult.OK)
return;
var projectFilePath = openDialog.FileName;
LoaderStart.UpdateRecentProjectsWithPruning(projectFilePath);
// Check, if the user chose an I18N Commander file or a JSON file:
if (projectFilePath.ToLowerInvariant().EndsWith(".i18nc", StringComparison.InvariantCulture))
this.OpenProject(LoaderAction.LOAD_PROJECT, projectFilePath);
else if (projectFilePath.ToLowerInvariant().EndsWith(".json", StringComparison.InvariantCulture))
this.OpenProject(LoaderAction.IMPORT_JSON, projectFilePath);
}
private void OpenRecentProject(object? sender, LoaderAction action)
{
if (sender is not ToolStripItem item)
return;
var path = (item.Tag as string)!;
LoaderStart.UpdateRecentProjectsWithPruning(path);
this.OpenProject(action, path);
}
private void OpenProject(LoaderAction action, string path)
{
// Hint: the project file might or might not exist (new project vs. recent project)
this.LoadProject?.Invoke(this, new LoaderResult(action, path));
}
private void contextMenuRecentProjects_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
this.areRecentProjectsVisible = false;
}
[Category("Settings"), Description("When the user chooses a project to load.")]
public event EventHandler<LoaderResult>? LoadProject;
public readonly record struct LoaderResult(LoaderAction Action, string DataFile);
public enum LoaderAction
{
NONE,
LOAD_PROJECT,
CREATE_NEW_PROJECT,
IMPORT_JSON,
}
}

View File

@ -1,63 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="contextMenuRecentProjects.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -1,251 +0,0 @@
namespace UI_WinForms.Components
{
partial class Main
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.splitContainerLR = new System.Windows.Forms.SplitContainer();
this.sectionTree = new UI_WinForms.Components.SectionTree();
this.splitContainerRTB = new System.Windows.Forms.SplitContainer();
this.textElements = new UI_WinForms.Components.TextElements();
this.translations = new UI_WinForms.Components.Translations();
this.translationProgress = new UI_WinForms.Components.TranslationProgress();
this.tabControl = new System.Windows.Forms.TabControl();
this.tabTranslation = new System.Windows.Forms.TabPage();
this.tabSettings = new System.Windows.Forms.TabPage();
this.settings = new UI_WinForms.Components.Settings();
this.imageList = new System.Windows.Forms.ImageList(this.components);
this.tableLayout.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainerLR)).BeginInit();
this.splitContainerLR.Panel1.SuspendLayout();
this.splitContainerLR.Panel2.SuspendLayout();
this.splitContainerLR.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainerRTB)).BeginInit();
this.splitContainerRTB.Panel1.SuspendLayout();
this.splitContainerRTB.Panel2.SuspendLayout();
this.splitContainerRTB.SuspendLayout();
this.tabControl.SuspendLayout();
this.tabTranslation.SuspendLayout();
this.tabSettings.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 1;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.splitContainerLR, 0, 1);
this.tableLayout.Controls.Add(this.translationProgress, 0, 0);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(3, 3);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 2;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Size = new System.Drawing.Size(1237, 709);
this.tableLayout.TabIndex = 0;
//
// splitContainerLR
//
this.splitContainerLR.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.splitContainerLR.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainerLR.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitContainerLR.Location = new System.Drawing.Point(3, 23);
this.splitContainerLR.Name = "splitContainerLR";
//
// splitContainerLR.Panel1
//
this.splitContainerLR.Panel1.Controls.Add(this.sectionTree);
this.splitContainerLR.Panel1MinSize = 300;
//
// splitContainerLR.Panel2
//
this.splitContainerLR.Panel2.Controls.Add(this.splitContainerRTB);
this.splitContainerLR.Size = new System.Drawing.Size(1231, 683);
this.splitContainerLR.SplitterDistance = 319;
this.splitContainerLR.TabIndex = 1;
//
// sectionTree
//
this.sectionTree.Dock = System.Windows.Forms.DockStyle.Fill;
this.sectionTree.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.sectionTree.Location = new System.Drawing.Point(0, 0);
this.sectionTree.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.sectionTree.Name = "sectionTree";
this.sectionTree.Size = new System.Drawing.Size(317, 681);
this.sectionTree.TabIndex = 0;
//
// splitContainerRTB
//
this.splitContainerRTB.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.splitContainerRTB.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainerRTB.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitContainerRTB.Location = new System.Drawing.Point(0, 0);
this.splitContainerRTB.Name = "splitContainerRTB";
this.splitContainerRTB.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainerRTB.Panel1
//
this.splitContainerRTB.Panel1.Controls.Add(this.textElements);
this.splitContainerRTB.Panel1MinSize = 376;
//
// splitContainerRTB.Panel2
//
this.splitContainerRTB.Panel2.Controls.Add(this.translations);
this.splitContainerRTB.Size = new System.Drawing.Size(908, 683);
this.splitContainerRTB.SplitterDistance = 376;
this.splitContainerRTB.TabIndex = 0;
//
// textElements
//
this.textElements.Dock = System.Windows.Forms.DockStyle.Fill;
this.textElements.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.textElements.Location = new System.Drawing.Point(0, 0);
this.textElements.Name = "textElements";
this.textElements.Size = new System.Drawing.Size(906, 374);
this.textElements.TabIndex = 0;
//
// translations
//
this.translations.Dock = System.Windows.Forms.DockStyle.Fill;
this.translations.Enabled = false;
this.translations.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.translations.Location = new System.Drawing.Point(0, 0);
this.translations.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.translations.Name = "translations";
this.translations.Size = new System.Drawing.Size(906, 301);
this.translations.TabIndex = 0;
//
// translationProgress
//
this.translationProgress.Dock = System.Windows.Forms.DockStyle.Fill;
this.translationProgress.Location = new System.Drawing.Point(0, 0);
this.translationProgress.Margin = new System.Windows.Forms.Padding(0);
this.translationProgress.Name = "translationProgress";
this.translationProgress.Size = new System.Drawing.Size(1237, 20);
this.translationProgress.TabIndex = 2;
//
// tabControl
//
this.tabControl.Alignment = System.Windows.Forms.TabAlignment.Left;
this.tabControl.Controls.Add(this.tabTranslation);
this.tabControl.Controls.Add(this.tabSettings);
this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl.ImageList = this.imageList;
this.tabControl.Location = new System.Drawing.Point(0, 0);
this.tabControl.Multiline = true;
this.tabControl.Name = "tabControl";
this.tabControl.Padding = new System.Drawing.Point(12, 12);
this.tabControl.SelectedIndex = 0;
this.tabControl.Size = new System.Drawing.Size(1317, 723);
this.tabControl.TabIndex = 1;
this.tabControl.SelectedIndexChanged += new System.EventHandler(this.tabControl_SelectedIndexChanged);
//
// tabTranslation
//
this.tabTranslation.Controls.Add(this.tableLayout);
this.tabTranslation.ImageIndex = 1;
this.tabTranslation.Location = new System.Drawing.Point(70, 4);
this.tabTranslation.Name = "tabTranslation";
this.tabTranslation.Padding = new System.Windows.Forms.Padding(3);
this.tabTranslation.Size = new System.Drawing.Size(1243, 715);
this.tabTranslation.TabIndex = 0;
this.tabTranslation.Text = "Translation";
this.tabTranslation.UseVisualStyleBackColor = true;
//
// tabSettings
//
this.tabSettings.Controls.Add(this.settings);
this.tabSettings.ImageIndex = 0;
this.tabSettings.Location = new System.Drawing.Point(70, 4);
this.tabSettings.Name = "tabSettings";
this.tabSettings.Padding = new System.Windows.Forms.Padding(3);
this.tabSettings.Size = new System.Drawing.Size(1243, 715);
this.tabSettings.TabIndex = 1;
this.tabSettings.Text = "Settings";
this.tabSettings.UseVisualStyleBackColor = true;
//
// settings
//
this.settings.Dock = System.Windows.Forms.DockStyle.Fill;
this.settings.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.settings.Location = new System.Drawing.Point(3, 3);
this.settings.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.settings.Name = "settings";
this.settings.Size = new System.Drawing.Size(1237, 709);
this.settings.TabIndex = 0;
//
// imageList
//
this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));
this.imageList.TransparentColor = System.Drawing.Color.Transparent;
this.imageList.Images.SetKeyName(0, "icons8-settings.svg.png");
this.imageList.Images.SetKeyName(1, "icons8-language-45.png");
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.tabControl);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "Main";
this.Size = new System.Drawing.Size(1317, 723);
this.tableLayout.ResumeLayout(false);
this.splitContainerLR.Panel1.ResumeLayout(false);
this.splitContainerLR.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainerLR)).EndInit();
this.splitContainerLR.ResumeLayout(false);
this.splitContainerRTB.Panel1.ResumeLayout(false);
this.splitContainerRTB.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainerRTB)).EndInit();
this.splitContainerRTB.ResumeLayout(false);
this.tabControl.ResumeLayout(false);
this.tabTranslation.ResumeLayout(false);
this.tabSettings.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private SplitContainer splitContainerLR;
private SplitContainer splitContainerRTB;
private SectionTree sectionTree;
private TextElements textElements;
private TabControl tabControl;
private TabPage tabTranslation;
private TabPage tabSettings;
private ImageList imageList;
private Settings settings;
private Translations translations;
private TranslationProgress translationProgress;
}
}

View File

@ -1,56 +0,0 @@
using DataModel.Database;
using Processor;
using UI_WinForms.Dialogs;
namespace UI_WinForms.Components;
public partial class Main : UserControl
{
public Main()
{
this.InitializeComponent();
Program.RestartMainApp = false;
// Register the something changed event to trigger the export:
AppEvents.WhenSomethingChanged += async (_, _) => await ExportProcessor.TriggerExport();
// Check, if the DeepL integration is enabled, but no API key is set:
this.Load += async (sender, args) =>
{
var deepLAPIKey = await AppSettings.GetDeepLAPIKey();
var deepLMode = await AppSettings.GetDeepLMode();
if (deepLMode is not SettingDeepLMode.DISABLED && string.IsNullOrWhiteSpace(deepLAPIKey))
{
// Show the input dialog to ask the user for the DeepL API key:
var inputDialog = InputDialog.Show(new InputDialog.Options
{
Title = "I18NCommander - DeepL API Key",
Message = "The DeepL integration is enabled, but there is no API key set. Do you want to set one now?",
OkButtonText = "Set API key",
CancelButtonText = "No, thanks",
ShowQuestionCheckbox = false,
});
if (inputDialog.DialogResult == DialogResult.OK)
{
await AppSettings.SetDeepLAPIKey(inputDialog.Text);
AppEvents.SettingsChanged();
}
}
};
}
private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.settings.NeedRestart())
{
var result = MessageBox.Show("You need to restart the app for the changes to take effect. Do you want to restart?", "Restart required", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if(result == DialogResult.Yes)
{
Program.RestartMainApp = true;
AppEvents.ResetAllSubscriptions();
this.ParentForm!.Close();
}
}
}
}

View File

@ -1,386 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="imageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="imageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAHEoAAAJNU0Z0AUkBTAIBAQIB
AAFgAQABYAEAAS0BAAEtAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABtAMAAS0DAAEBAQABIAUAAZAB
fvoAAw8BFAMTARkEAf8A/wAqAAMnATkDTgGWA1EBoQNRAaEDUQGhA04BlgMnATp8AAMLAQ4CUwFRAaIB
XQFbAVoBxwMlATb/AP8AJgADEQEWA1EB8wE6AjkB/wE9ATwBOwH/AT0BPAE7Af8BPQE8ATsB/wE6AjkB
/wNSAfQDEQEWeAADEgEYA10BzAG8AVsBGQH/AWICXgHXAxABFf8A/wAiAAM/AW4BRgFDAUIB/wHEAa8B
pgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AcQBrgGmAf8BRgFDAUIB/wNAAXB4AAMSARgDXQHMAbwB
WwEZAf8BvAFbARkB/wFhAV8BWwHYAyUBNwQB/wD/ABoAA1gBtwFXAVIBUAH/Ad4BxQG7Af8B5wHNAcIB
/wHnAc0BwgH/AecBzQHCAf8B3gHFAbsB/wFXAVIBTwH/A1gBugQBdAADEgEYA10BzAG7AVsBGQH/AbwB
WwEZAf8BvAFbARkB/wFjAl8B1QIaARkBI/8A8QADAwEEAyIBMQMpAT4DEgEYFAADEgEYA2AB2wF7AXAB
bAH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wF6AXABawH/A2AB2wMTARoU
AAMSARcDKQE+AyIBMQMDAQRQAAMSARgDXQHMAbsBWwEZAf8BuwFbARkB/wG7AVsBGQH/AbwBWwEZAf8B
YQJdAdQDIQEvBAH/AOUAAwIBAwM9AWkDWwHkA1cB7wNbAdADNgFZAwQBBQwAAygBOwNdAewBqwGaAZMB
/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8BqgGZAZIB/wNcAe0DKQE9DAAD
AwEEAzYBVwNdAc8DVwHvA18B5QM+AWoDAgEDTAADEgEYA10BzAG7AVsBGgH/AbsBWwEZAf8BuwFbARkB
/wG7AVsBGQH/AbsBWwEZAf8BXwFcAVsB0wMiATH/AOEAAwIBAwM0AVMDWAHxAW8BaQFmAf8BtwGrAaQB
/wFdAVkBVwH/AzoB+wNRAaQDGQEiAwQBBQMJAQwDPwFuATgCNwH7AdwByAG+Af8B5wHOAcMB/wHnAc0B
wgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AdgBwAG2Af8DKwH8A0ABcQMKAQ0DAwEEAxgBIANRAaIB
OwE6ATkB+wFeAVcBVAH/AbYBowGbAf8BcAFnAWMB/wNZAfIDNQFVAwIBA0gAAxIBGANdAcwBuwFbARoB
/wG7AVsBGgH/AbsBWwEZAf8BuwFbARkB/wG7AVsBGQH/AbsBWwEZAf8BYQJdAdQDGAEg/wDZAAMDAQQD
PQFoA1gB8QF/AXQBbwH/AeMBzAHBAf8B7AHaAdAB/wHkAdUBywH/AacBnQGXAf8BUwFQAU8B/wNbAeQD
TgGYA1UBtANdAewBeAFyAW4B/wHtAdwB0gH/AeoB1QHLAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AXUBawFnAf8DXAHtA1YBtQNOAZcDXgHiAVMBTgFMAf8BpAGUAY0B/wHfAcYB
uwH/AecBzQHCAf8B4wHJAb4B/wGAAXUBcAH/A1kB8gM+AWoDAwEERAADEgEYA10BzAG6AVsBGgH/AbsB
WwEaAf8BuwFbARoB/wG7AVsBGgH/AbsBWwEZAf8BuwFbARkB/wG7AVsBGQH/AWECXAHWAyUBN/8A1QAD
IQEvA14B4wFvAWoBZgH/AeMBzAHCAf8B5wHNAcIB/wHoAdABxQH/Ae0B3AHSAf8B7QHdAdMB/wHoAdkB
zwH/AYQBfgF5Af8DNwH/AU4BTAFLAf8BtwGrAaUB/wHqAdsB0QH/Ae0B3QHTAf8B7QHdAdMB/wHrAdUB
ywH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5QHLAcAB/wGzAaABmAH/AU0BSgFIAf8B
NwI2Af8BgQF1AXEB/wHjAckBvwH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B4wHJAb4B
/wFwAWcBYwH/A18B5QMiATEkAAMhATADUgGgAlYBVAGrAlYBVAGrAlYBVAGrAlYBVAGrAlYBVAGrAlYB
VAGrAlgBVgGzAXQBYgFVAe4BugFbARoB/wG6AVsBGgH/AbsBWwEaAf8BuwFbARoB/wG7AVsBGgH/AbsB
WwEaAf8BuwFbARkB/wG7AVsBGQH/AWwCXwHlA1UBrQJWAVQBqwJWAVQBqwJWAVQBqwJUAVMBqQJWAVQB
qwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQBqwJWAVQB
qwNSAaADIQEw/wCNAAMoATwDXAHtAbcBqwGkAf8B7AHbAdAB/wHpAdEBxgH/AecBzQHCAf8B6AHRAcYB
/wHsAdoB0AH/Ae0B3QHTAf8B7AHcAdIB/wHeAc8BxgH/AewB3AHSAf8B7QHdAdMB/wHtAd0B0wH/Ae0B
3QHTAf8B7QHdAdMB/wHtAd0B0wH/AeoB1QHLAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB
/wHnAc0BwgH/AeYBzAHBAf8B2AHAAbYB/wHmAcwBwQH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wHnAc0BwgH/AbEBngGXAf8DVwHvAykBPSAAAyABLgFxAV0BWgHsAbkBWgEaAf8B
uQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BuQFaARoB/wG6AVoBGgH/AboBWgEaAf8BugFbARoB/wG6AVsB
GgH/AboBWwEaAf8BugFbARoB/wG6AVsBGgH/AboBWwEaAf8BuwFbARoB/wG7AVsBGgH/AbsBWwEaAf8B
uwFbARkB/wG7AVsBGQH/AbsBWwEZAf8BuwFbARkB/wG7AVsBGQH/AbwBWwEZAf8BtQF1ASsB/AHsAaQB
QgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8B
6wGkAUIB/wHrAaQBQgH/AesBpAFCAf8B6wGkAUIB/wF3AW8BYQHrAyABLf8AiQADEAEVA1sBzQFcAVkB
VgH/AeMB1AHLAf8B7QHcAdIB/wHpAdEBxgH/AecBzQHCAf8B6AHQAcUB/wHsAdsB0QH/Ae0B3QHTAf8B
7QHdAdMB/wHtAd0B0wH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B0wH/Ae0B3QHTAf8B7QHdAdMB/wHtAdwB
0gH/AesB1QHKAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B3QHFAboB/wFaAVUB
UgH/A10BzgMRARYgAAMzAVABgwFgAT8B9gG5AVoBGwH/AbkBWgEaAf8BuQFaARoB/wG5AVoBGgH/AbkB
WgEaAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BugFaARoB/wG6AVsBGgH/AboBWwEaAf8BugFbARoB
/wG6AVsBGgH/AboBWwEaAf8BugFbARoB/wG7AVsBGgH/AbsBWwEaAf8BuwFbARoB/wG7AVsBGQH/AbsB
WwEZAf8BuwFbARkB/wGlAWkBJgH+Ab4BigFAAf0B7QGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB
/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AesB
pAFCAf8BlwF6AUgB9gMzAVD/AI0AAzMBUgNNAfoBpgGbAZUB/wHtAd0B0wH/AewB2wHQAf8B6QHRAcYB
/wHrAdcB0AH/AewB2gHTAf8B7AHbAdEB/wHtAd0B0wH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B0wH/Ae0B
3QHTAf8B7QHdAdMB/wHqAdoB0AH/AcYBuQGxAf8B6gHaAdAB/wHqAdUBygH/AecBzgHDAf8B5wHNAcIB
/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wGhAZEBiwH/AToCOQH7AzUBViQAAzMBUQGMAVsBQAH3AbgBWgEbAf8BuQFaARsB
/wG5AVoBGwH/AbkBWgEaAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BuQFaARoB/wG6AVoBGgH/AboB
WgEaAf8BugFaARoB/wG6AVsBGgH/AboBWwEaAf8BugFbARoB/wG6AVsBGgH/AboBWwEaAf8BuwFbARoB
/wG7AVsBGgH/AbsBWwEaAf8BuwFbARkB/wG7AVsBGQH/AaoBbwEqAf4BwwGZAUAB/QHtAaQBQgH/Ae0B
pAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB
/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wGXAXoBSAH2AzMBUf8AjQADAwEEA1ABnQFSAU8BTQH/AecB
1wHNAf8B7QHdAdMB/wHwAeQB3wH/AfYB8gH3Af8B9QHxAfUB/wHtAdsB1QH/AewB2gHQAf8B7QHdAdMB
/wHYAcoBwQH/AcYBuQGxAf8B6AHWAcwB/wHfAcsBwQH/Ac8BuwGxAf8BQQI/Af8BzwG6AbEB/wHfAcoB
wAH/AaQBlgGPAf8BjwGCAXwB/wHmAcwBwQH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B4QHIAb4B/wFQAUwBSgH/A1EBogMDAQQkAAMzAVEBjAFbAUAB
9wG4AVoBGwH/AbgBWgEbAf8BuAFaARsB/wG5AVoBGwH/AbkBWgEbAf8BuQFaARoB/wG5AVoBGgH/AbkB
WgEaAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BugFaARoB/wG6AVsBGgH/AboBWwEaAf8BugFbARoB
/wG6AVsBGgH/AboBWwEaAf8BugFbARoB/wG7AVsBGgH/AbsBWwEaAf8BuwFbARoB/wGzAXMBKwH8AewB
owFBAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB
/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8BlwF6AUgB9gMzAVH/AJEAAxcB
HwNdAd8BfwF5AXQB/wHsAdwB0gH/Ae0B3QHUAf8B9ALtAf8B8AHkAeIB/wHnAc0BwgH/AeUBzgHDAf8B
uwGvAagB/wFGAUQBQwH/AU8BSwFJAf8B0AG3AawB/wHQAbcBrAH/AcQBrQGjAf8BOAI3Af8BxAGtAaMB
/wHDAawBogH/AU8BSwFJAf8BZAFcAVkB/wHiAcgBvQH/AeYBzAHBAf8B5gHMAcEB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wHnAc0BwgH/AeYBzAHBAf8BfgF0AW4B/wNeAeIDGAEgKAADMwFRAYwBWwFAAfcB
uAFaARsB/wG4AVoBGwH/AbgBWgEbAf8BuAFaARsB/wG4AVoBGwH/AbkBWgEbAf8BuQFaARoB/wG5AVoB
GgH/AbkBWgEaAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BugFaARoB/wG6AVoBGgH/AboBWwEaAf8B
ugFbARoB/wG6AVsBGgH/AboBWwEaAf8BugFbARoB/wG6AVsBGgH/AbsBWwEaAf8BugGEATgB+wHtAaQB
QgH/Ae0BpAFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wHtAaQBQgH/AewBpAFCAf8B
7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AZcBegFIAfYDMwFR/wCRAAMDAQQD
TQGTAzYB/wHaAcoBwQH/Ae0B3QHTAf8B7gHfAdYB/wHtAd0B1AH/AeUBzgHDAf8BlgGIAYIB/wE4AjcB
/wFsAWMBXwH/AbYBoQGYAf8B0AG3AawB/wHQAbcBrAH/AcwBtAGpAf8BnAGLAYQB/wHMAbQBqQH/AbYB
ogGYAf8BVAFPAUwB/wGqAZcBjwH/Ac8BtgGsAf8BlAGFAYAB/wGvAZ4BlgH/AeYBzAHBAf8B5wHNAcIB
/wHnAc0BwgH/AecBzQHCAf8B2QHAAbYB/wE3AjYB/wNOAZYDAwEEKAADMwFRAYwBWwFAAfcBuAFaARsB
/wG4AVoBGwH/AbgBWgEbAf8BuAFaARsB/wG4AVoBGwH/AbgBWgEbAf8BuAFaARsB/wG5AVoBGwH/AbkB
WgEaAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BuQFaARoB/wG5AVoBGgH/AboBWgEaAf8BugFaARoB
/wG6AVsBGgH/AboBWwEaAf8BugFbARoB/wG6AVsBGgH/AaoBZgErAfwB1gGMAU0B/gHtAaQBQgH/Ae0B
pAFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB
/wHsAaQBQgH/AewBpAFCAf8B7AGkAUIB/wHsAaQBQgH/AZcBegFIAfYDMwFR/wCRAAMJAQwDVgGyAUkB
RgFFAf8B5gHPAcQB/wHtAdwB0gH/Ae0B3QHTAf8B7QHdAdMB/wG8AbABqAH/AjgBNwH/AXsBcAFrAf8B
zgG1AaoB/wHQAbcBrAH/AdABtwGsAf8B0AG3AawB/wHQAbcBrAH/AdABtwGsAf8B0AG3AawB/wHPAbYB
qwH/AcwBtAGpAf8BzwG2AasB/wGEAXcBcgH/AzUB/wGTAYUBfwH/AeYBzAHBAf8B5wHNAcIB/wHnAc0B
wgH/AecBzQHCAf8B5gHMAcEB/wFQAUsBSgH/A1UBtAMJAQwoAAMzAVEBiwFbAUAB9wG3AVoBGwH/AbgB
WgEbAf8BuAFaARsB/wG4AVoBGwH/AbgBWgEbAf8BuAFaARsB/wG4AVoBGwH/AbgBWgEbAf8BuQFaARsB
/wG5AVoBGgH/AbkBWgEaAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BuQFaARoB/wG6AVoBGgH/AboB
WgEaAf8BugFbARoB/wG6AVsBGgH/AboBWwEaAf8BrgFtATEB+wHuAaQBQgH/Ae0BpAFCAf8B7QGkAUIB
/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0B
pAFCAf8B7AGkAUIB/wHsAaQBQgH/AewBpAFCAf8BlwF6AUgB9gMzAVH/AIkAAxMBGgMpAT0DQAFwA14B
6wGvAZ8BmAH/AecBzQHCAf8B6QHRAcYB/wHsAdsB0AH/AdYByAG/Af8BRgFEAUMB/wFrAWIBXgH/Ac4B
tQGqAf8B0AG3AawB/wHOAbYBqwH/AaIBkQGJAf8BaAFgAVwB/wFBAT8BPgH/AzUB/wFBAT4BPQH/AWgB
XwFbAf8BogGQAYgB/wHNAbQBqgH/AZQBhQF+Af8BhAF3AXEB/wHPAbYBrAH/AeMByQG+Af8B5wHNAcIB
/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wG0AaIBmgH/A14B6wM/AW4DKAE8AxMBGSAAAzMBUQGLAVsB
QAH3AbcBWgEbAf8BtwFaARsB/wG4AVoBGwH/AbgBWgEbAf8BwwFyATwB/wHLAYUBVgH/Ab8BaQEwAf8B
uAFaARsB/wG4AVoBGwH/AbkBWgEbAf8BuQFaARsB/wG9AWQBKAH/AcsBhQFWAf8BxQF2AUEB/wG5AVoB
GgH/AbkBWgEaAf8BuQFaARoB/wG6AVoBGgH/AboBWwEaAf8BvgFVATUB/QHCAZcBQAH9Ae4BpAFCAf8B
7gGkAUIB/wHeAZQBOgH/Ae0BowFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wHrAaIB
QQH/Ad0BkwE6Af8B7QGkAUIB/wHtAaQBQgH/AewBpAFCAf8B7AGkAUIB/wGXAXoBSAH2AzMBUf8AfQAD
EQEWA0ABcANYAboDYAHbA1wB7QMrAfwBdgFwAW0B/wHpAdkBzwH/AekB0QHHAf8B5wHNAcIB/wHoAdAB
xQH/AYUBfQF3Af8BPgE8ATsB/wGxAZ0BlAH/AdABtwGsAf8BzgG2AasB/wGCAXUBcAH/AT0CPAH/AUsB
YAFnAf8BcgGnAboB/wF9AbsB0gH/AXIBqAG8Af8BTAFhAWgB/wE9AjwB/wGBAXQBbwH/Ac0BtQGqAf8B
zwG2AasB/wHAAakBnwH/AYUBeAFzAf8BoAGQAYkB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHlAcsB
wAH/AXkBbwFqAf8COAE3AfsDXQHsA2AB2wNYAbgDQAFvAxEBFhQAAzMBUQGLAVsBQAH3AbcBWgEbAf8B
twFaARsB/wG3AVoBGwH/AbcBWgEbAf8BzgGMAWEB/wH7AfUB8QH/Ad0BsQGTAf8BuAFaARsB/wG4AVoB
GwH/AbgBWgEbAf8BuAFaARsB/wHWAaABfAH/AfsB9QHxAf8B1wGhAX4B/wG5AVoBGgH/AbkBWgEaAf8B
uQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BvgFiATwB/QHUAYkBTAH+Ae4BpAFCAf8B2QGPATgB/wGWAUwB
FwH/AcUBegEuAf8B7AGjAUEB/wHtAaQBQgH/Ae0BpAFCAf8B6QGgAUAB/wG5AW0BJwH/AZgBSgEVAf8B
3gGUAToB/wHtAaQBQgH/Ae0BpAFCAf8B7QGkAUIB/wGXAXoBSAH2AzMBUf8AeQADJgE4A1EB8wFGAUMB
QgH/AVcBUgFPAf8BeQFvAWoB/wGqAZkBkgH/AdoBxgG9Af8B7QHcAdIB/wHtAd0B0wH/AewB2wHRAf8B
6AHQAcYB/wHWAb4BtAH/AVcBUQFPAf8BZAFcAVgB/wHQAbcBrAH/AdABtwGsAf8BowGRAYkB/wE9AjwB
/wFaAXsBiAH/AYsB1gHwAf8BjwHdAfkB/wGPAd0B+QH/AY8B3QH5Af8BiwHWAfEB/wFbAXwBiQH/AT0C
PAH/AaIBkAGJAf8BzAG0AakB/wFNAUkBRwH/AUcBRAFCAf8BiwF/AXoB/wHmAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B3QHEAboB/wGvAZ0BlgH/AX4BcwFvAf8BWQFUAVEB/wFHAUQB
QwH/A1EB8wMnATkQAAMzAVEBiwFbAUAB9wG3AVoBGwH/AbcBWgEbAf8BtwFaARsB/wG3AVoBGwH/AbgB
XgEgAf8B+QHxAewB/wH4Ae4B5wH/AckBgQFQAf8ByQGBAVAB/wHJAYEBUAH/AckBgQFQAf8B9AHlAdwB
/wH7AfYB8wH/AcYBeAFEAf8BuQFaARoB/wG5AVoBGgH/AbkBWgEaAf8BuQFaARoB/wG5AVoBGgH/AasB
awEwAfsB7gGkAUIB/wHtAaMBQgH/AbwBcgEqAf8BjQFCARIB/wGOAUIBEgH/Ab8BdAErAf8B6AGeAT8B
/wHbAZEBOQH/AaMBVQEbAf8BjgE/ARAB/wGYAUoBFgH/AcwBggExAf8B7QGkAUIB/wHtAaQBQgH/Ae0B
pAFCAf8BlwF6AUgB9gMzAVH/AHkAA04BlAE6AjkB/wHCAa0BpAH/Ad4BxQG7Af8B5wHNAcIB/wHnAc0B
wgH/AecBzQHCAf8B6gHUAcoB/wHtAd0B0wH/Ae0B3QHTAf8B7AHbAdEB/wHFAbMBqgH/AUMBQAE/Af8B
oAGOAYcB/wHQAbcBrAH/AdABtwGsAf8BagFhAV0B/wFKAV4BZQH/AYsB1gHwAf8BjwHdAfkB/wGPAd0B
+QH/AY8B3QH5Af8BjwHdAfkB/wGPAd0B+QH/AYsB1gHxAf8BSwFgAWgB/wFoAWABXAH/Ac8BtgGrAf8B
qAGWAY0B/wG4AaMBmQH/Ad0ByQG/Af8B6gHVAcoB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0B
wgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AeABxwG9Af8BxgGxAacB/wE7AjkB/wNOAZYQAAMzAVEB
iwFbAUAB9wG3AVoBGwH/AbcBWgEbAf8BtwFaARsB/wG3AVoBGwH/AbcBWwEcAf8B5gHGAbEZ/wHvAdkB
ywH/Ab4BZwEtAf8BuAFaARsB/wG5AVoBGwH/AbkBWgEaAf8BuQFaARoB/wGiAWcBJgH+AcQBfgExAfwB
7gGkAUIB/wHuAaQBQgH/AekBnwE/Af8BxwF9AS8B/wGTAUcBFQH/AY0BQQESAf8BpwFbAR4B/wGZAUwB
FgH/AY4BQAERAf8BrwFhASEB/wHbAZEBOQH/AewBowFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B
lwF6AUgB9gMzAVH/AHkAA1EBogE9ATwBOwH/AeYBzAHBAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AeoB1AHJAf8B7QHdAdMB/wHtAd0B0wH/Ab0BsQGpAf8BNwI2Af8BxAGtAaMB
/wHQAbcBrAH/AdABtwGsAf8BQwFAAT8B/wFwAaUBtwH/AY8B3QH5Af8BjwHdAfkB/wFsAZwBrQH/AToB
QQFEAf8BagGaAasB/wGPAd0B+QH/AY8B3QH5Af8BcgGnAboB/wFBAT8BPgH/AdABtwGsAf8BzAGzAakB
/wHEAa0BowH/Ac8BuwGxAf8B6gHaAdAB/wHrAdUBygH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wE9ATwBOwH/A1EBoRAAAzMBUQGLAVsB
QQH3AbYBWgEcAf8BtwFaARsB/wG3AVoBGwH/AbcBWgEbAf8BtwFaARsB/wHUAZwBdgH/Af4B/QH8Af8B
9gHqAeMB/wHjAcABqAH/AeQBwAGnAf8B8gHgAdQF/wHhAbgBnAH/AbgBWwEcAf8BuAFaARsB/wG4AVoB
GwH/AbkBWgEbAf8BuQFaARsB/wGiAW4BMgH6Ae8BowFCAf8B7wGjAUIB/wHuAaQBQgH/Ae4BpAFCAf8B
7gGkAUIB/wHNAYMBMgH/AZABRAETAf8BjAFAAREB/wGNAT8BEAH/AbgBbAEmAf8B7AGiAUEB/wHuAaQB
QgH/Ae0BpAFCAf8B7QGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8BlwF6AUgB9gMzAVH/AHkAA1EBogE9ATwB
OwH/AeYBzAHBAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
6gHUAcoB/wHtAdwB0gH/AbgBrAGlAf8DMwH/Ac4BtQGqAf8B0AG3AawB/wHQAbcBrAH/ATgCNwH/AXwB
uQHQAf8BjwHdAfkB/wGPAd0B+QH/AT0BRgFJAf8DMwH/ATsBQwFFAf8BjwHdAfkB/wGPAd0B+QH/AXwB
uwHRAf8BNgI1Af8B0AG3AawB/wGcAYsBgwH/ATgCNwH/AUEBQAE/Af8BxwG6AbIB/wHtAdwB0gH/AeoB
1QHKAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB
/wE9ATwBOwH/A1EBoRAAAzMBUQGLAVsBQQH3AbYBWgEcAf8BtgFaARwB/wG3AVoBGwH/AbcBWgEbAf8B
twFaARsB/wHFAXoBRwH/AfkB8gHtAf8B8QHeAdIB/wG9AWgBLwH/AboBYAEjAf8B6AHJAbQF/wHMAYgB
WwH/AbgBWgEbAf8BuAFaARsB/wG4AVoBGwH/AbgBWgEbAf8BogFnAScB/gG6AYUBOQH7Ae8BowFCAf8B
7wGjAUIB/wHvAaMBQgH/Ae8BpAFCAf8B7gGkAUIB/wHOAYMBMgH/AZEBRQETAf8BjAFAAREB/wGOAUAB
EQH/AcUBeQEtAf8B7QGjAUIB/wHuAaQBQgH/Ae4BpAFCAf8B7gGkAUIB/wHtAaQBQgH/Ae0BpAFCAf8B
lwF6AUgB9gMzAVH/AHkAA1EBogE9ATwBOwH/AeYBzAHBAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHqAdQBygH/Ab0BsQGqAf8CNwE2Af8BwwGsAaIB
/wHQAbcBrAH/AdABtwGsAf8BQwFBAUAB/wFvAaMBtgH/AY8B3QH5Af8BjwHdAfkB/wFuAaABsQH/AT4B
SAFLAf8BbQGeAa8B/wGPAd0B+QH/AY8B3QH5Af8BcQGmAbgB/wFCAUABPgH/AdABtwGsAf8BzAG0AakB
/wHEAa0BowH/Ac8BuwGxAf8B6gHaAdAB/wHtAd0B0wH/Ae0B3QHTAf8B6wHVAcoB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wE9ATwBOwH/A1EBoRAAAzMBUQGLAVsB
QQH3AbYBWgEcAf8BtgFaARwB/wG2AVoBHAH/AbYBWgEcAf8BtgFaARsB/wG4AV0BHwH/AfEB3wHSAf8B
+gHzAe8B/wHHAX8BTgH/Ab4BaQEwAf8B9gHrAeQB/wH7AfUB8gH/AboBXwEhAf8BuAFaARsB/wG4AVoB
GwH/AbgBWgEbAf8BuAFaARsB/wG+AVwBOgH9AdUBiAFMAf4B7wGjAUIB/wHvAaMBQgH/Ae8BowFCAf8B
7wGjAUIB/wHpAZ0BPwH/AZcBSwEWAf8BjAFAAREB/wGsAWABIAH/AZEBQwESAf8BlQFGARQB/wHWAYsB
NgH/Ae4BpAFCAf8B7gGkAUIB/wHuAaQBQgH/Ae4BpAFCAf8B7QGkAUIB/wGXAXoBSAH2AzMBUf8AeQAD
TQGSAToCOQH/AcIBrQGkAf8B3QHFAboB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wHnAc0BwgH/AcYBtAGrAf8BRAFCAUEB/wGeAY0BhQH/AdABtwGsAf8B0AG3AawB
/wFrAWIBXgH/AUkBXAFkAf8BiwHVAe8B/wGPAd0B+QH/AY8B3QH5Af8BjwHdAfkB/wGPAd0B+QH/AY8B
3QH5Af8BiwHVAfAB/wFKAV4BZQH/AWkBYQFdAf8BzwG2AasB/wG2AaEBmAH/AcIBqwGhAf8B4AHMAcEB
/wHtAd0B0wH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B0wH/AeoB1QHKAf8B5wHOAcMB/wHnAc0BwgH/AecB
zQHCAf8B2wHDAbkB/wHBAawBpAH/AToCOQH/A04BlRAAAzMBUQGLAVsBQQH3AbYBWgEcAf8BtgFaARwB
/wG2AVoBHAH/AbYBWgEcAf8BtgFaARwB/wG2AVoBGwH/AdYBoAF8Bf8B1wGjAYAB/wHNAYwBXwP/Af4B
/wHdAbABkwH/AbcBWgEbAf8BuAFaARsB/wG4AVoBGwH/AbgBWgEbAf8BuAFaARsB/wG4AXoBKwH8Ae4B
ogFBAf8B7wGjAUIB/wHvAaMBQgH/Ae8BowFCAf8B7wGjAUIB/wHRAYUBMwH/AZsBUAEZAf8BuQFtASgB
/wHrAaABQQH/AbgBbAEmAf8BjgE/ARAB/wGoAVsBHgH/AewBoQFBAf8B7gGkAUIB/wHuAaQBQgH/Ae4B
pAFCAf8B7gGkAUIB/wGXAXoBSAH2AzMBUf8AeQADIwEzA1gB7gFFAUMBQQH/AVYBUQFPAf8BeAFuAWoB
/wGpAZgBkQH/AdgBwAG2Af8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHXAb8BtQH/AVgB
UgFQAf8BYgFbAVcB/wHPAbcBrAH/AdABtwGsAf8BpAGSAYoB/wE+AjwB/wFZAXgBhAH/AYoB1QHvAf8B
jwHdAfkB/wGPAd0B+QH/AY8B3QH5Af8BiwHVAfAB/wFZAXoBhgH/AT0CPAH/AaMBkQGKAf8BzQG0AakB
/wFWAVEBTgH/AU4BSgFIAf8BqAGdAZYB/wHtAd0B0wH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B0wH/Ae0B
3AHSAf8B1wHDAboB/wGlAZUBjgH/AXUBawFnAf8BVQFQAU4B/wFEAUIBQQH/AlgBVwHxAyUBNhAAAzMB
UQGLAVsBQQH3AbUBWgEcAf8BtgFaARwB/wG2AVoBHAH/AbYBWgEcAf8BtgFaARwB/wG2AVoBHAH/AbwB
ZQErAf8B/AH4AfYB/wHuAdgByAH/AekBzQG6Af8B/QH6AfgB/wG/AW0BNQH/AbcBWgEbAf8BtwFaARsB
/wG3AVoBGwH/AbgBWgEbAf8BugFcARwB/wHAAX4BKwH8AfABowFCAf8B7wGjAUIB/wHvAaMBQgH/Ae8B
owFCAf8B7wGjAUIB/wHvAaMBQgH/AeMBlwE8Af8B6wGfAUAB/wHvAaMBQgH/AekBngE/Af8BpQFXARwB
/wGPAUABEQH/AcQBeAEsAf8B7gGkAUIB/wHuAaQBQgH/Ae4BpAFCAf8B7gGkAUIB/wGYAXoBSAH2AzMB
Uf8AfQADDAEQAzwBZgNWAbADXAHZA1oB6gNMAfoBcgFpAWUB/wHkAcoBvwH/AecBzQHCAf8B5wHNAcIB
/wHnAc0BwgH/AYUBeQF1Af8BPgE8ATsB/wGvAZsBkgH/AdABtwGsAf8BzwG2AasB/wGFAXgBcgH/AT4B
PQE8Af8BSQFcAWMB/wFvAaIBtQH/AXsBuQHPAf8BbwGjAbUB/wFKAV0BZAH/AT4CPAH/AYQBdwFxAf8B
zAG0AakB/wHOAbYBqwH/Aa0BmgGRAf8BZwFgAV0B/wGgAZYBkQH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B
0wH/AeoB2gHQAf8BcwFtAWoB/wE3AjYB+wNeAesDXwHaA1UBtAM9AWkDDgESFAADMwFRAYsBWgFBAfcB
tQFaARwB/wG1AVoBHAH/AbYBWgEcAf8BtgFaARwB/wG2AVoBHAH/AbYBWgEcAf8BtgFaARwB/wHoAckB
tQH/Af4C/QH/Af4B/QH8Af8B7gHXAcgB/wG4AV0BHwH/AbcBWgEbAf8BtwFaARsB/wG3AVoBGwH/AbcB
WgEbAf8BpgFuASsB/gHKAZ8BQAH9AfABowFCAf8B8AGjAUIB/wHvAaMBQgH/AboBbgEpAf8BpgFbAR8B
/wGnAVsBHwH/AacBWwEfAf8BpwFbAR8B/wGlAVgBHQH/AacBWQEdAf8BoAFSARkB/wGOAT8BEAH/AZAB
QQERAf8BqAFbAR0B/wHPAYQBMgH/Ae4BpAFCAf8B7gGkAUIB/wGYAXoBSAH2AzMBUf8AiQADDwEUAyUB
NwM9AWkDWgHpAa0BnAGUAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B0wG8AbIB/wFIAUUBRAH/AWgB
YAFcAf8BzgG1AaoB/wHQAbcBrAH/Ac8BtgGrAf8BpQGTAYsB/wFrAWIBXgH/AUQBQgFAAf8COQE4Af8B
RAFBAUAB/wFrAWIBXgH/AaQBkgGKAf8BzQG0AaoB/wGNAX8BeAH/AYABcwFuAf8BzgG3Aa0B/wHoAdYB
zAH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B0wH/Ae0B3QHTAf8BtAGpAaIB/wNeAesDPwFtAycBOgMRARYg
AAMzAVEBiwFaAUEB9wG1AVkBHAH/AbUBWQEcAf8BtQFaARwB/wG1AVoBHAH/AbYBWgEcAf8BtgFaARwB
/wG2AVoBHAH/AdABlAFsAf8B/gH9AfwC/wL+Af8B2wGtAY4B/wG3AVsBHAH/AbcBWgEbAf8BtwFaARsB
/wG3AVoBGwH/AbcBWgEbAf8BpwF9AUIB+gHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AaYB
WwEfAf8BiwFAAREB/wGLAUABEQH/AYsBQAERAf8BjAFAAREB/wGNAUABEQH/AY8BPwEQAf8BjQE/ARAB
/wGOAT8BEAH/AY4BPwEQAf8BjwE/ARAB/wHEAXgBLAH/Ae4BpAFCAf8B7gGkAUIB/wGYAXoBSAH2AzMB
Uf8AkQADCAEKA1UBrwFJAUYBRAH/AeUBywHAAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8BuwGnAZ8B
/wE5AjgB/wF0AWoBZQH/Ac4BtQGqAf8B0AG3AawB/wHQAbcBrAH/AdABtwGsAf8B0AG3AawB/wHQAbcB
rAH/AdABtwGsAf8B0AG3AawB/wHQAbcBrAH/Ac8BtgGrAf8BhQF4AXMB/wM1Af8BkgGGAYEB/wHsAdsB
0QH/Ae0B3QHTAf8B7QHdAdMB/wHtAd0B0wH/AesB2wHRAf8BSwFJAUgB/wNWAbMDCQEMKAADMwFRAYsB
WgFBAfcBtQFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFaARwB/wG1AVoBHAH/AbYBWgEcAf8BtgFaARwB
/wHCAXUBQgH/AfUB6AHgAf8B+gH0Ae8B/wHKAYcBWgH/AbYBWgEcAf8BtgFaARsB/wG3AVoBGwH/AbcB
WgEbAf8BoQFnASgB/gHBAZIBSwH7AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB
/wHwAaMBQgH/Ae8BowFCAf8B7wGjAUIB/wHvAaMBQgH/AY0BQAERAf8BpgFYARwB/wHvAaMBQgH/Ae8B
owFCAf8B7wGjAUIB/wHvAaMBQgH/Ae8BpAFCAf8B7gGkAUIB/wHuAaQBQgH/AZgBegFIAfYDMwFR/wCR
AAMDAQQDTgGUAzYB/wHWAb4BtAH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AeQBygG/Af8BmwGMAYUB
/wE6AjkB/wFoAWABXAH/Aa8BmwGSAf8BzwG2AawB/wHQAbcBrAH/AdABtwGsAf8B0AG3AawB/wHQAbcB
rAH/AdABtwGsAf8B0AG3AawB/wHQAbcBrAH/AdABuQGuAf8BmQGMAYYB/wGyAaABmAH/AegB0AHFAf8B
7AHbAdEB/wHxAeUB4QH/Ae0B3QHUAf8B3QHOAcUB/wM3Af8DTgGXAwMBBCgAAzMBUQGLAVoBQQH3AbUB
WQEcAf8BtQFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFaARwB/wG1AVoBHAH/AbUBWgEcAf8BtwFdASEB
/wHBAXMBPgH/AcMBdgFCAf8BuAFfASMB/wG2AVoBHAH/AbYBWgEcAf8BtgFaARwB/wG3AVoBGwH/AZ0B
XwEoAfsB8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB
/wHwAaMBQgH/AfABowFCAf8B7wGjAUIB/wGbAU8BGQH/AbEBYwEiAf8B7wGjAUIB/wHvAaMBQgH/Ae8B
owFCAf8B7wGjAUIB/wHvAaMBQgH/Ae8BowFCAf8B7gGkAUIB/wGYAXoBSAH2AzMBUf8AkQADGAEgA14B
4gF/AXQBbwH/AeYBzAHBAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHkAcoBvwH/Ab4B
qQGhAf8BSgFHAUUB/wE+ATwBOwH/AWIBWgFXAf8BpgGUAYwB/wHQAbcBrAH/AdABtwGsAf8BxQGuAaQB
/wGeAY0BhgH/AZMBhAF9Af8B2QHDAbgB/wHoAdYBzAH/AewB3AHRAf8B6QHRAcYB/wHnAc0BwgH/AewB
2AHSAf8B9wH0AfkB/wHyAegB5AH/AewB3AHSAf8BhgF+AXoB/wNeAeMDGAEhKAADMwFRAYsBWgFBAfcB
tAFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFZARwB/wG1AVoB
HAH/AbYBWgEcAf8BtgFaARwB/wG2AVoBHAH/AbYBWgEcAf8BtgFaARwB/wG2AVoBHAH/AaABZwEoAf4B
vwF+ASsB/AHxAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMB
QgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AegBmwE+Af8B6QGdAT8B/wHvAaMBQgH/Ae8BowFCAf8B
7wGjAUIB/wHvAaMBQgH/Ae8BowFCAf8B7wGjAUIB/wHvAaMBQgH/AZoBegFIAfYDMwFR/wCNAAMDAQQD
UQGiAVEBTAFKAf8B4QHIAb4B/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B
5wHNAcIB/wHnAc0BwgH/AdUBvgG0Af8BiwF+AXgB/wFaAVUBUgH/AV8BWgFXAf8B2wHGAbsB/wHRAbwB
sgH/AU8BTAFKAf8BRgFDAUIB/wFiAVsBWAH/AewB2wHRAf8B7QHdAdMB/wHtAd0B0wH/AewB2wHQAf8B
6QHRAcYB/wHnAc0BwgH/AewB2gHUAf8B7AHbAdEB/wHtAd0B0wH/AekB2QHQAf8BVAFSAVAB/wNRAaQD
BAEFJAADMwFRAYsBWgFBAfcBtAFZARwB/wG0AVkBHAH/AbUBWQEcAf8BtQFZARwB/wG1AVkBHAH/AbUB
WQEcAf8BtQFZARwB/wG1AVkBHAH/AbUBWgEcAf8BtQFaARwB/wG2AVoBHAH/AbYBWgEcAf8BtgFaARwB
/wG2AVoBHAH/AaYBbwEtAf4BxAGXAUAB/QHxAaMBQgH/AfEBowFCAf8B8AGjAUIB/wHwAaMBQgH/AfAB
owFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB
/wHvAaMBQgH/Ae8BowFCAf8B7wGjAUIB/wHvAaMBQgH/Ae8BowFCAf8B7wGjAUIB/wHvAaMBQgH/AZoB
egFIAfYDMwFR/wCNAAM1AVYBOgI5AfsBoQGRAYsB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0B
wgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AdkBwgG3Af8B
1gHCAbkB/wHtAd0B0wH/AesB3AHSAf8ByQG9AbQB/wHJAbYBrQH/AdoBwgG4Af8B6AHRAcYB/wHsAdsB
0AH/Ae0B3QHTAf8B7QHdAdMB/wHtAdsB0QH/AekB0gHHAf8B5wHNAcIB/wHoAdABxQH/AewB2gHQAf8B
7QHdAdMB/wGpAZ4BmAH/ATsCOgH7AzYBWCQAAzMBUQGLAVoBQQH3AbQBWQEdAf8BtAFZAR0B/wG0AVkB
HAH/AbQBWQEcAf8BtAFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFZARwB/wG1AVkBHAH/AbUBWQEcAf8B
tQFaARwB/wG1AVoBHAH/AbYBWgEcAf8BtgFaARwB/wGvAXABKwH8AfABogFBAf8B8QGjAUIB/wHxAaMB
QgH/AfEBowFCAf8B8QGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B
8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/Ae8BowFCAf8B7wGjAUIB/wHvAaMB
QgH/Ae8BowFCAf8B7wGjAUIB/wGaAXoBSAH2AzMBUf8AiQADEQEWA10BzgFaAVUBUgH/Ad0BxQG6Af8B
5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0B
wgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B6gHUAcoB/wHtAd4B1AH/Ae0B3QHTAf8B
7AHbAdEB/wHoAdABxQH/AecBzQHCAf8B6QHRAcYB/wHtAdwB0gH/Ae0B3QHTAf8B7QHdAdMB/wHsAdsB
0QH/AekB0QHGAf8B5wHNAcIB/wHoAdEBxgH/Ae0B3AHSAf8B5QHWAcwB/wFgAVwBWQH/A1sB0AMSARcg
AAMzAVEBiwFaAUEB9wG0AVkBHQH/AbQBWQEdAf8BtAFZAR0B/wG0AVkBHAH/AbQBWQEcAf8BtAFZARwB
/wG1AVkBHAH/AbUBWQEcAf8BtQFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFaARwB/wG1AVoBHAH/AbYB
WgEcAf8BuQF/ATcB+wHxAaMBQgH/AfEBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B8QGjAUIB
/wHxAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfAB
owFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B7wGjAUIB/wHvAaMBQgH/Ae8BowFCAf8BmgF6AUgB
9gMzAVH/AIkAAygBPANcAe0BrgGcAZUB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AecB
zQHCAf8B5wHNAcIB/wHmAcwBwQH/AdUBvQGzAf8B5AHKAcAB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB
/wHnAc0BwgH/AecBzgHDAf8B8QHmAeQB/wHwAeQB3gH/Ae0B3QHTAf8B7AHbAdAB/wHpAdEBxgH/AecB
zQHCAf8B5wHPAcQB/wHbAcsBwgH/AewB3AHSAf8B7QHdAdMB/wHsAdsB0AH/AekB0QHGAf8B5wHNAcIB
/wHoAdABxQH/AewB2gHQAf8BugGuAaYB/wNXAe8DKQE+IAADMwFRAYsBWgFBAfcBtAFZAR0B/wG0AVkB
HQH/AbQBWQEdAf8BtAFZAR0B/wG0AVkBHQH/AbQBWQEcAf8BtAFZARwB/wG0AVkBHAH/AbUBWQEcAf8B
tQFZARwB/wG1AVkBHAH/AbUBWQEcAf8BtQFZARwB/wGhAWIBKwH8AdgBiQFNAf4B8QGjAUIB/wHxAaMB
QgH/AfEBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B
8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMB
QgH/AfABowFCAf8B7wGjAUIB/wHvAaMBQgH/AZoBegFIAfYDMwFR/wCJAAMgAS4DXgHiAWkBYgFeAf8B
4QHIAb0B/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wHnAc0BwgH/AeEByAG9Af8BfgFzAW4B/wM2Af8B
RwFEAUMB/wGrAZoBkwH/AeMBygG/Af8B5wHNAcIB/wHnAc0BwgH/Ae4B3gHZAf8B9wH2AfwB/wH3AfYB
+wH/AfAB4wHdAf8B7QHdAdMB/wHqAdkBzwH/AbEBoQGaAf8BSwFIAUYB/wE3AjYB/wF+AXcBcwH/AeYB
1wHNAf8B7QHdAdMB/wHtAdwB0gH/AekB0QHGAf8B5wHNAcIB/wHjAcsBwQH/AW0BZwFjAf8DWwHkAyEB
MCAAAzMBUQF/AWABQAH2AbMBWQEdAf8BswFZAR0B/wG0AVkBHQH/AbQBWQEdAf8BtAFZAR0B/wG0AVkB
HQH/AbQBWQEdAf8BtAFZARwB/wG0AVkBHAH/AbUBWQEcAf8BtQFZARwB/wG1AVkBHAH/AbUBWQEcAf8B
qgFnAS8B+wHyAaMBQgH/AfIBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B8QGjAUIB/wHxAaMB
QgH/AfEBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B
8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B7wGjAUIB/wGaAXoB
SAH2AzMBUf8AiQADAgEDAzsBZANZAe8BewFxAW0B/wHhAcgBvQH/AecBzQHCAf8B3gHFAbsB/wGiAZIB
iwH/AVEBTAFLAf8DYAHgA00BkwNWAbADWgHpAW8BZgFiAf8B5wHNAcIB/wHqAdYBzwH/AfMB7AHuAf8B
+AH3Af4B/wH3AfYB/QH/AfIB6QHoAf8B7gHeAdYB/wF8AXUBcQH/A1wB6gNWAbADTQGSA10B3wFQAU0B
TAH/AaMBmQGTAf8B4QHSAckB/wHsAdsB0AH/AeMBzAHBAf8BfQFyAW0B/wNYAfEDPQFoAwMBBCAAAx0B
KAFlAl4B3QGzAVkBHQH/AbMBWQEdAf8BswFZAR0B/wG0AVkBHQH/AbQBWQEdAf8BtAFZAR0B/wG0AVkB
HQH/AbQBWQEdAf8BtAFZARwB/wG0AVkBHAH/AbQBWQEcAf8BtQFZARwB/wGiAWoBKgH+AcQBlQFAAf0B
8gGjAUIB/wHyAaMBQgH/AfIBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B8QGjAUIB/wHxAaMB
QgH/AfEBowFCAf8B8QGjAUIB/wHxAaMBQgH/AfEBowFCAf8B8QGjAUIB/wHwAaMBQgH/AfABowFCAf8B
8AGjAUIB/wHwAaMBQgH/AfABowFCAf8B8AGjAUIB/wHwAaMBQgH/AfABowFCAf8CZQFeAd0DHQEo/wCN
AAQCAzIBTwNZAe8BaQFiAV4B/wGxAZ4BlgH/AVsBVQFTAf8DTQH6A1EBngMYASADAwEEAwkBCwM/AWwD
NgH7AdQBvQGzAf8B5wHNAcIB/wHoAdABxwH/AfMB6wHtAf8B7wHhAd8B/wHoAc8BxQH/AeABzAHCAf8D
LQH8Az8BbgMJAQsDAwEEAxYBHgNQAZoDQQH5AVkBVgFUAf8BsAGlAZ4B/wFsAWcBYwH/A1QB8AMzAVID
AgEDJAAEAQMaASQDPQFoAkEBQAFxAkEBQAFxAkEBQAFxAkEBQAFxAkEBQAFxAkEBQAFxAkEBQAFxAkEB
QAFxAkEBQAFxAkEBQAFxAkEBQAFxAkEBQAFwAkEBQAFxA0EBcQNBAXEDQQFxA0EBcQNBAXEDQQFxA0EB
cQNBAXEDQQFxA0EBcQNBAXEDQQFxA0EBcQNBAXEDQQFxA0EBcQNBAXEDQQFxA0EBcQNBAXEDPQFoAxoB
JAQB/wCRAAQCAzsBZANeAeIDXAHtA1sBzQM0AVQDAwEEDAADJwE6A14B6wGlAZQBjgH/AecBzQHCAf8B
5wHNAcIB/wHqAdYBzgH/AegBzgHEAf8B5wHNAcIB/wGxAZ8BlwH/A10B7AMpAT0MAAMCAQMDMwFRA1wB
ywNcAe0DXgHjAz0BZwMCAQP/AP8AWgADAgEDAyABLQMoATsDEAEVFAADEgEXA18B2gF0AWsBZwH/AecB
zQHCAf8B5wHNAcIB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB/wGAAXUBcAH/A2AB2wMTARkUAAMPARQD
KAE7AyABLgMCAQP/AP8AhgADVgGzAVUBUAFOAf8B3AHDAbkB/wHnAc0BwgH/AecBzQHCAf8B5wHNAcIB
/wHhAcgBvQH/AVoBVAFSAf8DWAG6/wD/AK4AAz0BaQFEAUIBQQH/AcABqwGjAf8B5QHMAcEB/wHlAcwB
wQH/AeUBzAHBAf8BxQGwAacB/wFIAUUBQwH/A0ABcf8A/wCuAAMNAREDUwHwAToCOQH/AT0COwH/AT0C
OwH/AT0COwH/AToCOQH/A1EB8wMRARb/AP8AsgADJAE0A00BkgNRAaIDUQGiA1EBogNNAZMDJQE3/wD/
AP8A/wD/AD0AAUIBTQE+BwABPgMAASgDAAG0AwABLQMAAQEBAAEBBQABOAEEFgAD/wEAB/8BxwP/AcAM
AAL/AeABPwP/AYcD/wHADAAC/wHAAR8D/wGDA/8BwAwAAv8BwAEfA/8BgAP/AcAMAAL/AcABDwP/AYAD
/wHADAAB/wEPAYABDwGHAv8BgAE/Av8BwAwAAf4BAwGAAQ4BAwL/AYABPwL/AcAMAAH8AwABAQL/AYAB
HwL/AcAMAAH4BAAC/wGAAQ8C/wHADAAB+AQAAf8BgAMAAQMBwAwAAfgEAAH/BAABAQHADAAB+AQAAf8E
AAEBAcAMAAH8AwABAQH/BAABAQHADAAB/AMAAQEB/wQAAQEBwAwAAf4DAAEDAf8EAAEBAcAMAAH+AwAB
AwH/BAABAQHADAAB/gMAAQMB/wQAAQEBwAwAAfgEAAH/BAABAQHADAABwAQAAR8EAAEBAcAMAAGABAAB
DwQAAQEBwAwAAYAEAAEPBAABAQHADAABgAQAAQ8EAAEBAcAMAAGABAABDwQAAQEBwAwAAYAEAAEPBAAB
AQHADAABgAQAAQ8EAAEBAcAMAAGABAABDwQAAQEBwAwAAcAEAAEfBAABAQHADAAB+AQAAf8EAAEBAcAM
AAH+AwABAwH/BAABAQHADAAB/gMAAQMB/wQAAQEBwAwAAf4DAAEDAf8EAAEBAcAMAAH8AwABAQH/BAAB
AQHADAAB/AMAAQEB/wQAAQEBwAwAAfgEAAH/BAABAQHADAAB+AQAAf8EAAEBAcAMAAH4BAAB/wQAAQEB
wAwAAfgEAAH/BAABAQHADAAB/AMAAQEB/wQAAQEBwAwAAf4BAwGAAQ4BAwb/AcAMAAH/AQ8BgAEPAYcG
/wHADAAC/wHAAR8H/wHADAAC/wHAAR8H/wHADAAC/wHAAR8H/wHADAAC/wHgAT8H/wHADAAL/wHADAAL
</value>
</data>
</root>

View File

@ -1,48 +0,0 @@
namespace UI_WinForms.Components
{
sealed partial class NXProgressBar
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// NXProgressBar
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.LightSkyBlue;
this.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "NXProgressBar";
this.Size = new System.Drawing.Size(702, 41);
this.ResumeLayout(false);
}
#endregion
}
}

View File

@ -1,73 +0,0 @@
using System.ComponentModel;
using SolidBrush = System.Drawing.SolidBrush;
namespace UI_WinForms.Components;
public sealed partial class NXProgressBar : UserControl
{
private static readonly SolidBrush BACKGROUND_NOT_FILLED = new(SystemColors.Control);
private readonly SolidBrush backgroundFilled;
private readonly SolidBrush textBrush;
public NXProgressBar()
{
this.InitializeComponent();
this.backgroundFilled = new SolidBrush(this.BackColor);
this.textBrush = new SolidBrush(this.ForeColor);
}
[Category("Settings"), Description("Text to show inside the progress bar.")]
public string InformationText { get; set; } = string.Empty;
[Category("Settings"), Description("The current percentage [0,100] of the progress bar.")]
public int PercentInt
{
get => (int) (this.PercentFloat * 100);
set => this.PercentFloat = value / 100f;
}
[Category("Settings"), Description("The current percentage [0,1] of the progress bar.")]
public float PercentFloat { get; set; } = 0;
[Category("Settings"), Description("When true, appends the percentage to the text.")]
public bool AppendPercentageToText { get; set; } = true;
protected override void OnPaintBackground(PaintEventArgs e)
{
// Do not paint the background.
}
// Draw the progress bar by filling the background of the label with color:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var width = (int) MathF.Ceiling((this.Width - this.Margin.Horizontal) * this.PercentFloat);
var height = this.Height - this.Margin.Vertical;
// Erase the background:
e.Graphics.FillRectangle(BACKGROUND_NOT_FILLED, this.Margin.Left, this.Margin.Top, this.Width - this.Margin.Horizontal, height);
// Draw the filled background:
e.Graphics.FillRectangle(this.backgroundFilled, this.Margin.Left, this.Margin.Top, width, height);
// Calculate the text x position by using the margin:
var textX = this.Margin.Left + this.Padding.Left;
// Calculate the text y position by considering the margin:
var textY = (int) MathF.Ceiling((this.Height - this.Font.Height) / 2f) + this.Margin.Top + this.Padding.Top;
// Draw the text horizontally at the beginning, and vertically centered:
e.Graphics.DrawString(this.GetTextForRendering(), this.Font, this.textBrush, textX, textY);
}
private string GetTextForRendering()
{
var text = this.InformationText;
if (this.AppendPercentageToText)
text += $" ({this.PercentInt}%)";
return text;
}
}

View File

@ -1,60 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,182 +0,0 @@
namespace UI_WinForms.Components
{
partial class SectionTree
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutBottom = new System.Windows.Forms.FlowLayoutPanel();
this.buttonAdd = new System.Windows.Forms.Button();
this.buttonRemove = new System.Windows.Forms.Button();
this.buttonRename = new System.Windows.Forms.Button();
this.buttonGenerate = new System.Windows.Forms.Button();
this.treeView = new System.Windows.Forms.TreeView();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.tableLayout.SuspendLayout();
this.flowLayoutBottom.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 1;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayout.Controls.Add(this.flowLayoutBottom, 0, 1);
this.tableLayout.Controls.Add(this.treeView, 0, 0);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 2;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.Size = new System.Drawing.Size(296, 511);
this.tableLayout.TabIndex = 0;
//
// flowLayoutBottom
//
this.flowLayoutBottom.Controls.Add(this.buttonAdd);
this.flowLayoutBottom.Controls.Add(this.buttonRemove);
this.flowLayoutBottom.Controls.Add(this.buttonRename);
this.flowLayoutBottom.Controls.Add(this.buttonGenerate);
this.flowLayoutBottom.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutBottom.Location = new System.Drawing.Point(0, 445);
this.flowLayoutBottom.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutBottom.Name = "flowLayoutBottom";
this.flowLayoutBottom.Size = new System.Drawing.Size(296, 66);
this.flowLayoutBottom.TabIndex = 0;
//
// buttonAdd
//
this.buttonAdd.AutoSize = true;
this.buttonAdd.FlatAppearance.BorderSize = 0;
this.buttonAdd.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonAdd.Image = global::UI_WinForms.Resources.Icons.icons8_add_folder_512;
this.buttonAdd.Location = new System.Drawing.Point(3, 3);
this.buttonAdd.Name = "buttonAdd";
this.buttonAdd.Size = new System.Drawing.Size(60, 60);
this.buttonAdd.TabIndex = 0;
this.buttonAdd.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.toolTip.SetToolTip(this.buttonAdd, "Add section");
this.buttonAdd.UseVisualStyleBackColor = true;
this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
//
// buttonRemove
//
this.buttonRemove.AutoSize = true;
this.buttonRemove.Enabled = false;
this.buttonRemove.FlatAppearance.BorderSize = 0;
this.buttonRemove.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonRemove.Image = global::UI_WinForms.Resources.Icons.icons8_delete_folder_512;
this.buttonRemove.Location = new System.Drawing.Point(69, 3);
this.buttonRemove.Name = "buttonRemove";
this.buttonRemove.Size = new System.Drawing.Size(60, 60);
this.buttonRemove.TabIndex = 1;
this.buttonRemove.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.toolTip.SetToolTip(this.buttonRemove, "Removes the selected section");
this.buttonRemove.UseVisualStyleBackColor = true;
this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
//
// buttonRename
//
this.buttonRename.AutoSize = true;
this.buttonRename.Enabled = false;
this.buttonRename.FlatAppearance.BorderSize = 0;
this.buttonRename.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonRename.Image = global::UI_WinForms.Resources.Icons.icons8_rename_512;
this.buttonRename.Location = new System.Drawing.Point(135, 3);
this.buttonRename.Name = "buttonRename";
this.buttonRename.Size = new System.Drawing.Size(60, 60);
this.buttonRename.TabIndex = 2;
this.buttonRename.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.toolTip.SetToolTip(this.buttonRename, "Rename the selected section");
this.buttonRename.UseVisualStyleBackColor = true;
this.buttonRename.Click += new System.EventHandler(this.buttonRename_Click);
//
// buttonGenerate
//
this.buttonGenerate.AutoSize = true;
this.buttonGenerate.Enabled = false;
this.buttonGenerate.FlatAppearance.BorderSize = 0;
this.buttonGenerate.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonGenerate.Image = global::UI_WinForms.Resources.Icons.icons8_code_512__2_;
this.buttonGenerate.Location = new System.Drawing.Point(201, 3);
this.buttonGenerate.Name = "buttonGenerate";
this.buttonGenerate.Size = new System.Drawing.Size(60, 60);
this.buttonGenerate.TabIndex = 3;
this.buttonGenerate.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.toolTip.SetToolTip(this.buttonGenerate, "Triggers all enabled generators");
this.buttonGenerate.UseVisualStyleBackColor = true;
this.buttonGenerate.Click += new System.EventHandler(this.buttonGenerate_Click);
//
// treeView
//
this.treeView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.treeView.Dock = System.Windows.Forms.DockStyle.Fill;
this.treeView.HideSelection = false;
this.treeView.ItemHeight = 50;
this.treeView.Location = new System.Drawing.Point(3, 3);
this.treeView.Name = "treeView";
this.treeView.Size = new System.Drawing.Size(290, 439);
this.treeView.TabIndex = 1;
this.treeView.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.treeView_NodeMouseClick);
//
// toolTip
//
this.toolTip.AutoPopDelay = 30000;
this.toolTip.InitialDelay = 500;
this.toolTip.ReshowDelay = 100;
this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.toolTip.ToolTipTitle = "Help";
//
// SectionTree
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "SectionTree";
this.Size = new System.Drawing.Size(296, 511);
this.tableLayout.ResumeLayout(false);
this.flowLayoutBottom.ResumeLayout(false);
this.flowLayoutBottom.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private FlowLayoutPanel flowLayoutBottom;
private Button buttonAdd;
private Button buttonRemove;
private TreeView treeView;
private ToolTip toolTip;
private Button buttonRename;
private Button buttonGenerate;
}
}

View File

@ -1,339 +0,0 @@
using DataModel.Database;
using Processor;
using Processor.Generators;
using UI_WinForms.Dialogs;
using UI_WinForms.Resources;
using Timer = System.Timers.Timer;
namespace UI_WinForms.Components;
public partial class SectionTree : UserControl
{
private static readonly Dictionary<TreeNode, EventHandler<DataModel.Database.Translation?>?> NODE_PROGRESS_HANDLERS = new();
private readonly Timer generatorTimer = null!;
public SectionTree()
{
this.InitializeComponent();
// Check if we are in the designer:
if(Program.SERVICE_PROVIDER is null)
return;
// Create an image list from a resource:
var imgList = new ImageList();
imgList.ImageSize = new Size(45, 45);
imgList.ColorDepth = ColorDepth.Depth32Bit;
imgList.Images.Add(Icons.icons8_documents_folder_512);
// Set the image list to the tree view:
this.treeView.ImageList = imgList;
// The generator timer:
this.generatorTimer = new Timer
{
Enabled = false, // disable timer for now,
Interval = 6_000, // 6 second interval,
AutoReset = false, // runs only once
};
this.generatorTimer.Elapsed += async (sender, args) => await this.PerformGenerators();
// Subscribe to the load event:
this.Load += this.LoadNodes;
this.Load += (sender, args) => this.SetupGeneratorButton();
// Subscribe to all event for triggering the generators:
AppEvents.WhenTranslationChanged += (sender, translation) => this.GeneratorEvent();
AppEvents.WhenSettingsChanged += (sender, args) => this.GeneratorEvent();
}
private async void SetupGeneratorButton()
{
this.buttonGenerate.Enabled = false;
// Depend the generator button's visibility on the generator settings:
this.buttonGenerate.Enabled = await AppSettings.GetGeneratorDotnetEnabled() || await AppSettings.GetGeneratorGodotEnabled();
// Subscribe to the changed settings event:
AppEvents.WhenSettingsChanged += async (sender, args) =>
{
this.buttonGenerate.Enabled = await AppSettings.GetGeneratorDotnetEnabled() || await AppSettings.GetGeneratorGodotEnabled();
};
}
private async void LoadNodes(object? sender, EventArgs e)
{
if(this.DesignMode)
return;
// A dictionary to cache all known tree nodes:
var treeNodes = new Dictionary<string, TreeNode>();
// Get the max. depth of the tree:
var maxDepth = await SectionProcessor.GetDepth();
// Store nodes, where we cannot find the parents:
var missingParents = new List<TreeNode>();
// Populate the tree view out of the database, layer by layer:
for (var i = 0; i <= maxDepth; i++)
{
foreach (var section in await SectionProcessor.LoadLayer(i))
{
var translationProgress = await TranslationProcessor.CalculateTranslationProgress(section);
// Create the tree node:
var node = new TreeNode
{
Name = section.DataKey, // [sic] name is the key
Text = $"{section.Name} [{translationProgress.Result}%]",
StateImageIndex = 1,
};
// Cache the node:
treeNodes.Add(section.DataKey, node);
// Wire each node to the translation change event to update the translation progress:
NODE_PROGRESS_HANDLERS.Add(node, async (_, translation) => await this.UpdateTranslationProgress(node, section, translation));
AppEvents.WhenTranslationChanged += NODE_PROGRESS_HANDLERS[node];
// Is this a root node?
if (section.Depth is 0)
// Set the root node:
this.treeView.Nodes.Add(node);
// Otherwise, attach this section to its parent node:
else
{
// Get the parent from our cache within O(1):
treeNodes.TryGetValue(section.Parent?.DataKey ?? string.Empty, out var parent);
// If the parent node is not found, skip this section:
if (parent is null)
{
missingParents.Add(node);
continue;
}
// Add the node to the parent:
parent.Nodes.Add(node);
}
}
}
// If we found any missing parents, show a dialog:
if (missingParents.Any())
{
MessageBox.Show($"In {missingParents.Count} case(s) we could not found the matching parent. We added these nodes to a special root node, though.", "Parent not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
// Create a root node for all missing parents:
var rootMissedParents = new TreeNode
{
Name = "MISSING_PARENTS",
Text = "Missing Parents",
StateImageIndex = 1,
};
// Add the root node to the tree:
this.treeView.Nodes.Add(rootMissedParents);
// Add all missing parents to the root node:
foreach (var node in missingParents)
rootMissedParents.Nodes.Add(node);
}
// Expand the tree:
this.treeView.ExpandAll();
}
private async Task UpdateTranslationProgress(TreeNode node, Section section, DataModel.Database.Translation? translation)
{
if (translation is null || translation.TextElement.Section.DataKey == section.DataKey)
{
var currentTranslationProgress = await TranslationProcessor.CalculateTranslationProgress(section);
if(this.treeView.InvokeRequired)
this.treeView.Invoke(() => node.Text = $"{section.Name} [{currentTranslationProgress.Result}%]");
else
node.Text = $"{section.Name} [{currentTranslationProgress.Result}%]";
}
}
private async void buttonAdd_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
var result = InputDialog.Show(new InputDialog.Options(
Message: "Please type the desired section name.",
Title: "Add a section",
Placeholder: "My next section",
ShowQuestionCheckbox: true,
QuestionCheckboxText: "Add a root node (i.e. ignoring the selected node)"
));
if(result.DialogResult == DialogResult.Cancel)
return;
var addRootNode = result.AnswerToQuestion;
// Get the currently selected section as parent:
var selectedNode = this.treeView.SelectedNode;
// Add the new section to the database:
var addedSection = await SectionProcessor.AddSection(result.Text, addRootNode ? null : selectedNode?.Name);
addedSection.ProcessError();
if(!addedSection.Successful)
return;
var translationProgress = await TranslationProcessor.CalculateTranslationProgress(addedSection.Result!);
// Add the new section to the tree control:
var node = new TreeNode
{
Name = addedSection.Result!.DataKey, // [sic] name is the key
Text = $"{addedSection.Result.Name} [{translationProgress.Result}%]",
StateImageIndex = 1,
};
// Wire each node to the translation change event to update the translation progress:
NODE_PROGRESS_HANDLERS.Add(node, async (_, translation) => await this.UpdateTranslationProgress(node, addedSection.Result, translation));
AppEvents.WhenTranslationChanged += NODE_PROGRESS_HANDLERS[node];
if(!addRootNode && selectedNode is not null)
selectedNode.Nodes.Add(node);
else
this.treeView.Nodes.Add(node);
// Ensure, that the added node is visible and gets the focus:
node.EnsureVisible();
this.treeView.SelectedNode = node;
// Fire the click event:
this.treeView_NodeMouseClick(this, new TreeNodeMouseClickEventArgs(node, MouseButtons.Left, 1, 0, 0));
}
private async void buttonRemove_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
// Get the currently selected section, which will be removed:
var selectedNode = this.treeView.SelectedNode;
// Get the number of children:
// (notice, that the node's name is its key)
var numberChildren = await SectionProcessor.NumberChildren(selectedNode.Name);
// Ask the user, if he really wants to remove the section:
if(MessageBox.Show(numberChildren > 0 ? $"Are you sure, you want to remove the section '{selectedNode.Text}', its {numberChildren} children and so on?" : $"Are you sure, you want to remove the section '{selectedNode.Text}'?", "Remove section", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)
return;
// Remove the section from the database:
// (notice, that the node's name is its key)
await SectionProcessor.RemoveSection(selectedNode.Name);
// Remove all nodes from the tree control:
this.treeView.Nodes.Clear();
foreach (var (treeNode, handler) in NODE_PROGRESS_HANDLERS)
AppEvents.WhenTranslationChanged -= handler;
NODE_PROGRESS_HANDLERS.Clear();
// Reload the tree:
this.LoadNodes(this, EventArgs.Empty);
// Select the first root node:
this.treeView.SelectedNode = this.treeView.Nodes.Count > 0 ? this.treeView.Nodes[0] : null;
// Fire the click event:
this.treeView_NodeMouseClick(this, new TreeNodeMouseClickEventArgs(this.treeView.SelectedNode!, MouseButtons.Left, 1, 0, 0));
AppEvents.TranslationChanged(null);
}
private async void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
if(this.DesignMode)
return;
// Get the currently selected section:
var selectedNode = e.Node;
// If the selected node is not null, enable the remove & edit button:
this.buttonRename.Enabled = this.buttonRemove.Enabled = selectedNode is not null;
// When a section is selected, fire the event:
if (selectedNode is not null)
{
// Get the section from the database:
var section = await SectionProcessor.GetSection(selectedNode.Name);
AppEvents.SectionChanged(section);
}
}
private async void buttonRename_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
// Ask the user if he really wants to rename the section:
if(MessageBox.Show("Are you sure, you want to rename the selected section? If you are already using this section in your code, you will need to manually refactor your code after renaming it.", "Rename section", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.No)
return;
// Get the currently selected section:
var selectedNode = this.treeView.SelectedNode;
// Ask the user for the new name:
var result = InputDialog.Show(new InputDialog.Options(
Message: "Please edit the section name.",
PreloadedText: selectedNode.Text,
ShowQuestionCheckbox: false,
Title: "Rename section"
));
// If the user canceled, return:
if(result.DialogResult == DialogResult.Cancel)
return;
// Rename the section:
var alteredSection = await SectionProcessor.RenameSection(selectedNode.Name, result.Text);
alteredSection.ProcessError();
if(!alteredSection.Successful)
return;
// Rename the selected node:
selectedNode.Text = alteredSection.Result!.Name;
selectedNode.Name = alteredSection.Result.DataKey; // [sic] name is the key
}
private async void buttonGenerate_Click(object sender, EventArgs e) => await this.PerformGenerators();
private async void GeneratorEvent()
{
if(await AppSettings.GetGeneratorMode() == SettingGeneratorMode.MANUAL)
return;
if (this.generatorTimer.Enabled)
this.generatorTimer.Stop();
this.generatorTimer.Start();
}
private async Task PerformGenerators()
{
if (this.buttonGenerate.InvokeRequired)
{
await this.buttonGenerate.Invoke(this.PerformGenerators);
return;
}
this.buttonGenerate.Enabled = false;
var result = await Generator.TriggerAllAsync();
result.ProcessError();
this.buttonGenerate.Enabled = true;
}
}

View File

@ -1,63 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -1,107 +0,0 @@
namespace UI_WinForms.Components
{
sealed partial class Setting
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.labelSettingName = new System.Windows.Forms.Label();
this.labelIcon = new System.Windows.Forms.Label();
this.labelExplanation = new System.Windows.Forms.LinkLabel();
this.tableLayout.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 4;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 250F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 300F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.labelSettingName, 1, 0);
this.tableLayout.Controls.Add(this.labelIcon, 0, 0);
this.tableLayout.Controls.Add(this.labelExplanation, 3, 0);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Margin = new System.Windows.Forms.Padding(0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 1;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Size = new System.Drawing.Size(1000, 72);
this.tableLayout.TabIndex = 0;
//
// labelSettingName
//
this.labelSettingName.AutoSize = true;
this.labelSettingName.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelSettingName.Location = new System.Drawing.Point(69, 0);
this.labelSettingName.Name = "labelSettingName";
this.labelSettingName.Size = new System.Drawing.Size(244, 72);
this.labelSettingName.TabIndex = 2;
this.labelSettingName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// labelIcon
//
this.labelIcon.AutoSize = true;
this.labelIcon.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelIcon.Location = new System.Drawing.Point(3, 0);
this.labelIcon.Name = "labelIcon";
this.labelIcon.Size = new System.Drawing.Size(60, 72);
this.labelIcon.TabIndex = 3;
//
// labelExplanation
//
this.labelExplanation.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelExplanation.Location = new System.Drawing.Point(619, 0);
this.labelExplanation.Name = "labelExplanation";
this.labelExplanation.Size = new System.Drawing.Size(378, 72);
this.labelExplanation.TabIndex = 4;
this.labelExplanation.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// Setting
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "Setting";
this.Size = new System.Drawing.Size(1000, 72);
this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private Label labelSettingName;
private Label labelIcon;
private LinkLabel labelExplanation;
}
}

View File

@ -1,858 +0,0 @@
using System.Diagnostics;
using DataModel.Database;
using Processor;
using UI_WinForms.Resources;
namespace UI_WinForms.Components;
public sealed partial class Setting : UserControl
{
private readonly record struct SettingUIData(
Bitmap Icon,
Func<string> SettingName,
Func<string> SettingExplanation,
Func<(string URL, string TextPattern)> SettingExplanationLink,
Func<Action, Control> SetupDataControl,
bool ChangeNeedsRestart
);
private readonly SettingUIData data;
private bool needRestart = false;
public Setting()
{
this.InitializeComponent();
}
public bool NeedRestart => this.needRestart;
private Setting(SettingUIData settingMetaData)
{
this.InitializeComponent();
if(this.DesignMode)
return;
this.Dock = DockStyle.Top;
this.data = settingMetaData;
this.labelIcon.Image = settingMetaData.Icon;
this.labelSettingName.Text = settingMetaData.SettingName();
this.labelExplanation.Text = settingMetaData.SettingExplanation();
//
// Handle up to one link in the explanation:
//
var link = settingMetaData.SettingExplanationLink();
var startIdx = this.labelExplanation.Text.IndexOf(link.TextPattern, StringComparison.InvariantCulture);
this.labelExplanation.Links.Clear();
if (!string.IsNullOrWhiteSpace(link.TextPattern) && !string.IsNullOrWhiteSpace(link.URL) && startIdx > -1)
this.labelExplanation.Links.Add(startIdx, link.TextPattern.Length, link.URL);
this.labelExplanation.LinkClicked += (_, args) =>
{
if(args.Link.LinkData is string url && !string.IsNullOrWhiteSpace(url) && url.ToLowerInvariant().StartsWith("https://", StringComparison.InvariantCulture))
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
};
var dataControl = settingMetaData.SetupDataControl(this.ChangeTrigger);
this.tableLayout.Controls.Add(dataControl, 2, 0);
// Ensure, that this data control is vertical centered by calculating the needed margin, considering the outer size of the table layout:
var margin = (this.tableLayout.GetRowHeights().First() - dataControl.Height) / 2f;
dataControl.Margin = new Padding(0, (int) margin, 0, (int)margin);
// Calculate the needed height of the explanation label & centering of the data control when the parent window is resized:
this.tableLayout.Resize += (sender, args) =>
{
// Adjust the height of the parent controls (table & user control):
this.tableLayout.Height = Math.Max((int)this.labelExplanation.CreateGraphics().MeasureString(this.labelExplanation.Text, this.labelExplanation.Font, new SizeF(this.labelExplanation.Width, 1000)).Height, 66);
this.Height = this.tableLayout.Height + this.tableLayout.Margin.Vertical;
// Ensure, that this data control is vertical centered by calculating the needed margin, considering the outer size of the table layout:
var margin = (this.tableLayout.GetRowHeights().First() - dataControl.Height) / 2f;
dataControl.Margin = new Padding(0, (int) margin, 0, (int)margin);
};
}
private void ChangeTrigger()
{
if(this.data.ChangeNeedsRestart)
this.needRestart = true;
AppEvents.SettingsChanged();
}
private void UpdateExplanation() => this.labelExplanation.Text = this.data.SettingExplanation();
private static async Task<Setting> ShowDeepLModeSettingAsync()
{
var currentSetting = await AppSettings.GetDeepLMode();
var settingData = new SettingUIData(
Icon: Icons.deepl_logo_icon_170284,
SettingName: () => "DeepL Service",
ChangeNeedsRestart: true,
SettingExplanation: () => "DeepL is a translation service that offers a wide range of translation services. This setting allows you to choose between the free and pro version of DeepL.",
SettingExplanationLink: () => ("https://www.deepl.com/", "DeepL"),
SetupDataControl: (changeTrigger) =>
{
var dropdown = new ComboBox();
dropdown.Items.Add("Disabled");
dropdown.Items.Add("Free version");
dropdown.Items.Add("Pro version");
dropdown.SelectedIndex = currentSetting switch
{
SettingDeepLMode.DISABLED => 0,
SettingDeepLMode.USE_FREE_ACCOUNT => 1,
SettingDeepLMode.USE_PRO_ACCOUNT => 2,
_ => 0,
};
// Setup the change event handler:
dropdown.SelectedValueChanged += async (sender, args) => await AppSettings.SetDeepLMode(dropdown.SelectedIndex switch
{
0 => SettingDeepLMode.DISABLED,
1 => SettingDeepLMode.USE_FREE_ACCOUNT,
2 => SettingDeepLMode.USE_PRO_ACCOUNT,
_ => SettingDeepLMode.DISABLED,
});
// Fires the change trigger:
dropdown.SelectedValueChanged += (sender, args) => changeTrigger();
// Apply the desired layout:
dropdown.Dock = DockStyle.Fill;
dropdown.DropDownStyle = ComboBoxStyle.DropDownList;
return dropdown;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowDeepLAPIKeySettingAsync()
{
var currentSetting = await AppSettings.GetDeepLAPIKey();
var settingData = new SettingUIData(
Icon: Icons.icons8_key_512,
SettingName: () => "DeepL API Key",
ChangeNeedsRestart: true,
SettingExplanation: () => "The API key is required to use the DeepL translation service. You can find your API key on the DeepL website.",
SettingExplanationLink: () => ("https://www.deepl.com/", "DeepL"),
SetupDataControl: (changeTrigger) =>
{
var textbox = new TextBox();
textbox.Text = currentSetting;
textbox.TextChanged += async (sender, args) => await AppSettings.SetDeepLAPIKey(textbox.Text);
textbox.TextChanged += (sender, args) => changeTrigger();
textbox.Dock = DockStyle.Fill;
return textbox;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowDeepLUsageSettingAsync()
{
var currentUsage = await Processor.DeepL.GetUsage();
var percent = currentUsage.Enabled ? currentUsage.CharacterCount / (float)currentUsage.CharacterLimit : 0;
// Local function to show & update the explanation text:
string GetUsageText() => currentUsage.Enabled ?
$"You used {currentUsage.CharacterCount:###,###,###,##0} characters out of {currentUsage.CharacterLimit:###,###,###,##0} ({percent:P2})." : currentUsage.AuthIssue ?
"Was not able to authorize with DeepL. Please check your API key." :
"DeepL is disabled or the API key is not set.";
var settingData = new SettingUIData(
Icon: Icons.icons8_increase_512,
SettingName: () => "DeepL Usage",
ChangeNeedsRestart: false,
SettingExplanation: GetUsageText,
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
var progressbar = new ProgressBar();
progressbar.Maximum = 100;
progressbar.Margin = new Padding(0, 16, 0, 16);
progressbar.Dock = DockStyle.Fill;
progressbar.Style = ProgressBarStyle.Continuous;
progressbar.Value = percent switch
{
< 0 => 0,
> 1 => 100,
_ => (int)(percent * 100)
};
var reloadButton = new Button();
reloadButton.Text = string.Empty;
reloadButton.Image = Icons.icons8_reload_512;
reloadButton.FlatStyle = FlatStyle.Flat;
reloadButton.FlatAppearance.BorderSize = 0;
reloadButton.BackColor = Color.Empty;
reloadButton.UseVisualStyleBackColor = true;
reloadButton.Size = new Size(60, 60);
reloadButton.Click += async (sender, args) =>
{
var usage = await Processor.DeepL.GetUsage();
// Update the outer variables:
percent = usage.Enabled ? usage.CharacterCount / (float)usage.CharacterLimit : 0;
currentUsage = usage;
// Update the progress bar:
progressbar.Value = percent switch
{
< 0 => 0,
> 1 => 100,
_ => (int)(percent * 100)
};
// Update the explanation text. Therefore, we need to get the setting object through the chain of parents:
var setting = (Setting) (((Control) sender!)!).Parent.Parent.Parent;
setting.UpdateExplanation();
};
// Setup the layout:
var layout = new TableLayoutPanel();
layout.ColumnCount = 2;
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 66));
layout.RowCount = 1;
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
layout.Controls.Add(progressbar, 0, 0);
layout.Controls.Add(reloadButton, 1, 0);
layout.Dock = DockStyle.Fill;
return layout;
}
);
var setting = new Setting(settingData);
return setting;
}
private static async Task<Setting> ShowDeepLActionSettingAsync()
{
var currentSetting = await AppSettings.GetDeepLAction();
var settingData = new SettingUIData(
Icon: Icons.icons8_play_512__2_,
SettingName: () => "DeepL Operation",
ChangeNeedsRestart: true,
SettingExplanation: () => "Should the missing translations be automatically completed by DeepL? This can lead to higher costs. By default, DeepL is only applied manually.",
SettingExplanationLink: () => ("https://www.deepl.com/", "DeepL"),
SetupDataControl: (changeTrigger) =>
{
// We set up a combo box with the available actions:
var dropdown = new ComboBox();
dropdown.Items.Add("Manual");
dropdown.Items.Add("Automatic");
dropdown.SelectedIndex = currentSetting switch
{
SettingDeepLAction.MANUAL => 0,
SettingDeepLAction.AUTOMATIC_ALL => 1,
_ => 0,
};
// Setup the change event handler:
dropdown.SelectedValueChanged += async (sender, args) => await AppSettings.SetDeepLAction(dropdown.SelectedIndex switch
{
0 => SettingDeepLAction.MANUAL,
1 => SettingDeepLAction.AUTOMATIC_ALL,
_ => SettingDeepLAction.MANUAL,
});
dropdown.SelectedValueChanged += (sender, args) => changeTrigger();
// Apply the desired layout:
dropdown.Dock = DockStyle.Fill;
dropdown.DropDownStyle = ComboBoxStyle.DropDownList;
return dropdown;
}
);
return new Setting(settingData);
}
internal readonly record struct ComboBoxItem(string DisplayText, int CultureIndex)
{
public override string ToString() => this.DisplayText;
}
private static async Task<Setting> ShowDeepLSourceCultureSettingAsync()
{
var currentSourceCultureIndex = await AppSettings.GetDeepLSourceCultureIndex();
// We load the corresponding culture for that index. As dropdown items, we show
// all other available cultures:
var allCultures = await AppSettings.GetCultureInfos();
// Attention: We have to store the culture's index, because the index is not
// continuous and can change when the user adds or removes a culture!
var settingData = new SettingUIData(
Icon: Icons.icons8_chat_bubble_512,
SettingName: () => "DeepL Source Culture",
ChangeNeedsRestart: true,
SettingExplanation: () => "The source culture is used to translate the missing translations.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
var dropdown = new ComboBox();
var currentCultureDropdownIndex = 0;
for (var n = 0; n < allCultures.Count; n++)
{
var cultureInfo = allCultures[n];
if(cultureInfo.Index == currentSourceCultureIndex)
currentCultureDropdownIndex = n;
dropdown.Items.Add(new ComboBoxItem($"{cultureInfo.Index}.: {cultureInfo.Code}", cultureInfo.Index));
}
dropdown.SelectedIndex = currentCultureDropdownIndex;
// Setup the change event handler:
dropdown.SelectedValueChanged += async (sender, args) =>
{
if(dropdown.SelectedItem is ComboBoxItem selectedItem)
await AppSettings.SetDeepLSourceCultureIndex(selectedItem.CultureIndex);
};
dropdown.SelectedValueChanged += (sender, args) => changeTrigger();
// Apply the desired layout:
dropdown.Dock = DockStyle.Fill;
dropdown.DropDownStyle = ComboBoxStyle.DropDownList;
return dropdown;
}
);
return new Setting(settingData);
}
private static IEnumerable<Task<Setting>> ShowCultureSettingsAsync()
{
var isFirstCulture = true; // We need this flag to distinguish the first task from the others.
var cultureIndices = new List<int>(new []{ -1 });
while (cultureIndices.Count > 0)
{
var innerLoopIndex = cultureIndices.Last(); // needed to avoid closure issues.
yield return Task.Run(async () =>
{
var localCultureIndex = innerLoopIndex;
// Get a list of culture indices. Thus, we know the number of cultures. We cannot do this in the outer loop,
// because we cannot await there. The AppSettings is caching the answer, though. The list of indices is ordered
// ascending.
var localCultureIndices = await AppSettings.GetCultureIndices();
// Update the number of cultures in the outer loop for the first call:
if(isFirstCulture)
{
localCultureIndex = localCultureIndices.Last();
innerLoopIndex = localCultureIndices.Last();
cultureIndices.Clear();
cultureIndices.AddRange(localCultureIndices);
isFirstCulture = false;
}
// Get the current culture code:
var currentCultureCode = await AppSettings.GetCultureCode(localCultureIndex);
// Construct the setting:
return new Setting(new()
{
Icon = Icons.icons8_chat_bubble_512,
SettingName = () => $"{localCultureIndex}. Culture",
ChangeNeedsRestart = true,
SettingExplanation = () => "The culture according to RFC 4646: First comes the ISO 639-1 language code in lower case, followed by a hyphen, followed by the ISO 3166-1 alpha-2 country code in upper case. Example: en-US for English in the USA, de-DE for German in Germany.",
SettingExplanationLink = () => ("https://lonewolfonline.net/list-net-culture-country-codes/", "according to RFC 4646"),
SetupDataControl = (changeTrigger) =>
{
var textbox = new TextBox();
textbox.Text = currentCultureCode;
textbox.TextChanged += async (sender, args) =>
{
await AppSettings.SetCultureCode(localCultureIndex, textbox.Text);
changeTrigger();
};
textbox.Dock = DockStyle.Fill;
return textbox;
}
});
});
cultureIndices.Remove(innerLoopIndex);
}
}
private static async Task<Setting> ShowGeneratorModeSettingAsync()
{
var currentSetting = await AppSettings.GetGeneratorMode();
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator Mode",
ChangeNeedsRestart: false,
SettingExplanation: () => "The generator mode determines how the translation files are generated.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// We set up a combo box with the available actions:
var dropdown = new ComboBox();
dropdown.Items.Add("Automatic generation");
dropdown.Items.Add("Manual generation");
dropdown.SelectedIndex = currentSetting switch
{
SettingGeneratorMode.AUTOMATIC => 0,
SettingGeneratorMode.MANUAL => 1,
_ => 0,
};
// Setup the change event handler:
dropdown.SelectedValueChanged += async (sender, args) => await AppSettings.SetGeneratorMode(dropdown.SelectedIndex switch
{
0 => SettingGeneratorMode.AUTOMATIC,
1 => SettingGeneratorMode.MANUAL,
_ => SettingGeneratorMode.AUTOMATIC,
});
dropdown.SelectedValueChanged += (sender, args) => changeTrigger();
// Apply the desired layout:
dropdown.Dock = DockStyle.Fill;
dropdown.DropDownStyle = ComboBoxStyle.DropDownList;
return dropdown;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorDotnetEnabledSettingAsync()
{
var currentSetting = await AppSettings.GetGeneratorDotnetEnabled();
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator: .NET",
ChangeNeedsRestart: false,
SettingExplanation: () => "When enabled, .NET translation files are generated. Requires a .NET 7 or newer project.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// Set up an checkbox:
var checkbox = new CheckBox();
checkbox.Checked = currentSetting;
checkbox.CheckedChanged += async (sender, args) => await AppSettings.SetGeneratorDotnetEnabled(checkbox.Checked);
checkbox.CheckedChanged += (sender, args) => changeTrigger();
checkbox.Text = "Enable .NET Generator";
// Apply the desired layout:
checkbox.Dock = DockStyle.Fill;
return checkbox;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorDotnetDestinationPathSettingAsync()
{
var currentSetting = await AppSettings.GetGeneratorDotnetDestinationPath();
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator: .NET Destination Path",
ChangeNeedsRestart: false,
SettingExplanation: () => "The destination path for the .NET translation files. You might use environment variables like %USERPROFILE%.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// Set up a horizontal layout:
var layout = new TableLayoutPanel();
layout.ColumnCount = 2;
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 66F));
layout.RowCount = 1;
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
layout.Dock = DockStyle.Fill;
// Set up a textbox:
var textbox = new TextBox();
textbox.Text = currentSetting;
textbox.TextChanged += async (sender, args) => await AppSettings.SetGeneratorDotnetDestinationPath(textbox.Text);
textbox.TextChanged += (sender, args) => changeTrigger();
textbox.Dock = DockStyle.Fill;
textbox.Margin = new Padding(0, 13, 0, 13);
layout.Controls.Add(textbox, 0, 0);
// Set up a button:
var button = new Button();
button.Text = string.Empty;
button.Image = Icons.icons8_folder_tree_512;
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.BorderSize = 0;
button.BackColor = Color.Empty;
button.UseVisualStyleBackColor = true;
button.Size = new Size(60, 60);
button.Click += (sender, args) =>
{
var dialog = new FolderBrowserDialog();
dialog.SelectedPath = textbox.Text;
dialog.InitialDirectory = textbox.Text;
dialog.Description = "Select the destination path for the .NET translation files.";
dialog.ShowNewFolderButton = true;
if (dialog.ShowDialog() == DialogResult.OK)
textbox.Text = dialog.SelectedPath;
};
button.Dock = DockStyle.Fill;
layout.Controls.Add(button, 1, 0);
return layout;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorDotnetNamespaceSettingAsync()
{
var currentSetting = await AppSettings.GetGeneratorDotnetNamespace();
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator: .NET Namespace",
ChangeNeedsRestart: false,
SettingExplanation: () => "The namespace for the .NET I18N files.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// Set up a textbox:
var textbox = new TextBox();
textbox.Text = currentSetting;
textbox.TextChanged += async (sender, args) => await AppSettings.SetGeneratorDotnetNamespace(textbox.Text);
textbox.TextChanged += (sender, args) => changeTrigger();
textbox.Dock = DockStyle.Fill;
textbox.Margin = new Padding(0, 13, 0, 13);
return textbox;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorDotnetDefaultCultureSettingAsync()
{
var currentSourceCultureIndex = await AppSettings.GetGeneratorDotnetDefaultCultureIndex();
// We load the corresponding culture for that index. As dropdown items, we show
// all other available cultures:
var allCultures = await AppSettings.GetCultureInfos();
// Attention: We have to store the culture's index, because the index is not
// continuous and can change when the user adds or removes a culture!
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator: .NET Default Culture",
ChangeNeedsRestart: false,
SettingExplanation: () => "The default culture for the .NET, which is used when no culture is specified or available.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
var dropdown = new ComboBox();
var currentCultureDropdownIndex = 0;
for (var n = 0; n < allCultures.Count; n++)
{
var cultureInfo = allCultures[n];
if(cultureInfo.Index == currentSourceCultureIndex)
currentCultureDropdownIndex = n;
dropdown.Items.Add(new ComboBoxItem($"{cultureInfo.Index}.: {cultureInfo.Code}", cultureInfo.Index));
}
dropdown.SelectedIndex = currentCultureDropdownIndex;
// Setup the change event handler:
dropdown.SelectedValueChanged += async (sender, args) =>
{
if(dropdown.SelectedItem is ComboBoxItem selectedItem)
await AppSettings.SetGeneratorDotnetDefaultCultureIndex(selectedItem.CultureIndex);
};
dropdown.SelectedValueChanged += (sender, args) => changeTrigger();
// Apply the desired layout:
dropdown.Dock = DockStyle.Fill;
dropdown.DropDownStyle = ComboBoxStyle.DropDownList;
return dropdown;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorGodotEnabledSettingAsync()
{
var currentSetting = await AppSettings.GetGeneratorGodotEnabled();
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator: Godot",
ChangeNeedsRestart: false,
SettingExplanation: () => "When enabled, Godot translation files are generated. Requires a Godot 3.5 or newer project.",
SettingExplanationLink: () => ("https://godotengine.org/", "Godot"),
SetupDataControl: (changeTrigger) =>
{
// Set up an checkbox:
var checkbox = new CheckBox();
checkbox.Checked = currentSetting;
checkbox.CheckedChanged += async (sender, args) => await AppSettings.SetGeneratorGodotEnabled(checkbox.Checked);
checkbox.CheckedChanged += (sender, args) => changeTrigger();
checkbox.Text = "Enable Godot Generator";
// Apply the desired layout:
checkbox.Dock = DockStyle.Fill;
return checkbox;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorGodotDestinationPathSettingAsync()
{
var currentSetting = await AppSettings.GetGeneratorGodotDestinationPath();
var settingData = new SettingUIData(
Icon: Icons.icons8_code_512,
SettingName: () => "Generator: Godot Destination Path",
ChangeNeedsRestart: false,
SettingExplanation: () => "The destination path for the Godot translation files. You might use environment variables like %USERPROFILE%.",
SettingExplanationLink: () => ("https://godotengine.org/", "Godot"),
SetupDataControl: (changeTrigger) =>
{
// Set up a horizontal layout:
var layout = new TableLayoutPanel();
layout.ColumnCount = 2;
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 66F));
layout.RowCount = 1;
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
layout.Dock = DockStyle.Fill;
// Set up a textbox:
var textbox = new TextBox();
textbox.Text = currentSetting;
textbox.TextChanged += async (sender, args) => await AppSettings.SetGeneratorGodotDestinationPath(textbox.Text);
textbox.TextChanged += (sender, args) => changeTrigger();
textbox.Dock = DockStyle.Fill;
textbox.Margin = new Padding(0, 13, 0, 13);
layout.Controls.Add(textbox, 0, 0);
// Set up a button:
var button = new Button();
button.Text = string.Empty;
button.Image = Icons.icons8_folder_tree_512;
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.BorderSize = 0;
button.BackColor = Color.Empty;
button.UseVisualStyleBackColor = true;
button.Size = new Size(60, 60);
button.Click += (sender, args) =>
{
var dialog = new FolderBrowserDialog();
dialog.SelectedPath = textbox.Text;
dialog.InitialDirectory = textbox.Text;
dialog.Description = "Select the destination path for the Godot translation files.";
dialog.ShowNewFolderButton = true;
if (dialog.ShowDialog() == DialogResult.OK)
textbox.Text = dialog.SelectedPath;
};
button.Dock = DockStyle.Fill;
layout.Controls.Add(button, 1, 0);
return layout;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorAutoExportEnabledSettingAsync()
{
var currentSetting = await AppSettings.GetAutoExportEnabled();
var settingData = new SettingUIData(
Icon: Icons.icons8_git,
SettingName: () => "Git (JSON) Auto-Export: Enabled",
ChangeNeedsRestart: true,
SettingExplanation: () => "When enabled, all changes are automatically exported into a Git repository as JSON file.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// Set up an checkbox:
var checkbox = new CheckBox();
checkbox.Checked = currentSetting;
checkbox.CheckedChanged += async (sender, args) =>
{
await AppSettings.SetAutoExportEnabled(checkbox.Checked);
await ExportProcessor.TriggerExport();
changeTrigger();
};
checkbox.Text = "Enable Auto-Export";
// Apply the desired layout:
checkbox.Dock = DockStyle.Fill;
return checkbox;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorAutoExportDestinationPathSettingAsync()
{
var currentSetting = await AppSettings.GetAutoExportDestinationPath();
var settingData = new SettingUIData(
Icon: Icons.icons8_git,
SettingName: () => "Git (JSON) Auto-Export: Destination Path",
ChangeNeedsRestart: true,
SettingExplanation: () => "The destination path for the Git repository. You might use environment variables like %USERPROFILE%.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// Set up a horizontal layout:
var layout = new TableLayoutPanel();
layout.ColumnCount = 2;
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 66F));
layout.RowCount = 1;
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
layout.Dock = DockStyle.Fill;
// Set up a textbox:
var textbox = new TextBox();
textbox.Text = currentSetting;
textbox.TextChanged += async (sender, args) => await AppSettings.SetAutoExportDestinationPath(textbox.Text);
textbox.TextChanged += (sender, args) => changeTrigger();
textbox.Dock = DockStyle.Fill;
textbox.Margin = new Padding(0, 13, 0, 13);
layout.Controls.Add(textbox, 0, 0);
// Set up a button:
var button = new Button();
button.Text = string.Empty;
button.Image = Icons.icons8_folder_tree_512;
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.BorderSize = 0;
button.BackColor = Color.Empty;
button.UseVisualStyleBackColor = true;
button.Size = new Size(60, 60);
button.Click += (sender, args) =>
{
var dialog = new FolderBrowserDialog();
dialog.SelectedPath = textbox.Text;
dialog.InitialDirectory = textbox.Text;
dialog.Description = "Select the destination path for the Git repository.";
dialog.ShowNewFolderButton = true;
if (dialog.ShowDialog() == DialogResult.OK)
textbox.Text = dialog.SelectedPath;
};
button.Dock = DockStyle.Fill;
layout.Controls.Add(button, 1, 0);
return layout;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorAutoExportFilenameSettingAsync()
{
var currentSetting = await AppSettings.GetAutoExportFilename();
var settingData = new SettingUIData(
Icon: Icons.icons8_git,
SettingName: () => "Git (JSON) Auto-Export: Filename",
ChangeNeedsRestart: true,
SettingExplanation: () => "The filename used for the Git export. You might use environment variables like %USERPROFILE%.",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
var textbox = new TextBox();
textbox.Text = currentSetting;
textbox.TextChanged += async (sender, args) => await AppSettings.SetAutoExportFilename(textbox.Text);
textbox.TextChanged += (sender, args) => changeTrigger();
textbox.Dock = DockStyle.Fill;
textbox.Margin = new Padding(0, 13, 0, 13);
return textbox;
}
);
return new Setting(settingData);
}
private static async Task<Setting> ShowGeneratorAutoExportExportSensitiveDataSettingAsync()
{
var currentSetting = await AppSettings.GetAutoExportSensitiveData();
var settingData = new SettingUIData(
Icon: Icons.icons8_git,
SettingName: () => "Git (JSON) Auto-Export: Export Sensitive Data",
ChangeNeedsRestart: true,
SettingExplanation: () => "When enabled, sensitive data like API tokens are exported into the Git repository. This is not recommended!",
SettingExplanationLink: () => (string.Empty, string.Empty),
SetupDataControl: (changeTrigger) =>
{
// Set up an checkbox:
var checkbox = new CheckBox();
checkbox.Checked = currentSetting;
checkbox.CheckedChanged += async (sender, args) => await AppSettings.SetAutoExportSensitiveData(checkbox.Checked);
checkbox.CheckedChanged += (sender, args) => changeTrigger();
checkbox.Text = "Export Sensitive Data";
// Apply the desired layout:
checkbox.Dock = DockStyle.Fill;
return checkbox;
}
);
return new Setting(settingData);
}
public static IEnumerable<Task<Setting>> GetAllSettings()
{
//
// Remember: The reverse order is the order in the UI!
//
yield return ShowGeneratorAutoExportFilenameSettingAsync();
yield return ShowGeneratorAutoExportDestinationPathSettingAsync();
yield return ShowGeneratorAutoExportExportSensitiveDataSettingAsync();
yield return ShowGeneratorAutoExportEnabledSettingAsync();
yield return ShowGeneratorGodotDestinationPathSettingAsync();
yield return ShowGeneratorGodotEnabledSettingAsync();
yield return ShowGeneratorDotnetDefaultCultureSettingAsync();
yield return ShowGeneratorDotnetNamespaceSettingAsync();
yield return ShowGeneratorDotnetDestinationPathSettingAsync();
yield return ShowGeneratorDotnetEnabledSettingAsync();
yield return ShowGeneratorModeSettingAsync();
yield return ShowDeepLSourceCultureSettingAsync();
foreach (var setting in ShowCultureSettingsAsync())
yield return setting;
yield return ShowDeepLUsageSettingAsync();
yield return ShowDeepLActionSettingAsync();
yield return ShowDeepLAPIKeySettingAsync();
yield return ShowDeepLModeSettingAsync();
}
}

View File

@ -1,60 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,193 +0,0 @@
namespace UI_WinForms.Components
{
partial class Settings
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.labelHeadIcon = new System.Windows.Forms.Label();
this.labelHead = new System.Windows.Forms.Label();
this.panelSettings = new System.Windows.Forms.Panel();
this.flowLayoutToolbar = new System.Windows.Forms.FlowLayoutPanel();
this.buttonAddCulture = new System.Windows.Forms.Button();
this.buttonDeleteCulture = new System.Windows.Forms.Button();
this.contextMenuDelete = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.labelVersion = new System.Windows.Forms.Label();
this.tableLayout.SuspendLayout();
this.flowLayoutToolbar.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 2;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 70F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.labelHeadIcon, 0, 0);
this.tableLayout.Controls.Add(this.labelHead, 1, 0);
this.tableLayout.Controls.Add(this.panelSettings, 0, 1);
this.tableLayout.Controls.Add(this.flowLayoutToolbar, 0, 2);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 3;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.Size = new System.Drawing.Size(1001, 381);
this.tableLayout.TabIndex = 1;
//
// labelHeadIcon
//
this.labelHeadIcon.AutoSize = true;
this.labelHeadIcon.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelHeadIcon.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
this.labelHeadIcon.Image = global::UI_WinForms.Resources.Icons.icons8_settings_svg;
this.labelHeadIcon.Location = new System.Drawing.Point(3, 0);
this.labelHeadIcon.Name = "labelHeadIcon";
this.labelHeadIcon.Size = new System.Drawing.Size(64, 66);
this.labelHeadIcon.TabIndex = 0;
//
// labelHead
//
this.labelHead.AutoSize = true;
this.labelHead.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelHead.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
this.labelHead.Location = new System.Drawing.Point(73, 0);
this.labelHead.Name = "labelHead";
this.labelHead.Size = new System.Drawing.Size(925, 66);
this.labelHead.TabIndex = 1;
this.labelHead.Text = "Settings";
this.labelHead.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// panelSettings
//
this.panelSettings.AutoScroll = true;
this.tableLayout.SetColumnSpan(this.panelSettings, 21);
this.panelSettings.Dock = System.Windows.Forms.DockStyle.Fill;
this.panelSettings.Location = new System.Drawing.Point(0, 66);
this.panelSettings.Margin = new System.Windows.Forms.Padding(0);
this.panelSettings.Name = "panelSettings";
this.panelSettings.Size = new System.Drawing.Size(1001, 249);
this.panelSettings.TabIndex = 2;
//
// flowLayoutToolbar
//
this.tableLayout.SetColumnSpan(this.flowLayoutToolbar, 2);
this.flowLayoutToolbar.Controls.Add(this.buttonAddCulture);
this.flowLayoutToolbar.Controls.Add(this.buttonDeleteCulture);
this.flowLayoutToolbar.Controls.Add(this.labelVersion);
this.flowLayoutToolbar.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutToolbar.Location = new System.Drawing.Point(0, 315);
this.flowLayoutToolbar.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutToolbar.Name = "flowLayoutToolbar";
this.flowLayoutToolbar.Size = new System.Drawing.Size(1001, 66);
this.flowLayoutToolbar.TabIndex = 3;
//
// buttonAddCulture
//
this.buttonAddCulture.FlatAppearance.BorderSize = 0;
this.buttonAddCulture.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonAddCulture.Image = global::UI_WinForms.Resources.Icons.icons8_collectibles_512;
this.buttonAddCulture.Location = new System.Drawing.Point(3, 3);
this.buttonAddCulture.Name = "buttonAddCulture";
this.buttonAddCulture.Size = new System.Drawing.Size(60, 60);
this.buttonAddCulture.TabIndex = 0;
this.toolTip.SetToolTip(this.buttonAddCulture, "Add another culture");
this.buttonAddCulture.UseVisualStyleBackColor = true;
this.buttonAddCulture.Click += new System.EventHandler(this.buttonAddCulture_Click);
//
// buttonDeleteCulture
//
this.buttonDeleteCulture.ContextMenuStrip = this.contextMenuDelete;
this.buttonDeleteCulture.FlatAppearance.BorderSize = 0;
this.buttonDeleteCulture.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonDeleteCulture.Image = global::UI_WinForms.Resources.Icons.icons8_trash_can_512;
this.buttonDeleteCulture.Location = new System.Drawing.Point(69, 3);
this.buttonDeleteCulture.Name = "buttonDeleteCulture";
this.buttonDeleteCulture.Size = new System.Drawing.Size(60, 60);
this.buttonDeleteCulture.TabIndex = 0;
this.toolTip.SetToolTip(this.buttonDeleteCulture, "Delete a culture");
this.buttonDeleteCulture.UseVisualStyleBackColor = true;
this.buttonDeleteCulture.Click += new System.EventHandler(this.buttonDeleteCulture_Click);
//
// contextMenuDelete
//
this.contextMenuDelete.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.contextMenuDelete.ImageScalingSize = new System.Drawing.Size(20, 20);
this.contextMenuDelete.Name = "contextMenuDelete";
this.contextMenuDelete.Size = new System.Drawing.Size(61, 4);
//
// toolTip
//
this.toolTip.AutoPopDelay = 30000;
this.toolTip.InitialDelay = 500;
this.toolTip.ReshowDelay = 100;
this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.toolTip.ToolTipTitle = "Help";
//
// labelVersion
//
this.labelVersion.AutoSize = true;
this.labelVersion.Dock = System.Windows.Forms.DockStyle.Left;
this.labelVersion.Location = new System.Drawing.Point(135, 0);
this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(0, 66);
this.labelVersion.TabIndex = 1;
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// Settings
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "Settings";
this.Size = new System.Drawing.Size(1001, 381);
this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout();
this.flowLayoutToolbar.ResumeLayout(false);
this.flowLayoutToolbar.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private Label labelHeadIcon;
private Label labelHead;
private Panel panelSettings;
private FlowLayoutPanel flowLayoutToolbar;
private ToolTip toolTip;
private Button buttonAddCulture;
private Button buttonDeleteCulture;
private ContextMenuStrip contextMenuDelete;
private Label labelVersion;
}
}

View File

@ -1,68 +0,0 @@
using Processor;
using Version = Processor.Version;
namespace UI_WinForms.Components;
public partial class Settings : UserControl
{
public Settings()
{
this.InitializeComponent();
this.labelVersion.Text = Version.Text;
this.Load += async (sender, args) => await this.LoadAllSettings();
}
private async Task LoadAllSettings()
{
this.panelSettings.Controls.Clear();
foreach (var setting in Setting.GetAllSettings())
this.panelSettings.Controls.Add(await setting);
}
public bool NeedRestart()
{
// Iterate through all settings and check if any of them need a restart:
return this.panelSettings.Controls.Cast<Setting>().Any(setting => setting.NeedRestart);
}
private async void buttonAddCulture_Click(object sender, EventArgs e)
{
// Get the current indices of cultures:
var cultureIndices = await AppSettings.GetCultureIndices();
// Add a new culture:
await AppSettings.SetCultureCode(cultureIndices.Max() + 1, string.Empty);
// Reload all settings:
await this.LoadAllSettings();
}
private async void buttonDeleteCulture_Click(object sender, EventArgs e)
{
// Read all cultures:
var cultures = await AppSettings.GetCultureInfos();
// Populate the delete button's menu strip with all cultures:
this.contextMenuDelete.Items.Clear();
foreach (var culture in cultures)
{
var item = new ToolStripMenuItem($"{culture.Index}. Culture: {culture.Code}");
item.Tag = culture.Index;
item.Click += async (senderObj, args) =>
{
if (senderObj is not ToolStripMenuItem toolStripMenuItem)
return;
// Delete the culture:
await AppSettings.DeleteCulture((int)toolStripMenuItem.Tag);
// Reload all settings:
await this.LoadAllSettings();
};
this.contextMenuDelete.Items.Add(item);
}
this.contextMenuDelete.Show((Button)sender, new Point(0, (this.contextMenuDelete.Height + this.buttonDeleteCulture.Height / 2) * -1));
}
}

View File

@ -1,66 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="contextMenuDelete.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
</root>

View File

@ -1,250 +0,0 @@
namespace UI_WinForms.Components
{
partial class TextElements
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutToolbar = new System.Windows.Forms.FlowLayoutPanel();
this.buttonAdd = new System.Windows.Forms.Button();
this.buttonRemove = new System.Windows.Forms.Button();
this.buttonRename = new System.Windows.Forms.Button();
this.buttonChangeMultiLine = new System.Windows.Forms.Button();
this.buttonCopyKey = new System.Windows.Forms.Button();
this.textBoxFilter = new System.Windows.Forms.TextBox();
this.labelFilter = new System.Windows.Forms.Label();
this.labelSectionPath = new System.Windows.Forms.Label();
this.listTextElements = new System.Windows.Forms.ListView();
this.column = new System.Windows.Forms.ColumnHeader();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.tableLayout.SuspendLayout();
this.flowLayoutToolbar.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 3;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.flowLayoutToolbar, 0, 0);
this.tableLayout.Controls.Add(this.textBoxFilter, 2, 2);
this.tableLayout.Controls.Add(this.labelFilter, 1, 2);
this.tableLayout.Controls.Add(this.labelSectionPath, 1, 0);
this.tableLayout.Controls.Add(this.listTextElements, 1, 1);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 3;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
this.tableLayout.Size = new System.Drawing.Size(706, 370);
this.tableLayout.TabIndex = 0;
//
// flowLayoutToolbar
//
this.flowLayoutToolbar.Controls.Add(this.buttonAdd);
this.flowLayoutToolbar.Controls.Add(this.buttonRemove);
this.flowLayoutToolbar.Controls.Add(this.buttonRename);
this.flowLayoutToolbar.Controls.Add(this.buttonChangeMultiLine);
this.flowLayoutToolbar.Controls.Add(this.buttonCopyKey);
this.flowLayoutToolbar.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutToolbar.FlowDirection = System.Windows.Forms.FlowDirection.BottomUp;
this.flowLayoutToolbar.Location = new System.Drawing.Point(0, 0);
this.flowLayoutToolbar.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutToolbar.Name = "flowLayoutToolbar";
this.tableLayout.SetRowSpan(this.flowLayoutToolbar, 2);
this.flowLayoutToolbar.Size = new System.Drawing.Size(66, 330);
this.flowLayoutToolbar.TabIndex = 0;
//
// buttonAdd
//
this.buttonAdd.Enabled = false;
this.buttonAdd.FlatAppearance.BorderSize = 0;
this.buttonAdd.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonAdd.Image = global::UI_WinForms.Resources.Icons.icons8_add_tag_512;
this.buttonAdd.Location = new System.Drawing.Point(3, 267);
this.buttonAdd.Name = "buttonAdd";
this.buttonAdd.Size = new System.Drawing.Size(60, 60);
this.buttonAdd.TabIndex = 0;
this.toolTip.SetToolTip(this.buttonAdd, "Add text element to selected section");
this.buttonAdd.UseVisualStyleBackColor = true;
this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
//
// buttonRemove
//
this.buttonRemove.Enabled = false;
this.buttonRemove.FlatAppearance.BorderSize = 0;
this.buttonRemove.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonRemove.Image = global::UI_WinForms.Resources.Icons.icons8_remove_tag_512;
this.buttonRemove.Location = new System.Drawing.Point(3, 201);
this.buttonRemove.Name = "buttonRemove";
this.buttonRemove.Size = new System.Drawing.Size(60, 60);
this.buttonRemove.TabIndex = 2;
this.toolTip.SetToolTip(this.buttonRemove, "Delete this text element");
this.buttonRemove.UseVisualStyleBackColor = true;
this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
//
// buttonRename
//
this.buttonRename.Enabled = false;
this.buttonRename.FlatAppearance.BorderSize = 0;
this.buttonRename.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonRename.Image = global::UI_WinForms.Resources.Icons.icons8_rename_512;
this.buttonRename.Location = new System.Drawing.Point(3, 135);
this.buttonRename.Name = "buttonRename";
this.buttonRename.Size = new System.Drawing.Size(60, 60);
this.buttonRename.TabIndex = 1;
this.toolTip.SetToolTip(this.buttonRename, "Rename this text element");
this.buttonRename.UseVisualStyleBackColor = true;
this.buttonRename.Click += new System.EventHandler(this.buttonRename_Click);
//
// buttonChangeMultiLine
//
this.buttonChangeMultiLine.Enabled = false;
this.buttonChangeMultiLine.FlatAppearance.BorderSize = 0;
this.buttonChangeMultiLine.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonChangeMultiLine.Image = global::UI_WinForms.Resources.Icons.icons8_align_text_left_512;
this.buttonChangeMultiLine.Location = new System.Drawing.Point(3, 69);
this.buttonChangeMultiLine.Name = "buttonChangeMultiLine";
this.buttonChangeMultiLine.Size = new System.Drawing.Size(60, 60);
this.buttonChangeMultiLine.TabIndex = 3;
this.toolTip.SetToolTip(this.buttonChangeMultiLine, "Toggles the selected element\'s multi-line state");
this.buttonChangeMultiLine.UseVisualStyleBackColor = true;
this.buttonChangeMultiLine.Click += new System.EventHandler(this.buttonChangeMultiLine_Click);
//
// buttonCopyKey
//
this.buttonCopyKey.Enabled = false;
this.buttonCopyKey.FlatAppearance.BorderSize = 0;
this.buttonCopyKey.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonCopyKey.Image = global::UI_WinForms.Resources.Icons.icons8_key2_512;
this.buttonCopyKey.Location = new System.Drawing.Point(3, 3);
this.buttonCopyKey.Name = "buttonCopyKey";
this.buttonCopyKey.Size = new System.Drawing.Size(60, 60);
this.buttonCopyKey.TabIndex = 4;
this.toolTip.SetToolTip(this.buttonCopyKey, "Copy the key of the currently selected text element.");
this.buttonCopyKey.UseVisualStyleBackColor = true;
this.buttonCopyKey.Click += new System.EventHandler(this.buttonCopyKey_Click);
//
// textBoxFilter
//
this.textBoxFilter.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBoxFilter.Location = new System.Drawing.Point(149, 333);
this.textBoxFilter.Name = "textBoxFilter";
this.textBoxFilter.Size = new System.Drawing.Size(554, 29);
this.textBoxFilter.TabIndex = 2;
this.textBoxFilter.WordWrap = false;
this.textBoxFilter.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxFilter_KeyUp);
//
// labelFilter
//
this.labelFilter.AutoSize = true;
this.labelFilter.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelFilter.Location = new System.Drawing.Point(69, 330);
this.labelFilter.Name = "labelFilter";
this.labelFilter.Size = new System.Drawing.Size(74, 40);
this.labelFilter.TabIndex = 3;
this.labelFilter.Text = "Filter:";
this.labelFilter.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// labelSectionPath
//
this.labelSectionPath.AutoSize = true;
this.tableLayout.SetColumnSpan(this.labelSectionPath, 2);
this.labelSectionPath.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelSectionPath.Location = new System.Drawing.Point(69, 0);
this.labelSectionPath.Name = "labelSectionPath";
this.labelSectionPath.Size = new System.Drawing.Size(634, 40);
this.labelSectionPath.TabIndex = 4;
this.labelSectionPath.Text = "Path";
this.labelSectionPath.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.toolTip.SetToolTip(this.labelSectionPath, "The path of the currently selected section");
//
// listTextElements
//
this.listTextElements.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.column});
this.tableLayout.SetColumnSpan(this.listTextElements, 2);
this.listTextElements.Dock = System.Windows.Forms.DockStyle.Fill;
this.listTextElements.FullRowSelect = true;
this.listTextElements.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.listTextElements.Location = new System.Drawing.Point(69, 43);
this.listTextElements.MultiSelect = false;
this.listTextElements.Name = "listTextElements";
this.listTextElements.Size = new System.Drawing.Size(634, 284);
this.listTextElements.TabIndex = 5;
this.listTextElements.UseCompatibleStateImageBehavior = false;
this.listTextElements.View = System.Windows.Forms.View.SmallIcon;
this.listTextElements.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listTextElements_ItemSelectionChanged);
//
// column
//
this.column.Width = 194;
//
// toolTip
//
this.toolTip.AutoPopDelay = 30000;
this.toolTip.InitialDelay = 500;
this.toolTip.ReshowDelay = 100;
this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.toolTip.ToolTipTitle = "Help";
//
// TextElements
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "TextElements";
this.Size = new System.Drawing.Size(706, 370);
this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout();
this.flowLayoutToolbar.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private FlowLayoutPanel flowLayoutToolbar;
private Button buttonAdd;
private Button buttonRename;
private Button buttonRemove;
private ToolTip toolTip;
private TextBox textBoxFilter;
private Label labelFilter;
private Label labelSectionPath;
private ListView listTextElements;
private ColumnHeader column;
private Button buttonChangeMultiLine;
private Button buttonCopyKey;
}
}

View File

@ -1,271 +0,0 @@
using DataModel.Database;
using Processor;
using UI_WinForms.Dialogs;
using UI_WinForms.Resources;
namespace UI_WinForms.Components;
public partial class TextElements : UserControl
{
private Section? currentSection;
private TextElement? currentTextElement;
public TextElements()
{
this.InitializeComponent();
// Check if we are in the designer:
if(Program.SERVICE_PROVIDER is null)
return;
// Create an image list from a resource:
var imgList = new ImageList();
imgList.ImageSize = new Size(45, 45);
imgList.ColorDepth = ColorDepth.Depth32Bit;
imgList.Images.Add(Icons.icons8_row_512);
imgList.Images.Add(Icons.icons8_align_text_left_512);
// Set the image list to the list box:
this.listTextElements.SmallImageList = imgList;
// When the section is changed, update this component:
AppEvents.WhenSectionChanged += async (sender, section) =>
{
this.currentSection = section;
this.currentTextElement = null;
this.buttonAdd.Enabled = this.currentSection is not null;
this.buttonRename.Enabled = this.buttonRemove.Enabled = this.buttonChangeMultiLine.Enabled = this.buttonCopyKey.Enabled = false;
if (this.currentSection is null)
return;
// Update the path:
this.labelSectionPath.Text = await SectionProcessor.GetSectionPath(this.currentSection.DataKey);
await this.LoadTextElements();
};
// When the text element is changed, update the button states:
AppEvents.WhenTextElementChanged += (sender, textElement) =>
{
this.currentTextElement = textElement;
this.buttonRename.Enabled = this.buttonRemove.Enabled = this.buttonChangeMultiLine.Enabled = this.buttonCopyKey.Enabled = this.currentTextElement is not null;
if (this.currentTextElement is not null && this.currentTextElement.IsMultiLine)
this.buttonChangeMultiLine.Image = Icons.icons8_row_512;
else
this.buttonChangeMultiLine.Image = Icons.icons8_align_text_left_512;
};
AppEvents.WhenTranslationChanged += async (_, translation) =>
{
if (translation is null)
return;
// Check if the translation is in the current text element.
// When this is the case, update the list view item. We want
// to update the progress part.
if (this.currentTextElement?.Translations.Any(n => n.Id == translation.Id) ?? false)
{
// Determine the translation progress:
var progress = await TranslationProcessor.CalculateTranslationProgress(this.currentTextElement);
if (this.listTextElements.InvokeRequired)
this.listTextElements.Invoke(UpdateListElement);
else
UpdateListElement();
void UpdateListElement()
{
// Get the list view item by searching the TAG property:
var item = this.listTextElements.Items.Cast<ListViewItem>().FirstOrDefault(n => n.Tag is int id && id == this.currentTextElement.Id);
if (item is null)
return;
// Update the progress text:
item.Text = $"{this.currentTextElement.Name} [{progress.Result}%]";
}
}
};
// When the user press Ctrl + C, copy the text element's key to the clipboard:
this.listTextElements.KeyDown += (sender, e) =>
{
if (e is {Control: true, KeyCode: Keys.C})
this.buttonCopyKey.PerformClick();
};
}
// Loads all the text elements for the current section.
private async Task LoadTextElements()
{
if (this.currentSection is null)
return;
// Load the text elements:
var textElements = await TextElementProcessor.GetTextElements(this.currentSection, this.textBoxFilter.Text);
// Update the list:
this.listTextElements.Items.Clear();
foreach (var textElement in textElements)
{
// Determine the translation progress:
var progress = await TranslationProcessor.CalculateTranslationProgress(textElement);
this.listTextElements.Items.Add(new ListViewItem($"{textElement.Name} [{progress.Result}%]", textElement.IsMultiLine ? 1 : 0)
{
Tag = textElement.Id,
});
}
this.column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
}
private async void buttonAdd_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
var result = InputDialog.Show(new InputDialog.Options(
Message: "Please type the desired text element's name.",
Title: "Add a text element",
Placeholder: "My text element",
ShowQuestionCheckbox: true,
QuestionCheckboxText: "Is multi-line?"
));
if(result.DialogResult == DialogResult.Cancel)
return;
// Add the text element to the database into the current section:
var newTextElement = await TextElementProcessor.AddTextElement(this.currentSection?.DataKey, result.Text, result.AnswerToQuestion);
newTextElement.ProcessError();
if(!newTextElement.Successful)
return;
// Add the text element to the list:
this.listTextElements.Items.Add(new ListViewItem(newTextElement.Result!.Name, newTextElement.Result.IsMultiLine ? 1 : 0)
{
Tag = newTextElement.Result.Id,
});
this.column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
AppEvents.TranslationChanged(null);
}
private async void buttonRemove_Click(object sender, EventArgs e)
{
if(this.DesignMode || this.currentTextElement is null)
return;
// Ask the user, if he really wants to remove the text element:
if(MessageBox.Show(this.currentTextElement.Translations.Count > 0 ? $"Are you sure, you want to remove the text element '{this.currentTextElement.Name}', its {this.currentTextElement.Translations.Count} translations and so on?" : $"Are you sure, you want to remove the text element '{this.currentTextElement.Name}'?", "Remove text element", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)
return;
// Remove the text element from the database:
await TextElementProcessor.DeleteTextElement(this.currentTextElement.Id);
// Reload the data:
await this.LoadTextElements();
AppEvents.TranslationChanged(null);
}
private async void buttonRename_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
// Ask the user if he really wants to rename the text element:
if(MessageBox.Show("Are you sure, you want to rename the selected text element? If you are already using this element in your code, you will need to manually refactor your code after renaming it.", "Rename text element", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.No)
return;
// Ask the user for the new name:
var result = InputDialog.Show(new InputDialog.Options(
Message: "Please edit the text element's name.",
PreloadedText: this.currentTextElement!.Name,
ShowQuestionCheckbox: true,
Title: "Rename text element",
QuestionCheckboxText: "Is multi-line?",
QuestionCheckboxState: this.currentTextElement.IsMultiLine
));
// If the user canceled, return:
if(result.DialogResult == DialogResult.Cancel)
return;
ProcessorResult<TextElement> alteredTextElement;
if(this.currentTextElement.Name == result.Text)
// Update the multi-line state:
alteredTextElement = await TextElementProcessor.UpdateTextElementState(this.currentTextElement.Id, result.AnswerToQuestion);
else
// Rename the text element:
alteredTextElement = await TextElementProcessor.RenameTextElement(this.currentTextElement.Id, result.Text, result.AnswerToQuestion);
alteredTextElement.ProcessError();
if(!alteredTextElement.Successful)
return;
// Reload the text elements:
await this.LoadTextElements();
}
private async void buttonChangeMultiLine_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
// Update the multi-line state:
var alteredTextElement = await TextElementProcessor.UpdateTextElementState(this.currentTextElement!.Id, !this.currentTextElement.IsMultiLine);
alteredTextElement.ProcessError();
if(!alteredTextElement.Successful)
return;
// Reload the text elements:
await this.LoadTextElements();
// Re-select the text element:
foreach (ListViewItem item in this.listTextElements.Items)
{
if ((int)item.Tag == this.currentTextElement.Id)
{
item.Selected = true;
break;
}
}
}
private async void listTextElements_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected)
{
// Get the text element's id:
var selectedTextElementId = (int)e.Item.Tag;
// Load the text element:
this.currentTextElement = await TextElementProcessor.LoadTextElement(selectedTextElementId);
// Fire the event:
AppEvents.TextElementChanged(this.currentTextElement);
}
else
AppEvents.TextElementChanged(null);
}
private async void textBoxFilter_KeyUp(object sender, KeyEventArgs e) => await this.LoadTextElements();
private async void buttonCopyKey_Click(object sender, EventArgs e)
{
if(this.DesignMode || this.currentTextElement is null)
return;
Clipboard.SetText(await TextElementProcessor.GetKey(this.currentTextElement.Id));
//
// Switch the button's icon to the "ok" icon for a few
// seconds, to indicate, that the key was copied:
//
this.buttonCopyKey.Image = Icons.icons8_ok_512;
await Task.Delay(TimeSpan.FromSeconds(1));
this.buttonCopyKey.Image = Icons.icons8_key2_512;
}
}

View File

@ -1,63 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -1,156 +0,0 @@
namespace UI_WinForms.Components
{
sealed partial class Translation
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.labelHead = new System.Windows.Forms.Label();
this.textBox = new System.Windows.Forms.TextBox();
this.flowLayoutHeaderTools = new System.Windows.Forms.FlowLayoutPanel();
this.buttonDeepL = new System.Windows.Forms.Button();
this.checkBoxManual = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.tableLayout.SuspendLayout();
this.flowLayoutHeaderTools.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 2;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 366F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.labelHead, 0, 0);
this.tableLayout.Controls.Add(this.textBox, 0, 1);
this.tableLayout.Controls.Add(this.flowLayoutHeaderTools, 1, 0);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 2;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Size = new System.Drawing.Size(820, 279);
this.tableLayout.TabIndex = 0;
//
// labelHead
//
this.labelHead.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelHead.Location = new System.Drawing.Point(3, 0);
this.labelHead.Name = "labelHead";
this.labelHead.Size = new System.Drawing.Size(360, 66);
this.labelHead.TabIndex = 0;
this.labelHead.Text = "header";
this.labelHead.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// textBox
//
this.tableLayout.SetColumnSpan(this.textBox, 2);
this.textBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox.Location = new System.Drawing.Point(3, 69);
this.textBox.Multiline = true;
this.textBox.Name = "textBox";
this.textBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBox.Size = new System.Drawing.Size(814, 207);
this.textBox.TabIndex = 1;
this.textBox.TextChanged += new System.EventHandler(this.textBox_TextChanged);
//
// flowLayoutHeaderTools
//
this.flowLayoutHeaderTools.Controls.Add(this.buttonDeepL);
this.flowLayoutHeaderTools.Controls.Add(this.checkBoxManual);
this.flowLayoutHeaderTools.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutHeaderTools.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
this.flowLayoutHeaderTools.Location = new System.Drawing.Point(366, 0);
this.flowLayoutHeaderTools.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutHeaderTools.Name = "flowLayoutHeaderTools";
this.flowLayoutHeaderTools.Size = new System.Drawing.Size(454, 66);
this.flowLayoutHeaderTools.TabIndex = 3;
//
// buttonDeepL
//
this.buttonDeepL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonDeepL.AutoSize = true;
this.buttonDeepL.FlatAppearance.BorderSize = 0;
this.buttonDeepL.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonDeepL.Image = global::UI_WinForms.Resources.Icons.icons8_bot_512;
this.buttonDeepL.Location = new System.Drawing.Point(391, 3);
this.buttonDeepL.Name = "buttonDeepL";
this.buttonDeepL.Size = new System.Drawing.Size(60, 60);
this.buttonDeepL.TabIndex = 2;
this.toolTip.SetToolTip(this.buttonDeepL, "Auto-generate this text by using DeepL sourced by the source culture.");
this.buttonDeepL.UseVisualStyleBackColor = true;
this.buttonDeepL.Click += new System.EventHandler(this.buttonDeepL_Click);
//
// checkBoxManual
//
this.checkBoxManual.AutoSize = true;
this.checkBoxManual.Location = new System.Drawing.Point(188, 3);
this.checkBoxManual.Name = "checkBoxManual";
this.checkBoxManual.Padding = new System.Windows.Forms.Padding(0, 14, 0, 14);
this.checkBoxManual.Size = new System.Drawing.Size(197, 60);
this.checkBoxManual.TabIndex = 0;
this.checkBoxManual.Text = "Manual translation";
this.toolTip.SetToolTip(this.checkBoxManual, "Never overwrites this translation automatically");
this.checkBoxManual.UseVisualStyleBackColor = true;
this.checkBoxManual.CheckedChanged += new System.EventHandler(this.checkBoxManual_CheckedChanged);
//
// toolTip
//
this.toolTip.AutoPopDelay = 30000;
this.toolTip.InitialDelay = 500;
this.toolTip.ReshowDelay = 100;
this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.toolTip.ToolTipTitle = "Help";
//
// Translation
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "Translation";
this.Size = new System.Drawing.Size(820, 279);
this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout();
this.flowLayoutHeaderTools.ResumeLayout(false);
this.flowLayoutHeaderTools.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private Label labelHead;
private TextBox textBox;
private Button buttonDeepL;
private ToolTip toolTip;
private FlowLayoutPanel flowLayoutHeaderTools;
private CheckBox checkBoxManual;
}
}

View File

@ -1,187 +0,0 @@
using System.Timers;
using DataModel.Database;
using Processor;
using UI_WinForms.Resources;
using Timer = System.Timers.Timer;
namespace UI_WinForms.Components;
public sealed partial class Translation : UserControl
{
private readonly string culture = "en-US";
private readonly Timer saveTimer;
private readonly Timer translationTimer;
private bool isLoading = false;
private int currentTranslationId = -1;
private bool isDeepLSourceCulture = false;
private bool isManualOnlyMode = false;
private Translation? mainCultureTranslation = null;
public Translation()
{
this.InitializeComponent();
this.Dock = DockStyle.Top;
this.saveTimer = new Timer();
this.translationTimer = new Timer();
}
public Translation(AppSettings.CultureInfo cultureInfo)
{
this.InitializeComponent();
this.culture = cultureInfo.Code;
this.labelHead.Text = $"Culture: {cultureInfo.Code}";
this.Dock = DockStyle.Top;
this.saveTimer = new Timer
{
Enabled = false, // disable timer for now,
Interval = 1_000, // 1 second interval,
AutoReset = false, // runs only once
};
this.translationTimer = new Timer
{
Enabled = false, // disable timer for now,
Interval = 1_600, // 1.6 second interval,
AutoReset = false, // runs only once
};
this.saveTimer.Elapsed += this.SaveChanges;
this.translationTimer.Elapsed += this.TriggerTranslateNow;
this.Load += async (sender, args) => await this.LateSetup(cultureInfo);
}
private async Task LateSetup(AppSettings.CultureInfo cultureInfo)
{
this.isDeepLSourceCulture = await AppSettings.GetDeepLSourceCultureIndex() == cultureInfo.Index;
this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL);
this.checkBoxManual.Visible = !this.isDeepLSourceCulture;
this.buttonDeepL.Visible = await AppSettings.GetDeepLMode() != SettingDeepLMode.DISABLED;
this.buttonDeepL.Image = this.isDeepLSourceCulture ? Icons.icons8_trigger_1__svg : Icons.deepl_logo_icon_170284;
if (this.isDeepLSourceCulture)
{
this.labelHead.Text = $"Culture: {cultureInfo.Code} (DeepL source culture)";
this.toolTip.SetToolTip(this.buttonDeepL, "Replaces all other translations by DeepL translations using this culture as source culture.\nWarning: already translated texts will be replaced as well.");
if(this.Parent.Parent is Translations translations)
translations.RegisterMainCultureTranslationComponent(this);
}
}
public async Task Configure(DataModel.Database.Translation translation)
{
this.isLoading = true;
this.isManualOnlyMode = this.checkBoxManual.Checked = translation.TranslateManual;
this.currentTranslationId = translation.Id;
try
{
this.textBox.Text = translation.Text;
this.textBox.Multiline = translation.TextElement.IsMultiLine;
this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL);
if (this.isManualOnlyMode)
this.textBox.ReadOnly = false;
}
catch (ObjectDisposedException)
{
}
this.Height = translation.TextElement.IsMultiLine ? 280 : 106;
this.buttonDeepL.Visible = await AppSettings.GetDeepLMode() != SettingDeepLMode.DISABLED;
this.isLoading = false;
}
public void Clear()
{
this.isLoading = true;
this.currentTranslationId = -1;
this.textBox.Text = string.Empty;
this.textBox.Multiline = true;
this.Height = 280;
this.isLoading = false;
}
private async void textBox_TextChanged(object sender, EventArgs e)
{
if(this.isLoading)
return;
if(this.saveTimer.Enabled)
this.saveTimer.Stop();
this.saveTimer.Start();
if(this.ParentForm is UI_WinForms.Main main)
main.AddDeferredSaveOperation(this.currentTranslationId, () => this.SaveChanges(null, null));
if (this.isDeepLSourceCulture && await AppSettings.GetDeepLAction() == SettingDeepLAction.AUTOMATIC_ALL)
{
if (this.translationTimer.Enabled)
this.translationTimer.Stop();
this.translationTimer.Start();
}
}
private async void SaveChanges(object? sender, ElapsedEventArgs? e)
{
if (this.currentTranslationId > -1)
{
var storedTranslation = await TranslationProcessor.SaveChangedTranslation(this.currentTranslationId, this.textBox.Text, this.checkBoxManual.Checked);
AppEvents.TranslationChanged(storedTranslation.Result);
}
if(this.ParentForm is UI_WinForms.Main main)
main.RemoveDeferredSaveOperation(this.currentTranslationId);
this.isManualOnlyMode = this.checkBoxManual.Checked;
}
private async void TriggerTranslateNow(object? sender, ElapsedEventArgs? e)
{
if (this.currentTranslationId < 0 || this.isDeepLSourceCulture == false)
return;
if(this.Parent.Parent is Translations translations)
await translations.MainCultureWasChanged();
}
internal void SetMainCultureTranslation(Translation translation) => this.mainCultureTranslation = translation;
internal string GetCurrentText() => this.textBox.Text;
internal async Task Translate(bool wasManualTriggered = false)
{
if (this.mainCultureTranslation is null)
return;
if(this.isManualOnlyMode && !wasManualTriggered)
return;
var text = await Processor.DeepL.Translate(this.mainCultureTranslation.GetCurrentText(), this.culture);
if (this.textBox.InvokeRequired)
this.textBox.Invoke(() => this.textBox.Text = text);
else
this.textBox.Text = text;
}
private async void buttonDeepL_Click(object sender, EventArgs e)
{
if (this.isDeepLSourceCulture)
this.TriggerTranslateNow(null, null);
else
await this.Translate(wasManualTriggered: true);
}
private async void checkBoxManual_CheckedChanged(object sender, EventArgs e)
{
if(this.isLoading)
return;
this.SaveChanges(null, null);
this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL);
if (this.isManualOnlyMode)
this.textBox.ReadOnly = false;
}
}

View File

@ -1,63 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -1,65 +0,0 @@
namespace UI_WinForms.Components
{
sealed partial class TranslationProgress
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.nxProgressBar = new UI_WinForms.Components.NXProgressBar();
this.SuspendLayout();
//
// nxProgressBar
//
this.nxProgressBar.AppendPercentageToText = true;
this.nxProgressBar.BackColor = System.Drawing.Color.LightSkyBlue;
this.nxProgressBar.Dock = System.Windows.Forms.DockStyle.Fill;
this.nxProgressBar.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.nxProgressBar.InformationText = "Overall translation progress";
this.nxProgressBar.Location = new System.Drawing.Point(0, 0);
this.nxProgressBar.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.nxProgressBar.Name = "nxProgressBar";
this.nxProgressBar.Padding = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.nxProgressBar.PercentFloat = 0F;
this.nxProgressBar.PercentInt = 0;
this.nxProgressBar.Size = new System.Drawing.Size(832, 68);
this.nxProgressBar.TabIndex = 0;
//
// TranslationProgress
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.nxProgressBar);
this.Name = "TranslationProgress";
this.Size = new System.Drawing.Size(832, 68);
this.ResumeLayout(false);
}
#endregion
private NXProgressBar nxProgressBar;
}
}

View File

@ -1,38 +0,0 @@
using Processor;
namespace UI_WinForms.Components;
public sealed partial class TranslationProgress : UserControl
{
public TranslationProgress()
{
this.InitializeComponent();
this.DoubleBuffered = true;
this.Load += this.OnLoad;
AppEvents.WhenTranslationChanged += async (_, _) => await this.TranslationChanged();
}
private async void OnLoad(object? sender, EventArgs e) => await this.CalculateTranslationProgress();
private async Task TranslationChanged() => await this.CalculateTranslationProgress();
private async Task CalculateTranslationProgress()
{
var result = await TranslationProcessor.CalculateTranslationProgress();
if (this.nxProgressBar.InvokeRequired)
this.nxProgressBar.Invoke(() => SetProgress(result));
else
SetProgress(result);
void SetProgress(ProcessorResult<int> resultData)
{
if (resultData.Successful)
this.nxProgressBar.PercentInt = resultData.Result;
else
this.nxProgressBar.PercentInt = 0;
this.nxProgressBar.Refresh();
}
}
}

View File

@ -1,60 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,59 +0,0 @@
namespace UI_WinForms.Components
{
partial class Translations
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panelTranslations = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// panelTranslations
//
this.panelTranslations.AutoScroll = true;
this.panelTranslations.Dock = System.Windows.Forms.DockStyle.Fill;
this.panelTranslations.Location = new System.Drawing.Point(0, 0);
this.panelTranslations.Name = "panelTranslations";
this.panelTranslations.Size = new System.Drawing.Size(942, 462);
this.panelTranslations.TabIndex = 0;
//
// Translations
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.panelTranslations);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Name = "Translations";
this.Size = new System.Drawing.Size(942, 462);
this.ResumeLayout(false);
}
#endregion
private Panel panelTranslations;
}
}

View File

@ -1,115 +0,0 @@
using DataModel.Database;
using Processor;
using Timer = System.Timers.Timer;
namespace UI_WinForms.Components;
public partial class Translations : UserControl
{
private readonly Dictionary<string, Translation> translationComponents = new();
private readonly Timer clearTimer;
private Translation? mainCulture = null;
public Translations()
{
this.InitializeComponent();
this.Enabled = false;
this.clearTimer = new Timer
{
Enabled = false,
Interval = 600, // ms
AutoReset = false,
};
this.clearTimer.Elapsed += (sender, args) => this.ClearTranslations();
this.Load += async (sender, args) => await this.SetupTranslations();
AppEvents.WhenTextElementChanged += async (sender, textElement) =>
{
if(textElement is null)
{
this.clearTimer.Start();
return;
}
this.clearTimer.Stop();
if (!this.Enabled)
this.Enabled = true;
var allTranslations = await TranslationProcessor.GetTranslations(textElement);
foreach (var translation in allTranslations)
if (this.translationComponents.ContainsKey(translation.Culture))
await this.translationComponents[translation.Culture].Configure(translation);
};
AppEvents.WhenSectionChanged += (sender, section) => this.ClearTranslations();
}
private void ClearTranslations()
{
// Perform UI changes on the UI thread:
if (this.InvokeRequired)
{
this.Invoke(this.ClearTranslations);
return;
}
this.Enabled = false;
foreach (var (_, translation) in this.translationComponents)
translation.Clear();
}
private async Task SetupTranslations()
{
if(this.DesignMode)
return;
// Apply a custom order for the cultures. We want to show the default culture first,
// then the other cultures in order of their index. Please note: whatever we want to
// show as first, we have to return last!
async IAsyncEnumerable<AppSettings.CultureInfo> DesiredOrder()
{
// Get all configured cultures:
var cultureInfos = (await AppSettings.GetCultureInfos()).OrderByDescending(n => n.Index).ToList();
// Get the main culture:
var mainCultureIndex = await AppSettings.GetDeepLSourceCultureIndex();
// First, we return all the non-main cultures in descending order of their index:
foreach (var cultureInfo in cultureInfos.Where(n => n.Index != mainCultureIndex))
yield return cultureInfo;
// Last, we return the main culture:
if(cultureInfos.Any(n => n.Index == mainCultureIndex))
yield return cultureInfos.First(n => n.Index == mainCultureIndex);
}
await foreach (var cultureInfo in DesiredOrder())
{
var translationComponent = new Translation(cultureInfo);
this.translationComponents.Add(cultureInfo.Code, translationComponent);
this.panelTranslations.Controls.Add(translationComponent);
}
}
internal void RegisterMainCultureTranslationComponent(Translation trans)
{
this.mainCulture = trans;
// Register the main culture translation component into all the other
// translation components:
foreach (var (_, translation) in this.translationComponents.Where(n => n.Value != trans))
translation.SetMainCultureTranslation(trans);
}
internal async Task MainCultureWasChanged()
{
if(this.mainCulture is null || await AppSettings.GetDeepLMode() == SettingDeepLMode.DISABLED)
return;
var allTasks = new List<Task>();
foreach (var (_, translation) in this.translationComponents.Where(n => n.Value != this.mainCulture))
allTasks.Add(translation.Translate());
await Task.WhenAll(allTasks);
}
}

View File

@ -1,60 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,165 +0,0 @@
namespace UI_WinForms.Dialogs
{
partial class InputDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.labelHead = new System.Windows.Forms.Label();
this.flowLayoutBottom = new System.Windows.Forms.FlowLayoutPanel();
this.buttonOk = new System.Windows.Forms.Button();
this.buttonCancel = new System.Windows.Forms.Button();
this.textBoxInput = new System.Windows.Forms.TextBox();
this.checkBoxQuestion = new System.Windows.Forms.CheckBox();
this.tableLayout.SuspendLayout();
this.flowLayoutBottom.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.AutoSize = true;
this.tableLayout.ColumnCount = 1;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.labelHead, 0, 0);
this.tableLayout.Controls.Add(this.flowLayoutBottom, 0, 2);
this.tableLayout.Controls.Add(this.textBoxInput, 0, 1);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 4;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Size = new System.Drawing.Size(800, 139);
this.tableLayout.TabIndex = 0;
//
// labelHead
//
this.labelHead.AutoSize = true;
this.labelHead.Dock = System.Windows.Forms.DockStyle.Fill;
this.labelHead.Location = new System.Drawing.Point(3, 0);
this.labelHead.Name = "labelHead";
this.labelHead.Size = new System.Drawing.Size(794, 28);
this.labelHead.TabIndex = 0;
this.labelHead.Text = "header";
//
// flowLayoutBottom
//
this.flowLayoutBottom.Controls.Add(this.buttonOk);
this.flowLayoutBottom.Controls.Add(this.buttonCancel);
this.flowLayoutBottom.Controls.Add(this.checkBoxQuestion);
this.flowLayoutBottom.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutBottom.Location = new System.Drawing.Point(3, 68);
this.flowLayoutBottom.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.flowLayoutBottom.Name = "flowLayoutBottom";
this.flowLayoutBottom.Size = new System.Drawing.Size(797, 66);
this.flowLayoutBottom.TabIndex = 0;
//
// buttonOk
//
this.buttonOk.AutoSize = true;
this.buttonOk.Image = global::UI_WinForms.Resources.Icons.icons8_ok_512;
this.buttonOk.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonOk.Location = new System.Drawing.Point(3, 3);
this.buttonOk.Name = "buttonOk";
this.buttonOk.Size = new System.Drawing.Size(114, 60);
this.buttonOk.TabIndex = 1;
this.buttonOk.Text = "Ok";
this.buttonOk.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.buttonOk.UseVisualStyleBackColor = true;
this.buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
//
// buttonCancel
//
this.buttonCancel.AutoSize = true;
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.Image = global::UI_WinForms.Resources.Icons.icons8_cancel_512;
this.buttonCancel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonCancel.Location = new System.Drawing.Point(123, 3);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(124, 60);
this.buttonCancel.TabIndex = 2;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
this.buttonCancel.UseVisualStyleBackColor = true;
//
// textBoxInput
//
this.textBoxInput.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBoxInput.Location = new System.Drawing.Point(6, 31);
this.textBoxInput.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.textBoxInput.Name = "textBoxInput";
this.textBoxInput.Size = new System.Drawing.Size(791, 34);
this.textBoxInput.TabIndex = 1;
this.textBoxInput.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxInput_KeyUp);
//
// checkBoxIsRoot
//
this.checkBoxQuestion.AutoSize = true;
this.checkBoxQuestion.Dock = System.Windows.Forms.DockStyle.Left;
this.checkBoxQuestion.Location = new System.Drawing.Point(253, 3);
this.checkBoxQuestion.Name = "checkBoxQuestion";
this.checkBoxQuestion.Size = new System.Drawing.Size(458, 60);
this.checkBoxQuestion.TabIndex = 3;
this.checkBoxQuestion.UseVisualStyleBackColor = true;
//
// InputDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoSize = true;
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(800, 139);
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "InputDialog";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "InputDialog";
this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout();
this.flowLayoutBottom.ResumeLayout(false);
this.flowLayoutBottom.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private TableLayoutPanel tableLayout;
private Label labelHead;
private FlowLayoutPanel flowLayoutBottom;
private TextBox textBoxInput;
private Button buttonOk;
private Button buttonCancel;
private CheckBox checkBoxQuestion;
}
}

View File

@ -1,64 +0,0 @@
namespace UI_WinForms.Dialogs;
public partial class InputDialog : Form
{
public readonly record struct Options(
string Message,
string Title,
string Placeholder = "",
string PreloadedText = "",
string OkButtonText = "Ok",
string CancelButtonText = "Cancel",
bool ShowQuestionCheckbox = false,
string QuestionCheckboxText = "",
bool QuestionCheckboxState = false
);
private InputDialog()
{
this.InitializeComponent();
}
public static InputResult Show(Options options)
{
using var inputDialog = new InputDialog();
inputDialog.labelHead.Text = options.Message;
inputDialog.Text = options.Title;
inputDialog.textBoxInput.PlaceholderText = options.Placeholder;
inputDialog.textBoxInput.Text = options.PreloadedText;
inputDialog.buttonOk.Text = options.OkButtonText;
inputDialog.buttonCancel.Text = options.CancelButtonText;
inputDialog.checkBoxQuestion.Visible = options.ShowQuestionCheckbox;
inputDialog.checkBoxQuestion.Text = options.QuestionCheckboxText;
inputDialog.checkBoxQuestion.Checked = options.QuestionCheckboxState;
// Ensure, that the text box is focused on load:
inputDialog.textBoxInput.Select();
return new InputResult(
inputDialog.ShowDialog(),
inputDialog.textBoxInput.Text,
inputDialog.checkBoxQuestion.Checked
);
}
private void textBoxInput_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode is Keys.Enter or Keys.Return)
this.buttonOk.PerformClick();
}
private void buttonOk_Click(object sender, EventArgs e)
{
if(this.DesignMode)
return;
if (!string.IsNullOrWhiteSpace(this.textBoxInput.Text))
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
public readonly record struct InputResult(DialogResult DialogResult, string Text, bool AnswerToQuestion);
}

View File

@ -1,60 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,14 +0,0 @@
using Processor;
namespace UI_WinForms;
public static class ExtensionsError
{
public static void ProcessError<TResult>(this ProcessorResult<TResult> result)
{
if (result.Successful)
return;
MessageBox.Show(result.ErrorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

View File

@ -1,86 +0,0 @@
using UI_WinForms.Components;
namespace UI_WinForms
{
partial class Loader
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Loader));
this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.loaderStart = new UI_WinForms.Components.LoaderStart();
this.tableLayout.SuspendLayout();
this.SuspendLayout();
//
// tableLayout
//
this.tableLayout.ColumnCount = 1;
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayout.Controls.Add(this.loaderStart, 0, 0);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout";
this.tableLayout.RowCount = 1;
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayout.Size = new System.Drawing.Size(800, 450);
this.tableLayout.TabIndex = 0;
//
// loaderStart
//
this.loaderStart.Dock = System.Windows.Forms.DockStyle.Fill;
this.loaderStart.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.loaderStart.Location = new System.Drawing.Point(3, 3);
this.loaderStart.Name = "loaderStart";
this.loaderStart.Size = new System.Drawing.Size(794, 444);
this.loaderStart.TabIndex = 0;
this.loaderStart.LoadProject += new System.EventHandler<LoaderStart.LoaderResult>(this.loaderStart_LoadProject);
//
// Loader
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.tableLayout);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "Loader";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Loader";
this.tableLayout.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private TableLayoutPanel tableLayout;
private Components.LoaderStart loaderStart;
}
}

View File

@ -1,23 +0,0 @@
using UI_WinForms.Components;
namespace UI_WinForms;
public partial class Loader : Form
{
public LoaderStart.LoaderResult Result { get; private set; }
public Loader()
{
this.InitializeComponent();
}
private void loaderStart_LoadProject(object sender, LoaderStart.LoaderResult result)
{
if(this.DesignMode)
return;
this.Result = result;
this.DialogResult = DialogResult.OK;
this.Close();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +0,0 @@
namespace UI_WinForms
{
partial class Main
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
this.mainComponent = new UI_WinForms.Components.Main();
this.SuspendLayout();
//
// mainComponent
//
this.mainComponent.Dock = System.Windows.Forms.DockStyle.Fill;
this.mainComponent.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.mainComponent.Location = new System.Drawing.Point(0, 0);
this.mainComponent.Name = "mainComponent";
this.mainComponent.Size = new System.Drawing.Size(1902, 1033);
this.mainComponent.TabIndex = 0;
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(1902, 1033);
this.Controls.Add(this.mainComponent);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "Main";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "I18N Commander";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Main_FormClosing);
this.ResumeLayout(false);
}
#endregion
private Components.Main mainComponent;
}
}

View File

@ -1,33 +0,0 @@
namespace UI_WinForms;
public partial class Main : Form
{
private readonly Dictionary<int, Action> deferredSaveOperations = new();
public Main()
{
this.InitializeComponent();
}
private void Main_FormClosing(object sender, FormClosingEventArgs e)
{
foreach (var (_, action) in this.deferredSaveOperations)
action();
this.deferredSaveOperations.Clear();
}
internal void AddDeferredSaveOperation(int id, Action action)
{
if (this.deferredSaveOperations.ContainsKey(id))
this.deferredSaveOperations.Remove(id);
this.deferredSaveOperations.Add(id, action);
}
internal void RemoveDeferredSaveOperation(int id)
{
if (this.deferredSaveOperations.ContainsKey(id))
this.deferredSaveOperations.Remove(id);
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More