Switched to dependency injection for console use.

Created interfaces for input and output for better structure and easier testing.
This commit is contained in:
Harrison Deng 2020-02-23 20:51:39 -05:00
parent 72a1ba903b
commit fa74bc9ae5
12 changed files with 119 additions and 105 deletions

View File

@ -14,25 +14,25 @@ namespace RecrownedGTK.Tools.CommandProcessor
commands = new List<EngineCommand>(); commands = new List<EngineCommand>();
} }
public void Run(IUserInput input) public void Run(IUserInput input, IUserOutput output)
{ {
while (running) while (running)
{ {
ConsoleUtilities.WriteWrappedLine("\nAwaiting command."); output.WrappedOutput("\nAwaiting command.");
string command = input.GetInput(); string command = input.GetInput();
try try
{ {
Process(command); Process(input, output, command);
} }
catch (ArgumentException ae) catch (ArgumentException ae)
{ {
ConsoleUtilities.WriteWrappedLine("Error: " + ae.Message); output.WrappedOutput("Error: " + ae.Message);
} }
} }
} }
public void Process(string commandAndArguments) public void Process(IUserInput userInput, IUserOutput userOutput, string commandAndArguments)
{ {
string command = commandAndArguments; string command = commandAndArguments;
string[] arguments = null; string[] arguments = null;
@ -72,7 +72,7 @@ namespace RecrownedGTK.Tools.CommandProcessor
arguments = argumentsList.ToArray(); arguments = argumentsList.ToArray();
} }
if (!ContainsCommand(command)) throw new ArgumentException("Command not found. Type \"help\" for a list of commands."); if (!ContainsCommand(command)) throw new ArgumentException("Command not found. Type \"help\" for a list of commands.");
GetCommand(command).Run(arguments); GetCommand(command).Run(userInput, userOutput, arguments);
} }
public bool ContainsCommand(string command) public bool ContainsCommand(string command)

View File

@ -9,9 +9,9 @@ namespace RecrownedGTK.Tools.CommandProcessor.Commands
help = "Clears the console."; help = "Clears the console.";
} }
public override void Run(string[] arguments = null) public override void Run(IUserInput userInput, IUserOutput userOutput, string[] arguments = null)
{ {
Console.Clear(); userOutput.ClearOutput();
} }
} }
} }

View File

@ -13,16 +13,16 @@ namespace RecrownedGTK.Tools.CommandProcessor.Commands
} }
public override void Run(string[] arguments) public override void Run(IUserInput userInput, IUserOutput userOutput, string[] arguments)
{ {
if (arguments != null) if (arguments != null)
{ {
if (commandEngine.ContainsCommand(arguments[0])) if (commandEngine.ContainsCommand(arguments[0]))
{ {
if (arguments.Length < 2) ConsoleUtilities.WriteWrappedLine(commandEngine.GetCommand(arguments[0]).Help(null)); if (arguments.Length < 2) userOutput.WrappedOutput(commandEngine.GetCommand(arguments[0]).Help(null));
for (int i = 1; i < arguments.Length; i++) for (int i = 1; i < arguments.Length; i++)
{ {
ConsoleUtilities.WriteWrappedLine(commandEngine.GetCommand(arguments[0]).Help(arguments[i])); userOutput.WrappedOutput(commandEngine.GetCommand(arguments[0]).Help(arguments[i]));
} }
} }
else else
@ -32,20 +32,21 @@ namespace RecrownedGTK.Tools.CommandProcessor.Commands
} }
else else
{ {
ConsoleUtilities.WriteWrappedLine("Tools for RecrownedGTK library. Possible commands are as follows:\n"); userOutput.WrappedOutput("Tools for RecrownedGTK library. Possible commands are as follows:\n");
foreach (EngineCommand engineCommand in commandEngine.commands) foreach (EngineCommand engineCommand in commandEngine.commands)
{ {
for (int i = 0; i < engineCommand.InvokeStrings.Length; i++) for (int i = 0; i < engineCommand.InvokeStrings.Length; i++)
{ {
ConsoleUtilities.WriteWrapped(engineCommand.InvokeStrings[i]); userOutput.WrappedOutput(engineCommand.InvokeStrings[i]);
if (i + 1 < engineCommand.InvokeStrings.Length) if (i + 1 < engineCommand.InvokeStrings.Length)
{ {
ConsoleUtilities.WriteWrapped(", "); userOutput.WrappedOutput(", ");
} }
} }
ConsoleUtilities.WriteWrapped(" : "); userOutput.WrappedOutput(" : ");
ConsoleUtilities.WriteWrapped(engineCommand.Help().Replace("\n", "\n\t"), true); userOutput.WrappedOutput(engineCommand.Help().Replace("\n", "\n\t"));
Console.WriteLine("--------"); userOutput.WrappedOutput("\n");
userOutput.Output("--------");
} }
} }
} }

