// 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'; import '../map_edit_tools/imported_layer_style_sheet.dart'; import '../map_edit_tools/style_editable.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; final styles = LayerImportService.to.layerStyles; if (visible.isEmpty) return const SizedBox.shrink(); final polylines = []; final polygons = []; final markers = []; for (final layer in visible) { final style = styles[layer.id]; // ← override ha van if (style != null) { // Stílussal felülírva polylines.addAll(layer.polylines.map((p) => Polyline( points: p.points, color: style.color.withOpacity(0.85), strokeWidth: style.strokeWidth, ))); polygons.addAll(layer.polygons.map((p) => Polygon( points: p.points, holePointsList: p.holePointsList, color: style.color.withOpacity(style.opacity), borderColor: style.color, borderStrokeWidth: style.strokeWidth, label: p.label, ))); markers.addAll(layer.markers); // marker szín nem változik egyszerűen } else { // Eredeti stílus polylines.addAll(layer.polylines); polygons.addAll(layer.polygons); markers.addAll(layer.markers); } } 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, ), IconButton( icon: const Icon(Icons.palette_outlined, size: 16), onPressed: () => _openStyleSheet(context, layer), tooltip: 'Stílus szerkesztése'), // 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, ), ]), ); } void _openStyleSheet(BuildContext context, ImportedLayer layer) { final svc = LayerImportService.to; final current = svc.getLayerStyle(layer.id); final session = LayerStyleSession( color: current?.color ?? const Color(0xFF1565C0), opacity: current?.opacity ?? 0.35, strokeWidth: current?.strokeWidth ?? 2.5, ); Get.bottomSheet( ImportedLayerStyleSheet( layerName: layer.name, session: session, onSave: () => svc.setLayerStyle( layer.id, ImportedLayerStyle( color: session.activeEditColor.value, opacity: session.activeEditOpacity.value, strokeWidth: session.activeEditStrokeWidth.value, )), onReset: () { svc.layerStyles.remove(layer.id); svc.layers.refresh(); }, ), isScrollControlled: true, backgroundColor: Colors.transparent, ); } 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(' · '); } }