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.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>
/// Class that checks for Updates and then Updates the Launcher.
/// </summary>
//TODO: Mac support for auto updater in general
public static class LauncherUpdater
{
// How often this was broken count: 7
// Auto updating is fun!
// How often this was broken count: 7
// Auto updating is fun!
/// <summary>The Version that identifies this current release.</summary>
public const string VERSION = Core.Version;
/// <summary>The Version that identifies this current release.</summary>
public const string VERSION = Core.Version;
/// <summary>The Path of the oldConfig. Only gets used Windows-only</summary>
private static readonly string oldConfigPath = CrossPlatformOperations.CurrentPath + "/" + CrossPlatformOperations.LauncherName + ".oldCfg";
/// <summary>The Path of the oldConfig. Only gets used Windows-only</summary>
private static readonly string oldConfigPath = CrossPlatformOperations.CurrentPath + "/" + CrossPlatformOperations.LauncherName + ".oldCfg";
/// <summary>The actual Path where the executable is stored, only used for updating.</summary>
private static readonly string updatePath = OS.IsWindows ? CrossPlatformOperations.CurrentPath
: (OS.IsLinux ? Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) : Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory + "../../../"));
/// <summary>The actual Path where the executable is stored, only used for updating.</summary>
private static readonly string updatePath = OS.IsWindows ? CrossPlatformOperations.CurrentPath
: (OS.IsLinux ? Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) : Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory + "../../../"));
/// <summary>
/// Our log object, that handles logging the current execution to a file.
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(LauncherUpdater));
/// <summary>
/// Our log object, that handles logging the current execution to a file.
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(LauncherUpdater));
/// <summary>
/// Performs the entire AM2RLauncher update procedure.
/// </summary>
public static void Main()
{
log.Info("Running update check...");
/// <summary>
/// Performs the entire AM2RLauncher update procedure.
/// </summary>
public static void Main()
{
log.Info("Running update check...");
// Update section
// Update section
// Clean old files that have been left
if (File.Exists(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak"))
{
log.Info("AM2RLauncher.bak detected. Removing file.");
File.Delete(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak");
}
if (OS.IsWindows && File.Exists(oldConfigPath))
{
log.Info(CrossPlatformOperations.LauncherName + ".oldCfg detected. Removing file.");
File.Delete(oldConfigPath);
}
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/oldLib"))
// Clean old files that have been left
if (File.Exists(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak"))
{
log.Info("AM2RLauncher.bak detected. Removing file.");
File.Delete(CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak");
}
if (OS.IsWindows && File.Exists(oldConfigPath))
{
log.Info(CrossPlatformOperations.LauncherName + ".oldCfg detected. Removing file.");
File.Delete(oldConfigPath);
}
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.");
Directory.Delete(CrossPlatformOperations.CurrentPath + "/oldLib", true);
if (file.Name.EndsWith(".bak"))
file.Delete();
}
// Clean up old update libs
if (OS.IsWindows && Directory.Exists(CrossPlatformOperations.CurrentPath + "/lib"))
// Do the same for each subdirectory
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"))
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
bool autoUpdate = Boolean.Parse(MainForm.ReadFromConfig("AutoUpdateLauncher"));
// Check settings if autoUpdateLauncher is set to true
bool autoUpdate = Boolean.Parse(MainForm.ReadFromConfig("AutoUpdateLauncher"));
if (autoUpdate)
{
log.Info("AutoUpdate Launcher set to true!");
if (autoUpdate)
{
log.Info("AutoUpdate Launcher set to true!");
// 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
if (OS.IsWindows)
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}
// 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
if (OS.IsWindows)
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest");
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException)
{
log.Error("WebException caught! Displaying MessageBox.");
MessageBox.Show(Language.Text.NoInternetConnection);
return;
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest");
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException)
{
log.Error("WebException caught! Displaying MessageBox.");
MessageBox.Show(Language.Text.NoInternetConnection);
return;
}
Uri realUri = response.ResponseUri;
string onlineVersion = realUri.AbsoluteUri.Substring(realUri.AbsoluteUri.LastIndexOf('/') + 1);
bool isCurrentVersionOutdated = false;
Uri realUri = response.ResponseUri;
string onlineVersion = realUri.AbsoluteUri.Substring(realUri.AbsoluteUri.LastIndexOf('/') + 1);
bool isCurrentVersionOutdated = false;
string[] localVersionArray = VERSION.Split('.');
string[] onlineVersionArray = onlineVersion.Split('.');
string[] localVersionArray = VERSION.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]);
int localNum = Int32.Parse(localVersionArray[i]);
if (onlineNum > localNum)
{
isCurrentVersionOutdated = true;
break;
}
if (localNum > onlineNum)
break;
isCurrentVersionOutdated = true;
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
if (!isCurrentVersionOutdated)
return;
// No new update, exiting
if (!isCurrentVersionOutdated)
return;
// 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.
if (OS.IsMac)
{
MessageBox.Show("Your current version is outdated! The newest version is " + onlineVersion + "." +
"Please recompile AM2RLauncher again or disable auto-updating");
return;
}
// 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.
if (OS.IsMac)
{
MessageBox.Show("Your current version is outdated! The newest version is " + onlineVersion + "." +
"Please recompile AM2RLauncher again or disable auto-updating");
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 zipPath = CrossPlatformOperations.CurrentPath + "/launcher.zip";
string tmpUpdatePath = CrossPlatformOperations.CurrentPath + "/tmpupdate/";
string zipPath = CrossPlatformOperations.CurrentPath + "/launcher.zip";
// Clean tmpupdate
if (Directory.Exists(tmpUpdatePath))
Directory.Delete(tmpUpdatePath, true);
if (!Directory.Exists(tmpUpdatePath))
Directory.CreateDirectory(tmpUpdatePath);
// Clean tmpupdate
if (Directory.Exists(tmpUpdatePath))
Directory.Delete(tmpUpdatePath, true);
if (!Directory.Exists(tmpUpdatePath))
Directory.CreateDirectory(tmpUpdatePath);
try
{
using var client = new WebClient();
string platformSuffix = "";
if (OS.IsWindows) platformSuffix = "_win";
else if (OS.IsLinux) platformSuffix = "_lin";
try
{
using var client = new WebClient();
string platformSuffix = "";
if (OS.IsWindows) platformSuffix = "_win";
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.");
}
catch (UnauthorizedAccessException)
{
log.Error("UnauthorizedAccessException caught! Displaying MessageBox.");
MessageBox.Show(Language.Text.UnauthorizedAccessMessage);
return;
}
log.Info("File successfully downloaded.");
}
catch (UnauthorizedAccessException)
{
log.Error("UnauthorizedAccessException caught! Displaying MessageBox.");
MessageBox.Show(Language.Text.UnauthorizedAccessMessage);
return;
}
ZipFile.ExtractToDirectory(zipPath, tmpUpdatePath);
log.Info("Updates successfully extracted to " + tmpUpdatePath);
ZipFile.ExtractToDirectory(zipPath, tmpUpdatePath);
log.Info("Updates successfully extracted to " + tmpUpdatePath);
File.Delete(zipPath);
File.Move(updatePath + "/" + CrossPlatformOperations.LauncherName, CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak");
if (OS.IsWindows) File.Move(CrossPlatformOperations.LauncherName + ".config", CrossPlatformOperations.LauncherName + ".oldCfg");
File.Delete(zipPath);
File.Move(updatePath + "/" + CrossPlatformOperations.LauncherName, CrossPlatformOperations.CurrentPath + "/AM2RLauncher.bak");
if (OS.IsWindows) File.Move(CrossPlatformOperations.LauncherName + ".config", CrossPlatformOperations.LauncherName + ".oldCfg");
foreach (var file in new DirectoryInfo(tmpUpdatePath).GetFiles())
{
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.Copy(file.FullName, updatePath + "/" + file.Name, true);
file.CopyTo(file.Directory + "/" + file.Name + ".bak");
}
// 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
foreach (FileInfo file in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetFiles())
{
file.CopyTo(file.Directory + "/" + file.Name + ".bak");
}
// Do the same for each sub directory
foreach (DirectoryInfo dir in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetDirectories())
// Do the same for each sub directory
foreach (DirectoryInfo dir in new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/lib").GetDirectories())
{
foreach (FileInfo file in dir.GetFiles())
{
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...");
if (OS.IsLinux) System.Diagnostics.Process.Start("chmod", "+x " + updatePath + "./AM2RLauncher.Gtk");
MainForm.CopyOldConfigToNewConfig();
System.Diagnostics.Process.Start(updatePath + "/" + CrossPlatformOperations.LauncherName);
Environment.Exit(0);
}
else
{
log.Info("AutoUpdate Launcher set to false. Exiting update check.");
}
log.Info("Files extracted. Preparing to restart executable...");
if (OS.IsLinux) System.Diagnostics.Process.Start("chmod", "+x " + updatePath + "./AM2RLauncher.Gtk");
System.Diagnostics.Process.Start(updatePath + "/" + CrossPlatformOperations.LauncherName);
Environment.Exit(0);
}
else
{
log.Info("AutoUpdate Launcher set to false. Exiting update check.");
}
}
}

@ -2,73 +2,72 @@
using Eto.Forms;
using Pablo.Controls;
namespace AM2RLauncher
namespace AM2RLauncher;
/// <summary>
/// Extension of <see cref="CustomButton"/> that allows for advanced color settings.
/// </summary>
class ColorButton : CustomButton
{
/// <summary>
/// Extension of <see cref="CustomButton"/> that allows for advanced color settings.
/// </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="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>
public Font Font { get; set; }
/// <summary>The <see cref="Font"/> to use for text drawing.</summary>
public Font Font { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the frame.</summary>
public Color FrameColor { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the frame.</summary>
public Color FrameColor { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the frame when it is disabled.</summary>
public Color FrameColorDisabled { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the frame when it is disabled.</summary>
public Color FrameColorDisabled { get; set; }
/// <summary>The text to be drawn.</summary>
public string Text { get; set; }
/// <summary>The text to be drawn.</summary>
public string Text { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/>.</summary>
public Color TextColor { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/>.</summary>
public Color TextColor { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/> when it is disabled.</summary>
public Color TextColorDisabled { get; set; }
/// <summary>The <see cref="Color"/> with which to draw the <see cref="Text"/> when it is disabled.</summary>
public Color TextColorDisabled { get; set; }
/// <summary>
/// Creates a <see cref="ColorButton"/> with a default set of attributes.
/// </summary>
public ColorButton()
{
BackgroundColorHover = Colors.White;
Font = new Font(SystemFont.Default, 12);
FrameColor = Colors.White;
FrameColorDisabled = Colors.Gray;
Text = "";
TextColor = Colors.Black;
TextColorDisabled = Colors.Gray;
}
/// <summary>
/// Creates a <see cref="ColorButton"/> with a default set of attributes.
/// </summary>
public ColorButton()
{
BackgroundColorHover = Colors.White;
Font = new Font(SystemFont.Default, 12);
FrameColor = Colors.White;
FrameColorDisabled = Colors.Gray;
Text = "";
TextColor = Colors.Black;
TextColorDisabled = Colors.Gray;
}
/// <summary>
/// Event raised to draw this control.
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe)
{
// Define draw bounds
Rectangle drawBounds = new Rectangle(2, 2, Width - 5, Height - 5);
/// <summary>
/// Event raised to draw this control.
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe)
{
// Define draw bounds
Rectangle drawBounds = new Rectangle(2, 2, Width - 5, Height - 5);
// Draw background
pe.Graphics.FillRectangle(Hover ? BackgroundColorHover : BackgroundColor, drawBounds);
// Draw background
pe.Graphics.FillRectangle(Hover ? BackgroundColorHover : BackgroundColor, drawBounds);
// Draw frame
Pen framePen = new Pen(Enabled ? FrameColor : FrameColorDisabled, 1);
pe.Graphics.DrawRectangle(framePen, drawBounds);
// Draw frame
Pen framePen = new Pen(Enabled ? FrameColor : FrameColorDisabled, 1);
pe.Graphics.DrawRectangle(framePen, drawBounds);
SolidBrush brush = new SolidBrush(Enabled ? TextColor : TextColorDisabled);
SolidBrush brush = new SolidBrush(Enabled ? TextColor : TextColorDisabled);
// Get text measurements
SizeF stringSize = pe.Graphics.MeasureString(Font, Text);
int textWidth = (int)stringSize.Width;
int textHeight = (int)stringSize.Height;
// Get text measurements
SizeF stringSize = pe.Graphics.MeasureString(Font, Text);
int textWidth = (int)stringSize.Width;
int textHeight = (int)stringSize.Height;
// Draw text
pe.Graphics.DrawText(Font, brush, new PointF(Width / 2 - textWidth / 2, Height / 2 - textHeight / 2), Text);
}
// Draw 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 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>
/// 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>Whether or not this <see cref="CustomButton"/> is being pressed.</summary>
bool pressed;
/// <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>
bool hover;
/// <summary>Whether or not the mouse is hovering over this <see cref="CustomButton"/>.</summary>
bool hover;
/// <summary></summary>
bool mouseDown;
/// <summary></summary>
bool mouseDown;
/// <summary>Gets or sets the disabled color of this control.</summary>
public static Color DisabledColor = Color.FromGrayscale(0.4f, 0.3f);
/// <summary>Gets or sets the disabled color of this control.</summary>
public static Color DisabledColor = Color.FromGrayscale(0.4f, 0.3f);
/// <summary>Gets or sets the color of this control.</summary>
public static Color EnabledColor = Colors.Black;
/// <summary>Gets or sets the color of this control.</summary>
public static Color EnabledColor = Colors.Black;
/// <summary>Gets or sets whether or not this control is enabled.</summary>
public override bool Enabled
/// <summary>Gets or sets whether or not this control is enabled.</summary>
public override bool Enabled
{
get { return base.Enabled; }
set
{
get { return base.Enabled; }
set
if (base.Enabled != value)
{
if (base.Enabled != value)
{
base.Enabled = value;
if (Loaded)
Invalidate();
}
base.Enabled = value;
if (Loaded)
Invalidate();
}
}
}
/// <summary>Gets or sets <see cref="pressed"/>.</summary>
public bool Pressed
/// <summary>Gets or sets <see cref="pressed"/>.</summary>
public bool Pressed
{
get { return pressed; }
set
{
get { return pressed; }
set
if (pressed != value)
{
if (pressed != value)
{
pressed = value;
mouseDown = false;
if (Loaded)
Invalidate();
}
pressed = value;
mouseDown = false;
if (Loaded)
Invalidate();
}
}
}
/// <summary>Gets <see cref="hover"/>.</summary>
public bool Hover
{
get { return hover; }
}
/// <summary>Gets <see cref="hover"/>.</summary>
public bool Hover
{
get { return hover; }
}
/// <summary>Gets either the <see cref="EnabledColor"/> or <see cref="DisabledColor"/> dependent on <see cref="Enabled"/>.</summary>
public Color DrawColor
{
get { return Enabled ? EnabledColor : DisabledColor; }
}
/// <summary>Gets either the <see cref="EnabledColor"/> or <see cref="DisabledColor"/> dependent on <see cref="Enabled"/>.</summary>
public Color DrawColor
{
get { return Enabled ? EnabledColor : DisabledColor; }
}
/// <summary>Gets or sets whether or not this control should act as a toggle.</summary>
public bool Toggle { get; set; }
/// <summary>Gets or sets whether or not this control should act as a toggle.</summary>
public bool Toggle { get; set; }
/// <summary>Gets or sets whether or not this control is persistent.</summary>
public bool Persistent { get; set; }
/// <summary>Gets or sets whether or not this control is persistent.</summary>
public bool Persistent { get; set; }
public event EventHandler<EventArgs> Click;
public event EventHandler<EventArgs> Click;
/// <summary>
/// Event raised when this control is clicked.
/// </summary>
/// <param name="e"></param>
protected virtual void OnClick(EventArgs e)
{
if (Click != null)
Click(this, e);
}
/// <summary>
/// Event raised when this control is clicked.
/// </summary>
/// <param name="e"></param>
protected virtual void OnClick(EventArgs e)
{
if (Click != null)
Click(this, e);
}
/// <summary>Default constructor. Sets <see cref="Enabled"/> to true.</summary>
public CustomButton() { Enabled = true; }
/// <summary>Default constructor. Sets <see cref="Enabled"/> to true.</summary>
public CustomButton() { Enabled = true; }
/// <summary>Event raised when this control is resized.</summary>
/// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e)
/// <summary>Event raised when this control is resized.</summary>
/// <param name="e"></param>
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);
if (Loaded)
Invalidate();
mouseDown = true;
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>
/// 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)
/// <summary>
/// Event raised when the mouse leaves this control's bounding box.
/// </summary>
/// <param name="e"></param>
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)
{
mouseDown = true;
Invalidate();
}
OnClick(EventArgs.Empty);
}
/// <summary>
/// Event raised when the mouse enters this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseEnter(MouseEventArgs e)
else
{
Cursor = new Cursor(CursorType.Pointer);
base.OnMouseEnter(e);
hover = true;
Invalidate();
mouseDown = false;
this.Invalidate();
}
}
/// <summary>
/// Event raised when the mouse leaves this control's bounding box.
/// </summary>
/// <param name="e"></param>
protected override void OnMouseLeave(MouseEventArgs e)
/// <summary>
/// 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))
{
Cursor = new Cursor(CursorType.Default);
base.OnMouseLeave(e);
hover = false;
Invalidate();
pe.Graphics.FillRectangle(col, rect);
pe.Graphics.DrawInsetRectangle(Colors.Gray, Colors.White, rect);
}
/// <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)
else if (hover && Enabled)
{
base.OnMouseUp(e);
var rect = new Rectangle(this.Size);
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();
}
pe.Graphics.FillRectangle(col, rect);
pe.Graphics.DrawInsetRectangle(Colors.White, Colors.Gray, rect);
}
/// <summary>
/// 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);
}
base.OnPaint(pe);
}
}
}

@ -1,105 +1,103 @@
using Eto.Drawing;
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>
/// 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.
/// Whether or not this control's size has been set.
/// </summary>
public class ImageButton : CustomButton
{
/// <summary>
/// Whether or not this control's size has been set.
/// </summary>
bool sizeSet;
bool sizeSet;
/// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/>.
/// </summary>
public Image Image { get; set; }
/// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/>.
/// </summary>
public Image Image { get; set; }
/// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/> if this control is disabled.
/// </summary>
public Image DisabledImage { get; set; }
/// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Image"/> to draw during <see cref="OnPaint"/> if this control is disabled.
/// </summary>
public Image DisabledImage { get; set; }
/// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Size"/> of this control.
/// </summary>
public override Size Size
{
get { return base.Size; }
set { base.Size = value; sizeSet = true; }
}
/// <summary>
/// Gets or sets the <see cref="Eto.Drawing.Size"/> of this control.
/// </summary>
public override Size Size
{
get { return base.Size; }
set { base.Size = value; sizeSet = true; }
}
/// <summary>
/// Default constructor, assigns no special attributes.
/// </summary>
public ImageButton() { }
/// <summary>
/// Default constructor, assigns no special attributes.
/// </summary>
public ImageButton() { }
/// <summary>
/// Event raised when this control is loading.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
/// <summary>
/// Event raised when this control is loading.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (Image != null)
{
base.OnLoad(e);
if (Image != null)
{
if (!sizeSet)
this.Size = Image.Size + 4;
}
if (!sizeSet)
this.Size = Image.Size + 4;
}
}
/// <summary>
/// Event raised when this control has finished loading.
/// </summary>
/// <param name="e"></param>
protected override void OnLoadComplete(EventArgs e)
{
base.OnLoadComplete(e);
/// <summary>
/// Event raised when this control has finished loading.
/// </summary>
/// <param name="e"></param>
protected override void OnLoadComplete(EventArgs e)
{
base.OnLoadComplete(e);
if (DisabledImage == null)
if (DisabledImage == null)
{
var image = Image;
if (image != null)
{
var image = Image;
if (image != null)
var disabledImage = new Bitmap(image.Size.Width, image.Size.Height, PixelFormat.Format32bppRgba);
using (var graphics = new Graphics(disabledImage))
{
var disabledImage = new Bitmap(image.Size.Width, image.Size.Height, PixelFormat.Format32bppRgba);
using (var graphics = new Graphics(disabledImage))
{
graphics.DrawImage(image, 0, 0);
}
using (var bd = disabledImage.Lock())
graphics.DrawImage(image, 0, 0);
}
using (var bd = disabledImage.Lock())
{
unsafe
{
unsafe
var data = (int*)bd.Data;
for (int i = 0; i < bd.ScanWidth * disabledImage.Size.Height; i++)
{
var data = (int*)bd.Data;
for (int i = 0; i < bd.ScanWidth * disabledImage.Size.Height; i++)
{
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());
}
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 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>
/// 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(() =>
{
Application.Instance.Invoke(() =>
{
progressBar.MinValue = min;
progressBar.MaxValue = max;
progressBar.Value = value;
});
}
progressBar.MinValue = min;
progressBar.MaxValue = max;
progressBar.Value = value;
});
}
/// <summary>
/// Method that updates <see cref="progressBar"/> with a min value of 0 and max value of 100.
/// </summary>
/// <param name="value">The value that <see cref="progressBar"/> should be set to.</param>
private void UpdateProgressBar(int value)
{
UpdateProgressBar(value, 0, 100);
}
/// <summary>
/// Method that updates <see cref="progressBar"/> with a min value of 0 and max value of 100.
/// </summary>
/// <param name="value">The value that <see cref="progressBar"/> should be set to.</param>
private void UpdateProgressBar(int value)
{
UpdateProgressBar(value, 0, 100);
}
/// <summary>
/// Safety check function before accessing <see cref="profileIndex"/>.
/// </summary>
/// <returns><see langword="true"/> if it is valid, <see langword="false"/> if not.</returns>
private bool IsProfileIndexValid()
/// <summary>
/// Safety check function before accessing <see cref="profileIndex"/>.
/// </summary>
/// <returns><see langword="true"/> if it is valid, <see langword="false"/> if not.</returns>
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>
/// 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)
/// <summary>
/// Creates a single-file, zip-filtered file dialog.
/// </summary>
/// <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!!!!
// Also tldr; rtfm
if (isGitProcessGettingCancelled) return false;
Directory = new Uri(CrossPlatformOperations.CurrentPath),
MultiSelect = 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
// Otherwise this will throw a runtime exception
Application.Instance.Invoke(() =>
{
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;
}
private void DisableProgressBar()
{
progressBar.Visible = false;
progressBar.Value = 0;
}
/// <summary>
/// Creates a single-file, zip-filtered file dialog.
/// </summary>
/// <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
{
Directory = new Uri(CrossPlatformOperations.CurrentPath),
MultiSelect = false,
Title = title
};
fileDialog.Filters.Add(new FileFilter(Text.ZipArchiveText, ".zip"));
return fileDialog;
}
private void EnableProgressBar()
{
progressBar.Visible = true;
progressBar.Value = 0;
}
private void DisableProgressBar()
{
progressBar.Visible = false;
progressBar.Value = 0;
}
private void DisableProgressBarAndProgressLabel()
{
DisableProgressBar();
progressLabel.Visible = false;
progressLabel.Text = "";
}
private void EnableProgressBar()
{
progressBar.Visible = true;
progressBar.Value = 0;
}
private void EnableProgressBarAndLabel()
{
EnableProgressBar();
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();
progressLabel.Visible = false;
progressLabel.Text = "";
// We use the configuration manager in order to read `property` from the app.config and then return it
ConnectionStringSettings appConfig = ConfigurationManager.ConnectionStrings[property];
if (appConfig == null) throw new ArgumentException("The property " + property + " could not be found.");
return appConfig.ConnectionString;
}
private void EnableProgressBarAndLabel()
if (OS.IsUnix)
{
EnableProgressBar();
progressLabel.Visible = true;
progressLabel.Text = "";
}
string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
string launcherConfigPath = Path.GetDirectoryName(launcherConfigFilePath);
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
/// <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)
// If folder doesn't exist, create it and the config file
if (!Directory.Exists(launcherConfigPath) || !File.Exists(launcherConfigFilePath))
{
// We use the configuration manager in order to read `property` from the app.config and then return it
ConnectionStringSettings appConfig = ConfigurationManager.ConnectionStrings[property];
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();
Directory.CreateDirectory(launcherConfigPath);
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
log.Error(OS.Name + " has no config to read from!");
return null;
// 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();
}
/// <summary>
/// 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.Error(OS.Name + " has no config to read from!");
return null;
}
/// <summary>
/// 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.");
if (OS.IsWindows)
{
// We use the configuration manager in order to read from the app.config, change the value and save it
Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (appConfig == null)
throw new NullReferenceException("Could not find the Config file! Please make sure it exists!");
ConnectionStringsSection connectionStringsSection = (ConnectionStringsSection)appConfig.GetSection("connectionStrings");
if (connectionStringsSection?.ConnectionStrings[property]?.ConnectionString == null)
throw new ArgumentException("The property " + property + " could not be found.");
connectionStringsSection.ConnectionStrings[property].ConnectionString = value.ToString();
appConfig.Save();
ConfigurationManager.RefreshSection("connectionStrings");
}
else if (OS.IsUnix)
// We use the configuration manager in order to read from the app.config, change the value and save it
Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (appConfig == null)
throw new NullReferenceException("Could not find the Config file! Please make sure it exists!");
ConnectionStringsSection connectionStringsSection = (ConnectionStringsSection)appConfig.GetSection("connectionStrings");
if (connectionStringsSection?.ConnectionStrings[property]?.ConnectionString == null)
throw new ArgumentException("The property " + property + " could not be found.");
connectionStringsSection.ConnectionStrings[property].ConnectionString = value.ToString();
appConfig.Save();
ConfigurationManager.RefreshSection("connectionStrings");
}
else 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))
{
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));
// Uses indexer. Look at LauncherConfigXML for more info
launcherConfig[property] = value;
// Serialize back into the file
Directory.CreateDirectory(launcherConfigPath);
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
else
log.Error(OS.Name + " has no config to write to!");
// 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));
}
else
log.Error(OS.Name + " has no config to write to!");
}
/// <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.
/// </summary>
public static void CopyOldConfigToNewConfig()
/// <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.
/// </summary>
public static void CopyOldConfigToNewConfig()
{
if (OS.IsWindows)
{
if (OS.IsWindows)
{
string oldConfigPath = CrossPlatformOperations.LauncherName + ".oldCfg";
string newConfigPath = CrossPlatformOperations.LauncherName + ".config";
string oldConfigText = File.ReadAllText(oldConfigPath);
string newConfigText = File.ReadAllText(newConfigPath);
string oldConfigPath = CrossPlatformOperations.LauncherName + ".oldCfg";
string newConfigPath = CrossPlatformOperations.LauncherName + ".config";
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 newMatch = settingRegex.Matches(newConfigText);
MatchCollection oldMatch = settingRegex.Matches(oldConfigText);
MatchCollection newMatch = settingRegex.Matches(newConfigText);
for (int i = 0; i < oldMatch.Count; i++)
newConfigText = newConfigText.Replace(newMatch[i].Value, oldMatch[i].Value);
for (int i = 0; i < oldMatch.Count; i++)
newConfigText = newConfigText.Replace(newMatch[i].Value, oldMatch[i].Value);
File.WriteAllText(newConfigPath, newConfigText);
File.WriteAllText(newConfigPath, newConfigText);
}
else if (OS.IsUnix)
{
string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
}
else if (OS.IsUnix)
{
string launcherConfigFilePath = CrossPlatformOperations.NixLauncherConfigFilePath;
// 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));
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
else
log.Error(OS.Name + " has no config to transfer over!");
// 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));
File.WriteAllText(launcherConfigFilePath, Serializer.Serialize<XML.LauncherConfigXML>(launcherConfig));
}
else
log.Error(OS.Name + " has no config to transfer over!");
}
}

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