convert launcher to file scoped namespaces

pull/32/head
Miepee 4 years ago
parent dba7aca5f1
commit 328f74b03c

@ -6,223 +6,222 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Net; using System.Net;
namespace AM2RLauncher namespace AM2RLauncher;
/// <summary>
/// Class that checks for Updates and then Updates the Launcher.
/// </summary>
//TODO: Mac support for auto updater in general
public static class LauncherUpdater
{ {
/// <summary> // How often this was broken count: 7
/// Class that checks for Updates and then Updates the Launcher. // Auto updating is fun!
/// </summary>
//TODO: Mac support for auto updater in general
public static class LauncherUpdater
{
// How often this was broken count: 7
// Auto updating is fun!
/// <summary>The Version that identifies this current release.</summary> /// <summary>The Version that identifies this current release.</summary>
public const string VERSION = Core.Version; public const string VERSION = Core.Version;
/// <summary>The Path of the oldConfig. Only gets used Windows-only</summary> /// <summary>The Path of the oldConfig. Only gets used Windows-only</summary>
private static readonly string oldConfigPath = CrossPlatformOperations.CurrentPath + "/" + CrossPlatformOperations.LauncherName + ".oldCfg"; private static readonly string oldConfigPath = CrossPlatformOperations.CurrentPath + "/" + CrossPlatformOperations.LauncherName + ".oldCfg";
/// <summary>The actual Path where the executable is stored, only used for updating.</summary> /// <summary>The actual Path where the executable is stored, only used for updating.</summary>
private static readonly string updatePath = OS.IsWindows ? CrossPlatformOperations.CurrentPath private static readonly string updatePath = OS.IsWindows ? CrossPlatformOperations.CurrentPath
: (OS.IsLinux ? Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) : Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory + "../../../")); : (OS.IsLinux ? Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) : Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory + "../../../"));
/// <summary> /// <summary>
/// Our log object, that handles logging the current execution to a file. /// Our log object, that handles logging the current execution to a file.
/// </summary> /// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(LauncherUpdater)); private static readonly ILog log = LogManager.GetLogger(typeof(LauncherUpdater));
/// <summary> /// <summary>
/// Performs the entire AM2RLauncher update procedure. /// Performs the entire AM2RLauncher update procedure.
/// </summary> /// </summary>
public static void Main() public static void Main()
{ {
log.Info("Running update check..."); log.Info("Running update check...");
// Update section // Update section
// Clean old files that have been left // Clean old files that have been left
if (File.Exists(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak")) if (File.Exists(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak"))
{ {
log.Info("AM2RLauncher.bak detected. Removing file."); log.Info("AM2RLauncher.bak detected. Removing file.");
File.Delete(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak"); File.Delete(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak");
} }
if (OS.IsWindows && File.Exists(oldConfigPath)) if (OS.IsWindows && File.Exists(oldConfigPath))
{ {
log.Info(CrossPlatformOperations.LauncherName + ".oldCfg detected. Removing file."); log.Info(CrossPlatformOperations.LauncherName + ".oldCfg detected. Removing file.");
File.Delete(oldConfigPath); File.Delete(oldConfigPath);
} }
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/oldLib")) if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/oldLib"))
{
log.Info("Old lib folder detected, removing folder.");
Directory.Delete(CrossPlatformOperations.CurrentPath + "/oldLib", true);
}
// Clean up old update libs
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/lib"))
{
foreach (FileInfo file in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetFiles())
{ {
log.Info("Old lib folder detected, removing folder."); if (file.Name.EndsWith(".bak"))
Directory.Delete(CrossPlatformOperations.CurrentPath + "/oldLib", true); file.Delete();
} }
// Clean up old update libs // Do the same for each subdirectory
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/lib")) foreach (DirectoryInfo dir in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetDirectories())
{ {
foreach (FileInfo file in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetFiles()) foreach (FileInfo file in dir.GetFiles())
{ {
if (file.Name.EndsWith(".bak")) if (file.Name.EndsWith(".bak"))
file.Delete(); file.Delete();
} }
// Do the same for each subdirectory
foreach (DirectoryInfo dir in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetDirectories())
{
foreach (FileInfo file in dir.GetFiles())
{
if (file.Name.EndsWith(".bak"))
file.Delete();
}
}
} }
}
// Check settings if autoUpdateLauncher is set to true // Check settings if autoUpdateLauncher is set to true
bool autoUpdate = Boolean.Parse(MainForm.ReadFromConfig("AutoUpdateLauncher")); bool autoUpdate = Boolean.Parse(MainForm.ReadFromConfig("AutoUpdateLauncher"));
if (autoUpdate) if (autoUpdate)
{ {
log.Info("AutoUpdate Launcher set to true!"); log.Info("AutoUpdate Launcher set to true!");
// This is supposed to fix the updater throwing an exception on windows 7 and earlier(?) // This is supposed to fix the updater throwing an exception on windows 7 and earlier(?)
// See this for information: https://stackoverflow.com/q/2859790 and https://stackoverflow.com/a/50977774 // See this for information: https://stackoverflow.com/q/2859790 and https://stackoverflow.com/a/50977774
if (OS.IsWindows) if (OS.IsWindows)
{ {
ServicePointManager.Expect100Continue = true; ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
} }
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest");
HttpWebResponse response; HttpWebResponse response;
try try
{ {
response = (HttpWebResponse)request.GetResponse(); response = (HttpWebResponse)request.GetResponse();
} }
catch (WebException) catch (WebException)
{ {
log.Error("WebException caught! Displaying MessageBox."); log.Error("WebException caught! Displaying MessageBox.");
MessageBox.Show(Language.Text.NoInternetConnection); MessageBox.Show(Language.Text.NoInternetConnection);
return; return;
} }
Uri realUri = response.ResponseUri; Uri realUri = response.ResponseUri;
string onlineVersion = realUri.AbsoluteUri.Substring(realUri.AbsoluteUri.LastIndexOf('/') + 1); string onlineVersion = realUri.AbsoluteUri.Substring(realUri.AbsoluteUri.LastIndexOf('/') + 1);
bool isCurrentVersionOutdated = false; bool isCurrentVersionOutdated = false;
string[] localVersionArray = VERSION.Split('.'); string[] localVersionArray = VERSION.Split('.');
string[] onlineVersionArray = onlineVersion.Split('.'); string[] onlineVersionArray = onlineVersion.Split('.');
for (int i = 0; i < localVersionArray.Length; i++) for (int i = 0; i < localVersionArray.Length; i++)
{
int onlineNum = Int32.Parse(onlineVersionArray[i]);
int localNum = Int32.Parse(localVersionArray[i]);
if (onlineNum > localNum)
{ {
int onlineNum = Int32.Parse(onlineVersionArray[i]); isCurrentVersionOutdated = true;
int localNum = Int32.Parse(localVersionArray[i]); break;
if (onlineNum > localNum)
{
isCurrentVersionOutdated = true;
break;
}
if (localNum > onlineNum)
break;
} }
if (localNum > onlineNum)
break;
}
log.Info((isCurrentVersionOutdated ? "Updating" : "Not Updating") + " from " + VERSION + " to " + onlineVersion); log.Info((isCurrentVersionOutdated ? "Updating" : "Not Updating") + " from " + VERSION + " to " + onlineVersion);
// No new update, exiting // No new update, exiting
if (!isCurrentVersionOutdated) if (!isCurrentVersionOutdated)
return; return;
// For mac, we just show a message box that a new version is available, because I don't want to support it yet. // For mac, we just show a message box that a new version is available, because I don't want to support it yet.
// hardcoded string, since also temporarily until it gets supported one day. // hardcoded string, since also temporarily until it gets supported one day.
if (OS.IsMac) if (OS.IsMac)
{ {
MessageBox.Show("Your current version is outdated! The newest version is " + onlineVersion + "." + MessageBox.Show("Your current version is outdated! The newest version is " + onlineVersion + "." +
"Please recompile AM2RLauncher again or disable auto-updating"); "Please recompile AM2RLauncher again or disable auto-updating");
return; return;
} }
log.Info("Current version (" + VERSION + ") is outdated! Initiating update for version " + onlineVersion + "."); log.Info("Current version (" + VERSION + ") is outdated! Initiating update for version " + onlineVersion + ".");
string tmpUpdatePath = CrossPlatformOperations.CurrentPath + "/tmpupdate/"; string tmpUpdatePath = CrossPlatformOperations.CurrentPath + "/tmpupdate/";
string zipPath = CrossPlatformOperations.CurrentPath + "/launcher.zip"; string zipPath = CrossPlatformOperations.CurrentPath + "/launcher.zip";
// Clean tmpupdate // Clean tmpupdate
if (Directory.Exists(tmpUpdatePath)) if (Directory.Exists(tmpUpdatePath))
Directory.Delete(tmpUpdatePath, true); Directory.Delete(tmpUpdatePath, true);
if (!Directory.Exists(tmpUpdatePath)) if (!Directory.Exists(tmpUpdatePath))
Directory.CreateDirectory(tmpUpdatePath); Directory.CreateDirectory(tmpUpdatePath);
try try
{ {
using var client = new WebClient(); using var client = new WebClient();
string platformSuffix = ""; string platformSuffix = "";
if (OS.IsWindows) platformSuffix = "_win"; if (OS.IsWindows) platformSuffix = "_win";
else if (OS.IsLinux) platformSuffix = "_lin"; else if (OS.IsLinux) platformSuffix = "_lin";
log.Info("Downloading https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest/download/AM2RLauncher_" + onlineVersion + platformSuffix + ".zip to " + zipPath + "."); log.Info("Downloading https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest/download/AM2RLauncher_" + onlineVersion + platformSuffix + ".zip to " + zipPath + ".");
client.DownloadFile("https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest/download/AM2RLauncher_" + onlineVersion + platformSuffix + ".zip", zipPath); client.DownloadFile("https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest/download/AM2RLauncher_" + onlineVersion + platformSuffix + ".zip", zipPath);
log.Info("File successfully downloaded."); log.Info("File successfully downloaded.");
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)
{ {
log.Error("UnauthorizedAccessException caught! Displaying MessageBox."); log.Error("UnauthorizedAccessException caught! Displaying MessageBox.");
MessageBox.Show(Language.Text.UnauthorizedAccessMessage); MessageBox.Show(Language.Text.UnauthorizedAccessMessage);
return; return;
} }
ZipFile.ExtractToDirectory(zipPath, tmpUpdatePath);
log.Info("Updates successfully extracted to " + tmpUpdatePath);
ZipFile.ExtractToDirectory(zipPath, tmpUpdatePath); File.Delete(zipPath);
log.Info("Updates successfully extracted to " + tmpUpdatePath); File.Move(updatePath + "/" + CrossPlatformOperations.LauncherName, CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak");
if (OS.IsWindows) File.Move(CrossPlatformOperations.LauncherName + ".config", CrossPlatformOperations.LauncherName + ".oldCfg");
File.Delete(zipPath); foreach (var file in new DirectoryInfo(tmpUpdatePath).GetFiles())
File.Move(updatePath + "/" + CrossPlatformOperations.LauncherName, CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak"); {
if (OS.IsWindows) File.Move(CrossPlatformOperations.LauncherName + ".config", CrossPlatformOperations.LauncherName + ".oldCfg"); log.Info("Moving " + file.FullName + " to " + CrossPlatformOperations.CurrentPath + "/" + file.Name);
File.Copy(file.FullName, updatePath + "/" + file.Name, true);
}
// For windows, the actual application is in "AM2RLauncher.dll". Which means, we need to update the lib folder as well.
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/lib"))
{
// So, because Windows behavior is dumb...
foreach (var file in new DirectoryInfo(tmpUpdatePath).GetFiles()) // Rename all files in lib to *.bak
foreach (FileInfo file in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetFiles())
{ {
log.Info("Moving " + file.FullName + " to " + CrossPlatformOperations.CurrentPath + "/" + file.Name); file.CopyTo(file.Directory + "/" + file.Name + ".bak");
File.Copy(file.FullName, updatePath + "/" + file.Name, true);
} }
// For windows, the actual application is in "AM2RLauncher.dll". Which means, we need to update the lib folder as well.
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/lib"))
{
// So, because Windows behavior is dumb...
// Rename all files in lib to *.bak // Do the same for each sub directory
foreach (FileInfo file in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetFiles()) foreach (DirectoryInfo dir in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetDirectories())
{ {
file.CopyTo(file.Directory + "/" + file.Name + ".bak"); foreach (FileInfo file in dir.GetFiles())
}
// Do the same for each sub directory
foreach (DirectoryInfo dir in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetDirectories())
{ {
foreach (FileInfo file in dir.GetFiles()) file.CopyTo(file.Directory + "/" + file.Name + ".bak");
{
file.CopyTo(file.Directory + "/" + file.Name + ".bak");
}
} }
// Yes, the above calls could be recursive. No, I can't be bothered to make them as such.
if (Directory.Exists(tmpUpdatePath + "lib"))
HelperMethods.DirectoryCopy(tmpUpdatePath + "lib", CrossPlatformOperations.CurrentPath + "/lib");
} }
Directory.Delete(tmpUpdatePath, true); // Yes, the above calls could be recursive. No, I can't be bothered to make them as such.
if (Directory.Exists(tmpUpdatePath + "lib"))
HelperMethods.DirectoryCopy(tmpUpdatePath + "lib", CrossPlatformOperations.CurrentPath + "/lib");
}
MainForm.CopyOldConfigToNewConfig(); Directory.Delete(tmpUpdatePath, true);
log.Info("Files extracted. Preparing to restart executable..."); MainForm.CopyOldConfigToNewConfig();
if (OS.IsLinux) System.Diagnostics.Process.Start("chmod", "+x " + updatePath + "./AM2RLauncher.Gtk");
System.Diagnostics.Process.Start(updatePath + "/" + CrossPlatformOperations.LauncherName); log.Info("Files extracted. Preparing to restart executable...");
Environment.Exit(0); if (OS.IsLinux) System.Diagnostics.Process.Start("chmod", "+x " + updatePath + "./AM2RLauncher.Gtk");
}
else System.Diagnostics.Process.Start(updatePath + "/" + CrossPlatformOperations.LauncherName);
{ Environment.Exit(0);
log.Info("AutoUpdate Launcher set to false. Exiting update check."); }
} else
{
log.Info("AutoUpdate Launcher set to false. Exiting update check.");
} }
} }
} }

