|
|
@@ -91,8 +91,8 @@ class _ImageEmbedState extends State<ImageEmbed> {
|
|
91
|
91
|
@override
|
|
92
|
92
|
Widget build(BuildContext context) {
|
|
93
|
93
|
return _EditableImage(
|
|
|
94
|
+ child: new RawImage(image: _imageInfo?.image),
|
|
94
|
95
|
node: widget.node,
|
|
95
|
|
- image: _imageInfo?.image,
|
|
96
|
96
|
);
|
|
97
|
97
|
}
|
|
98
|
98
|
|
|
|
@@ -112,15 +112,16 @@ class _ImageEmbedState extends State<ImageEmbed> {
|
|
112
|
112
|
}
|
|
113
|
113
|
}
|
|
114
|
114
|
|
|
115
|
|
-class _EditableImage extends LeafRenderObjectWidget {
|
|
116
|
|
- _EditableImage({@required this.node, this.image}) : assert(node != null);
|
|
|
115
|
+class _EditableImage extends SingleChildRenderObjectWidget {
|
|
|
116
|
+ _EditableImage({@required Widget child, @required this.node})
|
|
|
117
|
+ : assert(node != null),
|
|
|
118
|
+ super(child: child);
|
|
117
|
119
|
|
|
118
|
120
|
final EmbedNode node;
|
|
119
|
|
- final ui.Image image;
|
|
120
|
121
|
|
|
121
|
122
|
@override
|
|
122
|
123
|
RenderEditableImage createRenderObject(BuildContext context) {
|
|
123
|
|
- return new RenderEditableImage(node: node, image: image);
|
|
|
124
|
+ return new RenderEditableImage(node: node);
|
|
124
|
125
|
}
|
|
125
|
126
|
|
|
126
|
127
|
@override
|
|
|
@@ -130,14 +131,19 @@ class _EditableImage extends LeafRenderObjectWidget {
|
|
130
|
131
|
}
|
|
131
|
132
|
}
|
|
132
|
133
|
|
|
133
|
|
-class RenderEditableImage extends RenderImage implements RenderEditableBox {
|
|
|
134
|
+class RenderEditableImage extends RenderBox
|
|
|
135
|
+ with
|
|
|
136
|
+ RenderObjectWithChildMixin<RenderImage>,
|
|
|
137
|
+ RenderProxyBoxMixin<RenderImage>
|
|
|
138
|
+ implements RenderEditableBox {
|
|
|
139
|
+ static const kPaddingBottom = 24.0;
|
|
|
140
|
+
|
|
134
|
141
|
RenderEditableImage({
|
|
135
|
|
- ui.Image image,
|
|
|
142
|
+ RenderImage child,
|
|
136
|
143
|
@required EmbedNode node,
|
|
137
|
|
- }) : _node = node,
|
|
138
|
|
- super(
|
|
139
|
|
- image: image,
|
|
140
|
|
- );
|
|
|
144
|
+ }) : _node = node {
|
|
|
145
|
+ this.child = child;
|
|
|
146
|
+ }
|
|
141
|
147
|
|
|
142
|
148
|
@override
|
|
143
|
149
|
EmbedNode get node => _node;
|
|
|
@@ -150,7 +156,7 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
|
|
150
|
156
|
double get preferredLineHeight => size.height;
|
|
151
|
157
|
|
|
152
|
158
|
@override
|
|
153
|
|
- SelectionOrder get selectionOrder => SelectionOrder.foreground;
|
|
|
159
|
+ SelectionOrder get selectionOrder => SelectionOrder.background;
|
|
154
|
160
|
|
|
155
|
161
|
@override
|
|
156
|
162
|
TextSelection getLocalSelection(TextSelection documentSelection) {
|
|
|
@@ -165,24 +171,36 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
|
|
165
|
171
|
}
|
|
166
|
172
|
|
|
167
|
173
|
@override
|
|
168
|
|
- List<TextBox> getEndpointsForSelection(TextSelection selection) {
|
|
|
174
|
+ List<ui.TextBox> getEndpointsForSelection(TextSelection selection) {
|
|
169
|
175
|
TextSelection local = getLocalSelection(selection);
|
|
170
|
176
|
if (local.isCollapsed) {
|
|
|
177
|
+ final dx = local.extentOffset == 0 ? 0.0 : size.width;
|
|
171
|
178
|
return [
|
|
172
|
|
- new TextBox.fromLTRBD(0.0, 0.0, 0.0, size.height, TextDirection.ltr),
|
|
|
179
|
+ new ui.TextBox.fromLTRBD(dx, 0.0, dx, size.height, TextDirection.ltr),
|
|
173
|
180
|
];
|
|
174
|
181
|
}
|
|
175
|
182
|
|
|
176
|
183
|
return [
|
|
177
|
|
- new TextBox.fromLTRBD(0.0, 0.0, 0.0, size.height, TextDirection.ltr),
|
|
178
|
|
- new TextBox.fromLTRBD(
|
|
|
184
|
+ new ui.TextBox.fromLTRBD(0.0, 0.0, 0.0, size.height, TextDirection.ltr),
|
|
|
185
|
+ new ui.TextBox.fromLTRBD(
|
|
179
|
186
|
size.width, 0.0, size.width, size.height, TextDirection.ltr),
|
|
180
|
187
|
];
|
|
181
|
188
|
}
|
|
182
|
189
|
|
|
183
|
190
|
@override
|
|
184
|
191
|
TextPosition getPositionForOffset(Offset offset) {
|
|
185
|
|
- return new TextPosition(offset: node.documentOffset);
|
|
|
192
|
+ int position = _node.documentOffset;
|
|
|
193
|
+
|
|
|
194
|
+ if (offset.dx > size.width / 2) {
|
|
|
195
|
+ position++;
|
|
|
196
|
+ }
|
|
|
197
|
+ return new TextPosition(offset: position);
|
|
|
198
|
+ }
|
|
|
199
|
+
|
|
|
200
|
+ @override
|
|
|
201
|
+ TextRange getWordBoundary(TextPosition position) {
|
|
|
202
|
+ final start = _node.documentOffset;
|
|
|
203
|
+ return new TextRange(start: start, end: start + 1);
|
|
186
|
204
|
}
|
|
187
|
205
|
|
|
188
|
206
|
@override
|
|
|
@@ -193,13 +211,7 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
|
|
193
|
211
|
}
|
|
194
|
212
|
|
|
195
|
213
|
@override
|
|
196
|
|
- TextRange getWordBoundary(ui.TextPosition position) {
|
|
197
|
|
- return new TextRange(start: position.offset, end: position.offset + 1);
|
|
198
|
|
- }
|
|
199
|
|
-
|
|
200
|
|
- @override
|
|
201
|
|
- ui.Offset getOffsetForCaret(
|
|
202
|
|
- ui.TextPosition position, ui.Rect caretPrototype) {
|
|
|
214
|
+ Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
|
|
203
|
215
|
final pos = position.offset - node.documentOffset;
|
|
204
|
216
|
Offset caretOffset = Offset.zero;
|
|
205
|
217
|
if (pos == 1) {
|
|
|
@@ -211,6 +223,27 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
|
|
211
|
223
|
@override
|
|
212
|
224
|
void paintSelection(PaintingContext context, ui.Offset offset,
|
|
213
|
225
|
TextSelection selection, ui.Color selectionColor) {
|
|
214
|
|
- // TODO: implement paintSelection
|
|
|
226
|
+ final localSelection = getLocalSelection(selection);
|
|
|
227
|
+ assert(localSelection != null);
|
|
|
228
|
+ if (!localSelection.isCollapsed) {
|
|
|
229
|
+ final Paint paint = new Paint()..color = selectionColor;
|
|
|
230
|
+ final rect = new Rect.fromLTWH(0.0, 0.0, size.width, size.height);
|
|
|
231
|
+ context.canvas.drawRect(rect.shift(offset), paint);
|
|
|
232
|
+ }
|
|
|
233
|
+ }
|
|
|
234
|
+
|
|
|
235
|
+ @override
|
|
|
236
|
+ void performLayout() {
|
|
|
237
|
+ assert(constraints.hasBoundedWidth);
|
|
|
238
|
+ if (child != null) {
|
|
|
239
|
+ // Make constraints use 16:9 aspect ratio.
|
|
|
240
|
+ final childConstraints = constraints.copyWith(
|
|
|
241
|
+ maxHeight: (constraints.maxWidth * 9 / 16).floorToDouble(),
|
|
|
242
|
+ );
|
|
|
243
|
+ child.layout(childConstraints, parentUsesSize: true);
|
|
|
244
|
+ size = new Size(child.size.width, child.size.height + kPaddingBottom);
|
|
|
245
|
+ } else {
|
|
|
246
|
+ performResize();
|
|
|
247
|
+ }
|
|
215
|
248
|
}
|
|
216
|
249
|
}
|