qamp/Qrakhen.Qamp.Editor/Controls/EditorFrame.xaml.cs

123 lines
3.6 KiB
C#

using Qrakhen.Qamp.Editor.Primitives;
using Qrakhen.Qamp.Editor.ViewModel;
using Qrakhen.Qamp.Memory;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace Qrakhen.Qamp.Editor.Controls;
public partial class EditorFrame : UserControl
{
public Caret Caret { get; private set; }
public EditorFrame()
{
InitializeComponent();
Loaded += OnLoaded;
PreviewKeyDown += OnKeyDown;
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (DataContext is EditorFrameViewModel vm) {
BufferPosition position = e.Key switch {
Key.Right => new(0, 1),
Key.Left => new(0, -1),
Key.Up => new(-1, 0),
Key.Down => new(1, 0),
_ => new(0, 0)
};
if (position != BufferPosition.Void)
vm.MoveCaretCommand.Execute(position);
else if (e.Key == Key.Back)
vm.DeleteCommand.Execute(-1);
else if (e.Key == Key.Delete)
vm.DeleteCommand.Execute(1);
else if (e.Key == Key.Enter)
vm.InsertCommand.Execute(Environment.NewLine);
else if (e.Key == Key.Delete)
vm.DeleteCommand.Execute(1);
else {
string c = e.Key.ToString();
if (c.Length == 1)
vm.InsertCommand.Execute(c);
}
e.Handled = true;
}
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Focus();
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
if (adornerLayer != null) {
Caret = new Caret(this, Brushes.LimeGreen);
adornerLayer.Add(Caret);
} else {
System.Diagnostics.Debug.WriteLine("AdornerLayer still null. Check parent hierarchy.");
}
Loaded -= OnLoaded;
}
private Point CalculateCaretPosition(int line, int index, double scrollY, double scrollX)
{
var ft = TextHelper.GetText(new string('_', index), 14, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
return new Point(ft.Width + scrollX + 2, line * TextHelper.LineHeight + scrollY);
}
private void MoveCaret(Point point)
{
Caret?.UpdatePosition(point);
}
private void UpdateCaret()
{
int line = CursorPosition.Line;
int charIndex = CursorPosition.Column;
double scrollY = ScrollView.VerticalOffset;
double scrollX = ScrollView.HorizontalOffset;
MoveCaret(
CalculateCaretPosition(
line,
charIndex,
scrollY,
scrollX));
}
public LineBuffer CurrentLineBuffer {
get => (LineBuffer)GetValue(CurrentLineBufferProperty);
set => SetValue(CurrentLineBufferProperty, value);
}
public static readonly DependencyProperty CurrentLineBufferProperty =
DependencyProperty.Register(
nameof(CurrentLineBuffer),
typeof(LineBuffer),
typeof(EditorFrame),
new PropertyMetadata(null));
public BufferPosition CursorPosition {
get => (BufferPosition)GetValue(CursorPositionProperty);
set => SetValue(CursorPositionProperty, value);
}
public static readonly DependencyProperty CursorPositionProperty =
DependencyProperty.Register(
nameof(CursorPosition),
typeof(BufferPosition),
typeof(EditorFrame),
new PropertyMetadata(BufferPosition.Void, OnCursorPositionChanged));
private static void OnCursorPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var frame = (EditorFrame)d;
frame.UpdateCaret();
}
}