// Térkép overlay és panel widget az importált rétegekhez. // Az ImportedLayer már kész flutter_map objektumokat tartalmaz — // itt csak megjelenítjük őket. import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:get/get.dart'; import 'package:latlong2/latlong.dart'; import 'package:terepi_seged/enums/layer_import_source_type.dart'; import '../../models/imported_layer.dart'; import '../../services/layer_import_service.dart'; // ════════════════════════════════════════════════════════════════════ // Térkép réteg — a flutter_map layers listájába kerül // ════════════════════════════════════════════════════════════════════ class ImportedLayerOverlay extends StatelessWidget { const ImportedLayerOverlay({super.key}); @override Widget build(BuildContext context) { if (!Get.isRegistered()) { return const SizedBox.shrink(); } return Obx(() { final visible = LayerImportService.to.visibleLayers; if (visible.isEmpty) return const SizedBox.shrink(); // Az összes látható réteg objektumait összegyűjtjük final polylines = visible.expand((l) => l.polylines).toList(); final polygons = visible.expand((l) => l.polygons).toList(); final markers = visible.expand((l) => l.markers).toList(); return Stack(children: [ if (polygons.isNotEmpty) PolygonLayer(polygons: polygons), if (polylines.isNotEmpty) PolylineLayer(polylines: polylines), if (markers.isNotEmpty) MarkerLayer(markers: markers), ]); }); } } // ════════════════════════════════════════════════════════════════════ // Réteg panel — import gomb + betöltött rétegek listája // ════════════════════════════════════════════════════════════════════ class ImportLayerPanel extends StatelessWidget { /// Ha meg van adva, a rétegre zoom gomb ezt hívja final void Function(LatLngBounds bounds)? onFitBounds; const ImportLayerPanel({super.key, this.onFitBounds}); @override Widget build(BuildContext context) { final svc = LayerImportService.to; return Obx(() => Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Import gomb _ImportButton(svc: svc), // Réteg lista if (svc.layers.isNotEmpty) ...[ const SizedBox(height: 12), const Divider(height: 1), const SizedBox(height: 8), ...svc.layers.map((layer) => _LayerTile( layer: layer, onToggle: () => svc.toggleLayer(layer.id), onRemove: () => svc.removeLayer(layer.id), onZoomTo: onFitBounds != null ? () { final b = layer.bounds; if (b != null) onFitBounds!(b); } : null, )), ], ], )); } } // ─── Import gomb ───────────────────────────────────────────────────────────── class _ImportButton extends StatelessWidget { final LayerImportService svc; const _ImportButton({required this.svc}); @override Widget build(BuildContext context) { return Obx(() => svc.isLoading.value ? const Padding( padding: EdgeInsets.symmetric(vertical: 8), child: Row(mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)), SizedBox(width: 8), Text('Betöltés...', style: TextStyle(fontSize: 13)), ]), ) : OutlinedButton.icon( onPressed: () => svc.importFile(), icon: const Icon(Icons.file_open_outlined, size: 18), label: const Text('GeoJSON / KML / KMZ'), )); } } // ─── Egy réteg sor ─────────────────────────────────────────────────────────── class _LayerTile extends StatelessWidget { final ImportedLayer layer; final VoidCallback onToggle; final VoidCallback onRemove; final VoidCallback? onZoomTo; const _LayerTile({ required this.layer, required this.onToggle, required this.onRemove, this.onZoomTo, }); @override Widget build(BuildContext context) { final icon = switch (layer.sourceType) { LayerImportSourceType.geoJson => Icons.data_object, LayerImportSourceType.kml => Icons.map_outlined, LayerImportSourceType.kmz => Icons.folder_zip_outlined, }; return Padding( padding: const EdgeInsets.only(bottom: 6), child: Row(children: [ // Láthatóság Transform.scale( scale: 0.85, child: Switch.adaptive( value: layer.isVisible, onChanged: (_) => onToggle(), ), ), // Ikon Icon(icon, size: 15, color: Colors.grey.shade500), const SizedBox(width: 6), // Név + statisztika Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text(layer.name, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis), Text(_stats(), style: TextStyle(fontSize: 10, color: Colors.grey.shade500)), ], ), ), // Zoom gomb if (onZoomTo != null) IconButton( icon: const Icon(Icons.fit_screen, size: 16), onPressed: onZoomTo, tooltip: 'Ráközelítés', padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 28, minHeight: 28), color: Colors.grey.shade500, ), // Törlés IconButton( icon: const Icon(Icons.close, size: 16), onPressed: onRemove, tooltip: 'Eltávolítás', padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 28, minHeight: 28), color: Colors.grey.shade400, ), ]), ); } String _stats() { final parts = []; if (layer.markers.isNotEmpty) parts.add('${layer.markers.length} pont'); if (layer.polylines.isNotEmpty) parts.add('${layer.polylines.length} vonal'); if (layer.polygons.isNotEmpty) parts.add('${layer.polygons.length} terület'); return parts.isEmpty ? 'Üres réteg' : parts.join(' · '); } }