From eeb70bfaff66f60d1ba782dbb1a094294c0ffdb6 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Wed, 13 Sep 2023 22:00:42 +0200 Subject: [PATCH] fixed extreme exposure pairs reciprocity display --- .../widget_picker_equipment_profiles.dart | 30 +++ ...dget_container_extreme_exposure_pairs.dart | 40 ++++ .../film_picker/widget_picker_film.dart | 52 ++++++ .../iso_picker/widget_picker_iso.dart | 40 ++++ .../nd_picker/widget_picker_nd.dart | 42 +++++ .../widget_dialog_animated.dart | 0 .../dialog_picker/widget_picker_dialog.dart | 0 .../widget_picker_dialog_animated.dart | 5 +- .../widget_container_reading_value.dart | 0 .../widget_container_readings.dart | 172 ++---------------- 10 files changed, 218 insertions(+), 163 deletions(-) create mode 100644 lib/screens/metering/components/shared/readings_container/components/equipment_profile_picker/widget_picker_equipment_profiles.dart create mode 100644 lib/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart create mode 100644 lib/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart create mode 100644 lib/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart create mode 100644 lib/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart rename lib/screens/metering/components/shared/readings_container/components/{ => shared}/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart (100%) rename lib/screens/metering/components/shared/readings_container/components/{ => shared}/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart (100%) rename lib/screens/metering/components/shared/readings_container/components/{ => shared}/animated_dialog_picker/widget_picker_dialog_animated.dart (89%) rename lib/screens/metering/components/shared/readings_container/components/{ => shared}/reading_value_container/widget_container_reading_value.dart (100%) diff --git a/lib/screens/metering/components/shared/readings_container/components/equipment_profile_picker/widget_picker_equipment_profiles.dart b/lib/screens/metering/components/shared/readings_container/components/equipment_profile_picker/widget_picker_equipment_profiles.dart new file mode 100644 index 0000000..f47cd53 --- /dev/null +++ b/lib/screens/metering/components/shared/readings_container/components/equipment_profile_picker/widget_picker_equipment_profiles.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; + +class EquipmentProfilePicker extends StatelessWidget { + const EquipmentProfilePicker(); + + @override + Widget build(BuildContext context) { + return AnimatedDialogPicker( + icon: Icons.camera, + title: S.of(context).equipmentProfile, + selectedValue: EquipmentProfiles.selectedOf(context), + values: EquipmentProfiles.of(context), + itemTitleBuilder: (_, value) => Text(value.id.isEmpty ? S.of(context).none : value.name), + onChanged: EquipmentProfileProvider.of(context).setProfile, + closedChild: ReadingValueContainer.singleValue( + value: ReadingValue( + label: S.of(context).equipmentProfile, + value: EquipmentProfiles.selectedOf(context).id.isEmpty + ? S.of(context).none + : EquipmentProfiles.selectedOf(context).name, + ), + ), + ); + } +} diff --git a/lib/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart b/lib/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart new file mode 100644 index 0000000..54c786c --- /dev/null +++ b/lib/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/data/models/exposure_pair.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; + +class ExtremeExposurePairsContainer extends StatelessWidget { + final ExposurePair? fastest; + final ExposurePair? slowest; + + const ExtremeExposurePairsContainer({ + required this.fastest, + required this.slowest, + super.key, + }); + + @override + Widget build(BuildContext context) { + return ReadingValueContainer( + values: [ + ReadingValue( + label: S.of(context).fastestExposurePair, + value: _exposurePairToString(context, fastest), + ), + ReadingValue( + label: S.of(context).slowestExposurePair, + value: _exposurePairToString(context, slowest), + ), + ], + ); + } + + String _exposurePairToString(BuildContext context, ExposurePair? pair) { + if (pair == null) { + return '-'; + } + + return '${pair.aperture} - ${Films.selectedOf(context).reciprocityFailure(pair.shutterSpeed)}'; + } +} diff --git a/lib/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart b/lib/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart new file mode 100644 index 0000000..fe136cc --- /dev/null +++ b/lib/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; + +class FilmPicker extends StatelessWidget { + final IsoValue selectedIso; + + const FilmPicker({required this.selectedIso}); + + @override + Widget build(BuildContext context) { + return AnimatedDialogPicker( + icon: Icons.camera_roll, + title: S.of(context).film, + selectedValue: Films.selectedOf(context), + values: Films.of(context), + itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name), + onChanged: FilmsProvider.of(context).setFilm, + closedChild: ReadingValueContainer.singleValue( + value: ReadingValue( + label: _label(context), + value: Films.selectedOf(context).name.isEmpty + ? S.of(context).none + : Films.selectedOf(context).name, + ), + ), + ); + } + + String _label(BuildContext context) { + if (Films.selectedOf(context) == const Film.other() || + Films.selectedOf(context).iso == selectedIso.value) { + return S.of(context).film; + } + + final evDiff = IsoValue( + Films.selectedOf(context).iso, + StopType.full, + ).difference(selectedIso); + + if (evDiff > 0) { + return S.of(context).filmPush; + } else if (evDiff < 0) { + return S.of(context).filmPull; + } else { + return S.of(context).film; + } + } +} diff --git a/lib/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart b/lib/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart new file mode 100644 index 0000000..a85b30c --- /dev/null +++ b/lib/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; + +class IsoValuePicker extends StatelessWidget { + final List values; + final IsoValue selectedValue; + final ValueChanged onChanged; + + const IsoValuePicker({ + required this.selectedValue, + required this.values, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return AnimatedDialogPicker( + icon: Icons.iso, + title: S.of(context).iso, + subtitle: S.of(context).filmSpeed, + selectedValue: selectedValue, + values: values, + itemTitleBuilder: (_, value) => Text(value.value.toString()), + // using ascending order, because increase in film speed rises EV + itemTrailingBuilder: (selected, value) => value.value != selected.value + ? Text(S.of(context).evValue(selected.toStringDifference(value))) + : null, + onChanged: onChanged, + closedChild: ReadingValueContainer.singleValue( + value: ReadingValue( + label: S.of(context).iso, + value: selectedValue.value.toString(), + ), + ), + ); + } +} diff --git a/lib/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart b/lib/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart new file mode 100644 index 0000000..eda016c --- /dev/null +++ b/lib/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; + +class NdValuePicker extends StatelessWidget { + final List values; + final NdValue selectedValue; + final ValueChanged onChanged; + + const NdValuePicker({ + required this.selectedValue, + required this.values, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return AnimatedDialogPicker( + icon: Icons.filter_b_and_w, + title: S.of(context).nd, + subtitle: S.of(context).ndFilterFactor, + selectedValue: selectedValue, + values: values, + itemTitleBuilder: (_, value) => Text( + value.value == 0 ? S.of(context).none : value.value.toString(), + ), + // using descending order, because ND filter darkens image & lowers EV + itemTrailingBuilder: (selected, value) => value.value != selected.value + ? Text(S.of(context).evValue(value.toStringDifference(selected))) + : null, + onChanged: onChanged, + closedChild: ReadingValueContainer.singleValue( + value: ReadingValue( + label: S.of(context).nd, + value: selectedValue.value.toString(), + ), + ), + ); + } +} diff --git a/lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart b/lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart similarity index 100% rename from lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart rename to lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart diff --git a/lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart b/lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart similarity index 100% rename from lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart rename to lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart diff --git a/lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart b/lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart similarity index 89% rename from lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart rename to lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart index d123d99..eeeec52 100644 --- a/lib/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart +++ b/lib/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/widget_picker_dialog_animated.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; - -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart'; // Has to be stateful, so that [GlobalKey] is not recreated. // Otherwise use will no be able to close the dialog after EV value has changed. diff --git a/lib/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart b/lib/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart similarity index 100% rename from lib/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart rename to lib/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart diff --git a/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart b/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart index 8802bd5..f10546d 100644 --- a/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart +++ b/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart @@ -1,11 +1,13 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; -import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/providers/user_preferences_provider.dart'; import 'package:lightmeter/res/dimens.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/equipment_profile_picker/widget_picker_equipment_profiles.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; @@ -36,24 +38,16 @@ class ReadingsContainer extends StatelessWidget { context, MeteringScreenLayoutFeature.equipmentProfiles, )) ...[ - const _EquipmentProfilePicker(), + const EquipmentProfilePicker(), const _InnerPadding(), ], if (UserPreferencesProvider.meteringScreenFeatureOf( context, MeteringScreenLayoutFeature.extremeExposurePairs, )) ...[ - ReadingValueContainer( - values: [ - ReadingValue( - label: S.of(context).fastestExposurePair, - value: fastest != null ? fastest!.toString() : '-', - ), - ReadingValue( - label: S.of(context).slowestExposurePair, - value: fastest != null ? slowest!.toString() : '-', - ), - ], + ExtremeExposurePairsContainer( + fastest: fastest, + slowest: slowest, ), const _InnerPadding(), ], @@ -61,13 +55,13 @@ class ReadingsContainer extends StatelessWidget { context, MeteringScreenLayoutFeature.filmPicker, )) ...[ - _FilmPicker(selectedIso: iso), + FilmPicker(selectedIso: iso), const _InnerPadding(), ], Row( children: [ Expanded( - child: _IsoValuePicker( + child: IsoValuePicker( selectedValue: iso, values: EquipmentProfiles.selectedOf(context).isoValues, onChanged: onIsoChanged, @@ -75,7 +69,7 @@ class ReadingsContainer extends StatelessWidget { ), const _InnerPadding(), Expanded( - child: _NdValuePicker( + child: NdValuePicker( selectedValue: nd, values: EquipmentProfiles.selectedOf(context).ndValues, onChanged: onNdChanged, @@ -91,145 +85,3 @@ class ReadingsContainer extends StatelessWidget { class _InnerPadding extends SizedBox { const _InnerPadding() : super(height: Dimens.grid8, width: Dimens.grid8); } - -class _EquipmentProfilePicker extends StatelessWidget { - const _EquipmentProfilePicker(); - - @override - Widget build(BuildContext context) { - return AnimatedDialogPicker( - icon: Icons.camera, - title: S.of(context).equipmentProfile, - selectedValue: EquipmentProfiles.selectedOf(context), - values: EquipmentProfiles.of(context), - itemTitleBuilder: (_, value) => Text(value.id.isEmpty ? S.of(context).none : value.name), - onChanged: EquipmentProfileProvider.of(context).setProfile, - closedChild: ReadingValueContainer.singleValue( - value: ReadingValue( - label: S.of(context).equipmentProfile, - value: EquipmentProfiles.selectedOf(context).id.isEmpty - ? S.of(context).none - : EquipmentProfiles.selectedOf(context).name, - ), - ), - ); - } -} - -class _FilmPicker extends StatelessWidget { - final IsoValue selectedIso; - - const _FilmPicker({required this.selectedIso}); - - @override - Widget build(BuildContext context) { - return AnimatedDialogPicker( - icon: Icons.camera_roll, - title: S.of(context).film, - selectedValue: Films.selectedOf(context), - values: Films.of(context), - itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name), - onChanged: FilmsProvider.of(context).setFilm, - closedChild: ReadingValueContainer.singleValue( - value: ReadingValue( - label: _label(context), - value: Films.selectedOf(context).name.isEmpty - ? S.of(context).none - : Films.selectedOf(context).name, - ), - ), - ); - } - - String _label(BuildContext context) { - if (Films.selectedOf(context) == const Film.other() || - Films.selectedOf(context).iso == selectedIso.value) { - return S.of(context).film; - } - - final evDiff = IsoValue( - Films.selectedOf(context).iso, - StopType.full, - ).difference(selectedIso); - - if (evDiff > 0) { - return S.of(context).filmPush; - } else if (evDiff < 0) { - return S.of(context).filmPull; - } else { - return S.of(context).film; - } - } -} - -class _IsoValuePicker extends StatelessWidget { - final List values; - final IsoValue selectedValue; - final ValueChanged onChanged; - - const _IsoValuePicker({ - required this.selectedValue, - required this.values, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return AnimatedDialogPicker( - icon: Icons.iso, - title: S.of(context).iso, - subtitle: S.of(context).filmSpeed, - selectedValue: selectedValue, - values: values, - itemTitleBuilder: (_, value) => Text(value.value.toString()), - // using ascending order, because increase in film speed rises EV - itemTrailingBuilder: (selected, value) => value.value != selected.value - ? Text(S.of(context).evValue(selected.toStringDifference(value))) - : null, - onChanged: onChanged, - closedChild: ReadingValueContainer.singleValue( - value: ReadingValue( - label: S.of(context).iso, - value: selectedValue.value.toString(), - ), - ), - ); - } -} - -class _NdValuePicker extends StatelessWidget { - final List values; - final NdValue selectedValue; - final ValueChanged onChanged; - - const _NdValuePicker({ - required this.selectedValue, - required this.values, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return AnimatedDialogPicker( - icon: Icons.filter_b_and_w, - title: S.of(context).nd, - subtitle: S.of(context).ndFilterFactor, - selectedValue: selectedValue, - values: values, - itemTitleBuilder: (_, value) => Text( - value.value == 0 ? S.of(context).none : value.value.toString(), - ), - // using descending order, because ND filter darkens image & lowers EV - itemTrailingBuilder: (selected, value) => value.value != selected.value - ? Text(S.of(context).evValue(value.toStringDifference(selected))) - : null, - onChanged: onChanged, - closedChild: ReadingValueContainer.singleValue( - value: ReadingValue( - label: S.of(context).nd, - value: selectedValue.value.toString(), - ), - ), - ); - } -}