@ -2,73 +2,72 @@
using Eto.Forms; using Eto.Forms;
using Pablo.Controls; using Pablo.Controls;
namespace AM2RLauncher namespace AM2RLauncher;
/// <summary>
/// Extension of <see cref="CustomButton"/> that allows for advanced color settings.
/// </summary>
class ColorButton : CustomButton
{ {
/// <summary> /// <summary>The <see cref="Color"/> to draw the background with when <see cref="CustomButton.Hover"/> is true.</summary>
/// Extension of <see cref="CustomButton"/> that allows for advanced color settings. public Color BackgroundColorHover { get; set; }
/// </summary>
class ColorButton : CustomButton
{
/// <summary>The <see cref="Color"/> to draw the background with when <see cref="CustomButton.Hover"/> is true.</summary>
public Color BackgroundColorHover { get; set; }
/// <summary>The <see cref="Font"/> to use for text drawing.</summary> /// <summary>The <see cref="Font"/> to use for text drawing.</summary>
public Font Font { get; set; } public Font Font { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the frame.</summary> /// <summary>The <see cref="Color"/> with which to draw the frame.</summary>
public Color FrameColor { get; set; } public Color FrameColor { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the frame when it is disabled.</summary> /// <summary>The <see cref="Color"/> with which to draw the frame when it is disabled.</summary>
public Color FrameColorDisabled { get; set; } public Color FrameColorDisabled { get; set; }
/// <summary>The text to be drawn.</summary> /// <summary>The text to be drawn.</summary>
public string Text { get; set; } public string Text { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/>.</summary> /// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/>.</summary>
public Color TextColor { get; set; } public Color TextColor { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/> when it is disabled.</summary> /// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/> when it is disabled.</summary>
public Color TextColorDisabled { get; set; } public Color TextColorDisabled { get; set; }
/// <summary> /// <summary>
/// Creates a <see cref="ColorButton"/> with a default set of attributes. /// Creates a <see cref="ColorButton"/> with a default set of attributes.
/// </summary> /// </summary>
public ColorButton() public ColorButton()
{ {
BackgroundColorHover = Colors.White; BackgroundColorHover = Colors.White;
Font = new Font(SystemFont.Default, 12); Font = new Font(SystemFont.Default, 12);
FrameColor = Colors.White; FrameColor = Colors.White;
FrameColorDisabled = Colors.Gray; FrameColorDisabled = Colors.Gray;
Text = ""; Text = "";
TextColor = Colors.Black; TextColor = Colors.Black;
TextColorDisabled = Colors.Gray; TextColorDisabled = Colors.Gray;
} }
/// <summary> /// <summary>
/// Event raised to draw this control. /// Event raised to draw this control.
/// </summary> /// </summary>
/// <param name="pe"></param> /// <param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe) protected override void OnPaint(PaintEventArgs pe)
{ {
// Define draw bounds // Define draw bounds
Rectangle drawBounds = new Rectangle(2, 2, Width - 5, Height - 5); Rectangle drawBounds = new Rectangle(2, 2, Width - 5, Height - 5);
// Draw background // Draw background
pe.Graphics.FillRectangle(Hover ? BackgroundColorHover : BackgroundColor, drawBounds); pe.Graphics.FillRectangle(Hover ? BackgroundColorHover : BackgroundColor, drawBounds);
// Draw frame // Draw frame
Pen framePen = new Pen(Enabled ? FrameColor : FrameColorDisabled, 1); Pen framePen = new Pen(Enabled ? FrameColor : FrameColorDisabled, 1);
pe.Graphics.DrawRectangle(framePen, drawBounds); pe.Graphics.DrawRectangle(framePen, drawBounds);
SolidBrush brush = new SolidBrush(Enabled ? TextColor : TextColorDisabled); SolidBrush brush = new SolidBrush(Enabled ? TextColor : TextColorDisabled);
// Get text measurements // Get text measurements
SizeF stringSize = pe.Graphics.MeasureString(Font, Text); SizeF stringSize = pe.Graphics.MeasureString(Font, Text);
int textWidth = (int)stringSize.Width; int textWidth = (int)stringSize.Width;
int textHeight = (int)stringSize.Height; int textHeight = (int)stringSize.Height;
// Draw text // Draw text
pe.Graphics.DrawText(Font, brush, new PointF(Width / 2 - textWidth / 2, Height / 2 - textHeight / 2), Text); pe.Graphics.DrawText(Font, brush, new PointF(Width / 2 - textWidth / 2, Height / 2 - textHeight / 2), Text);
}
} }
} }

@ -2,190 +2,189 @@
using Eto.Forms; using Eto.Forms;
using System; using System;
namespace Pablo.Controls namespace Pablo.Controls;
/// <summary>
/// A custom button implementation for advanced drawing and events.
/// Originally written by cwensley (https://gist.github.com/cwensley/95000998e37acd93e830),
/// modified by Lojemiru and Miepee for use in the AM2RLauncher.
/// </summary>
public class CustomButton : Drawable
{ {
/// <summary> /// <summary>Whether or not this <see cref="CustomButton"/> is being pressed.</summary>
/// A custom button implementation for advanced drawing and events. bool pressed;
/// Originally written by cwensley (https://gist.github.com/cwensley/95000998e37acd93e830),
/// modified by Lojemiru and Miepee for use in the AM2RLauncher.
/// </summary>
public class CustomButton : Drawable
{
/// <summary>Whether or not this <see cref="CustomButton"/> is being pressed.</summary>
bool pressed;
/// <summary>Whether or not the mouse is hovering over this <see cref="CustomButton"/>.</summary> /// <summary>Whether or not the mouse is hovering over this <see cref="CustomButton"/>.</summary>
bool hover; bool hover;
/// <summary></summary> /// <summary></summary>
bool mouseDown; bool mouseDown;
/// <summary>Gets or sets the disabled color of this control.</summary> /// <summary>Gets or sets the disabled color of this control.</summary>
public static Color DisabledColor = Color.FromGrayscale(0.4f, 0.3f); public static Color DisabledColor = Color.FromGrayscale(0.4f, 0.3f);
/// <summary>Gets or sets the color of this control.</summary> /// <summary>Gets or sets the color of this control.</summary>
public static Color EnabledColor = Colors.Black; public static Color EnabledColor = Colors.Black;
/// <summary>Gets or sets whether or not this control is enabled.</summary> /// <summary>Gets or sets whether or not this control is enabled.</summary>
public override bool Enabled public override bool Enabled
{
get { return base.Enabled; }
set
{ {
get { return base.Enabled; } if (base.Enabled != value)
set
{ {
if (base.Enabled != value) base.Enabled = value;
{ if (Loaded)
base.Enabled = value; Invalidate();
if (Loaded)
Invalidate();
}
} }
} }
}
/// <summary>Gets or sets <see cref="pressed"/>.</summary> /// <summary>Gets or sets <see cref="pressed"/>.</summary>
public bool Pressed public bool Pressed
{
get { return pressed; }
set
{ {
get { return pressed; } if (pressed != value)
set
{ {
if (pressed != value) pressed = value;
{ mouseDown = false;
pressed = value; if (Loaded)
mouseDown = false; Invalidate();
if (Loaded)
Invalidate();
}
} }
} }
}
/// <summary>Gets <see cref="hover"/>.</summary> /// <summary>Gets <see cref="hover"/>.</summary>
public bool Hover public bool Hover
{ {
get { return hover; } get { return hover; }
} }
/// <summary>Gets either the <see cref="EnabledColor"/> or <see cref="DisabledColor"/> dependent on <see cref="Enabled"/>.</summary> /// <summary>Gets either the <see cref="EnabledColor"/> or <see cref="DisabledColor"/> dependent on <see cref="Enabled"/>.</summary>
public Color DrawColor public Color DrawColor
{ {
get { return Enabled ? EnabledColor : DisabledColor; } get { return Enabled ? EnabledColor : DisabledColor; }
} }
/// <summary>Gets or sets whether or not this control should act as a toggle.</summary> /// <summary>Gets or sets whether or not this control should act as a toggle.</summary>
public bool Toggle { get; set; } public bool Toggle { get; set; }
/// <summary>Gets or sets whether or not this control is persistent.</summary> /// <summary>Gets or sets whether or not this control is persistent.</summary>
public bool Persistent { get; set; } public bool Persistent { get; set; }
public event EventHandler<EventArgs> Click; public event EventHandler<EventArgs> Click;
/// <summary> /// <summary>
/// Event raised when this control is clicked. /// Event raised when this control is clicked.
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected virtual void OnClick(EventArgs e) protected virtual void OnClick(EventArgs e)
{ {
if (Click != null) if (Click != null)
Click(this, e); Click(this, e);
} }
/// <summary>Default constructor. Sets <see cref="Enabled"/> to true.</summary> /// <summary>Default constructor. Sets <see cref="Enabled"/> to true.</summary>
public CustomButton() { Enabled = true; } public CustomButton() { Enabled = true; }
/// <summary>Event raised when this control is resized.</summary> /// <summary>Event raised when this control is resized.</summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e) protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
if (Loaded)
Invalidate();
}
/// <summary>
/// Event raised when the mouse is pressed down over this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (Enabled)
{ {
base.OnSizeChanged(e); mouseDown = true;
if (Loaded) Invalidate();
Invalidate();
} }
}
/// <summary>
/// Event raised when the mouse enters this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseEnter(MouseEventArgs e)
{
Cursor = new Cursor(CursorType.Pointer);
base.OnMouseEnter(e);
hover = true;
Invalidate();
}
/// <summary> /// <summary>
/// Event raised when the mouse is pressed down over this control's bounding box. /// Event raised when the mouse leaves this control's bounding box.
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e) protected override void OnMouseLeave(MouseEventArgs e)
{
Cursor = new Cursor(CursorType.Default);
base.OnMouseLeave(e);
hover = false;
Invalidate();
}
/// <summary>
/// Event raised when the mouse is released over this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
var rect = new Rectangle(this.Size);
if (mouseDown && rect.Contains((Point)e.Location))
{ {
base.OnMouseDown(e); if (Toggle)
pressed = !pressed;
else if (Persistent)
pressed = true;
else
pressed = false;
mouseDown = false;
this.Invalidate();
if (Enabled) if (Enabled)
{ OnClick(EventArgs.Empty);
mouseDown = true;
Invalidate();
}
} }
else
/// <summary>
/// Event raised when the mouse enters this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseEnter(MouseEventArgs e)
{ {
Cursor = new Cursor(CursorType.Pointer); mouseDown = false;
base.OnMouseEnter(e); this.Invalidate();
hover = true;
Invalidate();
} }
}
/// <summary> /// <summary>
/// Event raised when the mouse leaves this control's bounding box. /// Event raised to draw this control.
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="pe"></param>
protected override void OnMouseLeave(MouseEventArgs e) protected override void OnPaint(PaintEventArgs pe)
{
var rect = new Rectangle(this.Size);
var col = Color.FromGrayscale(hover && Enabled ? 0.95f : 0.8f);
if (Enabled && (pressed || mouseDown))
{ {
Cursor = new Cursor(CursorType.Default); pe.Graphics.FillRectangle(col, rect);
base.OnMouseLeave(e); pe.Graphics.DrawInsetRectangle(Colors.Gray, Colors.White, rect);
hover = false;
Invalidate();
} }
else if (hover && Enabled)
/// <summary>
/// Event raised when the mouse is released over this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)
{ {
base.OnMouseUp(e); pe.Graphics.FillRectangle(col, rect);
var rect = new Rectangle(this.Size); pe.Graphics.DrawInsetRectangle(Colors.White, Colors.Gray, rect);
if (mouseDown && rect.Contains((Point)e.Location))
{
if (Toggle)
pressed = !pressed;
else if (Persistent)
pressed = true;
else
pressed = false;
mouseDown = false;
this.Invalidate();
if (Enabled)
OnClick(EventArgs.Empty);
}
else
{
mouseDown = false;
this.Invalidate();
}
} }
/// <summary> base.OnPaint(pe);
/// Event raised to draw this control.
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe)
{
var rect = new Rectangle(this.Size);
var col = Color.FromGrayscale(hover && Enabled ? 0.95f : 0.8f);
if (Enabled && (pressed || mouseDown))
{
pe.Graphics.FillRectangle(col, rect);
pe.Graphics.DrawInsetRectangle(Colors.Gray, Colors.White, rect);
}
else if (hover && Enabled)
{
pe.Graphics.FillRectangle(col, rect);
pe.Graphics.DrawInsetRectangle(Colors.White, Colors.Gray, rect);
}
base.OnPaint(pe);
}
} }
} }

