/// <summary> /// Try to load the registry of an instance /// </summary> /// <param name="ksp">Game instance</param> /// <param name="render">Function that shows a loading message</param> /// <returns> /// True if successfully loaded, false if it's locked or the registry was corrupted, etc. /// </returns> public static bool TryGetInstance(KSP ksp, Action render) { bool retry; do { try { retry = false; // Show loading message render(); // Try to get the lock; this will throw if another instance is in there RegistryManager.Instance(ksp); } catch (RegistryInUseKraken k) { ConsoleMessageDialog md = new ConsoleMessageDialog( $"Lock file with live process ID found at {k.lockfilePath}\n\n" + "This means that another instance of CKAN probably is accessing this instance." + " You can delete the file to continue, but data corruption is very likely.\n\n" + "Do you want to delete this lock file to force access?", new List <string>() { "Cancel", "Force" } ); if (md.Run() == 1) { // Delete it File.Delete(k.lockfilePath); retry = true; } else { // User cancelled, return failure return(false); } } catch (NotKSPDirKraken k) { ConsoleMessageDialog errd = new ConsoleMessageDialog( $"Error loading {ksp.GameDir()}:\n{k.Message}", new List <string>() { "OK" } ); errd.Run(); return(false); } catch (Exception e) { ConsoleMessageDialog errd = new ConsoleMessageDialog( $"Error loading {Path.Combine(ksp.CkanDir(), "registry.json")}:\n{e.Message}", new List <string>() { "OK" } ); errd.Run(); return(false); } } while (retry); // If we got the lock, then return success return(true); }
// IUser stuff for managing the progress bar and message box /// <summary> /// Ask the user a yes/no question and capture the answer. /// </summary> /// <param name="question">Message to display to the user</param> /// <returns> /// True if the user selected Yes, and false if the user selected No. /// </returns> public override bool RaiseYesNoDialog(string question) { // Show the popup at the top of the screen // to overwrite the progress bar instead of the messages ConsoleMessageDialog d = new ConsoleMessageDialog( // The installer's questions include embedded newlines for spacing in CmdLine question.Trim(), new List <string>() { "Yes", "No" }, null, TextAlign.Center, -Console.WindowHeight / 2 ); d.AddBinding(Keys.Y, (object sender, ConsoleTheme theme) => { d.PressButton(0); return(false); }); d.AddBinding(Keys.N, (object sender, ConsoleTheme theme) => { d.PressButton(1); return(false); }); // Scroll messages d.AddTip("Cursor keys", "Scroll messages"); messages.AddScrollBindings(d, true); bool val = d.Run(yesNoTheme) == 0; DrawBackground(yesNoTheme); Draw(yesNoTheme); return(val); }
private bool ViewMetadata() { ConsoleMessageDialog md = new ConsoleMessageDialog( $"\"{mod.identifier}\": {registry.GetAvailableMetadata(mod.identifier)}", new List<string> {"OK"}, () => $"{mod.name} Metadata", TextAlign.Left ); md.Run(); DrawBackground(); return true; }
private bool UpdateRegistry() { ConsoleMessageDialog d = new ConsoleMessageDialog( "Updating registry...", new List <string>() ); d.Run(() => { HashSet <string> availBefore = new HashSet <string>( Array.ConvertAll <CkanModule, string>( registry.Available( manager.CurrentInstance.VersionCriteria() ).ToArray(), (l => l.identifier) ) ); recent.Clear(); try { Repo.UpdateAllRepositories( RegistryManager.Instance(manager.CurrentInstance), manager.CurrentInstance, manager.Cache, this ); } catch (Exception ex) { // There can be errors while you re-install mods with changed metadata RaiseError(ex.Message + ex.StackTrace); } // Update recent with mods that were updated in this pass foreach (CkanModule mod in registry.Available( manager.CurrentInstance.VersionCriteria() )) { if (!availBefore.Contains(mod.identifier)) { recent.Add(mod.identifier); } } }); if (recent.Count > 0 && RaiseYesNoDialog(newModPrompt(recent.Count))) { searchBox.Clear(); moduleList.FilterString = searchBox.Value = "~n"; } RefreshList(); return(true); }
/// <summary> /// Launch a URL in the system browser. /// </summary> /// <param name="theme">The visual theme to use to draw the dialog</param> /// <param name="u">URL to launch</param> /// <returns> /// True. /// </returns> public static bool LaunchURL(ConsoleTheme theme, Uri u) { // I'm getting error output on Linux, because this runs xdg-open which // calls chromium-browser which prints a bunch of stuff about plugins that // no one cares about. Which corrupts the screen. // But redirecting stdout requires UseShellExecute=false, which doesn't // support launching URLs! .NET's API design has painted us into a corner. // So instead we display a popup dialog for the garbage to print all over, // then wait 1.5 seconds and refresh the screen when it closes. ConsoleMessageDialog d = new ConsoleMessageDialog("Launching...", new List <string>()); d.Run(theme, (ConsoleTheme th) => { Utilities.ProcessStartURL(u.ToString()); System.Threading.Thread.Sleep(1500); }); return(true); }
private bool CaptureKey(ConsoleTheme theme) { ConsoleKeyInfo k = default(ConsoleKeyInfo); ConsoleMessageDialog keyprompt = new ConsoleMessageDialog("Press a key", new List <string>()); keyprompt.Run(theme, (ConsoleTheme th) => { k = Console.ReadKey(true); }); ConsoleMessageDialog output = new ConsoleMessageDialog( $"Key: {k.Key,18}\nKeyChar: 0x{(int)k.KeyChar:x2}\nModifiers: {k.Modifiers,12}", new List <string> { "OK" } ); output.Run(theme); return(true); }
/// <summary> /// Initialize the screen. /// </summary> /// <param name="mgr">KSP manager object for getting hte Instances</param> /// <param name="first">If true, this is the first screen after the splash, so Ctrl+Q exits, else Esc exits</param> public KSPListScreen(KSPManager mgr, bool first = false) { manager = mgr; AddObject(new ConsoleLabel( 1, 2, -1, () => "Select a game instance:" )); kspList = new ConsoleListBox <KSP>( 1, 4, -1, -2, manager.Instances.Values, new List <ConsoleListBoxColumn <KSP> >() { new ConsoleListBoxColumn <KSP>() { Header = "Default", Width = 7, Renderer = StatusSymbol }, new ConsoleListBoxColumn <KSP>() { Header = "Name", Width = 20, Renderer = k => k.Name }, new ConsoleListBoxColumn <KSP>() { Header = "Version", Width = 12, Renderer = k => k.Version()?.ToString() ?? noVersion, Comparer = (a, b) => a.Version()?.CompareTo(b.Version() ?? KspVersion.Any) ?? 1 }, new ConsoleListBoxColumn <KSP>() { Header = "Path", Width = 70, Renderer = k => k.GameDir() } }, 1, 0, ListSortDirection.Descending ); if (first) { AddTip("Ctrl+Q", "Quit"); AddBinding(Keys.AltX, (object sender) => false); AddBinding(Keys.CtrlQ, (object sender) => false); } else { AddTip("Esc", "Quit"); AddBinding(Keys.Escape, (object sender) => false); } AddTip("Enter", "Select"); AddBinding(Keys.Enter, (object sender) => { ConsoleMessageDialog d = new ConsoleMessageDialog( $"Loading instance {kspList.Selection.Name}...", new List <string>() ); if (TryGetInstance(kspList.Selection, () => { d.Run(() => {}); })) { try { manager.SetCurrentInstance(kspList.Selection.Name); } catch (Exception ex) { // This can throw if the previous current instance had an error, // since it gets destructed when it's replaced. RaiseError(ex.Message); } return(false); } else { return(true); } }); kspList.AddTip("A", "Add"); kspList.AddBinding(Keys.A, (object sender) => { LaunchSubScreen(new KSPAddScreen(manager)); kspList.SetData(manager.Instances.Values); return(true); }); kspList.AddTip("R", "Remove"); kspList.AddBinding(Keys.R, (object sender) => { manager.RemoveInstance(kspList.Selection.Name); kspList.SetData(manager.Instances.Values); return(true); }); kspList.AddTip("E", "Edit"); kspList.AddBinding(Keys.E, (object sender) => { ConsoleMessageDialog d = new ConsoleMessageDialog( $"Loading instance {kspList.Selection.Name}...", new List <string>() ); TryGetInstance(kspList.Selection, () => { d.Run(() => {}); }); // Still launch the screen even if the load fails, // because you need to be able to fix the name/path. LaunchSubScreen(new KSPEditScreen(manager, kspList.Selection)); return(true); }); kspList.AddTip("D", "Default"); kspList.AddBinding(Keys.D, (object sender) => { string name = kspList.Selection.Name; if (name == manager.AutoStartInstance) { manager.ClearAutoStart(); } else { try { manager.SetAutoStart(name); } catch (NotKSPDirKraken k) { ConsoleMessageDialog errd = new ConsoleMessageDialog( $"Error loading {k.path}:\n{k.Message}", new List <string>() { "OK" } ); errd.Run(); } } return(true); }); AddObject(kspList); mainMenu = kspList.SortMenu(); }