View File

@ -10,7 +10,7 @@
help = "Exits the tool."; help = "Exits the tool.";
} }
public override void Run(string[] arguments = null) public override void Run(IUserInput userInput, IUserOutput userOutput, string[] arguments = null)
{ {
commandEngine.running = false; commandEngine.running = false;
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Text; using System.Text;
using RecrownedGTK.Tools.CommandProcessor;
namespace RecrownedGTK.Tools.CommandProcessor namespace RecrownedGTK.Tools.CommandProcessor
{ {
@ -51,7 +52,7 @@ namespace RecrownedGTK.Tools.CommandProcessor
/// Runs the command. /// Runs the command.
/// </summary> /// </summary>
/// <param name="arguments">arguments to be used. May be null.</param> /// <param name="arguments">arguments to be used. May be null.</param>
public abstract void Run(string[] arguments = null); public abstract void Run(IUserInput userInput = null, IUserOutput userOutput = null, string[] arguments = null);
/// <summary> /// <summary>
/// Check if given argument is viable for command. /// Check if given argument is viable for command.

View File

@ -0,0 +1,8 @@
namespace RecrownedGTK.Tools.CommandProcessor {
public interface IUserOutput
{
void Output(string output);
void WrappedOutput(string output);
void ClearOutput();
}
}

View File

@ -0,0 +1,68 @@
using RecrownedGTK.Tools.CommandProcessor;
using RecrownedGTK.Tools.CommandProcessor.Commands;
using RecrownedGTK.Tools.NinePatchTools;
using RecrownedGTK.Tools.TextureAtlasTools;
using System;
using System.Reflection;
using System.Text;
namespace RecrownedGTK.Tools.ConsoleInterface
{
internal class ConsoleProgram
{
private class ConsoleInput : IUserInput {
public string GetInput() {
return Console.ReadLine();
}
}
private class ConsoleOutput : IUserOutput {
public void Output(string output) {
Console.WriteLine(output);
}
public void WrappedOutput(string output) {
ConsoleUtilities.WrapMessageToConsoleWidth(output);
}
public void ClearOutput() {
Console.Clear();
}
}
static void Main(string[] args)
{
ConsoleInput consoleInput = new ConsoleInput();
ConsoleOutput consoleOutput = new ConsoleOutput();
CommandEngine ce = new CommandEngine();
ConsoleUtilities.WrapMessageToConsoleWidth("Recrowned Athenaeum Console Tools version " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
ConsoleUtilities.WrapMessageToConsoleWidth("Type \"help\" for help.");
ce.commands.Add(new HelpCommand(ce));
ce.commands.Add(new TexturePackerCommand());
ce.commands.Add(new StopCommand(ce));
ce.commands.Add(new ClearConsoleCommand());
ce.commands.Add(new NinePatchCommand());
if (args.Length > 0)
{
ConsoleUtilities.WrapMessageToConsoleWidth("Executing as one time use.");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < args.Length; i++) sb.Append(args[i] + ' ');
string commandAndArgs = sb.ToString().TrimEnd();
try
{
ConsoleUtilities.WrapMessageToConsoleWidth("Command and argument received: " + commandAndArgs);
ce.Process(consoleInput, consoleOutput, commandAndArgs);
}
catch (ArgumentException e)
{
ConsoleUtilities.WrapMessageToConsoleWidth("An error has occurred: " + e.Message);
}
}
else
{
ce.Run(consoleInput, consoleOutput);
}
}
}
}

View File

@ -1,17 +1,10 @@
using System; using System;
using System.Text; using System.Text;
namespace RecrownedGTK.Tools namespace RecrownedGTK.Tools.ConsoleInterface
{ {
internal class ConsoleUtilities internal class ConsoleUtilities
{ {
public static void WriteWrapped(string message, bool line = false)
{
message = WrapMessageToConsoleWidth(message);
if (line) message = message + "\n";
Console.Write(message);
}
public static string WrapMessageToConsoleWidth(string message) public static string WrapMessageToConsoleWidth(string message)
{ {
string[] words = message.Split(' '); string[] words = message.Split(' ');
@ -39,12 +32,8 @@ namespace RecrownedGTK.Tools
stringBuilder.Append(' '); stringBuilder.Append(' ');
} }
} }
stringBuilder.AppendLine();
return stringBuilder.ToString(); return stringBuilder.ToString();
} }
public static void WriteWrappedLine(string message)
{
WriteWrapped(message, true);
}
} }
} }

