Skip to content

Commit 7588a76

Browse files
committed
Add text editor.
* Add TextCursor class. * Add cursor & selectedText painter. * Add hover text cursor. * Change TextShape factory to default height = 2. * Add startPoint cursor to TextChangeState.
1 parent 4d67df9 commit 7588a76

File tree

5 files changed

+141
-16
lines changed

5 files changed

+141
-16
lines changed

patterns/state/manipulator_state/states/_/paint_style.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
22

33
import '../../shapes/circle_shape.dart';
44
import '../../shapes/shape.dart';
5+
import '../../shapes/text_shape.dart';
6+
import '../selections/text_change_state.dart';
57

68
class PaintStyle {
79
PaintStyle(this.color)
@@ -60,6 +62,25 @@ class PaintStyle {
6062
canvas.restore();
6163
}
6264

65+
void paintSelectedText(TextShape selectedShape, Canvas canvas) {
66+
canvas.drawRect(
67+
selectedShape.rect,
68+
Paint()..color = color.withOpacity(0.3),
69+
);
70+
}
71+
72+
void paintTextCursor(
73+
TextCursor cursor, TextShape selectedShape, Canvas canvas) {
74+
canvas.drawRect(
75+
Rect.fromLTWH(
76+
cursor.xCoordinate,
77+
selectedShape.y + (selectedShape.height - selectedShape.userHeight),
78+
1.5,
79+
selectedShape.userHeight),
80+
Paint()..color = Colors.white,
81+
);
82+
}
83+
6384
final Paint _selectStroke;
6485
final Paint _markerStroke;
6586
final Paint _markerFill;

patterns/state/manipulator_state/states/creations/text_creation_state.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import '../_/creation_state.dart';
55
class TextCreationState extends CreationState {
66
@override
77
Shape createShape(double x, double y) {
8-
return TextShape(x, y, 2, 2);
8+
return TextShape(x, y, 2);
99
}
1010

1111
@override

patterns/state/manipulator_state/states/selections/text_change_state.dart

Lines changed: 111 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,135 @@ import '../../shapes/text_shape.dart';
55
import 'selection_state.dart';
66

77
class TextChangeState extends SelectionState<TextShape> {
8-
TextChangeState({required super.selectedShape});
8+
TextChangeState({
9+
required Offset startPointer,
10+
required super.selectedShape,
11+
}) : _startPointer = startPointer,
12+
_textCursor = TextCursor(selectedShape);
13+
14+
@override
15+
void init() {
16+
_textCursor.changePosition(_startPointer.dx, _startPointer.dy);
17+
context.cursor = SystemMouseCursors.text;
18+
context.update();
19+
}
920

1021
@override
1122
void mouseDown(double x, double y) {
12-
super.mouseDown(x, y);
1323
if (selectedShape.rect.contains(Offset(x, y))) {
14-
} else {}
24+
_textCursor.changePosition(x, y);
25+
context.update();
26+
return;
27+
}
28+
29+
super.mouseDown(x, y);
1530
}
1631

1732
@override
1833
void keyDown(KeyEvent keyEvent) {
19-
if ((keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) &&
20-
keyEvent.character != null) {
21-
print(keyEvent.character);
22-
selectedShape.text += keyEvent.character!;
23-
context.update();
34+
if (keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) {
35+
if (keyEvent.physicalKey == PhysicalKeyboardKey.backspace) {
36+
_textCursor.backspace();
37+
context.update();
38+
} else if (keyEvent.character != null) {
39+
_textCursor.inputText(keyEvent.character!);
40+
context.update();
41+
}
2442
}
2543
}
2644

2745
@override
2846
void paint(Canvas canvas) {
29-
canvas.drawRect(
30-
selectedShape.rect,
31-
Paint()..color = Colors.pink.withOpacity(0.3),
32-
);
47+
context.paintStyle.paintSelectedText(selectedShape, canvas);
3348
super.paint(canvas);
49+
context.paintStyle.paintTextCursor(_textCursor, selectedShape, canvas);
50+
}
51+
52+
@override
53+
void onHover() {
54+
if (hoverShape == selectedShape) {
55+
context.cursor = SystemMouseCursors.text;
56+
}
3457
}
3558

59+
@override
60+
void onMouseLeave() {
61+
context.cursor = SystemMouseCursors.basic;
62+
}
63+
64+
double xx0 = 0;
65+
int len = 0;
66+
final Offset _startPointer;
67+
final TextCursor _textCursor;
68+
3669
@override
3770
String toString() {
3871
return '${super.toString()} + Text Change State';
3972
}
4073
}
74+
75+
class TextCursor {
76+
TextCursor(this._shape);
77+
78+
double get xCoordinate => _xPosition;
79+
80+
void changePosition(double x, double y) {
81+
x = x - _shape.x;
82+
y = y - _shape.y;
83+
84+
final pos = _shape.paragraph.getPositionForOffset(Offset(x, y));
85+
_charIndex = pos.offset;
86+
87+
final range = _shape.paragraph.getBoxesForRange(
88+
pos.offset - 1,
89+
pos.offset,
90+
);
91+
92+
_xPosition = _shape.x;
93+
94+
if (range.isNotEmpty) {
95+
_xPosition += range.first.right;
96+
}
97+
}
98+
99+
String inputText(String char) {
100+
final start = _shape.text.substring(0, _charIndex);
101+
final end = _shape.text.substring(_charIndex);
102+
_shape.text = '$start$char$end';
103+
final range = _shape.paragraph.getBoxesForRange(_charIndex, ++_charIndex);
104+
_xPosition = _shape.x;
105+
106+
if (range.isNotEmpty) {
107+
_xPosition += range.first.right;
108+
}
109+
110+
return '$start$char$end';
111+
}
112+
113+
void backspace() {
114+
if (_charIndex <= 0) {
115+
return;
116+
}
117+
118+
final start = _shape.text.substring(0, _charIndex - 1);
119+
final end = _shape.text.length > start.length
120+
? _shape.text.substring(_charIndex)
121+
: '';
122+
123+
_shape.text = '$start$end';
124+
125+
final range = _shape.paragraph.getBoxesForRange(_charIndex - 1, _charIndex);
126+
_xPosition = _shape.x;
127+
128+
if (range.isNotEmpty) {
129+
_xPosition += range.first.left;
130+
} else {
131+
_xPosition += _shape.width;
132+
}
133+
_charIndex--;
134+
}
135+
136+
final TextShape _shape;
137+
int _charIndex = 0;
138+
double _xPosition = 0;
139+
}

patterns/state/manipulator_state/states/selections/text_resize_marker/text_resize_marker_state.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ class TextSizeMarkerState extends Marker<TextShape> {
88

99
@override
1010
void mouseDragAction(double x, double y) {
11-
final newHeight = y - selectedShape.y;
12-
selectedShape.resize(-1, newHeight);
11+
final newHeight =
12+
y - selectedShape.y - (selectedShape.height - selectedShape.userHeight);
13+
14+
selectedShape.resize(0, newHeight);
1315
}
1416

1517
@override

patterns/state/manipulator_state/states/selections/text_resize_state.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:ui';
2+
13
import '../../shapes/text_shape.dart';
24
import '../_/sub_states/parent_state.dart';
35
import 'text_change_state.dart';
@@ -11,9 +13,10 @@ class TextResizeState extends ParentState<TextShape> {
1113
}
1214

1315
@override
14-
void mouseDoubleClick() {
16+
void mouseDoubleClick(double x, double y) {
1517
context.changeState(
1618
TextChangeState(
19+
startPointer: Offset(x, y),
1720
selectedShape: selectedShape,
1821
),
1922
);

0 commit comments

Comments
 (0)