/// <summary> /// Inserts the lines. /// </summary> /// <param name="project">The project.</param> /// <param name="lineCount">The line count.</param> private void InsertLines( Project project, int lineCount) { // Pull out some useful variables. ProjectBlockCollection blocks = project.Blocks; // Modify the first line, which is always there. using (blocks[0].AcquireBlockLock(RequestLock.Write)) { blocks[0].SetText("Line 1"); } // Add in the additional lines after the first one. for (int i = 1; i < lineCount; i++) { var block = new Block(blocks); using (block.AcquireBlockLock(RequestLock.Write)) { block.SetText("Line " + (i + 1)); } blocks.Add(block); } }
public void AnalyzeBlock( Block block, int blockVersion) { // Grab the information about the block. string text; var originalMispelledWords = new TextSpanCollection(); using (block.AcquireBlockLock(RequestLock.Read)) { // If we are stale, then break out. if (block.IsStale(blockVersion)) { return; } // Grab the information from the block. We need the text and // alow the current spelling areas. text = block.Text; originalMispelledWords.AddRange( block.TextSpans.Where(span => span.Controller == this)); } // Split the word and perform spell-checking. var misspelledWords = new List<TextSpan>(); IList<TextSpan> words = Splitter.SplitAndNormalize(text); IEnumerable<TextSpan> misspelledSpans = words.Where(span => !IsCorrect(span.GetText(text))); foreach (TextSpan span in misspelledSpans) { // We aren't correct, so add it to the list. span.Controller = this; misspelledWords.Add(span); } // Look to see if we have any change from the original spelling // errors and this one. This will only happen if the count is // identical and every one in the original list is in the new list. if (originalMispelledWords.Count == misspelledWords.Count) { bool isMatch = originalMispelledWords.All(misspelledWords.Contains); if (isMatch) { // There are no new changes, so we don't have anything to // update. return; } } // Inside a write lock, we need to make modifications to the block's list. using (block.AcquireBlockLock(RequestLock.Write)) { // Check one last time to see if the block is stale. if (block.IsStale(blockVersion)) { return; } // Make the changes to the block's contents. block.TextSpans.Remove(this); block.TextSpans.AddRange(misspelledWords); // Raise that we changed the spelling on the block. block.RaiseTextSpansChanged(); } }
/// <summary> /// Processes any block analysis on the given block. /// </summary> /// <param name="block">The block.</param> public async void ProcessBlockAnalysis(Block block) { // If we don't have any analysis controllers, we don't have to do anything. if (BlockAnalyzers.Count == 0) { return; } // Keep track of the running tasks so we can wait for them to finish // (if needed). Interlocked.Increment(ref tasksRunning); try { // Grab information about the block inside a read lock. int blockVersion; HashSet<IBlockAnalyzerProjectPlugin> analysis; using (block.AcquireBlockLock(RequestLock.Read)) { blockVersion = block.Version; analysis = block.GetAnalysis(); } // Create a background task that will analyze the block. This will return // false if the block had changed in the process of analysis (which would // have triggered another background task). var analyzer = new BlockAnalyzer( block, blockVersion, BlockAnalyzers, analysis); Task task = Task.Factory.StartNew(analyzer.Run); // Wait for the task to complete in the background so we can then // decrement our running counter. await task; } finally { // Decrement the counter to keep track of running tasks. Interlocked.Decrement(ref tasksRunning); } }
/// <summary> /// Analyzes the block and counts the word. Once counted, this updates /// the block and all parent blocks with the altered change. /// </summary> /// <param name="block">The block.</param> /// <param name="blockVersion">The block version of the initial request.</param> public void AnalyzeBlock( Block block, int blockVersion) { // Grab counts from the current block text. int newCount = 1; int newWordCount; int newCharacterCount; int newNonWhitespaceCount; string text = block.Text; WordCounter.CountWords( text, out newWordCount, out newCharacterCount, out newNonWhitespaceCount); // Grab the existing counts from the current block, if we have one. int oldCount; int oldWordCount; int oldCharacterCount; int oldNonWhitespaceCount; WordCounterPathUtility.GetCounts( this, block, out oldCount, out oldWordCount, out oldCharacterCount, out oldNonWhitespaceCount); // Calculate the deltas between the values. int delta = newCount - oldCount; int wordDelta = newWordCount - oldWordCount; int characterDelta = newCharacterCount - oldCharacterCount; int nonWhitespaceDelta = newNonWhitespaceCount - oldNonWhitespaceCount; // Build up a dictionary of changes so we can have a simple loop to // set them in the various elements. Dictionary<HierarchicalPath, int> deltas = WordCounterPathUtility.GetDeltas( this, block, delta, wordDelta, characterDelta, nonWhitespaceDelta); // Get a write lock on the blocks list and update that block and all // parent blocks in the document. using (block.AcquireBlockLock(RequestLock.Write)) { // Log that we are analyzing this block. Log("BEGIN AnalyzeBlock: {0}: Words {1:N0}", block, newWordCount); // First check to see if we've gotten stale. if (block.IsStale(blockVersion)) { return; } // Update the block and the document. UpdateDeltas(block, deltas); UpdateDeltas(block.Project, deltas); // Log that we finished processing this block. Log("END AnalyzeBlock: {0}: Words {1:N0}", block, newWordCount); } }
public void ChangeBlockType( Block block, BlockType oldBlockType) { // We need a write lock on the blocks while we make this change. using (block.AcquireBlockLock(RequestLock.Write)) { // Report what we're doing if we have logging on. Log("ChangeBlockType: {0}: Old Type {1}", block, oldBlockType); //// Figure out the deltas for this block. //var deltas = new Dictionary<HierarchicalPath, int>(); //deltas[WordCounterPathUtility.GetPath(oldBlockType)] = -1; //deltas[WordCounterPathUtility.GetPath(block.BlockType)] = 1; //// Update the parent types. //UpdateDeltas(block, deltas); //UpdateDeltas(block.Project, deltas); } }
public void Do(BlockCommandContext context) { // We have to clear the undo buffer every time because we'll be creating // new blocks. addedBlocks.Clear(); // Start by breaking apart the lines on the newline. string[] lines = Text.Split('\n'); // Make changes to the first line by creating a command, adding it to the // list of commands we need an inverse for, and then performing it. Block block = context.Blocks[BlockPosition.BlockKey]; string remainingText = block.Text.Substring((int) BlockPosition.TextIndex); deleteFirstCommand = new DeleteTextCommand(BlockPosition, block.Text.Length); insertFirstCommand = new InsertTextCommand(BlockPosition, lines[0]); deleteFirstCommand.Do(context); insertFirstCommand.Do(context); // Update the final lines text with the remains of the first line. int lastLineLength = lines[lines.Length - 1].Length; lines[lines.Length - 1] += remainingText; // For the remaining lines, we need to insert each one in turn. if (UpdateTextPosition.HasFlag(DoTypes.Do)) { context.Position = BlockPosition.Empty; } if (lines.Length > 1) { // Go through all the lines in reverse order to insert them. int firstBlockIndex = context.Blocks.IndexOf(block); for (int i = lines.Length - 1; i > 0; i--) { // Insert the line and set its text value. var newBlock = new Block(context.Blocks); addedBlocks.Add(newBlock); using (newBlock.AcquireBlockLock(RequestLock.Write)) { newBlock.SetText(lines[i]); } context.Blocks.Insert(firstBlockIndex + 1, newBlock); // Update the last position as we go. if (context.Position == BlockPosition.Empty) { if (UpdateTextPosition.HasFlag(DoTypes.Do)) { context.Position = new BlockPosition( newBlock.BlockKey, (CharacterPosition) lastLineLength); } } } } }