/// <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); } } } }