267 lines
11 KiB
Dart
267 lines
11 KiB
Dart
|
|
// Bemérés mód alsó panel:
|
|||
|
|
// - Aktuális koordináták (WGS84 + EOV)
|
|||
|
|
// - GPS minőség + pontosság
|
|||
|
|
// - Rögzített pontok száma
|
|||
|
|
// - Nagy "Pont rögzítése" gomb
|
|||
|
|
|
|||
|
|
import 'package:flutter/material.dart';
|
|||
|
|
import 'package:get/get.dart';
|
|||
|
|
import 'package:terepi_seged/services/gnss/gnss_connection.dart';
|
|||
|
|
import 'package:terepi_seged/services/gnss/gnss_service.dart';
|
|||
|
|
|
|||
|
|
import '../../pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
|||
|
|
|
|||
|
|
class MeasureBottomPanel extends StatelessWidget {
|
|||
|
|
final MapSurveyController ctrl;
|
|||
|
|
const MeasureBottomPanel({super.key, required this.ctrl});
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
Widget build(BuildContext context) {
|
|||
|
|
final cs = Theme.of(context).colorScheme;
|
|||
|
|
|
|||
|
|
return Container(
|
|||
|
|
decoration: BoxDecoration(
|
|||
|
|
color: cs.surface,
|
|||
|
|
boxShadow: [
|
|||
|
|
BoxShadow(
|
|||
|
|
color: Colors.black.withOpacity(0.12),
|
|||
|
|
blurRadius: 12,
|
|||
|
|
offset: const Offset(0, -3),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
child: SafeArea(
|
|||
|
|
top: false,
|
|||
|
|
child: Padding(
|
|||
|
|
padding: const EdgeInsets.fromLTRB(16, 10, 16, 8),
|
|||
|
|
child: Column(
|
|||
|
|
mainAxisSize: MainAxisSize.min,
|
|||
|
|
children: [
|
|||
|
|
// ── Koordináta sor ─────────────────────────────────────
|
|||
|
|
Obx(() {
|
|||
|
|
final lat = ctrl.gpsLatitude.value;
|
|||
|
|
final lon = ctrl.gpsLongitude.value;
|
|||
|
|
final eovY = ctrl.eovY.value;
|
|||
|
|
final eovX = ctrl.eovX.value;
|
|||
|
|
final hasGps = GnssService.to.connectionState.value ==
|
|||
|
|
GnssConnectionState.connected;
|
|||
|
|
|
|||
|
|
if (!hasGps) {
|
|||
|
|
return Padding(
|
|||
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|||
|
|
child: Text(
|
|||
|
|
'GPS pozíció nem elérhető',
|
|||
|
|
style:
|
|||
|
|
TextStyle(color: cs.onSurfaceVariant, fontSize: 12),
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Padding(
|
|||
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|||
|
|
child: Row(
|
|||
|
|
children: [
|
|||
|
|
// WGS84
|
|||
|
|
Expanded(
|
|||
|
|
child: Column(
|
|||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|||
|
|
children: [
|
|||
|
|
Text('WGS84',
|
|||
|
|
style: TextStyle(
|
|||
|
|
fontSize: 10,
|
|||
|
|
color: cs.onSurfaceVariant,
|
|||
|
|
fontWeight: FontWeight.w500)),
|
|||
|
|
Text(
|
|||
|
|
'${lat.toStringAsFixed(7)}°',
|
|||
|
|
style: const TextStyle(
|
|||
|
|
fontSize: 12,
|
|||
|
|
fontFeatures: [FontFeature.tabularFigures()]),
|
|||
|
|
),
|
|||
|
|
Text(
|
|||
|
|
'${lon.toStringAsFixed(7)}°',
|
|||
|
|
style: const TextStyle(
|
|||
|
|
fontSize: 12,
|
|||
|
|
fontFeatures: [FontFeature.tabularFigures()]),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
|
|||
|
|
Container(
|
|||
|
|
width: 1,
|
|||
|
|
height: 36,
|
|||
|
|
color: cs.outlineVariant,
|
|||
|
|
margin: const EdgeInsets.symmetric(horizontal: 10)),
|
|||
|
|
|
|||
|
|
// EOV
|
|||
|
|
Expanded(
|
|||
|
|
child: Column(
|
|||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|||
|
|
children: [
|
|||
|
|
Text('EOV',
|
|||
|
|
style: TextStyle(
|
|||
|
|
fontSize: 10,
|
|||
|
|
color: cs.onSurfaceVariant,
|
|||
|
|
fontWeight: FontWeight.w500)),
|
|||
|
|
Text(
|
|||
|
|
'Y: ${eovY == 0 ? "–" : eovY.toStringAsFixed(1)}',
|
|||
|
|
style: const TextStyle(
|
|||
|
|
fontSize: 12,
|
|||
|
|
fontFeatures: [FontFeature.tabularFigures()]),
|
|||
|
|
),
|
|||
|
|
Text(
|
|||
|
|
'X: ${eovX == 0 ? "–" : eovX.toStringAsFixed(1)}',
|
|||
|
|
style: const TextStyle(
|
|||
|
|
fontSize: 12,
|
|||
|
|
fontFeatures: [FontFeature.tabularFigures()]),
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
|
|||
|
|
Container(
|
|||
|
|
width: 1,
|
|||
|
|
height: 36,
|
|||
|
|
color: cs.outlineVariant,
|
|||
|
|
margin: const EdgeInsets.symmetric(horizontal: 10)),
|
|||
|
|
|
|||
|
|
// Pontosság
|
|||
|
|
Column(
|
|||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|||
|
|
children: [
|
|||
|
|
Text('Pontosság',
|
|||
|
|
style: TextStyle(
|
|||
|
|
fontSize: 10,
|
|||
|
|
color: cs.onSurfaceVariant,
|
|||
|
|
fontWeight: FontWeight.w500)),
|
|||
|
|
Obx(() => Text(
|
|||
|
|
'H: ${ctrl.horizontalAccuracyText}',
|
|||
|
|
style: TextStyle(
|
|||
|
|
fontSize: 12,
|
|||
|
|
color: _accuracyColor(
|
|||
|
|
ctrl.gpsLatitudeError.value,
|
|||
|
|
ctrl.gpsLongitudeError.value),
|
|||
|
|
fontWeight: FontWeight.w600,
|
|||
|
|
fontFeatures: const [
|
|||
|
|
FontFeature.tabularFigures()
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
)),
|
|||
|
|
Obx(() => Text(
|
|||
|
|
'V: ${ctrl.verticalAccuracyText}',
|
|||
|
|
style: TextStyle(
|
|||
|
|
fontSize: 12,
|
|||
|
|
color: _accuracyColor(
|
|||
|
|
ctrl.gpsAltitudeError.value,
|
|||
|
|
ctrl.gpsAltitudeError.value),
|
|||
|
|
fontWeight: FontWeight.w600,
|
|||
|
|
fontFeatures: const [
|
|||
|
|
FontFeature.tabularFigures()
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
)),
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
}),
|
|||
|
|
|
|||
|
|
const Divider(height: 1),
|
|||
|
|
const SizedBox(height: 8),
|
|||
|
|
|
|||
|
|
// ── Minőség chip + rögzített pontok + gomb ─────────────
|
|||
|
|
Row(
|
|||
|
|
children: [
|
|||
|
|
// GPS minőség chip
|
|||
|
|
Obx(() {
|
|||
|
|
final q = ctrl.gpsQuality.value;
|
|||
|
|
final color = ctrl.getCurrentLocationMarkerColor(q);
|
|||
|
|
final label = ctrl.getGpsQualityIndicator(quality: q);
|
|||
|
|
return Container(
|
|||
|
|
padding: const EdgeInsets.symmetric(
|
|||
|
|
horizontal: 8, vertical: 4),
|
|||
|
|
decoration: BoxDecoration(
|
|||
|
|
color: color.withOpacity(0.15),
|
|||
|
|
borderRadius: BorderRadius.circular(6),
|
|||
|
|
border: Border.all(color: color.withOpacity(0.5)),
|
|||
|
|
),
|
|||
|
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
|||
|
|
Container(
|
|||
|
|
width: 7,
|
|||
|
|
height: 7,
|
|||
|
|
decoration: BoxDecoration(
|
|||
|
|
color: color, shape: BoxShape.circle),
|
|||
|
|
),
|
|||
|
|
const SizedBox(width: 5),
|
|||
|
|
Text(label,
|
|||
|
|
style: TextStyle(
|
|||
|
|
fontSize: 11,
|
|||
|
|
color: color,
|
|||
|
|
fontWeight: FontWeight.w600)),
|
|||
|
|
]),
|
|||
|
|
);
|
|||
|
|
}),
|
|||
|
|
|
|||
|
|
const SizedBox(width: 8),
|
|||
|
|
|
|||
|
|
// Rögzített pontok száma
|
|||
|
|
Obx(() {
|
|||
|
|
final count = ctrl.pointWithDescriptionList.length;
|
|||
|
|
return Container(
|
|||
|
|
padding: const EdgeInsets.symmetric(
|
|||
|
|
horizontal: 8, vertical: 4),
|
|||
|
|
decoration: BoxDecoration(
|
|||
|
|
color: cs.surfaceContainerHighest,
|
|||
|
|
borderRadius: BorderRadius.circular(6),
|
|||
|
|
),
|
|||
|
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
|||
|
|
Icon(Icons.location_on,
|
|||
|
|
size: 13, color: Colors.amber.shade700),
|
|||
|
|
const SizedBox(width: 4),
|
|||
|
|
Text('$count pont',
|
|||
|
|
style: const TextStyle(
|
|||
|
|
fontSize: 11, fontWeight: FontWeight.w500)),
|
|||
|
|
]),
|
|||
|
|
);
|
|||
|
|
}),
|
|||
|
|
|
|||
|
|
const Spacer(),
|
|||
|
|
IconButton(
|
|||
|
|
onPressed: ctrl.openMeasuredPointsList,
|
|||
|
|
icon: const Icon(Icons.list_alt_outlined),
|
|||
|
|
tooltip: 'Bemért pontok'),
|
|||
|
|
const SizedBox(width: 4),
|
|||
|
|
|
|||
|
|
// Pont rögzítése gomb
|
|||
|
|
Obx(() {
|
|||
|
|
final hasGps = GnssService.to.connectionState.value ==
|
|||
|
|
GnssConnectionState.connected;
|
|||
|
|
return FilledButton.icon(
|
|||
|
|
onPressed: hasGps ? ctrl.showAddPointDialog : null,
|
|||
|
|
icon: const Icon(Icons.add_location_alt, size: 18),
|
|||
|
|
label: const Text('Rögzítés'),
|
|||
|
|
style: FilledButton.styleFrom(
|
|||
|
|
padding: const EdgeInsets.symmetric(
|
|||
|
|
horizontal: 16, vertical: 10),
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
})
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
],
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Color _accuracyColor(double e1, double e2) {
|
|||
|
|
final e = e1 > e2 ? e1 : e2;
|
|||
|
|
if (e <= 0.05) return Colors.green;
|
|||
|
|
if (e <= 0.20) return Colors.lightGreen;
|
|||
|
|
if (e <= 1.00) return Colors.orange;
|
|||
|
|
return Colors.red;
|
|||
|
|
}
|
|||
|
|
}
|