qamp/Qrakhen.Qamp.Editor/ViewModel/EditorFrameViewModel.cs

206 lines
6.0 KiB
C#

using Qrakhen.Qamp.Editor.Commands;
using Qrakhen.Qamp.Editor.Primitives;
using Qrakhen.Qamp.Memory;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Documents;
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 FileInfo _fileInfo;
public FileInfo FileInfo {
get => _fileInfo;
set => SetProperty(ref _fileInfo, value);
}
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 SelectableLineBuffer CurrentLine => Lines[CursorLine];
public ICommand MoveCaretCommand { get; }
public ICommand MoveBlockCommand { get; }
public ICommand InsertCommand { get; }
public ICommand DeleteCommand { get; }
public ICommand ClipBoardCommand { get; }
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()
{
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(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(CurrentLine));
}
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].Buffer.Tail;
Lines[CursorLine - 1].Buffer.Insert(
position,
CurrentLine.Buffer.Slice(0));
Lines.RemoveAt(CursorLine);
SetCursor(CursorLine - 1, position);
} else {
MoveCursor(0, -count);
CurrentLine.Buffer.Delete(CursorColumn, count);
}
} else {
if (CursorColumn + count > CurrentLine.Buffer.Tail &&
CursorLine < Lines.Count - 1) {
CurrentLine.Buffer.Insert(
CurrentLine.Buffer.Tail,
Lines[CursorLine + 1].Buffer.Slice(0));
Lines.RemoveAt(CursorLine + 1);
}
CurrentLine.Buffer.Delete(CursorColumn, count);
}
}
public void Select(BufferPosition relativePosition, bool jump = false)
{
if (CurrentSelection.IsVoid) {
CurrentSelection = new BufferRegion(CursorPosition, CursorPosition);
}
CurrentSelection += relativePosition;
}
public void Deselect()
{
CurrentSelection = BufferRegion.Void;
}
/*
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(
CurrentLine.Buffer.Slice(CursorColumn),
CurrentLine.Buffer.Encoding);
Lines.Insert(CursorLine + 1, new SelectableLineBuffer(split));
SetCursor(new BufferPosition(CursorLine + 1, 0));
}
CurrentLine.Buffer.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].Buffer;
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
}