Line data Source code
1 : // Copyright 2014 The Flutter Authors.
2 : // Copyright 2020 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';
8 : import 'package:flutter/rendering.dart';
9 :
10 : /// These classes were adapted from Flutter [ButtonBar]
11 :
12 : class MongolButtonBar extends StatelessWidget {
13 0 : const MongolButtonBar({
14 : Key? key,
15 : this.alignment,
16 : this.mainAxisSize,
17 : this.buttonTextTheme,
18 : this.buttonMinWidth,
19 : this.buttonHeight,
20 : this.buttonPadding,
21 : this.layoutBehavior,
22 : this.children = const <Widget>[],
23 0 : }) : assert(buttonMinWidth == null || buttonMinWidth >= 0.0),
24 0 : assert(buttonHeight == null || buttonHeight >= 0.0),
25 0 : super(key: key);
26 :
27 : /// How the children should be placed along the vertical axis.
28 : ///
29 : /// If null then it will use [ButtonBarTheme.alignment]. If that is null,
30 : /// it will default to [MainAxisAlignment.end].
31 : final MainAxisAlignment? alignment;
32 :
33 : /// How much horizontal space is available. See [Column.mainAxisSize].
34 : ///
35 : /// If null then it will use the surrounding [ButtonBarTheme.mainAxisSize].
36 : /// If that is null, it will default to [MainAxisSize.max].
37 : final MainAxisSize? mainAxisSize;
38 :
39 : final ButtonTextTheme? buttonTextTheme;
40 :
41 : final double? buttonMinWidth;
42 :
43 : final double? buttonHeight;
44 :
45 : final EdgeInsetsGeometry? buttonPadding;
46 :
47 : final ButtonBarLayoutBehavior? layoutBehavior;
48 :
49 : /// The buttons to arrange horizontally.
50 : ///
51 : /// Typically [ElevatedButton] or [TextButton] widgets using [MongolText].
52 : final List<Widget> children;
53 :
54 0 : @override
55 : Widget build(BuildContext context) {
56 0 : final parentButtonTheme = ButtonTheme.of(context);
57 0 : final barTheme = ButtonBarTheme.of(context);
58 :
59 0 : final buttonTheme = parentButtonTheme.copyWith(
60 0 : textTheme: buttonTextTheme ??
61 0 : barTheme.buttonTextTheme ??
62 : ButtonTextTheme.primary,
63 0 : minWidth: buttonMinWidth ?? barTheme.buttonMinWidth ?? 36.0,
64 0 : height: buttonHeight ?? barTheme.buttonHeight ?? 64.0,
65 0 : padding: buttonPadding ??
66 0 : barTheme.buttonPadding ??
67 : const EdgeInsets.symmetric(vertical: 8.0),
68 : alignedDropdown: false,
69 0 : layoutBehavior: layoutBehavior ??
70 0 : barTheme.layoutBehavior ??
71 : ButtonBarLayoutBehavior.padded,
72 : );
73 :
74 0 : final paddingUnit = buttonTheme.padding.vertical / 4.0;
75 0 : final Widget child = ButtonTheme.fromButtonThemeData(
76 : data: buttonTheme,
77 0 : child: _ButtonBarColumn(
78 : mainAxisAlignment:
79 0 : alignment ?? barTheme.alignment ?? MainAxisAlignment.end,
80 0 : mainAxisSize: mainAxisSize ?? barTheme.mainAxisSize ?? MainAxisSize.max,
81 0 : children: children.map<Widget>((Widget child) {
82 0 : return Padding(
83 0 : padding: EdgeInsets.symmetric(vertical: paddingUnit),
84 : child: child,
85 : );
86 0 : }).toList(),
87 : ),
88 : );
89 0 : switch (buttonTheme.layoutBehavior) {
90 0 : case ButtonBarLayoutBehavior.padded:
91 0 : return Padding(
92 0 : padding: EdgeInsets.symmetric(
93 0 : horizontal: 2.0 * paddingUnit,
94 : vertical: paddingUnit,
95 : ),
96 : child: child,
97 : );
98 : default: // ButtonBarLayoutBehavior.constrained:
99 0 : return Container(
100 0 : padding: EdgeInsets.symmetric(vertical: paddingUnit),
101 : constraints: const BoxConstraints(minWidth: 52.0),
102 : alignment: Alignment.center,
103 : child: child,
104 : );
105 : }
106 : }
107 : }
108 :
109 : class _ButtonBarColumn extends Flex {
110 : /// Creates a button bar that attempts to display in a column, but displays in
111 : /// a row if there is insufficient vertical space.
112 0 : _ButtonBarColumn({
113 : required List<Widget> children,
114 : Axis direction = Axis.vertical,
115 : MainAxisSize mainAxisSize = MainAxisSize.max,
116 : MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
117 : CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
118 0 : }) : super(
119 : children: children,
120 : direction: direction,
121 : mainAxisSize: mainAxisSize,
122 : mainAxisAlignment: mainAxisAlignment,
123 : crossAxisAlignment: crossAxisAlignment,
124 : );
125 :
126 0 : @override
127 : _RenderButtonBarColumn createRenderObject(BuildContext context) {
128 0 : return _RenderButtonBarColumn(
129 0 : direction: direction,
130 0 : mainAxisAlignment: mainAxisAlignment,
131 0 : mainAxisSize: mainAxisSize,
132 0 : crossAxisAlignment: crossAxisAlignment,
133 : );
134 : }
135 :
136 0 : @override
137 : void updateRenderObject(
138 : BuildContext context, covariant _RenderButtonBarColumn renderObject) {
139 : renderObject
140 0 : ..direction = direction
141 0 : ..mainAxisAlignment = mainAxisAlignment
142 0 : ..mainAxisSize = mainAxisSize
143 0 : ..crossAxisAlignment = crossAxisAlignment;
144 : }
145 : }
146 :
147 : class _RenderButtonBarColumn extends RenderFlex {
148 0 : _RenderButtonBarColumn({
149 : List<RenderBox>? children,
150 : Axis direction = Axis.vertical,
151 : MainAxisSize mainAxisSize = MainAxisSize.max,
152 : MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
153 : CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
154 0 : }) : super(
155 : children: children,
156 : direction: direction,
157 : mainAxisSize: mainAxisSize,
158 : mainAxisAlignment: mainAxisAlignment,
159 : crossAxisAlignment: crossAxisAlignment,
160 : );
161 :
162 : bool _hasCheckedLayoutHeight = false;
163 :
164 0 : @override
165 : BoxConstraints get constraints {
166 0 : if (_hasCheckedLayoutHeight) return super.constraints;
167 0 : return super.constraints.copyWith(maxHeight: double.infinity);
168 : }
169 :
170 0 : @override
171 : void performLayout() {
172 0 : _hasCheckedLayoutHeight = false;
173 :
174 0 : super.performLayout();
175 0 : _hasCheckedLayoutHeight = true;
176 :
177 0 : if (size.height <= constraints.maxHeight) {
178 0 : super.performLayout();
179 : } else {
180 0 : final childConstraints = constraints.copyWith(minHeight: 0.0);
181 : RenderBox? child;
182 : var currentWidth = 0.0;
183 0 : child = firstChild;
184 :
185 : while (child != null) {
186 0 : final childParentData = child.parentData as FlexParentData;
187 0 : child.layout(childConstraints, parentUsesSize: true);
188 0 : switch (mainAxisAlignment) {
189 0 : case MainAxisAlignment.center:
190 0 : final midpoint = (constraints.maxHeight - child.size.height) / 2.0;
191 0 : childParentData.offset = Offset(midpoint, currentWidth);
192 : break;
193 0 : case MainAxisAlignment.end:
194 0 : childParentData.offset =
195 0 : Offset(constraints.maxHeight - child.size.height, currentWidth);
196 : break;
197 : default:
198 0 : childParentData.offset = Offset(0, currentWidth);
199 : break;
200 : }
201 0 : currentWidth += child.size.width;
202 0 : child = childParentData.nextSibling;
203 : }
204 0 : size = constraints.constrain(Size(constraints.maxHeight, currentWidth));
205 : }
206 : }
207 : }
|