Skip to content

Commit

Permalink
Add recent projects, build & run, toolbar icons (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
WiIIiam278 authored Feb 10, 2023
1 parent ba18582 commit 5e7c4f5
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 34 deletions.
49 changes: 31 additions & 18 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 @@ -24,29 +25,27 @@ public static Config LoadConfig(ILogger log)
if (!File.Exists(configJson))
{
log.Log($"Creating default config at '{configJson}'...");
Config defaultConfig = GetDefault();
Config defaultConfig = GetDefault(log);
defaultConfig.ValidateConfig(log);
defaultConfig.ConfigPath = configJson;
IO.WriteStringFile(configJson, JsonSerializer.Serialize(defaultConfig), log);
return defaultConfig;
}
else

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

Expand All @@ -58,7 +57,7 @@ public void ValidateConfig(ILogger log)
}
}

private static Config GetDefault()
private static Config GetDefault(ILogger log)
{
string devkitArmDir;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
Expand All @@ -74,10 +73,24 @@ 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 = "";
log.LogWarning("Valid emulator path not found in config.json.");
}

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
{
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/Help.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.
Binary file added src/SerialLoops/Icons/Warning.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.LogError($"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);
_log.LogWarning("No emulator path set. Please set the path to your emulator.");
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}");
}
}
else
{
_log.LogError("Build failed!");
}
}
}

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

0 comments on commit 5e7c4f5

Please sign in to comment.