237 lines
6.8 KiB
C#
237 lines
6.8 KiB
C#
using Microsoft.Win32;
|
|
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.Text;
|
|
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 Encoding _encoding;
|
|
public Encoding Encoding {
|
|
get => _encoding;
|
|
set => SetProperty(ref _encoding, value);
|
|
}
|
|
|
|
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()
|
|
{
|
|
Encoding = Encoding.ASCII;
|
|
|
|
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
|
|
|
|
public string Serialize(string? lineTerminator = null)
|
|
{
|
|
lineTerminator ??= Environment.NewLine;
|
|
string result = "";
|
|
foreach (var line in Lines) {
|
|
result += $"{line.Buffer.ToString()}{lineTerminator}";
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void Deserialize(string source, Encoding? encoding = null, string? lineTerminator = null)
|
|
{
|
|
encoding ??= Encoding.ASCII;
|
|
lineTerminator ??= Environment.NewLine;
|
|
Lines.Clear();
|
|
string[] lines = source.Split(lineTerminator);
|
|
foreach (var line in lines) {
|
|
Lines.Add(new SelectableLineBuffer(new LineBuffer(line, encoding)));
|
|
}
|
|
}
|
|
}
|