Commit: 6ed077299184d1ba8796e624bd0815e98f167fd7
Parent: 6d44e42c35ee6ae7fab9cdf76e0c2e6958901a53
Author: Randy Palamar
Date: Wed, 19 Mar 2025 07:45:47 -0600
ui: limit view drawing to provided draw rectangle
Diffstat:
M | ui.c | | | 171 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
1 file changed, 116 insertions(+), 55 deletions(-)
diff --git a/ui.c b/ui.c
@@ -115,6 +115,7 @@ struct Variable {
VariableType type;
f32 hover_t;
+ f32 name_width;
};
enum variable_flags {
@@ -276,17 +277,17 @@ add_variable(Variable *group, Arena *arena, s8 name, u32 flags, VariableType typ
Variable *result;
if (type == VT_BEAMFORMER_VARIABLE) result = (Variable *)push_struct(arena, BeamformerVariable);
else result = push_struct(arena, Variable);
- result->flags = flags;
- result->type = type;
- result->name = name;
- result->parent = group;
+ result->flags = flags;
+ result->type = type;
+ result->name = name;
+ result->parent = group;
+ result->name_width = measure_text(font, name).x;
if (group && group->type == VT_GROUP) {
if (group->u.group.last) group->u.group.last = group->u.group.last->next = result;
else group->u.group.last = group->u.group.first = result;
- f32 name_width = measure_text(font, name).x;
- group->u.group.max_name_width = MAX(group->u.group.max_name_width, name_width);
+ group->u.group.max_name_width = MAX(group->u.group.max_name_width, result->name_width);
}
return result;
@@ -507,6 +508,30 @@ draw_text(Font font, s8 text, v2 pos, Color colour)
return result;
}
+static v2
+draw_text_limited(Font font, s8 text, v2 pos, Color colour, f32 space, f32 text_width)
+{
+ v2 result = {.y = font.baseSize};
+ if (text_width < space) {
+ result = draw_text(font, text, pos, colour);
+ } else {
+ f32 elipsis_width = measure_text(font, s8("...")).x;
+ if (elipsis_width < space) {
+ /* TODO(rnp): there must be a better way */
+ while (text.len) {
+ text.len--;
+ f32 width = measure_text(font, text).x;
+ if (width + elipsis_width < space)
+ break;
+ }
+ result.x += draw_text(font, text, pos, colour).x;
+ pos.x += result.x;
+ result.x += draw_text(font, s8("..."), pos, colour).x;
+ }
+ }
+ return result;
+}
+
/* NOTE(rnp): expensive but of the available options in raylib this gives the best results */
static v2
draw_outlined_text(Font font, s8 text, v2 pos, f32 outline_width, Color colour, Color outline)
@@ -700,10 +725,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, BeamformerFrameView *view,
v2 txt_s = measure_text(ui->small_font, s8("-288.8 mm"));
- display_rect.pos.x += 0.02 * display_rect.size.w;
- display_rect.pos.y += 0.02 * display_rect.size.h;
- display_rect.size.w *= 0.96;
- display_rect.size.h *= 0.96;
+ display_rect = shrink_rect_centered(display_rect, (v2){.x = 2 * UI_REGION_PAD, .y = UI_REGION_PAD});
f32 pad = 1.2 * txt_s.x + RULER_TICK_LENGTH;
Rect vr = display_rect;
@@ -750,16 +772,22 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, BeamformerFrameView *view,
v2 start_pos = vr.pos;
start_pos.y += vr.size.y;
- do_scale_bar(ui, &buf, &view->lateral_scale_bar, SB_LATERAL, mouse,
- (Rect){.pos = start_pos, .size = vr.size}, bp->output_min_coordinate.x * 1e3,
- bp->output_max_coordinate.x * 1e3, s8(" mm"));
+ if (vr.size.w > 0) {
+ do_scale_bar(ui, &buf, &view->lateral_scale_bar, SB_LATERAL, mouse,
+ (Rect){.pos = start_pos, .size = vr.size},
+ bp->output_min_coordinate.x * 1e3,
+ bp->output_max_coordinate.x * 1e3, s8(" mm"));
+ }
start_pos = vr.pos;
start_pos.x += vr.size.x;
- do_scale_bar(ui, &buf, &view->axial_scale_bar, SB_AXIAL, mouse,
- (Rect){.pos = start_pos, .size = vr.size}, bp->output_max_coordinate.z * 1e3,
- bp->output_min_coordinate.z * 1e3, s8(" mm"));
+ if (vr.size.h > 0) {
+ do_scale_bar(ui, &buf, &view->axial_scale_bar, SB_AXIAL, mouse,
+ (Rect){.pos = start_pos, .size = vr.size},
+ bp->output_max_coordinate.z * 1e3,
+ bp->output_min_coordinate.z * 1e3, s8(" mm"));
+ }
v2 pixels_to_mm = output_dim;
pixels_to_mm.x /= vr.size.x * 1e-3;
@@ -787,24 +815,29 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, BeamformerFrameView *view,
buf.widx = 0;
stream_append_v2(&buf, mm);
v2 txt_s = measure_text(ui->small_font, stream_to_s8(&buf));
- v2 txt_p = {
- .x = vr.pos.x + vr.size.w - txt_s.w - 4,
- .y = vr.pos.y + vr.size.h - txt_s.h - 4,
- };
- draw_outlined_text(ui->small_font, stream_to_s8(&buf), txt_p, 1,
- colour_from_normalized(RULER_COLOUR), BLACK);
+ if (vr.size.w + vr.pos.x - txt_s.w - 4 > display_rect.pos.x && txt_s.h < display_rect.size.h - 4) {
+ v2 txt_p = {
+ .x = vr.pos.x + vr.size.w - txt_s.w - 4,
+ .y = vr.pos.y + vr.size.h - txt_s.h - 4,
+ };
+ draw_outlined_text(ui->small_font, stream_to_s8(&buf), txt_p, 1,
+ colour_from_normalized(RULER_COLOUR), BLACK);
+ }
}
{
buf.widx = 0;
s8 shader = push_das_shader_id(&buf, frame->das_shader_id, frame->compound_count);
v2 txt_s = measure_text(ui->font, shader);
- v2 txt_p = {
- .x = vr.pos.x + vr.size.w - txt_s.w - 16,
- .y = vr.pos.y + 4,
- };
- draw_outlined_text(ui->font, shader, txt_p, 1,
- colour_from_normalized(RULER_COLOUR), BLACK);
+ /* TODO(rnp): we want this 16 to be proportional to vr size */
+ if (vr.size.w + vr.pos.x - txt_s.w - 16 > display_rect.pos.x && txt_s.h < display_rect.size.h - 4) {
+ v2 txt_p = {
+ .x = vr.pos.x + vr.size.w - txt_s.w - 16,
+ .y = vr.pos.y + 4,
+ };
+ draw_outlined_text(ui->font, shader, txt_p, 1,
+ colour_from_normalized(RULER_COLOUR), BLACK);
+ }
}
/* TODO(rnp): store converted ruler points instead of screen points */
@@ -836,14 +869,15 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, BeamformerFrameView *view,
}
static v2
-draw_beamformer_variable(BeamformerUI *ui, Arena arena, Variable *var, v2 at, v2 mouse, f32 *hover_t)
+draw_beamformer_variable(BeamformerUI *ui, Arena arena, Variable *var, v2 at, v2 mouse,
+ f32 *hover_t, f32 space)
{
Stream buf = arena_stream(&arena);
stream_append_variable(&buf, var);
Color colour = NORMALIZED_FG_COLOUR;
+ v2 text_size = measure_text(ui->font, stream_to_s8(&buf));
if (var->flags & V_INPUT) {
- v2 text_size = measure_text(ui->font, stream_to_s8(&buf));
Rect text_rect = {.pos = at, .size = text_size};
text_rect = extend_rect_centered(text_rect, (v2){.x = 8});
@@ -858,10 +892,10 @@ draw_beamformer_variable(BeamformerUI *ui, Arena arena, Variable *var, v2 at, v2
colour = colour_from_normalized(lerp_v4(FG_COLOUR, HOVERED_COLOUR, *hover_t));
}
- return draw_text(ui->font, stream_to_s8(&buf), at, colour);
+ return draw_text_limited(ui->font, stream_to_s8(&buf), at, colour, space, text_size.x);
}
-#define LISTING_CENTER_PAD 12.0f
+#define LISTING_ITEM_PAD 12.0f
#define LISTING_INDENT 20.0f
#define LISTING_LINE_PAD 6.0f
@@ -884,10 +918,11 @@ draw_variable_list(BeamformerUI *ui, Variable *group, Rect r, v2 mouse)
BeamformerVariable *bv = (BeamformerVariable *)var;
suffix = bv->suffix;
- advance = draw_text(ui->font, var->name, at, NORMALIZED_FG_COLOUR).y;
- at.x += x_off + LISTING_CENTER_PAD;
-
- draw_beamformer_variable(ui, ui->arena, var, at, mouse, &var->hover_t);
+ advance = draw_text_limited(ui->font, var->name, at, NORMALIZED_FG_COLOUR,
+ r.size.w + r.pos.x - at.x, var->name_width).y;
+ at.x += x_off + LISTING_ITEM_PAD;
+ at.x += draw_beamformer_variable(ui, ui->arena, var, at, mouse,
+ &var->hover_t, r.size.w + r.pos.x - at.x).x;
while (var) {
if (var->next) {
@@ -903,8 +938,9 @@ draw_variable_list(BeamformerUI *ui, Variable *group, Rect r, v2 mouse)
case VT_GROUP: {
VariableGroup *g = &var->u.group;
- advance = draw_beamformer_variable(ui, ui->arena, var, at, mouse, &var->hover_t).y;
- at.x += x_off + LISTING_CENTER_PAD;
+ advance = draw_beamformer_variable(ui, ui->arena, var, at, mouse, &var->hover_t,
+ r.size.w + r.pos.x - at.x).y;
+ at.x += x_off + LISTING_ITEM_PAD;
if (g->expanded) {
r.pos.x += LISTING_INDENT;
r.size.x -= LISTING_INDENT;
@@ -921,16 +957,23 @@ draw_variable_list(BeamformerUI *ui, Variable *group, Rect r, v2 mouse)
case VG_LIST: break;
case VG_V2:
case VG_V4: {
- at.x += draw_text(ui->font, s8("{"), at, NORMALIZED_FG_COLOUR).x;
+ at.x += draw_text_limited(ui->font, s8("{"), at, NORMALIZED_FG_COLOUR,
+ r.size.w + r.pos.x - at.x,
+ measure_text(ui->font, s8("{")).x).x;
while (v) {
at.x += draw_beamformer_variable(ui, ui->arena,
- (Variable *)v, at, mouse, &v->base.hover_t).x;
+ (Variable *)v, at, mouse, &v->base.hover_t,
+ r.size.w + r.pos.x - at.x).x;
v = (BeamformerVariable *)v->base.next;
- if (v) at.x += draw_text(ui->font, s8(", "), at,
- NORMALIZED_FG_COLOUR).x;
+ if (v) at.x += draw_text_limited(ui->font, s8(", "),
+ at, NORMALIZED_FG_COLOUR,
+ r.size.w + r.pos.x - at.x,
+ measure_text(ui->font, s8(", ")).x).x;
}
- at.x += draw_text(ui->font, s8("}"), at, NORMALIZED_FG_COLOUR).x;
+ at.x += draw_text_limited(ui->font, s8("}"), at, NORMALIZED_FG_COLOUR,
+ r.size.w + r.pos.x - at.x,
+ measure_text(ui->font, s8("}")).x).x;
} break;
}
@@ -942,8 +985,10 @@ draw_variable_list(BeamformerUI *ui, Variable *group, Rect r, v2 mouse)
if (suffix.len) {
v2 suffix_s = measure_text(ui->font, suffix);
- v2 suffix_p = {.x = r.pos.x + r.size.w - suffix_s.w, .y = r.pos.y};
- draw_text(ui->font, suffix, suffix_p, NORMALIZED_FG_COLOUR);
+ if (r.size.w + r.pos.x - LISTING_ITEM_PAD - suffix_s.x > at.x) {
+ v2 suffix_p = {.x = r.pos.x + r.size.w - suffix_s.w, .y = r.pos.y};
+ draw_text(ui->font, suffix, suffix_p, NORMALIZED_FG_COLOUR);
+ }
}
r.pos.y += advance + LISTING_LINE_PAD;
@@ -968,31 +1013,45 @@ draw_compute_stats(BeamformerCtx *ctx, ComputeShaderStats *stats, Arena arena, R
v2 pos = r.pos;
pos.y += r.size.h;
+ s8 compute_total = s8("Compute Total:");
+ f32 compute_total_width = measure_text(ui->font, compute_total).x;
+ f32 max_label_width = compute_total_width;
+ f32 *label_widths = alloc(&arena, f32, ARRAY_COUNT(labels));
+ for (u32 i = 0; i < ARRAY_COUNT(labels); i++) {
+ label_widths[i] = measure_text(ui->font, labels[i]).x;
+ max_label_width = MAX(label_widths[i], max_label_width);
+ }
+
f32 compute_time_sum = 0;
u32 stages = ctx->params->compute_stages_count;
for (u32 i = 0; i < stages; i++) {
u32 index = ctx->params->compute_stages[i];
pos.y -= measure_text(ui->font, labels[index]).y;
- draw_text(ui->font, labels[index], pos, colour_from_normalized(FG_COLOUR));
+ draw_text_limited(ui->font, labels[index], pos, colour_from_normalized(FG_COLOUR),
+ r.size.w, label_widths[index]);
- buf.widx = 0;
+ stream_reset(&buf, 0);
stream_append_f64_e(&buf, stats->times[index]);
stream_append_s8(&buf, s8(" [s]"));
v2 txt_fs = measure_text(ui->font, stream_to_s8(&buf));
- v2 rpos = {.x = r.pos.x + r.size.w - txt_fs.w, .y = pos.y};
- draw_text(ui->font, stream_to_s8(&buf), rpos, colour_from_normalized(FG_COLOUR));
+ v2 rpos = {.x = r.pos.x + max_label_width + LISTING_ITEM_PAD, .y = pos.y};
+ draw_text_limited(ui->font, stream_to_s8(&buf), rpos, colour_from_normalized(FG_COLOUR),
+ r.size.w - LISTING_ITEM_PAD - max_label_width, txt_fs.w);
compute_time_sum += stats->times[index];
}
pos.y -= ui->font.baseSize;
- draw_text(ui->font, s8("Compute Total:"), pos, colour_from_normalized(FG_COLOUR));
- buf.widx = 0;
+ draw_text_limited(ui->font, compute_total, pos, colour_from_normalized(FG_COLOUR),
+ r.size.w, compute_total_width);
+
+ stream_reset(&buf, 0);
stream_append_f64_e(&buf, compute_time_sum);
stream_append_s8(&buf, s8(" [s]"));
v2 txt_fs = measure_text(ui->font, stream_to_s8(&buf));
- v2 rpos = {.x = r.pos.x + r.size.w - txt_fs.w, .y = pos.y};
- draw_text(ui->font, stream_to_s8(&buf), rpos, colour_from_normalized(FG_COLOUR));
+ v2 rpos = {.x = r.pos.x + max_label_width + LISTING_ITEM_PAD, .y = pos.y};
+ draw_text_limited(ui->font, stream_to_s8(&buf), rpos, colour_from_normalized(FG_COLOUR),
+ r.size.w - LISTING_ITEM_PAD - max_label_width, txt_fs.w);
pos.y -= ui->font.baseSize;
if (ctx->csctx.processing_compute) ui->progress_display_t_velocity += 65 * dt_for_frame;
@@ -1005,10 +1064,12 @@ draw_compute_stats(BeamformerCtx *ctx, ComputeShaderStats *stats, Arena arena, R
if (ui->progress_display_t > (1.0 / 255.0)) {
s8 progress_text = s8("Compute Progress:");
v2 txt_s = measure_text(ui->font, progress_text);
- rpos = (v2){.x = pos.x + txt_s.x + 8, .y = pos.y};
draw_text(ui->font, progress_text, pos,
fade(colour_from_normalized(FG_COLOUR), ui->progress_display_t));
- Rect prect = {.pos = rpos, .size = {.w = r.size.w - rpos.x, .h = txt_s.h}};
+ Rect prect = {
+ .pos = {.x = r.pos.x + txt_s.w + LISTING_ITEM_PAD, .y = pos.y},
+ .size = {.w = r.size.w - txt_s.w - LISTING_ITEM_PAD, .h = txt_s.h}
+ };
prect = scale_rect_centered(prect, (v2){.x = 1, .y = 0.7});
Rect fprect = prect;
fprect.size.w *= ctx->csctx.processing_progress;