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 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); } else { MoveCursor(0, -count); CurrentLineBuffer.Delete(CursorColumn, count); } } else { if (CursorColumn + count > CurrentLineBuffer.Tail && CursorLine < Lines.Count - 1) { CurrentLineBuffer.Insert( CurrentLineBuffer.Tail, Lines[CursorLine + 1].Slice(0)); Lines.RemoveAt(CursorLine + 1); } 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 }