private void OnCodeElementLine(object sender, DocumentChangedEvent <ICodeElementsLine> e) { System.Console.WriteLine("+++ OnCodeElementLine(..):"); int c = 0; if (e.DocumentChanges != null) { foreach (var change in e.DocumentChanges) { System.Console.WriteLine(" - " + change.Type + "@" + change.LineIndex); if (change.NewLine == null) { System.Console.WriteLine("Line NIL"); } else if (change.NewLine.CodeElements == null) { System.Console.WriteLine("CodeElements NIL"); } else { int i = 0; foreach (var ce in change.NewLine.CodeElements) { System.Console.WriteLine(" - " + ce); i++; } System.Console.WriteLine(" " + i + " CodeElements"); } c++; } } System.Console.WriteLine("+++ --> " + (c > 0?("" + c):(e.DocumentChanges == null?"?":"0")) + " changes"); }
public Controller(ICategoryService categoryService, IDocumentService documentService, IElementService elementService, IFilterService filterService, IParameterService parameterService, DocumentChangedEvent documentChangedEvent) { CategoryController = new CategoryController(categoryService); DocumentController = new DocumentController(documentService); ElementController = new ElementController(elementService); FilterController = new FilterController(filterService); ParameterController = new ParameterController(parameterService); DocumentChangedEvent = documentChangedEvent; }
// --- Handle Scanner and error events --- public void OnNext(DocumentChangedEvent <ITokensLine> tokensLinesChangedEvent) { // Refresh the display of all the lines which were not directly modified // but which were rescanned because of a scanner state change on a previous or following line foreach (var documentChange in tokensLinesChangedEvent.DocumentChanges) { DocumentLine rescannedLine = Document.GetLineByNumber(documentChange.LineIndex); TextArea.TextView.Redraw(rescannedLine.Offset, rescannedLine.Length); } }
private void HandleDocumentChanged(object sender, DocumentChangedEvent e) { SLogManager.getInstance().Info("HandleDocumentChanged received in DocumentManagerSupport"); _controlsForSave.Add(e.RequestData.VisualControl); foreach (DevExpress.XtraBars.BarItem item in _saveAllComponents) { item.Enabled = true; } if (e.RequestData.VisualControl == _activeControl) { foreach (DevExpress.XtraBars.BarItem item in _saveComponents) { item.Enabled = true; } } }
private void OnTextLine(object sender, DocumentChangedEvent <ICobolTextLine> e) { System.Console.WriteLine("--- OnTextLine(..):"); int c = 0; if (e.DocumentChanges != null) { foreach (var change in e.DocumentChanges) { System.Console.Write(" + " + change.Type + "@" + change.LineIndex + ": "); if (change.NewLine == null) { System.Console.WriteLine("?"); } else { System.Console.WriteLine("\"" + change.NewLine.SourceText + "\""); } c++; } } System.Console.WriteLine("--- --> " + (c > 0?("" + c):(e.DocumentChanges == null?"?":"0")) + " changes"); }
/// <summary> /// Creates a new snapshot of the document viewed as CodeElement objects after parsing. /// (if the processed tokens lines changed since the last time this method was called) /// Thread-safe : this method can be called from any thread. /// </summary> public void RefreshCodeElementsDocumentSnapshot() { // Make sure two threads don't try to update this snapshot at the same time lock (lockObjectForCodeElementsDocumentSnapshot) { // Capture previous snapshots at one point in time ProcessedTokensDocument processedTokensDocument = ProcessedTokensDocumentSnapshot; CodeElementsDocument previousCodeElementsDocument = CodeElementsDocumentSnapshot; // Check if an update is necessary and compute changes to apply since last version bool scanAllDocumentLines = false; IList <DocumentChange <IProcessedTokensLine> > processedTokensLineChanges = null; if (previousCodeElementsDocument == null) { scanAllDocumentLines = true; } else if (processedTokensDocument.CurrentVersion == previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion) { // Processed tokens lines did not change since last update => nothing to do return; } else { DocumentVersion <IProcessedTokensLine> previousProcessedTokensDocumentVersion = previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion; processedTokensLineChanges = previousProcessedTokensDocumentVersion.GetReducedAndOrderedChangesInNewerVersion(processedTokensDocument.CurrentVersion); } // Start perf measurement var perfStatsForParserInvocation = PerfStatsForCodeElementsParser.OnStartRefreshParsingStep(); // Track all changes applied to the document while updating this snapshot DocumentChangedEvent <ICodeElementsLine> documentChangedEvent = null; // Apply text changes to the compilation document if (scanAllDocumentLines) { if (processedTokensDocument != null) { // Parse the whole document for the first time CodeElementsParserStep.ParseDocument(TextSourceInfo, ((ImmutableList <CodeElementsLine>)processedTokensDocument.Lines), CompilerOptions, perfStatsForParserInvocation); // Create the first code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, new DocumentVersion <ICodeElementsLine>(this), ((ImmutableList <CodeElementsLine>)processedTokensDocument.Lines)); } } else { ImmutableList <CodeElementsLine> .Builder codeElementsDocumentLines = ((ImmutableList <CodeElementsLine>)processedTokensDocument.Lines).ToBuilder(); IList <DocumentChange <ICodeElementsLine> > documentChanges = CodeElementsParserStep.ParseProcessedTokensLinesChanges(TextSourceInfo, codeElementsDocumentLines, processedTokensLineChanges, PrepareDocumentLineForUpdate, CompilerOptions, perfStatsForParserInvocation); // Create a new version of the document to track these changes DocumentVersion <ICodeElementsLine> currentCodeElementsLinesVersion = previousCodeElementsDocument.CurrentVersion; currentCodeElementsLinesVersion.changes = documentChanges; currentCodeElementsLinesVersion.next = new DocumentVersion <ICodeElementsLine>(currentCodeElementsLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent <ICodeElementsLine>(currentCodeElementsLinesVersion, currentCodeElementsLinesVersion.next); currentCodeElementsLinesVersion = currentCodeElementsLinesVersion.next; // Update the code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, currentCodeElementsLinesVersion, codeElementsDocumentLines.ToImmutable()); } // Stop perf measurement PerfStatsForCodeElementsParser.OnStopRefreshParsingStep(); // Send events to all listeners EventHandler <DocumentChangedEvent <ICodeElementsLine> > codeElementsLinesChanged = CodeElementsLinesChanged; // avoid race condition if (documentChangedEvent != null && codeElementsLinesChanged != null) { codeElementsLinesChanged(this, documentChangedEvent); } } }
/// <summary> /// Update the tokens lines of the document if the text lines changed since the last time this method was called. /// NOT thread-safe : this method can only be called from the owner thread. /// </summary> public void UpdateTokensLines(System.Action onVersion = null) { // This method can only be called by the document owner thread if (documentOwnerThread == null) { documentOwnerThread = Thread.CurrentThread; } else { VerifyAccess(); } // Check if an update is necessary and compute changes to apply since last version bool scanAllDocumentLines = false; IList <DocumentChange <ICobolTextLine> > textLineChanges = null; if (textLinesVersionForCurrentTokensLines == null) { scanAllDocumentLines = true; } else if (currentTextLinesVersion == textLinesVersionForCurrentTokensLines) { // Text lines did not change since last update => nothing to do return; } else { textLineChanges = textLinesVersionForCurrentTokensLines.GetReducedAndOrderedChangesInNewerVersion(currentTextLinesVersion); } // Make sure we don't update the document while taking a snapshot DocumentChangedEvent <ITokensLine> documentChangedEvent = null; lock (lockObjectForDocumentLines) { // Start perf measurement PerfStatsForScanner.OnStartRefresh(); // Apply text changes to the compilation document if (scanAllDocumentLines) { ScannerStep.ScanDocument(TextSourceInfo, compilationDocumentLines, CompilerOptions, CopyTextNamesVariations, initialScanStateForCopy); } else { IList <DocumentChange <ITokensLine> > documentChanges = ScannerStep.ScanTextLinesChanges(TextSourceInfo, compilationDocumentLines, textLineChanges, PrepareDocumentLineForUpdate, CompilerOptions, CopyTextNamesVariations, initialScanStateForCopy); // Create a new version of the document to track these changes currentTokensLinesVersion.changes = documentChanges; currentTokensLinesVersion.next = new DocumentVersion <ITokensLine>(currentTokensLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent <ITokensLine>(currentTokensLinesVersion, currentTokensLinesVersion.next); currentTokensLinesVersion = currentTokensLinesVersion.next; if (onVersion != null) { onVersion(); } } // Register that the tokens lines were synchronized with the current text lines version textLinesVersionForCurrentTokensLines = currentTextLinesVersion; // Stop perf measurement PerfStatsForScanner.OnStopRefresh(); } // Send events to all listeners EventHandler <DocumentChangedEvent <ITokensLine> > tokensLinesChanged = TokensLinesChanged; // avoid race condition if (documentChangedEvent != null && tokensLinesChanged != null) { tokensLinesChanged(this, documentChangedEvent); } }
/// <summary> /// Update the text lines of the document after a text change event. /// NOT thread-safe : this method can only be called from the owner thread. /// </summary> public void UpdateTextLines(TextChangedEvent textChangedEvent) { // This method can only be called by the document owner thread if (documentOwnerThread == null) { documentOwnerThread = Thread.CurrentThread; } else { VerifyAccess(); } // Make sure we don't update the document while taking a snapshot DocumentChangedEvent <ICobolTextLine> documentChangedEvent = null; lock (lockObjectForDocumentLines) { // Start perf measurement PerfStatsForText.OnStartRefresh(); // Apply text changes to the compilation document IList <DocumentChange <ICobolTextLine> > documentChanges = new List <DocumentChange <ICobolTextLine> >(textChangedEvent.TextChanges.Count); foreach (TextChange textChange in textChangedEvent.TextChanges) { DocumentChange <ICobolTextLine> appliedChange = null; CodeElementsLine newLine = null; bool encounteredCodeElement; switch (textChange.Type) { case TextChangeType.DocumentCleared: compilationDocumentLines.Clear(); appliedChange = new DocumentChange <ICobolTextLine>(DocumentChangeType.DocumentCleared, 0, null); // Ignore all previous document changes : they are meaningless now that the document was completely cleared documentChanges.Clear(); break; case TextChangeType.LineInserted: newLine = CreateNewDocumentLine(textChange.NewLine, TextSourceInfo.ColumnsLayout); compilationDocumentLines.Insert(textChange.LineIndex, newLine); encounteredCodeElement = false; //Will allow to update allow line index without erasing all diagnostics after the first encountered line with CodeElements foreach (var lineToUpdate in compilationDocumentLines.Skip(textChange.LineIndex + 1)) //Loop on every line that appears after added line { //Remove generated diagnostics for the line below the inserted line. if (!encounteredCodeElement) { lineToUpdate.ResetDiagnostics(); //Reset diag when on the same zone } lineToUpdate.LineIndex++; lineToUpdate.UpdateDiagnositcsLine(); if (lineToUpdate.CodeElements != null) { encounteredCodeElement = true; } } appliedChange = new DocumentChange <ICobolTextLine>(DocumentChangeType.LineInserted, textChange.LineIndex, newLine); break; case TextChangeType.LineUpdated: newLine = CreateNewDocumentLine(textChange.NewLine, TextSourceInfo.ColumnsLayout); compilationDocumentLines[textChange.LineIndex] = newLine; // Check to see if this change can be merged with a previous one bool changeAlreadyApplied = false; foreach (DocumentChange <ICobolTextLine> documentChangeToAdjust in documentChanges) { if (documentChangeToAdjust.LineIndex == textChange.LineIndex) { changeAlreadyApplied = true; break; } } if (!changeAlreadyApplied) { appliedChange = new DocumentChange <ICobolTextLine>(DocumentChangeType.LineUpdated, textChange.LineIndex, newLine); } // Line indexes are not impacted break; case TextChangeType.LineRemoved: compilationDocumentLines.RemoveAt(textChange.LineIndex); encounteredCodeElement = false; //Will allow to update allow line index without erasing all diagnostics after the first encountered line with CodeElements foreach (var lineToUpdate in compilationDocumentLines.Skip(textChange.LineIndex)) //Loop on every line that appears after deleted line { //Remove generated diagnostics for the line below the deleted line. if (!encounteredCodeElement) { lineToUpdate.ResetDiagnostics(); } lineToUpdate.LineIndex--; lineToUpdate.UpdateDiagnositcsLine(); if (lineToUpdate.CodeElements != null) { encounteredCodeElement = true; } } appliedChange = new DocumentChange <ICobolTextLine>(DocumentChangeType.LineRemoved, textChange.LineIndex, null); // Recompute the line indexes of all the changes prevously applied IList <DocumentChange <ICobolTextLine> > documentChangesToRemove = null; foreach (DocumentChange <ICobolTextLine> documentChangeToAdjust in documentChanges) { if (documentChangeToAdjust.LineIndex > textChange.LineIndex) { documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex - 1; } else if (documentChangeToAdjust.LineIndex == textChange.LineIndex) { if (documentChangesToRemove == null) { documentChangesToRemove = new List <DocumentChange <ICobolTextLine> >(1); } documentChangesToRemove.Add(documentChangeToAdjust); } } // Ignore all previous changes applied to a line now removed if (documentChangesToRemove != null) { foreach (DocumentChange <ICobolTextLine> documentChangeToRemove in documentChangesToRemove) { documentChanges.Remove(documentChangeToRemove); } } break; } if (appliedChange != null) { documentChanges.Add(appliedChange); } } // Create a new version of the document to track these changes currentTextLinesVersion.changes = documentChanges; currentTextLinesVersion.next = new DocumentVersion <ICobolTextLine>(currentTextLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent <ICobolTextLine>(currentTextLinesVersion, currentTextLinesVersion.next); currentTextLinesVersion = currentTextLinesVersion.next; // Stop perf measurement PerfStatsForText.OnStopRefresh(); } // Send events to all listeners EventHandler <DocumentChangedEvent <ICobolTextLine> > textLinesChanged = TextLinesChanged; // avoid race condition if (textLinesChanged != null) { textLinesChanged(this, documentChangedEvent); } }
void OnDocumentChanged(object sender, DocumentChangedEventArgs e) { var document = e.GetDocument(); var added = e.GetAddedElementIds(); var deleted = e.GetDeletedElementIds(); var modified = e.GetModifiedElementIds(); if (added.Count > 0 || deleted.Count > 0 || modified.Count > 0) { foreach (GH_Document definition in Instances.DocumentServer) { bool expireNow = (e.Operation == UndoOperation.TransactionCommitted || e.Operation == UndoOperation.TransactionUndone || e.Operation == UndoOperation.TransactionRedone) && GH_Document.EnableSolutions && Instances.ActiveCanvas.Document == definition && definition.Enabled && definition.SolutionState != GH_ProcessStep.Process; var change = new DocumentChangedEvent() { Operation = e.Operation, Document = document, Definition = definition }; foreach (var obj in definition.Objects) { if (obj is Parameters.IGH_ElementIdParam persistentParam) { if (persistentParam.DataType == GH_ParamData.remote) { continue; } if (persistentParam.Phase == GH_SolutionPhase.Blank) { continue; } if (persistentParam.NeedsToBeExpired(document, added, deleted, modified)) { if (expireNow) { persistentParam.ExpireSolution(false); } else { change.ExpiredObjects.Add(persistentParam); } } } else if (obj is Components.IGH_ElementIdComponent persistentComponent) { if (persistentComponent.NeedsToBeExpired(e)) { if (expireNow) { persistentComponent.ExpireSolution(false); } else { change.ExpiredObjects.Add(persistentComponent); } } } } if (definition.SolutionState != GH_ProcessStep.Process) { changeQuque.Enqueue(change); } else if (definition == Instances.ActiveCanvas.Document) { if (change.ExpiredObjects.Count > 0) { foreach (var obj in change.ExpiredObjects) { obj.ClearData(); obj.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"This object was expired because it contained obsolete Revit elements."); } Instances.DocumentEditor.SetStatusBarEvent ( new GH_RuntimeMessage ( change.ExpiredObjects.Count == 1 ? $"An object was expired because it contained obsolete Revit elements." : $"{change.ExpiredObjects.Count} objects were expired because them contained obsolete Revit elements.", GH_RuntimeMessageLevel.Remark, "Document" ) ); } } } } }
// --- Handle Scanner and error events --- public void OnNext(DocumentChangedEvent<ITokensLine> tokensLinesChangedEvent) { // Refresh the display of all the lines which were not directly modified // but which were rescanned because of a scanner state change on a previous or following line foreach (var documentChange in tokensLinesChangedEvent.DocumentChanges) { DocumentLine rescannedLine = Document.GetLineByNumber(documentChange.LineIndex); TextArea.TextView.Redraw(rescannedLine.Offset, rescannedLine.Length); } }
/// <summary> /// Creates a new snapshot of the document viewed as CodeElement objects after parsing. /// (if the processed tokens lines changed since the last time this method was called) /// Thread-safe : this method can be called from any thread. /// </summary> public void RefreshCodeElementsDocumentSnapshot() { // Make sure two threads don't try to update this snapshot at the same time lock (lockObjectForCodeElementsDocumentSnapshot) { // Capture previous snapshots at one point in time ProcessedTokensDocument processedTokensDocument = ProcessedTokensDocumentSnapshot; CodeElementsDocument previousCodeElementsDocument = CodeElementsDocumentSnapshot; // Check if an update is necessary and compute changes to apply since last version bool scanAllDocumentLines = false; IList<DocumentChange<IProcessedTokensLine>> processedTokensLineChanges = null; if (previousCodeElementsDocument == null) { scanAllDocumentLines = true; } else if (processedTokensDocument.CurrentVersion == previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion) { // Processed tokens lines did not change since last update => nothing to do return; } else { DocumentVersion<IProcessedTokensLine> previousProcessedTokensDocumentVersion = previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion; processedTokensLineChanges = previousProcessedTokensDocumentVersion.GetReducedAndOrderedChangesInNewerVersion(processedTokensDocument.CurrentVersion); } // Start perf measurement PerfStatsForCodeElementsParser.OnStartRefresh(); // Track all changes applied to the document while updating this snapshot DocumentChangedEvent<ICodeElementsLine> documentChangedEvent = null; // Apply text changes to the compilation document if (scanAllDocumentLines) { // Parse the whole document for the first time CodeElementsParserStep.ParseDocument(TextSourceInfo, ((ImmutableList<CodeElementsLine>)processedTokensDocument.Lines), CompilerOptions); // Create the first code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, new DocumentVersion<ICodeElementsLine>(this), ((ImmutableList<CodeElementsLine>)processedTokensDocument.Lines)); } else { ImmutableList<CodeElementsLine>.Builder codeElementsDocumentLines = ((ImmutableList<CodeElementsLine>)processedTokensDocument.Lines).ToBuilder(); IList<DocumentChange<ICodeElementsLine>> documentChanges = CodeElementsParserStep.ParseProcessedTokensLinesChanges(TextSourceInfo, codeElementsDocumentLines, processedTokensLineChanges, PrepareDocumentLineForUpdate, CompilerOptions); // Create a new version of the document to track these changes DocumentVersion<ICodeElementsLine> currentCodeElementsLinesVersion = previousCodeElementsDocument.CurrentVersion; currentCodeElementsLinesVersion.changes = documentChanges; currentCodeElementsLinesVersion.next = new DocumentVersion<ICodeElementsLine>(currentCodeElementsLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent<ICodeElementsLine>(currentCodeElementsLinesVersion, currentCodeElementsLinesVersion.next); currentCodeElementsLinesVersion = currentCodeElementsLinesVersion.next; // Update the code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, currentCodeElementsLinesVersion, codeElementsDocumentLines.ToImmutable()); } // Stop perf measurement PerfStatsForCodeElementsParser.OnStopRefresh(); // Send events to all listeners EventHandler<DocumentChangedEvent<ICodeElementsLine>> codeElementsLinesChanged = CodeElementsLinesChanged; // avoid race condition if (documentChangedEvent != null && codeElementsLinesChanged != null) { codeElementsLinesChanged(this, documentChangedEvent); } } }
/// <summary> /// Update the tokens lines of the document if the text lines changed since the last time this method was called. /// NOT thread-safe : this method can only be called from the owner thread. /// </summary> public void UpdateTokensLines() { // This method can only be called by the document owner thread if (documentOwnerThread == null) { documentOwnerThread = Thread.CurrentThread; } else { VerifyAccess(); } // Check if an update is necessary and compute changes to apply since last version bool scanAllDocumentLines = false; IList<DocumentChange<ICobolTextLine>> textLineChanges = null; if(textLinesVersionForCurrentTokensLines == null) { scanAllDocumentLines = true; } else if(currentTextLinesVersion == textLinesVersionForCurrentTokensLines) { // Text lines did not change since last update => nothing to do return; } else { textLineChanges = textLinesVersionForCurrentTokensLines.GetReducedAndOrderedChangesInNewerVersion(currentTextLinesVersion); } // Make sure we don't update the document while taking a snapshot DocumentChangedEvent<ITokensLine> documentChangedEvent = null; lock (lockObjectForDocumentLines) { // Start perf measurement PerfStatsForScanner.OnStartRefresh(); // Apply text changes to the compilation document if (scanAllDocumentLines) { ScannerStep.ScanDocument(TextSourceInfo, compilationDocumentLines, CompilerOptions); } else { IList<DocumentChange<ITokensLine>> documentChanges = ScannerStep.ScanTextLinesChanges(TextSourceInfo, compilationDocumentLines, textLineChanges, PrepareDocumentLineForUpdate, CompilerOptions); // Create a new version of the document to track these changes currentTokensLinesVersion.changes = documentChanges; currentTokensLinesVersion.next = new DocumentVersion<ITokensLine>(currentTokensLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent<ITokensLine>(currentTokensLinesVersion, currentTokensLinesVersion.next); currentTokensLinesVersion = currentTokensLinesVersion.next; } // Register that the tokens lines were synchronized with the current text lines version textLinesVersionForCurrentTokensLines = currentTextLinesVersion; // Stop perf measurement PerfStatsForScanner.OnStopRefresh(); } // Send events to all listeners EventHandler<DocumentChangedEvent<ITokensLine>> tokensLinesChanged = TokensLinesChanged; // avoid race condition if (documentChangedEvent != null && tokensLinesChanged != null) { tokensLinesChanged(this, documentChangedEvent); } }
/// <summary> /// Update the text lines of the document after a text change event. /// NOT thread-safe : this method can only be called from the owner thread. /// </summary> public void UpdateTextLines(TextChangedEvent textChangedEvent) { // This method can only be called by the document owner thread if (documentOwnerThread == null) { documentOwnerThread = Thread.CurrentThread; } else { VerifyAccess(); } // Make sure we don't update the document while taking a snapshot DocumentChangedEvent<ICobolTextLine> documentChangedEvent = null; lock (lockObjectForDocumentLines) { // Start perf measurement PerfStatsForText.OnStartRefresh(); // Apply text changes to the compilation document IList<DocumentChange<ICobolTextLine>> documentChanges = new List<DocumentChange<ICobolTextLine>>(textChangedEvent.TextChanges.Count); foreach (TextChange textChange in textChangedEvent.TextChanges) { DocumentChange<ICobolTextLine> appliedChange = null; CodeElementsLine newLine = null; switch (textChange.Type) { case TextChangeType.DocumentCleared: compilationDocumentLines.Clear(); appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.DocumentCleared, 0, null); // Ignore all previous document changes : they are meaningless now that the document was completely cleared documentChanges.Clear(); break; case TextChangeType.LineInserted: newLine = CreateNewDocumentLine(textChange.NewLine, TextSourceInfo.ColumnsLayout); compilationDocumentLines.Insert(textChange.LineIndex, newLine); appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.LineInserted, textChange.LineIndex, newLine); // Recompute the line indexes of all the changes prevously applied foreach (DocumentChange<ICobolTextLine> documentChangeToAdjust in documentChanges) { if(documentChangeToAdjust.LineIndex >= textChange.LineIndex) { documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex + 1; } } break; case TextChangeType.LineUpdated: newLine = CreateNewDocumentLine(textChange.NewLine, TextSourceInfo.ColumnsLayout); compilationDocumentLines[textChange.LineIndex] = newLine; // Check to see if this change can be merged with a previous one bool changeAlreadyApplied = false; foreach (DocumentChange<ICobolTextLine> documentChangeToAdjust in documentChanges) { if (documentChangeToAdjust.LineIndex == textChange.LineIndex) { changeAlreadyApplied = true; break; } } if (!changeAlreadyApplied) { appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.LineUpdated, textChange.LineIndex, newLine); } // Line indexes are not impacted break; case TextChangeType.LineRemoved: compilationDocumentLines.RemoveAt(textChange.LineIndex); appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.LineRemoved, textChange.LineIndex, null); // Recompute the line indexes of all the changes prevously applied IList<DocumentChange<ICobolTextLine>> documentChangesToRemove = null; foreach (DocumentChange<ICobolTextLine> documentChangeToAdjust in documentChanges) { if (documentChangeToAdjust.LineIndex > textChange.LineIndex) { documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex - 1; } else if(documentChangeToAdjust.LineIndex == textChange.LineIndex) { if(documentChangesToRemove == null) { documentChangesToRemove = new List<DocumentChange<ICobolTextLine>>(1); } documentChangesToRemove.Add(documentChangeToAdjust); } } // Ignore all previous changes applied to a line now removed if(documentChangesToRemove != null) { foreach (DocumentChange<ICobolTextLine> documentChangeToRemove in documentChangesToRemove) { documentChanges.Remove(documentChangeToRemove); } } break; } if (appliedChange != null) { documentChanges.Add(appliedChange); } } // Create a new version of the document to track these changes currentTextLinesVersion.changes = documentChanges; currentTextLinesVersion.next = new DocumentVersion<ICobolTextLine>(currentTextLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent<ICobolTextLine>(currentTextLinesVersion, currentTextLinesVersion.next); currentTextLinesVersion = currentTextLinesVersion.next; // Stop perf measurement PerfStatsForText.OnStopRefresh(); } // Send events to all listeners EventHandler<DocumentChangedEvent<ICobolTextLine>> textLinesChanged = TextLinesChanged; // avoid race condition if (textLinesChanged != null) { textLinesChanged(this, documentChangedEvent); } }