Skip to content

Commit a17f98b

Browse files
committed
fix(ui): flex-basis was not recalculated during layout
1 parent 3395ec0 commit a17f98b

File tree

8 files changed

+114
-101
lines changed

8 files changed

+114
-101
lines changed

lib/ui-widgets/src/text.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ static void ui_text_on_destroy(ui_widget_t *w)
177177
}
178178
}
179179

180-
static void ui_text_on_auto_size(ui_widget_t *w, float *width, float *height,
181-
ui_layout_rule_t rule)
180+
static void ui_text_on_autosize(ui_widget_t *w, float *width, float *height,
181+
ui_layout_rule_t rule)
182182
{
183183
float max_width, max_height;
184184
ui_text_t *txt = ui_widget_get_data(w, ui_text.prototype);
@@ -344,7 +344,7 @@ void ui_register_text(void)
344344
ui_text.prototype->init = ui_text_on_init;
345345
ui_text.prototype->paint = ui_text_on_paint;
346346
ui_text.prototype->destroy = ui_text_on_destroy;
347-
ui_text.prototype->autosize = ui_text_on_auto_size;
347+
ui_text.prototype->autosize = ui_text_on_autosize;
348348
ui_text.prototype->resize = ui_text_on_resize;
349349
ui_text.prototype->update = ui_text_on_update;
350350
ui_text.prototype->settext = ui_text_on_parse_text;

lib/ui/include/ui/base.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,8 @@ LIBUI_PUBLIC dict_t *ui_widget_collect_references(ui_widget_t *w);
110110
/**
111111
* 执行布局前的准备操作
112112
* 重置布局相关属性,以让它们在布局时被重新计算
113-
* @param rule 父级组件所使用的布局规则
114113
*/
115-
LIBUI_PUBLIC void ui_widget_reset_layout(ui_widget_t *w, ui_layout_rule_t rule);
114+
LIBUI_PUBLIC void ui_widget_reset_layout(ui_widget_t *w);
116115

117116
LIBUI_PUBLIC void ui_widget_auto_reflow(ui_widget_t *w);
118117

lib/ui/src/ui_block_layout.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static void ui_block_layout_load(ui_block_layout_context_t *ctx)
104104
#endif
105105
for (list_each(node, &ctx->widget->children)) {
106106
child = node->data;
107-
ui_widget_reset_layout(child, ctx->rule);
107+
ui_widget_reset_layout(child);
108108
if (!ui_widget_in_layout_flow(child)) {
109109
list_append(&ctx->row->items, child);
110110
continue;
@@ -234,7 +234,7 @@ static void ui_block_layout_update(ui_block_layout_context_t *ctx)
234234
size_str);
235235
}
236236
#endif
237-
ui_widget_reset_layout(child, ctx->rule);
237+
ui_widget_reset_layout(child);
238238
ui_widget_compute_style(child);
239239
ui_widget_auto_reflow(child);
240240
ui_block_layout_update_item_margin(ctx, child);
@@ -315,7 +315,7 @@ void ui_block_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule)
315315
ctx.row = NULL;
316316
ctx.widget = w;
317317
ctx.x = w->computed_style.padding_left;
318-
ctx.y = w->computed_style.padding_right;
318+
ctx.y = w->computed_style.padding_top;
319319
ctx.content_width = 0;
320320
ctx.content_height = 0;
321321
ctx.prev_display = 0;

lib/ui/src/ui_debug.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void ui_widget_to_string(ui_widget_t *w, char *str)
4242
node->status = NULL;
4343
css_selector_node_update(node);
4444
}
45-
strcpy(str, node->fullname);
45+
strcpy(str, node->fullname ? node->fullname : "<widget>");
4646
css_selector_node_destroy(node);
4747
}
4848

