import 'dart:collection'; import 'package:flutter_quill/models/documents/style.dart'; import 'package:quill_delta/quill_delta.dart'; import '../attribute.dart'; import 'container.dart'; import 'line.dart'; /* node in a document tree */ abstract class Node extends LinkedListEntry { Container parent; Style _style = Style(); Style get style => _style; void applyAttribute(Attribute attribute) { _style = _style.merge(attribute); } void applyStyle(Style value) { if (value == null) { throw ArgumentError('null value'); } _style = _style.mergeAll(value); } void clearStyle() { _style = Style(); } bool get isFirst => list.first == this; bool get isLast => list.last == this; int get length; Node clone() { Node node = newInstance(); node.applyStyle(style); return node; } int getOffset() { int offset = 0; if (list == null || isFirst) { return offset; } Node cur = this; do { cur = cur.previous; offset += cur.length; } while (!cur.isFirst); return offset; } int getDocumentOffset() { final parentOffset = (parent is! Root) ? parent.getDocumentOffset() : 0; return parentOffset + getOffset(); } bool containsOffset(int offset) { final o = getDocumentOffset(); return o <= offset && offset < o + length; } @override void insertBefore(Node entry) { assert(entry.parent == null && parent != null); entry.parent = parent; super.insertBefore(entry); } @override void insertAfter(Node entry) { assert(entry.parent == null && parent != null); entry.parent = parent; super.insertAfter(entry); } @override void unlink() { assert(parent != null); parent = null; super.unlink(); } adjust() { // do nothing } /// abstract methods begin Node newInstance(); String toPlainText(); Delta toDelta(); insert(int index, Object data, Style style); retain(int index, int len, Style style); delete(int index, int len); /// abstract methods end } /* Root node of document tree */ class Root extends Container> { @override Container get defaultChild => Line(); @override Delta toDelta() => children .map((child) => child.toDelta()) .fold(Delta(), (a, b) => a.concat(b)); @override Node newInstance() { return Root(); } }