⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compilermessageview.cs

📁 c#源代码
💻 CS
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
//     <version value="$version"/>
// </file>

using System;
using System.Collections;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
using System.CodeDom.Compiler;
using System.IO;
using System.Diagnostics;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.Core.Properties;
using ICSharpCode.Core.Services;
using ICSharpCode.SharpDevelop.Gui.Dialogs.OptionPanels;

namespace ICSharpCode.SharpDevelop.Gui.Pads
{
	/// <summary>
	/// This class displays the errors and warnings which the compiler outputs and
	/// allows the user to jump to the source of the warnig / error
	/// </summary>
	public class CompilerMessageView : AbstractPadContent
	{
		RichTextBox     textEditorControl = new RichTextBox();
		ComboBox        messageCategory   = new ComboBox();
		Panel           myPanel           = new Panel();
		
		ResourceService resourceService   = (ResourceService)ServiceManager.Services.GetService(typeof(IResourceService));
		ArrayList       messageCategories = new ArrayList();
		
		// The compiler message view properties.
		IProperties 	properties	      = null;
		
		public override Control Control {
			get {
				return myPanel;
			}
		}
		
		public CompilerMessageView() : base("${res:MainWindow.Windows.OutputWindow}", "Icons.16x16.OutputIcon")
		{
			AddCategory(new MessageViewCategory("Build", "${res:MainWindow.Windows.OutputWindow.BuildCategory}"));
			
			messageCategory.Dock = DockStyle.Top;
			messageCategory.DropDownStyle = ComboBoxStyle.DropDownList;
			StringParserService stringParserService = (StringParserService)ServiceManager.Services.GetService(typeof(StringParserService));
			messageCategory.SelectedIndex = 0;
			messageCategory.SelectedIndexChanged += new EventHandler(MessageCategorySelectedIndexChanged);
			textEditorControl.Dock     = DockStyle.Fill;
			textEditorControl.ReadOnly = true;
			
			ResourceService resourceService = (ResourceService)ServiceManager.Services.GetService(typeof(IResourceService));
			messageCategory.Font = resourceService.LoadFont("Arial", 9, FontStyle.Bold);
			
			PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
			properties = (IProperties)propertyService.GetProperty(OutputWindowOptionsPanel.OutputWindowsProperty, new DefaultProperties());
			textEditorControl.WordWrap = properties.GetProperty("WordWrap", true);
			textEditorControl.Font     = FontSelectionPanel.ParseFont(properties.GetProperty("DefaultFont", new Font("Courier New", 10).ToString()).ToString());
			properties.PropertyChanged += new PropertyEventHandler(PropertyChanged);
			
			myPanel.Controls.Add(textEditorControl);
			myPanel.Controls.Add(messageCategory);
			
			TaskService     taskService    = (TaskService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(TaskService));
			IProjectService projectService = (IProjectService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
			
			taskService.CompilerOutputChanged += new EventHandler(SetCompilerOutput);
			
			projectService.StartBuild    += new EventHandler(ProjectServiceStartBuild);
			projectService.CombineOpened += new CombineEventHandler(ClearOnCombineEvent);
			textEditorControl.MouseDown += new MouseEventHandler(TextEditorControlMouseDown);
			textEditorControl.CreateControl();
		}
		
		public override void RedrawContent()
		{
			StringParserService stringParserService = (StringParserService)ServiceManager.Services.GetService(typeof(StringParserService));
			messageCategory.Items.Clear();
			foreach (MessageViewCategory category in messageCategories) {
				messageCategory.Items.Add(stringParserService.Parse(category.DisplayCategory));
			}
			OnTitleChanged(null);
			OnIconChanged(null);
		}
		
		#region Category handling
		public void AddCategory(MessageViewCategory category)
		{
			StringParserService stringParserService = (StringParserService)ServiceManager.Services.GetService(typeof(StringParserService));
			messageCategory.Items.Add(stringParserService.Parse(category.DisplayCategory));
			messageCategories.Add(category);
			category.TextChanged += new EventHandler(CategoryTextChanged);
		}
		
		void CategoryTextChanged(object sender, EventArgs e)
		{
			MessageViewCategory category = (MessageViewCategory)sender;
			SelectCategory(category.Category);
			OutputCategoryText();
		}
		
		public void SelectCategory(string categoryName)
		{
			for (int i = 0; i < messageCategories.Count; ++i) {
				MessageViewCategory category = (MessageViewCategory)messageCategories[i];
				if (category.Category == categoryName) {
					messageCategory.SelectedIndex = i;
					break;
				}
			}
			ActivateThisPad();
		}
		
		public MessageViewCategory GetCategory(string categoryName)
		{
			foreach (MessageViewCategory category in messageCategories) {
				if (category.Category == categoryName) {
					return category;
				}
			}
			return null;
		}
		#endregion
		
		#region Message Event Handlers (Build)
		void ProjectServiceStartBuild(object sender, EventArgs e)
		{
			MessageViewCategory buildCategory = GetCategory("Build");
			buildCategory.ClearText();
			SelectCategory("Build");
		}
		
		void ClearOnCombineEvent(object sender, CombineEventArgs e)
		{
			MessageViewCategory buildCategory = GetCategory("Build");
			buildCategory.ClearText();
		}
		
		void SetCompilerOutput(object sender, EventArgs e)
		{
			TaskService taskService = (TaskService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(TaskService));
			MessageViewCategory buildCategory = GetCategory("Build");
			buildCategory.SetText(taskService.CompilerOutput);
		}
		#endregion
		
		delegate void StringDelegate(string text);
		/// <summary>
		/// Non threadsafe way of setting text -> use OutputCategoryText() to do the job.
		/// </summary>
		void SetText(string text)
		{
			if (text == null) {
				text = String.Empty;
			}
			textEditorControl.Text = text;
			textEditorControl.Select(text.Length , 0);
			textEditorControl.Select();
			textEditorControl.ScrollToCaret();
		}
		
		/// <summary>
		/// Makes this pad visible (usually BEFORE build or debug events)
		/// </summary>
		void ActivateThisPad()
		{
			PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
			WorkbenchSingleton.Workbench.WorkbenchLayout.ActivatePad(this);
		}
		
		/// <summary>
		/// Thread safe way to set the output text of the current selected category
		/// in the text area.
		/// </summary>
		void OutputCategoryText()
		{
			StringParserService stringParserService = (StringParserService)ServiceManager.Services.GetService(typeof(StringParserService));
			string text = stringParserService.Parse(((MessageViewCategory)messageCategories[messageCategory.SelectedIndex]).Text);
			// use invoke when running on another thread (in #D all other treads are background threads)
			if (Thread.CurrentThread.IsBackground) {
				textEditorControl.Invoke(new StringDelegate(SetText), new object[] {text} );
			} else {
				SetText(text);
			}
		}
		
		void MessageCategorySelectedIndexChanged(object sender, EventArgs e)
		{
			OutputCategoryText();
		}
		
		/// <summary>
		/// Occurs when the mouse pointer is over the control and a
		/// mouse button is pressed.
		/// </summary>
		void TextEditorControlMouseDown(object sender, MouseEventArgs e)
		{
			// Double click?
			if (e.Clicks == 2) {
				
				// Any text?
				if (textEditorControl.Text.Length > 0) {
					
					// Parse text line double clicked.
					Point point = new Point(e.X, e.Y);
					
					int charIndex = textEditorControl.GetCharIndexFromPosition(point);
					string textLine = GetTextLine(charIndex, textEditorControl.Text);
					
//					if (textLine != null) {
//						Console.WriteLine("textEditorDblClick textline=" + textLine);
//					} else {
//						Console.WriteLine("textEditorDblClick GetTextLine returned null. CharIndex=" + charIndex);
//					}
					
					FileLineReference lineReference = OutputTextLineParser.GetFileLineReference(textLine);
					if (lineReference != null) {
						// Open matching file.
						JumpToFilePosition(Path.GetFullPath(lineReference.FileName),
						                   lineReference.Line,
						                   lineReference.Column);
					}
				}
			}
		}
		/// <summary>
		/// Gets the line of text that includes the specified
		/// character index.
		/// </summary>
		/// <remarks>
		/// This is used instead of using the <see cref="RichTextBox.Lines"/>
		/// array since we have to take into account word wrapping.
		/// </remarks>
		string GetTextLine(int charIndex, string textLines)
		{
			Debug.Assert(charIndex < textLines.Length, String.Concat("CharIndex out of range. charIndex=", charIndex, ", textLines.Length=", textLines.Length));
			
			string textLine = String.Empty;
			
			int lineStartIndex = 0;
			int lineLength = 0;
			bool wasFound = false;
			
			for (int i = 0; i < textLines.Length; ++i) {
				char ch = textLines[i];
				
				if (ch == '\r' || ch == '\n') {
					// End of line.
					if (i >= charIndex) {
						// Found line.
						textLine = textLines.Substring(lineStartIndex, lineLength);
						wasFound = true;
						break;
					}
					else {
						lineStartIndex = i + 1;
						lineLength = 0;
					}
				} else {
					++lineLength;
				}
			}
			
			if (!wasFound && (lineLength > 0)) {
				textLine = textLines.Substring(lineStartIndex, lineLength);
			}
			
			return textLine;
		}
		
		/// <summary>
		/// Jumps to the specified file line number and position.
		/// </summary>
		/// <param name="filename">The filename.</param>
		/// <param name="line">The line number.</param>
		/// <param name="column">The line column</param>
		private void JumpToFilePosition(string filename, int line, int column)
		{
			IFileService fileService = (IFileService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(IFileService));
			fileService.JumpToFilePosition(filename, line, column);
		}
		
		/// <summary>
		/// Changes wordwrap settings if that property has changed.
		/// </summary>
		void PropertyChanged(object sender, PropertyEventArgs e)
		{
//			Console.WriteLine("OutputWindow.PropertyChanged");
//			Console.WriteLine("e.Key=" + e.Key);
			
			if (e.Key == "WordWrap") {
				textEditorControl.WordWrap = (bool)(e.NewValue);
			}
			if (e.Key == "DefaultFont") {
				textEditorControl.Font     = FontSelectionPanel.ParseFont(properties.GetProperty("DefaultFont", new Font("Courier New", 10).ToString()).ToString());
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -