daydayup9 / theia_flutter

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

theia_flutter

用flutter实现的富文本编辑器

介绍

theia_flutter的目标是所见即所得的富文本编辑器(截至目前仅支持显示不支持编辑)。theia_flutter的总体设计是协议层基于slate;渲染层将节点一一对应到flutter widget,因此整个theia_flutter会包含很多个TextField;因为有很多TextField,交互层例如选区、光标等通过操作手势指定哪一个TextField进行操作,最后再拼装起来。

协议层

theia_flutter协议层基于slate,创建Thiea Widget时需要传入slate结构的document,例如:test.json

theia_flutter中定义的结构如下:

classDiagram
  class Node {
    Map~String, dynamic~ json
    build(BuildContext context)* WidgetNullable
    buildSpan(TextStyle? textStyle)* InlineSpanNullable
  }
  <<interface>> Node
  class ElementNode {
    Map~String, dynamic~ json
    String? key
    String? type
    List~Node~ children
    build(BuildContext context)* WidgetNullable
    buildSpan(TextStyle? textStyle)* InlineSpanNullable
  }
  <<abstract>> ElementNode
  class TextNode {
    String text
    Color? background
    ...
    buildSpan(TextStyle? textStyle) InlineSpan
  }
  class BlockNode {
    ...
    build(BuildContext context) Widget
  }
  class InlineNode {
    ...
    buildSpan(TextStyle? textStyle) InlineSpan
  }
  Node <|.. ElementNode
  Node <|.. TextNode
  ElementNode <|-- BlockNode
  ElementNode <|-- InlineNode
Loading

每一个document中的节点会被转化成Node

TextNode直接实现Node,没有type``children等属性,Widget? build(BuildContenxt)默认返回null

ElementNode同样实现Node,拥有type``children等属性

BlockNodeInlineNode继承ElementNode,例如paragraph是BlockNode,inline-code是InlineCode

这里遵循slate的规则:

A "block" element can only be siblings with other "block" elements. An "inline" node can be siblings with Text nodes or other "inline" elements.

满足slate的规则通常可以使渲染层有更好的可预测性

渲染层

渲染时Node可以被build为Widget或者InlineSpan,根据上述slate规则,BlockNode需要实现Widget build(BuildContext context)InlineNodeTextNode需要实现InlineSpan buildSpan({TextStyle? textStyle})。因此,InlineNodeTextNode的上层通常为TextField或者Text.rich

交互层

因为整个theia_flutter存在多个text相关widget,所以选区必须在所有text相关widget的上层处理。目前的设想是通过手势处理,当手势在哪一个widget上方就让哪一个widget处理,最后再讲结果拼接起来。在flutter 3.3.0版本,官方加入了SelectionArea,通过阅读源码了解到官方也是通过这样的思路实现的跨Widget选区,然而遗憾的是,TextField并没有支持SelectionArea(需要传入SelectionRegistrar)因此目前的处理方案是:在theia_flutter readonly=true 的时候,text由Text.rich实现,这样可以实现在只读时拥有选区功能,编辑功能稍后再做支持。

About


Languages

Language:Dart 53.2%Language:C++ 22.0%Language:CMake 19.1%Language:HTML 1.9%Language:C 1.5%Language:Swift 1.2%Language:Java 0.9%Language:Kotlin 0.1%Language:Objective-C 0.0%