@ -1,105 +1,103 @@
using Eto.Drawing; using Eto.Drawing;
using System; using System;
namespace Pablo.Controls namespace Pablo.Controls;
/// <summary>
/// Extension of <see cref="CustomButton"/> that allows image assignment and drawing.
/// Originally written by cwensley (https://gist.github.com/cwensley/95000998e37acd93e830),
/// modified by Lojemiru and Miepee for use in the AM2RLauncher.
/// </summary>
public class ImageButton : CustomButton
{ {
/// <summary> /// <summary>
/// Extension of <see cref="CustomButton"/> that allows image assignment and drawing. /// Whether or not this control's size has been set.
/// Originally written by cwensley (https://gist.github.com/cwensley/95000998e37acd93e830),
/// modified by Lojemiru and Miepee for use in the AM2RLauncher.
/// </summary> /// </summary>
public class ImageButton : CustomButton bool sizeSet;
{
/// <summary>
/// Whether or not this control's size has been set.
/// </summary>
bool sizeSet;
/// <summary> /// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/>. /// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/>.
/// </summary> /// </summary>
public Image Image { get; set; } public Image Image { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/> if this control is disabled. /// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/> if this control is disabled.
/// </summary> /// </summary>
public Image DisabledImage { get; set; } public Image DisabledImage { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Size"/> of this control. /// Gets or sets the <see cref="Eto.Drawing.Size"/> of this control.
/// </summary> /// </summary>
public override Size Size public override Size Size
{ {
get { return base.Size; } get { return base.Size; }
set { base.Size = value; sizeSet = true; } set { base.Size = value; sizeSet = true; }
} }
/// <summary> /// <summary>
/// Default constructor, assigns no special attributes. /// Default constructor, assigns no special attributes.
/// </summary> /// </summary>
public ImageButton() { } public ImageButton() { }
/// <summary> /// <summary>
/// Event raised when this control is loading. /// Event raised when this control is loading.
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnLoad(EventArgs e) protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (Image != null)
{ {
base.OnLoad(e); if (!sizeSet)
if (Image != null) this.Size = Image.Size + 4;
{
if (!sizeSet)
this.Size = Image.Size + 4;
}
} }
}
/// <summary> /// <summary>
/// Event raised when this control has finished loading. /// Event raised when this control has finished loading.
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnLoadComplete(EventArgs e) protected override void OnLoadComplete(EventArgs e)
{ {
base.OnLoadComplete(e); base.OnLoadComplete(e);
if (DisabledImage == null) if (DisabledImage == null)
{
var image = Image;
if (image != null)
{ {
var image = Image; var disabledImage = new Bitmap(image.Size.Width, image.Size.Height, PixelFormat.Format32bppRgba);
if (image != null) using (var graphics = new Graphics(disabledImage))
{ {
var disabledImage = new Bitmap(image.Size.Width, image.Size.Height, PixelFormat.Format32bppRgba); graphics.DrawImage(image, 0, 0);
using (var graphics = new Graphics(disabledImage)) }
{ using (var bd = disabledImage.Lock())
graphics.DrawImage(image, 0, 0); {
} unsafe
using (var bd = disabledImage.Lock())
{ {
unsafe var data = (int*)bd.Data;
for (int i = 0; i < bd.ScanWidth * disabledImage.Size.Height; i++)
{ {
var data = (int*)bd.Data; var col = Color.FromArgb(bd.TranslateDataToArgb(*data));
for (int i = 0; i < bd.ScanWidth * disabledImage.Size.Height; i++) var gray = (col.R + col.G + col.B) / 3;
{ *data = bd.TranslateArgbToData(Color.FromGrayscale(gray, 0.8f).ToArgb());
var col = Color.FromArgb(bd.TranslateDataToArgb(*data));
var gray = (col.R + col.G + col.B) / 3;
*data = bd.TranslateArgbToData(Color.FromGrayscale(gray, 0.8f).ToArgb());
}
} }
} }
} }
} }
} }
/// <summary>
/// Event raised to draw this control.
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(Eto.Forms.PaintEventArgs pe)
{
var image = this.Enabled ? Image : DisabledImage;
var size = image.Size.FitTo(this.Size - 2);
var xoffset = (this.Size.Width - size.Width) / 2;
var yoffset = (this.Size.Height - size.Height) / 2;
pe.Graphics.DrawImage(image, xoffset, yoffset, size.Width, size.Height);
}
} }
} /// <summary>
/// Event raised to draw this control.
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(Eto.Forms.PaintEventArgs pe)
{
var image = this.Enabled ? Image : DisabledImage;
var size = image.Size.FitTo(this.Size - 2);
var xoffset = (this.Size.Width - size.Width) / 2;
var yoffset = (this.Size.Height - size.Height) / 2;
pe.Graphics.DrawImage(image, xoffset, yoffset, size.Width, size.Height);
}
}

File diff suppressed because it is too large Load Diff

@ -9,231 +9,230 @@ using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Configuration = System.Configuration.Configuration; using Configuration = System.Configuration.Configuration;
namespace AM2RLauncher namespace AM2RLauncher;
public partial class MainForm : Form
{ {
public partial class MainForm : Form /// <summary>
/// Method that updates <see cref="progressBar"/>.
/// </summary>
/// <param name="value">The value that <see cref="progressBar"/> should be set to.</param>
/// <param name="min">The min value that <see cref="progressBar"/> should be set to.</param>
/// <param name="max">The max value that <see cref="progressBar"/> should be set to.</param>
private void UpdateProgressBar(int value, int min = 0, int max = 100)
{ {
/// <summary> Application.Instance.Invoke(() =>
/// Method that updates <see cref="progressBar"/>.
/// </summary>
/// <param name="value">The value that <see cref="progressBar"/> should be set to.</param>
/// <param name="min">The min value that <see cref="progressBar"/> should be set to.</param>
/// <param name="max">The max value that <see cref="progressBar"/> should be set to.</param>
private void UpdateProgressBar(int value, int min = 0, int max = 100)
{ {
Application.Instance.Invoke(() => progressBar.MinValue = min;
{ progressBar.MaxValue = max;
progressBar.MinValue = min; progressBar.Value = value;
progressBar.MaxValue = max; });
progressBar.Value = value; }
});
}
/// <summary> /// <summary>
/// Method that updates <see cref="progressBar"/> with a min value of 0 and max value of 100. /// Method that updates <see cref="progressBar"/> with a min value of 0 and max value of 100.
/// </summary> /// </summary>
/// <param name="value">The value that <see cref="progressBar"/> should be set to.</param> /// <param name="value">The value that <see cref="progressBar"/> should be set to.</param>
private void UpdateProgressBar(int value) private void UpdateProgressBar(int value)
{ {
UpdateProgressBar(value, 0, 100); UpdateProgressBar(value, 0, 100);
} }
/// <summary> /// <summary>
/// Safety check function before accessing <see cref="profileIndex"/>. /// Safety check function before accessing <see cref="profileIndex"/>.
/// </summary> /// </summary>
/// <returns><see langword="true"/> if it is valid, <see langword="false"/> if not.</returns> /// <returns><see langword="true"/> if it is valid, <see langword="false"/> if not.</returns>
private bool IsProfileIndexValid() private bool IsProfileIndexValid()
{
return profileIndex != null;
}
/// <summary>
/// This is just a helper method for the git commands in order to have a progress bar display for them.
/// </summary>
private bool TransferProgressHandlerMethod(TransferProgress transferProgress)
{
// Thank you random issue on the gitlib2sharp repo!!!!
// Also tldr; rtfm
if (isGitProcessGettingCancelled) return false;
// This needs to be in an Invoke, in order to access the variables from the main thread
// Otherwise this will throw a runtime exception
Application.Instance.Invoke(() =>
{ {
return profileIndex != null; progressBar.MinValue = 0;
} progressBar.MaxValue = transferProgress.TotalObjects;
if (currentGitObject >= transferProgress.ReceivedObjects)
return;
progressLabel.Text = Text.ProgressbarProgress + " " + transferProgress.ReceivedObjects + " (" + ((int)transferProgress.ReceivedBytes / 1000000) + "MB) / " + transferProgress.TotalObjects + " objects";
currentGitObject = transferProgress.ReceivedObjects;
progressBar.Value = transferProgress.ReceivedObjects;
});
return true;
}
/// <summary> /// <summary>
/// This is just a helper method for the git commands in order to have a progress bar display for them. /// Creates a single-file, zip-filtered file dialog.
/// </summary> /// </summary>
private bool TransferProgressHandlerMethod(TransferProgress transferProgress) /// <param name="title">The title of the file dialog.</param>
/// <returns>The created file dialog.</returns>
private OpenFileDialog GetSingleZipDialog(string title = "")
{
OpenFileDialog fileDialog = new OpenFileDialog
{ {
// Thank you random issue on the gitlib2sharp repo!!!! Directory = new Uri(CrossPlatformOperations.CurrentPath),
// Also tldr; rtfm MultiSelect = false,
if (isGitProcessGettingCancelled) return false; Title = title
};
fileDialog.Filters.Add(new FileFilter(Text.ZipArchiveText, ".zip"));
return fileDialog;
}
// This needs to be in an Invoke, in order to access the variables from the main thread private void DisableProgressBar()
// Otherwise this will throw a runtime exception {
Application.Instance.Invoke(() => progressBar.Visible = false;
{ progressBar.Value = 0;
progressBar.MinValue = 0; }
progressBar.MaxValue = transferProgress.TotalObjects;
if (currentGitObject >= transferProgress.ReceivedObjects)
return;
progressLabel.Text = Text.ProgressbarProgress + " " + transferProgress.ReceivedObjects + " (" + ((int)transferProgress.ReceivedBytes / 1000000) + "MB) / " + transferProgress.TotalObjects + " objects";
currentGitObject = transferProgress.ReceivedObjects;
progressBar.Value = transferProgress.ReceivedObjects;
});
return true;
}
/// <summary> private void EnableProgressBar()
/// Creates a single-file, zip-filtered file dialog. {
/// </summary> progressBar.Visible = true;
/// <param name="title">The title of the file dialog.</param> progressBar.Value = 0;
/// <returns>The created file dialog.</returns> }
private OpenFileDialog GetSingleZipDialog(string title = "")
{
OpenFileDialog fileDialog = new OpenFileDialog
{
Directory = new Uri(CrossPlatformOperations.CurrentPath),
MultiSelect = false,
Title = title
};
fileDialog.Filters.Add(new FileFilter(Text.ZipArchiveText, ".zip"));
return fileDialog;
}
private void DisableProgressBar() private void DisableProgressBarAndProgressLabel()
{ {
progressBar.Visible = false; DisableProgressBar();
progressBar.Value = 0; progressLabel.Visible = false;
} progressLabel.Text = "";
}
private void EnableProgressBar() private void EnableProgressBarAndLabel()
{ {
progressBar.Visible = true; EnableProgressBar();
progressBar.Value = 0; progressLabel.Visible = true;
} progressLabel.Text = "";
}
private void DisableProgressBarAndProgressLabel() /// <summary>
/// Reads the Launcher config file on the current Platform and returns the value for <paramref name="property"/>.
/// </summary>
/// <param name="property">The property to get the value from.</param>
/// <returns>The value from <paramref name="property"/> as a string</returns>
public static string ReadFromConfig(string property)
{
log.Info($"Reading {property} from config.");
if (OS.IsWindows)
{ {
DisableProgressBar(); // We use the configuration manager in order to read `property` from the app.config and then return it
progressLabel.Visible = false; ConnectionStringSettings appConfig = ConfigurationManager.ConnectionStrings[property];
progressLabel.Text = ""; if (appConfig == null) throw new ArgumentException("The property " + property + " could not be found.");
return appConfig.ConnectionString;
} }
if (OS.IsUnix)
private void EnableProgressBarAndLabel()
{ {
EnableProgressBar(); string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
progressLabel.Visible = true; string launcherConfigPath = Path.GetDirectoryName(launcherConfigFilePath);
progressLabel.Text = ""; XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
}
/// <summary> // If folder doesn't exist, create it and the config file
/// Reads the Launcher config file on the current Platform and returns the value for <paramref name="property"/>. if (!Directory.Exists(launcherConfigPath) || !File.Exists(launcherConfigFilePath))
/// </summary>
/// <param name="property">The property to get the value from.</param>
/// <returns>The value from <paramref name="property"/> as a string</returns>
public static string ReadFromConfig(string property)
{
log.Info($"Reading {property} from config.");
if (OS.IsWindows)
{ {
// We use the configuration manager in order to read `property` from the app.config and then return it Directory.CreateDirectory(launcherConfigPath);
ConnectionStringSettings appConfig = ConfigurationManager.ConnectionStrings[property]; File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
if (appConfig == null) throw new ArgumentException("The property " + property + " could not be found.");
return appConfig.ConnectionString;
}
if (OS.IsUnix)
{
string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
string launcherConfigPath = Path.GetDirectoryName(launcherConfigFilePath);
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
// If folder doesn't exist, create it and the config file
if (!Directory.Exists(launcherConfigPath) || !File.Exists(launcherConfigFilePath))
{
Directory.CreateDirectory(launcherConfigPath);
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
// Deserialize the config xml into launcherConfig
launcherConfig = Serializer.Deserialize<XML.LauncherConfigXML>(File.ReadAllText(launcherConfigFilePath));
// This uses the indexer, which means, we can use the variable in order to get the property. Look at LauncherConfigXML for more info
return launcherConfig[property]?.ToString();
} }
log.Error(OS.Name + " has no config to read from!"); // Deserialize the config xml into launcherConfig
return null; launcherConfig = Serializer.Deserialize<XML.LauncherConfigXML>(File.ReadAllText(launcherConfigFilePath));
// This uses the indexer, which means, we can use the variable in order to get the property. Look at LauncherConfigXML for more info
return launcherConfig[property]?.ToString();
} }
/// <summary> log.Error(OS.Name + " has no config to read from!");
/// Writes <paramref name="value"/> to <paramref name="property"/> in the Launcher Config file. return null;
/// </summary> }
/// <param name="property">The property whose value you want to change.</param>
/// <param name="value">The value that will be written.</param> /// <summary>
public static void WriteToConfig(string property, object value) /// Writes <paramref name="value"/> to <paramref name="property"/> in the Launcher Config file.
/// </summary>
/// <param name="property">The property whose value you want to change.</param>
/// <param name="value">The value that will be written.</param>
public static void WriteToConfig(string property, object value)
{
log.Info($"Writing {value} of type {value.GetType()} to {property} to config.");
if (OS.IsWindows)
{ {
log.Info($"Writing {value} of type {value.GetType()} to {property} to config."); // We use the configuration manager in order to read from the app.config, change the value and save it
if (OS.IsWindows) Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
{ if (appConfig == null)
// We use the configuration manager in order to read from the app.config, change the value and save it throw new NullReferenceException("Could not find the Config file! Please make sure it exists!");
Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConnectionStringsSection connectionStringsSection = (ConnectionStringsSection)appConfig.GetSection("connectionStrings");
if (appConfig == null) if (connectionStringsSection?.ConnectionStrings[property]?.ConnectionString == null)
throw new NullReferenceException("Could not find the Config file! Please make sure it exists!"); throw new ArgumentException("The property " + property + " could not be found.");
ConnectionStringsSection connectionStringsSection = (ConnectionStringsSection)appConfig.GetSection("connectionStrings"); connectionStringsSection.ConnectionStrings[property].ConnectionString = value.ToString();
if (connectionStringsSection?.ConnectionStrings[property]?.ConnectionString == null) appConfig.Save();
throw new ArgumentException("The property " + property + " could not be found."); ConfigurationManager.RefreshSection("connectionStrings");
connectionStringsSection.ConnectionStrings[property].ConnectionString = value.ToString(); }
appConfig.Save(); else if (OS.IsUnix)
ConfigurationManager.RefreshSection("connectionStrings"); {
} string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
else if (OS.IsUnix) string launcherConfigPath = Path.GetDirectoryName(launcherConfigFilePath);
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
// If folder doesn't exist, create it and the config file
if (!Directory.Exists(launcherConfigPath) || !File.Exists(launcherConfigFilePath))
{ {
string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath; Directory.CreateDirectory(launcherConfigPath);
string launcherConfigPath = Path.GetDirectoryName(launcherConfigFilePath);
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
// If folder doesn't exist, create it and the config file
if (!Directory.Exists(launcherConfigPath) || !File.Exists(launcherConfigFilePath))
{
Directory.CreateDirectory(launcherConfigPath);
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
// Deserialize the config xml into launcherConfig
launcherConfig = Serializer.Deserialize<XML.LauncherConfigXML>(File.ReadAllText(launcherConfigFilePath));
// Uses indexer. Look at LauncherConfigXML for more info
launcherConfig[property] = value;
// Serialize back into the file
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig)); File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
} }
else // Deserialize the config xml into launcherConfig
log.Error(OS.Name + " has no config to write to!"); launcherConfig = Serializer.Deserialize<XML.LauncherConfigXML>(File.ReadAllText(launcherConfigFilePath));
// Uses indexer. Look at LauncherConfigXML for more info
launcherConfig[property] = value;
// Serialize back into the file
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
} }
else
log.Error(OS.Name + " has no config to write to!");
}
/// <summary> /// <summary>
/// When a Launcher update occurs that introduces new config properties, this method ensures that the old user config is copied over as much as possible. /// When a Launcher update occurs that introduces new config properties, this method ensures that the old user config is copied over as much as possible.
/// </summary> /// </summary>
public static void CopyOldConfigToNewConfig() public static void CopyOldConfigToNewConfig()
{
if (OS.IsWindows)
{ {
if (OS.IsWindows) string oldConfigPath = CrossPlatformOperations.LauncherName + ".oldCfg";
{ string newConfigPath = CrossPlatformOperations.LauncherName + ".config";
string oldConfigPath = CrossPlatformOperations.LauncherName + ".oldCfg"; string oldConfigText = File.ReadAllText(oldConfigPath);
string newConfigPath = CrossPlatformOperations.LauncherName + ".config"; string newConfigText = File.ReadAllText(newConfigPath);
string oldConfigText = File.ReadAllText(oldConfigPath);
string newConfigText = File.ReadAllText(newConfigPath);
Regex settingRegex = new Regex("<add name=\".*\" />"); Regex settingRegex = new Regex("<add name=\".*\" />");
MatchCollection oldMatch = settingRegex.Matches(oldConfigText); MatchCollection oldMatch = settingRegex.Matches(oldConfigText);
MatchCollection newMatch = settingRegex.Matches(newConfigText); MatchCollection newMatch = settingRegex.Matches(newConfigText);
for (int i = 0; i < oldMatch.Count; i++) for (int i = 0; i < oldMatch.Count; i++)
newConfigText = newConfigText.Replace(newMatch[i].Value, oldMatch[i].Value); newConfigText = newConfigText.Replace(newMatch[i].Value, oldMatch[i].Value);
File.WriteAllText(newConfigPath, newConfigText); File.WriteAllText(newConfigPath, newConfigText);
} }
else if (OS.IsUnix) else if (OS.IsUnix)
{ {
string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath; string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
// For some reason deserializing and saving back again works, not exactly sure why, but I'll take it // For some reason deserializing and saving back again works, not exactly sure why, but I'll take it
XML.LauncherConfigXML launcherConfig = Serializer.Deserialize<XML.LauncherConfigXML>(File.ReadAllText(launcherConfigFilePath)); XML.LauncherConfigXML launcherConfig = Serializer.Deserialize<XML.LauncherConfigXML>(File.ReadAllText(launcherConfigFilePath));
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig)); File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
else
log.Error(OS.Name + " has no config to transfer over!");
} }
else
log.Error(OS.Name + " has no config to transfer over!");
} }
} }

