示例#1
0
        public void TestUndoRedoCommand()
        {
            // Arrange
            var project = new Project();
            var context = new BlockCommandContext(project);
            ProjectBlockCollection blocks = project.Blocks;
            Block block = blocks[0];

            using (block.AcquireBlockLock(RequestLock.Write))
            {
                block.SetText("abcd");
            }
            int      blockVersion = block.Version;
            BlockKey blockKey     = block.BlockKey;

            var command = new ReplaceTextCommand(
                new BlockPosition(blockKey, 2), 1, "YES");

            project.Commands.Do(command, context);
            project.Commands.Undo(context);

            // Act
            project.Commands.Redo(context);

            // Assert
            Assert.AreEqual(1, blocks.Count);
            Assert.AreEqual(
                new BlockPosition(blocks[0], 5), project.Commands.LastPosition);

            const int index = 0;

            Assert.AreEqual("abYESd", blocks[index].Text);
            Assert.AreEqual(blockVersion + 6, blocks[index].Version);
        }
        /// <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);
            }
        }
示例#3
0
        public void TestUndoRedoCommand()
        {
            // Arrange
            var project = new Project();
            var context = new BlockCommandContext(project);
            ProjectBlockCollection blocks = project.Blocks;
            Block block = blocks[0];

            using (block.AcquireBlockLock(RequestLock.Write))
            {
                block.SetText("Testing 123");
            }
            BlockKey blockKey = block.BlockKey;

            var command = new InsertAfterBlockCommand(blockKey, 1);

            project.Commands.Do(command, context);
            project.Commands.Undo(context);

            // Act
            project.Commands.Redo(context);

            // Assert
            Assert.AreEqual(2, blocks.Count);
            Assert.AreEqual(
                new BlockPosition(blocks[1], 0), project.Commands.LastPosition);

            int index = 0;

            Assert.AreEqual("Testing 123", blocks[index].Text);

            index++;
            Assert.AreEqual("", blocks[index].Text);
        }
        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);
            }
        }
示例#5
0
        /// <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);
            }
        }
        public void WriteRead()
        {
            // Arrange: Cleanup any existing output file.
            DirectoryInfo testDirectory = PrepareTestDirectory();

            // Arrange: Set up the plugin.
            ProjectBlockCollection             blocks;
            BlockCommandSupervisor             commands;
            PluginSupervisor                   plugins;
            FilesystemPersistenceProjectPlugin projectPlugin;

            SetupPlugin(out blocks, out commands, out plugins, out projectPlugin);

            PersistenceManager persistenceManager = PersistenceManager.Instance;

            // Arrange: Create a project with some interesting data and write it out.
            SetupComplexMultilineTest(blocks.Project, 10);
            blocks.Project.BlockTypes.Add("Custom Type", false);
            Block block = blocks[0];

            block.Properties[new HierarchicalPath("/Test")] = "Custom Property";
            block.TextSpans.Add(new TextSpan(1, 3, null, null));
            using (block.AcquireBlockLock(RequestLock.Write))
            {
                block.SetText("Incor Wurd Onz");
            }
            plugins.WaitForBlockAnalzyers();
            projectPlugin.Settings.SetIndividualDirectoryLayout();
            projectPlugin.Save(testDirectory);

            // Act
            var projectFile =
                new FileInfo(Path.Combine(testDirectory.FullName, "Project.aiproj"));
            Project project = persistenceManager.ReadProject(projectFile);

            // Assert: Block Types
            block = project.Blocks[0];

            BlockTypeSupervisor blockTypes = project.BlockTypes;

            blocks = project.Blocks;

            Assert.AreEqual(2, project.Plugins.Controllers.Count);
            Assert.NotNull(blockTypes["Custom Type"]);
            Assert.IsFalse(blockTypes["Custom Type"].IsStructural);

            // Assert: Blocks
            Assert.AreEqual(10, blocks.Count);

            Assert.AreEqual(blockTypes.Chapter, block.BlockType);
            Assert.AreEqual("Incor Wurd Onz", block.Text);

            Assert.AreEqual(blockTypes.Scene, blocks[1].BlockType);
            Assert.AreEqual("Line 2", blocks[1].Text);

            Assert.AreEqual(blockTypes.Epigraph, blocks[2].BlockType);
            Assert.AreEqual("Line 3", blocks[2].Text);

            Assert.AreEqual(blockTypes.EpigraphAttribution, blocks[3].BlockType);
            Assert.AreEqual("Line 4", blocks[3].Text);

            Assert.AreEqual(blockTypes.Paragraph, blocks[9].BlockType);
            Assert.AreEqual("Line 10", blocks[9].Text);

            // Assert: Verify content data.
            Assert.AreEqual(1, block.Properties.Count);
            Assert.AreEqual(
                "Custom Property", block.Properties[new HierarchicalPath("/Test")]);

            // Assert: Verify text spans.
            Assert.AreEqual(1, block.TextSpans.Count);

            Assert.AreEqual(1, block.TextSpans[0].StartTextIndex);
            Assert.AreEqual(3, block.TextSpans[0].StopTextIndex);
            Assert.IsNull(block.TextSpans[0].Controller);
            Assert.IsNull(block.TextSpans[0].Data);
        }
        /// <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 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);
                        }
                    }
                }
            }
        }
示例#9
0
        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();
            }
        }