This reverts commit c74a646b7bba1641d0b2b29f6024dc867844e94c.
This commit is contained in:
parent
bf98767e8e
commit
64d9ea60b1
@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@ -49,15 +48,15 @@ class _CupertinoDesktopTextSelectionControls extends TextSelectionControls {
|
|||||||
Offset selectionMidpoint,
|
Offset selectionMidpoint,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
return _CupertinoDesktopTextSelectionControlsToolbar(
|
return _CupertinoDesktopTextSelectionControlsToolbar(
|
||||||
clipboardStatus: clipboardStatus,
|
clipboardStatus: clipboardStatus,
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
globalEditableRegion: globalEditableRegion,
|
globalEditableRegion: globalEditableRegion,
|
||||||
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
|
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
|
||||||
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
|
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
|
||||||
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
||||||
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
||||||
selectionMidpoint: selectionMidpoint,
|
selectionMidpoint: selectionMidpoint,
|
||||||
@ -99,7 +98,7 @@ class _CupertinoDesktopTextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
required this.lastSecondaryTapDownPosition,
|
required this.lastSecondaryTapDownPosition,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final ValueListenable<ClipboardStatus>? clipboardStatus;
|
final ClipboardStatusNotifier? clipboardStatus;
|
||||||
final List<TextSelectionPoint> endpoints;
|
final List<TextSelectionPoint> endpoints;
|
||||||
final Rect globalEditableRegion;
|
final Rect globalEditableRegion;
|
||||||
final VoidCallback? handleCopy;
|
final VoidCallback? handleCopy;
|
||||||
@ -115,6 +114,8 @@ class _CupertinoDesktopTextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_CupertinoDesktopTextSelectionControlsToolbar> {
|
class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_CupertinoDesktopTextSelectionControlsToolbar> {
|
||||||
|
ClipboardStatusNotifier? _clipboardStatus;
|
||||||
|
|
||||||
void _onChangedClipboardStatus() {
|
void _onChangedClipboardStatus() {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Inform the widget that the value of clipboardStatus has changed.
|
// Inform the widget that the value of clipboardStatus has changed.
|
||||||
@ -124,28 +125,46 @@ class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_Cupertin
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
if (widget.handlePaste != null) {
|
||||||
|
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
|
||||||
|
_clipboardStatus!.addListener(_onChangedClipboardStatus);
|
||||||
|
_clipboardStatus!.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(_CupertinoDesktopTextSelectionControlsToolbar oldWidget) {
|
void didUpdateWidget(_CupertinoDesktopTextSelectionControlsToolbar oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
|
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
|
||||||
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
if (_clipboardStatus != null) {
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
|
||||||
|
_clipboardStatus!.dispose();
|
||||||
|
}
|
||||||
|
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
|
||||||
|
_clipboardStatus!.addListener(_onChangedClipboardStatus);
|
||||||
|
if (widget.handlePaste != null) {
|
||||||
|
_clipboardStatus!.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
// When used in an Overlay, this can be disposed after its creator has
|
||||||
|
// already disposed _clipboardStatus.
|
||||||
|
if (_clipboardStatus != null && !_clipboardStatus!.disposed) {
|
||||||
|
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
|
||||||
|
if (widget.clipboardStatus == null) {
|
||||||
|
_clipboardStatus!.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Don't render the menu until the state of the clipboard is known.
|
// Don't render the menu until the state of the clipboard is known.
|
||||||
if (widget.handlePaste != null && widget.clipboardStatus?.value == ClipboardStatus.unknown) {
|
if (widget.handlePaste != null && _clipboardStatus!.value == ClipboardStatus.unknown) {
|
||||||
return const SizedBox(width: 0.0, height: 0.0);
|
return const SizedBox(width: 0.0, height: 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +206,7 @@ class _CupertinoDesktopTextSelectionControlsToolbarState extends State<_Cupertin
|
|||||||
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
|
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
|
||||||
}
|
}
|
||||||
if (widget.handlePaste != null
|
if (widget.handlePaste != null
|
||||||
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable) {
|
&& _clipboardStatus!.value == ClipboardStatus.pasteable) {
|
||||||
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
|
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
|
||||||
}
|
}
|
||||||
if (widget.handleSelectAll != null) {
|
if (widget.handleSelectAll != null) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ class _CupertinoTextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
required this.textLineHeight,
|
required this.textLineHeight,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final ValueListenable<ClipboardStatus>? clipboardStatus;
|
final ClipboardStatusNotifier? clipboardStatus;
|
||||||
final List<TextSelectionPoint> endpoints;
|
final List<TextSelectionPoint> endpoints;
|
||||||
final Rect globalEditableRegion;
|
final Rect globalEditableRegion;
|
||||||
final VoidCallback? handleCopy;
|
final VoidCallback? handleCopy;
|
||||||
@ -53,6 +52,8 @@ class _CupertinoTextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSelectionControlsToolbar> {
|
class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSelectionControlsToolbar> {
|
||||||
|
ClipboardStatusNotifier? _clipboardStatus;
|
||||||
|
|
||||||
void _onChangedClipboardStatus() {
|
void _onChangedClipboardStatus() {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Inform the widget that the value of clipboardStatus has changed.
|
// Inform the widget that the value of clipboardStatus has changed.
|
||||||
@ -62,28 +63,47 @@ class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSe
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
if (widget.handlePaste != null) {
|
||||||
|
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
|
||||||
|
_clipboardStatus!.addListener(_onChangedClipboardStatus);
|
||||||
|
_clipboardStatus!.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(_CupertinoTextSelectionControlsToolbar oldWidget) {
|
void didUpdateWidget(_CupertinoTextSelectionControlsToolbar oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
|
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
|
||||||
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
if (_clipboardStatus != null) {
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
|
||||||
|
_clipboardStatus!.dispose();
|
||||||
|
}
|
||||||
|
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
|
||||||
|
_clipboardStatus!.addListener(_onChangedClipboardStatus);
|
||||||
|
if (widget.handlePaste != null) {
|
||||||
|
_clipboardStatus!.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
// When used in an Overlay, this can be disposed after its creator has
|
||||||
|
// already disposed _clipboardStatus.
|
||||||
|
if (_clipboardStatus != null && !_clipboardStatus!.disposed) {
|
||||||
|
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
|
||||||
|
if (widget.clipboardStatus == null) {
|
||||||
|
_clipboardStatus!.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Don't render the menu until the state of the clipboard is known.
|
// Don't render the menu until the state of the clipboard is known.
|
||||||
if (widget.handlePaste != null && widget.clipboardStatus?.value == ClipboardStatus.unknown) {
|
if (widget.handlePaste != null
|
||||||
|
&& _clipboardStatus!.value == ClipboardStatus.unknown) {
|
||||||
return const SizedBox(width: 0.0, height: 0.0);
|
return const SizedBox(width: 0.0, height: 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +157,7 @@ class _CupertinoTextSelectionControlsToolbarState extends State<_CupertinoTextSe
|
|||||||
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
|
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
|
||||||
}
|
}
|
||||||
if (widget.handlePaste != null
|
if (widget.handlePaste != null
|
||||||
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable) {
|
&& _clipboardStatus!.value == ClipboardStatus.pasteable) {
|
||||||
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
|
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
|
||||||
}
|
}
|
||||||
if (widget.handleSelectAll != null) {
|
if (widget.handleSelectAll != null) {
|
||||||
@ -209,15 +229,15 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
|
|||||||
Offset selectionMidpoint,
|
Offset selectionMidpoint,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
return _CupertinoTextSelectionControlsToolbar(
|
return _CupertinoTextSelectionControlsToolbar(
|
||||||
clipboardStatus: clipboardStatus,
|
clipboardStatus: clipboardStatus,
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
globalEditableRegion: globalEditableRegion,
|
globalEditableRegion: globalEditableRegion,
|
||||||
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
|
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
|
||||||
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
|
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
|
||||||
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
||||||
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
||||||
selectionMidpoint: selectionMidpoint,
|
selectionMidpoint: selectionMidpoint,
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@ -35,15 +34,15 @@ class _DesktopTextSelectionControls extends TextSelectionControls {
|
|||||||
Offset selectionMidpoint,
|
Offset selectionMidpoint,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
return _DesktopTextSelectionControlsToolbar(
|
return _DesktopTextSelectionControlsToolbar(
|
||||||
clipboardStatus: clipboardStatus,
|
clipboardStatus: clipboardStatus,
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
globalEditableRegion: globalEditableRegion,
|
globalEditableRegion: globalEditableRegion,
|
||||||
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
|
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
|
||||||
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
|
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
|
||||||
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
||||||
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
||||||
selectionMidpoint: selectionMidpoint,
|
selectionMidpoint: selectionMidpoint,
|
||||||
@ -95,7 +94,7 @@ class _DesktopTextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
required this.lastSecondaryTapDownPosition,
|
required this.lastSecondaryTapDownPosition,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final ValueListenable<ClipboardStatus>? clipboardStatus;
|
final ClipboardStatusNotifier? clipboardStatus;
|
||||||
final List<TextSelectionPoint> endpoints;
|
final List<TextSelectionPoint> endpoints;
|
||||||
final Rect globalEditableRegion;
|
final Rect globalEditableRegion;
|
||||||
final VoidCallback? handleCopy;
|
final VoidCallback? handleCopy;
|
||||||
@ -111,6 +110,8 @@ class _DesktopTextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelectionControlsToolbar> {
|
class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelectionControlsToolbar> {
|
||||||
|
ClipboardStatusNotifier? _clipboardStatus;
|
||||||
|
|
||||||
void _onChangedClipboardStatus() {
|
void _onChangedClipboardStatus() {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Inform the widget that the value of clipboardStatus has changed.
|
// Inform the widget that the value of clipboardStatus has changed.
|
||||||
@ -120,28 +121,46 @@ class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelect
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
if (widget.handlePaste != null) {
|
||||||
|
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
|
||||||
|
_clipboardStatus!.addListener(_onChangedClipboardStatus);
|
||||||
|
_clipboardStatus!.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(_DesktopTextSelectionControlsToolbar oldWidget) {
|
void didUpdateWidget(_DesktopTextSelectionControlsToolbar oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
|
if (oldWidget.clipboardStatus != widget.clipboardStatus) {
|
||||||
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
if (_clipboardStatus != null) {
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
|
||||||
|
_clipboardStatus!.dispose();
|
||||||
|
}
|
||||||
|
_clipboardStatus = widget.clipboardStatus ?? ClipboardStatusNotifier();
|
||||||
|
_clipboardStatus!.addListener(_onChangedClipboardStatus);
|
||||||
|
if (widget.handlePaste != null) {
|
||||||
|
_clipboardStatus!.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
// When used in an Overlay, this can be disposed after its creator has
|
||||||
|
// already disposed _clipboardStatus.
|
||||||
|
if (_clipboardStatus != null && !_clipboardStatus!.disposed) {
|
||||||
|
_clipboardStatus!.removeListener(_onChangedClipboardStatus);
|
||||||
|
if (widget.clipboardStatus == null) {
|
||||||
|
_clipboardStatus!.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Don't render the menu until the state of the clipboard is known.
|
// Don't render the menu until the state of the clipboard is known.
|
||||||
if (widget.handlePaste != null && widget.clipboardStatus?.value == ClipboardStatus.unknown) {
|
if (widget.handlePaste != null && _clipboardStatus!.value == ClipboardStatus.unknown) {
|
||||||
return const SizedBox(width: 0.0, height: 0.0);
|
return const SizedBox(width: 0.0, height: 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +197,7 @@ class _DesktopTextSelectionControlsToolbarState extends State<_DesktopTextSelect
|
|||||||
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
|
addToolbarButton(localizations.copyButtonLabel, widget.handleCopy!);
|
||||||
}
|
}
|
||||||
if (widget.handlePaste != null
|
if (widget.handlePaste != null
|
||||||
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable) {
|
&& _clipboardStatus!.value == ClipboardStatus.pasteable) {
|
||||||
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
|
addToolbarButton(localizations.pasteButtonLabel, widget.handlePaste!);
|
||||||
}
|
}
|
||||||
if (widget.handleSelectAll != null) {
|
if (widget.handleSelectAll != null) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ class MaterialTextSelectionControls extends TextSelectionControls {
|
|||||||
Offset selectionMidpoint,
|
Offset selectionMidpoint,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
return _TextSelectionControlsToolbar(
|
return _TextSelectionControlsToolbar(
|
||||||
@ -46,8 +45,8 @@ class MaterialTextSelectionControls extends TextSelectionControls {
|
|||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
delegate: delegate,
|
delegate: delegate,
|
||||||
clipboardStatus: clipboardStatus,
|
clipboardStatus: clipboardStatus,
|
||||||
handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
|
handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
|
||||||
handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null,
|
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
|
||||||
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
|
||||||
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
|
||||||
);
|
);
|
||||||
@ -144,7 +143,7 @@ class _TextSelectionControlsToolbar extends StatefulWidget {
|
|||||||
required this.textLineHeight,
|
required this.textLineHeight,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final ValueListenable<ClipboardStatus>? clipboardStatus;
|
final ClipboardStatusNotifier clipboardStatus;
|
||||||
final TextSelectionDelegate delegate;
|
final TextSelectionDelegate delegate;
|
||||||
final List<TextSelectionPoint> endpoints;
|
final List<TextSelectionPoint> endpoints;
|
||||||
final Rect globalEditableRegion;
|
final Rect globalEditableRegion;
|
||||||
@ -169,22 +168,28 @@ class _TextSelectionControlsToolbarState extends State<_TextSelectionControlsToo
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
|
||||||
|
widget.clipboardStatus.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(_TextSelectionControlsToolbar oldWidget) {
|
void didUpdateWidget(_TextSelectionControlsToolbar oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.clipboardStatus != oldWidget.clipboardStatus) {
|
if (widget.clipboardStatus != oldWidget.clipboardStatus) {
|
||||||
widget.clipboardStatus?.addListener(_onChangedClipboardStatus);
|
widget.clipboardStatus.addListener(_onChangedClipboardStatus);
|
||||||
oldWidget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
oldWidget.clipboardStatus.removeListener(_onChangedClipboardStatus);
|
||||||
}
|
}
|
||||||
|
widget.clipboardStatus.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
widget.clipboardStatus?.removeListener(_onChangedClipboardStatus);
|
// When used in an Overlay, it can happen that this is disposed after its
|
||||||
|
// creator has already disposed _clipboardStatus.
|
||||||
|
if (!widget.clipboardStatus.disposed) {
|
||||||
|
widget.clipboardStatus.removeListener(_onChangedClipboardStatus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -197,7 +202,7 @@ class _TextSelectionControlsToolbarState extends State<_TextSelectionControlsToo
|
|||||||
// If the paste button is desired, don't render anything until the state of
|
// If the paste button is desired, don't render anything until the state of
|
||||||
// the clipboard is known, since it's used to determine if paste is shown.
|
// the clipboard is known, since it's used to determine if paste is shown.
|
||||||
if (widget.handlePaste != null
|
if (widget.handlePaste != null
|
||||||
&& widget.clipboardStatus?.value == ClipboardStatus.unknown) {
|
&& widget.clipboardStatus.value == ClipboardStatus.unknown) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +238,7 @@ class _TextSelectionControlsToolbarState extends State<_TextSelectionControlsToo
|
|||||||
onPressed: widget.handleCopy!,
|
onPressed: widget.handleCopy!,
|
||||||
),
|
),
|
||||||
if (widget.handlePaste != null
|
if (widget.handlePaste != null
|
||||||
&& widget.clipboardStatus?.value == ClipboardStatus.pasteable)
|
&& widget.clipboardStatus.value == ClipboardStatus.pasteable)
|
||||||
_TextSelectionToolbarItemData(
|
_TextSelectionToolbarItemData(
|
||||||
label: localizations.pasteButtonLabel,
|
label: localizations.pasteButtonLabel,
|
||||||
onPressed: widget.handlePaste!,
|
onPressed: widget.handlePaste!,
|
||||||
|
@ -1671,7 +1671,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_clipboardStatus?.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cut current selection to [Clipboard].
|
/// Cut current selection to [Clipboard].
|
||||||
@ -1695,7 +1694,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
});
|
});
|
||||||
hideToolbar();
|
hideToolbar();
|
||||||
}
|
}
|
||||||
_clipboardStatus?.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Paste text from [Clipboard].
|
/// Paste text from [Clipboard].
|
||||||
@ -2921,7 +2919,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
if (_selectionOverlay == null || _selectionOverlay!.toolbarIsVisible) {
|
if (_selectionOverlay == null || _selectionOverlay!.toolbarIsVisible) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_clipboardStatus?.update();
|
|
||||||
_selectionOverlay!.showToolbar();
|
_selectionOverlay!.showToolbar();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3028,7 +3026,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
&& copyEnabled
|
&& copyEnabled
|
||||||
&& _hasFocus
|
&& _hasFocus
|
||||||
&& (controls?.canCopy(this) ?? false)
|
&& (controls?.canCopy(this) ?? false)
|
||||||
? () => controls!.handleCopy(this)
|
? () => controls!.handleCopy(this, _clipboardStatus)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3037,7 +3035,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
&& cutEnabled
|
&& cutEnabled
|
||||||
&& _hasFocus
|
&& _hasFocus
|
||||||
&& (controls?.canCut(this) ?? false)
|
&& (controls?.canCut(this) ?? false)
|
||||||
? () => controls!.handleCut(this)
|
? () => controls!.handleCut(this, _clipboardStatus)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ abstract class TextSelectionControls {
|
|||||||
Offset position,
|
Offset position,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -199,16 +199,18 @@ abstract class TextSelectionControls {
|
|||||||
///
|
///
|
||||||
/// This is called by subclasses when their cut affordance is activated by
|
/// This is called by subclasses when their cut affordance is activated by
|
||||||
/// the user.
|
/// the user.
|
||||||
void handleCut(TextSelectionDelegate delegate) {
|
void handleCut(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
|
||||||
delegate.cutSelection(SelectionChangedCause.toolbar);
|
delegate.cutSelection(SelectionChangedCause.toolbar);
|
||||||
|
clipboardStatus?.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call [TextSelectionDelegate.copySelection] to copy current selection.
|
/// Call [TextSelectionDelegate.copySelection] to copy current selection.
|
||||||
///
|
///
|
||||||
/// This is called by subclasses when their copy affordance is activated by
|
/// This is called by subclasses when their copy affordance is activated by
|
||||||
/// the user.
|
/// the user.
|
||||||
void handleCopy(TextSelectionDelegate delegate) {
|
void handleCopy(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
|
||||||
delegate.copySelection(SelectionChangedCause.toolbar);
|
delegate.copySelection(SelectionChangedCause.toolbar);
|
||||||
|
clipboardStatus?.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call [TextSelectionDelegate.pasteText] to paste text.
|
/// Call [TextSelectionDelegate.pasteText] to paste text.
|
||||||
@ -1078,7 +1080,7 @@ class _SelectionToolbarOverlayState extends State<_SelectionToolbarOverlay> with
|
|||||||
widget.midpoint,
|
widget.midpoint,
|
||||||
widget.selectionEndpoints,
|
widget.selectionEndpoints,
|
||||||
widget.selectionDelegate!,
|
widget.selectionDelegate!,
|
||||||
widget.clipboardStatus,
|
widget.clipboardStatus!,
|
||||||
widget.toolbarLocation,
|
widget.toolbarLocation,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -2129,6 +2131,8 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
|
|||||||
}) : super(value);
|
}) : super(value);
|
||||||
|
|
||||||
bool _disposed = false;
|
bool _disposed = false;
|
||||||
|
/// True if this instance has been disposed.
|
||||||
|
bool get disposed => _disposed;
|
||||||
|
|
||||||
/// Check the [Clipboard] and update [value] if needed.
|
/// Check the [Clipboard] and update [value] if needed.
|
||||||
Future<void> update() async {
|
Future<void> update() async {
|
||||||
@ -2179,7 +2183,7 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
|
|||||||
@override
|
@override
|
||||||
void removeListener(VoidCallback listener) {
|
void removeListener(VoidCallback listener) {
|
||||||
super.removeListener(listener);
|
super.removeListener(listener);
|
||||||
if (!_disposed && !hasListeners) {
|
if (!hasListeners) {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2199,9 +2203,9 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class MockTextSelectionControls extends TextSelectionControls {
|
|||||||
Offset position,
|
Offset position,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
|
@ -24,7 +24,7 @@ class _CustomCupertinoTextSelectionControls extends CupertinoTextSelectionContro
|
|||||||
Offset selectionMidpoint,
|
Offset selectionMidpoint,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
final MediaQueryData mediaQuery = MediaQuery.of(context);
|
final MediaQueryData mediaQuery = MediaQuery.of(context);
|
||||||
|
@ -22,7 +22,7 @@ class _CustomMaterialTextSelectionControls extends MaterialTextSelectionControls
|
|||||||
Offset selectionMidpoint,
|
Offset selectionMidpoint,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
final TextSelectionPoint startTextSelectionPoint = endpoints[0];
|
final TextSelectionPoint startTextSelectionPoint = endpoints[0];
|
||||||
|
@ -11747,7 +11747,7 @@ class MockTextFormatter extends TextInputFormatter {
|
|||||||
|
|
||||||
class MockTextSelectionControls extends Fake implements TextSelectionControls {
|
class MockTextSelectionControls extends Fake implements TextSelectionControls {
|
||||||
@override
|
@override
|
||||||
Widget buildToolbar(BuildContext context, Rect globalEditableRegion, double textLineHeight, Offset position, List<TextSelectionPoint> endpoints, TextSelectionDelegate delegate, ValueListenable<ClipboardStatus>? clipboardStatus, Offset? lastSecondaryTapDownPosition) {
|
Widget buildToolbar(BuildContext context, Rect globalEditableRegion, double textLineHeight, Offset position, List<TextSelectionPoint> endpoints, TextSelectionDelegate delegate, ClipboardStatusNotifier clipboardStatus, Offset? lastSecondaryTapDownPosition) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11775,7 +11775,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls {
|
|||||||
int copyCount = 0;
|
int copyCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void handleCopy(TextSelectionDelegate delegate) {
|
void handleCopy(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
|
||||||
copyCount += 1;
|
copyCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11785,7 +11785,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void handleCut(TextSelectionDelegate delegate) {
|
void handleCut(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
|
||||||
cutCount += 1;
|
cutCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart' show defaultTargetPlatform, ValueListenable;
|
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
|
||||||
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
|
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
@ -1034,6 +1034,28 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('TextSelectionControls', () {
|
||||||
|
test('ClipboardStatusNotifier is updated on handleCut', () async {
|
||||||
|
final FakeClipboardStatusNotifier clipboardStatus = FakeClipboardStatusNotifier();
|
||||||
|
final FakeTextSelectionDelegate delegate = FakeTextSelectionDelegate();
|
||||||
|
final CustomTextSelectionControls textSelectionControls = CustomTextSelectionControls();
|
||||||
|
|
||||||
|
expect(clipboardStatus.updateCalled, false);
|
||||||
|
textSelectionControls.handleCut(delegate, clipboardStatus);
|
||||||
|
expect(clipboardStatus.updateCalled, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ClipboardStatusNotifier is updated on handleCopy', () async {
|
||||||
|
final FakeClipboardStatusNotifier clipboardStatus = FakeClipboardStatusNotifier();
|
||||||
|
final FakeTextSelectionDelegate delegate = FakeTextSelectionDelegate();
|
||||||
|
final CustomTextSelectionControls textSelectionControls = CustomTextSelectionControls();
|
||||||
|
|
||||||
|
expect(clipboardStatus.updateCalled, false);
|
||||||
|
textSelectionControls.handleCopy(delegate, clipboardStatus);
|
||||||
|
expect(clipboardStatus.updateCalled, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeTextSelectionGestureDetectorBuilderDelegate implements TextSelectionGestureDetectorBuilderDelegate {
|
class FakeTextSelectionGestureDetectorBuilderDelegate implements TextSelectionGestureDetectorBuilderDelegate {
|
||||||
@ -1162,7 +1184,7 @@ class CustomTextSelectionControls extends TextSelectionControls {
|
|||||||
Offset position,
|
Offset position,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
@ -1199,15 +1221,15 @@ class TextSelectionControlsSpy extends TextSelectionControls {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildToolbar(
|
Widget buildToolbar(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
Rect globalEditableRegion,
|
Rect globalEditableRegion,
|
||||||
double textLineHeight,
|
double textLineHeight,
|
||||||
Offset position,
|
Offset position,
|
||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
ValueListenable<ClipboardStatus>? clipboardStatus,
|
ClipboardStatusNotifier clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
) {
|
) {
|
||||||
return Text('dummy', key: toolBarKey);
|
return Text('dummy', key: toolBarKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1225,6 +1247,9 @@ class TextSelectionControlsSpy extends TextSelectionControls {
|
|||||||
class FakeClipboardStatusNotifier extends ClipboardStatusNotifier {
|
class FakeClipboardStatusNotifier extends ClipboardStatusNotifier {
|
||||||
FakeClipboardStatusNotifier() : super(value: ClipboardStatus.unknown);
|
FakeClipboardStatusNotifier() : super(value: ClipboardStatus.unknown);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get disposed => false;
|
||||||
|
|
||||||
bool updateCalled = false;
|
bool updateCalled = false;
|
||||||
@override
|
@override
|
||||||
Future<void> update() async {
|
Future<void> update() async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user