Skip to content

Commit

Permalink
Prevent toolbar from leaving editor (#336)
Browse files Browse the repository at this point in the history
* Prevent toolbar from leaving editor
  • Loading branch information
amantoux authored May 6, 2024
1 parent 428bf54 commit 491642c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 10 deletions.
4 changes: 2 additions & 2 deletions packages/fleather/lib/src/rendering/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class RenderEditor extends RenderEditableContainerBox
markNeedsSemanticsUpdate();
}

Offset get _paintOffset => Offset(0.0, -(offset?.pixels ?? 0.0));
Offset get paintOffset => Offset(0.0, -(offset?.pixels ?? 0.0));

ViewportOffset? get offset => _offset;
ViewportOffset? _offset;
Expand Down Expand Up @@ -633,7 +633,7 @@ class RenderEditor extends RenderEditableContainerBox
_paintFloatingCursor(context, offset);
}
defaultPaint(context, offset);
_updateSelectionExtentsVisibility(offset + _paintOffset);
_updateSelectionExtentsVisibility(offset + paintOffset);
_paintHandleLayers(context, getEndpointsForSelection(selection));

if (hasFocus &&
Expand Down
28 changes: 20 additions & 8 deletions packages/fleather/lib/src/widgets/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2025,21 +2025,24 @@ class RawEditorState extends EditorState
final smallestLineHeight = math.min(baseLineHeight, extentLineHeight);

return _textSelectionToolbarAnchorsFromSelection(
renderEditor: renderEditor,
startGlyphHeight: smallestLineHeight,
endGlyphHeight: smallestLineHeight,
selectionEndpoints: endpoints);
}

TextSelectionToolbarAnchors _textSelectionToolbarAnchorsFromSelection({
required RenderEditor renderEditor,
required double startGlyphHeight,
required double endGlyphHeight,
required List<TextSelectionPoint> selectionEndpoints,
}) {
// If editor is scrollable, the editing region is only the viewport
// otherwise use editor as editing region
final viewport = RenderAbstractViewport.maybeOf(renderEditor);
final visualSizeRenderer = (viewport ?? renderEditor) as RenderBox;
final Rect editingRegion = Rect.fromPoints(
renderEditor.localToGlobal(Offset.zero),
renderEditor.localToGlobal(renderEditor.size.bottomRight(Offset.zero)),
visualSizeRenderer.localToGlobal(Offset.zero),
visualSizeRenderer
.localToGlobal(visualSizeRenderer.size.bottomRight(Offset.zero)),
);

if (editingRegion.left.isNaN ||
Expand All @@ -2056,12 +2059,21 @@ class RawEditorState extends EditorState
final Rect selectionRect = Rect.fromLTRB(
isMultiline
? editingRegion.left
: editingRegion.left + selectionEndpoints.first.point.dx,
editingRegion.top + selectionEndpoints.first.point.dy - startGlyphHeight,
: editingRegion.left +
selectionEndpoints.first.point.dx +
renderEditor.paintOffset.dx,
editingRegion.top +
selectionEndpoints.first.point.dy +
renderEditor.paintOffset.dy -
startGlyphHeight,
isMultiline
? editingRegion.right
: editingRegion.left + selectionEndpoints.last.point.dx,
editingRegion.top + selectionEndpoints.last.point.dy,
: editingRegion.left +
selectionEndpoints.last.point.dx +
renderEditor.paintOffset.dx,
editingRegion.top +
selectionEndpoints.last.point.dy +
renderEditor.paintOffset.dy,
);

return TextSelectionToolbarAnchors(
Expand Down
42 changes: 42 additions & 0 deletions packages/fleather/test/widgets/editor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,48 @@ void main() {
tester.view.viewInsets = FakeViewPadding.zero;
});

testWidgets('Keep selectiontoolbar with editor bounds', (tester) async {
final delta = Delta();
for (int i = 0; i < 30; i++) {
delta.insert('Test\n');
}
final scrollController = ScrollController();
final controller =
FleatherController(document: ParchmentDocument.fromDelta(delta));
final editor = MaterialApp(
home: Scaffold(
body: Column(
children: [
const SizedBox(width: 300, height: 150),
Expanded(
child: FleatherEditor(
controller: controller,
scrollController: scrollController,
),
),
],
),
),
);
await tester.pumpWidget(editor);
// Double tap to show toolbar
await tester.tapAt(
tester.getTopLeft(find.byType(RawEditor)) + const Offset(1, 1));
await tester.tapAt(
tester.getTopLeft(find.byType(RawEditor)) + const Offset(1, 1));
await tester.pumpAndSettle();
expect(find.byType(TextSelectionToolbar), findsOneWidget);
// Scroll extent is > 500, toolbar position should be around -400 if not
// capped
scrollController.jumpTo(scrollController.position.maxScrollExtent);
await tester.pumpAndSettle();
final renderToolbarTextButton =
tester.renderObject(find.byType(TextSelectionToolbarTextButton).first)
as RenderBox;
final toolbarTop = renderToolbarTextButton.localToGlobal(Offset.zero);
expect(toolbarTop.dy, greaterThan(90));
});

testWidgets('allows merging attribute theme data', (tester) async {
var delta = Delta()
..insert(
Expand Down

0 comments on commit 491642c

Please sign in to comment.