private void BtnShowDesigner_Click(object S, EventArgs E) { var Designer = new FrmDesigner(this); // Set up a new FrmDesigner with a reference to this Designer.VisibleChanged += (S2, E2) => { if (S2 is FrmDesigner D && D.Visible) { return; } Show(); }; // Add event handlers Designer.Closed += (S2, E2) => { Show(); }; Designer.Show(); // Show designer Hide(); }
/// <summary> /// Load a FrmDesigner with blocks stored in the .bs file /// </summary> /// <param name="Path">The path to the .bs file</param> /// <returns>A reconstructed FrmDesigner</returns> public static FrmDesigner LoadFromFile(string Path) { if (!File.Exists(Path) || !Path.EndsWith(".bs")) { MessageBox.Show("An invalid path was provided.", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } var Contents = File.ReadAllLines(Path); var BlockSet = Contents.Select(JsonConvert.DeserializeObject <DeserializedProps>) .Select(RebuildBlock) .Where(Rebuilt => !(Rebuilt is null)) .ToList(); var Designer = new FrmDesigner(); Designer.SContainer_Workspace.Panel2.Controls.RemoveByKey("StartBlock1"); Designer.SContainer_Workspace.Panel2.Controls.RemoveByKey("VarDeclareBlock0"); foreach (var Block in BlockSet) { if (Block is VarCreateBlock VCB) { VCB.OnVarNameChanged += Designer.UpdateVarNameList; } Block.MouseDown += Designer.Block_OnMouseDown; Block.MouseUp += Designer.Block_OnMouseUp; Designer.SContainer_Workspace.Panel2.SuspendLayout(); Designer.SContainer_Workspace.Panel2.Controls.Add(Block); Designer.SContainer_Workspace.Panel2.ResumeLayout(); } Designer.FileInfo = $"{DateTime.Now:g}|{Path}"; Designer.UpdateVarNameList(null, null); return(Designer); }
/// <inheritdoc /> /// <summary> /// Initialization with parameters. Allows debugging to begin /// </summary> /// <param name="FileToDebug">The path of the "*.exe" file to be debugged</param> /// <param name="MyParent">The FrmWelcome that instantiated the FrmDebugger</param> public FrmDebugger(string FileToDebug, FrmDesigner MyParent) { InitializeComponent(); // Reqd. for forms BtnStartExecution.Enabled = true; // Text colour changes do not occur on disabled controls BtnStartExecution.EnabledChanged += Buttons_EnabledChanged; // Handle the events BtnExitDebugging.EnabledChanged += Buttons_EnabledChanged; // By using the same handler, code can be BtnPauseExecution.EnabledChanged += Buttons_EnabledChanged; // reduced to prevent unnecessary BtnSubmitInput.EnabledChanged += Buttons_EnabledChanged; // methods BtnStopExecution.EnabledChanged += Buttons_EnabledChanged; StopDebuggingInterfaceChanges(); // Not sure if we're ready yet, so disable everything Just In Case (JIC) // Bind the enter key to sending an input TxtInputToProgram.KeyUp += (Sender, Args) => { if (Args.KeyCode == Keys.Enter) { BtnSubmitInput_Click(null, null); // null parameters because the delegate requires them, but we don't use them } }; // If parameters are missing, don't function because otherwise things are going to break violently if (FileToDebug == null || MyParent == null) { TxtStandardOutput.Text = @"No program was loaded, debugging will not occur"; TxtVariableOutput.Text = @"No variables can be observed"; TxtErrorOutput.Text = @"No errors will be recorded"; return; } // If the App is closed, kill the process Application.ApplicationExit += (S, E) => { try { _DebugProcess?.Close(); _DebugProcess?.Kill(); // This is needed because otherwise the child process is not killed. It then keeps running, // causing RAM-leaking behaviours. We don't like those. They're bad for the RAM } catch (InvalidOperationException) {} // Don't break if the program has already been murdered }; // Instantiate the process _DebugProcess = new Process { StartInfo = new ProcessStartInfo { FileName = FileToDebug, CreateNoWindow = true, // No new window UseShellExecute = false, // Don't run it in the system shell Arguments = "DEBUG", // We are debugging after all, and it's crucial // to the behaviour of the programs RedirectStandardError = true, // Allows me to read the error output RedirectStandardOutput = true, // Allows me to read normal output RedirectStandardInput = true // Allows me to send my own inputs to the program }, EnableRaisingEvents = true // Allows me to hook on to the "Exited" event }; _ParentFrmDesigner = MyParent; // Set parent form _ParentFrmDesigner.Hide(); // Hide the parent form _ParentFrmDesigner._ParentFrmWelcome.Hide(); _IsDebugging = _DebugProcess.Start(); // Start the process if (!_IsDebugging) // Did something break? { MessageBox.Show(@"Something went wrong and the process couldn't start, sorry.", @"Unable to start process", MessageBoxButtons.OK); KillDebugProcess(); // Kill everything just in case _ParentFrmDesigner.Show(); // Show the main form _ParentFrmDesigner._ParentFrmWelcome.Hide(); // Prevent some quirky behaviour Hide(); // Disappear Dispose(); // Clean up } TxtStandardOutput.Text = $@": Process started at {_DebugProcess.StartTime:f} {Environment.NewLine}"; // Feedback to user //Console.WriteLine($@"Process is called: {_DebugProcess.ProcessName} {Environment.NewLine}" + // $@"Process was started at {_DebugProcess.StartTime:f} {Environment.NewLine}" + // $@"Process has {(_DebugProcess.HasExited ? "" : "not ")}exited"); // // Feedback to me (plus string interpolation, yay) // Add output listeners _DebugProcess.ErrorDataReceived += ReadError; // Bind the ASYNC code _DebugProcess.OutputDataReceived += ReadOutput; // MORE ASYNC CODE BINDING _DebugProcess.Exited += (Sender, E) => { WriteExitText(); StopDebuggingInterfaceChanges(); }; // Sleep if the program exits StartDebuggingInterfaceChanges(); // Enable buttons because nothing broke TxtInputToProgram.Text = ""; // Empty the input TxtInputToProgram_TextChanged(null, null); // Disable the SUBMIT button // START THE ASYNC OPERATIONS _DebugProcess.BeginOutputReadLine(); _DebugProcess.BeginErrorReadLine(); TxtInputToProgram.Focus(); // Give focus to TxtInputToProgram }
/// <summary> /// Saves the project at the file location specified by the user /// </summary> /// <param name="Designer">The FrmDesigner to save</param> /// <returns>true: Save was successful, False: Save went bad</returns> public static bool SaveProject(FrmDesigner Designer) { try { var Path = Designer.FileInfo.Split('|')[1]; if (File.Exists(Path)) { File.WriteAllText(Path, ""); } else { var F = File.Create(Path); F.Close(); } var DesignerAsJson = new StringBuilder(); foreach (var Control in Designer.SContainer_Workspace.Panel2.Controls) { if (!(Control is BaseBlock Block)) { continue; } var BlockAsJson = JsonConvert.SerializeObject(Block, new JsonSerializerSettings { ContractResolver = new BaseBlockContractResolver(), //ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); //MessageBox.Show($"Block: JSON Follows{Environment.NewLine}{BlockAsJson}"); DesignerAsJson.AppendLine(BlockAsJson); } using (var SW = new StreamWriter(Path)) { SW.Write(DesignerAsJson.ToString()); } } catch (UnauthorizedAccessException Ex) { // Error handling MessageBox.Show($"You did not have permission to access the file. Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (ArgumentException Ex) { // I probably did a bad thing MessageBox.Show($"Something broke but it wasn't your fault. Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (DirectoryNotFoundException Ex) { // FAKE MessageBox.Show($"We couldn't find that directory. Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (PathTooLongException Ex) { // File path too long MessageBox.Show($"The file path was too long. Windows is mad at you. Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (IOException Ex) { // IO Disagrees with my decisions MessageBox.Show($"Something broke but it wasn't your fault. Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (NotSupportedException Ex) { // Windows hates me MessageBox.Show($"Something broke but it wasn't your fault. Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (System.Security.SecurityException Ex) { // Get your permissions sorted MessageBox.Show($"Security settings stopped us from saving your work. Please contact your local sysadmin." + $"Details follow: {Environment.NewLine}{Ex.Message}", "B#", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } return(true); }