From 1c344da29f4bcf77819edb6ef2261c0a665ad875 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Sun, 4 Dec 2022 22:12:52 +0300 Subject: [PATCH] Recalculate EV on ND change Recalculate EV on ND change `PhotographyValue` -> `PhotographyStopValue` --- lib/generated/intl/messages_en.dart | 2 ++ lib/generated/l10n.dart | 20 +++++++++++ lib/l10n/intl_en.arb | 2 ++ lib/models/aperture_value.dart | 7 ++-- lib/models/exposure_pair.dart | 3 +- lib/models/iso_value.dart | 7 ++-- lib/models/nd_value.dart | 31 +++++++++++++++++ lib/models/photography_value.dart | 17 +++++----- lib/models/shutter_speed_value.dart | 4 +-- .../components/exposure_pair_item.dart | 2 +- .../metering/components/topbar/topbar.dart | 33 ++++++++++++++++--- lib/screens/metering/metering_bloc.dart | 20 +++++++++-- lib/screens/metering/metering_event.dart | 9 ++++- lib/screens/metering/metering_screen.dart | 1 + lib/screens/metering/metering_state.dart | 5 +-- lib/utils/log_2.dart | 2 +- test/photograpy_values_test.dart | 3 ++ 17 files changed, 134 insertions(+), 34 deletions(-) create mode 100644 lib/models/nd_value.dart diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index f7ac216..1c1cacd 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -29,6 +29,8 @@ class MessageLookup extends MessageLookupByLibrary { "iso": MessageLookupByLibrary.simpleMessage("ISO"), "keepsScreenOn": MessageLookupByLibrary.simpleMessage("Keeps screen on"), + "nd": MessageLookupByLibrary.simpleMessage("ND"), + "none": MessageLookupByLibrary.simpleMessage("None"), "openSettings": MessageLookupByLibrary.simpleMessage("Open settings"), "permissionNeeded": MessageLookupByLibrary.simpleMessage("Permission needed"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index e6e18a2..c7d7453 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -110,6 +110,26 @@ class S { ); } + /// `ND` + String get nd { + return Intl.message( + 'ND', + name: 'nd', + desc: '', + args: [], + ); + } + + /// `None` + String get none { + return Intl.message( + 'None', + name: 'none', + desc: '', + args: [], + ); + } + /// `Cancel` String get cancel { return Intl.message( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 7f59ba1..adbf419 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -6,6 +6,8 @@ "fastestExposurePair": "Fastest", "slowestExposurePair": "Slowest", "iso": "ISO", + "nd": "ND", + "none": "None", "cancel": "Cancel", "select": "Select", "settings": "Settings", diff --git a/lib/models/aperture_value.dart b/lib/models/aperture_value.dart index 996c081..d790001 100644 --- a/lib/models/aperture_value.dart +++ b/lib/models/aperture_value.dart @@ -1,11 +1,8 @@ -part of 'photography_value.dart'; +import 'photography_value.dart'; -class ApertureValue extends PhotographyValue { +class ApertureValue extends PhotographyStopValue { const ApertureValue(super.rawValue, super.stopType); - @override - double get value => rawValue; - @override String toString() { final buffer = StringBuffer("f/"); diff --git a/lib/models/exposure_pair.dart b/lib/models/exposure_pair.dart index cfc2ed6..4fc6826 100644 --- a/lib/models/exposure_pair.dart +++ b/lib/models/exposure_pair.dart @@ -1,4 +1,5 @@ -import 'photography_value.dart'; +import 'aperture_value.dart'; +import 'shutter_speed_value.dart'; class ExposurePair { final ApertureValue aperture; diff --git a/lib/models/iso_value.dart b/lib/models/iso_value.dart index 6cef3cf..536cda6 100644 --- a/lib/models/iso_value.dart +++ b/lib/models/iso_value.dart @@ -1,11 +1,8 @@ -part of 'photography_value.dart'; +import 'photography_value.dart'; -class IsoValue extends PhotographyValue { +class IsoValue extends PhotographyStopValue { const IsoValue(super.rawValue, super.stopType); - @override - int get value => rawValue; - @override String toString() => value.toString(); } diff --git a/lib/models/nd_value.dart b/lib/models/nd_value.dart new file mode 100644 index 0000000..a30f1e8 --- /dev/null +++ b/lib/models/nd_value.dart @@ -0,0 +1,31 @@ +import 'package:lightmeter/utils/log_2.dart'; + +import 'photography_value.dart'; + +class NdValue extends PhotographyValue { + const NdValue(super.rawValue); + + double get stopReduction => value == 0 ? 0.0 : log2(value); + + @override + String toString() => 'ND$value'; +} + +/// https://shuttermuse.com/neutral-density-filter-numbers-names/ +const List ndValues = [ + NdValue(0), + NdValue(2), + NdValue(4), + NdValue(8), + NdValue(16), + NdValue(32), + NdValue(64), + NdValue(128), + NdValue(256), + NdValue(512), + NdValue(1024), + NdValue(2048), + NdValue(4096), + NdValue(8192), + NdValue(10000), +]; diff --git a/lib/models/photography_value.dart b/lib/models/photography_value.dart index a881dc4..59c8a07 100644 --- a/lib/models/photography_value.dart +++ b/lib/models/photography_value.dart @@ -1,19 +1,20 @@ -part 'aperture_value.dart'; -part 'iso_value.dart'; -part 'shutter_speed_value.dart'; - enum StopType { full, half, third } abstract class PhotographyValue { final T rawValue; - final StopType stopType; - const PhotographyValue(this.rawValue, this.stopType); + const PhotographyValue(this.rawValue); - T get value; + T get value => rawValue; } -extension PhotographyValues on List { +abstract class PhotographyStopValue extends PhotographyValue { + final StopType stopType; + + const PhotographyStopValue(super.rawValue, this.stopType); +} + +extension PhotographyStopValues on List { List whereStopType(StopType stopType) { switch (stopType) { case StopType.full: diff --git a/lib/models/shutter_speed_value.dart b/lib/models/shutter_speed_value.dart index d330d45..9e18c9b 100644 --- a/lib/models/shutter_speed_value.dart +++ b/lib/models/shutter_speed_value.dart @@ -1,6 +1,6 @@ -part of 'photography_value.dart'; +import 'photography_value.dart'; -class ShutterSpeedValue extends PhotographyValue { +class ShutterSpeedValue extends PhotographyStopValue { final bool isFraction; const ShutterSpeedValue(super.rawValue, this.isFraction, super.stopType); diff --git a/lib/screens/metering/components/exposure_pairs_list/components/exposure_pair_item.dart b/lib/screens/metering/components/exposure_pairs_list/components/exposure_pair_item.dart index 219de3f..c31e3ce 100644 --- a/lib/screens/metering/components/exposure_pairs_list/components/exposure_pair_item.dart +++ b/lib/screens/metering/components/exposure_pairs_list/components/exposure_pair_item.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/models/photography_value.dart'; import 'package:lightmeter/res/dimens.dart'; -class ExposurePaitListItem extends StatelessWidget { +class ExposurePaitListItem extends StatelessWidget { final T value; final bool tickOnTheLeft; diff --git a/lib/screens/metering/components/topbar/topbar.dart b/lib/screens/metering/components/topbar/topbar.dart index b9df605..374e549 100644 --- a/lib/screens/metering/components/topbar/topbar.dart +++ b/lib/screens/metering/components/topbar/topbar.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/models/exposure_pair.dart'; +import 'package:lightmeter/models/iso_value.dart'; +import 'package:lightmeter/models/nd_value.dart'; import 'package:lightmeter/models/photography_value.dart'; import 'package:lightmeter/res/dimens.dart'; @@ -12,13 +14,15 @@ import 'models/reading_value.dart'; class MeteringTopBar extends StatelessWidget { static const _columnsCount = 3; final _isoDialogKey = GlobalKey(); + final _ndDialogKey = GlobalKey(); final ExposurePair? fastest; final ExposurePair? slowest; final double ev; final IsoValue iso; - final double nd; + final NdValue nd; final ValueChanged onIsoChanged; + final ValueChanged onNdChanged; MeteringTopBar({ required this.fastest, @@ -27,6 +31,7 @@ class MeteringTopBar extends StatelessWidget { required this.iso, required this.nd, required this.onIsoChanged, + required this.onNdChanged, super.key, }); @@ -137,10 +142,28 @@ class MeteringTopBar extends StatelessWidget { ), ), const _InnerPadding(), - ReadingContainer.singleValue( - value: ReadingValue( - label: 'ND', - value: nd.toString(), + AnimatedDialog( + key: _ndDialogKey, + closedChild: ReadingContainer.singleValue( + value: ReadingValue( + label: S.of(context).nd, + value: nd.value.toString(), + ), + ), + openedChild: MeteringScreenDialogPicker( + title: S.of(context).nd, + initialValue: nd, + values: ndValues, + itemTitleBuilder: (context, value) => Text( + value.value == 0 ? S.of(context).none : value.value.toString(), + style: Theme.of(context).textTheme.bodyLarge, + ), + onCancel: () { + _ndDialogKey.currentState?.close(); + }, + onSelect: (value) { + _ndDialogKey.currentState?.close().then((_) => onNdChanged(value)); + }, ), ), ], diff --git a/lib/screens/metering/metering_bloc.dart b/lib/screens/metering/metering_bloc.dart index e469211..1ce65bb 100644 --- a/lib/screens/metering/metering_bloc.dart +++ b/lib/screens/metering/metering_bloc.dart @@ -1,8 +1,12 @@ import 'dart:math'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:lightmeter/models/aperture_value.dart'; import 'package:lightmeter/models/exposure_pair.dart'; +import 'package:lightmeter/models/iso_value.dart'; +import 'package:lightmeter/models/nd_value.dart'; import 'package:lightmeter/models/photography_value.dart'; +import 'package:lightmeter/models/shutter_speed_value.dart'; import 'package:lightmeter/utils/log_2.dart'; import 'metering_event.dart'; @@ -21,11 +25,12 @@ class MeteringBloc extends Bloc { iso: isoValues.where((element) => element.value == 100).first, ev: 21.3, evCompensation: 0.0, - nd: 0.0, + nd: ndValues.first, exposurePairs: [], ), ) { on(_onIsoChanged); + on(_onNdChanged); on(_onMeasure); add(const MeasureEvent()); @@ -42,10 +47,19 @@ class MeteringBloc extends Bloc { )); } + void _onNdChanged(NdChangedEvent event, Emitter emit) { + final ev = state.ev - event.ndValue.stopReduction + state.nd.stopReduction; + emit(MeteringState( + iso: state.iso, + ev: ev, + evCompensation: state.evCompensation, + nd: event.ndValue, + exposurePairs: _buildExposureValues(ev), + )); + } + /// https://www.scantips.com/lights/exposurecalc.html void _onMeasure(_, Emitter emit) { - double log2(double x) => log(x) / log(2); - final aperture = _apertureValues[_random.nextInt(_apertureValues.length)]; final shutterSpeed = _shutterSpeedValues[_random.nextInt(_shutterSpeedValues.thirdStops().length)]; final iso = _isoValues[_random.nextInt(_isoValues.thirdStops().length)]; diff --git a/lib/screens/metering/metering_event.dart b/lib/screens/metering/metering_event.dart index ecc5e9f..9576e16 100644 --- a/lib/screens/metering/metering_event.dart +++ b/lib/screens/metering/metering_event.dart @@ -1,4 +1,5 @@ -import 'package:lightmeter/models/photography_value.dart'; +import 'package:lightmeter/models/iso_value.dart'; +import 'package:lightmeter/models/nd_value.dart'; abstract class MeteringEvent { const MeteringEvent(); @@ -10,6 +11,12 @@ class IsoChangedEvent extends MeteringEvent { const IsoChangedEvent(this.isoValue); } +class NdChangedEvent extends MeteringEvent { + final NdValue ndValue; + + const NdChangedEvent(this.ndValue); +} + class MeasureEvent extends MeteringEvent { const MeasureEvent(); } diff --git a/lib/screens/metering/metering_screen.dart b/lib/screens/metering/metering_screen.dart index 775edbf..ab78803 100644 --- a/lib/screens/metering/metering_screen.dart +++ b/lib/screens/metering/metering_screen.dart @@ -113,6 +113,7 @@ class _MeteringScreenState extends State { iso: state.iso, nd: state.nd, onIsoChanged: (value) => context.read().add(IsoChangedEvent(value)), + onNdChanged: (value) => context.read().add(NdChangedEvent(value)), ); } diff --git a/lib/screens/metering/metering_state.dart b/lib/screens/metering/metering_state.dart index d180710..f6dbb17 100644 --- a/lib/screens/metering/metering_state.dart +++ b/lib/screens/metering/metering_state.dart @@ -1,11 +1,12 @@ import 'package:lightmeter/models/exposure_pair.dart'; -import 'package:lightmeter/models/photography_value.dart'; +import 'package:lightmeter/models/iso_value.dart'; +import 'package:lightmeter/models/nd_value.dart'; class MeteringState { final double ev; final double evCompensation; final IsoValue iso; - final double nd; + final NdValue nd; final List exposurePairs; const MeteringState({ diff --git a/lib/utils/log_2.dart b/lib/utils/log_2.dart index 83b847f..37bcc92 100644 --- a/lib/utils/log_2.dart +++ b/lib/utils/log_2.dart @@ -1,3 +1,3 @@ import 'dart:math'; -double log2(double x) => log(x) / log(2); +double log2(num x) => log(x) / log(2); diff --git a/test/photograpy_values_test.dart b/test/photograpy_values_test.dart index be3f63d..7af90b9 100644 --- a/test/photograpy_values_test.dart +++ b/test/photograpy_values_test.dart @@ -1,4 +1,7 @@ +import 'package:lightmeter/models/aperture_value.dart'; +import 'package:lightmeter/models/iso_value.dart'; import 'package:lightmeter/models/photography_value.dart'; +import 'package:lightmeter/models/shutter_speed_value.dart'; import 'package:test/test.dart'; void main() {