phase 1
This commit is contained in:
58
ModVersionChecker/ui/controls/DirectoryPickerControl.cs
Normal file
58
ModVersionChecker/ui/controls/DirectoryPickerControl.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ModVersionChecker.controls
|
||||
{
|
||||
public class DirectoryPickerControl : UserControl
|
||||
{
|
||||
private readonly TextBox _textBox;
|
||||
private readonly Button _browseButton;
|
||||
|
||||
public string SelectedPath
|
||||
{
|
||||
get => _textBox.Text;
|
||||
set => _textBox.Text = value;
|
||||
}
|
||||
|
||||
public DirectoryPickerControl()
|
||||
{
|
||||
_textBox = new TextBox
|
||||
{
|
||||
Width = 300,
|
||||
ReadOnly = true,
|
||||
Dock = DockStyle.Fill
|
||||
};
|
||||
|
||||
_browseButton = new Button
|
||||
{
|
||||
Text = "Browse",
|
||||
Width = 80,
|
||||
Dock = DockStyle.Right
|
||||
};
|
||||
|
||||
_browseButton.Click += (s, e) =>
|
||||
{
|
||||
using var folderDialog = new FolderBrowserDialog();
|
||||
folderDialog.Description = "Select directory";
|
||||
if (folderDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
SelectedPath = folderDialog.SelectedPath;
|
||||
}
|
||||
};
|
||||
|
||||
var panel = new TableLayoutPanel
|
||||
{
|
||||
ColumnCount = 2,
|
||||
Dock = DockStyle.Fill,
|
||||
AutoSize = true
|
||||
};
|
||||
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 80));
|
||||
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20));
|
||||
panel.Controls.Add(_textBox, 0, 0);
|
||||
panel.Controls.Add(_browseButton, 1, 0);
|
||||
|
||||
Controls.Add(panel);
|
||||
AutoSize = true;
|
||||
}
|
||||
}
|
||||
}
|
74
ModVersionChecker/ui/forms/AppDetailsForm.cs
Normal file
74
ModVersionChecker/ui/forms/AppDetailsForm.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using ModVersionChecker.managers.interfaces;
|
||||
using ModVersionChecker.service.interfaces;
|
||||
|
||||
namespace ModVersionChecker.ui.forms
|
||||
{
|
||||
public class AppDetailsForm : Form
|
||||
{
|
||||
private TextBox _searchBox;
|
||||
private ListBox _resultsList;
|
||||
private Button _addButton;
|
||||
private readonly IApiService _apiService;
|
||||
private readonly IAppsManager _appsManager;
|
||||
public App? SelectedApp { get; private set; }
|
||||
|
||||
public event EventHandler<string> OnAppAdded;
|
||||
|
||||
public AppDetailsForm(IApiService apiService, IAppsManager appsManager)
|
||||
{
|
||||
_apiService = apiService ?? throw new ArgumentNullException(nameof(apiService));
|
||||
_appsManager = appsManager ?? throw new ArgumentNullException(nameof(appsManager));
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
Text = "Search and Add App";
|
||||
Width = 400;
|
||||
Height = 500;
|
||||
Padding = new Padding(20);
|
||||
|
||||
_searchBox = new TextBox { Dock = DockStyle.Top, PlaceholderText = "Search..." };
|
||||
_resultsList = new ListBox { Dock = DockStyle.Fill };
|
||||
_addButton = new Button { Text = "Add Selected", Dock = DockStyle.Bottom, Enabled = false };
|
||||
|
||||
_searchBox.TextChanged += async (s, e) => await UpdateResultsAync();
|
||||
_resultsList.SelectedIndexChanged += (s, e) => _addButton.Enabled = _resultsList.SelectedItem != null;
|
||||
_resultsList.DoubleClick += (s, e) => AddSelected();
|
||||
_addButton.Click += (s, e) => AddSelected();
|
||||
|
||||
Controls.Add(_resultsList);
|
||||
Controls.Add(_addButton);
|
||||
Controls.Add(_searchBox);
|
||||
}
|
||||
|
||||
private async Task UpdateResultsAync()
|
||||
{
|
||||
var query = _searchBox.Text.Trim().ToLower();
|
||||
if (query.Length < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(query))
|
||||
{
|
||||
_resultsList.DataSource = null;
|
||||
return;
|
||||
}
|
||||
var results = await _apiService.SearchApps(query);
|
||||
_resultsList.DataSource = results;
|
||||
_resultsList.DisplayMember = "Name";
|
||||
}
|
||||
|
||||
private void AddSelected()
|
||||
{
|
||||
if (_resultsList.SelectedItem is App app)
|
||||
{
|
||||
SelectedApp = app;
|
||||
_appsManager.Insert(app);
|
||||
DialogResult = DialogResult.OK;
|
||||
OnAppAdded?.Invoke(this, "App saved");
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
ModVersionChecker/ui/forms/AppDetailsForm.resx
Normal file
120
ModVersionChecker/ui/forms/AppDetailsForm.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<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>
|
70
ModVersionChecker/ui/forms/FormFactory.cs
Normal file
70
ModVersionChecker/ui/forms/FormFactory.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ModVersionChecker.managers.interfaces;
|
||||
using ModVersionChecker.service.interfaces;
|
||||
|
||||
namespace ModVersionChecker.ui.forms
|
||||
{
|
||||
public class FormFactory : IFormFactory
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public FormFactory(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||
}
|
||||
|
||||
public AppDetailsForm CreateAppDetailsForm(App? app, bool isEditable, EventHandler<string>? onAppSaved)
|
||||
{
|
||||
var apiService = _serviceProvider.GetRequiredService<IApiService>();
|
||||
var appsManager = _serviceProvider.GetRequiredService<IAppsManager>();
|
||||
var form = new AppDetailsForm(apiService, appsManager);
|
||||
if (onAppSaved != null)
|
||||
{
|
||||
form.OnAppAdded += onAppSaved;
|
||||
}
|
||||
return form;
|
||||
}
|
||||
|
||||
public GlobalConfigForm CreateGlobalConfigForm()
|
||||
{
|
||||
var configManager = _serviceProvider.GetRequiredService<IConfigManager>();
|
||||
return new GlobalConfigForm(configManager);
|
||||
}
|
||||
|
||||
public TypeConfigForm CreateTypeConfigForm()
|
||||
{
|
||||
var typeManager = _serviceProvider.GetRequiredService<ITypeManager>();
|
||||
var apiService = _serviceProvider.GetRequiredService<IApiService>();
|
||||
var configManager = _serviceProvider.GetRequiredService<IConfigManager>();
|
||||
return new TypeConfigForm(typeManager, apiService, configManager);
|
||||
}
|
||||
|
||||
//public SourcesConfigForm CreateSourcesConfigForm(EventHandler<string>? onSourcesChanged)
|
||||
//{
|
||||
// var sourcesDefManager = _serviceProvider.GetRequiredService<ISourcesDefManager>();
|
||||
// var formFactory = _serviceProvider.GetRequiredService<IFormFactory>();
|
||||
// var form = new SourcesConfigForm(formFactory, sourcesDefManager);
|
||||
// if (onSourcesChanged != null)
|
||||
// {
|
||||
// form.OnSourcesChanged += onSourcesChanged;
|
||||
// }
|
||||
// return form;
|
||||
//}
|
||||
|
||||
//public SourceDetailForm CreateSourceDetailForm(SourceDef? sourceDef, EventHandler<string>? onSourceChanged)
|
||||
//{
|
||||
// var sourcesDefManager = _serviceProvider.GetRequiredService<ISourcesDefManager>();
|
||||
// var checkerTypesDefManager = _serviceProvider.GetRequiredService<ICheckerTypesDefManager>();
|
||||
// var formFactory = _serviceProvider.GetRequiredService<IFormFactory>();
|
||||
// var form = new SourceDetailForm(formFactory, sourcesDefManager);
|
||||
// form.SourceDef = sourceDef;
|
||||
|
||||
// if (onSourceChanged != null)
|
||||
// {
|
||||
// form.UpdateFields();
|
||||
// form.OnSourceChanged += onSourceChanged;
|
||||
// }
|
||||
// return form;
|
||||
//}
|
||||
}
|
||||
}
|
151
ModVersionChecker/ui/forms/GlobalConfigForm.cs
Normal file
151
ModVersionChecker/ui/forms/GlobalConfigForm.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using ModVersionChecker.managers.interfaces;
|
||||
using ModVersionChecker.model;
|
||||
|
||||
namespace ModVersionChecker.ui.forms
|
||||
{
|
||||
public class GlobalConfigForm : Form
|
||||
{
|
||||
private IConfigManager _configManager;
|
||||
private Config _config;
|
||||
|
||||
private Label _millislabel, _checkStartupLabel, _runOnStartupLabel;
|
||||
private TrackBar _millisField;
|
||||
private CheckBox _checkStartupField, _runOnStartupField;
|
||||
private Button _saveButton, _cancelButton;
|
||||
private TableLayoutPanel _mainLayout, _configsPanel;
|
||||
private FlowLayoutPanel _buttonPanel;
|
||||
|
||||
public GlobalConfigForm(IConfigManager configManager)
|
||||
{
|
||||
_configManager = configManager;
|
||||
_config = _configManager.GetConfig();
|
||||
this.Load += GlobalConfigForm_Load;
|
||||
}
|
||||
|
||||
private void GlobalConfigForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
// Load existing configurations if needed
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
SuspendLayout();
|
||||
|
||||
ClientSize = new System.Drawing.Size(600, 250);
|
||||
Name = "GlobalConfigForm";
|
||||
Text = "Global Configuration";
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
Padding = new Padding(10, 20, 10, 20 );
|
||||
_mainLayout = GetMainLayout();
|
||||
_configsPanel = GetConfigsPanel();
|
||||
|
||||
_buttonPanel = GetButtonsPanel();
|
||||
|
||||
_mainLayout.Controls.Add(_configsPanel, 0, 0);
|
||||
_mainLayout.Controls.Add(_buttonPanel, 0, 1);
|
||||
|
||||
Controls.Add(_mainLayout);
|
||||
|
||||
|
||||
ResumeLayout(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private FlowLayoutPanel GetButtonsPanel()
|
||||
{
|
||||
var buttonsPanel = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, AutoSize = true, Dock = DockStyle.Fill };
|
||||
_saveButton = new Button { Text = "Save", AutoSize = true };
|
||||
_saveButton.Click += (sender, e) =>
|
||||
{
|
||||
_config.IntervalMinutes = _millisField.Value;
|
||||
_config.CheckOnStartup = _checkStartupField.Checked;
|
||||
_config.RunOnStartup = _runOnStartupField.Checked;
|
||||
_configManager.Save(_config);
|
||||
DialogResult = DialogResult.OK;
|
||||
UpdateStartupSetting(_config.RunOnStartup);
|
||||
Close();
|
||||
};
|
||||
_cancelButton = new Button { Text = "Cancel", AutoSize = true };
|
||||
_cancelButton.Click += (sender, e) =>
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
};
|
||||
buttonsPanel.Controls.Add(_saveButton);
|
||||
buttonsPanel.Controls.Add(_cancelButton);
|
||||
return buttonsPanel;
|
||||
}
|
||||
|
||||
private TableLayoutPanel GetConfigsPanel()
|
||||
{
|
||||
// Initialize the configurations panel
|
||||
var configsPanel = new TableLayoutPanel
|
||||
{
|
||||
AutoSize = true,
|
||||
Dock = DockStyle.Fill,
|
||||
ColumnCount = 2,
|
||||
RowCount = 2,
|
||||
ColumnStyles = { new ColumnStyle(SizeType.Absolute, 150), new ColumnStyle(SizeType.Percent, 100) }
|
||||
};
|
||||
|
||||
_millislabel = new Label { Text = "Millis", Width = 150};
|
||||
_millisField = new TrackBar { Minimum = 0, Maximum = 120, Value= _config.IntervalMinutes, Width = 300, TickStyle = TickStyle.None };
|
||||
FlowLayoutPanel millisPanel = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, AutoSize = true };
|
||||
Label millisValue = new Label { Text = _millisField.Value.ToString() + " minutes", AutoSize = true, Padding = new Padding(10, 10, 0, 0) };
|
||||
millisPanel.Controls.Add(_millisField);
|
||||
millisPanel.Controls.Add(millisValue);
|
||||
|
||||
_millisField.Scroll += (sender, e) => { millisValue.Text = _millisField.Value.ToString() + " minutes"; };
|
||||
|
||||
_checkStartupLabel = new Label { Text = "Check on Application Start:", Width = 150 };
|
||||
_checkStartupField = new CheckBox { Checked = _config.CheckOnStartup };
|
||||
_runOnStartupLabel= new Label { Text = "Run on Windows Startup:", Width = 150 };
|
||||
_runOnStartupField = new CheckBox { Checked = _config.RunOnStartup };
|
||||
|
||||
configsPanel.Controls.Add(_millislabel, 0, 0);
|
||||
configsPanel.Controls.Add(millisPanel, 1, 0);
|
||||
configsPanel.Controls.Add(_checkStartupLabel, 0, 1);
|
||||
configsPanel.Controls.Add(_checkStartupField, 1, 1);
|
||||
configsPanel.Controls.Add(_runOnStartupLabel, 0, 2);
|
||||
configsPanel.Controls.Add(_runOnStartupField, 1, 2);
|
||||
|
||||
return configsPanel;
|
||||
}
|
||||
|
||||
private TableLayoutPanel GetMainLayout()
|
||||
{
|
||||
// Initialize the main layout panel
|
||||
var mainLayout = new TableLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
RowCount = 2,
|
||||
ColumnCount = 1
|
||||
};
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 150)); // Paths panel height
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50)); // Button panel height
|
||||
Controls.Add(mainLayout);
|
||||
return mainLayout;
|
||||
}
|
||||
|
||||
private void UpdateStartupSetting(bool runOnStartup)
|
||||
{
|
||||
using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true))
|
||||
{
|
||||
if (runOnStartup)
|
||||
{
|
||||
key?.SetValue("XintanalabsUpdateChecker", $"\"{Application.ExecutablePath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
key?.DeleteValue("XintanalabsUpdateChecker", false); // Remove if unchecked
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add methods and properties for global configuration management here
|
||||
|
||||
}
|
||||
}
|
14
ModVersionChecker/ui/forms/IFormFactory.cs
Normal file
14
ModVersionChecker/ui/forms/IFormFactory.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
namespace ModVersionChecker.ui.forms
|
||||
{
|
||||
public interface IFormFactory
|
||||
{
|
||||
AppDetailsForm CreateAppDetailsForm(App? app, bool isEditable, EventHandler<string>? onAppChanged);
|
||||
GlobalConfigForm CreateGlobalConfigForm();
|
||||
TypeConfigForm CreateTypeConfigForm();
|
||||
|
||||
//SourcesConfigForm CreateSourcesConfigForm(EventHandler<string>? onSourcesChanged);
|
||||
|
||||
//SourceDetailForm CreateSourceDetailForm(SourceDef? sourceDef, EventHandler<string>? onSourceChanged);
|
||||
}
|
||||
}
|
316
ModVersionChecker/ui/forms/MainForm.cs
Normal file
316
ModVersionChecker/ui/forms/MainForm.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using ModVersionChecker.enums;
|
||||
using ModVersionChecker.managers.interfaces;
|
||||
using ModVersionChecker.model;
|
||||
using ModVersionChecker.repository.api.dto;
|
||||
using ModVersionChecker.service.interfaces;
|
||||
using ModVersionChecker.utils;
|
||||
|
||||
|
||||
namespace ModVersionChecker.ui.forms
|
||||
{
|
||||
public class MainForm : Form
|
||||
{
|
||||
private readonly IAppsManager _appsManager;
|
||||
private readonly IFormFactory _formFactory;
|
||||
private readonly IFlightSimsManager _fsManager;
|
||||
private readonly IApiService _apiService;
|
||||
private readonly IVersionService _versionService;
|
||||
private readonly TableLayoutPanel _mainLayout;
|
||||
|
||||
private readonly Config _globalConfig;
|
||||
private List<App> _apps = new List<App>();
|
||||
private ListView _listView;
|
||||
private ImageList _statusImageList = new ImageList();
|
||||
|
||||
public event EventHandler<EventArgs> OnConfigChanged;
|
||||
public event EventHandler<string> OnRecheck;
|
||||
private EventHandler<string> onAppSavedHandler;
|
||||
private MenuStrip _menuStrip;
|
||||
private List<TypeResponse> _fsMods;
|
||||
private readonly Dictionary<string, TextBox> _fsModPathTextBoxes = new Dictionary<string, TextBox>();
|
||||
|
||||
private List<SourceResponse> _sources = new List<SourceResponse>();
|
||||
private List<TypeResponse> _typesDef = new List<TypeResponse>();
|
||||
|
||||
public MainForm(
|
||||
IConfigManager configManager,
|
||||
IAppsManager appsManager,
|
||||
IFormFactory formFactory,
|
||||
IFlightSimsManager fsManager,
|
||||
IApiService apiService,
|
||||
ITypeManager typeConfigManager,
|
||||
IVersionService versionService)
|
||||
{
|
||||
_appsManager = appsManager ?? throw new ArgumentNullException(nameof(appsManager));
|
||||
_formFactory = formFactory ?? throw new ArgumentNullException(nameof(formFactory));
|
||||
_fsManager = fsManager ?? throw new ArgumentNullException(nameof(fsManager));
|
||||
_apiService = apiService ?? throw new ArgumentNullException(nameof(apiService));
|
||||
_versionService = versionService ?? throw new ArgumentNullException(nameof(versionService));
|
||||
_fsMods = _fsManager.Load();
|
||||
|
||||
_statusImageList.Images.Add("none", new Icon("Resources/ok-icon.ico"));
|
||||
_statusImageList.Images.Add("update", new Icon("Resources/up-icon.ico"));
|
||||
_statusImageList.Images.Add("error", new Icon("Resources/error-icon.ico"));
|
||||
|
||||
Text = "Update Checker Configuration";
|
||||
Size = new Size(600, 800);
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
|
||||
_globalConfig = configManager.Load() ?? new Config();
|
||||
|
||||
_mainLayout = GetMainLayout();
|
||||
|
||||
_listView = GetListView();
|
||||
_listView.SmallImageList = _statusImageList;
|
||||
|
||||
_mainLayout.Controls.Add(_listView , 0, 0);
|
||||
|
||||
_mainLayout.Controls.Add(GetButtonsPanel(), 0, 1);
|
||||
|
||||
onAppSavedHandler = (s2, e) =>
|
||||
{
|
||||
var form = s2 as AppDetailsForm;
|
||||
if (form == null || form.SelectedApp == null) return;
|
||||
|
||||
var app = form.SelectedApp;
|
||||
UpdateCurrentVersion(app);
|
||||
UpdateListView();
|
||||
OnConfigChanged?.Invoke(this, EventArgs.Empty);
|
||||
};
|
||||
|
||||
this.Load += MainForm_LoadAsync;
|
||||
}
|
||||
|
||||
private void UpdateCurrentVersion(App app)
|
||||
{
|
||||
TypeConfig? typeConfig = _globalConfig.Types.FirstOrDefault(tc => app.Type == tc.ShortName);
|
||||
if (typeConfig == null) return;
|
||||
var versionInDisk = VersionUtils.GetCurrentVersion(app, typeConfig);
|
||||
|
||||
if (!string.IsNullOrEmpty(versionInDisk))
|
||||
{
|
||||
app.CurrentVersion = versionInDisk;
|
||||
app.LastCheckedAt = TimeUtils.GetUnixTimeMillis(DateTime.Now);
|
||||
|
||||
_versionService.CheckApp(app);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async void MainForm_LoadAsync(object? sender, EventArgs e)
|
||||
{
|
||||
await _apiService.AuthenticateAsync("user", "user");
|
||||
_apps = await _apiService.GetAppsByIds([]);
|
||||
_sources = await _apiService.GetSources();
|
||||
_typesDef = await _apiService.GetTypes();
|
||||
UpdateListView();
|
||||
}
|
||||
|
||||
private TableLayoutPanel GetMainLayout()
|
||||
{
|
||||
// Initialize the main layout panel
|
||||
var mainLayout = new TableLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
RowCount = 2,
|
||||
ColumnCount = 1
|
||||
};
|
||||
// mainLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 150)); // Paths panel height
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 70)); // ListView takes remaining space
|
||||
mainLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50)); // Button panel height
|
||||
Controls.Add(mainLayout);
|
||||
InitializeMenu();
|
||||
return mainLayout;
|
||||
}
|
||||
|
||||
private ListView GetListView()
|
||||
{
|
||||
var listView = new ListView
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
View = View.Details,
|
||||
FullRowSelect = true,
|
||||
MultiSelect = false,
|
||||
Visible = true,
|
||||
Sorting = SortOrder.Ascending
|
||||
};
|
||||
|
||||
listView.Columns.Add("Name", 150);
|
||||
listView.Columns.Add("MSFS Versions", 100);
|
||||
listView.Columns.Add("Current", 80);
|
||||
listView.Columns.Add("Latest", 80);
|
||||
listView.Columns.Add("Last Checked", 150);
|
||||
|
||||
listView.DoubleClick += (s, e) =>
|
||||
{
|
||||
if (listView.SelectedItems.Count > 0)
|
||||
{
|
||||
ListViewItem selectedItem = listView.SelectedItems[0];
|
||||
App? app = selectedItem.Tag as App;
|
||||
if (app == null) return;
|
||||
if (app.Status == AppStatus.UPDATE_AVAILABLE)
|
||||
{
|
||||
if (string.IsNullOrEmpty(app.DownloadUrl))
|
||||
{
|
||||
MessageBox.Show("No download URL specified for this app.");
|
||||
return;
|
||||
}
|
||||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = app.DownloadUrl,
|
||||
UseShellExecute = true
|
||||
});
|
||||
} else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
return listView;
|
||||
}
|
||||
|
||||
private FlowLayoutPanel GetButtonsPanel() {
|
||||
var buttonPanel = new FlowLayoutPanel { Dock = DockStyle.Fill };
|
||||
var addButton = new Button { Text = "Add App" };
|
||||
var deleteButton = new Button { Text = "Delete App", Enabled = false };
|
||||
var recheckButton = new Button { Text = "Recheck Versions" };
|
||||
|
||||
addButton.Click += (s, e) =>
|
||||
{
|
||||
var form = _formFactory.CreateAppDetailsForm(null, true, onAppSavedHandler); // Use factory
|
||||
form.ShowDialog();
|
||||
};
|
||||
deleteButton.Click += (s, e) =>
|
||||
{
|
||||
if (_listView.SelectedItems.Count > 0 && _listView.SelectedItems[0].Tag != null)
|
||||
{
|
||||
var app = _listView.SelectedItems[0].Tag as App;
|
||||
DeleteApp(app);
|
||||
}
|
||||
};
|
||||
_listView.SelectedIndexChanged += (s, e) =>
|
||||
{
|
||||
deleteButton.Enabled = _listView.SelectedItems.Count > 0;
|
||||
};
|
||||
|
||||
// Add recheck logic here
|
||||
recheckButton.Click += async (s, e) =>
|
||||
{
|
||||
recheckButton.Enabled = false;
|
||||
await _versionService.CheckAllApps();
|
||||
UpdateListView();
|
||||
//OnRecheck.Invoke(this, "User initiated recheck from ConfigForm");
|
||||
recheckButton.Enabled = true;
|
||||
};
|
||||
|
||||
buttonPanel.Controls.AddRange(new[] { addButton, deleteButton, recheckButton });
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
public void UpdateListView()
|
||||
{
|
||||
_apps = _appsManager.Load();
|
||||
_listView.Items.Clear();
|
||||
foreach (var app in _apps)
|
||||
{
|
||||
var item = new ListViewItem(app.Name);
|
||||
try {
|
||||
item.Tag = app;
|
||||
item.SubItems.Add(app.Type);
|
||||
|
||||
var currentVersion = app.CurrentVersion;
|
||||
var latestVersion = app.LatestVersion;
|
||||
var lastChecked = TimeUtils.ToFriendlyTime(app.LastCheckedAt);
|
||||
item.SubItems.Add(currentVersion);
|
||||
item.SubItems.Add(latestVersion);
|
||||
item.SubItems.Add(lastChecked);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
item.SubItems.Add($"Error: {ex.Message}");
|
||||
}
|
||||
|
||||
switch (app.Status)
|
||||
{
|
||||
case AppStatus.UPDATE_AVAILABLE:
|
||||
item.ImageKey = "update";
|
||||
break;
|
||||
case AppStatus.ERROR:
|
||||
item.ImageKey = "error";
|
||||
break;
|
||||
default:
|
||||
item.ImageKey = "none";
|
||||
break;
|
||||
}
|
||||
_listView.Items.Add(item);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteApp(App app)
|
||||
{
|
||||
var result = MessageBox.Show($"Are you sure you want to delete '{app?.Name ?? ""}'?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
_appsManager.Delete((_listView.SelectedItems[0].Tag as App).Id);
|
||||
UpdateListView();
|
||||
OnConfigChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeMenu()
|
||||
{
|
||||
_menuStrip = new MenuStrip();
|
||||
|
||||
// Create top-level menu
|
||||
var configMenu = new ToolStripMenuItem("Configuration");
|
||||
|
||||
// Add sub-menu items
|
||||
var settingsItem = new ToolStripMenuItem("Settings");
|
||||
settingsItem.Click += (s, e) => ShowGlobalConfigDialog();
|
||||
|
||||
var typesItem = new ToolStripMenuItem("Types");
|
||||
typesItem.Click += (s, e) => ShowTypesConfigForm();
|
||||
|
||||
//var sourcesConfigItem = new ToolStripMenuItem("Sources");
|
||||
//sourcesConfigItem.Click += (s, e) => ShowSourcesConfigDialog();
|
||||
|
||||
//var FlightSimsConfigItem = new ToolStripMenuItem("Flight Sims");
|
||||
//FlightSimsConfigItem.Click += (s, e) => MessageBox.Show("Flight Sims configuration dialog would open here.");
|
||||
|
||||
configMenu.DropDownItems.Add(settingsItem);
|
||||
configMenu.DropDownItems.Add(typesItem);
|
||||
// configMenu.DropDownItems.Add(sourcesConfigItem);
|
||||
// configMenu.DropDownItems.Add(FlightSimsConfigItem);
|
||||
|
||||
_menuStrip.Items.Add(configMenu);
|
||||
|
||||
// Add the menu to the form
|
||||
Controls.Add(_menuStrip);
|
||||
MainMenuStrip = _menuStrip;
|
||||
}
|
||||
|
||||
private void ShowTypesConfigForm()
|
||||
{
|
||||
var typesConfigForm = _formFactory.CreateTypeConfigForm();
|
||||
typesConfigForm.ShowDialog();
|
||||
}
|
||||
|
||||
private void ShowGlobalConfigDialog()
|
||||
{
|
||||
// Show your global config form/dialog here
|
||||
var globalConfigForm = _formFactory.CreateGlobalConfigForm();
|
||||
globalConfigForm.ShowDialog();
|
||||
}
|
||||
|
||||
//private void ShowSourcesConfigDialog()
|
||||
//{
|
||||
// EventHandler<string> onSourcesChanged = (s, e) => MessageBox.Show("Sources Changed");
|
||||
// var form = _formFactory.CreateSourcesConfigForm(onSourcesChanged);
|
||||
// form.ShowDialog();
|
||||
//}
|
||||
}
|
||||
}
|
120
ModVersionChecker/ui/forms/MainForm.resx
Normal file
120
ModVersionChecker/ui/forms/MainForm.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<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>
|
145
ModVersionChecker/ui/forms/TypeConfigForm.cs
Normal file
145
ModVersionChecker/ui/forms/TypeConfigForm.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using ModVersionChecker.controls;
|
||||
using ModVersionChecker.managers.interfaces;
|
||||
using ModVersionChecker.model;
|
||||
using ModVersionChecker.repository.api.dto;
|
||||
using ModVersionChecker.service.interfaces;
|
||||
using ModVersionChecker.utils;
|
||||
|
||||
namespace ModVersionChecker.ui.forms
|
||||
{
|
||||
public class TypeConfigForm : Form
|
||||
{
|
||||
private List<TypeResponse> _typeDefs;
|
||||
private List<TypeConfig> _typeConfigs;
|
||||
private Config _globalConfig;
|
||||
|
||||
private readonly Dictionary<string, CheckBox> _typeCheckBoxes = new();
|
||||
private readonly Dictionary<string, Panel> _typePanels = new();
|
||||
private readonly Dictionary<(string typeId, string fieldName), Control> _fieldControls = new();
|
||||
private FlowLayoutPanel _mainPanel;
|
||||
private Button _saveButton, _cancelButton;
|
||||
private readonly IApiService _apiService;
|
||||
private readonly IConfigManager _configManager;
|
||||
private readonly ITypeManager _typeManager;
|
||||
|
||||
public TypeConfigForm(
|
||||
ITypeManager typeManager,
|
||||
IApiService apiService,
|
||||
IConfigManager configManager
|
||||
)
|
||||
{
|
||||
_apiService = apiService ?? throw new ArgumentNullException(nameof(apiService));
|
||||
_configManager = configManager ?? throw new ArgumentNullException(nameof(configManager));
|
||||
_typeManager = typeManager ?? throw new ArgumentNullException(nameof(typeManager));
|
||||
Load += TypeConfigForm_LoadAsync;
|
||||
|
||||
}
|
||||
|
||||
public async void TypeConfigForm_LoadAsync(object sender, EventArgs e)
|
||||
{
|
||||
_typeDefs = await _apiService.GetTypes();
|
||||
_typeConfigs = _typeManager.GetTypeConfigs();
|
||||
_globalConfig = _configManager.Load();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
Text = "Configure Types";
|
||||
Width = 600;
|
||||
Height = 700;
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
_mainPanel = new FlowLayoutPanel { Dock = DockStyle.Top, AutoScroll = true, FlowDirection = FlowDirection.TopDown, WrapContents = false, Width = 580, Height = 600 };
|
||||
|
||||
foreach (var typeDef in _typeDefs)
|
||||
{
|
||||
var isInConfig = _globalConfig.Types.Any(t => t.Id == typeDef.Id);
|
||||
var typeConfig = _globalConfig.Types.FirstOrDefault(tc => tc.Id == typeDef.Id);
|
||||
var checkBox = new CheckBox {
|
||||
Text = typeDef.Name,
|
||||
Checked = isInConfig,
|
||||
Enabled = !isInConfig,
|
||||
AutoSize = true
|
||||
};
|
||||
_typeCheckBoxes[typeDef.Id] = checkBox;
|
||||
var panel = new Panel {
|
||||
Visible = checkBox.Checked,
|
||||
AutoSize = false,
|
||||
BorderStyle = BorderStyle.FixedSingle,
|
||||
Width = _mainPanel.Width - 20, // leave some margin
|
||||
Height = 0 // will be set by content
|
||||
};
|
||||
_typePanels[typeDef.Id] = panel;
|
||||
|
||||
checkBox.CheckedChanged += (s, e) => { panel.Visible = checkBox.Checked; };
|
||||
|
||||
var fieldsLayout = new TableLayoutPanel {
|
||||
ColumnCount = 2,
|
||||
AutoSize = true,
|
||||
Dock = DockStyle.Top
|
||||
};
|
||||
foreach (var field in typeDef.ConfigFields)
|
||||
{
|
||||
fieldsLayout.RowCount++;
|
||||
fieldsLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||||
fieldsLayout.Controls.Add(new Label {
|
||||
Text = $"{field.Label ?? field.Name} {field.ControlType}",
|
||||
AutoSize = true
|
||||
}, 0, fieldsLayout.RowCount - 1);
|
||||
|
||||
|
||||
|
||||
var filedInput = InputControlsFactory.CreateControl(field, typeConfig, !isInConfig);
|
||||
_fieldControls[(typeDef.Id, field.Name)] = filedInput;
|
||||
fieldsLayout.Controls.Add(filedInput, 1, fieldsLayout.RowCount - 1);
|
||||
}
|
||||
panel.Controls.Add(fieldsLayout);
|
||||
panel.Height = fieldsLayout.PreferredSize.Height + 10;
|
||||
_mainPanel.Controls.Add(checkBox);
|
||||
_mainPanel.Controls.Add(panel);
|
||||
}
|
||||
|
||||
_saveButton = new Button { Text = "Save", AutoSize = true };
|
||||
_saveButton.Click += (s, e) => { SaveConfigs(); };
|
||||
_cancelButton = new Button { Text = "Cancel", AutoSize = true };
|
||||
_cancelButton.Click += (s, e) => { DialogResult = DialogResult.Cancel; Close(); };
|
||||
var buttonPanel = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, Dock = DockStyle.Bottom, AutoSize = true };
|
||||
buttonPanel.Controls.Add(_saveButton);
|
||||
buttonPanel.Controls.Add(_cancelButton);
|
||||
|
||||
Controls.Add(_mainPanel);
|
||||
Controls.Add(buttonPanel);
|
||||
}
|
||||
|
||||
private void SaveConfigs()
|
||||
{
|
||||
var result = new List<TypeConfig>();
|
||||
foreach (var typeDef in _typeDefs)
|
||||
{
|
||||
if (_typeCheckBoxes[typeDef.Id].Checked)
|
||||
{
|
||||
var config = new TypeConfig { Id = typeDef.Id, Name = typeDef.Name, ShortName = typeDef.ShortName, ConfigValues = new Dictionary<string, string>() };
|
||||
foreach (var field in typeDef.ConfigFields)
|
||||
{
|
||||
if (_fieldControls.TryGetValue((typeDef.Id, field.Name), out var ctrl))
|
||||
{
|
||||
if (ctrl is DirectoryPickerControl)
|
||||
{
|
||||
config.ConfigValues[field.Name] = (ctrl as DirectoryPickerControl).SelectedPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.ConfigValues[field.Name] = ctrl.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.Add(config);
|
||||
}
|
||||
}
|
||||
_globalConfig.Types = result;
|
||||
_configManager.Save(_globalConfig);
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user