Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add recent projects, build & run, toolbar icons #27

Merged
merged 12 commits into from
Feb 10, 2023
Merged
44 changes: 28 additions & 16 deletions src/SerialLoops.Lib/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class Config
public string ConfigPath { get; set; }
public string ProjectsDirectory { get; set; }
public string DevkitArmPath { get; set; }
public string EmulatorPath { get; set; }

public void Save(ILogger log)
{
Expand All @@ -30,23 +31,21 @@ public static Config LoadConfig(ILogger log)
IO.WriteStringFile(configJson, JsonSerializer.Serialize(defaultConfig), log);
return defaultConfig;
}
else

try
{
try
{
Config config = JsonSerializer.Deserialize<Config>(File.ReadAllText(configJson));
config.ValidateConfig(log);
config.ConfigPath = configJson;
return config;
}
catch (JsonException exc)
{
log.LogError($"Exception occurred while parsing config.json!\n{exc.Message}\n\n{exc.StackTrace}");
Config defaultConfig = GetDefault();
defaultConfig.ValidateConfig(log);
IO.WriteStringFile(configJson, JsonSerializer.Serialize(defaultConfig), log);
return defaultConfig;
}
Config config = JsonSerializer.Deserialize<Config>(File.ReadAllText(configJson));
config.ValidateConfig(log);
config.ConfigPath = configJson;
return config;
}
catch (JsonException exc)
{
log.LogError($"Exception occurred while parsing config.json!\n{exc.Message}\n\n{exc.StackTrace}");
Config defaultConfig = GetDefault();
defaultConfig.ValidateConfig(log);
IO.WriteStringFile(configJson, JsonSerializer.Serialize(defaultConfig), log);
return defaultConfig;
}
}

Expand Down Expand Up @@ -74,10 +73,23 @@ private static Config GetDefault()
devkitArmDir = "";
}

// TODO: Probably make a way of defining "presets" of common emulator install paths on different platforms.
// Ideally this should be as painless as possible.
string emulatorPath = "";
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
emulatorPath = Path.Combine("/Applications", "melonDS.app");
}
if (!Directory.Exists(emulatorPath))
{
emulatorPath = "";
WiIIiam278 marked this conversation as resolved.
Show resolved Hide resolved
}

return new Config
{
ProjectsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "SerialLoops"),
DevkitArmPath = devkitArmDir,
EmulatorPath = emulatorPath
};
}
}
Expand Down
70 changes: 70 additions & 0 deletions src/SerialLoops.Lib/RecentProjects.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using HaruhiChokuretsuLib.Util;

namespace SerialLoops.Lib
jonko0493 marked this conversation as resolved.
Show resolved Hide resolved
{
public class RecentProjects
{
private const int MAX_RECENT_PROJECTS = 10;
public string RecentProjectsPath { get; set; }
public List<string> Projects { get; set; }

public void Save(ILogger log)
{
log.Log($"Saving recent projects to '{RecentProjectsPath}'...");
IO.WriteStringFile(RecentProjectsPath, JsonSerializer.Serialize(this), log);
}

public static RecentProjects LoadRecentProjects(ILogger log)
{
string recentProjectsJson = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "recent_projects.json");
if (!File.Exists(recentProjectsJson))
{
log.Log($"Creating default recent projects cache at '{recentProjectsJson}'...");
RecentProjects defaultRecentProjects = GetDefault();
defaultRecentProjects.RecentProjectsPath = recentProjectsJson;
IO.WriteStringFile(recentProjectsJson, JsonSerializer.Serialize(defaultRecentProjects), log);
return defaultRecentProjects;
}

try
{
RecentProjects recentProjects = JsonSerializer.Deserialize<RecentProjects>(File.ReadAllText(recentProjectsJson));
recentProjects.RecentProjectsPath = recentProjectsJson;
return recentProjects;
}
catch (JsonException exc)
{
log.LogError($"Exception occurred while parsing recent_projects.json!\n{exc.Message}\n\n{exc.StackTrace}");
RecentProjects defaultRecentProjects = GetDefault();
IO.WriteStringFile(recentProjectsJson, JsonSerializer.Serialize(defaultRecentProjects), log);
return defaultRecentProjects;
}
}

private static RecentProjects GetDefault()
{
return new()
{
Projects = new List<string>()
};
}

public void AddProject(string projectPath)
{
if (Projects.Contains(projectPath))
{
Projects.Remove(projectPath);
}
if (Projects.Count >= MAX_RECENT_PROJECTS)
{
Projects.RemoveAt(Projects.Count - 1);
}
Projects.Insert(0, projectPath);
}

}
}
Binary file added src/SerialLoops/Icons/Build.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/SerialLoops/Icons/Build_Run.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/SerialLoops/Icons/Build_Scratch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/SerialLoops/Icons/Search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 88 additions & 7 deletions src/SerialLoops/MainForm.eto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using SerialLoops.Utility;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

