182 lines
5.1 KiB
C#
182 lines
5.1 KiB
C#
using Qrakhen.Qamp.Editor.Commands;
|
|
using Qrakhen.Qamp.Editor.Primitives;
|
|
using Qrakhen.Qamp.Memory;
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
|
|
namespace Qrakhen.Qamp.Editor.ViewModel;
|
|
|
|
public class EditorFrameViewModel : ObservableObject
|
|
{
|
|
private BufferPosition _cursorPosition;
|
|
public BufferPosition CursorPosition {
|
|
get => _cursorPosition;
|
|
set => SetProperty(ref _cursorPosition, value);
|
|
}
|
|
|
|
private BufferRegion _currentSelection;
|
|
public BufferRegion CurrentSelection {
|
|
get => _currentSelection;
|
|
set => SetProperty(ref _currentSelection, value);
|
|
}
|
|
|
|
public int CursorLine => _cursorPosition.Line;
|
|
|
|
public int CursorColumn => _cursorPosition.Column;
|
|
|
|
public LineBuffer CurrentLineBuffer => Lines[CursorLine];
|
|
|
|
public ICommand MoveCaretCommand { get; }
|
|
public ICommand MoveBlockCommand { get; }
|
|
public ICommand InsertCommand { get; }
|
|
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 EditorFrameViewModel()
|
|
{
|
|
MoveCaretCommand = new RelayCommand(ExecuteMoveCaret);
|
|
MoveBlockCommand = new RelayCommand(ExecuteMoveBlock);
|
|
InsertCommand = new RelayCommand(ExecuteInsert);
|
|
DeleteCommand = new RelayCommand(ExecuteDelete);
|
|
ClipBoardCommand = new RelayCommand(() => { });
|
|
}
|
|
|
|
|
|
|
|
public void SetCursor(int line, int column) => SetCursor(new BufferPosition(line, column));
|
|
public void SetCursor(BufferPosition position)
|
|
{
|
|
CursorPosition = AlignBufferPosition(position);
|
|
OnPropertyChanged(nameof(CurrentLineBuffer));
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
public void Delete(BufferRegion region, bool follow = true)
|
|
{
|
|
if (follow)
|
|
SetCursor(new BufferPosition(region.From.Line, region.From.Column));
|
|
for (int line = region.From.Line; line < region.To.Line; line++) {
|
|
|
|
}
|
|
}
|
|
|
|
public void Delete(int count = 1, bool follow = true)
|
|
{
|
|
if (count < 1)
|
|
return;
|
|
|
|
if (follow) {
|
|
// remove newline
|
|
if (CursorColumn - count < 0 && CursorLine > 0) {
|
|
int position = Lines[CursorLine - 1].Tail;
|
|
Lines[CursorLine - 1].Insert(
|
|
position,
|
|
CurrentLineBuffer.Slice(0));
|
|
Lines.RemoveAt(CursorLine);
|
|
SetCursor(CursorLine - 1, position);
|
|
return;
|
|
} else
|
|
MoveCursor(0, -count);
|
|
} else {
|
|
if (CursorColumn + count >= CurrentLineBuffer.Tail &&
|
|
CursorLine < Lines.Count - 1) {
|
|
CurrentLineBuffer.Insert(
|
|
CurrentLineBuffer.Tail,
|
|
Lines[CursorLine + 1].Slice(0));
|
|
Lines.RemoveAt(CursorLine + 1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
CurrentLineBuffer.Delete(CursorColumn, count);
|
|
}
|
|
|
|
/*
|
|
|
|
asdasdy
|
|
klöklöklökl
|
|
köäläälööx
|
|
cyxc
|
|
|
|
asdasd
|
|
|
|
* */
|
|
|
|
public void Insert(string data, bool follow = true)
|
|
{
|
|
data = data.Replace("\t", " ");
|
|
var lines = data.Split(Environment.NewLine, StringSplitOptions.None);
|
|
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);
|
|
SetCursor(new BufferPosition(CursorLine + 1, 0));
|
|
}
|
|
CurrentLineBuffer.Insert(CursorColumn, lines[i]);
|
|
if (follow)
|
|
MoveCursor(new BufferPosition(0, lines[i].Length));
|
|
}
|
|
}
|
|
|
|
private BufferPosition AlignBufferPosition(BufferPosition position)
|
|
{
|
|
int line = Math.Max(0, Math.Min(position.Line, Lines.Count - 1));
|
|
LineBuffer buffer = Lines[line];
|
|
int column = Math.Max(0, Math.Min(position.Column, buffer.Tail));
|
|
return new BufferPosition(line, column);
|
|
}
|
|
|
|
#region Commands
|
|
|
|
private void ExecuteMoveCaret(object? parameter)
|
|
{
|
|
if (parameter is MoveCaretOptions options) {
|
|
if (options.Relative)
|
|
MoveCursor(options.Position, options.Jump);
|
|
else
|
|
SetCursor(options.Position);
|
|
}
|
|
}
|
|
|
|
private void ExecuteMoveBlock(object? parameter)
|
|
{
|
|
if (parameter is BufferPosition relative)
|
|
MoveCursor(relative);
|
|
}
|
|
|
|
private void ExecuteInsert(object? parameter)
|
|
{
|
|
if (parameter is string str)
|
|
Insert(str, true);
|
|
if (parameter is char c)
|
|
Insert(c + "", true);
|
|
}
|
|
|
|
private void ExecuteDelete(object? parameter)
|
|
{
|
|
if (parameter is int count)
|
|
Delete(Math.Abs(count), count < 0);
|
|
if (parameter is BufferRegion region)
|
|
Delete(region);
|
|
}
|
|
|
|
#endregion
|
|
}
|