Line data Source code
1 : // Copyright 2014 The Flutter Authors. 2 : // Copyright 2021 Suragch. 3 : // All rights reserved. 4 : // Use of this source code is governed by a BSD-style license that can be 5 : // found in the LICENSE file. 6 : 7 : import 'package:flutter/material.dart' show Theme, Brightness, Colors, IconButton; 8 : import 'package:flutter/widgets.dart'; 9 : 10 8 : enum _TextSelectionToolbarItemPosition { 11 : /// The first item among multiple in the menu. 12 : first, 13 : 14 : /// One of several items, not the first or last. 15 : middle, 16 : 17 : /// The last item among multiple in the menu. 18 : last, 19 : 20 : /// The only item in the menu. 21 : only, 22 : } 23 : 24 : /// A button styled like a Material native Android text selection menu button. 25 : class MongolTextSelectionToolbarButton extends StatelessWidget { 26 : /// Creates an instance of MongolTextSelectionToolbarButton. 27 1 : const MongolTextSelectionToolbarButton({ 28 : Key? key, 29 : required this.child, 30 : required this.padding, 31 : this.onPressed, 32 1 : }) : super(key: key); 33 : 34 : // These values were eyeballed to match the native text selection menu on a 35 : // Pixel 2 running Android 10. 36 : static const double _kMiddlePadding = 9.5; 37 : static const double _kEndPadding = 14.5; 38 : 39 : /// The child of this button. 40 : /// 41 : /// Usually an [Icon]. 42 : final Widget child; 43 : 44 : /// Called when this button is pressed. 45 : final VoidCallback? onPressed; 46 : 47 : /// The padding between the button's edge and its child. 48 : /// 49 : /// See also: 50 : /// 51 : /// * [getPadding], which calculates the standard padding based on the 52 : /// button's position. 53 : /// * [ButtonStyle.padding], which is where this padding is applied. 54 : final EdgeInsets padding; 55 : 56 : /// Returns the standard padding for a button at index out of a total number 57 : /// of buttons. 58 1 : static EdgeInsets getPadding(int index, int total) { 59 3 : assert(total > 0 && index >= 0 && index < total); 60 1 : final position = _getPosition(index, total); 61 1 : return EdgeInsets.only( 62 1 : top: _getTopPadding(position), 63 1 : bottom: _getBottomPadding(position), 64 : ); 65 : } 66 : 67 1 : static double _getTopPadding(_TextSelectionToolbarItemPosition position) { 68 1 : if (position == _TextSelectionToolbarItemPosition.first 69 1 : || position == _TextSelectionToolbarItemPosition.only) { 70 : return _kEndPadding; 71 : } 72 : return _kMiddlePadding; 73 : } 74 : 75 1 : static double _getBottomPadding(_TextSelectionToolbarItemPosition position) { 76 1 : if (position == _TextSelectionToolbarItemPosition.last 77 1 : || position == _TextSelectionToolbarItemPosition.only) { 78 : return _kEndPadding; 79 : } 80 : return _kMiddlePadding; 81 : } 82 : 83 1 : static _TextSelectionToolbarItemPosition _getPosition(int index, int total) { 84 1 : if (index == 0) { 85 1 : return total == 1 86 : ? _TextSelectionToolbarItemPosition.only 87 : : _TextSelectionToolbarItemPosition.first; 88 : } 89 2 : if (index == total - 1) { 90 : return _TextSelectionToolbarItemPosition.last; 91 : } 92 : return _TextSelectionToolbarItemPosition.middle; 93 : } 94 : 95 1 : @override 96 : Widget build(BuildContext context) { 97 1 : final theme = Theme.of(context); 98 3 : final isDark = theme.colorScheme.brightness == Brightness.dark; 99 : final primary = isDark ? Colors.white : Colors.black87; 100 : 101 1 : return IconButton( 102 1 : padding: padding, 103 : color: primary, 104 1 : onPressed: onPressed, 105 1 : icon: child, 106 : ); 107 : } 108 : }