From 796cb7ebc3d1dea3332d42f55998f6a7ef5e26a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Aagaard=20S=C3=B8rensen?= Date: Sun, 28 Dec 2014 12:06:23 +0100 Subject: [PATCH 1/3] Implemented selection dialog for multiple selection possibilities. --- Action/KSP.cs | 43 ++++++++++++++++++++++++++++++++++++------- Main.cs | 34 +++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/Action/KSP.cs b/Action/KSP.cs index 6e01658dd1..dde6960cb4 100644 --- a/Action/KSP.cs +++ b/Action/KSP.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using CommandLine; namespace CKAN.CmdLine @@ -212,21 +213,49 @@ private int ForgetInstall(ForgetOptions options) private int SetDefaultInstall(DefaultOptions options) { - if (options.name == null) + string name = options.name; + + if (name == null) { - User.RaiseMessage("default - argument missing, perhaps you forgot it?"); - return Exit.BADOPT; + // No input argument from the user. Present a list of the possible instances. + string message = "default - argument missing, please select from the list below."; + string[] keys = new string[Manager.Instances.Count]; + + for (int i = 0; i < Manager.Instances.Count; i++) + { + var instance = Manager.Instances.ElementAt(i); + + keys[i] = String.Format("\"{0}\" - {1}", instance.Key, instance.Value.GameDir()); + } + + int result = -1; + + try + { + result = User.RaiseSelectionDialog(message, keys); + } + catch (Kraken) + { + return Exit.BADOPT; + } + + if (result < 0) + { + return Exit.BADOPT; + } + + name = Manager.Instances.ElementAt(result).Key; } - if (!Manager.HasInstance(options.name)) + if (!Manager.Instances.ContainsKey(name)) { - User.RaiseMessage("Couldn't find install with name \"{0}\", aborting..", options.name); + User.RaiseMessage("Couldn't find install with name \"{0}\", aborting..", name); return Exit.BADOPT; } - Manager.SetAutoStart(options.name); + Manager.SetAutoStart(name); - User.RaiseMessage("Successfully set \"{0}\" as the default KSP installation", options.name); + User.RaiseMessage("Successfully set \"{0}\" as the default KSP installation", name); return Exit.OK; } } diff --git a/Main.cs b/Main.cs index 3df7eb2076..c5c9954b8c 100644 --- a/Main.cs +++ b/Main.cs @@ -460,16 +460,40 @@ private static int Install(InstallOptions options, CKAN.KSP current_instance, IU } catch (TooManyModsProvideKraken ex) { - user.RaiseMessage("Too many mods provide {0}. Please pick from the following:\n", ex.requested); + // Request the user selects one of the mods. + string[] mods = new string[ex.modules.Count]; - foreach (CkanModule mod in ex.modules) + for (int i = 0; i < ex.modules.Count; i++) { - user.RaiseMessage("* {0} ({1})", mod.identifier, mod.name); + mods[i] = String.Format("{0} ({1})", ex.modules[i].identifier, ex.modules[i].name); } - user.RaiseMessage(String.Empty); // Looks tidier. + string message = String.Format("Too many mods provide {0}. Please pick from the following:\n", ex.requested); - return Exit.ERROR; + int result = -1; + + try + { + result = user.RaiseSelectionDialog(message, mods); + } + catch (Kraken e) + { + user.RaiseMessage(e.Message); + + return Exit.ERROR; + } + + if (result < 0) + { + user.RaiseMessage(String.Empty); // Looks tidier. + + return Exit.ERROR; + } + + // Add the module to the list. + options.modules.Add(ex.modules[result].identifier); + + return Install(options, current_instance, user); } catch (FileExistsKraken ex) { From c5a0c3a76d5e04bfc18e33147c817d820f56ecbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Aagaard=20S=C3=B8rensen?= Date: Sun, 28 Dec 2014 12:31:22 +0100 Subject: [PATCH 2/3] Added preselected default. --- Action/KSP.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Action/KSP.cs b/Action/KSP.cs index dde6960cb4..f960148600 100644 --- a/Action/KSP.cs +++ b/Action/KSP.cs @@ -219,13 +219,30 @@ private int SetDefaultInstall(DefaultOptions options) { // No input argument from the user. Present a list of the possible instances. string message = "default - argument missing, please select from the list below."; - string[] keys = new string[Manager.Instances.Count]; + // Check if there is a default instance. + string defaultInstance = Manager.Win32Registry.AutoStartInstance; + int defaultInstancePresent = 0; + + if (!String.IsNullOrWhiteSpace(defaultInstance)) + { + defaultInstancePresent = 1; + } + + object[] keys = new object[Manager.Instances.Count + defaultInstancePresent]; + + // Populate the list of instances. for (int i = 0; i < Manager.Instances.Count; i++) { var instance = Manager.Instances.ElementAt(i); - keys[i] = String.Format("\"{0}\" - {1}", instance.Key, instance.Value.GameDir()); + keys[i + defaultInstancePresent] = String.Format("\"{0}\" - {1}", instance.Key, instance.Value.GameDir()); + } + + // Mark the default intance for the user. + if (!String.IsNullOrWhiteSpace(defaultInstance)) + { + keys[0] = Manager.Instances.IndexOfKey(defaultInstance); } int result = -1; From f38245547ee86a2b9cac72d746449fe65d3235b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Aagaard=20S=C3=B8rensen?= Date: Mon, 5 Jan 2015 15:01:31 +0100 Subject: [PATCH 3/3] Added selection dialog to ConsoleUser. --- ConsoleUser.cs | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/ConsoleUser.cs b/ConsoleUser.cs index e8bdd54dcf..40b676db34 100644 --- a/ConsoleUser.cs +++ b/ConsoleUser.cs @@ -64,6 +64,146 @@ protected override void DisplayError(string message, params object[] args) Console.Error.WriteLine(message, args); } + protected override int DisplaySelectionDialog(string message, params object[] args) + { + // Validate input. + if (String.IsNullOrWhiteSpace(message)) + { + throw new Kraken("Passed message string must be non-empty."); + } + + if (args.Length == 0) + { + throw new Kraken("Passed list of selection candidates must be non-empty."); + } + + // Check if we have a default selection. + int defaultSelection = -1; + + if (args[0] is int) + { + // Check that the default selection makes sense. + defaultSelection = (int)args[0]; + + if (defaultSelection < 0 || defaultSelection > args.Length - 1) + { + throw new Kraken("Passed default arguments is out of range of the selection candidates."); + } + + // Extract the relevant arguments. + object[] newArgs = new object[args.Length - 1]; + + for (int i = 1; i < args.Length; i++) + { + newArgs[i - 1] = args[i]; + } + + args = newArgs; + } + + // Further data validation. + foreach (object argument in args) + { + if (String.IsNullOrWhiteSpace(argument.ToString())) + { + throw new Kraken("Candidate may not be empty."); + } + } + + // List options. + for (int i = 0; i < args.Length; i++) + { + string CurrentRow = String.Format("{0}", i + 1); + + if (i == defaultSelection) + { + CurrentRow += "*"; + } + + CurrentRow += String.Format(") {0}", args[i]); + + RaiseMessage(CurrentRow); + } + + // Create message string. + string output = String.Format("Enter a number between {0} and {1} (To cancel press \"c\" or \"n\".", 1, args.Length); + + if (defaultSelection >= 0) + { + output += String.Format(" \"Enter\" will select {0}.", defaultSelection + 1); + } + + output += "): "; + + RaiseMessage(output); + + bool valid = false; + int result = 0; + + while (!valid) + { + // Wait for input from the command line. + string input = Console.ReadLine().Trim().ToLower(); + + // Check for default selection. + if (String.IsNullOrEmpty(input)) + { + if (defaultSelection >= 0) + { + return defaultSelection; + } + } + + // Check for cancellation characters. + if (input == "c" || input == "n") + { + RaiseMessage("Selection cancelled."); + + return -1; + } + + // Attempt to parse the input. + try + { + result = Convert.ToInt32(input); + } + catch (FormatException) + { + RaiseMessage("The input is not a number."); + continue; + } + catch (OverflowException) + { + RaiseMessage("The number in the input is too large."); + continue; + } + + // Check the input against the boundaries. + if (result > args.Length) + { + RaiseMessage("The number in the input is too large."); + RaiseMessage(output); + + continue; + } + else if (result < 1) + { + RaiseMessage("The number in the input is too small."); + RaiseMessage(output); + + continue; + } + + // The list we provide is index 1 based, but the array is index 0 based. + result--; + + // We have checked for all errors and have gotten a valid result. Stop the input loop. + valid = true; + } + + return result; + } + protected override void ReportProgress(string format, int percent) { if (Regex.IsMatch(format, "download", RegexOptions.IgnoreCase))