One settings table in CameraBridge watches every camera value into the telemetry tick and backs a generic setCameraValue, so the tabbed camera menu (Exposure / Photo / Video / Other) is built from row specs and the camera's own capability ranges. Writes show at once and fall back to what the camera reports. Adds the quick exposure panel (Auto/A/S/M, ISO slider, shutter and aperture wheels, EV strip, metered EV in M), a new camera column with record timer and interval/pano progress, a zoom column for zoom cameras, tap-to-focus / tap-to-meter, and a live histogram. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
2.0 KiB
Dart
64 lines
2.0 KiB
Dart
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../../../fly/state/camera_state.dart';
|
|
import '../../../theme.dart';
|
|
|
|
/// The live luminance histogram, shown while the camera menu's Histogram row is
|
|
/// on and the camera is streaming bins (plan P4).
|
|
class HistogramView extends StatelessWidget {
|
|
const HistogramView({super.key, required this.camera});
|
|
|
|
final CameraState camera;
|
|
|
|
static const Size size = Size(120, 48);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ListenableBuilder(
|
|
listenable: camera,
|
|
builder: (BuildContext context, _) {
|
|
if (!camera.histogramEnabled) return const SizedBox.shrink();
|
|
return ValueListenableBuilder<List<int>?>(
|
|
valueListenable: camera.histogram,
|
|
builder: (BuildContext context, List<int>? bins, _) {
|
|
if (bins == null || bins.isEmpty) return const SizedBox.shrink();
|
|
return Container(
|
|
key: const ValueKey<String>('histogram'),
|
|
width: size.width,
|
|
height: size.height,
|
|
padding: const EdgeInsets.all(5),
|
|
decoration: BoxDecoration(color: Glass.pill, borderRadius: BorderRadius.circular(8)),
|
|
child: CustomPaint(painter: HistogramPainter(bins)),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class HistogramPainter extends CustomPainter {
|
|
const HistogramPainter(this.bins);
|
|
|
|
final List<int> bins;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
if (bins.length < 2) return;
|
|
final int peak = math.max(1, bins.reduce(math.max));
|
|
final Path p = Path()..moveTo(0, size.height);
|
|
for (int i = 0; i < bins.length; i++) {
|
|
p.lineTo(size.width * i / (bins.length - 1), size.height * (1 - bins[i] / peak));
|
|
}
|
|
p
|
|
..lineTo(size.width, size.height)
|
|
..close();
|
|
canvas.drawPath(p, Paint()..color = const Color(0x99EAF0FA));
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant HistogramPainter old) => !identical(old.bins, bins);
|
|
}
|