From dc7b4e794fa725c2872d060832dbf621202426e2 Mon Sep 17 00:00:00 2001 From: singerdmx Date: Wed, 16 Dec 2020 23:44:38 -0800 Subject: [PATCH] Add cursor --- lib/models/documents/attribute.dart | 24 ++++----- lib/widgets/cursor.dart | 83 +++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 lib/widgets/cursor.dart diff --git a/lib/models/documents/attribute.dart b/lib/models/documents/attribute.dart index 1a936b4f..c4419816 100644 --- a/lib/models/documents/attribute.dart +++ b/lib/models/documents/attribute.dart @@ -1,5 +1,3 @@ -import 'package:quiver_hashcode/hashcode.dart'; - enum AttributeScope { INLINE, // refer to https://quilljs.com/docs/formats/#inline BLOCK, // refer to https://quilljs.com/docs/formats/#block @@ -71,21 +69,23 @@ class Attribute { return attribute; } + @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other is! Attribute) return false; - Attribute typedOther = other; - return key == typedOther.key && - scope == typedOther.scope && - value == typedOther.value; - } + bool operator ==(Object other) => + identical(this, other) || + other is Attribute && + runtimeType == other.runtimeType && + key == other.key && + scope == other.scope && + value == other.value; @override - int get hashCode => hash3(key, scope, value); + int get hashCode => key.hashCode ^ scope.hashCode ^ value.hashCode; @override - String toString() => '$key: $value'; + String toString() { + return 'Attribute{key: $key, scope: $scope, value: $value}'; + } } class BoldAttribute extends Attribute { diff --git a/lib/widgets/cursor.dart b/lib/widgets/cursor.dart new file mode 100644 index 00000000..481424b1 --- /dev/null +++ b/lib/widgets/cursor.dart @@ -0,0 +1,83 @@ +import 'package:flutter/widgets.dart'; + +const Duration _FADE_DURATION = Duration(milliseconds: 250); + +class CursorStyle { + final Color color; + final Color backgroundColor; + final double width; + final double height; + final Radius radius; + final Offset offset; + final bool opacityAnimates; + final bool paintAboveText; + + const CursorStyle({ + @required this.color, + @required this.backgroundColor, + this.width = 1.0, + this.height, + this.radius, + this.offset, + this.opacityAnimates = false, + this.paintAboveText = false, + }) : assert(color != null), + assert(backgroundColor != null), + assert(opacityAnimates != null), + assert(paintAboveText != null); + + @override + bool operator ==(Object other) => + identical(this, other) || + other is CursorStyle && + runtimeType == other.runtimeType && + color == other.color && + backgroundColor == other.backgroundColor && + width == other.width && + height == other.height && + radius == other.radius && + offset == other.offset && + opacityAnimates == other.opacityAnimates && + paintAboveText == other.paintAboveText; + + @override + int get hashCode => + color.hashCode ^ + backgroundColor.hashCode ^ + width.hashCode ^ + height.hashCode ^ + radius.hashCode ^ + offset.hashCode ^ + opacityAnimates.hashCode ^ + paintAboveText.hashCode; +} + +class CursorCont extends ChangeNotifier { + + final ValueNotifier show; + final ValueNotifier _blink; + final ValueNotifier _color; + AnimationController _blinkOpacityCont; + CursorStyle _style; + + CursorCont({ + @required ValueNotifier show, + @required CursorStyle style, + @required TickerProvider tickerProvider, + }) : assert(show != null), + assert(style != null), + assert(tickerProvider != null), + show = show ?? ValueNotifier(false), + _style = style, + _blink = ValueNotifier(false), + _color = ValueNotifier(style.color) { + _blinkOpacityCont = + AnimationController(vsync: tickerProvider, duration: _FADE_DURATION); + _blinkOpacityCont.addListener(_onColorTick); + } + + void _onColorTick() { + _color.value = _style.color.withOpacity(_blinkOpacityCont.value); + _blink.value = show.value && _blinkOpacityCont.value > 0; + } +}