using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Drawing.Printing; using System.Reflection; using System.Threading; using NRefactory = ICSharpCode.NRefactory; using Dom = ICSharpCode.SharpDevelop.Dom; using CodeComplete; using System.Reflection; using System.CodeDom.Compiler; using System.CodeDom; using DarkWynter.Engine.Globals; using DarkWynter.App; namespace CSTextEditor { public partial class PrettyCompilerControl : Form { internal Dom.ProjectContentRegistry pcRegistry; internal Dom.DefaultProjectContent myProjectContent; internal Dom.ICompilationUnit lastCompilationUnit; CompilerResults compilerResults; // Handles Intellisense Thread parserThread; /// /// Many SharpDevelop.Dom methods take a file name, which is really just a unique identifier /// for a file - Dom methods don't try to access code files on disk, so the file does not have /// to exist. /// SharpDevelop itself uses internal names of the kind "[randomId]/Class1.cs" to support /// code-completion in unsaved files. /// public const string CompilableFileName = "edited.cs"; private PrintDocument printDoc = new PrintDocument(); bool changed = false; public delegate void TextChanged_EventHandler(string message); TextChanged_EventHandler textChanged_EventHandler; public delegate void Compile_EventHandler(ref TextBox output); public delegate void Run_EventHandler(ref TextBox output); public PrettyCompilerControl() { // Code Project myProjectContent = new Dom.DefaultProjectContent(); myProjectContent.Language = Dom.LanguageProperties.CSharp; // Default .NET 2.0 registry pcRegistry = new Dom.ProjectContentRegistry(); InitializeComponent(); textChanged_EventHandler += new TextChanged_EventHandler(CodeBaseChanged); printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage); textEditorControl1.SetHighlighting("C#"); textEditorControl1.Document.DocumentChanged += new ICSharpCode.TextEditor.Document.DocumentEventHandler(textChanged); textEditorControl1.Document.TextEditorProperties.Font = new Font("Courier New", 10); //fontDialog1.Font = textEditorControl1.Document.TextEditorProperties.Font; textEditorControl1.ShowEOLMarkers = false; textEditorControl1.Text = "using System; \n" + "using System.Collections.Generic; \n" + "class MainClass \n" + "{ \n" + " static void Main(string[] args) \n" + " { \n" + " \n" + " } \n" + "} \n"; CodeCompletionKeyHandler.Attach(this, textEditorControl1); HostCallbackImplementation.Register(this); // Persistence caches referenced project contents for faster loading. // It also activates loading XML documentation files and caching them // for faster loading and lower memory usage. string path = Path.Combine(Path.GetTempPath(), "CSharpCodeCompletion"); pcRegistry.ActivatePersistence(path); parserThread = new Thread(ParserThread); parserThread.IsBackground = true; parserThread.Start(); } #region Intellisense void ParserThread() { Thread.Sleep(2000); BeginInvoke(new MethodInvoker(delegate { parserThreadLabel.Text = "Loading mscorlib..."; })); myProjectContent.AddReferencedContent(pcRegistry.Mscorlib); // do one initial parser step to enable code-completion while other // references are loading ParseStep(); string[] referencedAssemblies = { "System", "System.Data", "System.Drawing", "System.Xml", "System.Windows.Forms" }; foreach (string assemblyName in referencedAssemblies) { { // block for anonymous method string assemblyNameCopy = assemblyName; BeginInvoke(new MethodInvoker(delegate { parserThreadLabel.Text = "Loading " + assemblyNameCopy + "..."; })); } myProjectContent.AddReferencedContent(pcRegistry.GetProjectContentForReference(assemblyName, assemblyName)); } BeginInvoke(new MethodInvoker(delegate { parserThreadLabel.Text = "Ready"; })); // Parse the current file every 2 seconds while (!IsDisposed) { ParseStep(); Thread.Sleep(2000); } } void ParseStep() { string code = ""; Invoke(new MethodInvoker(delegate { code = textEditorControl1.Text; })); TextReader textReader = new StringReader(code); Dom.ICompilationUnit newCompilationUnit; using (NRefactory.IParser p = NRefactory.ParserFactory.CreateParser(NRefactory.SupportedLanguage.CSharp, textReader)) { p.Parse(); newCompilationUnit = ConvertCompilationUnit(p.CompilationUnit); } // Remove information from lastCompilationUnit and add information from newCompilationUnit. myProjectContent.UpdateCompilationUnit(lastCompilationUnit, newCompilationUnit, PrettyCompilerControl.CompilableFileName); lastCompilationUnit = newCompilationUnit; } Dom.ICompilationUnit ConvertCompilationUnit(NRefactory.Ast.CompilationUnit cu) { Dom.NRefactoryResolver.NRefactoryASTConvertVisitor converter; converter = new Dom.NRefactoryResolver.NRefactoryASTConvertVisitor(myProjectContent); cu.AcceptVisitor(converter, null); return converter.Cu; } #endregion #region Handled Events private void textBox1_TextChanged(object sender, EventArgs e) { compilerOutput.Select(compilerOutput.Text.Length, 0); compilerOutput.ScrollToCaret(); } private void OutputBoxChanged(string message) { compilerOutput.Text = message; } void textChanged(object sender, EventArgs args) { CodeBaseChanged(textEditorControl1.Text); } private void CodeBaseChanged(string message) { //CompilerControl.richTextBox_CodeWindow.Text = message; SynchronizationContext synchContext = SynchronizationContext.Current; if (DarkWynter.App.CompilerControl.richTextBox_CodeWindow.InvokeRequired) { CompilerControl.richTextBox_CodeWindow.Invoke( textChanged_EventHandler, // the method to call back on new object[] { message }); // the list of arguments to pass } else { changed = true; CompilerControl.richTextBox_CodeWindow.Text = message; } } private void printDoc_PrintPage(Object sender, PrintPageEventArgs e) { String textToPrint = textEditorControl1.Document.TextContent; Font printFont = new Font("Courier New", 12); e.Graphics.DrawString(textToPrint, printFont, Brushes.Black, 0, 0); } #endregion #region Compile and Debug public virtual void compileToolStripMenuItem_Click(object sender, EventArgs e) { //try //{ // //CSCompiler temp = new CSCompiler(textEditorControl1.Document.TextContent, // // new string[] { "System.dll", "System.Windows.Forms.dll" }); // //temp.Compile(new CompilerOutputDelegate(this.HandleCompilerOutput)); //} //catch (Exception exp) //{ // MessageBox.Show(this, "An error occurred compiling this script:\n\n" + exp.Message, "Error compiling script", MessageBoxButtons.OK, MessageBoxIcon.Error); // System.Diagnostics.Debug.WriteLine(exp); //} Compile(ref compilerOutput); } private void Compile(ref TextBox output) { if (DarkWynter.App.CompilerControl.compilerControl.InvokeRequired) { Compile_EventHandler d = new Compile_EventHandler(Compile); DarkWynter.App.CompilerControl.compilerControl.Invoke(d, new object[] { output }); } else { output.Text = CompilerControl.compilerControl.CompileCodeWithOutput(); } } private delegate void AddCompilerOutputLineDelegate(string line); public void HandleCompilerOutput(string line) { compilerOutput.BeginInvoke(new AddCompilerOutputLineDelegate(this.AddCompilerOutputLine), line); } private void AddCompilerOutputLine(string line) { this.compilerOutput.Text += line + "\r\n"; } public virtual void runCodeStripMenuItem_Click(object sender, EventArgs e) { // try // { // string[] temp = new string[1]; // //Mike: This is where the program passes its self into the program. // //Here we pass the parameters into the game // //We can put Machina or normal code here. // //Real code // CSCompiler temp2 = new CSCompiler(textEditorControl1.Document.TextContent, // new string[] { "System.dll", "System.Windows.Forms.dll" }); // temp2.Run( // new CompilerOutputDelegate(this.HandleCompilerOutput), // null, new object[] { temp }, // CSTextEditor.CSCompiler.GetDefaultScriptPermissionSet()); // //Machina Script - Machina script may hide the class Script part (user can add 'using' statements. // //scriptEditorControl1.Script.Run(new CompilerOutputDelegate(this.HandleCompilerOutput), null, new object[] { new Machina() }, scriptPermissions); // } // catch (Exception exp) // { // MessageBox.Show(this, "An error occurred executing this script, please refer to the debug output for details.\n\n" + (exp.InnerException == null ? exp.Message : exp.InnerException.Message) + "", "Error running script", MessageBoxButtons.OK, MessageBoxIcon.Error); // System.Diagnostics.Debug.WriteLine(exp); // } } #endregion #region MenuStrip Buttons and Commands private void fontToolStripMenuItem_Click(object sender, EventArgs e) { if (fontDialog1.ShowDialog() != DialogResult.Cancel) { textEditorControl1.Document.TextEditorProperties.Font = fontDialog1.Font; textEditorControl1.Refresh(); } } private void newToolStripMenuItem_Click(object sender, EventArgs e) { newFile(); } public virtual void newFile() { if (!changed || MessageBox.Show(this, "The script source code has been changed. Are you sure you wish to continue?", "Source code changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { textEditorControl1.ResetText(); textEditorControl1.Refresh(); } saveFileDialog1.FileName = ""; textEditorControl1.FileName = "newFile"; } private void openToolStripMenuItem_Click(object sender, EventArgs e) { openFile(); } private void openFile() { openFileDialog1.Filter = "C# Files|*.cs"; if (openFileDialog1.ShowDialog() != DialogResult.Cancel) { textEditorControl1.LoadFile(openFileDialog1.FileName); textEditorControl1.FileName = openFileDialog1.FileName; } //So the new file will not save to the old location. saveFileDialog1.FileName = openFileDialog1.FileName; } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { saveFile(); } private void saveFile() { if (saveFileDialog1.FileName != "") { textEditorControl1.SaveFile(saveFileDialog1.FileName); textEditorControl1.FileName = saveFileDialog1.FileName; } else saveAs();; } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { saveAs(); } private void saveAs() { saveFileDialog1.Title = "Specify Destination Filename"; saveFileDialog1.Filter = "C# Files |*.cs"; saveFileDialog1.FilterIndex = 1; saveFileDialog1.OverwritePrompt = true; if (saveFileDialog1.ShowDialog() != DialogResult.Cancel) { textEditorControl1.SaveFile(saveFileDialog1.FileName); textEditorControl1.FileName = saveFileDialog1.FileName; } } private void printToolStripMenuItem_Click(object sender, EventArgs e) { printFile(); } private void printFile() { PrintDialog dlg = new PrintDialog(); dlg.Document = printDoc; if (dlg.ShowDialog() == DialogResult.OK) { printDoc.Print(); } } private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e) { printPreview(); } private void printPreview() { PrintPreviewDialog dlg = new PrintPreviewDialog(); dlg.Document = printDoc; dlg.ShowDialog(); } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { exit(); } private void exit() { if (!changed || MessageBox.Show(this, "The script source code has been changed. Are you sure you wish to close?", "Source code changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { //this.Close(); Statics_Engine.SystemSettings.enableCompilerConsole = false; } } private void undoToolStripMenuItem_Click(object sender, EventArgs e) { textEditorControl1.Undo(); } private void redoToolStripMenuItem_Click(object sender, EventArgs e) { textEditorControl1.Redo(); } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { } private void cutToolStripMenuItem_Click(object sender, EventArgs e) { textCut(sender,e); } private void copyToolStripMenuItem_Click(object sender, EventArgs e) { textCopy(sender,e); } private void pasteToolStripMenuItem_Click(object sender, EventArgs e) { textPaste(sender, e); } private void selectAllToolStripMenuItem_Click(object sender, EventArgs e) { textEditorControl1.ActiveTextAreaControl.TextArea.ClipboardHandler.SelectAll(sender, e); } #endregion #region Tool Strip private void newToolStripButton_Click(object sender, EventArgs e) { newFile(); } private void openToolStripButton_Click(object sender, EventArgs e) { openFile(); } private void saveToolStripButton_Click(object sender, EventArgs e) { saveFile(); } private void printToolStripButton_Click(object sender, EventArgs e) { printFile(); } private void cutToolStripButton_Click(object sender, EventArgs e) { textCut(sender, e); } private void textCut(object sender, EventArgs e) { textEditorControl1.ActiveTextAreaControl.TextArea.ClipboardHandler.Cut(sender, e); } private void copyToolStripButton_Click(object sender, EventArgs e) { textCopy(sender, e); } private void textCopy(object sender, EventArgs e) { textEditorControl1.ActiveTextAreaControl.TextArea.ClipboardHandler.Copy(sender, e); } private void pasteToolStripButton_Click(object sender, EventArgs e) { textPaste(sender, e); } private void textPaste(object sender, EventArgs e) { textEditorControl1.ActiveTextAreaControl.TextArea.ClipboardHandler.Paste(sender, e); } private void helpToolStripButton_Click(object sender, EventArgs e) { } #endregion #region Context Menu Strip Items private void undoToolStripMenuItem1_Click(object sender, EventArgs e) { textEditorControl1.Undo(); } private void cutToolStripMenuItem1_Click(object sender, EventArgs e) { textCut(sender, e); } private void copyToolStripMenuItem1_Click(object sender, EventArgs e) { textCopy(sender, e); } private void pasteToolStripMenuItem1_Click(object sender, EventArgs e) { textPaste(sender, e); } private void deleteToolStripMenuItem_Click(object sender, EventArgs e) { textEditorControl1.ActiveTextAreaControl.TextArea.ClipboardHandler.Delete(sender, e); } private void selectAllToolStripMenuItem1_Click(object sender, EventArgs e) { textEditorControl1.ActiveTextAreaControl.TextArea.ClipboardHandler.SelectAll(sender, e); } #endregion } }