Expand All @@ -18,10 +19,13 @@ public partial class MainForm : Form
private const string BASE_TITLE = "Serial Loops";

private LoopyLogger _log;
public RecentProjects RecentProjects { get; set; }
public Config CurrentConfig { get; set; }
public Project OpenProject { get; set; }
public EditorTabsPanel EditorTabs { get; set; }
public ItemExplorerPanel ItemExplorer { get; set; }

private readonly SubMenuItem _recentProjects = new() { Text = "Recent Projects" };

void InitializeComponent()
{
Expand All @@ -43,23 +47,26 @@ void InitializeComponent()
saveProject.Executed += SaveProject_Executed;

// Tools
Command searchProject = new() { MenuText = "Search", ToolBarText = "Search", Shortcut = Application.Instance.CommonModifier | Keys.F };
Command searchProject = new() { MenuText = "Search", ToolBarText = "Search", Shortcut = Application.Instance.CommonModifier | Keys.F, Image = ControlGenerator.GetIcon("Search", _log) };
searchProject.Executed += Search_Executed;

// Build
Command buildIterativeProject = new() { MenuText = "Build", ToolBarText = "Build" };
Command buildIterativeProject = new() { MenuText = "Build", ToolBarText = "Build", Image = ControlGenerator.GetIcon("Build", _log) };
buildIterativeProject.Executed += BuildIterativeProject_Executed;

Command buildBaseProject = new() { MenuText = "Build from Scratch", ToolBarText = "Build from Scratch" };
Command buildBaseProject = new() { MenuText = "Build from Scratch", ToolBarText = "Build from Scratch", Image = ControlGenerator.GetIcon("Build_Scratch", _log) };
buildBaseProject.Executed += BuildBaseProject_Executed;

Command buildAndRunProject = new() { MenuText = "Build and Run", ToolBarText = "Run", Image = ControlGenerator.GetIcon("Build_Run", _log) };
buildAndRunProject.Executed += BuildAndRunProject_Executed;

// Application Items
Command preferencesCommand = new();
preferencesCommand.Executed += PreferencesCommand_Executed;

// About
Command aboutCommand = new() { MenuText = "About..." };
AboutDialog aboutDialog = new() { ProgramName = "Serial Loops", Developers = new string[] { "Jonko", "William" }, Copyright = "© Haroohie Translation Club, 2023", Website = new Uri("https://haroohie.club") };
AboutDialog aboutDialog = new() { ProgramName = "Serial Loops", Developers = new[] { "Jonko", "William" }, Copyright = "© Haroohie Translation Club, 2023", Website = new Uri("https://haroohie.club") };
aboutCommand.Executed += (sender, e) => aboutDialog.ShowDialog(this);

// create menu
Expand All @@ -68,11 +75,11 @@ void InitializeComponent()
Items =
{
// File submenu
new SubMenuItem { Text = "&File", Items = { newProject, openProject, saveProject } },
new SubMenuItem { Text = "&File", Items = { newProject, openProject, _recentProjects, saveProject } },
new SubMenuItem { Text = "&Tools", Items = { searchProject } },
// new SubMenuItem { Text = "&Edit", Items = { /* commands/items */ } },
// new SubMenuItem { Text = "&View", Items = { /* commands/items */ } },
new SubMenuItem { Text = "&Build", Items = { buildIterativeProject, buildBaseProject } },
new SubMenuItem { Text = "&Build", Items = { buildIterativeProject, buildBaseProject, buildAndRunProject } },
},
ApplicationItems =
{
Expand All @@ -86,7 +93,9 @@ void InitializeComponent()
{
Items =
{
buildIterativeProject
buildIterativeProject,
buildAndRunProject,
searchProject
}
};
}
Expand All @@ -97,13 +106,43 @@ private void OpenProjectView(Project project)
ItemExplorer = new(project, EditorTabs, _log);
Title = $"{BASE_TITLE} - {project.Name}";
Content = new TableLayout(new TableRow(ItemExplorer, EditorTabs));
try
{
RecentProjects.AddProject(Path.Combine(project.MainDirectory, $"{project.Name}.{Project.PROJECT_FORMAT}"));
RecentProjects.Save(_log);
UpdateRecentProjects();
}
catch (Exception e)
{
_log.Log($"Failed to add project to recent projects list: {e.Message}");
}
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_log = new();
CurrentConfig = Config.LoadConfig(_log);
RecentProjects = RecentProjects.LoadRecentProjects(_log);
UpdateRecentProjects();
}

