diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs index 872548806b..053883c836 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs @@ -167,7 +167,7 @@ namespace CSharpBinding cachedLines.Clear(); invalidLines.Clear(); forceParseOnNextRefresh = true; - OnHighlightingStateChanged(0, document.LineCount); + OnHighlightingStateChanged(1, document.LineCount); } void ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e) @@ -190,7 +190,7 @@ namespace CSharpBinding protected virtual void OnHighlightingStateChanged(int fromLineNumber, int toLineNumber) { if (HighlightingStateChanged != null) { - HighlightingStateChanged(this, fromLineNumber, toLineNumber); + HighlightingStateChanged(fromLineNumber, toLineNumber); } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs index c6e4ecf38e..27c5a37e83 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -17,7 +16,6 @@ using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.Editor; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; -using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Refactoring; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditorControlService.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditorControlService.cs index a60ed414be..9e1c49d681 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditorControlService.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditorControlService.cs @@ -52,9 +52,7 @@ namespace ICSharpCode.AvalonEdit.AddIn // add additional highlighters highlighters.AddRange(SD.AddInTree.BuildItems(HighlighterDoozer.AddInPath, document, false)); var multiHighlighter = new MultiHighlighter(document, highlighters.ToArray()); - return new CustomizingHighlighter( - document, CustomizedHighlightingColor.FetchCustomizations(def.Name), - multiHighlighter); + return new CustomizingHighlighter(multiHighlighter, CustomizedHighlightingColor.FetchCustomizations(def.Name)); } } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizingHighlighter.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizingHighlighter.cs index 058cf73e35..5d36f25750 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizingHighlighter.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizingHighlighter.cs @@ -121,59 +121,34 @@ namespace ICSharpCode.AvalonEdit.AddIn } #endregion - readonly TextView textView; readonly IEnumerable customizations; readonly IHighlighter baseHighlighter; - readonly IDocument document; - public CustomizingHighlighter(TextView textView, IEnumerable customizations, IHighlighter baseHighlighter) + public CustomizingHighlighter(IHighlighter baseHighlighter, IEnumerable customizations) { - if (textView == null) - throw new ArgumentNullException("textView"); - if (customizations == null) - throw new ArgumentNullException("customizations"); if (baseHighlighter == null) throw new ArgumentNullException("baseHighlighter"); - - this.textView = textView; - this.document = textView.Document; - this.customizations = customizations; - this.baseHighlighter = baseHighlighter; - baseHighlighter.HighlightingStateChanged += highlighter_HighlightingStateChanged; - } - - public CustomizingHighlighter(IDocument document, IEnumerable customizations, IHighlighter baseHighlighter) - { - if (document == null) - throw new ArgumentNullException("document"); if (customizations == null) throw new ArgumentNullException("customizations"); - if (baseHighlighter == null) - throw new ArgumentNullException("baseHighlighter"); - this.document = document; this.customizations = customizations; this.baseHighlighter = baseHighlighter; - baseHighlighter.HighlightingStateChanged += highlighter_HighlightingStateChanged; } public IDocument Document { get { return baseHighlighter.Document; } } - public event HighlightingStateChangedEventHandler HighlightingStateChanged; + public event HighlightingStateChangedEventHandler HighlightingStateChanged { + add { baseHighlighter.HighlightingStateChanged += value; } + remove { baseHighlighter.HighlightingStateChanged -= value; } + } public void UpdateHighlightingState(int lineNumber) { baseHighlighter.UpdateHighlightingState(lineNumber); } - void highlighter_HighlightingStateChanged(IHighlighter sender, int fromLineNumber, int toLineNumber) - { - if (HighlightingStateChanged != null) - HighlightingStateChanged(this, fromLineNumber, toLineNumber); - } - public IEnumerable GetSpanColorNamesFromLineStart(int lineNumber) { // delayed evaluation doesn't cause a problem here: GetColorStack is called immediately, @@ -198,25 +173,7 @@ namespace ICSharpCode.AvalonEdit.AddIn return line; } - public void InvalidateLine(IDocumentLine line) - { - if (textView == null) - throw new InvalidOperationException("IHighlighter has no TextView assigned!"); - textView.Redraw(line, DispatcherPriority.Background); - } - - public void InvalidateAll() - { - if (textView == null) - throw new InvalidOperationException("IHighlighter has no TextView assigned!"); - textView.Redraw(DispatcherPriority.Background); - } - - public event EventHandler VisibleDocumentLinesChanged { - add { textView.VisualLinesChanged += value; } - remove { textView.VisualLinesChanged -= value; } - } - + /* public IEnumerable GetVisibleDocumentLines() { if (textView == null) @@ -239,7 +196,7 @@ namespace ICSharpCode.AvalonEdit.AddIn } } return result; - } + }*/ public HighlightingColor GetNamedColor(string name) { diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DiffControl.xaml.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DiffControl.xaml.cs index bbb7a7d456..f93a988ed0 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DiffControl.xaml.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DiffControl.xaml.cs @@ -49,9 +49,8 @@ namespace ICSharpCode.AvalonEdit.AddIn string language = source.SyntaxHighlighting != null ? source.SyntaxHighlighting.Name : null; editor.TextArea.TextView.LineTransformers.RemoveAll(x => x is HighlightingColorizer); var customizedHighlighter = new CustomizingHighlighter( - editor.TextArea.TextView, - CustomizedHighlightingColor.FetchCustomizations(language), - new DocumentHighlighter(editor.Document, source.SyntaxHighlighting) + new DocumentHighlighter(editor.Document, source.SyntaxHighlighting), + CustomizedHighlightingColor.FetchCustomizations(language) ); editor.TextArea.TextView.LineTransformers.Insert(0, new HighlightingColorizer(customizedHighlighter)); CustomizingHighlighter.ApplyCustomizationsToDefaultElements(editor, CustomizedHighlightingColor.FetchCustomizations(language)); diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs index b8f89f0dc5..c4f594d4c9 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs @@ -557,8 +557,8 @@ namespace ICSharpCode.AvalonEdit.AddIn.Options if (item != null) { if (item.ParentDefinition != null) { var highlighter = new CustomizingHighlighter( - textView, customizationsForCurrentLanguage, - new DocumentHighlighter(textView.Document, item.ParentDefinition) + new DocumentHighlighter(textView.Document, item.ParentDefinition), + customizationsForCurrentLanguage ); colorizer = new HighlightingColorizer(highlighter); textView.LineTransformers.Add(colorizer); diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockDocument.cs b/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockDocument.cs index 5b47cd9bdc..7f2910681e 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockDocument.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockDocument.cs @@ -177,7 +177,10 @@ namespace XmlEditor.Tests.Utils throw new NotImplementedException(); } - public event EventHandler ChangeCompleted; + public event EventHandler ChangeCompleted { + add { throw new NotImplementedException(); } + remove { throw new NotImplementedException(); } + } public IDocument CreateDocumentSnapshot() { diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/DocumentHighlighter.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/DocumentHighlighter.cs index 94ade5cd0f..3f867a0288 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/DocumentHighlighter.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/DocumentHighlighter.cs @@ -244,7 +244,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting } else { firstInvalidLine = int.MaxValue; } - OnHighlightStateChanged(lineNumber, lineNumber); + if (lineNumber + 1 < document.LineCount) + OnHighlightStateChanged(lineNumber + 1, lineNumber + 1); } else if (firstInvalidLine == lineNumber) { isValid[lineNumber] = true; firstInvalidLine = isValid.IndexOf(false); @@ -284,7 +285,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting protected virtual void OnHighlightStateChanged(int fromLineNumber, int toLineNumber) { if (HighlightingStateChanged != null) - HighlightingStateChanged(this, fromLineNumber, toLineNumber); + HighlightingStateChanged(fromLineNumber, toLineNumber); } #region Highlighting Engine diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs index 17266d67e7..ebc9e24f36 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs @@ -3,12 +3,9 @@ using System; using System.Diagnostics; -using System.Windows; using System.Windows.Media; -using System.Windows.Threading; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; -using ICSharpCode.NRefactory.Editor; namespace ICSharpCode.AvalonEdit.Highlighting { @@ -147,11 +144,13 @@ namespace ICSharpCode.AvalonEdit.Highlighting if (highlighter != null) { // Force update of highlighting state up to the position where we start generating visual lines. // This is necessary in case the document gets modified above the FirstLineInView so that the highlighting state changes. - // We need to detect this case and issue a redraw (through TextViewDocumentHighligher.OnHighlightStateChanged) + // We need to detect this case and issue a redraw (through OnHighlightStateChanged) // before the visual line construction reuses existing lines that were built using the invalid highlighting state. lineNumberBeingColorized = e.FirstLineInView.LineNumber - 1; if (!isInHighlightingGroup) { // avoid opening group twice if there was an exception during the previous visual line construction + // (not ideal, but better than throwing InvalidOperationException "group already open" + // without any way of recovering) highlighter.BeginHighlighting(); isInHighlightingGroup = true; } @@ -254,13 +253,15 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// Hey, the user typed "/*". Don't just recreate that line, but also the next one /// because my highlighting state (at end of line) changed! /// - void OnHighlightStateChanged(IHighlighter sender, int fromlineNumber, int toLineNumber) + void OnHighlightStateChanged(int fromLineNumber, int toLineNumber) { - if (lineNumberBeingColorized < fromlineNumber || lineNumberBeingColorized > toLineNumber) { + if (lineNumberBeingColorized != 0) { // Ignore notifications for any line except the one we're interested in. // This improves the performance as Redraw() can take quite some time when called repeatedly // while scanning the document (above the visible area) for highlighting changes. - return; + if (toLineNumber <= lineNumberBeingColorized) { + return; + } } // The user may have inserted "/*" into the current line, and so far only that line got redrawn. @@ -268,7 +269,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting // If the highlighting state change applies to the lines below, too, the construction of each line // will invalidate the next line, and the construction pass will regenerate all lines. - Debug.WriteLine("OnHighlightStateChanged forces redraw of lines {0} to {1}", fromlineNumber + 1, toLineNumber + 1); + Debug.WriteLine("OnHighlightStateChanged forces redraw of lines {0} to {1}", fromLineNumber, toLineNumber); // If the VisualLine construction is in progress, we have to avoid sending redraw commands for // anything above the line currently being constructed. @@ -309,9 +310,17 @@ namespace ICSharpCode.AvalonEdit.Highlighting // so it will always invalidate the next visual line when a folded line is constructed // and the highlighting stack has changed. - for (int lineNumber = fromlineNumber; lineNumber <= toLineNumber; lineNumber++) { - if (lineNumber + 1 <= textView.Document.LineCount) - textView.Redraw(textView.Document.GetLineByNumber(lineNumber + 1), DispatcherPriority.Normal); + if (fromLineNumber == toLineNumber) { + textView.Redraw(textView.Document.GetLineByNumber(fromLineNumber)); + } else { + // If there are multiple lines marked as changed; only the first one really matters + // for the highlighting during rendering. + // However this callback is also called outside of the rendering process, e.g. when a highlighter + // decides to re-highlight some section based on external feedback (e.g. semantic highlighting). + var fromLine = textView.Document.GetLineByNumber(fromLineNumber); + var toLine = textView.Document.GetLineByNumber(toLineNumber); + int startOffset = fromLine.Offset; + textView.Redraw(startOffset, toLine.EndOffset - startOffset); } /* diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/IHighlighter.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/IHighlighter.cs index 1252d1147f..888b76bef7 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/IHighlighter.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/IHighlighter.cs @@ -45,20 +45,29 @@ namespace ICSharpCode.AvalonEdit.Highlighting void UpdateHighlightingState(int lineNumber); /// - /// Notification when the highlighter detects that the highlighting state at the end of a line - /// has changed. - /// This event gets raised for each line as it is processed by the highlighter - /// unless the highlighting state for the line is equal to the old state (when the same line was highlighted previously). + /// Notification when the highlighter detects that the highlighting state at the + /// beginning of the specified lines has changed. + /// fromLineNumber and toLineNumber are both inclusive; + /// the common case of a single-line change is represented by fromLineNumber == toLineNumber. + /// + /// During highlighting, the highlighting of line X will cause this event to be raised + /// for line X+1 if the highlighting state at the end of line X has changed from its previous state. + /// This event may also be raised outside of the highlighting process to signalize that + /// changes to external data (not the document text; but e.g. semantic information) + /// require a re-highlighting of the specified lines. /// /// - /// For implementers: there is the requirement that, if there was no state changed reported at line X, - /// and there were no document changes between line X and Y (with Y > X), then - /// this event must not be raised for any line between X and Y. + /// For implementers: there is the requirement that, during highlighting, + /// if there was no state changed reported for the beginning of line X, + /// and there were no document changes between the start of line X and the start of line Y (with Y > X), + /// then this event must not be raised for any line between X and Y (inclusive). /// /// Equal input state + unchanged line = Equal output state. /// /// See the comment in the HighlightingColorizer.OnHighlightStateChanged implementation /// for details about the requirements for a correct custom IHighlighter. + /// + /// Outside of the highlighting process, this event can be raised without such restrictions. /// event HighlightingStateChangedEventHandler HighlightingStateChanged; @@ -94,5 +103,5 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// /// Event handler for /// - public delegate void HighlightingStateChangedEventHandler(IHighlighter sender, int fromLineNumber, int toLineNumber); + public delegate void HighlightingStateChangedEventHandler(int fromLineNumber, int toLineNumber); } diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.xaml.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.xaml.cs index ec531ebeb6..cc416e8634 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.xaml.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.xaml.cs @@ -233,7 +233,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels src.StreamSource = memoryStream; src.EndInit(); Image = src; - + } catch (OutOfMemoryException) { Image = null; MessageService.ShowErrorFormatted("${res:Dialog.ProjectOptions.ApplicationSettings.InvalidIconFile}", @@ -282,7 +282,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels // Because this event is raised while the combobox is still switching to the "" or "" value, // we cannot set comboBox.Text within this event handler. // To avoid this problem, we invoke the operation after the combobox has finished switching to the new value. - WorkbenchSingleton.SafeThreadAsyncCall( + Dispatcher.BeginInvoke(new Action( delegate { if (applicationManifestComboBox.SelectedIndex == applicationManifestComboBox.Items.Count - 2) { CreateManifest(); @@ -292,7 +292,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels // we need to store re-load the changed property value. applicationManifestComboBox.Text = this.ApplicationManifest.Value; } - }); + })); } void CreateManifest() diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/Signing.xaml.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/Signing.xaml.cs index 958e3edf3f..3d9b172762 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/Signing.xaml.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/Signing.xaml.cs @@ -22,7 +22,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels public partial class Signing : ProjectOptionPanel { private const string KeyFileExtensions = "*.snk;*.pfx;*.key"; - + public Signing() { InitializeComponent(); @@ -50,7 +50,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels #region overrides - + protected override void Load(MSBuildBasedProject project, string configuration, string platform) { base.Load(project, configuration, platform); @@ -130,7 +130,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels // Because this event is raised while the combobox is still switching to the "" or "" value, // we cannot set comboBox.Text within this event handler. // To avoid this problem, we invoke the operation after the combobox has finished switching to the new value. - WorkbenchSingleton.SafeThreadAsyncCall( + Dispatcher.BeginInvoke(new Action( delegate { if (this.keyFileComboBox.SelectedIndex == keyFile.Count - 1) { keyFileComboBox.Text = String.Empty; @@ -141,7 +141,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels keyFileComboBox.Text = String.Empty; CreateKeyFile(); } - }); + })); } private void CreateKeyFile()