Skip to content

Commit 11f1945

Browse files
committed
Grid View #1
- Implement grid view node, transformer, library, suggestion, and settings panel. - WIP: Implement grid view layout model.
1 parent 1a27ccc commit 11f1945

File tree

4 files changed

+621
-0
lines changed

4 files changed

+621
-0
lines changed

lib/src/api/node_json_converter.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class NodeJsonConverter implements JsonConverter<BaseNode?, Map> {
7171
'progressBar': ProgressBarNode.fromJson,
7272
'variance': VarianceNode.fromJson,
7373
'listView': ListViewNode.fromJson,
74+
'gridView': GridViewNode.fromJson,
7475
'pageView': PageViewNode.fromJson,
7576
'tabBar': TabBarNode.fromJson,
7677
'external': ExternalComponentNode.fromJson,
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
import 'package:codelessly_json_annotation/codelessly_json_annotation.dart';
2+
import 'package:equatable/equatable.dart';
3+
4+
import '../../../codelessly_api.dart';
5+
6+
part 'grid_view_node.g.dart';
7+
8+
/// A material design [GridView].
9+
/// Refer to [GridView](https://api.flutter.dev/flutter/widgets/GridView-class.html)
10+
/// in Flutter for more details.
11+
@JsonSerializable()
12+
class GridViewNode extends SinglePlaceholderNode
13+
with ScrollableMixin, CustomPropertiesMixin, ClipMixin {
14+
@override
15+
final String type = 'gridView';
16+
17+
@override
18+
final bool supportsPadding = true;
19+
20+
@override
21+
bool get isScrollingEnforced => true;
22+
23+
/// The properties of the [GridView].
24+
GridViewProperties properties;
25+
26+
@override
27+
BoxConstraintsModel? relegatedConstraintsToChildren(BaseNode child) {
28+
// TODO: implement relegatedConstraintsToChildren.
29+
// if (scrollDirection == AxisC.vertical) {
30+
// return BoxConstraintsModel(maxHeight: properties.itemExtent);
31+
// } else {
32+
// return BoxConstraintsModel(maxWidth: properties.itemExtent);
33+
// }
34+
}
35+
36+
/// Creates a [GridViewNode].
37+
GridViewNode({
38+
required super.id,
39+
required super.name,
40+
required super.basicBoxLocal,
41+
super.outerBoxLocal,
42+
super.retainedOuterBoxLocal,
43+
super.visible,
44+
super.rotationDegrees,
45+
super.alignment,
46+
super.margin,
47+
super.padding,
48+
super.horizontalFit,
49+
super.verticalFit,
50+
super.flex,
51+
super.constraints,
52+
super.edgePins,
53+
super.aspectRatioLock,
54+
super.positioningMode,
55+
super.parentID,
56+
super.reactions,
57+
required this.properties,
58+
required List<String> children,
59+
super.variables,
60+
super.multipleVariables,
61+
bool clipsContent = true,
62+
// [ScrollableMixin] properties.
63+
AxisC scrollDirection = AxisC.vertical,
64+
bool reverse = false,
65+
ScrollPhysicsC physics = ScrollPhysicsC.platformDependent,
66+
bool primary = false,
67+
ScrollViewKeyboardDismissBehaviorC keyboardDismissBehavior =
68+
ScrollViewKeyboardDismissBehaviorC.manual,
69+
bool shouldAlwaysScroll = true,
70+
}) : super(
71+
children: [],
72+
allowedTypes: [],
73+
deniedTypes: [
74+
'GridView',
75+
],
76+
) {
77+
setChildrenMixin(children: children);
78+
setClipMixin(clipsContent: clipsContent);
79+
80+
setScrollableMixin(
81+
isScrollable: true,
82+
scrollDirection: scrollDirection,
83+
reverse: reverse,
84+
physics: physics,
85+
primary: primary,
86+
shrinkWrap: false,
87+
keyboardDismissBehavior: keyboardDismissBehavior,
88+
useFlutterListView: false,
89+
shouldAlwaysScroll: shouldAlwaysScroll,
90+
);
91+
}
92+
93+
/// Creates a [GridViewNode] from a JSON object.
94+
factory GridViewNode.fromJson(Map json) => _$GridViewNodeFromJson(json);
95+
96+
@override
97+
Map toJson() => _$GridViewNodeToJson(this);
98+
99+
/// Returns the appropriate alignment of the child based on the
100+
/// [scrollDirection] and [reverse] properties.
101+
AlignmentModel childAlignment() {
102+
switch (scrollDirection) {
103+
case AxisC.horizontal:
104+
return reverse ? AlignmentModel.centerRight : AlignmentModel.centerLeft;
105+
case AxisC.vertical:
106+
return reverse ? AlignmentModel.bottomCenter : AlignmentModel.topCenter;
107+
}
108+
}
109+
}
110+
111+
/// The properties of a [GridViewNode].
112+
@JsonSerializable()
113+
class GridViewProperties with SerializableMixin, EquatableMixin {
114+
/// The number of items to display in the list view. Can be null if the list
115+
/// is infinite.
116+
int? itemCount;
117+
118+
/// The number of pixels by which to allow pre-rendering of items outside
119+
/// the visible area.
120+
double? cacheExtent;
121+
122+
/// Properties of the grid delegate that controls the layout of the grid.
123+
GridDelegateProperties gridDelegate;
124+
125+
/// Creates a new [GridViewProperties] instance.
126+
GridViewProperties({
127+
this.itemCount,
128+
this.cacheExtent,
129+
required this.gridDelegate,
130+
DividerProperties? dividerProperties,
131+
});
132+
133+
/// Creates a copy of this [GridViewProperties] instance with the given value
134+
/// overrides.
135+
GridViewProperties copyWith({
136+
String? bodyId,
137+
int? itemCount,
138+
ScrollPhysicsC? physics,
139+
AxisC? scrollDirection,
140+
double? cacheExtent,
141+
bool? reverse,
142+
GridDelegateProperties? gridDelegate,
143+
}) {
144+
return GridViewProperties(
145+
itemCount: itemCount ?? this.itemCount,
146+
cacheExtent: cacheExtent ?? this.cacheExtent,
147+
gridDelegate: gridDelegate ?? this.gridDelegate,
148+
);
149+
}
150+
151+
@override
152+
Map toJson() => _$GridViewPropertiesToJson(this);
153+
154+
/// Creates a [GridViewProperties] from a JSON object.
155+
factory GridViewProperties.fromJson(Map json) =>
156+
_$GridViewPropertiesFromJson(json);
157+
158+
@override
159+
List<Object?> get props => [
160+
itemCount,
161+
cacheExtent,
162+
gridDelegate,
163+
];
164+
}
165+
166+
/// Defines the type of grid delegate to use for a [GridViewNode].
167+
enum GridDelegateType {
168+
/// Represents a delegate that makes grid layouts with a fixed number of tiles
169+
/// in the cross axis.
170+
fixedCrossAxisCount,
171+
172+
/// Represents a delegate that makes grid layouts with tiles that each have a
173+
/// maximum cross-axis extent.
174+
maxCrossAxisExtent;
175+
176+
/// Pretty name of the enum value.
177+
String get label => switch (this) {
178+
fixedCrossAxisCount => 'Fixed Cross Axis Count',
179+
maxCrossAxisExtent => 'Max Cross Axis Extent',
180+
};
181+
}
182+
183+
sealed class GridDelegateProperties with EquatableMixin, SerializableMixin {
184+
final GridDelegateType type;
185+
186+
/// Creates a new [GridDelegateProperties] instance.
187+
const GridDelegateProperties(this.type);
188+
189+
factory GridDelegateProperties.fromJson(Map json) {
190+
final type = GridDelegateType.values.byName(json['type']);
191+
return switch (type) {
192+
GridDelegateType.fixedCrossAxisCount =>
193+
FixedCrossAxisCountGridDelegateProperties.fromJson(json),
194+
GridDelegateType.maxCrossAxisExtent =>
195+
MaxCrossAxisExtentGridDelegateProperties.fromJson(json),
196+
};
197+
}
198+
199+
@override
200+
List<Object?> get props => [type];
201+
}
202+
203+
/// Represents a delegate that makes grid layouts with a fixed number of tiles
204+
/// in the cross axis.
205+
@JsonSerializable()
206+
class FixedCrossAxisCountGridDelegateProperties extends GridDelegateProperties {
207+
final int crossAxisCount;
208+
final double mainAxisSpacing;
209+
final double crossAxisSpacing;
210+
final double childAspectRatio;
211+
final double? mainAxisExtent;
212+
213+
/// Creates a new [FixedCrossAxisCountGridDelegateProperties] instance.
214+
const FixedCrossAxisCountGridDelegateProperties({
215+
required this.crossAxisCount,
216+
this.mainAxisSpacing = 0,
217+
this.crossAxisSpacing = 0,
218+
this.childAspectRatio = 1,
219+
this.mainAxisExtent,
220+
}) : super(GridDelegateType.fixedCrossAxisCount);
221+
222+
@override
223+
Map toJson() => _$FixedCrossAxisCountGridDelegatePropertiesToJson(this)
224+
..['type'] = type.name;
225+
226+
factory FixedCrossAxisCountGridDelegateProperties.fromJson(Map json) =>
227+
_$FixedCrossAxisCountGridDelegatePropertiesFromJson(json);
228+
229+
/// Creates a copy of this [FixedCrossAxisCountGridDelegateProperties]
230+
/// instance with the given value overrides.
231+
FixedCrossAxisCountGridDelegateProperties copyWith({
232+
int? crossAxisCount,
233+
double? mainAxisSpacing,
234+
double? crossAxisSpacing,
235+
double? childAspectRatio,
236+
double? mainAxisExtent,
237+
bool forceMainAxisExtent = false,
238+
}) {
239+
return FixedCrossAxisCountGridDelegateProperties(
240+
crossAxisCount: crossAxisCount ?? this.crossAxisCount,
241+
mainAxisSpacing: mainAxisSpacing ?? this.mainAxisSpacing,
242+
crossAxisSpacing: crossAxisSpacing ?? this.crossAxisSpacing,
243+
childAspectRatio: childAspectRatio ?? this.childAspectRatio,
244+
mainAxisExtent: forceMainAxisExtent
245+
? mainAxisExtent
246+
: mainAxisExtent ?? this.mainAxisExtent,
247+
);
248+
}
249+
250+
@override
251+
List<Object?> get props => [
252+
...super.props,
253+
crossAxisCount,
254+
mainAxisSpacing,
255+
crossAxisSpacing,
256+
childAspectRatio,
257+
];
258+
}
259+
260+
/// Represents a delegate that makes grid layouts with tiles that each have a
261+
/// maximum cross-axis extent.
262+
@JsonSerializable()
263+
class MaxCrossAxisExtentGridDelegateProperties extends GridDelegateProperties {
264+
final double maxCrossAxisExtent;
265+
final double mainAxisSpacing;
266+
final double crossAxisSpacing;
267+
final double childAspectRatio;
268+
final double? mainAxisExtent;
269+
270+
/// Creates a new [MaxCrossAxisExtentGridDelegateProperties] instance.
271+
const MaxCrossAxisExtentGridDelegateProperties({
272+
required this.maxCrossAxisExtent,
273+
this.mainAxisSpacing = 0,
274+
this.crossAxisSpacing = 0,
275+
this.childAspectRatio = 1,
276+
this.mainAxisExtent,
277+
}) : super(GridDelegateType.maxCrossAxisExtent);
278+
279+
@override
280+
Map toJson() => _$MaxCrossAxisExtentGridDelegatePropertiesToJson(this)
281+
..['type'] = type.name;
282+
283+
factory MaxCrossAxisExtentGridDelegateProperties.fromJson(Map json) =>
284+
_$MaxCrossAxisExtentGridDelegatePropertiesFromJson(json);
285+
286+
/// Creates a copy of this [MaxCrossAxisExtentGridDelegateProperties]
287+
/// instance with the given value overrides.
288+
MaxCrossAxisExtentGridDelegateProperties copyWith({
289+
double? maxCrossAxisExtent,
290+
double? mainAxisSpacing,
291+
double? crossAxisSpacing,
292+
double? childAspectRatio,
293+
double? mainAxisExtent,
294+
bool forceMainAxisExtent = false,
295+
}) {
296+
return MaxCrossAxisExtentGridDelegateProperties(
297+
maxCrossAxisExtent: maxCrossAxisExtent ?? this.maxCrossAxisExtent,
298+
mainAxisSpacing: mainAxisSpacing ?? this.mainAxisSpacing,
299+
crossAxisSpacing: crossAxisSpacing ?? this.crossAxisSpacing,
300+
childAspectRatio: childAspectRatio ?? this.childAspectRatio,
301+
mainAxisExtent: forceMainAxisExtent
302+
? mainAxisExtent
303+
: mainAxisExtent ?? this.mainAxisExtent,
304+
);
305+
}
306+
307+
@override
308+
List<Object?> get props => [
309+
...super.props,
310+
maxCrossAxisExtent,
311+
mainAxisSpacing,
312+
crossAxisSpacing,
313+
childAspectRatio,
314+
];
315+
}

0 commit comments

Comments
 (0)