|
|
|
@ -7,7 +7,9 @@
@@ -7,7 +7,9 @@
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Drawing; |
|
|
|
|
using System.Text; |
|
|
|
|
using System.Threading; |
|
|
|
|
using System.Windows.Forms; |
|
|
|
|
|
|
|
|
@ -56,15 +58,29 @@ namespace ICSharpCode.SharpDevelop.Gui
@@ -56,15 +58,29 @@ namespace ICSharpCode.SharpDevelop.Gui
|
|
|
|
|
return selectedCategory; |
|
|
|
|
} |
|
|
|
|
set { |
|
|
|
|
WorkbenchSingleton.AssertMainThread(); |
|
|
|
|
if (selectedCategory != value) { |
|
|
|
|
selectedCategory = value; |
|
|
|
|
textEditorControl.Text = (value < 0) ? "" : StringParser.Parse(messageCategories[value].Text); |
|
|
|
|
//textEditorControl.Refresh();
|
|
|
|
|
DisplayActiveCategory(); |
|
|
|
|
OnSelectedCategoryIndexChanged(EventArgs.Empty); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DisplayActiveCategory() |
|
|
|
|
{ |
|
|
|
|
WorkbenchSingleton.DebugAssertMainThread(); |
|
|
|
|
if (selectedCategory < 0) { |
|
|
|
|
textEditorControl.Text = ""; |
|
|
|
|
} else { |
|
|
|
|
lock (messageCategories[selectedCategory].SyncRoot) { |
|
|
|
|
// accessing a categories' text takes its lock - but we have to take locks in the same
|
|
|
|
|
// order as in the Append calls to prevent a deadlock
|
|
|
|
|
EnqueueAppend(new AppendCall(messageCategories[selectedCategory], messageCategories[selectedCategory].Text, true)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public bool WordWrap { |
|
|
|
|
get { |
|
|
|
|
return properties.Get("WordWrap", true); |
|
|
|
@ -136,19 +152,17 @@ namespace ICSharpCode.SharpDevelop.Gui
@@ -136,19 +152,17 @@ namespace ICSharpCode.SharpDevelop.Gui
|
|
|
|
|
|
|
|
|
|
SetWordWrap(); |
|
|
|
|
myPanel.ResumeLayout(false); |
|
|
|
|
SetText(messageCategories[selectedCategory], messageCategories[selectedCategory].Text); |
|
|
|
|
DisplayActiveCategory(); |
|
|
|
|
ProjectService.SolutionLoaded += SolutionLoaded; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SolutionLoaded(object sender, SolutionEventArgs e) |
|
|
|
|
{ |
|
|
|
|
foreach (MessageViewCategory category in messageCategories) |
|
|
|
|
{ |
|
|
|
|
ClearText(category); |
|
|
|
|
foreach (MessageViewCategory category in messageCategories) { |
|
|
|
|
category.ClearText(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void SetWordWrap() |
|
|
|
|
{ |
|
|
|
|
bool wordWrap = this.WordWrap; |
|
|
|
@ -179,105 +193,111 @@ namespace ICSharpCode.SharpDevelop.Gui
@@ -179,105 +193,111 @@ namespace ICSharpCode.SharpDevelop.Gui
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
messageCategories.Add(category); |
|
|
|
|
category.Cleared += new EventHandler(CategoryTextCleared); |
|
|
|
|
category.TextSet += new TextEventHandler(CategoryTextSet); |
|
|
|
|
category.TextAppended += new TextEventHandler(CategoryTextAppended); |
|
|
|
|
|
|
|
|
|
OnMessageCategoryAdded(EventArgs.Empty); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CategoryTextCleared(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
WorkbenchSingleton.SafeThreadAsyncCall(new Action<MessageViewCategory>(ClearText), |
|
|
|
|
(MessageViewCategory)sender); |
|
|
|
|
} |
|
|
|
|
void ClearText(MessageViewCategory category) |
|
|
|
|
void CategoryTextSet(object sender, TextEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (messageCategories[SelectedCategoryIndex] == category) { |
|
|
|
|
textEditorControl.Text = String.Empty; |
|
|
|
|
//textEditorControl.Refresh();
|
|
|
|
|
} |
|
|
|
|
EnqueueAppend(new AppendCall((MessageViewCategory)sender, e.Text, true)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CategoryTextSet(object sender, TextEventArgs e) |
|
|
|
|
struct AppendCall |
|
|
|
|
{ |
|
|
|
|
WorkbenchSingleton.SafeThreadAsyncCall(new Action<MessageViewCategory, string>(SetText), |
|
|
|
|
(MessageViewCategory)sender, e.Text); |
|
|
|
|
internal readonly MessageViewCategory Category; |
|
|
|
|
internal readonly string Text; |
|
|
|
|
internal readonly bool ClearCategory; |
|
|
|
|
|
|
|
|
|
public AppendCall(MessageViewCategory category, string text, bool clearCategory) |
|
|
|
|
{ |
|
|
|
|
this.Category = category; |
|
|
|
|
this.Text = text; |
|
|
|
|
this.ClearCategory = clearCategory; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
object appendCallLock = new object(); |
|
|
|
|
volatile int pendingAppendCalls = 0; |
|
|
|
|
readonly object appendLock = new object(); |
|
|
|
|
List<AppendCall> appendCalls = new List<AppendCall>(); |
|
|
|
|
|
|
|
|
|
void CategoryTextAppended(object sender, TextEventArgs e) |
|
|
|
|
{ |
|
|
|
|
lock (appendCallLock) { |
|
|
|
|
pendingAppendCalls += 1; |
|
|
|
|
MessageViewCategory cat = (MessageViewCategory)sender; |
|
|
|
|
if (pendingAppendCalls < 5) { |
|
|
|
|
WorkbenchSingleton.SafeThreadAsyncCall(new Action<MessageViewCategory, string, string>(AppendText), |
|
|
|
|
cat, cat.Text, e.Text); |
|
|
|
|
} else if (pendingAppendCalls == 5) { |
|
|
|
|
WorkbenchSingleton.SafeThreadAsyncCall(new Action<MessageViewCategory>(AppendTextCombined), |
|
|
|
|
cat); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
EnqueueAppend(new AppendCall((MessageViewCategory)sender, e.Text, false)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AppendTextCombined(MessageViewCategory category) |
|
|
|
|
void EnqueueAppend(AppendCall appendCall) |
|
|
|
|
{ |
|
|
|
|
Application.DoEvents(); |
|
|
|
|
Thread.Sleep(50); |
|
|
|
|
Application.DoEvents(); |
|
|
|
|
lock (appendCallLock) { |
|
|
|
|
NativeMethods.SetWindowRedraw(textEditorControl.Handle, false); |
|
|
|
|
SetText(category, category.Text); |
|
|
|
|
NativeMethods.SetWindowRedraw(textEditorControl.Handle, true); |
|
|
|
|
textEditorControl.SelectionStart = textEditorControl.TextLength; |
|
|
|
|
if (LoggingService.IsDebugEnabled) { |
|
|
|
|
LoggingService.Debug("Replaced " + pendingAppendCalls + " appends with one set call"); |
|
|
|
|
} |
|
|
|
|
pendingAppendCalls = 0; |
|
|
|
|
} |
|
|
|
|
textEditorControl.Refresh(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AppendText(MessageViewCategory category, string fullText, string text) |
|
|
|
|
bool waitForMainThread; |
|
|
|
|
lock (appendLock) { |
|
|
|
|
appendCalls.Add(appendCall); |
|
|
|
|
if (appendCalls.Count == 1) |
|
|
|
|
WorkbenchSingleton.SafeThreadAsyncCall(ProcessAppendText); |
|
|
|
|
waitForMainThread = appendCalls.Count > 2000; |
|
|
|
|
} |
|
|
|
|
if (waitForMainThread && WorkbenchSingleton.InvokeRequired) { |
|
|
|
|
int sleepLength = 20; |
|
|
|
|
do { |
|
|
|
|
Thread.Sleep(sleepLength); |
|
|
|
|
sleepLength += 20; |
|
|
|
|
lock (appendLock) |
|
|
|
|
waitForMainThread = appendCalls.Count > 2000; |
|
|
|
|
//if (waitForMainThread) LoggingService.Debug("Extending sleep (" + sleepLength + ")");
|
|
|
|
|
} while (waitForMainThread); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ProcessAppendText() |
|
|
|
|
{ |
|
|
|
|
lock (appendCallLock) { |
|
|
|
|
if (pendingAppendCalls >= 5) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
pendingAppendCalls -= 1; |
|
|
|
|
List<AppendCall> appendCalls; |
|
|
|
|
lock (appendLock) { |
|
|
|
|
appendCalls = this.appendCalls; |
|
|
|
|
this.appendCalls = new List<AppendCall>(); |
|
|
|
|
} |
|
|
|
|
if (messageCategories[SelectedCategoryIndex] != category) { |
|
|
|
|
SelectCategory(category.Category, fullText); |
|
|
|
|
Debug.Assert(appendCalls.Count > 0); |
|
|
|
|
if (appendCalls.Count == 0) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (text != null) { |
|
|
|
|
text = StringParser.Parse(text); |
|
|
|
|
textEditorControl.AppendText(text); |
|
|
|
|
textEditorControl.SelectionStart = textEditorControl.TextLength; |
|
|
|
|
/*textEditorControl.Document.ReadOnly = false; |
|
|
|
|
textEditorControl.Document.Insert(textEditorControl.Document.TextLength, text); |
|
|
|
|
textEditorControl.Document.ReadOnly = true; |
|
|
|
|
textEditorControl.ActiveTextAreaControl.Caret.Position = new Point(0, textEditorControl.Document.TotalNumberOfLines); |
|
|
|
|
textEditorControl.ActiveTextAreaControl.ScrollTo(textEditorControl.Document.TotalNumberOfLines);*/ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SetText(MessageViewCategory category, string text) |
|
|
|
|
{ |
|
|
|
|
if (messageCategories[SelectedCategoryIndex] != category) { |
|
|
|
|
SelectCategory(category.Category); |
|
|
|
|
|
|
|
|
|
MessageViewCategory newCategory = appendCalls[appendCalls.Count - 1].Category; |
|
|
|
|
if (messageCategories[SelectedCategoryIndex] != newCategory) { |
|
|
|
|
SelectCategory(newCategory.Category); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (text == null) { |
|
|
|
|
text = String.Empty; |
|
|
|
|
|
|
|
|
|
bool clear; |
|
|
|
|
string text; |
|
|
|
|
if (appendCalls.Count == 1) { |
|
|
|
|
//LoggingService.Debug("CompilerMessageView: Single append.");
|
|
|
|
|
clear = appendCalls[0].ClearCategory; |
|
|
|
|
text = appendCalls[0].Text; |
|
|
|
|
} else { |
|
|
|
|
if (LoggingService.IsDebugEnabled) { |
|
|
|
|
LoggingService.Debug("CompilerMessageView: Combined " + appendCalls.Count + " appends."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
clear = false; |
|
|
|
|
StringBuilder b = new StringBuilder(); |
|
|
|
|
foreach (AppendCall append in appendCalls) { |
|
|
|
|
if (append.Category == newCategory) { |
|
|
|
|
if (append.ClearCategory) { |
|
|
|
|
b.Length = 0; |
|
|
|
|
clear = true; |
|
|
|
|
} |
|
|
|
|
b.Append(append.Text); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
text = b.ToString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//NativeMethods.SetWindowRedraw(textEditorControl.Handle, false);
|
|
|
|
|
if (clear) { |
|
|
|
|
textEditorControl.Text = text; |
|
|
|
|
} else { |
|
|
|
|
text = StringParser.Parse(text); |
|
|
|
|
textEditorControl.SelectionStart = textEditorControl.TextLength; |
|
|
|
|
textEditorControl.SelectedText = text; |
|
|
|
|
} |
|
|
|
|
textEditorControl.Text = text; |
|
|
|
|
//textEditorControl.Refresh();
|
|
|
|
|
//NativeMethods.SetWindowRedraw(textEditorControl.Handle, true);
|
|
|
|
|
textEditorControl.SelectionStart = textEditorControl.TextLength; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void SelectCategory(string categoryName) |
|
|
|
|