Rich text editor for Flutter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

160 lines
4.6 KiB

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'box.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<bool> show;
final ValueNotifier<bool> _blink;
final ValueNotifier<Color> color;
AnimationController _blinkOpacityCont;
CursorStyle _style;
CursorCont({
@required ValueNotifier<bool> show,
@required CursorStyle style,
@required TickerProvider tickerProvider,
}) : assert(show != null),
assert(style != null),
assert(tickerProvider != null),
show = show ?? ValueNotifier<bool>(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;
}
}
class CursorPainter {
final RenderContentProxyBox editable;
final CursorStyle style;
final Rect prototype;
final Color color;
final double devicePixelRatio;
CursorPainter(this.editable, this.style, this.prototype, this.color,
this.devicePixelRatio);
paint(Canvas canvas, Offset offset, TextPosition position) {
assert(prototype != null);
Offset caretOffset =
editable.getOffsetForCaret(position, prototype) + offset;
Rect caretRect = prototype.shift(caretOffset);
if (style.offset != null) {
caretRect = caretRect.shift(style.offset);
}
if (caretRect.left < 0.0) {
caretRect = caretRect.shift(Offset(-caretRect.left, 0.0));
}
double caretHeight = editable.getFullHeightForCaret(position);
if (caretHeight != null) {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
caretRect = Rect.fromLTWH(
caretRect.left,
caretRect.top - 2.0,
caretRect.width,
caretHeight,
);
break;
case TargetPlatform.iOS:
case TargetPlatform.macOS:
caretRect = Rect.fromLTWH(
caretRect.left,
caretRect.top + (caretHeight - caretRect.height) / 2,
caretRect.width,
caretRect.height,
);
break;
default:
throw UnimplementedError();
}
}
Offset caretPosition = editable.localToGlobal(caretRect.topLeft);
double pixelMultiple = 1.0 / devicePixelRatio;
caretRect = caretRect.shift(Offset(
caretPosition.dx.isFinite
? (caretPosition.dx / pixelMultiple).round() * pixelMultiple -
caretPosition.dx
: caretPosition.dx,
caretPosition.dy.isFinite
? (caretPosition.dy / pixelMultiple).round() * pixelMultiple -
caretPosition.dy
: caretPosition.dy));
Paint paint = Paint()..color = color;
if (style.radius == null) {
canvas.drawRect(caretRect, paint);
return;
}
RRect caretRRect = RRect.fromRectAndRadius(caretRect, style.radius);
canvas.drawRRect(caretRRect, paint);
}
}