View File

@ -23,7 +23,7 @@ namespace RecrownedGTK.Tools.NinePatchTools
commandArguments[5] = new EngineCommandArgument("-b", "bottom patch.", true); commandArguments[5] = new EngineCommandArgument("-b", "bottom patch.", true);
} }
public override void Run(string[] arguments = null) public override void Run(IUserInput userInput = null, IUserOutput userOutput = null, string[] arguments = null)
{ {
if (arguments == null) throw new ArgumentException("Missing arguments. Type \"help 9p\" for more information."); if (arguments == null) throw new ArgumentException("Missing arguments. Type \"help 9p\" for more information.");
int leftBound = 0, rightBound = 0, topBound = 0, bottomBound = 0; int leftBound = 0, rightBound = 0, topBound = 0, bottomBound = 0;
@ -51,8 +51,8 @@ namespace RecrownedGTK.Tools.NinePatchTools
File.Move(imagePath, modifiedPath); File.Move(imagePath, modifiedPath);
File.WriteAllText(outPath + ".9p", serialized); File.WriteAllText(outPath + ".9p", serialized);
ConsoleUtilities.WriteWrappedLine("Done. Written to \"" + outPath + "\" with values: left = " + leftBound + " right = " + rightBound + " top = " + topBound + " bottom = " + bottomBound); userOutput.WrappedOutput("Done. Written to \"" + outPath + "\" with values: left = " + leftBound + " right = " + rightBound + " top = " + topBound + " bottom = " + bottomBound);
ConsoleUtilities.WriteWrappedLine("Image renamed to: " + Path.GetFileName(modifiedPath)); userOutput.WrappedOutput("Image renamed to: " + Path.GetFileName(modifiedPath));
} }
} }
} }

View File

@ -1,52 +0,0 @@
using RecrownedGTK.Tools.CommandProcessor;
using RecrownedGTK.Tools.CommandProcessor.Commands;
using RecrownedGTK.Tools.NinePatchTools;
using RecrownedGTK.Tools.TextureAtlasTools;
using System;
using System.Reflection;
using System.Text;
namespace RecrownedGTK.Tools
{
internal class Program
{
private class ConsoleInput : IUserInput {
public string GetInput() {
return Console.ReadLine();
}
}
static void Main(string[] args)
{
CommandEngine ce = new CommandEngine();
ConsoleUtilities.WriteWrappedLine("Recrowned Athenaeum Console Tools version " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
ConsoleUtilities.WriteWrappedLine("Type \"help\" for help.");
ce.commands.Add(new HelpCommand(ce));
ce.commands.Add(new TexturePackerCommand());
ce.commands.Add(new StopCommand(ce));
ce.commands.Add(new ClearConsoleCommand());
ce.commands.Add(new NinePatchCommand());
if (args.Length > 0)
{
ConsoleUtilities.WriteWrappedLine("Executing as one time use.");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < args.Length; i++) sb.Append(args[i] + ' ');
string commandAndArgs = sb.ToString().TrimEnd();
try
{
ConsoleUtilities.WriteWrappedLine("Command and argument received: " + commandAndArgs);
ce.Process(commandAndArgs);
}
catch (ArgumentException e)
{
ConsoleUtilities.WriteWrappedLine("An error has occurred: " + e.Message);
}
}
else
{
ce.Run(new ConsoleInput());
}
}
}
}

