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); }
private void PerformCommandAction( OperationContext context, Action <BlockCommandContext> action) { // Every command needs a full write lock on the blocks. using (Project.Blocks.AcquireLock(RequestLock.Write)) { // Create the context for the block commands. var blockContext = new BlockCommandContext(Project); // Execute the internal command. action(blockContext); // Set the operation context from the block context. if (blockContext.Position.HasValue) { // Grab the block position and figure out the index. BlockPosition blockPosition = blockContext.Position.Value; int blockIndex = Project.Blocks.IndexOf(blockPosition.BlockKey); var position = new TextPosition(blockIndex, (int)blockPosition.TextIndex); // Set the context results. context.Results = new LineBufferOperationResults(position); } } }
/// <summary> /// Configures the environment to load the plugin manager and verify we /// have access to the ImmediateCorrectionPlugin. /// </summary> private void SetupCorrectionPlugin( out BlockCommandContext context, out ProjectBlockCollection blocks, out BlockCommandSupervisor commands, out ImmediateCorrectionProjectPlugin projectPlugin) { // Start getting us a simple plugin manager. var plugin = new ImmediateCorrectionPlugin(); var pluginManager = new PluginManager(plugin); PluginManager.Instance = pluginManager; // Create a project and pull out the useful properties we'll use to // make changes. var project = new Project(); context = new BlockCommandContext(project); blocks = project.Blocks; commands = project.Commands; // Load in the immediate correction editor. if (!project.Plugins.Add("Immediate Correction")) { // We couldn't load it for some reason. throw new ApplicationException("Cannot load immediate correction plugin"); } // Pull out the controller for the correction and cast it (since we know // what type it is). ProjectPluginController pluginController = project.Plugins.Controllers[0]; projectPlugin = (ImmediateCorrectionProjectPlugin)pluginController.ProjectPlugin; }
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 TestUndoRedoCommand() { // Arrange var project = new Project(); var context = new BlockCommandContext(project); ProjectBlockCollection blocks = project.Blocks; Block block = blocks[0]; int blockVersion = block.Version; BlockKey blockKey = block.BlockKey; var command = new SetTextCommand(blockKey, "Testing 123"); 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], "Testing 123".Length), project.Commands.LastPosition); const int index = 0; Assert.AreEqual("Testing 123", blocks[index].Text); Assert.AreEqual(blockVersion + 3, blocks[index].Version); }
/// <summary> /// Creates a project with a set number of lines and gives them a state that /// can easily be tested for. /// </summary> /// <param name="context"></param> /// <param name="blocks">The block collection in the project.</param> /// <param name="blockTypes">The block types supervisor for the project.</param> /// <param name="commands">The commands supervisor for the project.</param> /// <param name="lineCount">The number of blocks to insert into the projects.</param> protected void SetupMultilineTest( out BlockCommandContext context, out ProjectBlockCollection blocks, out BlockTypeSupervisor blockTypes, out BlockCommandSupervisor commands, int lineCount = 4) { // Everything is based on the project. var project = new Project(); context = new BlockCommandContext(project); blocks = project.Blocks; commands = project.Commands; blockTypes = project.BlockTypes; // Insert the bulk of the lines. InsertLines(project, lineCount); // Go through and set up the block types for these elements. project.Blocks[0].SetBlockType(blockTypes.Chapter); for (int index = 1; index < project.Blocks.Count; index++) { project.Blocks[index].SetBlockType(blockTypes.Scene); } }
public ICommand <OperationContext> Undo(OperationContext context) { // Every command needs a full write lock on the blocks. using (Project.Blocks.AcquireLock(RequestLock.Write)) { // Create the context for the block commands. var blockContext = new BlockCommandContext(Project); // Execute the internal command. ICommand <BlockCommandContext> command = Commands.Undo(blockContext); // Set the operation context from the block context. if (blockContext.Position.HasValue) { // Grab the block position and figure out the index. BlockPosition blockPosition = blockContext.Position.Value; int blockIndex = Project.Blocks.IndexOf(blockPosition.BlockKey); var position = new TextPosition(blockIndex, (int)blockPosition.TextIndex); // Set the context results. context.Results = new LineBufferOperationResults(position); } // See if we have a wrapped command, then do the post do. var wrapped = command as IWrappedCommand; if (wrapped != null) { wrapped.PostUndo(context); } } return(null); }
/// <summary> /// Checks for immediate edits on a block. This is intended to be a blocking /// editing that will always happen within a write lock. /// </summary> /// <param name="context">The context of the edit just performed.</param> /// <param name="block">The block associated with the current changes.</param> /// <param name="textIndex">Index of the text inside the block.</param> public void ProcessImmediateEdits( BlockCommandContext context, Block block, int textIndex) { foreach ( IImmediateEditorProjectPlugin immediateBlockEditor in ImmediateEditors) { immediateBlockEditor.ProcessImmediateEdits(context, block, textIndex); } }
private void AddToInsensitiveList( BlockCommandContext context, string word) { // Update the internal dictionaries. CaseInsensitiveDictionary.Add(word.ToLowerInvariant()); // Clear the spell-checking on the entire document and reparse it. Project.Plugins.ClearAnalysis(BlockAnalyzer); Project.Plugins.ProcessBlockAnalysis(); // Make sure the settings are written out. WriteSettings(); }
public override LineBufferOperationResults DeleteLines( int lineIndex, int count) { using (project.Blocks.AcquireLock(RequestLock.Write)) { Block block = project.Blocks[lineIndex]; var command = new DeleteBlockCommand(block.BlockKey); var context = new BlockCommandContext(project); project.Commands.Do(command, context); return(GetOperationResults()); } }
public override LineBufferOperationResults InsertText( int lineIndex, int characterIndex, string text) { using (project.Blocks.AcquireLock(RequestLock.Write)) { Block block = project.Blocks[lineIndex]; var position = new BlockPosition(block.BlockKey, characterIndex); var command = new InsertTextCommand(position, text); var context = new BlockCommandContext(project); project.Commands.Do(command, context); return(GetOperationResults()); } }
public void ProcessImmediateEdits( BlockCommandContext context, Block block, int textIndex) { // Get the plugin settings from the project. ImmediateBlockTypesSettings settings = Settings; // Grab the substring from the beginning to the index and compare that // in the dictionary. string text = block.Text.Substring(0, textIndex); if (!settings.Replacements.ContainsKey(text)) { // We want to fail as fast as possible. return; } // If the block type is already set to the same name, skip it. string blockTypeName = settings.Replacements[text]; BlockType blockType = Project.BlockTypes[blockTypeName]; if (block.BlockType == blockType) { return; } // Perform the substitution with a replace operation and a block change // operation. var replaceCommand = new ReplaceTextCommand( new BlockPosition(block.BlockKey, 0), textIndex, string.Empty); var changeCommand = new ChangeBlockTypeCommand(block.BlockKey, blockType); // Create a composite command that binds everything together. var compositeCommand = new CompositeCommand <BlockCommandContext>(true, false); compositeCommand.Commands.Add(replaceCommand); compositeCommand.Commands.Add(changeCommand); // Add the command to the deferred execution so the command could // be properly handled via the undo/redo management. block.Project.Commands.DeferDo(compositeCommand); }
/// <summary> /// Configures the environment to load the plugin manager and verify we /// have access to our plugin and projectPlugin. /// </summary> private void SetupPlugin( out BlockCommandContext context, out ProjectBlockCollection blocks, out BlockCommandSupervisor commands, out PluginSupervisor plugins, out SpellEngineSpellingProjectPlugin projectPlugin) { // Start getting us a simple plugin manager. var spelling = new SpellingFrameworkPlugin(); var nhunspell = new HunspellSpellingPlugin(); var pluginManager = new PluginManager(spelling, nhunspell); PluginManager.Instance = pluginManager; // Create a project and pull out the useful properties we'll use to // make changes. var project = new Project(); context = new BlockCommandContext(project); blocks = project.Blocks; commands = project.Commands; plugins = project.Plugins; // Load in the immediate correction editor. if (!plugins.Add("Spelling Framework")) { // We couldn't load it for some reason. throw new ApplicationException("Cannot load 'Spelling' plugin."); } if (!plugins.Add("NHunspell")) { // We couldn't load it for some reason. throw new ApplicationException("Cannot load 'NHunspell' plugin."); } // Pull out the projectPlugin for the correction and cast it (since we know // what type it is). ProjectPluginController pluginController = plugins.Controllers[1]; projectPlugin = (SpellEngineSpellingProjectPlugin)pluginController.ProjectPlugin; }
public override LineBufferOperationResults InsertLines( int lineIndex, int count) { var composite = new CompositeCommand <BlockCommandContext>(true, false); using (project.Blocks.AcquireLock(RequestLock.Write)) { for (int i = 0; i < count; i++) { var block = new Block(project.Blocks); var command = new InsertIndexedBlockCommand(lineIndex, block); composite.Commands.Add(command); } var context = new BlockCommandContext(project); project.Commands.Do(composite, context); return(GetOperationResults()); } }
public void Do( ICommand <OperationContext> command, OperationContext context) { // Every command needs a full write lock on the blocks. using (Project.Blocks.AcquireLock(RequestLock.Write)) { // Create the context for the block commands. var blockContext = new BlockCommandContext(Project); LinePosition linePosition = context.Position.LinePosition; int lineIndex = linePosition.GetLineIndex(Project.Blocks.Count); Block currentBlock = Project.Blocks[lineIndex]; blockContext.Position = new BlockPosition( currentBlock, context.Position.CharacterPosition); // Wrap the command with our wrappers. IWrappedCommand wrappedCommand = WrapCommand(command, context); Project.Commands.Do(wrappedCommand, blockContext); // Set the operation context from the block context. if (blockContext.Position.HasValue) { // Grab the block position and figure out the index. BlockPosition blockPosition = blockContext.Position.Value; int blockIndex = Project.Blocks.IndexOf(blockPosition.BlockKey); var position = new TextPosition(blockIndex, (int)blockPosition.TextIndex); // Set the context results. context.Results = new LineBufferOperationResults(position); } // Make sure we process our wrapped command. wrappedCommand.PostDo(context); } }
public void ProcessImmediateEdits( BlockCommandContext context, Block block, int textIndex) { // If we aren't optimized, we have to pull the settings back in from the // project settings and optimize them. if (!optimizedSubstitions) { RetrieveSettings(); } // Pull out the edit text and add a leading space to simplify the // "whole word" substitutions. string editText = block.Text.Substring(0, textIndex); if (editText.Length - 1 < 0) { return; } // Figure out if we're at a word break. char finalCharacter = editText[editText.Length - 1]; bool isWordBreak = char.IsPunctuation(finalCharacter) || char.IsWhiteSpace(finalCharacter); // Go through the substitution elements and look for each one. foreach (RegisteredSubstitution substitution in Substitutions) { // If we are doing whole word searches, then we don't bother if // the final character isn't a word break or if it isn't a word // break before it. ReplaceTextCommand command; int searchLength = substitution.Search.Length; int startSearchIndex = editText.Length - searchLength; // If we are going to be searching before the string, then this // search term will never be valid. if (startSearchIndex < 0) { continue; } // Do the search based on the whole word or suffix search. if (substitution.IsWholeWord) { // Check to see if we have a valid search term. if (!isWordBreak) { continue; } if (startSearchIndex > 0 && char.IsPunctuation(editText[startSearchIndex - 1])) { continue; } if (startSearchIndex - 1 < 0) { continue; } // Make sure the string we're looking at actually is the same. string editSubstring = editText.Substring( startSearchIndex - 1, substitution.Search.Length); if (editSubstring != substitution.Search) { // The words don't match. continue; } // Perform the substitution with a replace operation. command = new ReplaceTextCommand( new BlockPosition(block.BlockKey, startSearchIndex - 1), searchLength + 1, substitution.Replacement + finalCharacter); } else { // Perform a straight comparison search. if (!editText.EndsWith(substitution.Search)) { continue; } // Figure out the replace operation. command = new ReplaceTextCommand( new BlockPosition(block.BlockKey, startSearchIndex), searchLength, substitution.Replacement); } // Add the command to the deferred execution so the command could // be properly handled via the undo/redo management. block.Project.Commands.DeferDo(command); } }
/// <summary> /// Called when the context menu is being populated. /// </summary> /// <param name="sender">The sender.</param> /// <param name="args">The event arguments.</param> private void OnPopulateContextMenu( object sender, PopulateContextMenuArgs args) { // Remove the existing items from the list. var menuItems = new HashSet <Widget>(args.Menu.Children); foreach (Widget menuItem in menuItems) { args.Menu.Remove(menuItem); } // We need a read lock on both the collection and the specific block // for the given line index. TextPosition position = editorView.Caret.Position; int blockIndex = position.LinePosition.GetLineIndex(editorView.LineBuffer.LineCount); int characterIndex = position.GetCharacterIndex(editorView.LineBuffer); Block block; var context = new BlockCommandContext(project); using (blocks.AcquireBlockLock(RequestLock.Read, blockIndex, out block)) { // Figure out if we have any spans for this position. if (!block.TextSpans.Contains(characterIndex)) { // Nothing to add, so we can stop processing. return; } // Gather up all the text spans for the current position in the line. var textSpans = new List <TextSpan>(); textSpans.AddRange(block.TextSpans.GetAll(characterIndex)); // Gather up the menu items for this point. bool firstItem = true; foreach (TextSpan textSpan in textSpans) { IList <IEditorAction> actions = textSpan.Controller.GetEditorActions( block, textSpan); foreach (IEditorAction action in actions) { // Create a menu item and hook up events. IEditorAction doAction = action; var menuItem = new MenuItem(action.DisplayName); menuItem.Activated += delegate { doAction.Do(context); RaiseLineChanged(new LineChangedArgs(blockIndex)); }; // If this is the first item, then make the initial // selection to avoid scrolling. if (firstItem) { menuItem.Select(); } firstItem = false; // Add the item to the popup menu. args.Menu.Add(menuItem); } } } }
public void Do(BlockCommandContext context) { command.Do(context); }
public void Redo(BlockCommandContext context) { command.Redo(context); }
public void Do(BlockCommandContext context) { Action(context); }
public void Undo(BlockCommandContext context) { command.Undo(context); }