@ -4,380 +4,379 @@ using AM2RLauncherLib;
using AM2RLauncherLib.XML; using AM2RLauncherLib.XML;
using AM2RLauncher.Language; using AM2RLauncher.Language;
namespace AM2RLauncher namespace AM2RLauncher;
/// <summary>
/// Everything UI/Form state machine-related goes in here
/// </summary>
public partial class MainForm
{ {
/// <summary> /// <summary>
/// Everything UI/Form state machine-related goes in here /// Updates <see cref="updateState"/>, <see cref="playButton"/>, <see cref="apkButtonState"/>, and <see cref="apkButton"/> according to the current conditions.
/// </summary>
private void UpdateStateMachine()
{
UpdatePlayState();
UpdateApkState();
UpdateProfileState();
UpdateModSettingsState();
}
/// <summary>
/// Determines current conditions and calls <see cref="SetPlayButtonState(PlayButtonState)"/> accordingly.
/// </summary> /// </summary>
public partial class MainForm private void UpdatePlayState()
{ {
/// <summary> // If we're downloading or installing, don't change anything
/// Updates <see cref="updateState"/>, <see cref="playButton"/>, <see cref="apkButtonState"/>, and <see cref="apkButton"/> according to the current conditions. if ((updateState == PlayButtonState.Downloading) || (updateState == PlayButtonState.Installing))
/// </summary> return;
private void UpdateStateMachine()
// If we're currently creating an APK, we disable the play button
if (apkButtonState == ApkButtonState.Creating)
{ {
UpdatePlayState(); playButton.Enabled = false;
UpdateApkState(); return;
UpdateProfileState();
UpdateModSettingsState();
} }
/// <summary> playButton.Enabled = true;
/// Determines current conditions and calls <see cref="SetPlayButtonState(PlayButtonState)"/> accordingly. // If PatchData isn't cloned, we still need to download
/// </summary> if (!Profile.IsPatchDataCloned())
private void UpdatePlayState()
{ {
// If we're downloading or installing, don't change anything SetPlayButtonState(PlayButtonState.Download);
if ((updateState == PlayButtonState.Downloading) || (updateState == PlayButtonState.Installing)) return;
return; }
// If we're currently creating an APK, we disable the play button
if (apkButtonState == ApkButtonState.Creating)
{
playButton.Enabled = false;
return;
}
playButton.Enabled = true;
// If PatchData isn't cloned, we still need to download
if (!Profile.IsPatchDataCloned())
{
SetPlayButtonState(PlayButtonState.Download);
return;
}
// If 1.1 isn't installed, we still need to select it
if (!Profile.Is11Installed())
{
SetPlayButtonState(PlayButtonState.Select11);
return;
}
var isProfileValid = IsProfileIndexValid();
// If current profile is installed, we're ready to play!
if (isProfileValid && Profile.IsProfileInstalled(profileList[profileIndex.Value]))
{
SetPlayButtonState(PlayButtonState.Play);
return;
}
// Otherwise, if profile is NOT installable, we delete the profile because we can't install it and therefore holds no value!
if (isProfileValid && profileList[profileIndex.Value].Installable == false)
{
DeleteProfileAndAdjustLists(profileList[profileIndex.Value]);
return;
}
// Otherwise, we still need to install. // If 1.1 isn't installed, we still need to select it
SetPlayButtonState(PlayButtonState.Install); if (!Profile.Is11Installed())
{
SetPlayButtonState(PlayButtonState.Select11);
return;
} }
/// <summary> var isProfileValid = IsProfileIndexValid();
/// Determines current conditions and enables or disables <see cref="apkButton"/> accordingly. // If current profile is installed, we're ready to play!
/// </summary> if (isProfileValid && Profile.IsProfileInstalled(profileList[profileIndex.Value]))
private void UpdateApkState()
{ {
// Safety check SetPlayButtonState(PlayButtonState.Play);
if (apkButton == null) return;
return; }
// Otherwise, if profile is NOT installable, we delete the profile because we can't install it and therefore holds no value!
if (isProfileValid && profileList[profileIndex.Value].Installable == false)
{
DeleteProfileAndAdjustLists(profileList[profileIndex.Value]);
return;
}
// Our default values // Otherwise, we still need to install.
apkButton.Enabled = false; SetPlayButtonState(PlayButtonState.Install);
apkButton.ToolTip = Text.ApkButtonDisabledToolTip; }
// If profile supports Android and if we are NOT already creating an APK... /// <summary>
if (!IsProfileIndexValid()) /// Determines current conditions and enables or disables <see cref="apkButton"/> accordingly.
return; /// </summary>
private void UpdateApkState()
{
// Safety check
if (apkButton == null)
return;
var profile = profileList[profileIndex.Value]; // Our default values
if (!profile.SupportsAndroid || !profile.Installable || apkButtonState != ApkButtonState.Create) apkButton.Enabled = false;
return; apkButton.ToolTip = Text.ApkButtonDisabledToolTip;
// Switch status based on main button's state // If profile supports Android and if we are NOT already creating an APK...
switch (updateState) if (!IsProfileIndexValid())
{ return;
case PlayButtonState.Download:
case PlayButtonState.Downloading: var profile = profileList[profileIndex.Value];
case PlayButtonState.Select11: if (!profile.SupportsAndroid || !profile.Installable || apkButtonState != ApkButtonState.Create)
case PlayButtonState.Installing: return;
case PlayButtonState.Playing: return;
// Switch status based on main button's state
case PlayButtonState.Install: switch (updateState)
case PlayButtonState.Play: apkButton.Enabled = true; apkButton.ToolTip = HelperMethods.GetText(Text.ApkButtonEnabledToolTip, profileDropDown?.Items[profileDropDown.SelectedIndex]?.Text ?? ""); break; {
} case PlayButtonState.Download:
case PlayButtonState.Downloading:
case PlayButtonState.Select11:
case PlayButtonState.Installing:
case PlayButtonState.Playing: return;
case PlayButtonState.Install:
case PlayButtonState.Play: apkButton.Enabled = true; apkButton.ToolTip = HelperMethods.GetText(Text.ApkButtonEnabledToolTip, profileDropDown?.Items[profileDropDown.SelectedIndex]?.Text ?? ""); break;
} }
}
/// <summary> /// <summary>
/// Determines current conditions and enables or disables the <see cref="profileDropDown"/> and related controls accordingly. /// Determines current conditions and enables or disables the <see cref="profileDropDown"/> and related controls accordingly.
/// </summary> /// </summary>
private void UpdateProfileState() private void UpdateProfileState()
{
// Safety check
if (profileDropDown == null)
return;
switch (updateState)
{ {
// Safety check case PlayButtonState.Download:
if (profileDropDown == null) case PlayButtonState.Downloading:
return; case PlayButtonState.Select11:
switch (updateState) case PlayButtonState.Installing:
{ case PlayButtonState.Playing: profileDropDown.Enabled = false; break;
case PlayButtonState.Download:
case PlayButtonState.Downloading:
case PlayButtonState.Select11:
case PlayButtonState.Installing:
case PlayButtonState.Playing: profileDropDown.Enabled = false; break;
case PlayButtonState.Install: case PlayButtonState.Install:
case PlayButtonState.Play: profileDropDown.Enabled = true; break; case PlayButtonState.Play: profileDropDown.Enabled = true; break;
} }
if (apkButtonState == ApkButtonState.Creating) profileDropDown.Enabled = false; if (apkButtonState == ApkButtonState.Creating) profileDropDown.Enabled = false;
Color col = profileDropDown.Enabled ? colGreen : colInactive; Color col = profileDropDown.Enabled ? colGreen : colInactive;
if (OS.IsWindows) if (OS.IsWindows)
profileDropDown.TextColor = col; profileDropDown.TextColor = col;
profileAuthorLabel.TextColor = col; profileAuthorLabel.TextColor = col;
profileVersionLabel.TextColor = col; profileVersionLabel.TextColor = col;
profileLabel.TextColor = col; profileLabel.TextColor = col;
} }
/// <summary> /// <summary>
/// Determines current conditions and enables or disabled the mainPage controls accordingly. /// Determines current conditions and enables or disabled the mainPage controls accordingly.
/// </summary> /// </summary>
private void UpdateModSettingsState() private void UpdateModSettingsState()
{ {
// Safety check // Safety check
if (modSettingsProfileDropDown == null || modSettingsProfileDropDown.Items.Count <= 0) return; if (modSettingsProfileDropDown == null || modSettingsProfileDropDown.Items.Count <= 0) return;
bool enabled = false; bool enabled = false;
switch (updateState) switch (updateState)
{ {
case PlayButtonState.Download: case PlayButtonState.Download:
case PlayButtonState.Downloading: case PlayButtonState.Downloading:
case PlayButtonState.Select11: case PlayButtonState.Select11:
case PlayButtonState.Installing: case PlayButtonState.Installing:
case PlayButtonState.Playing: enabled = false; break; case PlayButtonState.Playing: enabled = false; break;
case PlayButtonState.Install: case PlayButtonState.Install:
case PlayButtonState.Play: enabled = true; break; case PlayButtonState.Play: enabled = true; break;
} }
if (apkButtonState == ApkButtonState.Creating) enabled = false; if (apkButtonState == ApkButtonState.Creating) enabled = false;
string selectedProfileName = modSettingsProfileDropDown.Items[modSettingsProfileDropDown.SelectedIndex].Text; string selectedProfileName = modSettingsProfileDropDown.Items[modSettingsProfileDropDown.SelectedIndex].Text;
settingsProfileLabel.TextColor = colGreen; settingsProfileLabel.TextColor = colGreen;
modSettingsProfileDropDown.Enabled = enabled; modSettingsProfileDropDown.Enabled = enabled;
profileButton.Enabled = enabled; profileButton.Enabled = enabled;
profileButton.ToolTip = HelperMethods.GetText(Text.OpenProfileFolderToolTip, selectedProfileName); profileButton.ToolTip = HelperMethods.GetText(Text.OpenProfileFolderToolTip, selectedProfileName);
saveButton.Enabled = enabled; saveButton.Enabled = enabled;
saveButton.ToolTip = HelperMethods.GetText(Text.OpenSaveFolderToolTip, selectedProfileName); saveButton.ToolTip = HelperMethods.GetText(Text.OpenSaveFolderToolTip, selectedProfileName);
addModButton.Enabled = enabled; addModButton.Enabled = enabled;
addModButton.ToolTip = Text.AddNewModToolTip; addModButton.ToolTip = Text.AddNewModToolTip;
// Only enable these, when we're not on the community updates // Only enable these, when we're not on the community updates
if (modSettingsProfileDropDown.SelectedIndex > 0) if (modSettingsProfileDropDown.SelectedIndex > 0)
{ {
updateModButton.Enabled = profileList[modSettingsProfileDropDown.SelectedIndex].Installable; updateModButton.Enabled = profileList[modSettingsProfileDropDown.SelectedIndex].Installable;
updateModButton.ToolTip = HelperMethods.GetText(Text.UpdateModButtonToolTip, selectedProfileName); updateModButton.ToolTip = HelperMethods.GetText(Text.UpdateModButtonToolTip, selectedProfileName);
deleteModButton.Enabled = enabled; deleteModButton.Enabled = enabled;
deleteModButton.ToolTip = HelperMethods.GetText(Text.DeleteModButtonToolTip, selectedProfileName); deleteModButton.ToolTip = HelperMethods.GetText(Text.DeleteModButtonToolTip, selectedProfileName);
} }
Color col = enabled ? colGreen : colInactive; Color col = enabled ? colGreen : colInactive;
if (OS.IsWindows) if (OS.IsWindows)
modSettingsProfileDropDown.TextColor = col; modSettingsProfileDropDown.TextColor = col;
settingsProfileLabel.TextColor = col; settingsProfileLabel.TextColor = col;
if (enabled) if (enabled)
modSettingsProfileDropDown.SelectedIndex = profileDropDown.SelectedIndex; modSettingsProfileDropDown.SelectedIndex = profileDropDown.SelectedIndex;
} }
/// <summary> /// <summary>
/// Sets the global <see cref="updateState"/> and then changes the state of <see cref="playButton"/> accordingly. /// Sets the global <see cref="updateState"/> and then changes the state of <see cref="playButton"/> accordingly.
/// </summary> /// </summary>
/// <param name="state">The state that should be set to.</param> /// <param name="state">The state that should be set to.</param>
private void SetPlayButtonState(PlayButtonState state) private void SetPlayButtonState(PlayButtonState state)
{
updateState = state;
switch (updateState)
{ {
updateState = state; case PlayButtonState.Download:
switch (updateState) case PlayButtonState.Downloading:
{ case PlayButtonState.Select11:
case PlayButtonState.Download: case PlayButtonState.Install:
case PlayButtonState.Downloading: case PlayButtonState.Play: playButton.Enabled = true; break;
case PlayButtonState.Select11:
case PlayButtonState.Install: case PlayButtonState.Installing:
case PlayButtonState.Play: playButton.Enabled = true; break; case PlayButtonState.Playing: playButton.Enabled = false; break;
}
case PlayButtonState.Installing: playButton.Text = GetPlayButtonText();
case PlayButtonState.Playing: playButton.Enabled = false; break; playButton.ToolTip = GetPlayButtonTooltip();
}
playButton.Text = GetPlayButtonText();
playButton.ToolTip = GetPlayButtonTooltip();
playButton.Invalidate(); playButton.Invalidate();
UpdateModSettingsState(); UpdateModSettingsState();
} }
/// <summary> /// <summary>
/// Sets the global <see cref="apkButtonState"/> and then changes the state of <see cref="apkButton"/> accordingly. /// Sets the global <see cref="apkButtonState"/> and then changes the state of <see cref="apkButton"/> accordingly.
/// </summary> /// </summary>
/// <param name="state">The state that should be set to.</param> /// <param name="state">The state that should be set to.</param>
private void SetApkButtonState(ApkButtonState state) private void SetApkButtonState(ApkButtonState state)
{
apkButtonState = state;
switch (apkButtonState)
{ {
apkButtonState = state; case ApkButtonState.Create: apkButton.Enabled = true; break;
switch (apkButtonState) case ApkButtonState.Creating: apkButton.Enabled = false; break;
{
case ApkButtonState.Create: apkButton.Enabled = true; break;
case ApkButtonState.Creating: apkButton.Enabled = false; break;
}
apkButton.Text = GetApkButtonText();
} }
apkButton.Text = GetApkButtonText();
}
/// <summary> /// <summary>
/// This returns the text that <see cref="playButton"/> should have depending on the global updateState. /// This returns the text that <see cref="playButton"/> should have depending on the global updateState.
/// </summary> /// </summary>
/// <returns>The text as a <see cref="String"/>, or <see langword="null"/> if the current State is invalid.</returns> /// <returns>The text as a <see cref="String"/>, or <see langword="null"/> if the current State is invalid.</returns>
private string GetPlayButtonText() private string GetPlayButtonText()
{
switch (updateState)
{ {
switch (updateState) case PlayButtonState.Download: return Text.Download;
{ case PlayButtonState.Downloading: return Text.Abort;
case PlayButtonState.Download: return Text.Download; case PlayButtonState.Select11: return Text.Select11;
case PlayButtonState.Downloading: return Text.Abort; case PlayButtonState.Install: return Text.Install;
case PlayButtonState.Select11: return Text.Select11; case PlayButtonState.Installing: return Text.Installing;
case PlayButtonState.Install: return Text.Install; case PlayButtonState.Play: return Text.Play;
case PlayButtonState.Installing: return Text.Installing; case PlayButtonState.Playing: return Text.Playing;
case PlayButtonState.Play: return Text.Play; default: return null;
case PlayButtonState.Playing: return Text.Playing;
default: return null;
}
} }
}
/// <summary> /// <summary>
/// This returns the tooltip that <see cref="playButton"/> should have depending on the global updateState. /// This returns the tooltip that <see cref="playButton"/> should have depending on the global updateState.
/// </summary> /// </summary>
/// <returns>The tooltip as a <see cref="String"/>, or <see langword="null"/> if the current State is invalid.</returns> /// <returns>The tooltip as a <see cref="String"/>, or <see langword="null"/> if the current State is invalid.</returns>
private string GetPlayButtonTooltip() private string GetPlayButtonTooltip()
{
string profileName = ((profileDropDown != null) && (profileDropDown.Items.Count > 0)) ? profileDropDown.Items[profileDropDown.SelectedIndex].Text : "";
switch (updateState)
{ {
string profileName = ((profileDropDown != null) && (profileDropDown.Items.Count > 0)) ? profileDropDown.Items[profileDropDown.SelectedIndex].Text : ""; case PlayButtonState.Download: return Text.PlayButtonDownloadToolTip;
switch (updateState) case PlayButtonState.Downloading: return Text.PlayButtonDownloadToolTip;
{ case PlayButtonState.Select11: return Text.PlayButtonSelect11ToolTip;
case PlayButtonState.Download: return Text.PlayButtonDownloadToolTip; case PlayButtonState.Install: return playButton.ToolTip = HelperMethods.GetText(Text.PlayButtonInstallToolTip, profileName);
case PlayButtonState.Downloading: return Text.PlayButtonDownloadToolTip; case PlayButtonState.Installing: return Text.PlayButtonInstallingToolTip;
case PlayButtonState.Select11: return Text.PlayButtonSelect11ToolTip; case PlayButtonState.Play: return HelperMethods.GetText(Text.PlayButtonPlayToolTip, profileName);
case PlayButtonState.Install: return playButton.ToolTip = HelperMethods.GetText(Text.PlayButtonInstallToolTip, profileName); case PlayButtonState.Playing: return Text.PlayButtonPlayingToolTip;
case PlayButtonState.Installing: return Text.PlayButtonInstallingToolTip; default: return null;
case PlayButtonState.Play: return HelperMethods.GetText(Text.PlayButtonPlayToolTip, profileName);
case PlayButtonState.Playing: return Text.PlayButtonPlayingToolTip;
default: return null;
}
} }
}
/// <summary> /// <summary>
/// This returns the text that the apkButton should have depending on the global updateState. /// This returns the text that the apkButton should have depending on the global updateState.
/// </summary> /// </summary>
/// <returns>The text as a <see cref="String"/>, or <see langword="null"/> if the current State is invalid.</returns> /// <returns>The text as a <see cref="String"/>, or <see langword="null"/> if the current State is invalid.</returns>
private string GetApkButtonText() private string GetApkButtonText()
{
switch (apkButtonState)
{ {
switch (apkButtonState) case ApkButtonState.Create: return Text.CreateAPK;
{ case ApkButtonState.Creating: return Text.CreatingAPK;
case ApkButtonState.Create: return Text.CreateAPK; default: return null;
case ApkButtonState.Creating: return Text.CreatingAPK;
default: return null;
}
} }
}
/// <summary> /// <summary>
/// Loads valid profile entries and reloads the necessary UI components. /// Loads valid profile entries and reloads the necessary UI components.
/// </summary> /// </summary>
private void LoadProfilesAndAdjustLists() private void LoadProfilesAndAdjustLists()
{ {
// Reset loaded profiles // Reset loaded profiles
profileDropDown.Items.Clear(); profileDropDown.Items.Clear();
profileList.Clear(); profileList.Clear();
profileIndex = null; profileIndex = null;
// Load the profileList
profileList = Profile.LoadProfiles();
// Add profile names to the profileDropDown
foreach (ProfileXML profile in profileList)
{
// Archive version notes
if (!profile.Installable)
{
if (profile.Name.Contains("Community Updates"))
profile.ProfileNotes = Text.ArchiveNotesCommunityUpdates;
else
profile.ProfileNotes = Text.ArchiveNotesMods + "\n\n" + profile.ProfileNotes;
}
profileDropDown.Items.Add(profile.Name);
}
// Read the value from the config
string profIndexString = ReadFromConfig("ProfileIndex");
// Check if either no profile was found or the setting says that the last current profile didn't exist
if (profileDropDown.Items.Count == 0)
profileIndex = null;
else
{
// We know that profiles exist at this point, so we're going to point it to 0 instead so the following code doesn't fail
if (profIndexString == "null")
profIndexString = "0";
// We parse from the settings, and check if profiles got deleted from the last time the launcher has been selected. if yes, we revert the last selection to 0;
int intParseResult = Int32.Parse(profIndexString);
profileIndex = intParseResult;
if (profileIndex >= profileDropDown.Items.Count)
profileIndex = 0;
profileDropDown.SelectedIndex = profileIndex.Value;
}
// Update stored profiles in the Profile Settings tab // Load the profileList
modSettingsProfileDropDown.Items.Clear(); profileList = Profile.LoadProfiles();
modSettingsProfileDropDown.Items.AddRange(profileDropDown.Items);
modSettingsProfileDropDown.SelectedIndex = profileDropDown.Items.Count != 0 ? 0 : -1;
// Refresh the author and version label on the main tab // Add profile names to the profileDropDown
if (profileList.Count > 0) foreach (ProfileXML profile in profileList)
{
// Archive version notes
if (!profile.Installable)
{ {
profileAuthorLabel.Text = Text.Author + " " + profileList[profileDropDown.SelectedIndex].Author; if (profile.Name.Contains("Community Updates"))
profileVersionLabel.Text = Text.VersionLabel + " " + profileList[profileDropDown.SelectedIndex].Version; profile.ProfileNotes = Text.ArchiveNotesCommunityUpdates;
else
profile.ProfileNotes = Text.ArchiveNotesMods + "\n\n" + profile.ProfileNotes;
} }
log.Info("Reloading UI components after loading successful."); profileDropDown.Items.Add(profile.Name);
UpdateStateMachine();
} }
// Read the value from the config
string profIndexString = ReadFromConfig("ProfileIndex");
/// <summary> // Check if either no profile was found or the setting says that the last current profile didn't exist
/// Deletes a profile and reloads the necessary UI components. if (profileDropDown.Items.Count == 0)
/// </summary> profileIndex = null;
/// <param name="profile">The profile to delete.</param> else
private void DeleteProfileAndAdjustLists(ProfileXML profile)
{ {
Profile.DeleteProfile(profile); // We know that profiles exist at this point, so we're going to point it to 0 instead so the following code doesn't fail
LoadProfilesAndAdjustLists(); if (profIndexString == "null")
profIndexString = "0";
// We parse from the settings, and check if profiles got deleted from the last time the launcher has been selected. if yes, we revert the last selection to 0;
int intParseResult = Int32.Parse(profIndexString);
profileIndex = intParseResult;
if (profileIndex >= profileDropDown.Items.Count)
profileIndex = 0;
profileDropDown.SelectedIndex = profileIndex.Value;
} }
private void ArchiveProfileAndAdjustLists(ProfileXML profile) // Update stored profiles in the Profile Settings tab
{ modSettingsProfileDropDown.Items.Clear();
Profile.ArchiveProfile(profile); modSettingsProfileDropDown.Items.AddRange(profileDropDown.Items);
LoadProfilesAndAdjustLists(); modSettingsProfileDropDown.SelectedIndex = profileDropDown.Items.Count != 0 ? 0 : -1;
}
/// <summary>Enables and changes colors for <see cref="customMirrorTextBox"/> and <see cref="mirrorDropDown"/> accordingly.</summary> // Refresh the author and version label on the main tab
private void EnableMirrorControlsAccordingly() if (profileList.Count > 0)
{ {
bool enabled = (bool)customMirrorCheck.Checked; profileAuthorLabel.Text = Text.Author + " " + profileList[profileDropDown.SelectedIndex].Author;
customMirrorTextBox.Enabled = enabled; profileVersionLabel.Text = Text.VersionLabel + " " + profileList[profileDropDown.SelectedIndex].Version;
mirrorDropDown.Enabled = !enabled;
// Not sure why the dropdown menu needs this hack, but the textBox does not.
//TODO: eto feature request
if (OS.IsWindows)
mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive;
mirrorLabel.TextColor = !enabled ? colGreen : colInactive;
} }
log.Info("Reloading UI components after loading successful.");
UpdateStateMachine();
}
/// <summary>
/// Deletes a profile and reloads the necessary UI components.
/// </summary>
/// <param name="profile">The profile to delete.</param>
private void DeleteProfileAndAdjustLists(ProfileXML profile)
{
Profile.DeleteProfile(profile);
LoadProfilesAndAdjustLists();
}
private void ArchiveProfileAndAdjustLists(ProfileXML profile)
{
Profile.ArchiveProfile(profile);
LoadProfilesAndAdjustLists();
}
/// <summary>Enables and changes colors for <see cref="customMirrorTextBox"/> and <see cref="mirrorDropDown"/> accordingly.</summary>
private void EnableMirrorControlsAccordingly()
{
bool enabled = (bool)customMirrorCheck.Checked;
customMirrorTextBox.Enabled = enabled;
mirrorDropDown.Enabled = !enabled;
// Not sure why the dropdown menu needs this hack, but the textBox does not.
//TODO: eto feature request
if (OS.IsWindows)
mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive;
mirrorLabel.TextColor = !enabled ? colGreen : colInactive;
} }
} }

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save