View File

@ -7,9 +7,8 @@ using SixLabors.Primitives;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Security; using System.Security;
using RecrownedGTK.Tools.CommandProcessor;
namespace RecrownedGTK.Tools.TextureAtlas namespace RecrownedGTK.Tools.TextureAtlas
{ {
@ -34,7 +33,7 @@ namespace RecrownedGTK.Tools.TextureAtlas
/// <param name="rootDirectoryPath">Path to textures.</param> /// <param name="rootDirectoryPath">Path to textures.</param>
/// <param name="powLimit">Power of two limit for auto expanding texture. Default is 12 which is a 4096x4096 texture.</param> /// <param name="powLimit">Power of two limit for auto expanding texture. Default is 12 which is a 4096x4096 texture.</param>
/// <param name="startingPower">What power to start at and build up from. Default is 8 which is a 256x256 texture.</param> /// <param name="startingPower">What power to start at and build up from. Default is 8 which is a 256x256 texture.</param>
internal TexturePacker(string rootDirectoryPath, int powLimit = 12, int startingPower = 8) internal TexturePacker(IUserOutput userOutput, string rootDirectoryPath, int powLimit = 12, int startingPower = 8)
{ {
this.powLimit = powLimit; this.powLimit = powLimit;
string[] paths; string[] paths;
@ -54,7 +53,7 @@ namespace RecrownedGTK.Tools.TextureAtlas
SupportedExtensions extension; SupportedExtensions extension;
if (Enum.TryParse(Path.GetExtension(paths[pathID]).ToLower().Substring(1), out extension)) if (Enum.TryParse(Path.GetExtension(paths[pathID]).ToLower().Substring(1), out extension))
{ {
ConsoleUtilities.WriteWrappedLine("Reading texture data for: " + paths[pathID]); userOutput.WrappedOutput("Reading texture data for: " + paths[pathID]);
ImageHandler image = new ImageHandler(paths[pathID]); ImageHandler image = new ImageHandler(paths[pathID]);
imageHandlers.Add(image); imageHandlers.Add(image);
minAreaRequired += image.Area; minAreaRequired += image.Area;
@ -66,7 +65,7 @@ namespace RecrownedGTK.Tools.TextureAtlas
else if (Path.GetExtension(paths[pathID]).ToLower() == ".9p") else if (Path.GetExtension(paths[pathID]).ToLower() == ".9p")
{ {
if (ninePatchDictionary == null) ninePatchDictionary = new Dictionary<string, NinePatchInfo>(); if (ninePatchDictionary == null) ninePatchDictionary = new Dictionary<string, NinePatchInfo>();
ConsoleUtilities.WriteWrappedLine("Reading ninepatch data for: " + paths[pathID]); userOutput.WrappedOutput("Reading ninepatch data for: " + paths[pathID]);
string serialized = File.ReadAllText(paths[pathID]); string serialized = File.ReadAllText(paths[pathID]);
NinePatchInfo npData = JsonConvert.DeserializeObject<NinePatchInfo>(serialized); NinePatchInfo npData = JsonConvert.DeserializeObject<NinePatchInfo>(serialized);
ninePatchDictionary.Add(npData.name, npData); ninePatchDictionary.Add(npData.name, npData);

View File

@ -23,7 +23,7 @@ namespace RecrownedGTK.Tools.TextureAtlasTools
}; };
} }
public override void Run(string[] arguments) public override void Run(IUserInput userInput, IUserOutput userOutput, string[] arguments)
{ {
TexturePacker texturePacker = null; TexturePacker texturePacker = null;
@ -36,29 +36,29 @@ namespace RecrownedGTK.Tools.TextureAtlasTools
if (HasArgument("-interactive", arguments)) if (HasArgument("-interactive", arguments))
{ {
string input; string input;
ConsoleUtilities.WriteWrappedLine("Texture packer interactive mode triggered. Type \"q\" at any time to exit."); userOutput.WrappedOutput("Texture packer interactive mode triggered. Type \"q\" at any time to exit.");
ConsoleUtilities.WriteWrappedLine("Please enter path of folder containing the textures to be packed."); userOutput.WrappedOutput("Please enter path of folder containing the textures to be packed.");
input = Console.ReadLine(); input = userInput.GetInput();
if (input == "q") return; if (input == "q") return;
path = input.Replace("\"", ""); path = input.Replace("\"", "");
ConsoleUtilities.WriteWrappedLine("Please enter output path of file name."); userOutput.WrappedOutput("Please enter output path of file name.");
input = Console.ReadLine(); input = userInput.GetInput();
if (input == "q") return; if (input == "q") return;
output = input.Replace("\"", ""); output = input.Replace("\"", "");
do do
{ {
ConsoleUtilities.WriteWrappedLine("Please enter a valid starting power of two for the lengths of the resulting texture atlas. Leave blank for default of " + sp + "."); userOutput.WrappedOutput("Please enter a valid starting power of two for the lengths of the resulting texture atlas. Leave blank for default of " + sp + ".");
input = Console.ReadLine(); input = userInput.GetInput();
if (input == "q") return; if (input == "q") return;
if (input.Length == 0) break; if (input.Length == 0) break;
} while (!int.TryParse(input, out sp)); } while (!int.TryParse(input, out sp));
do do
{ {
ConsoleUtilities.WriteWrappedLine("Please enter a valid maximum power by two of the lengths of the resulting texture atlas. Leave blank for default of " + mp + "."); userOutput.WrappedOutput("Please enter a valid maximum power by two of the lengths of the resulting texture atlas. Leave blank for default of " + mp + ".");
input = Console.ReadLine(); input = userInput.GetInput();
if (input == "q") return; if (input == "q") return;
if (input.Length == 0) break; if (input.Length == 0) break;
} while (!int.TryParse(input, out mp)); } while (!int.TryParse(input, out mp));
@ -83,8 +83,8 @@ namespace RecrownedGTK.Tools.TextureAtlasTools
if (HasArgument("-dau", arguments)) dau = true; if (HasArgument("-dau", arguments)) dau = true;
} }
texturePacker = new TexturePacker(path, mp, sp); texturePacker = new TexturePacker(userOutput, path, mp, sp);
ConsoleUtilities.WriteWrappedLine("Calculated minimum texture size: " + texturePacker.TextureLength + "x" + texturePacker.TextureLength + " with a total of " + texturePacker.TexturesFound + " textures."); userOutput.WrappedOutput("Calculated minimum texture size: " + texturePacker.TextureLength + "x" + texturePacker.TextureLength + " with a total of " + texturePacker.TexturesFound + " textures.");
try try
{ {
@ -112,7 +112,7 @@ namespace RecrownedGTK.Tools.TextureAtlasTools
} }
} }
texturePacker.Save(Path.GetDirectoryName(output), Path.GetFileName(output)); texturePacker.Save(Path.GetDirectoryName(output), Path.GetFileName(output));
Console.WriteLine("Complete. Final texture size: " + texturePacker.TextureLength + "x" + texturePacker.TextureLength + "."); userOutput.Output("Complete. Final texture size: " + texturePacker.TextureLength + "x" + texturePacker.TextureLength + ".");
} }
} }
} }