Unverified Commit f646e26e authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

iOS Text Selection Menu Overflow (#54140)

Adds the ability for the iOS text selection menu to handle items that are too wide for the screen.
parent 57dd045c
......@@ -213,7 +213,7 @@ class _TextSelectionToolbarContainerRenderBox extends RenderProxyBox {
child.size.height,
));
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
childParentData.offset = Offset(
size.width - child.size.width,
0.0,
......@@ -223,7 +223,7 @@ class _TextSelectionToolbarContainerRenderBox extends RenderProxyBox {
// Paint at the offset set in the parent data.
@override
void paint(PaintingContext context, Offset offset) {
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
context.paintChild(child, childParentData.offset + offset);
}
......@@ -231,7 +231,7 @@ class _TextSelectionToolbarContainerRenderBox extends RenderProxyBox {
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
// The x, y parameters have the top left of the node's box as the origin.
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
return result.addWithPaintOffset(
offset: childParentData.offset,
position: position,
......@@ -244,14 +244,14 @@ class _TextSelectionToolbarContainerRenderBox extends RenderProxyBox {
@override
void setupParentData(RenderBox child) {
if (child.parentData is! _ToolbarParentData) {
child.parentData = _ToolbarParentData();
if (child.parentData is! ToolbarItemsParentData) {
child.parentData = ToolbarItemsParentData();
}
}
@override
void applyPaintTransform(RenderObject child, Matrix4 transform) {
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
transform.translate(childParentData.offset.dx, childParentData.offset.dy);
super.applyPaintTransform(child, transform);
}
......@@ -292,24 +292,13 @@ class _TextSelectionToolbarItems extends MultiChildRenderObjectWidget {
_TextSelectionToolbarItemsElement createElement() => _TextSelectionToolbarItemsElement(this);
}
class _ToolbarParentData extends ContainerBoxParentData<RenderBox> {
/// Whether or not this child is painted.
///
/// Children in the selection toolbar may be laid out for measurement purposes
/// but not painted. This allows these children to be identified.
bool shouldPaint;
@override
String toString() => '${super.toString()}; shouldPaint=$shouldPaint';
}
class _TextSelectionToolbarItemsElement extends MultiChildRenderObjectElement {
_TextSelectionToolbarItemsElement(
MultiChildRenderObjectWidget widget,
) : super(widget);
static bool _shouldPaint(Element child) {
return (child.renderObject.parentData as _ToolbarParentData).shouldPaint;
return (child.renderObject.parentData as ToolbarItemsParentData).shouldPaint;
}
@override
......@@ -318,7 +307,7 @@ class _TextSelectionToolbarItemsElement extends MultiChildRenderObjectElement {
}
}
class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRenderObjectMixin<RenderBox, _ToolbarParentData> {
class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRenderObjectMixin<RenderBox, ToolbarItemsParentData> {
_TextSelectionToolbarItemsRenderBox({
@required bool isAbove,
@required bool overflowOpen,
......@@ -425,7 +414,7 @@ class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRender
i++;
final RenderBox child = renderObjectChild as RenderBox;
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
// Handle placing the navigation button after iterating all children.
if (renderObjectChild == navButton) {
......@@ -457,7 +446,7 @@ class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRender
});
// Place the navigation button if needed.
final _ToolbarParentData navButtonParentData = navButton.parentData as _ToolbarParentData;
final ToolbarItemsParentData navButtonParentData = navButton.parentData as ToolbarItemsParentData;
if (_shouldPaintChild(firstChild, 0)) {
navButtonParentData.shouldPaint = true;
if (overflowOpen) {
......@@ -495,7 +484,7 @@ class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRender
void paint(PaintingContext context, Offset offset) {
visitChildren((RenderObject renderObjectChild) {
final RenderBox child = renderObjectChild as RenderBox;
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
if (!childParentData.shouldPaint) {
return;
}
......@@ -506,8 +495,8 @@ class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRender
@override
void setupParentData(RenderBox child) {
if (child.parentData is! _ToolbarParentData) {
child.parentData = _ToolbarParentData();
if (child.parentData is! ToolbarItemsParentData) {
child.parentData = ToolbarItemsParentData();
}
}
......@@ -516,7 +505,7 @@ class _TextSelectionToolbarItemsRenderBox extends RenderBox with ContainerRender
// The x, y parameters have the top left of the node's box as the origin.
RenderBox child = lastChild;
while (child != null) {
final _ToolbarParentData childParentData = child.parentData as _ToolbarParentData;
final ToolbarItemsParentData childParentData = child.parentData as ToolbarItemsParentData;
// Don't hit test children aren't shown.
if (!childParentData.shouldPaint) {
......
......@@ -85,6 +85,22 @@ typedef TextSelectionOverlayChanged = void Function(TextEditingValue value, Rect
/// having to store the start position.
typedef DragSelectionUpdateCallback = void Function(DragStartDetails startDetails, DragUpdateDetails updateDetails);
/// ParentData that determines whether or not to paint the corresponding child.
///
/// Used in the layout of the Cupertino and Material text selection menus, which
/// decide whether or not to paint their buttons after laying them out and
/// determining where they overflow.
class ToolbarItemsParentData extends ContainerBoxParentData<RenderBox> {
/// Whether or not this child is painted.
///
/// Children in the selection toolbar may be laid out for measurement purposes
/// but not painted. This allows these children to be identified.
bool shouldPaint = false;
@override
String toString() => '${super.toString()}; shouldPaint=$shouldPaint';
}
/// An interface for building the selection UI, to be provided by the
/// implementor of the toolbar widget.
///
......
......@@ -17,8 +17,8 @@ import 'package:flutter/gestures.dart' show DragStartBehavior, PointerDeviceKind
import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';
import '../widgets/text.dart' show findRenderEditable, globalize, textOffsetToPosition;
import 'feedback_tester.dart';
import 'text.dart' show findRenderEditable, globalize, textOffsetToPosition;
class MockClipboard {
Object _clipboardData = <String, dynamic>{
......
......@@ -6,7 +6,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'text.dart' show findRenderEditable, globalize, textOffsetToPosition;
import '../widgets/text.dart' show findRenderEditable, globalize, textOffsetToPosition;
void main() {
group('canSelectAll', () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment