MobilApp/lib/models/note_item.dart

184 lines
5.5 KiB
Dart
Raw Normal View History

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import '../enums/note_type.dart';
class NoteItem {
final int? id;
final int? projectId;
final NoteType type;
final List<LatLng> points; // ← szerkesztéshez mindig elérhető
final Color color;
final double opacity;
final double strokeWidth;
final Color strokeColor;
final String label;
final DateTime createdAt;
const NoteItem(
{this.id,
this.projectId,
required this.type,
required this.points,
required this.color,
this.opacity = 0.5,
this.strokeWidth = 3.0,
required this.strokeColor,
this.label = '',
required this.createdAt});
NoteItem copyWith({
List<LatLng>? points,
Color? color,
double? opacity,
double? strokeWidth,
Color? strokeColor,
String? label,
}) =>
NoteItem(
id: id,
projectId: projectId,
type: type,
points: points ?? this.points,
color: color ?? this.color,
opacity: opacity ?? this.opacity,
strokeWidth: strokeWidth ?? this.strokeWidth,
strokeColor: strokeColor ?? this.strokeColor,
label: label ?? this.label,
createdAt: createdAt,
);
// ── Koordináta ↔ GeoJSON ────────────────────────────────────────
static List<LatLng> _parsePoints(String json) {
final geom = jsonDecode(json) as Map<String, dynamic>;
final gType = geom['type'] as String;
final coords = geom['coordinates'];
switch (gType) {
case 'Point':
final c = coords as List;
return [
LatLng(
(c[1] as num).toDouble(),
(c[0] as num).toDouble(),
)
];
case 'LineString':
return (coords as List)
.map((c) => LatLng(
(c[1] as num).toDouble(),
(c[0] as num).toDouble(),
))
.toList();
case 'Polygon':
// Külső gyűrű (index 0)
return ((coords as List)[0] as List)
.map((c) => LatLng(
(c[1] as num).toDouble(),
(c[0] as num).toDouble(),
))
.toList();
default:
return [];
}
}
String _toPointsJson() {
List<dynamic> coords;
String gType;
switch (type) {
case NoteType.point:
// GeoJSON: [lon, lat]
gType = 'Point';
coords = [points.first.longitude, points.first.latitude];
case NoteType.line:
gType = 'LineString';
coords = points.map((p) => [p.longitude, p.latitude]).toList();
case NoteType.polygon:
gType = 'Polygon';
final ring = points.map((p) => [p.longitude, p.latitude]).toList();
// Polygon zárt: első = utolsó pont
if (ring.isNotEmpty) {
final first = ring.first;
final last = ring.last;
final isClosed = first[0] == last[0] && first[1] == last[1];
if (!isClosed) ring.add(List.from(first));
}
coords = [ring];
}
return jsonEncode({'type': gType, 'coordinates': coords});
}
// ── SQLite ↔ Map ────────────────────────────────────────────────
static Color _parseColor(String hex) {
final h = hex.replaceFirst('#', '');
return Color(int.parse(h.length == 6 ? 'FF$h' : h, radix: 16));
}
static String _colorHex(Color c) =>
'#${c.value.toRadixString(16).padLeft(8, '0').substring(2).toUpperCase()}';
Map<String, dynamic> toMap() => {
if (id != null) 'id': id,
if (projectId != null) 'project_id': projectId,
'type': type.name,
'points_json': _toPointsJson(),
'color': _colorHex(color),
'opacity': opacity,
'stroke_width': strokeWidth,
'stroke_color': _colorHex(strokeColor),
'label': label,
'created_at': createdAt.toIso8601String(),
};
factory NoteItem.fromMap(Map<String, dynamic> m) => NoteItem(
id: m['id'] as int?,
projectId: m['project_id'] as int?,
type: NoteType.values.firstWhere((t) => t.name == (m['type'] as String),
orElse: () => NoteType.point),
points: _parsePoints(m['points_json'] as String),
color: _parseColor(m['color'] as String? ?? '#185FA5'),
opacity: (m['opacity'] as num?)?.toDouble() ?? 0.5,
strokeWidth: (m['stroke_width'] as num?)?.toDouble() ?? 3.0,
strokeColor: _parseColor(m['stroke_color'] as String? ?? '#FFD700'),
label: m['label'] as String? ?? '',
createdAt: DateTime.parse(m['created_at'] as String),
);
/// Kitöltési szín az opacity-val alkalmazva.
Color get fillColor => Color.fromARGB(
(opacity * 255).round(),
color.red,
color.green,
color.blue,
);
// Rendereléshez — a hitValue hordozza az id-t a tap detektáláshoz
Polyline<int> toPolyline() => Polyline(
points: points,
color: color,
strokeWidth: strokeWidth,
hitValue: id!,
);
Polygon<int> toPolygon() => Polygon(
2026-06-23 15:21:20 +02:00
points: points,
color: color.withOpacity(opacity),
borderColor: strokeColor,
borderStrokeWidth: strokeWidth,
label: label.isEmpty ? null : label,
hitValue: id!,
labelStyle: TextStyle(fontSize: 10.0));
}