private void UpdateRecentProjects()
{
_recentProjects.Items.Clear();
foreach (string project in RecentProjects.Projects)
{
Command recentProject = new() { MenuText = Path.GetFileNameWithoutExtension(project), ToolTip = project };
recentProject.Executed += OpenRecentProject_Executed;
if (!File.Exists(project))
{
recentProject.Enabled = false;
recentProject.MenuText += " (Missing)";
recentProject.Image = ControlGenerator.GetIcon("Warning", _log);
}
_recentProjects.Items.Add(recentProject);
}
_recentProjects.Enabled = _recentProjects.Items.Count > 0;
}

private void NewProjectCommand_Executed(object sender, EventArgs e)
Expand All @@ -127,6 +166,13 @@ private void OpenProject_Executed(object sender, EventArgs e)
OpenProjectView(OpenProject);
}
}

private void OpenRecentProject_Executed(object sender, EventArgs e)
{
Command command = (Command)sender;
OpenProject = Project.OpenProject(command.ToolTip, CurrentConfig, _log);
OpenProjectView(OpenProject);
}

private void SaveProject_Executed(object sender, EventArgs e)
{
Expand Down Expand Up @@ -195,6 +241,41 @@ private async void BuildBaseProject_Executed(object sender, EventArgs e)
}
}
}

private async void BuildAndRunProject_Executed(object sender, EventArgs e)
{
if (OpenProject is not null)
{
if (CurrentConfig.EmulatorPath is null)
{
MessageBox.Show("No emulator path set. Please set the path to your emulator.", "No Emulator Path", MessageBoxType.Warning);
WiIIiam278 marked this conversation as resolved.
Show resolved Hide resolved
return;
}
if (await Build.BuildIterative(OpenProject, CurrentConfig, _log))
{
_log.Log("Build succeeded!");
try
{
// If the EmulatorPath is an .app bundle, we need to run the executable inside it
string emulatorExecutable = CurrentConfig.EmulatorPath;
if (emulatorExecutable.EndsWith(".app"))
{
emulatorExecutable = Path.Combine(CurrentConfig.EmulatorPath, "Contents", "MacOS", Path.GetFileNameWithoutExtension(CurrentConfig.EmulatorPath));
}

Process.Start(emulatorExecutable, $"\"{Path.Combine(OpenProject.MainDirectory, $"{OpenProject.Name}.nds")}\"");
} catch (Exception ex)
{
_log.LogError($"Failed to start emulator: {ex.Message}");
MessageBox.Show("Failed to start your emulator", "Emulator Startup Failed", MessageBoxType.Error);
WiIIiam278 marked this conversation as resolved.
Show resolved Hide resolved
}
}
else
{
_log.LogError("Build failed!");
}
}
}

private void PreferencesCommand_Executed(object sender, EventArgs e)
{
Expand Down
Loading