blob: 19302c2feafd14756753c0cd8b346bd44c9c1490 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'desktop_text_selection_toolbar.dart';
import 'desktop_text_selection_toolbar_button.dart';
import 'text_selection_toolbar.dart';
import 'text_selection_toolbar_button.dart';
/// The default Cupertino context menu for text selection for the current
/// platform with the given children.
///
/// {@template flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.platforms}
/// Builds the mobile Cupertino context menu on all mobile platforms, not just
/// iOS, and builds the desktop Cupertino context menu on all desktop platforms,
/// not just MacOS. For a widget that builds the native-looking context menu for
/// all platforms, see [AdaptiveTextSelectionToolbar].
/// {@endtemplate}
///
/// See also:
///
/// * [AdaptiveTextSelectionToolbar], which does the same thing as this widget
/// but for all platforms, not just the Cupertino-styled platforms.
/// * [CupertinoAdaptiveTextSelectionToolbar.getAdaptiveButtons], which builds
/// the Cupertino button Widgets for the current platform given
/// [ContextMenuButtonItem]s.
class CupertinoAdaptiveTextSelectionToolbar extends StatelessWidget {
/// Create an instance of [CupertinoAdaptiveTextSelectionToolbar] with the
/// given [children].
///
/// See also:
///
/// {@template flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.buttonItems}
/// * [CupertinoAdaptiveTextSelectionToolbar.buttonItems], which takes a list
/// of [ContextMenuButtonItem]s instead of [children] widgets.
/// {@endtemplate}
/// {@template flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editable}
/// * [CupertinoAdaptiveTextSelectionToolbar.editable], which builds the
/// default Cupertino children for an editable field.
/// {@endtemplate}
/// {@template flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editableText}
/// * [CupertinoAdaptiveTextSelectionToolbar.editableText], which builds the
/// default Cupertino children for an [EditableText].
/// {@endtemplate}
/// {@template flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.selectable}
/// * [CupertinoAdaptiveTextSelectionToolbar.selectable], which builds the
/// Cupertino children for content that is selectable but not editable.
/// {@endtemplate}
const CupertinoAdaptiveTextSelectionToolbar({
super.key,
required this.children,
required this.anchors,
}) : buttonItems = null;
/// Create an instance of [CupertinoAdaptiveTextSelectionToolbar] whose
/// children will be built from the given [buttonItems].
///
/// See also:
///
/// {@template flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.new}
/// * [CupertinoAdaptiveTextSelectionToolbar.new], which takes the children
/// directly as a list of widgets.
/// {@endtemplate}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editable}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editableText}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.selectable}
const CupertinoAdaptiveTextSelectionToolbar.buttonItems({
super.key,
required this.buttonItems,
required this.anchors,
}) : children = null;
/// Create an instance of [CupertinoAdaptiveTextSelectionToolbar] with the
/// default children for an editable field.
///
/// If a callback is null, then its corresponding button will not be built.
///
/// See also:
///
/// * [AdaptiveTextSelectionToolbar.editable], which is similar to this but
/// includes Material and Cupertino toolbars.
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.new}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editableText}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.buttonItems}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.selectable}
CupertinoAdaptiveTextSelectionToolbar.editable({
super.key,
required ClipboardStatus clipboardStatus,
required VoidCallback? onCopy,
required VoidCallback? onCut,
required VoidCallback? onPaste,
required VoidCallback? onSelectAll,
required this.anchors,
}) : children = null,
buttonItems = EditableText.getEditableButtonItems(
clipboardStatus: clipboardStatus,
onCopy: onCopy,
onCut: onCut,
onPaste: onPaste,
onSelectAll: onSelectAll,
);
/// Create an instance of [CupertinoAdaptiveTextSelectionToolbar] with the
/// default children for an [EditableText].
///
/// See also:
///
/// * [AdaptiveTextSelectionToolbar.editableText], which is similar to this
/// but includes Material and Cupertino toolbars.
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.new}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editable}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.buttonItems}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.selectable}
CupertinoAdaptiveTextSelectionToolbar.editableText({
super.key,
required EditableTextState editableTextState,
}) : children = null,
buttonItems = editableTextState.contextMenuButtonItems,
anchors = editableTextState.contextMenuAnchors;
/// Create an instance of [CupertinoAdaptiveTextSelectionToolbar] with the
/// default children for selectable, but not editable, content.
///
/// See also:
///
/// * [AdaptiveTextSelectionToolbar.selectable], which is similar to this but
/// includes Material and Cupertino toolbars.
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.new}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.buttonItems}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editable}
/// {@macro flutter.cupertino.CupertinoAdaptiveTextSelectionToolbar.editableText}
CupertinoAdaptiveTextSelectionToolbar.selectable({
super.key,
required VoidCallback onCopy,
required VoidCallback onSelectAll,
required SelectionGeometry selectionGeometry,
required this.anchors,
}) : children = null,
buttonItems = SelectableRegion.getSelectableButtonItems(
selectionGeometry: selectionGeometry,
onCopy: onCopy,
onSelectAll: onSelectAll,
);
/// {@macro flutter.material.AdaptiveTextSelectionToolbar.anchors}
final TextSelectionToolbarAnchors anchors;
/// The children of the toolbar, typically buttons.
final List<Widget>? children;
/// The [ContextMenuButtonItem]s that will be turned into the correct button
/// widgets for the current platform.
final List<ContextMenuButtonItem>? buttonItems;
/// Returns a List of Widgets generated by turning [buttonItems] into the
/// default context menu buttons for Cupertino on the current platform.
///
/// This is useful when building a text selection toolbar with the default
/// button appearance for the given platform, but where the toolbar and/or the
/// button actions and labels may be custom.
///
/// Does not build Material buttons. On non-Apple platforms, Cupertino buttons
/// will still be used, because the Cupertino library does not access the
/// Material library. To get the native-looking buttons on every platform,
/// use [AdaptiveTextSelectionToolbar.getAdaptiveButtons] in the Material
/// library.
///
/// See also:
///
/// * [AdaptiveTextSelectionToolbar.getAdaptiveButtons], which is the Material
/// equivalent of this class and builds only the Material buttons. It
/// includes a live example of using `getAdaptiveButtons`.
static Iterable<Widget> getAdaptiveButtons(BuildContext context, List<ContextMenuButtonItem> buttonItems) {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.iOS:
return buttonItems.map((ContextMenuButtonItem buttonItem) {
return CupertinoTextSelectionToolbarButton.buttonItem(
buttonItem: buttonItem,
);
});
case TargetPlatform.linux:
case TargetPlatform.windows:
case TargetPlatform.macOS:
return buttonItems.map((ContextMenuButtonItem buttonItem) {
return CupertinoDesktopTextSelectionToolbarButton.buttonItem(
buttonItem: buttonItem,
);
});
}
}
@override
Widget build(BuildContext context) {
// If there aren't any buttons to build, build an empty toolbar.
if ((children?.isEmpty ?? false) || (buttonItems?.isEmpty ?? false)) {
return const SizedBox.shrink();
}
final List<Widget> resultChildren = children
?? getAdaptiveButtons(context, buttonItems!).toList();
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
return CupertinoTextSelectionToolbar(
anchorAbove: anchors.primaryAnchor,
anchorBelow: anchors.secondaryAnchor ?? anchors.primaryAnchor,
children: resultChildren,
);
case TargetPlatform.linux:
case TargetPlatform.windows:
case TargetPlatform.macOS:
return CupertinoDesktopTextSelectionToolbar(
anchor: anchors.primaryAnchor,
children: resultChildren,
);
}
}
}