Skip to content

Commit 0aaf6e7

Browse files
committed
feat: make the section theme configurable and simplify theme resolution
1 parent 87be225 commit 0aaf6e7

File tree

5 files changed

+89
-77
lines changed

5 files changed

+89
-77
lines changed

packages/dogs_flutter/example/lib/models.conv.g.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dogs_flutter/example/lib/models.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Person with Dataclass<Person> {
3838

3939
@LengthRange(min: 3)
4040
@MaterialBindingStyle.inputTheme(
41-
InputDecorationTheme(border: OutlineInputBorder()),
41+
InputDecorationThemeData(border: OutlineInputBorder()),
4242
)
4343
String password;
4444

packages/dogs_flutter/example/pubspec.lock

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ packages:
55
dependency: transitive
66
description:
77
name: _fe_analyzer_shared
8-
sha256: f0bb5d1648339c8308cc0b9838d8456b3cfe5c91f9dc1a735b4d003269e5da9a
8+
sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f
99
url: "https://pub.dev"
1010
source: hosted
11-
version: "88.0.0"
11+
version: "85.0.0"
1212
analyzer:
1313
dependency: transitive
1414
description:
1515
name: analyzer
16-
sha256: "0b7b9c329d2879f8f05d6c05b32ee9ec025f39b077864bdb5ac9a7b63418a98f"
16+
sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d"
1717
url: "https://pub.dev"
1818
source: hosted
19-
version: "8.1.1"
19+
version: "7.7.1"
2020
args:
2121
dependency: transitive
2222
description:
@@ -173,31 +173,31 @@ packages:
173173
dependency: transitive
174174
description:
175175
name: dart_style
176-
sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697
176+
sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb"
177177
url: "https://pub.dev"
178178
source: hosted
179-
version: "3.1.2"
179+
version: "3.1.1"
180180
dogs_core:
181181
dependency: "direct overridden"
182182
description:
183183
path: "../../dogs_core"
184184
relative: true
185185
source: path
186-
version: "10.0.0-dev.4"
186+
version: "10.0.0-dev.5"
187187
dogs_flutter:
188188
dependency: "direct main"
189189
description:
190190
path: ".."
191191
relative: true
192192
source: path
193-
version: "0.0.1-dev.6"
193+
version: "0.0.1-dev.7"
194194
dogs_generator:
195195
dependency: "direct dev"
196196
description:
197197
path: "../../dogs_generator"
198198
relative: true
199199
source: path
200-
version: "7.0.0-dev.4"
200+
version: "7.0.0-dev.5"
201201
duffer:
202202
dependency: transitive
203203
description:
@@ -356,10 +356,10 @@ packages:
356356
dependency: transitive
357357
description:
358358
name: lyell_gen
359-
sha256: ce9d006796e2f8286c68e988f7ed7aa1e98e993838ed4e5120d7a526caef0cee
359+
sha256: "566acd859dc12207740c5285963c3169b2537f6290760dc86388fcb8b8808187"
360360
url: "https://pub.dev"
361361
source: hosted
362-
version: "3.0.9"
362+
version: "3.0.11"
363363
matcher:
364364
dependency: transitive
365365
description:
@@ -489,10 +489,10 @@ packages:
489489
dependency: transitive
490490
description:
491491
name: source_gen
492-
sha256: "800f12fb87434defa13432ab37e33051b43b290a174e15259563b043cda40c46"
492+
sha256: "7b19d6ba131c6eb98bfcbf8d56c1a7002eba438af2e7ae6f8398b2b0f4f381e3"
493493
url: "https://pub.dev"
494494
source: hosted
495-
version: "4.0.0"
495+
version: "3.1.0"
496496
source_span:
497497
dependency: transitive
498498
description:

packages/dogs_flutter/lib/databinding/material/style.dart

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,36 @@ import 'package:flutter/material.dart';
55

66
class MaterialBindingStyle extends BindingStyleExtension<MaterialBindingStyle>
77
implements StructureMetadata, BindingStyleModifier {
8-
final InputDecorationTheme? inputTheme;
8+
final InputDecorationThemeData? inputTheme;
9+
final InputDecorationThemeData? sectionTheme;
910
final ButtonStyle? buttonStyle;
1011

11-
const MaterialBindingStyle({this.inputTheme, this.buttonStyle});
12+
const MaterialBindingStyle({
13+
this.inputTheme,
14+
this.buttonStyle,
15+
this.sectionTheme,
16+
});
1217

13-
const MaterialBindingStyle.inputTheme(this.inputTheme) : buttonStyle = null;
18+
const MaterialBindingStyle.inputTheme(this.inputTheme)
19+
: buttonStyle = null,
20+
sectionTheme = null;
1421

15-
const MaterialBindingStyle.buttonStyle(this.buttonStyle) : inputTheme = null;
22+
const MaterialBindingStyle.buttonStyle(this.buttonStyle)
23+
: inputTheme = null,
24+
sectionTheme = null;
25+
26+
const MaterialBindingStyle.sectionTheme(this.sectionTheme)
27+
: inputTheme = null,
28+
buttonStyle = null;
1629

1730
@override
1831
MaterialBindingStyle merge(MaterialBindingStyle? other) {
1932
if (other == null) return this;
2033
return MaterialBindingStyle(
2134
inputTheme: inputTheme?.merge(other.inputTheme) ?? other.inputTheme,
2235
buttonStyle: buttonStyle?.merge(other.buttonStyle) ?? other.buttonStyle,
36+
sectionTheme:
37+
sectionTheme?.merge(other.sectionTheme) ?? other.sectionTheme,
2338
);
2439
}
2540

@@ -35,14 +50,7 @@ extension BindingStyleDataMaterialExtension on BindingStyle {
3550
bool includeHelper = true,
3651
bool includeHint = true,
3752
}) {
38-
final currentTheme = Theme.of(context);
39-
final theme =
40-
getExtension<MaterialBindingStyle>() ?? MaterialBindingStyle();
41-
final inputTheme =
42-
theme.inputTheme?.merge(
43-
InputDecorationTheme(data: currentTheme.inputDecorationTheme),
44-
) ??
45-
currentTheme.inputDecorationTheme;
53+
var (inputTheme, style, theme) = resolveTheme(context);
4654
final decoration = InputDecoration()
4755
.applyDefaults(inputTheme)
4856
.copyWith(
@@ -61,17 +69,25 @@ extension BindingStyleDataMaterialExtension on BindingStyle {
6169
Object? labelOverride = #none,
6270
String? errorText,
6371
}) {
64-
return Padding(
65-
padding: const EdgeInsets.symmetric(vertical: 8.0),
66-
child: InputDecorator(
67-
decoration: InputDecoration(
68-
border: OutlineInputBorder(),
72+
var (inputTheme, style, theme) = resolveTheme(context);
73+
if (style.sectionTheme != null) {
74+
inputTheme = style.sectionTheme!.merge(inputTheme);
75+
} else {
76+
inputTheme = inputTheme.copyWith(border: OutlineInputBorder());
77+
}
78+
var decoration = InputDecoration()
79+
.applyDefaults(inputTheme)
80+
.copyWith(
6981
labelText: labelOverride == #none ? label : labelOverride.toString(),
7082
errorText: errorText,
71-
helperText: helper
72-
),
73-
child: widget,
74-
),
83+
helperText: helper,
84+
prefix: prefix,
85+
suffix: suffix,
86+
);
87+
88+
return Padding(
89+
padding: const EdgeInsets.symmetric(vertical: 8.0),
90+
child: InputDecorator(decoration: decoration, child: widget),
7591
);
7692
}
7793

@@ -86,22 +102,12 @@ extension BindingStyleDataMaterialExtension on BindingStyle {
86102
}
87103

88104
if (label == null) return null;
89-
final currentTheme = Theme.of(context);
90-
final theme =
91-
getExtension<MaterialBindingStyle>() ?? MaterialBindingStyle();
92-
final inputTheme =
93-
theme.inputTheme?.merge(
94-
InputDecorationTheme(data: currentTheme.inputDecorationTheme),
95-
) ??
96-
InputDecorationTheme(data: currentTheme.inputDecorationTheme);
105+
final (inputTheme, bindingStyle, theme) = resolveTheme(context);
97106
var style = inputTheme.labelStyle;
98-
99107
if (isError) {
100108
style =
101-
inputTheme.errorStyle ??
102-
TextStyle(color: currentTheme.colorScheme.error);
109+
inputTheme.errorStyle ?? TextStyle(color: theme.colorScheme.error);
103110
}
104-
105111
return Text(label, style: style);
106112
}
107113

@@ -114,37 +120,33 @@ extension BindingStyleDataMaterialExtension on BindingStyle {
114120

115121
Widget? buildMaterialHelperText(BuildContext context) {
116122
if (helper == null) return null;
117-
final currentTheme = Theme.of(context);
118-
final theme =
119-
getExtension<MaterialBindingStyle>() ?? MaterialBindingStyle();
120-
final inputTheme =
121-
theme.inputTheme?.merge(
122-
InputDecorationTheme(data: currentTheme.inputDecorationTheme),
123-
) ??
124-
InputDecorationTheme(data: currentTheme.inputDecorationTheme);
123+
final (inputTheme, style, theme) = resolveTheme(context);
125124
return Text(helper!, style: inputTheme.helperStyle);
126125
}
127126

128127
Widget? buildMaterialErrorText(BuildContext context, String? error) {
129128
if (error == null) return null;
130-
final currentTheme = Theme.of(context);
131-
final theme =
132-
getExtension<MaterialBindingStyle>() ?? MaterialBindingStyle();
133-
final inputTheme =
134-
theme.inputTheme?.merge(
135-
InputDecorationTheme(data: currentTheme.inputDecorationTheme),
136-
) ??
137-
InputDecorationTheme(data: currentTheme.inputDecorationTheme);
138-
129+
final (inputTheme, style, theme) = resolveTheme(context);
139130
return DefaultTextStyle(
140-
style:
141-
inputTheme.errorStyle ??
142-
TextStyle(color: currentTheme.colorScheme.error),
131+
style: inputTheme.errorStyle ?? TextStyle(color: theme.colorScheme.error),
143132
child: Text(error),
144133
);
145134
}
146135

147136
ButtonStyle? getMaterialButtonStyle() {
148137
return getExtension<MaterialBindingStyle>()?.buttonStyle;
149138
}
139+
140+
(InputDecorationThemeData, MaterialBindingStyle, ThemeData) resolveTheme(
141+
BuildContext context,
142+
) {
143+
final currentTheme = Theme.of(context);
144+
final style =
145+
getExtension<MaterialBindingStyle>() ?? MaterialBindingStyle();
146+
var inputTheme = currentTheme.inputDecorationTheme;
147+
if (style.inputTheme != null) {
148+
inputTheme = style.inputTheme!.merge(inputTheme);
149+
}
150+
return (inputTheme, style, currentTheme);
151+
}
150152
}

packages/dogs_flutter/lib/databinding/widgets/field_widget.dart

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ import 'package:flutter/foundation.dart' show kDebugMode;
2424
import 'package:flutter/material.dart';
2525
import 'package:flutter/widgets.dart';
2626

27+
typedef StyleBuilder = BindingStyle Function(BindingStyle);
28+
typedef FieldBindingWrapper =
29+
Widget Function(BuildContext context, Widget inner);
30+
2731
class FieldBinding extends StatefulWidget {
2832
final FieldBindingController? controller;
2933
final String? field;
30-
final BindingStyle Function(BindingStyle)? styleBuilder;
34+
final StyleBuilder? styleBuilder;
35+
final FieldBindingWrapper? wrapper;
3136
final BindingStyle? style;
3237
final ValidationTrigger? validationTrigger;
3338
final AnnotationTransformer? annotationTransformer;
@@ -42,6 +47,7 @@ class FieldBinding extends StatefulWidget {
4247
this.validationTrigger,
4348
this.annotationTransformer,
4449
this.binder,
50+
this.wrapper,
4551
});
4652

4753
@override
@@ -80,11 +86,10 @@ class _FieldBindingState extends State<FieldBinding> {
8086
}
8187

8288
generatedStyle = BindingStyle(label: controller!.fieldName);
83-
fieldStyleData =
84-
controller!.bindingContext.field
85-
.annotationsOf<BindingStyleModifier>()
86-
.map((e) => e.createStyleOverrides())
87-
.toList();
89+
fieldStyleData = controller!.bindingContext.field
90+
.annotationsOf<BindingStyleModifier>()
91+
.map((e) => e.createStyleOverrides())
92+
.toList();
8893
styleBuilder =
8994
widget.styleBuilder ?? (style) => widget.style?.merge(style) ?? style;
9095
}
@@ -132,7 +137,12 @@ class _FieldBindingState extends State<FieldBinding> {
132137
annotationTransformer: annotationTransformer,
133138
child: Builder(
134139
builder: (context) {
135-
return currentBinder.buildBindingField(context, currentController);
140+
var child = currentBinder.buildBindingField(
141+
context,
142+
currentController,
143+
);
144+
if (widget.wrapper != null) child = widget.wrapper!(context, child);
145+
return child;
136146
},
137147
),
138148
);
@@ -151,8 +161,8 @@ class BindingTheme extends InheritedWidget {
151161
});
152162

153163
static BindingTheme of(BuildContext context) {
154-
final BindingTheme? result =
155-
context.dependOnInheritedWidgetOfExactType<BindingTheme>();
164+
final BindingTheme? result = context
165+
.dependOnInheritedWidgetOfExactType<BindingTheme>();
156166
assert(result != null, 'No BindingContext found in context');
157167
return result!;
158168
}

0 commit comments

Comments
 (0)