123 lines
3.3 KiB
Dart
123 lines
3.3 KiB
Dart
|
import 'package:flutter/material.dart';
|
||
|
|
||
|
import 'cursor.dart';
|
||
|
import 'line_info.dart';
|
||
|
|
||
|
class CursorProvider extends ChangeNotifier {
|
||
|
Cursor cursor = Cursor(line: 1, column: 0);
|
||
|
bool inMouseSelection = false;
|
||
|
|
||
|
int get line => cursor.line;
|
||
|
int get column => cursor.column;
|
||
|
|
||
|
void publishCursor(List<LineInfo> elements) {
|
||
|
var ncursor = cursor.normalized();
|
||
|
elements.forEach((element) {
|
||
|
element.setCursor(ncursor);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void moveCursorToDocStart() {
|
||
|
clearSelection();
|
||
|
cursor.line = 0;
|
||
|
cursor.column = 0;
|
||
|
cursor = cursor.normalized();
|
||
|
notifyListeners();
|
||
|
}
|
||
|
|
||
|
void moveCursorToLineStart() {
|
||
|
cursor.column = 0;
|
||
|
notifyListeners();
|
||
|
}
|
||
|
|
||
|
void clearSelection() {
|
||
|
inMouseSelection = false;
|
||
|
cursor.anchorLine = cursor.line;
|
||
|
cursor.anchorColumn = cursor.column;
|
||
|
notifyListeners();
|
||
|
}
|
||
|
|
||
|
void moveCursorToLineEnd(int lineLength) {
|
||
|
cursor.column = lineLength;
|
||
|
notifyListeners();
|
||
|
}
|
||
|
|
||
|
void moveCursor(int dx, int dy, List<LineInfo> backingLines, {bool keepAnchor = false}) {
|
||
|
//print(cursor.line.toString() + " " + cursor.column.toString() + " " + dx.toString() + " " + dy.toString() + " " + backingLines[cursor.line - 1].text.length.toString());
|
||
|
|
||
|
if (dx != 0) {
|
||
|
if (cursor.column + dx < 0) {
|
||
|
moveCursor(0, -1, backingLines, keepAnchor: keepAnchor);
|
||
|
if (cursor.line > 1) {
|
||
|
moveCursorToLineEnd(backingLines[cursor.line - 1].text.length);
|
||
|
}
|
||
|
} else if (cursor.column + dx > backingLines[cursor.line - 1].text.length) {
|
||
|
moveCursor(0, 1, backingLines, keepAnchor: keepAnchor);
|
||
|
moveCursorToLineStart();
|
||
|
} else {
|
||
|
cursor.column += dx;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dy != 0) {
|
||
|
// Only allow the cursor line to change if in bounds
|
||
|
if (cursor.line + dy > 0 && cursor.line + dy <= backingLines.length) {
|
||
|
cursor.line += dy;
|
||
|
// Change cursor to line end
|
||
|
if (cursor.column > backingLines[cursor.line - 1].text.length) {
|
||
|
moveCursorToLineEnd(backingLines[cursor.line - 1].text.length);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!keepAnchor) {
|
||
|
clearSelection();
|
||
|
}
|
||
|
|
||
|
notifyListeners();
|
||
|
}
|
||
|
|
||
|
void mouseDownEnd() {
|
||
|
inMouseSelection = false;
|
||
|
}
|
||
|
|
||
|
void mouseDownMoveUpdate(int col, List<LineInfo> backingLines) {
|
||
|
if (cursor.column != col) {
|
||
|
var lineLength = backingLines[cursor.line - 1].text.length;
|
||
|
cursor.column = col.clamp(0, lineLength);
|
||
|
if (inMouseSelection == false) {
|
||
|
clearSelection();
|
||
|
}
|
||
|
publishCursor(backingLines);
|
||
|
} else if (inMouseSelection == false) {
|
||
|
clearSelection();
|
||
|
publishCursor(backingLines);
|
||
|
}
|
||
|
inMouseSelection = true;
|
||
|
}
|
||
|
|
||
|
void mouseDownUpdate(int line, int col, List<LineInfo> backingLines) {
|
||
|
if (cursor.line != line || cursor.column != col) {
|
||
|
cursor.line = line;
|
||
|
var lineLength = backingLines[cursor.line - 1].text.length;
|
||
|
cursor.column = col.clamp(0, lineLength);
|
||
|
if (inMouseSelection == false) {
|
||
|
clearSelection();
|
||
|
}
|
||
|
publishCursor(backingLines);
|
||
|
} else if (inMouseSelection == false) {
|
||
|
clearSelection();
|
||
|
publishCursor(backingLines);
|
||
|
}
|
||
|
inMouseSelection = true;
|
||
|
}
|
||
|
|
||
|
bool hasSelection() {
|
||
|
return cursor.hasSelection();
|
||
|
}
|
||
|
|
||
|
Cursor normalized() {
|
||
|
return cursor.normalized();
|
||
|
}
|
||
|
}
|