mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-25 00:40:39 +00:00
Added stop fraction picker
TODO: fix `MeteringScreen` double build on fraction change
This commit is contained in:
parent
9143701b76
commit
10764086ad
8 changed files with 147 additions and 17 deletions
|
@ -13,6 +13,10 @@
|
|||
"cancel": "Cancel",
|
||||
"select": "Select",
|
||||
"settings": "Settings",
|
||||
"fractionalStops": "Fractional stops",
|
||||
"showFractionalStops": "Show fractional stops",
|
||||
"halfStops": "1/2",
|
||||
"thirdStops": "1/3",
|
||||
"caffeine": "Caffeine",
|
||||
"keepsScreenOn": "Keeps screen on",
|
||||
"haptics": "Haptics"
|
||||
|
|
|
@ -13,12 +13,12 @@ import 'metering_event.dart';
|
|||
import 'metering_state.dart';
|
||||
|
||||
class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
|
||||
final StopType stopType;
|
||||
late final _apertureValues = apertureValues.whereStopType(stopType);
|
||||
late final _shutterSpeedValues = shutterSpeedValues.whereStopType(stopType);
|
||||
late final _isoValues = isoValues.whereStopType(stopType);
|
||||
List<ApertureValue> get _apertureValues => apertureValues.whereStopType(stopType);
|
||||
List<ShutterSpeedValue> get _shutterSpeedValues => shutterSpeedValues.whereStopType(stopType);
|
||||
final _random = Random();
|
||||
|
||||
StopType stopType;
|
||||
|
||||
MeteringBloc(this.stopType)
|
||||
: super(
|
||||
MeteringState(
|
||||
|
@ -29,6 +29,7 @@ class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
|
|||
exposurePairs: [],
|
||||
),
|
||||
) {
|
||||
on<StopTypeChangedEvent>(_onStopTypeChanged);
|
||||
on<IsoChangedEvent>(_onIsoChanged);
|
||||
on<NdChangedEvent>(_onNdChanged);
|
||||
on<MeasureEvent>(_onMeasure);
|
||||
|
@ -36,6 +37,17 @@ class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
|
|||
add(const MeasureEvent());
|
||||
}
|
||||
|
||||
void _onStopTypeChanged(StopTypeChangedEvent event, Emitter emit) {
|
||||
stopType = event.stopType;
|
||||
emit(MeteringState(
|
||||
iso: state.iso,
|
||||
ev: state.ev,
|
||||
evCompensation: state.evCompensation,
|
||||
nd: state.nd,
|
||||
exposurePairs: _buildExposureValues(state.ev),
|
||||
));
|
||||
}
|
||||
|
||||
void _onIsoChanged(IsoChangedEvent event, Emitter emit) {
|
||||
final ev = state.ev + log2(event.isoValue.value / state.iso.value);
|
||||
emit(MeteringState(
|
||||
|
@ -62,7 +74,7 @@ class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
|
|||
void _onMeasure(_, Emitter emit) {
|
||||
final aperture = _apertureValues[_random.nextInt(_apertureValues.length)];
|
||||
final shutterSpeed = _shutterSpeedValues[_random.nextInt(_shutterSpeedValues.thirdStops().length)];
|
||||
final iso = _isoValues[_random.nextInt(_isoValues.thirdStops().length)];
|
||||
final iso = isoValues[_random.nextInt(isoValues.thirdStops().length)];
|
||||
|
||||
final evAtSystemIso = log2(pow(aperture.value, 2).toDouble() / shutterSpeed.value);
|
||||
final ev = evAtSystemIso - log2(iso.value / state.iso.value);
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import 'package:lightmeter/models/iso_value.dart';
|
||||
import 'package:lightmeter/models/nd_value.dart';
|
||||
import 'package:lightmeter/models/photography_value.dart';
|
||||
|
||||
abstract class MeteringEvent {
|
||||
const MeteringEvent();
|
||||
}
|
||||
|
||||
class StopTypeChangedEvent extends MeteringEvent {
|
||||
final StopType stopType;
|
||||
|
||||
const StopTypeChangedEvent(this.stopType);
|
||||
}
|
||||
|
||||
class IsoChangedEvent extends MeteringEvent {
|
||||
final IsoValue isoValue;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:lightmeter/models/photography_value.dart';
|
||||
import 'package:lightmeter/res/dimens.dart';
|
||||
import 'package:lightmeter/screens/settings/settings_page_route_builder.dart';
|
||||
|
||||
|
@ -43,6 +44,12 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
context.read<MeteringBloc>().add(StopTypeChangedEvent(context.watch<StopType>()));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:lightmeter/generated/l10n.dart';
|
||||
import 'package:lightmeter/models/photography_value.dart';
|
||||
|
||||
class FractionalStopsDialog extends StatefulWidget {
|
||||
final StopType selectedType;
|
||||
|
||||
const FractionalStopsDialog({required this.selectedType, super.key});
|
||||
|
||||
@override
|
||||
State<FractionalStopsDialog> createState() => _FractionalStopsDialogState();
|
||||
}
|
||||
|
||||
class _FractionalStopsDialogState extends State<FractionalStopsDialog> {
|
||||
late StopType _selected = widget.selectedType;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: Text(S.of(context).showFractionalStops),
|
||||
children: [
|
||||
RadioListTile<StopType>(
|
||||
value: StopType.full,
|
||||
groupValue: _selected,
|
||||
title: Text(S.of(context).none),
|
||||
onChanged: _onChanged,
|
||||
),
|
||||
RadioListTile<StopType>(
|
||||
value: StopType.half,
|
||||
groupValue: _selected,
|
||||
title: Text(S.of(context).halfStops),
|
||||
onChanged: _onChanged,
|
||||
),
|
||||
RadioListTile<StopType>(
|
||||
value: StopType.third,
|
||||
groupValue: _selected,
|
||||
title: Text(S.of(context).thirdStops),
|
||||
onChanged: _onChanged,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _onChanged(StopType? value) {
|
||||
setState(() {
|
||||
_selected = value!;
|
||||
});
|
||||
Navigator.of(context).pop(_selected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:lightmeter/generated/l10n.dart';
|
||||
import 'package:lightmeter/models/photography_value.dart';
|
||||
import 'package:lightmeter/utils/stop_type_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'dialog_fractional_stops.dart';
|
||||
|
||||
class FractionalStopsListTile extends StatefulWidget {
|
||||
const FractionalStopsListTile({super.key});
|
||||
|
||||
@override
|
||||
State<FractionalStopsListTile> createState() => _FractionalStopsListTileState();
|
||||
}
|
||||
|
||||
class _FractionalStopsListTileState extends State<FractionalStopsListTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: Text(S.of(context).fractionalStops),
|
||||
trailing: Text(selectedType),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => FractionalStopsDialog(selectedType: context.read<StopType>()),
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
StopTypeProvider.of(context).set(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String get selectedType {
|
||||
switch (context.watch<StopType>()) {
|
||||
case StopType.full:
|
||||
return S.of(context).none;
|
||||
case StopType.half:
|
||||
return S.of(context).halfStops;
|
||||
case StopType.third:
|
||||
return S.of(context).thirdStops;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import 'package:lightmeter/res/dimens.dart';
|
|||
|
||||
import 'components/caffeine_tile.dart';
|
||||
import 'components/haptics_tile.dart';
|
||||
import 'components/fractional_stops/list_tile_fractional_stops.dart';
|
||||
|
||||
class SettingsScreen extends StatelessWidget {
|
||||
const SettingsScreen({super.key});
|
||||
|
@ -36,6 +37,7 @@ class SettingsScreen extends StatelessWidget {
|
|||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
const FractionalStopsListTile(),
|
||||
const CaffeineListTile(),
|
||||
const HapticsListTile(),
|
||||
],
|
||||
|
|
|
@ -7,27 +7,30 @@ class StopTypeProvider extends StatefulWidget {
|
|||
|
||||
const StopTypeProvider({this.child, super.key});
|
||||
|
||||
static StopTypeProviderState of(BuildContext context) {
|
||||
return context.findAncestorStateOfType<StopTypeProviderState>()!;
|
||||
}
|
||||
|
||||
@override
|
||||
State<StopTypeProvider> createState() => StopTypeProviderState();
|
||||
}
|
||||
|
||||
class StopTypeProviderState extends State<StopTypeProvider> {
|
||||
StopType stopType = StopType.full;
|
||||
StopType _stopType = StopType.third;
|
||||
|
||||
StopType get stopType => _stopType;
|
||||
|
||||
void set(StopType type) {
|
||||
setState(() {
|
||||
_stopType = type;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Provider.value(
|
||||
value: stopType,
|
||||
child: Provider.value(
|
||||
value: this,
|
||||
child: widget.child,
|
||||
),
|
||||
value: _stopType,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
void setStopType(StopType type) {
|
||||
setState(() {
|
||||
stopType = type;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue