Skip to content

Commit

Permalink
support a contextmenu in AvaloniaEdit
Browse files Browse the repository at this point in the history
  • Loading branch information
whistyun committed Apr 27, 2023
1 parent 9c2f522 commit 84d4291
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 0 deletions.
3 changes: 3 additions & 0 deletions MdXaml/Markdown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using System.IO;
using System.Threading.Tasks;
using System.Windows.Threading;
using MdXaml.Menus;

// I will not add System.Index and System.Range. There is not exist with net45.
#pragma warning disable IDE0056
Expand Down Expand Up @@ -1492,6 +1493,8 @@ private Block CodeBlocksEvaluator(string? lang, string code)


var result = new BlockUIContainer(txtEdit);
CommandsForTextEditor.Setup(txtEdit);

if (CodeBlockStyle is not null)
{
result.Style = CodeBlockStyle;
Expand Down
7 changes: 7 additions & 0 deletions MdXaml/MarkdownScrollViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,13 @@ public MarkdownScrollViewer()
_engine.DocumentStyle = MarkdownStyle;

UpdateClickAction();


var menu = new ContextMenu();
menu.Items.Add(ApplicationCommands.Copy);
menu.Items.Add(ApplicationCommands.SelectAll);

ContextMenu = menu;
}

private void UpdateClickAction()
Expand Down
92 changes: 92 additions & 0 deletions MdXaml/Menus/CommandsForTextEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using ICSharpCode.AvalonEdit;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace MdXaml.Menus
{
public static class CommandsForTextEditor
{

public static void Setup(TextEditor editor)
{
editor.ContextMenuOpening += Editor_ContextMenuOpening;

var menu = new ContextMenu();
menu.Items.Add(new MenuItem()
{
Name = ApplicationCommands.Copy.Name,
Header = ApplicationCommands.Copy.Text,
InputGestureText = ExtractShortcut(ApplicationCommands.Copy.InputGestures),
Command = new TextEditorCopyCommand(editor)
});
menu.Items.Add(new MenuItem()
{
Name = ApplicationCommands.SelectAll.Name,
Header = ApplicationCommands.SelectAll.Text,
InputGestureText = ExtractShortcut(ApplicationCommands.SelectAll.InputGestures),
Command = new TextEditorSelectAllCommand(editor)
});

editor.ContextMenu = menu;

}

private static void Editor_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
if (sender is TextEditor editor)
{
var viewer = WalkParent<FlowDocumentScrollViewer>(editor);

if (viewer is null)
return;

if (viewer.Selection is not null
&& !viewer.Selection.IsEmpty)
{
viewer.IsSelectionEnabled = false;
viewer.IsSelectionEnabled = true;
}
}
}

private static T? WalkParent<T>(FrameworkElement start)
where T : class
{
DependencyObject dobj = start.Parent;
for (; ; )
{
if (dobj is T t)
{
return t;
}
else if (dobj is FrameworkElement element)
{
dobj = element.Parent;
}
else if (dobj is FrameworkContentElement content)
{
dobj = content.Parent;
}
else return null;
}
}

private static string? ExtractShortcut(InputGestureCollection? collection)
{
if (collection is null)
return "";

return collection.OfType<KeyGesture>()
.Select(g => g.GetDisplayStringForCulture(CultureInfo.CurrentCulture))
.FirstOrDefault()
?? "";
}
}
}
42 changes: 42 additions & 0 deletions MdXaml/Menus/TextEditorCopyCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using ICSharpCode.AvalonEdit;
using System;
using System.Windows.Controls;
using System.Windows.Input;

namespace MdXaml.Menus
{
public class TextEditorCopyCommand : ICommand
{
public event EventHandler? CanExecuteChanged;

private TextEditor _editor;
private bool _isExecutable;

public TextEditorCopyCommand(TextEditor editor)
{
_editor = editor;
_editor.ContextMenuOpening += TryUpdateExecutable;
}

private void TryUpdateExecutable(object sender, ContextMenuEventArgs e)
{
var isExecutable = _editor.SelectionLength != 0;

if (_isExecutable != isExecutable)
{
_isExecutable = isExecutable;
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

public bool CanExecute(object parameter)
{
return _isExecutable;
}

public void Execute(object parameter)
{
_editor.Copy();
}
}
}
32 changes: 32 additions & 0 deletions MdXaml/Menus/TextEditorSelectAllCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using ICSharpCode.AvalonEdit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MdXaml.Menus
{
public class TextEditorSelectAllCommand : ICommand
{
public event EventHandler? CanExecuteChanged;

private TextEditor _editor;

public TextEditorSelectAllCommand(TextEditor editor)
{
_editor = editor;
}

public bool CanExecute(object parameter)
{
return true;
}

public void Execute(object parameter)
{
_editor.SelectAll();
}
}
}

1 comment on commit 84d4291

@whistyun
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refs #59

Please sign in to comment.