From 162711deafaaeb856db97dd9c9715cd15e946e27 Mon Sep 17 00:00:00 2001 From: singerdmx Date: Wed, 16 Dec 2020 02:45:39 -0800 Subject: [PATCH] Refactor Container --- lib/models/documents/nodes/block.dart | 14 +++++- lib/models/documents/nodes/container.dart | 53 +++++++++++++++++++++++ lib/models/documents/nodes/leaf.dart | 37 ++++++++++++++++ lib/models/documents/nodes/line.dart | 28 +++++++++++- lib/models/documents/nodes/node.dart | 44 +++++++++++++------ lib/models/documents/style.dart | 5 +++ 6 files changed, 165 insertions(+), 16 deletions(-) create mode 100644 lib/models/documents/nodes/container.dart diff --git a/lib/models/documents/nodes/block.dart b/lib/models/documents/nodes/block.dart index e0ba3ab8..cee0952b 100644 --- a/lib/models/documents/nodes/block.dart +++ b/lib/models/documents/nodes/block.dart @@ -1,6 +1,16 @@ +import 'package:quill_delta/quill_delta.dart'; + +import 'container.dart'; import 'line.dart'; -import 'node.dart'; class Block extends Container { + @override + Line get defaultChild => Line(); -} \ No newline at end of file + @override + Delta toDelta() { + return children + .map((child) => child.toDelta()) + .fold(Delta(), (a, b) => a.concat(b)); + } +} diff --git a/lib/models/documents/nodes/container.dart b/lib/models/documents/nodes/container.dart new file mode 100644 index 00000000..4940a889 --- /dev/null +++ b/lib/models/documents/nodes/container.dart @@ -0,0 +1,53 @@ +import 'dart:collection'; + +import 'node.dart'; + +/* Container of multiple nodes */ +abstract class Container extends Node { + final LinkedList _children = LinkedList(); + + LinkedList get children => _children; + + int get childCount => _children.length; + + Node get first => _children.first; + + Node get last => _children.last; + + bool get isEmpty => _children.isEmpty; + + bool get isNotEmpty => _children.isNotEmpty; + + /// abstract methods begin + + T get defaultChild; + + /// abstract methods end + + add(T node) { + assert(node.parent == null); + node.parent = this; + _children.add(node); + } + + addFirst(T node) { + assert(node.parent == null); + node.parent = this; + _children.addFirst(node); + } + + void remove(T node) { + assert(node.parent == this); + node.parent = null; + _children.remove(node); + } + + @override + String toPlainText() => children.map((child) => child.toPlainText()).join(); + + @override + int get length => _children.fold(0, (cur, node) => cur + node.length); + + @override + String toString() => _children.join('\n'); +} diff --git a/lib/models/documents/nodes/leaf.dart b/lib/models/documents/nodes/leaf.dart index 66ba27fd..08998bf1 100644 --- a/lib/models/documents/nodes/leaf.dart +++ b/lib/models/documents/nodes/leaf.dart @@ -1,5 +1,42 @@ +import 'package:quill_delta/quill_delta.dart'; + import 'node.dart'; /* A leaf node in document tree */ abstract class Leaf extends Node { + Object _value; + + Object get value => _value; + + Leaf.val(Object val) + : assert(val != null), + _value = val; + + @override + int get length { + if (_value is String) { + return (_value as String).length; + } + // return 1 for embedded object + return 1; + } + + @override + Delta toDelta() { + return null; // TODO + } +} + +class Text extends Leaf { + Text([String text = '']) + : assert(!text.contains('\n')), + super.val(text); + + @override + String get value => _value as String; + + @override + String toPlainText() { + return value; + } } diff --git a/lib/models/documents/nodes/line.dart b/lib/models/documents/nodes/line.dart index 78770b2d..1a9b1ce6 100644 --- a/lib/models/documents/nodes/line.dart +++ b/lib/models/documents/nodes/line.dart @@ -1,5 +1,31 @@ +import 'package:quill_delta/quill_delta.dart'; + +import 'block.dart'; +import 'container.dart'; import 'leaf.dart'; -import 'node.dart'; class Line extends Container { + + @override + Leaf get defaultChild => Text(); + + @override + int get length => super.length + 1; + + @override + Delta toDelta() { + final delta = children + .map((child) => child.toDelta()) + .fold(Delta(), (a, b) => a.concat(b)); + var attributes = style; + if (parent is Block) { + Block block = parent; + attributes = attributes.mergeAll(block.style); + } + delta.insert('\n', attributes.toJson()); + return delta; + } + + @override + String toPlainText() => super.toPlainText() + '\n'; } diff --git a/lib/models/documents/nodes/node.dart b/lib/models/documents/nodes/node.dart index 73d89dfd..c5c3e48b 100644 --- a/lib/models/documents/nodes/node.dart +++ b/lib/models/documents/nodes/node.dart @@ -1,18 +1,19 @@ 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 */ -class Node extends LinkedListEntry { - Container _parent; +abstract class Node extends LinkedListEntry { + Container parent; Style _style = Style(); Style get style => _style; - Container get parent => _parent; - void applyAttribute(Attribute attribute) { _style = _style.merge(attribute); } @@ -32,29 +33,46 @@ class Node extends LinkedListEntry { bool get isLast => list.last == this; + int get length; + @override void insertBefore(Node entry) { - assert(entry._parent == null && _parent != null); - entry._parent = _parent; + 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; + assert(entry.parent == null && parent != null); + entry.parent = parent; super.insertAfter(entry); } @override void unlink() { - assert(_parent != null); - _parent = null; + assert(parent != null); + parent = null; super.unlink(); } -} -abstract class Container extends Node {} + /// abstract methods begin + + String toPlainText(); + + Delta toDelta(); + + /// abstract methods end + +} /* Root node of document tree */ -class Root extends Container> {} +class Root extends Container> { + @override + Container get defaultChild => Line(); + + @override + Delta toDelta() => children + .map((child) => child.toDelta()) + .fold(Delta(), (a, b) => a.concat(b)); +} diff --git a/lib/models/documents/style.dart b/lib/models/documents/style.dart index d5e6944d..2453b011 100644 --- a/lib/models/documents/style.dart +++ b/lib/models/documents/style.dart @@ -20,6 +20,11 @@ class Style { return Style.attr(result); } + Map toJson() => _attributes.isEmpty + ? null + : _attributes.map((String _, Attribute value) => + MapEntry(value.key, value.value)); + Iterable get keys => _attributes.keys; Iterable get values => _attributes.values;