made AnimatedDialogPicker more generic

This commit is contained in:
Vadim 2023-03-21 20:57:40 +03:00
parent 29404e2f87
commit 18210caf7d
3 changed files with 24 additions and 26 deletions

View file

@ -2,38 +2,36 @@ import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
typedef DialogPickerItemBuilder<T extends PhotographyValue> = Widget Function(BuildContext, T); typedef DialogPickerItemTitleBuilder<T> = Widget Function(BuildContext context, T value);
typedef DialogPickerEvDifferenceBuilder<T extends PhotographyValue> = String Function( typedef DialogPickerItemTrailingBuilder<T> = Widget? Function(T selected, T value);
T selected, T other);
class PhotographyValuePickerDialog<T extends PhotographyValue> extends StatefulWidget { class DialogPicker<T> extends StatefulWidget {
final String title; final String title;
final String subtitle; final String subtitle;
final T initialValue; final T initialValue;
final List<T> values; final List<T> values;
final DialogPickerItemBuilder<T> itemTitleBuilder; final DialogPickerItemTitleBuilder<T> itemTitleBuilder;
final DialogPickerEvDifferenceBuilder<T> evDifferenceBuilder; final DialogPickerItemTrailingBuilder<T> itemTrailingBuilder;
final VoidCallback onCancel; final VoidCallback onCancel;
final ValueChanged onSelect; final ValueChanged onSelect;
const PhotographyValuePickerDialog({ const DialogPicker({
required this.title, required this.title,
required this.subtitle, required this.subtitle,
required this.initialValue, required this.initialValue,
required this.values, required this.values,
required this.itemTitleBuilder, required this.itemTitleBuilder,
required this.evDifferenceBuilder, required this.itemTrailingBuilder,
required this.onCancel, required this.onCancel,
required this.onSelect, required this.onSelect,
super.key, super.key,
}); });
@override @override
State<PhotographyValuePickerDialog<T>> createState() => _PhotographyValuePickerDialogState<T>(); State<DialogPicker<T>> createState() => _DialogPickerState<T>();
} }
class _PhotographyValuePickerDialogState<T extends PhotographyValue> class _DialogPickerState<T> extends State<DialogPicker<T>> {
extends State<PhotographyValuePickerDialog<T>> {
late T _selectedValue = widget.initialValue; late T _selectedValue = widget.initialValue;
late final _scrollController = late final _scrollController =
ScrollController(initialScrollOffset: Dimens.grid56 * widget.values.indexOf(_selectedValue)); ScrollController(initialScrollOffset: Dimens.grid56 * widget.values.indexOf(_selectedValue));
@ -81,10 +79,7 @@ class _PhotographyValuePickerDialogState<T extends PhotographyValue>
style: Theme.of(context).textTheme.bodyLarge!, style: Theme.of(context).textTheme.bodyLarge!,
child: widget.itemTitleBuilder(context, widget.values[index]), child: widget.itemTitleBuilder(context, widget.values[index]),
), ),
secondary: widget.values[index].value != _selectedValue.value secondary: widget.itemTrailingBuilder(_selectedValue, widget.values[index]),
? Text(S.of(context).evValue(
widget.evDifferenceBuilder.call(_selectedValue, widget.values[index])))
: null,
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
setState(() { setState(() {

View file

@ -1,17 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'components/animated_dialog/widget_dialog_animated.dart'; import 'components/animated_dialog/widget_dialog_animated.dart';
import 'components/photography_value_picker_dialog/widget_dialog_picker_photography_value.dart'; import 'components/dialog_picker/widget_picker_dialog.dart';
class AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget { class AnimatedDialogPicker<T> extends StatelessWidget {
final _key = GlobalKey<AnimatedDialogState>(); final _key = GlobalKey<AnimatedDialogState>();
final String title; final String title;
final String subtitle; final String subtitle;
final T selectedValue; final T selectedValue;
final List<T> values; final List<T> values;
final DialogPickerItemBuilder<T> itemTitleBuilder; final DialogPickerItemTitleBuilder<T> itemTitleBuilder;
final DialogPickerEvDifferenceBuilder<T> evDifferenceBuilder; final DialogPickerItemTrailingBuilder<T> itemTrailingBuilder;
final ValueChanged<T> onChanged; final ValueChanged<T> onChanged;
final Widget closedChild; final Widget closedChild;
@ -21,7 +20,7 @@ class AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget {
required this.selectedValue, required this.selectedValue,
required this.values, required this.values,
required this.itemTitleBuilder, required this.itemTitleBuilder,
required this.evDifferenceBuilder, required this.itemTrailingBuilder,
required this.onChanged, required this.onChanged,
required this.closedChild, required this.closedChild,
super.key, super.key,
@ -32,13 +31,13 @@ class AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget {
return AnimatedDialog( return AnimatedDialog(
key: _key, key: _key,
closedChild: closedChild, closedChild: closedChild,
openedChild: PhotographyValuePickerDialog<T>( openedChild: DialogPicker<T>(
title: title, title: title,
subtitle: subtitle, subtitle: subtitle,
initialValue: selectedValue, initialValue: selectedValue,
values: values, values: values,
itemTitleBuilder: itemTitleBuilder, itemTitleBuilder: itemTitleBuilder,
evDifferenceBuilder: evDifferenceBuilder, itemTrailingBuilder: itemTrailingBuilder,
onCancel: () { onCancel: () {
_key.currentState?.close(); _key.currentState?.close();
}, },

View file

@ -4,7 +4,7 @@ import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/equipment_profile_provider.dart'; import 'package:lightmeter/providers/equipment_profile_provider.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'components/animated_dialog_picker/widget_dialog_animated_picker.dart'; import 'components/animated_dialog_picker/widget_picker_dialog_animated.dart';
import 'components/reading_value_container/widget_container_reading_value.dart'; import 'components/reading_value_container/widget_container_reading_value.dart';
/// Contains a column of fastest & slowest exposure pairs + a row of ISO and ND pickers /// Contains a column of fastest & slowest exposure pairs + a row of ISO and ND pickers
@ -107,7 +107,9 @@ class _IsoValueTile extends StatelessWidget {
values: values, values: values,
itemTitleBuilder: (_, value) => Text(value.value.toString()), itemTitleBuilder: (_, value) => Text(value.value.toString()),
// using ascending order, because increase in film speed rises EV // using ascending order, because increase in film speed rises EV
evDifferenceBuilder: (selected, other) => selected.toStringDifference(other), itemTrailingBuilder: (selected, value) => value.value != selected.value
? Text(S.of(context).evValue(selected.toStringDifference(value)))
: null,
onChanged: onChanged, onChanged: onChanged,
closedChild: ReadingValueContainer.singleValue( closedChild: ReadingValueContainer.singleValue(
value: ReadingValue( value: ReadingValue(
@ -141,7 +143,9 @@ class _NdValueTile extends StatelessWidget {
value.value == 0 ? S.of(context).none : value.value.toString(), value.value == 0 ? S.of(context).none : value.value.toString(),
), ),
// using descending order, because ND filter darkens image & lowers EV // using descending order, because ND filter darkens image & lowers EV
evDifferenceBuilder: (selected, other) => other.toStringDifference(selected), itemTrailingBuilder: (selected, value) => value.value != selected.value
? Text(S.of(context).evValue(value.toStringDifference(selected)))
: null,
onChanged: onChanged, onChanged: onChanged,
closedChild: ReadingValueContainer.singleValue( closedChild: ReadingValueContainer.singleValue(
value: ReadingValue( value: ReadingValue(