creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
lib/data/models/canvas_models.dart (4072B)
1import 'dart:ui';
2import 'package:flutter/material.dart';
3
4enum DragHandle { none, topLeft, topRight, bottomLeft, bottomRight, center }
5
6enum LayerType { sketch, image }
7
8class DrawingPoint {
9 final Offset offset;
10 final Paint paint;
11 const DrawingPoint({required this.offset, required this.paint});
12
13 Map<String, dynamic> toMap() => {'dx': offset.dx, 'dy': offset.dy};
14
15 factory DrawingPoint.fromMap(Map<String, dynamic> map) {
16 return DrawingPoint(
17 offset: Offset(map['dx'] ?? 0, map['dy'] ?? 0),
18 paint: Paint(),
19 );
20 }
21}
22
23class DrawingPath {
24 final List<DrawingPoint> points;
25 final Color color;
26 final double strokeWidth;
27 final bool isEraser;
28
29 DrawingPath({
30 required this.points,
31 required this.color,
32 required this.strokeWidth,
33 required this.isEraser,
34 });
35
36 Map<String, dynamic> toMap() {
37 return {
38 'points': points.map((p) => p.toMap()).toList(),
39 'color': color.value,
40 'strokeWidth': strokeWidth,
41 'isEraser': isEraser,
42 };
43 }
44
45 factory DrawingPath.fromMap(Map<String, dynamic> map) {
46 return DrawingPath(
47 points:
48 (map['points'] as List).map((p) => DrawingPoint.fromMap(p)).toList(),
49 color: Color(map['color']),
50 strokeWidth: (map['strokeWidth'] as num).toDouble(),
51 isEraser: map['isEraser'] ?? false,
52 );
53 }
54}
55
56// Layer Models
57abstract class CanvasLayer {
58 final String id;
59 final LayerType type;
60 bool isVisible;
61
62 CanvasLayer({required this.id, required this.type, this.isVisible = true});
63
64 Map<String, dynamic> toMap();
65
66 static CanvasLayer fromMap(Map<String, dynamic> map) {
67 if (map['type'] == 'sketch') {
68 return SketchLayer.fromMap(map);
69 } else {
70 return ImageLayer.fromMap(map);
71 }
72 }
73}
74
75class SketchLayer extends CanvasLayer {
76 final List<DrawingPath> paths;
77 final bool isMagicDraw;
78
79 SketchLayer({
80 required String id,
81 this.paths = const [],
82 this.isMagicDraw = false,
83 bool isVisible = true,
84 }) : super(id: id, type: LayerType.sketch, isVisible: isVisible);
85
86 @override
87 Map<String, dynamic> toMap() {
88 return {
89 'id': id,
90 'type': 'sketch',
91 'paths': paths.map((p) => p.toMap()).toList(),
92 'isMagicDraw': isMagicDraw,
93 'isVisible': isVisible,
94 };
95 }
96
97 factory SketchLayer.fromMap(Map<String, dynamic> map) {
98 return SketchLayer(
99 id: map['id'],
100 paths: (map['paths'] as List).map((p) => DrawingPath.fromMap(p)).toList(),
101 isMagicDraw: map['isMagicDraw'] ?? false,
102 isVisible: map['isVisible'] ?? true,
103 );
104 }
105}
106
107class ImageLayer extends CanvasLayer {
108 final Map<String, dynamic> data;
109
110 ImageLayer({required String id, required this.data, bool isVisible = true})
111 : super(id: id, type: LayerType.image, isVisible: isVisible);
112
113 @override
114 Map<String, dynamic> toMap() {
115 final encodableData = Map<String, dynamic>.from(data);
116
117 if (encodableData['position'] is Offset) {
118 final pos = encodableData['position'] as Offset;
119 encodableData['position'] = {'dx': pos.dx, 'dy': pos.dy};
120 }
121
122 if (encodableData['size'] is Size) {
123 final size = encodableData['size'] as Size;
124 encodableData['size'] = {'width': size.width, 'height': size.height};
125 }
126
127 return {
128 'id': id,
129 'type': 'image',
130 'data': encodableData,
131 'isVisible': isVisible,
132 };
133 }
134
135 factory ImageLayer.fromMap(Map<String, dynamic> map) {
136 final data = Map<String, dynamic>.from(map['data']);
137 // Restore Offset/Size objects
138 if (data['position'] is Map) {
139 data['position'] = Offset(
140 (data['position']['dx'] as num).toDouble(),
141 (data['position']['dy'] as num).toDouble(),
142 );
143 }
144 if (data['size'] is Map) {
145 data['size'] = Size(
146 (data['size']['width'] as num).toDouble(),
147 (data['size']['height'] as num).toDouble(),
148 );
149 }
150
151 return ImageLayer(
152 id: map['id'],
153 data: data,
154 isVisible: map['isVisible'] ?? true,
155 );
156 }
157}
158
159class CanvasState {
160 final List<CanvasLayer> layers;
161 CanvasState(this.layers);
162}