@@ -63,7 +63,7 @@ void ui_widget_size_to_string(ui_widget_t *w, char str[40])
6363
break;
6464
}
6565
switch (w->computed_style.type_bits.height) {
66-
case CSS_WIDTH_SET:
66+
case CSS_HEIGHT_SET:
6767
snprintf(height_str, 16, "%g%s", w->computed_style.height,
6868
get_css_unit_str(w->computed_style.unit_bits.height));
6969
break;

lib/ui/src/ui_diff.c

+22-12
Original file line numberDiff line numberDiff line change
@@ -55,28 +55,38 @@ void ui_style_diff_begin(ui_style_diff_t *diff, ui_widget_t *w)
5555
void ui_style_diff_end(ui_style_diff_t *diff, ui_widget_t *w)
5656
{
5757
ui_mutation_record_t *record;
58-
bool layout_changed = IS_PROP_TYPE_CHANGED(display) ||
59-
IS_PROP_TYPE_CHANGED(position) ||
60-
diff->padding_box.width != w->padding_box.width ||
61-
diff->padding_box.height != w->padding_box.height;
58+
bool flow_changed =
59+
IS_PROP_TYPE_CHANGED(display) || IS_PROP_TYPE_CHANGED(position);
60+
bool inner_changed = diff->padding_box.width != w->padding_box.width ||
61+
diff->padding_box.height != w->padding_box.height;
6262

63-
if (layout_changed || (ui_widget_has_flex_display(w) &&
64-
(IS_PROP_TYPE_CHANGED(flex_wrap) ||
65-
IS_PROP_TYPE_CHANGED(flex_direction) ||
66-
IS_PROP_TYPE_CHANGED(justify_content) ||
67-
IS_PROP_TYPE_CHANGED(align_content) ||
68-
IS_PROP_TYPE_CHANGED(align_items)))) {
63+
if (flow_changed || inner_changed ||
64+
(ui_widget_has_flex_display(w) &&
65+
(IS_PROP_TYPE_CHANGED(flex_wrap) ||
66+
IS_PROP_TYPE_CHANGED(flex_direction) ||
67+
IS_PROP_TYPE_CHANGED(justify_content) ||
68+
IS_PROP_TYPE_CHANGED(align_content) ||
69+
IS_PROP_TYPE_CHANGED(align_items)))) {
6970
ui_widget_request_reflow(w);
7071
}
71-
if (w->parent && ui_widget_in_layout_flow(w)) {
72-
if (layout_changed || IS_LENGTH_PROP_CHANGED(margin_left) ||
72+
if (ui_widget_has_class(w, "file-info-panel")) {
73+
logger_debug("[ui-diff] [.file-info-panel] flow_changed=%d\n",
74+
flow_changed);
75+
}
76+
if (w->parent && (flow_changed || ui_widget_in_layout_flow(w))) {
77+
if (flow_changed || inner_changed ||
78+
IS_LENGTH_PROP_CHANGED(margin_left) ||
7379
IS_LENGTH_PROP_CHANGED(margin_right) ||
7480
IS_LENGTH_PROP_CHANGED(margin_top) ||
7581
IS_LENGTH_PROP_CHANGED(margin_bottom) ||
7682
(ui_widget_has_flex_display(w->parent) &&
7783
(IS_PROP_TYPE_CHANGED(flex_grow) ||
7884
IS_PROP_TYPE_CHANGED(flex_shrink) ||
7985
IS_PROP_TYPE_CHANGED(flex_basis)))) {
86+
if (ui_widget_has_class(w, "file-info-panel")) {
87+
logger_debug("[ui-diff] [.file-info-panel] "
88+
"parent reflow\n");
89+
}
8090
ui_widget_request_reflow(w->parent);
8191
}
8292
}

lib/ui/src/ui_flexbox_layout.c

+62-53
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,48 @@ static void ui_flexbox_layout_next_line(ui_flexbox_layout_context_t *ctx)
9797
list_append(&ctx->lines, ctx->line);
9898
}
9999

100-
LIBUI_INLINE float ui_compute_row_item_main_size(css_computed_style_t *s)
100+
float ui_compute_row_item_main_size(ui_widget_t *item)
101101
{
102+
css_computed_style_t *s = &item->computed_style;
103+
float spacing = css_padding_x(s) + css_border_x(s);
104+
105+
if (s->type_bits.flex_basis == CSS_FLEX_BASIS_CONTENT) {
106+
CSS_SET_FIXED_LENGTH(
107+
s, flex_basis,
108+
css_convert_content_box_width(s, item->max_content_width));
109+
}
102110
if (css_computed_box_sizing(s) == CSS_BOX_SIZING_BORDER_BOX) {
103-
if (s->flex_basis < css_padding_x(s) + css_border_x(s)) {
104-
return 0;
111+
if (s->flex_basis < spacing) {
112+
s->flex_basis = spacing;
105113
}
106-
return s->flex_basis - css_padding_x(s) - css_border_x(s);
114+
return s->flex_basis + css_margin_x(s);
107115
}
108-
return s->flex_basis;
116+
if (s->flex_basis < 0) {
117+
s->flex_basis = 0;
118+
}
119+
return s->flex_basis + css_margin_x(s) + spacing;
109120
}
110121

111-
LIBUI_INLINE float ui_compute_column_item_main_size(css_computed_style_t *s)
122+
float ui_compute_column_item_main_size(ui_widget_t *item)
112123
{
124+
css_computed_style_t *s = &item->computed_style;
125+
float spacing = css_padding_y(s) + css_border_y(s);
126+
127+
if (s->type_bits.flex_basis == CSS_FLEX_BASIS_CONTENT) {
128+
CSS_SET_FIXED_LENGTH(s, flex_basis,
129+
css_convert_content_box_height(
130+
s, item->max_content_height));
131+
}
113132
if (css_computed_box_sizing(s) == CSS_BOX_SIZING_BORDER_BOX) {
114-
if (s->flex_basis < css_padding_y(s) + css_border_y(s)) {
115-
return 0;
133+
if (s->flex_basis < spacing) {
134+
s->flex_basis = spacing;
116135
}
117-
return s->flex_basis - css_padding_y(s) - css_border_y(s);
136+
return s->flex_basis + css_margin_y(s);
137+
}
138+
if (s->flex_basis < 0) {
139+
s->flex_basis = 0;
118140
}
119-
return s->flex_basis;
141+
return s->flex_basis + css_margin_y(s) + spacing;
120142
}
121143

122144
static void ui_flexbox_layout_load_rows(ui_flexbox_layout_context_t *ctx)
@@ -142,25 +164,14 @@ static void ui_flexbox_layout_load_rows(ui_flexbox_layout_context_t *ctx)
142164
if (cs->type_bits.display == CSS_DISPLAY_NONE) {
143165
continue;
144166
}
145-
ui_widget_reset_layout(child, ctx->rule);
146167
if (!ui_widget_in_layout_flow(child)) {
147168
list_append(&ctx->line->items, child);
148169
continue;
149170
}
171+
ui_widget_reset_layout(child);
150172
ui_widget_compute_style(child);
151173
ui_widget_auto_reflow(child);
152-
switch (cs->type_bits.flex_basis) {
153-
case CSS_FLEX_BASIS_CONTENT:
154-
CSS_SET_FIXED_LENGTH(cs, flex_basis,
155-
css_convert_content_box_width(
156-
cs, child->max_content_width));
157-
break;
158-
default:
159-
break;
160-
}
161-
main_size = ui_compute_row_item_main_size(cs) +
162-
css_margin_x(cs) + css_padding_x(cs) +
163-
css_border_x(cs);
174+
main_size = ui_compute_row_item_main_size(child);
164175
#ifdef UI_DEBUG_ENABLED
165176
{
166177
UI_WIDGET_STR(child, str);
@@ -226,22 +237,14 @@ static void ui_flexbox_layout_load_columns(ui_flexbox_layout_context_t *ctx)
226237
if (cs->type_bits.display == CSS_DISPLAY_NONE) {
227238
continue;
228239
}
229-
ui_widget_reset_layout(child, ctx->rule);
230240
if (!ui_widget_in_layout_flow(child)) {
231241
list_append(&ctx->line->items, child);
232242
continue;
233243
}
244+
ui_widget_reset_layout(child);
234245
ui_widget_compute_style(child);
235246
ui_widget_auto_reflow(child);
236-
if (cs->type_bits.flex_basis == CSS_FLEX_BASIS_CONTENT) {
237-
CSS_SET_FIXED_LENGTH(
238-
cs, flex_basis,
239-
css_convert_content_box_height(
240-
cs, child->max_content_height));
241-
}
242-
main_size = ui_compute_column_item_main_size(cs) +
243-
css_margin_y(cs) + css_padding_y(cs) +
244-
css_border_y(cs);
247+
main_size = ui_compute_column_item_main_size(child);
245248
#ifdef UI_DEBUG_ENABLED
246249
{
247250
UI_WIDGET_STR(child, str);
@@ -368,22 +371,22 @@ static void ui_flexbox_layout_update_row(ui_flexbox_layout_context_t *ctx)
368371

369372
for (list_each(node, &ctx->line->items)) {
370373
child = node->data;
374+
if (!ui_widget_in_layout_flow(child)) {
375+
continue;
376+
}
371377
s = &child->computed_style;
372-
ui_widget_reset_layout(child, ctx->rule);
378+
ui_widget_reset_layout(child);
373379
ui_widget_compute_style(child);
374-
main_size = ui_compute_row_item_main_size(s);
375-
if (css_computed_box_sizing(s) == CSS_BOX_SIZING_BORDER_BOX) {
376-
main_size += css_border_x(s) + css_padding_x(s);
377-
}
380+
main_size = ui_compute_row_item_main_size(child);
378381
// 根据项目的 flex-grow 和 flex-shrink,调整它的宽度
379382
if (space >= 0) {
380383
if (s->type_bits.flex_grow > 0) {
381384
CSS_SET_FIXED_LENGTH(
382-
s, width, main_size + k * s->flex_grow);
385+
s, width, s->flex_basis + k * s->flex_grow);
383386
}
384387
} else if (s->type_bits.flex_shrink > 0) {
385-
CSS_SET_FIXED_LENGTH(s, width,
386-
main_size + k * s->flex_shrink);
388+
CSS_SET_FIXED_LENGTH(
389+
s, width, s->flex_basis + k * s->flex_shrink);
387390
}
388391
// 计算拉伸的高度
389392
if (align_items == CSS_ALIGN_ITEMS_STRETCH &&
@@ -394,7 +397,7 @@ static void ui_flexbox_layout_update_row(ui_flexbox_layout_context_t *ctx)
394397
css_margin_y(s)));
395398
}
396399
ui_widget_auto_reflow(child);
397-
main_axis += child->outer_box.width;
400+
main_axis += main_size;
398401
}
399402
ctx->line->main_size = main_axis;
400403
space = ctx->widget->content_box.width - main_axis;
@@ -431,8 +434,11 @@ static void ui_flexbox_layout_update_row(ui_flexbox_layout_context_t *ctx)
431434
#ifdef UI_DEBUG_ENABLED
432435
{
433436
UI_WIDGET_STR(ctx->widget, str);
434-
UI_DEBUG_MSG("%s: main_axis_start = %g, free_space = %g, justify_content = %d",
435-
str, main_axis, space, ctx->widget->computed_style.type_bits.justify_content);
437+
UI_DEBUG_MSG(
438+
"%s: main_axis_start = %g, free_space = %g, "
439+
"justify_content = %d",
440+
str, main_axis, space,
441+
ctx->widget->computed_style.type_bits.justify_content);
436442
}
437443
#endif
438444
for (list_each(node, &ctx->line->items)) {
@@ -441,6 +447,7 @@ static void ui_flexbox_layout_update_row(ui_flexbox_layout_context_t *ctx)
441447
child->layout_x = main_axis;
442448
child->layout_y = ctx->line->cross_axis;
443449
if (!ui_widget_in_layout_flow(child)) {
450+
ui_widget_reset_layout(child);
444451
ui_widget_compute_style(node->data);
445452
ui_widget_auto_reflow(node->data);
446453
ui_widget_update_box_position(node->data);
@@ -497,22 +504,23 @@ static void ui_flexbox_layout_update_column(ui_flexbox_layout_context_t *ctx)
497504

498505
for (list_each(node, &ctx->line->items)) {
499506
child = node->data;
507+
if (!ui_widget_in_layout_flow(child)) {
508+
continue;
509+
}
500510
s = &child->computed_style;
501-
ui_widget_reset_layout(child, ctx->rule);
511+
ui_widget_reset_layout(child);
502512
ui_widget_compute_style(child);
503-
main_size = ui_compute_column_item_main_size(s);
504-
if (css_computed_box_sizing(s) == CSS_BOX_SIZING_BORDER_BOX) {
505-
main_size += css_border_y(s) + css_padding_y(s);
506-
}
513+
main_size = ui_compute_column_item_main_size(child);
507514
// 根据项目的 flex-grow 和 flex-shrink,调整它的高度
508515
if (space >= 0) {
509516
if (s->type_bits.flex_grow > 0) {
510517
CSS_SET_FIXED_LENGTH(
511-
s, height, main_size + k * s->flex_grow);
518+
s, height,
519+
s->flex_basis + k * s->flex_grow);
512520
}
513521
} else if (s->type_bits.flex_shrink > 0) {
514-
CSS_SET_FIXED_LENGTH(s, height,
515-
main_size + k * s->flex_shrink);
522+
CSS_SET_FIXED_LENGTH(
523+
s, height, s->flex_basis + k * s->flex_shrink);
516524
}
517525
// 计算拉伸的宽度
518526
if (align_items == CSS_ALIGN_ITEMS_STRETCH &&
@@ -523,7 +531,7 @@ static void ui_flexbox_layout_update_column(ui_flexbox_layout_context_t *ctx)
523531
css_margin_x(s)));
524532
}
525533
ui_widget_auto_reflow(child);
526-
main_axis += child->outer_box.height;
534+
main_axis += main_size;
527535
}
528536
ctx->line->main_size = main_axis;
529537
space = ctx->widget->content_box.height - main_axis;
@@ -563,6 +571,7 @@ static void ui_flexbox_layout_update_column(ui_flexbox_layout_context_t *ctx)
563571
child->layout_y = main_axis;
564572
child->layout_x = ctx->line->cross_axis;
565573
if (!ui_widget_in_layout_flow(child)) {
574+
ui_widget_reset_layout(child);
566575
ui_widget_compute_style(node->data);
567576
ui_widget_auto_reflow(node->data);
568577
ui_widget_update_box_position(node->data);

lib/ui/src/ui_updater.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,7 @@ static void ui_widget_update_size(ui_widget_t *w)
311311
css_computed_style_t *src = &w->specified_style;
312312
css_computed_style_t *dest = &w->computed_style;
313313

314-
CSS_COPY_LENGTH(dest, src, width);
315-
CSS_COPY_LENGTH(dest, src, height);
314+
ui_widget_reset_layout(w);
316315
ui_widget_compute_style(w);
317316
ui_widget_update_box_size(w);
318317
ui_widget_reflow(w);

0 commit comments

Comments
 (0)