Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic flex support #1021

Merged
merged 17 commits into from
Oct 27, 2023
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 102 additions & 5 deletions packages/core/lib/src/core_widget_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -681,10 +681,18 @@ class WidgetFactory {
..[kCssDisplay] = kCssDisplayBlock
..tsb.enqueue(TextStyleOps.fontStyle, FontStyle.italic);
break;
case 'div':
final displayExpressions = meta.element.styles.where((element) => element.property == 'display');
final displayExpression = displayExpressions.isNotEmpty ? displayExpressions.first : null;
final display = displayExpression?.term ?? 'block';
if (display == 'flex') {
meta.register(_flexOp(meta));
}

meta[kCssDisplay] = kCssDisplayBlock;
break;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flex is supported for all kind of tags, not just DIV right? I think we should handle flex for all of them in parseStyleDisplay.

case 'article':
case 'aside':
case 'div':
case 'figcaption':
case 'footer':
case 'header':
Expand Down Expand Up @@ -1150,14 +1158,103 @@ class WidgetFactory {
return baseUrl.resolveUri(uri).toString();
}

/// Builds custom widget for div elements with display: flex from [meta]
BuildOp _flexOp(BuildMetadata meta) {
return BuildOp(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This op should be in its own file I think, probably packages/core/lib/src/internal/ops/flex.dart. Because of the complexity, flex implementation will grow to support all kind of use cases, the factory file is already too long.

onChild: (childMeta) {
childMeta.register(_flexItemOp(childMeta));
},
onWidgets: (meta, widgets) {
final String id = meta.element.id;
String flexDirection = 'row';
String justifyContent = 'flex-start';
String alignItems = 'flex-start';

for (final element in meta.element.styles) {
final String? value = element.term;

if (value != null) {
switch (element.property) {
case 'flex-direction':
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo usually defines constants for inline style key & values. Like this:

const kCssBoxSizing = 'box-sizing';
const kCssBoxSizingContentBox = 'content-box';
const kCssBoxSizingBorderBox = 'border-box';

flexDirection = value;
break;
case 'justify-content':
justifyContent = value;
break;
case 'align-items':
alignItems = value;
break;
}
}
}

return [
Flex(
key: Key(id),
direction: 'row' == flexDirection ? Axis.horizontal : Axis.vertical,
mainAxisAlignment: _toMainAxisAlignment(justifyContent),
crossAxisAlignment: _toCrossAxisAlignment(alignItems),
children: widgets.toList()
)
];
},
);
}

/// Build op for child elements of flex containers
BuildOp _flexItemOp(BuildMetadata meta) {
return BuildOp(
defaultStyles: (element) {
return {
kCssWidth: "auto",
kCssHeight: "auto"
};
}
);
}

/// Converts CSS [justifyContent] to Flutter Grid MainAxisAlignment
static MainAxisAlignment _toMainAxisAlignment(String justifyContent) {
switch (justifyContent) {
case 'flex-start':
return MainAxisAlignment.start;
case 'flex-end':
return MainAxisAlignment.end;
case 'center':
return MainAxisAlignment.center;
case 'space-between':
return MainAxisAlignment.spaceBetween;
case 'space-around':
return MainAxisAlignment.spaceAround;
case 'space-evenly':
return MainAxisAlignment.spaceEvenly;
default:
return MainAxisAlignment.start;
}
}

/// Converts CSS [alignItems] to Flutter Grid CrossAxisAlignment
static CrossAxisAlignment _toCrossAxisAlignment(String alignItems) {
switch (alignItems) {
case 'flex-start':
return CrossAxisAlignment.start;
case 'flex-end':
return CrossAxisAlignment.end;
case 'center':
return CrossAxisAlignment.center;
case 'baseline':
return CrossAxisAlignment.baseline;
case 'stretch':
return CrossAxisAlignment.stretch;
default:
return CrossAxisAlignment.start;
}
}

BuildOp _anchorOp(String id) {
final anchor = GlobalKey(debugLabel: id);

return BuildOp(
onTree: (meta, tree) {
_anchorRegistry.register(id, anchor);
tree.registerAnchor(anchor);
},
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these lines being removed? I think the anchor logic won't work without them?

onTreeFlattening: (meta, tree) {
final widget = WidgetPlaceholder('#$id').wrapWith(
(context, _) => SizedBox(
Expand Down