|
@@ -0,0 +1,153 @@
|
|
|
+import 'package:fis_ui/index.dart';
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class ButtonGroup extends StatelessWidget {
|
|
|
+ static const List<Type> supportedButtonTypes = [
|
|
|
+ FElevatedButtonWithIcon,
|
|
|
+ ElevatedButton,
|
|
|
+ OutlinedButton,
|
|
|
+ ];
|
|
|
+ ButtonGroup(
|
|
|
+ {super.key,
|
|
|
+ required this.children,
|
|
|
+ this.spacing = 10.0,
|
|
|
+ this.buttonPadding = 16.0})
|
|
|
+ : assert(
|
|
|
+ children.every((e) => supportedButtonTypes.contains(e.runtimeType)),
|
|
|
+ 'FButtonGroup children must be Supported');
|
|
|
+ final List<Widget> children;
|
|
|
+
|
|
|
+
|
|
|
+ final double spacing;
|
|
|
+
|
|
|
+
|
|
|
+ final double buttonPadding;
|
|
|
+
|
|
|
+
|
|
|
+ static const double _defaultBorderWidth = 1.0;
|
|
|
+
|
|
|
+
|
|
|
+ double getMaxWidth() {
|
|
|
+ double maxWidth = 0;
|
|
|
+ for (var i = 0; i < children.length; i++) {
|
|
|
+ var child = children[i];
|
|
|
+ if (child is FElevatedButtonWithIcon) {
|
|
|
+ final double innerSpacing = 8.0;
|
|
|
+ var text = child.label;
|
|
|
+ var icon = child.icon;
|
|
|
+ var iconWidth = 24.0;
|
|
|
+ if (icon is Icon) {
|
|
|
+ iconWidth = getIconWidth(icon);
|
|
|
+ }
|
|
|
+ if (text is Text) {
|
|
|
+ var width = getTextWidth(text) +
|
|
|
+ iconWidth +
|
|
|
+ innerSpacing +
|
|
|
+ _defaultBorderWidth * 2;
|
|
|
+ if (width > maxWidth) {
|
|
|
+
|
|
|
+ maxWidth = width;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (child is ElevatedButton) {
|
|
|
+ var text = child.child;
|
|
|
+ if (text is Text) {
|
|
|
+ var width = getTextWidth(text) + _defaultBorderWidth * 2;
|
|
|
+ if (width > maxWidth) {
|
|
|
+ maxWidth = width;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (child is FOutlinedButton) {
|
|
|
+ var text = child.child;
|
|
|
+ if (text is Text) {
|
|
|
+ var width = getTextWidth(text) + _defaultBorderWidth * 2;
|
|
|
+ if (width > maxWidth) {
|
|
|
+ maxWidth = width;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (child is FDelayedTiriggerButton) {
|
|
|
+ var text = child.child;
|
|
|
+ if (text is Text) {
|
|
|
+ var width = getTextWidth(text) + _defaultBorderWidth * 2 + 16;
|
|
|
+ if (width > maxWidth) {
|
|
|
+ maxWidth = width;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return maxWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ double getTextWidth(Text text) {
|
|
|
+ final TextStyle style = text.style ?? TextStyle();
|
|
|
+ var textPainter = TextPainter(
|
|
|
+ text: TextSpan(
|
|
|
+ style: style,
|
|
|
+
|
|
|
+ text: text.data),
|
|
|
+ textDirection: TextDirection.ltr,
|
|
|
+ maxLines: 1,
|
|
|
+ textScaleFactor: 1);
|
|
|
+ textPainter.layout();
|
|
|
+ var width = textPainter.width;
|
|
|
+ return width;
|
|
|
+ }
|
|
|
+
|
|
|
+ double getIconWidth(Icon icon) {
|
|
|
+ final double width = icon.size ?? 24.0;
|
|
|
+ return width;
|
|
|
+ }
|
|
|
+
|
|
|
+ double get totalWidth =>
|
|
|
+ getMaxWidth() * children.length +
|
|
|
+ buttonPadding * 2 * children.length +
|
|
|
+ spacing * (children.length - 1);
|
|
|
+
|
|
|
+ @override
|
|
|
+ build(BuildContext context) {
|
|
|
+ return ConstrainedBox(
|
|
|
+ constraints: BoxConstraints.tightFor(width: totalWidth),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ mainAxisSize: MainAxisSize.max,
|
|
|
+ children: children.map((e) {
|
|
|
+
|
|
|
+ return Expanded(child: e) as Widget;
|
|
|
+ }).toList()
|
|
|
+
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+extension ListExt<Widget> on List<Widget> {
|
|
|
+ List<Widget> superJoin(Widget separator) {
|
|
|
+ final iterator = this.iterator;
|
|
|
+ if (!iterator.moveNext()) return [];
|
|
|
+
|
|
|
+ final l = [iterator.current];
|
|
|
+ while (iterator.moveNext()) {
|
|
|
+ l
|
|
|
+ ..add(separator)
|
|
|
+ ..add(iterator.current);
|
|
|
+ }
|
|
|
+ return l;
|
|
|
+ }
|
|
|
+}
|