stoff
This commit is contained in:
parent
e2022ef80e
commit
b3385c0860
|
|
@ -7,26 +7,28 @@ namespace Qrakhen.Qamp.Editor.Controls;
|
||||||
|
|
||||||
public class Caret : Adorner
|
public class Caret : Adorner
|
||||||
{
|
{
|
||||||
private readonly Pen _pen;
|
private readonly Pen _pen;
|
||||||
private readonly double _height;
|
private readonly double _height;
|
||||||
private readonly Brush _brush;
|
private readonly Brush _brush;
|
||||||
private bool _blink;
|
private bool _blink;
|
||||||
private Point _cursorPosition;
|
private bool _enabled;
|
||||||
private Point _targetPosition;
|
private Point _cursorPosition;
|
||||||
|
private Point _targetPosition;
|
||||||
private (Point from, Point to)[] _lines = [];
|
private (Point from, Point to)[] _lines = [];
|
||||||
private DispatcherTimer _blinkTimer;
|
private DispatcherTimer _blinkTimer;
|
||||||
private DispatcherTimer _moveTimer;
|
private DispatcherTimer _moveTimer;
|
||||||
|
|
||||||
public Caret(UIElement adornedElement, Brush brush, double height = 18, double thickness = 1.72) : base(adornedElement)
|
public Caret(UIElement adornedElement, Brush brush, double height = 18, double thickness = 1.72) : base(adornedElement)
|
||||||
{
|
{
|
||||||
IsHitTestVisible = false;
|
IsHitTestVisible = false;
|
||||||
|
|
||||||
|
_enabled = true;
|
||||||
_height = height;
|
_height = height;
|
||||||
_brush = brush;
|
_brush = brush;
|
||||||
_pen = new Pen(brush, 1.92);
|
_pen = new Pen(brush, 1.92);
|
||||||
|
|
||||||
_blinkTimer = new DispatcherTimer();
|
_blinkTimer = new DispatcherTimer();
|
||||||
_blinkTimer.Interval = TimeSpan.FromMilliseconds(428);
|
_blinkTimer.Interval = TimeSpan.FromMilliseconds(324);
|
||||||
_blinkTimer.Tick += new EventHandler((s, e) => {
|
_blinkTimer.Tick += new EventHandler((s, e) => {
|
||||||
Toggle(_blink = !_blink);
|
Toggle(_blink = !_blink);
|
||||||
});
|
});
|
||||||
|
|
@ -50,22 +52,30 @@ public class Caret : Adorner
|
||||||
public void Toggle(bool hide)
|
public void Toggle(bool hide)
|
||||||
{
|
{
|
||||||
_pen.Brush = hide ? Brushes.Transparent : _brush;
|
_pen.Brush = hide ? Brushes.Transparent : _brush;
|
||||||
|
InvalidateVisual();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Disable()
|
||||||
|
{
|
||||||
|
_blinkTimer?.Stop();
|
||||||
|
_enabled = false;
|
||||||
|
Toggle(true);
|
||||||
|
InvalidateVisual();
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateSelection((Point from, Point to)[] lines)
|
public void UpdateSelection((Point from, Point to)[] lines)
|
||||||
{
|
{
|
||||||
_lines = lines;
|
_lines = lines;
|
||||||
InvalidateVisual();
|
InvalidateVisual();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdatePosition(Point newPosition)
|
public void UpdatePosition(Point newPosition)
|
||||||
{
|
{
|
||||||
_cursorPosition = _targetPosition = newPosition;
|
_cursorPosition = _targetPosition = newPosition;
|
||||||
Toggle(_blink = false);
|
_enabled = true;
|
||||||
//_blinkTimer.Stop();
|
Toggle(_blink = false);
|
||||||
//_moveTimer.Start();
|
_blinkTimer.Start();
|
||||||
InvalidateVisual();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnRender(DrawingContext drawingContext)
|
protected override void OnRender(DrawingContext drawingContext)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,26 +15,40 @@
|
||||||
<Setter Property="CurrentSelection" Value="{Binding CurrentSelection}" />
|
<Setter Property="CurrentSelection" Value="{Binding CurrentSelection}" />
|
||||||
<Setter Property="CurrentLineBuffer" Value="{Binding CurrentLineBuffer}" />
|
<Setter Property="CurrentLineBuffer" Value="{Binding CurrentLineBuffer}" />
|
||||||
</Style>
|
</Style>
|
||||||
</UserControl.Style>
|
</UserControl.Style>
|
||||||
|
<ScrollViewer x:Name="ScrollView"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
HorizontalScrollBarVisibility="Auto">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="32" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ListBox x:Name="LinesList"
|
||||||
|
Grid.Column="0"
|
||||||
|
ItemsSource="{Binding Lines.Count}"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
Background="#121314"
|
||||||
|
Foreground="#969696"
|
||||||
|
BorderThickness="0"
|
||||||
|
Padding="0,0,5,0"
|
||||||
|
VerticalContentAlignment="Top"
|
||||||
|
HorizontalContentAlignment="Right"/>
|
||||||
|
<ItemsControl ItemsSource="{Binding Lines}"
|
||||||
|
Grid.Column="1">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<VirtualizingStackPanel IsItemsHost="True" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<local:LineRenderer LineBuffer="{Binding Buffer}"
|
||||||
|
Selection="{Binding Selection}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
|
||||||
<ScrollViewer x:Name="ScrollView"
|
</ItemsControl>
|
||||||
VerticalScrollBarVisibility="Auto"
|
</Grid>
|
||||||
HorizontalScrollBarVisibility="Auto">
|
|
||||||
<ItemsControl ItemsSource="{Binding Lines}">
|
|
||||||
|
|
||||||
<ItemsControl.ItemsPanel>
|
|
||||||
<ItemsPanelTemplate>
|
|
||||||
<VirtualizingStackPanel IsItemsHost="True" />
|
|
||||||
</ItemsPanelTemplate>
|
|
||||||
</ItemsControl.ItemsPanel>
|
|
||||||
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<local:LineRenderer LineBuffer="{Binding}" />
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
|
|
||||||
</ItemsControl>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
||||||
|
|
@ -3,26 +3,32 @@ using Qrakhen.Qamp.Editor.Input;
|
||||||
using Qrakhen.Qamp.Editor.Primitives;
|
using Qrakhen.Qamp.Editor.Primitives;
|
||||||
using Qrakhen.Qamp.Editor.ViewModel;
|
using Qrakhen.Qamp.Editor.ViewModel;
|
||||||
using Qrakhen.Qamp.Memory;
|
using Qrakhen.Qamp.Memory;
|
||||||
|
using System.Diagnostics.Eventing.Reader;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace Qrakhen.Qamp.Editor.Controls;
|
namespace Qrakhen.Qamp.Editor.Controls;
|
||||||
|
|
||||||
public partial class EditorFrame : UserControl
|
public partial class EditorFrame : UserControl
|
||||||
{
|
{
|
||||||
public Caret Caret { get; private set; }
|
public Caret Caret { get; private set; }
|
||||||
|
|
||||||
public EditorFrame()
|
public EditorFrame()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Loaded += OnLoaded;
|
Loaded += OnLoaded;
|
||||||
PreviewKeyDown += OnKeyDown;
|
PreviewKeyDown += OnKeyDown;
|
||||||
PreviewMouseDown += OnMouseDown;
|
PreviewMouseDown += OnMouseDown;
|
||||||
}
|
ScrollView.ScrollChanged += OnScroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnScroll(object sender, ScrollChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateCaret(false);
|
||||||
|
}
|
||||||
|
|
||||||
protected void OnMouseDown(object sender, MouseButtonEventArgs e)
|
protected void OnMouseDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
@ -30,133 +36,151 @@ public partial class EditorFrame : UserControl
|
||||||
if (DataContext is EditorFrameViewModel vm) {
|
if (DataContext is EditorFrameViewModel vm) {
|
||||||
vm.MoveCaretCommand.Execute(
|
vm.MoveCaretCommand.Execute(
|
||||||
new MoveCaretOptions(
|
new MoveCaretOptions(
|
||||||
CalculateCursorPosition(e.GetPosition(this), 0, 0),
|
CalculateCursorPosition(e.GetPosition(this), 0, 0),
|
||||||
false,
|
false,
|
||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnKeyDown(object sender, KeyEventArgs e)
|
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is EditorFrameViewModel vm) {
|
if (DataContext is EditorFrameViewModel vm) {
|
||||||
BufferPosition position = e.Key switch {
|
BufferPosition position = e.Key switch {
|
||||||
Key.Right => new(0, 1),
|
Key.Right => new(0, 1),
|
||||||
Key.Left => new(0, -1),
|
Key.Left => new(0, -1),
|
||||||
Key.Up => new(-1, 0),
|
Key.Up => new(-1, 0),
|
||||||
Key.Down => new(1, 0),
|
Key.Down => new(1, 0),
|
||||||
_ => new(0, 0)
|
_ => new(0, 0)
|
||||||
};
|
};
|
||||||
if (position != BufferPosition.Initial)
|
if (position != BufferPosition.Initial)
|
||||||
vm.MoveCaretCommand.Execute(
|
vm.MoveCaretCommand.Execute(
|
||||||
new MoveCaretOptions(
|
new MoveCaretOptions(
|
||||||
position,
|
position,
|
||||||
true,
|
true,
|
||||||
InputService.CtrlHeld));
|
InputService.CtrlHeld));
|
||||||
else if (e.Key == Key.Back)
|
else if (e.Key == Key.Back)
|
||||||
vm.DeleteCommand.Execute(-1);
|
vm.DeleteCommand.Execute(-1);
|
||||||
else if (e.Key == Key.Delete)
|
else if (e.Key == Key.Delete)
|
||||||
vm.DeleteCommand.Execute(1);
|
vm.DeleteCommand.Execute(1);
|
||||||
else if (e.Key == Key.Enter)
|
else if (e.Key == Key.Enter)
|
||||||
vm.InsertCommand.Execute(Environment.NewLine);
|
vm.InsertCommand.Execute(Environment.NewLine);
|
||||||
else if (e.Key == Key.Delete)
|
else if (e.Key == Key.Delete)
|
||||||
vm.DeleteCommand.Execute(1);
|
vm.DeleteCommand.Execute(1);
|
||||||
else {
|
else {
|
||||||
char c = KeyHelper.Get(e.Key,
|
char c = KeyHelper.Get(e.Key,
|
||||||
InputService.ShiftHeld ? 1 :
|
InputService.ShiftHeld ? 1 :
|
||||||
(InputService.CtrlHeld && InputService.AltHeld) ? 2 : 0);
|
(InputService.CtrlHeld && InputService.AltHeld) ? 2 : 0);
|
||||||
if (c != 0)
|
if (c != 0)
|
||||||
vm.InsertCommand.Execute(c);
|
vm.InsertCommand.Execute(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Focus();
|
Focus();
|
||||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||||
if (adornerLayer != null) {
|
if (adornerLayer != null) {
|
||||||
Caret = new Caret(this, Brushes.LimeGreen);
|
Caret = new Caret(this, Brushes.LimeGreen);
|
||||||
adornerLayer.Add(Caret);
|
adornerLayer.Add(Caret);
|
||||||
} else {
|
} else {
|
||||||
System.Diagnostics.Debug.WriteLine("AdornerLayer still null. Check parent hierarchy.");
|
System.Diagnostics.Debug.WriteLine("AdornerLayer still null. Check parent hierarchy.");
|
||||||
}
|
}
|
||||||
Loaded -= OnLoaded;
|
Loaded -= OnLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferPosition CalculateCursorPosition(Point point, double scrollY, double scrollX)
|
private BufferPosition CalculateCursorPosition(Point point, double scrollY, double scrollX)
|
||||||
{
|
{
|
||||||
var ft = TextHelper.GetText(new string('_', 1), 14, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
var ft = TextHelper.GetText(new string('_', 1), 14, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
||||||
return new BufferPosition((int)(point.Y / TextHelper.LineHeight), (int)(point.X / ft.Width));
|
return new BufferPosition((int)(point.Y / TextHelper.LineHeight), (int)((point.X - 34) / ft.Width));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Point CalculateCaretPosition(int line, int index, double scrollY, double scrollX)
|
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 SelectRegion((Point from, Point to)[] lines)
|
|
||||||
{
|
{
|
||||||
Caret?.UpdateSelection(lines);
|
var ft = TextHelper.GetText(new string('_', index), 14, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
||||||
|
return new Point(ft.Width - scrollX + 34, line * TextHelper.LineHeight - scrollY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCaret()
|
private void MoveCaret(Point point)
|
||||||
{
|
{
|
||||||
int line = CursorPosition.Line;
|
Caret?.UpdatePosition(point);
|
||||||
int charIndex = CursorPosition.Column;
|
}
|
||||||
|
|
||||||
double scrollY = ScrollView.VerticalOffset;
|
private void HideCaret()
|
||||||
double scrollX = ScrollView.HorizontalOffset;
|
{
|
||||||
|
Caret?.Disable();
|
||||||
|
}
|
||||||
|
|
||||||
MoveCaret(
|
private void AutoScroll(Point point)
|
||||||
CalculateCaretPosition(
|
{
|
||||||
line,
|
MoveCaret(point);
|
||||||
charIndex,
|
}
|
||||||
scrollY,
|
|
||||||
scrollX));
|
private void UpdateCaret(bool autoScroll = true)
|
||||||
|
{
|
||||||
|
int line = CursorPosition.Line;
|
||||||
|
int charIndex = CursorPosition.Column;
|
||||||
|
|
||||||
|
double scrollY = ScrollView.VerticalOffset;
|
||||||
|
double scrollX = ScrollView.HorizontalOffset;
|
||||||
|
|
||||||
|
Point position = CalculateCaretPosition(
|
||||||
|
line,
|
||||||
|
charIndex,
|
||||||
|
scrollY,
|
||||||
|
scrollX);
|
||||||
|
|
||||||
|
Point offset = ScrollView.TranslatePoint(position, ScrollView);
|
||||||
|
|
||||||
|
if (offset.X < 0 ||
|
||||||
|
offset.Y < 0 ||
|
||||||
|
offset.X >= ScrollView.ActualWidth ||
|
||||||
|
offset.Y >= ScrollView.ActualHeight) {
|
||||||
|
if (autoScroll)
|
||||||
|
AutoScroll(offset);
|
||||||
|
else
|
||||||
|
HideCaret();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MoveCaret(position);
|
||||||
|
|
||||||
if (!CurrentSelection.IsVoid) {
|
if (!CurrentSelection.IsVoid) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LineBuffer CurrentLineBuffer {
|
public LineBuffer CurrentLineBuffer {
|
||||||
get => (LineBuffer)GetValue(CurrentLineBufferProperty);
|
get => (LineBuffer)GetValue(CurrentLineBufferProperty);
|
||||||
set => SetValue(CurrentLineBufferProperty, value);
|
set => SetValue(CurrentLineBufferProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly DependencyProperty CurrentLineBufferProperty =
|
public static readonly DependencyProperty CurrentLineBufferProperty =
|
||||||
DependencyProperty.Register(
|
DependencyProperty.Register(
|
||||||
nameof(CurrentLineBuffer),
|
nameof(CurrentLineBuffer),
|
||||||
typeof(LineBuffer),
|
typeof(LineBuffer),
|
||||||
typeof(EditorFrame),
|
typeof(EditorFrame),
|
||||||
new PropertyMetadata(null));
|
new PropertyMetadata(null));
|
||||||
|
|
||||||
public BufferPosition CursorPosition {
|
public BufferPosition CursorPosition {
|
||||||
get => (BufferPosition)GetValue(CursorPositionProperty);
|
get => (BufferPosition)GetValue(CursorPositionProperty);
|
||||||
set => SetValue(CursorPositionProperty, value);
|
set => SetValue(CursorPositionProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly DependencyProperty CursorPositionProperty =
|
public static readonly DependencyProperty CursorPositionProperty =
|
||||||
DependencyProperty.Register(
|
DependencyProperty.Register(
|
||||||
nameof(CursorPosition),
|
nameof(CursorPosition),
|
||||||
typeof(BufferPosition),
|
typeof(BufferPosition),
|
||||||
typeof(EditorFrame),
|
typeof(EditorFrame),
|
||||||
new PropertyMetadata(BufferPosition.Initial, OnCursorPositionChanged));
|
new PropertyMetadata(BufferPosition.Initial, OnCursorPositionChanged));
|
||||||
|
|
||||||
private static void OnCursorPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
private static void OnCursorPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
var frame = (EditorFrame)d;
|
var frame = (EditorFrame)d;
|
||||||
frame.UpdateCaret();
|
frame.UpdateCaret();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferRegion CurrentSelection {
|
public BufferRegion CurrentSelection {
|
||||||
get => (BufferRegion)GetValue(CurrentSelectionProperty);
|
get => (BufferRegion)GetValue(CurrentSelectionProperty);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
using Qrakhen.Qamp.Memory;
|
using Qrakhen.Qamp.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Text;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
namespace Qrakhen.Qamp.Editor.Controls;
|
namespace Qrakhen.Qamp.Editor.Controls;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,39 +7,74 @@
|
||||||
xmlns:vm="clr-namespace:Qrakhen.Qamp.Editor.ViewModel"
|
xmlns:vm="clr-namespace:Qrakhen.Qamp.Editor.ViewModel"
|
||||||
xmlns:controls="clr-namespace:Qrakhen.Qamp.Editor.Controls"
|
xmlns:controls="clr-namespace:Qrakhen.Qamp.Editor.Controls"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DataContext="{d:DesignInstance Type=vm:FileViewModel}"
|
Background="#161718"
|
||||||
Title="MainWindow" Height="450" Width="800">
|
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
|
||||||
|
Title="MainWindow" Height="640" Width="920">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<RowDefinition Height="32" />
|
||||||
<ColumnDefinition Width="5*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.ColumnDefinitions>
|
<RowDefinition Height="18" />
|
||||||
<Grid Grid.Column="1">
|
</Grid.RowDefinitions>
|
||||||
<Grid.RowDefinitions>
|
<Grid Grid.Row="0"
|
||||||
<RowDefinition Height="5*" />
|
Background="#202122">
|
||||||
<RowDefinition Height="*" />
|
<Menu Background="#202122"
|
||||||
</Grid.RowDefinitions>
|
VerticalAlignment="Stretch"
|
||||||
<Grid Grid.Row="0">
|
VerticalContentAlignment="Center"
|
||||||
<Grid.ColumnDefinitions>
|
Height="32">
|
||||||
<ColumnDefinition Width="32" />
|
<MenuItem Header="File"
|
||||||
<ColumnDefinition Width="*" />
|
Height="32"
|
||||||
</Grid.ColumnDefinitions>
|
Foreground="#fefefe">
|
||||||
|
<MenuItem></MenuItem>
|
||||||
|
<MenuItem></MenuItem>
|
||||||
|
<MenuItem></MenuItem>
|
||||||
|
<MenuItem></MenuItem>
|
||||||
|
<MenuItem></MenuItem>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Fun" Foreground="#fefefe">
|
||||||
|
|
||||||
<ListBox Grid.Column="0"
|
</MenuItem>
|
||||||
ItemsSource="{Binding Lines.Count}"
|
<MenuItem Header="Run" Foreground="#fefefe">
|
||||||
IsHitTestVisible="False"
|
|
||||||
Background="#242628"
|
|
||||||
Foreground="#969696"
|
|
||||||
BorderThickness="0"
|
|
||||||
Padding="0,0,5,0"
|
|
||||||
VerticalContentAlignment="Top"
|
|
||||||
HorizontalContentAlignment="Right"/>
|
|
||||||
|
|
||||||
<controls:EditorFrame Grid.Column="1" />
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Row="1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="5*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid Grid.Column="0" Background="#242526">
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Grid.Row="1" Background="#161718">
|
<GridSplitter Grid.Column="0"
|
||||||
|
ResizeDirection="Columns"
|
||||||
|
Width="1"
|
||||||
|
Background="#40fefefe" />
|
||||||
|
<Grid Grid.Column="1">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="5*" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.Row="0">
|
||||||
|
<controls:EditorFrame />
|
||||||
|
</Grid>
|
||||||
|
<GridSplitter Grid.Row="0"
|
||||||
|
ResizeDirection="Rows"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Bottom"
|
||||||
|
Height="1"
|
||||||
|
Background="#40fefefe" />
|
||||||
|
<Grid Grid.Row="1" Background="#1e1f20">
|
||||||
|
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid Grid.Row="2"
|
||||||
|
Background="#141516">
|
||||||
|
<Label Foreground="#80efefef"
|
||||||
|
FontSize="10"
|
||||||
|
Padding="2">Fun & Status</Label>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,12 @@ using System.Windows.Input;
|
||||||
|
|
||||||
namespace Qrakhen.Qamp.Editor.ViewModel;
|
namespace Qrakhen.Qamp.Editor.ViewModel;
|
||||||
|
|
||||||
|
public class SelectableLineBuffer(LineBuffer buffer)
|
||||||
|
{
|
||||||
|
public LineBuffer Buffer { get; private set; } = buffer;
|
||||||
|
public BufferRegion Selection { get; private set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
public class EditorFrameViewModel : ObservableObject
|
public class EditorFrameViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
private BufferPosition _cursorPosition;
|
private BufferPosition _cursorPosition;
|
||||||
|
|
@ -26,7 +32,7 @@ public class EditorFrameViewModel : ObservableObject
|
||||||
|
|
||||||
public int CursorColumn => _cursorPosition.Column;
|
public int CursorColumn => _cursorPosition.Column;
|
||||||
|
|
||||||
public LineBuffer CurrentLineBuffer => Lines[CursorLine];
|
public SelectableLineBuffer CurrentLine => Lines[CursorLine];
|
||||||
|
|
||||||
public ICommand MoveCaretCommand { get; }
|
public ICommand MoveCaretCommand { get; }
|
||||||
public ICommand MoveBlockCommand { get; }
|
public ICommand MoveBlockCommand { get; }
|
||||||
|
|
@ -34,11 +40,11 @@ public class EditorFrameViewModel : ObservableObject
|
||||||
public ICommand DeleteCommand { get; }
|
public ICommand DeleteCommand { get; }
|
||||||
public ICommand ClipBoardCommand { get; }
|
public ICommand ClipBoardCommand { get; }
|
||||||
|
|
||||||
public ObservableCollection<LineBuffer> Lines { get; private set; } = new() {
|
public ObservableCollection<SelectableLineBuffer> Lines { get; private set; } = new() {
|
||||||
new LineBuffer("test"),
|
new SelectableLineBuffer(new LineBuffer("test {")),
|
||||||
new LineBuffer(" is very good;"),
|
new SelectableLineBuffer(new LineBuffer(" is very good;")),
|
||||||
new LineBuffer(" jaja();"),
|
new SelectableLineBuffer(new LineBuffer(" jaja();")),
|
||||||
new LineBuffer("}")
|
new SelectableLineBuffer(new LineBuffer("}"))
|
||||||
};
|
};
|
||||||
|
|
||||||
public EditorFrameViewModel()
|
public EditorFrameViewModel()
|
||||||
|
|
@ -56,14 +62,14 @@ public class EditorFrameViewModel : ObservableObject
|
||||||
public void SetCursor(BufferPosition position)
|
public void SetCursor(BufferPosition position)
|
||||||
{
|
{
|
||||||
CursorPosition = AlignBufferPosition(position);
|
CursorPosition = AlignBufferPosition(position);
|
||||||
OnPropertyChanged(nameof(CurrentLineBuffer));
|
OnPropertyChanged(nameof(CurrentLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveCursor(int lines, int columns) => MoveCursor(new BufferPosition(lines, columns));
|
public void MoveCursor(int lines, int columns) => MoveCursor(new BufferPosition(lines, columns));
|
||||||
public void MoveCursor(BufferPosition relative, bool jump = false)
|
public void MoveCursor(BufferPosition relative, bool jump = false)
|
||||||
{
|
{
|
||||||
SetCursor(CursorPosition + relative);
|
SetCursor(CursorPosition + relative);
|
||||||
OnPropertyChanged(nameof(CurrentLineBuffer));
|
OnPropertyChanged(nameof(CurrentLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Delete(BufferRegion region, bool follow = true)
|
public void Delete(BufferRegion region, bool follow = true)
|
||||||
|
|
@ -83,25 +89,25 @@ public class EditorFrameViewModel : ObservableObject
|
||||||
if (follow) {
|
if (follow) {
|
||||||
// remove newline
|
// remove newline
|
||||||
if (CursorColumn - count < 0 && CursorLine > 0) {
|
if (CursorColumn - count < 0 && CursorLine > 0) {
|
||||||
int position = Lines[CursorLine - 1].Tail;
|
int position = Lines[CursorLine - 1].Buffer.Tail;
|
||||||
Lines[CursorLine - 1].Insert(
|
Lines[CursorLine - 1].Buffer.Insert(
|
||||||
position,
|
position,
|
||||||
CurrentLineBuffer.Slice(0));
|
CurrentLine.Buffer.Slice(0));
|
||||||
Lines.RemoveAt(CursorLine);
|
Lines.RemoveAt(CursorLine);
|
||||||
SetCursor(CursorLine - 1, position);
|
SetCursor(CursorLine - 1, position);
|
||||||
} else {
|
} else {
|
||||||
MoveCursor(0, -count);
|
MoveCursor(0, -count);
|
||||||
CurrentLineBuffer.Delete(CursorColumn, count);
|
CurrentLine.Buffer.Delete(CursorColumn, count);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CursorColumn + count > CurrentLineBuffer.Tail &&
|
if (CursorColumn + count > CurrentLine.Buffer.Tail &&
|
||||||
CursorLine < Lines.Count - 1) {
|
CursorLine < Lines.Count - 1) {
|
||||||
CurrentLineBuffer.Insert(
|
CurrentLine.Buffer.Insert(
|
||||||
CurrentLineBuffer.Tail,
|
CurrentLine.Buffer.Tail,
|
||||||
Lines[CursorLine + 1].Slice(0));
|
Lines[CursorLine + 1].Buffer.Slice(0));
|
||||||
Lines.RemoveAt(CursorLine + 1);
|
Lines.RemoveAt(CursorLine + 1);
|
||||||
}
|
}
|
||||||
CurrentLineBuffer.Delete(CursorColumn, count);
|
CurrentLine.Buffer.Delete(CursorColumn, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,12 +129,12 @@ public class EditorFrameViewModel : ObservableObject
|
||||||
for (int i = 0; i < lines.Length; i++) {
|
for (int i = 0; i < lines.Length; i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
LineBuffer split = new LineBuffer(
|
LineBuffer split = new LineBuffer(
|
||||||
CurrentLineBuffer.Slice(CursorColumn),
|
CurrentLine.Buffer.Slice(CursorColumn),
|
||||||
CurrentLineBuffer.Encoding);
|
CurrentLine.Buffer.Encoding);
|
||||||
Lines.Insert(CursorLine + 1, split);
|
Lines.Insert(CursorLine + 1, new SelectableLineBuffer(split));
|
||||||
SetCursor(new BufferPosition(CursorLine + 1, 0));
|
SetCursor(new BufferPosition(CursorLine + 1, 0));
|
||||||
}
|
}
|
||||||
CurrentLineBuffer.Insert(CursorColumn, lines[i]);
|
CurrentLine.Buffer.Insert(CursorColumn, lines[i]);
|
||||||
if (follow)
|
if (follow)
|
||||||
MoveCursor(new BufferPosition(0, lines[i].Length));
|
MoveCursor(new BufferPosition(0, lines[i].Length));
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +143,7 @@ public class EditorFrameViewModel : ObservableObject
|
||||||
private BufferPosition AlignBufferPosition(BufferPosition position)
|
private BufferPosition AlignBufferPosition(BufferPosition position)
|
||||||
{
|
{
|
||||||
int line = Math.Max(0, Math.Min(position.Line, Lines.Count - 1));
|
int line = Math.Max(0, Math.Min(position.Line, Lines.Count - 1));
|
||||||
LineBuffer buffer = Lines[line];
|
LineBuffer buffer = Lines[line].Buffer;
|
||||||
int column = Math.Max(0, Math.Min(position.Column, buffer.Tail));
|
int column = Math.Max(0, Math.Min(position.Column, buffer.Tail));
|
||||||
return new BufferPosition(line, column);
|
return new BufferPosition(line, column);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue