stoff
This commit is contained in:
parent
e2022ef80e
commit
b3385c0860
|
|
@ -11,6 +11,7 @@ public class Caret : Adorner
|
|||
private readonly double _height;
|
||||
private readonly Brush _brush;
|
||||
private bool _blink;
|
||||
private bool _enabled;
|
||||
private Point _cursorPosition;
|
||||
private Point _targetPosition;
|
||||
private (Point from, Point to)[] _lines = [];
|
||||
|
|
@ -21,12 +22,13 @@ public class Caret : Adorner
|
|||
{
|
||||
IsHitTestVisible = false;
|
||||
|
||||
_enabled = true;
|
||||
_height = height;
|
||||
_brush = brush;
|
||||
_pen = new Pen(brush, 1.92);
|
||||
|
||||
_blinkTimer = new DispatcherTimer();
|
||||
_blinkTimer.Interval = TimeSpan.FromMilliseconds(428);
|
||||
_blinkTimer.Interval = TimeSpan.FromMilliseconds(324);
|
||||
_blinkTimer.Tick += new EventHandler((s, e) => {
|
||||
Toggle(_blink = !_blink);
|
||||
});
|
||||
|
|
@ -50,6 +52,15 @@ public class Caret : Adorner
|
|||
public void Toggle(bool hide)
|
||||
{
|
||||
_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)
|
||||
|
|
@ -61,10 +72,9 @@ public class Caret : Adorner
|
|||
public void UpdatePosition(Point newPosition)
|
||||
{
|
||||
_cursorPosition = _targetPosition = newPosition;
|
||||
_enabled = true;
|
||||
Toggle(_blink = false);
|
||||
//_blinkTimer.Stop();
|
||||
//_moveTimer.Start();
|
||||
InvalidateVisual();
|
||||
_blinkTimer.Start();
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
|
|
|
|||
|
|
@ -16,25 +16,39 @@
|
|||
<Setter Property="CurrentLineBuffer" Value="{Binding CurrentLineBuffer}" />
|
||||
</Style>
|
||||
</UserControl.Style>
|
||||
|
||||
<ScrollViewer x:Name="ScrollView"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding Lines}">
|
||||
|
||||
<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}" />
|
||||
<local:LineRenderer LineBuffer="{Binding Buffer}"
|
||||
Selection="{Binding Selection}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
</UserControl>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ using Qrakhen.Qamp.Editor.Input;
|
|||
using Qrakhen.Qamp.Editor.Primitives;
|
||||
using Qrakhen.Qamp.Editor.ViewModel;
|
||||
using Qrakhen.Qamp.Memory;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Qrakhen.Qamp.Editor.Controls;
|
||||
|
||||
|
|
@ -22,6 +22,12 @@ public partial class EditorFrame : UserControl
|
|||
Loaded += OnLoaded;
|
||||
PreviewKeyDown += OnKeyDown;
|
||||
PreviewMouseDown += OnMouseDown;
|
||||
ScrollView.ScrollChanged += OnScroll;
|
||||
}
|
||||
|
||||
private void OnScroll(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
UpdateCaret(false);
|
||||
}
|
||||
|
||||
protected void OnMouseDown(object sender, MouseButtonEventArgs e)
|
||||
|
|
@ -89,13 +95,13 @@ public partial class EditorFrame : UserControl
|
|||
private BufferPosition CalculateCursorPosition(Point point, double scrollY, double scrollX)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var ft = TextHelper.GetText(new string('_', index), 14, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
||||
return new Point(ft.Width + scrollX + 2, line * TextHelper.LineHeight + scrollY);
|
||||
return new Point(ft.Width - scrollX + 34, line * TextHelper.LineHeight - scrollY);
|
||||
}
|
||||
|
||||
private void MoveCaret(Point point)
|
||||
|
|
@ -103,12 +109,17 @@ public partial class EditorFrame : UserControl
|
|||
Caret?.UpdatePosition(point);
|
||||
}
|
||||
|
||||
private void SelectRegion((Point from, Point to)[] lines)
|
||||
private void HideCaret()
|
||||
{
|
||||
Caret?.UpdateSelection(lines);
|
||||
Caret?.Disable();
|
||||
}
|
||||
|
||||
private void UpdateCaret()
|
||||
private void AutoScroll(Point point)
|
||||
{
|
||||
MoveCaret(point);
|
||||
}
|
||||
|
||||
private void UpdateCaret(bool autoScroll = true)
|
||||
{
|
||||
int line = CursorPosition.Line;
|
||||
int charIndex = CursorPosition.Column;
|
||||
|
|
@ -116,12 +127,25 @@ public partial class EditorFrame : UserControl
|
|||
double scrollY = ScrollView.VerticalOffset;
|
||||
double scrollX = ScrollView.HorizontalOffset;
|
||||
|
||||
MoveCaret(
|
||||
CalculateCaretPosition(
|
||||
Point position = CalculateCaretPosition(
|
||||
line,
|
||||
charIndex,
|
||||
scrollY,
|
||||
scrollX));
|
||||
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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
using Qrakhen.Qamp.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
namespace Qrakhen.Qamp.Editor.Controls;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,39 +7,74 @@
|
|||
xmlns:vm="clr-namespace:Qrakhen.Qamp.Editor.ViewModel"
|
||||
xmlns:controls="clr-namespace:Qrakhen.Qamp.Editor.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=vm:FileViewModel}"
|
||||
Title="MainWindow" Height="450" Width="800">
|
||||
Background="#161718"
|
||||
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
|
||||
Title="MainWindow" Height="640" Width="920">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="18" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0"
|
||||
Background="#202122">
|
||||
<Menu Background="#202122"
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
Height="32">
|
||||
<MenuItem Header="File"
|
||||
Height="32"
|
||||
Foreground="#fefefe">
|
||||
<MenuItem></MenuItem>
|
||||
<MenuItem></MenuItem>
|
||||
<MenuItem></MenuItem>
|
||||
<MenuItem></MenuItem>
|
||||
<MenuItem></MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Fun" Foreground="#fefefe">
|
||||
|
||||
</MenuItem>
|
||||
<MenuItem Header="Run" Foreground="#fefefe">
|
||||
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Column="0" Background="#242526">
|
||||
|
||||
</Grid>
|
||||
<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">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ListBox Grid.Column="0"
|
||||
ItemsSource="{Binding Lines.Count}"
|
||||
IsHitTestVisible="False"
|
||||
Background="#242628"
|
||||
Foreground="#969696"
|
||||
BorderThickness="0"
|
||||
Padding="0,0,5,0"
|
||||
VerticalContentAlignment="Top"
|
||||
HorizontalContentAlignment="Right"/>
|
||||
|
||||
<controls:EditorFrame Grid.Column="1" />
|
||||
<controls:EditorFrame />
|
||||
</Grid>
|
||||
<Grid Grid.Row="1" Background="#161718">
|
||||
<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.Row="2"
|
||||
Background="#141516">
|
||||
<Label Foreground="#80efefef"
|
||||
FontSize="10"
|
||||
Padding="2">Fun & Status</Label>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ using System.Windows.Input;
|
|||
|
||||
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
|
||||
{
|
||||
private BufferPosition _cursorPosition;
|
||||
|
|
@ -26,7 +32,7 @@ public class EditorFrameViewModel : ObservableObject
|
|||
|
||||
public int CursorColumn => _cursorPosition.Column;
|
||||
|
||||
public LineBuffer CurrentLineBuffer => Lines[CursorLine];
|
||||
public SelectableLineBuffer CurrentLine => Lines[CursorLine];
|
||||
|
||||
public ICommand MoveCaretCommand { get; }
|
||||
public ICommand MoveBlockCommand { get; }
|
||||
|
|
@ -34,11 +40,11 @@ public class EditorFrameViewModel : ObservableObject
|
|||
public ICommand DeleteCommand { get; }
|
||||
public ICommand ClipBoardCommand { get; }
|
||||
|
||||
public ObservableCollection<LineBuffer> Lines { get; private set; } = new() {
|
||||
new LineBuffer("test"),
|
||||
new LineBuffer(" is very good;"),
|
||||
new LineBuffer(" jaja();"),
|
||||
new LineBuffer("}")
|
||||
public ObservableCollection<SelectableLineBuffer> Lines { get; private set; } = new() {
|
||||
new SelectableLineBuffer(new LineBuffer("test {")),
|
||||
new SelectableLineBuffer(new LineBuffer(" is very good;")),
|
||||
new SelectableLineBuffer(new LineBuffer(" jaja();")),
|
||||
new SelectableLineBuffer(new LineBuffer("}"))
|
||||
};
|
||||
|
||||
public EditorFrameViewModel()
|
||||
|
|
@ -56,14 +62,14 @@ public class EditorFrameViewModel : ObservableObject
|
|||
public void SetCursor(BufferPosition 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(BufferPosition relative, bool jump = false)
|
||||
{
|
||||
SetCursor(CursorPosition + relative);
|
||||
OnPropertyChanged(nameof(CurrentLineBuffer));
|
||||
OnPropertyChanged(nameof(CurrentLine));
|
||||
}
|
||||
|
||||
public void Delete(BufferRegion region, bool follow = true)
|
||||
|
|
@ -83,25 +89,25 @@ public class EditorFrameViewModel : ObservableObject
|
|||
if (follow) {
|
||||
// remove newline
|
||||
if (CursorColumn - count < 0 && CursorLine > 0) {
|
||||
int position = Lines[CursorLine - 1].Tail;
|
||||
Lines[CursorLine - 1].Insert(
|
||||
int position = Lines[CursorLine - 1].Buffer.Tail;
|
||||
Lines[CursorLine - 1].Buffer.Insert(
|
||||
position,
|
||||
CurrentLineBuffer.Slice(0));
|
||||
CurrentLine.Buffer.Slice(0));
|
||||
Lines.RemoveAt(CursorLine);
|
||||
SetCursor(CursorLine - 1, position);
|
||||
} else {
|
||||
MoveCursor(0, -count);
|
||||
CurrentLineBuffer.Delete(CursorColumn, count);
|
||||
CurrentLine.Buffer.Delete(CursorColumn, count);
|
||||
}
|
||||
} else {
|
||||
if (CursorColumn + count > CurrentLineBuffer.Tail &&
|
||||
if (CursorColumn + count > CurrentLine.Buffer.Tail &&
|
||||
CursorLine < Lines.Count - 1) {
|
||||
CurrentLineBuffer.Insert(
|
||||
CurrentLineBuffer.Tail,
|
||||
Lines[CursorLine + 1].Slice(0));
|
||||
CurrentLine.Buffer.Insert(
|
||||
CurrentLine.Buffer.Tail,
|
||||
Lines[CursorLine + 1].Buffer.Slice(0));
|
||||
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++) {
|
||||
if (i > 0) {
|
||||
LineBuffer split = new LineBuffer(
|
||||
CurrentLineBuffer.Slice(CursorColumn),
|
||||
CurrentLineBuffer.Encoding);
|
||||
Lines.Insert(CursorLine + 1, split);
|
||||
CurrentLine.Buffer.Slice(CursorColumn),
|
||||
CurrentLine.Buffer.Encoding);
|
||||
Lines.Insert(CursorLine + 1, new SelectableLineBuffer(split));
|
||||
SetCursor(new BufferPosition(CursorLine + 1, 0));
|
||||
}
|
||||
CurrentLineBuffer.Insert(CursorColumn, lines[i]);
|
||||
CurrentLine.Buffer.Insert(CursorColumn, lines[i]);
|
||||
if (follow)
|
||||
MoveCursor(new BufferPosition(0, lines[i].Length));
|
||||
}
|
||||
|
|
@ -137,7 +143,7 @@ public class EditorFrameViewModel : ObservableObject
|
|||
private BufferPosition AlignBufferPosition(BufferPosition position)
|
||||
{
|
||||
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));
|
||||
return new BufferPosition(line, column);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue