DVUI

numberFieldWidget

Display a numeric field

Parameters

#
src:std.builtin.SourceLocation
std.builtin.SourceLocation
field_name:[]const u8
[]const u8
field_value_ptr:anytype
anytype
opt:NumberFieldOptions
NumberFieldOptions
alignment:*dvui.Alignment
*dvui.Alignment

Source

Implementation

#
pub fn numberFieldWidget(
    src: std.builtin.SourceLocation,
    field_name: []const u8,
    field_value_ptr: anytype,
    opt: NumberFieldOptions,
    alignment: *dvui.Alignment,
) void {
    validateFieldPtrType(null, &.{ .float, .int }, "numberFieldWidget", @TypeOf(field_value_ptr));
    if (opt.display == .none) return;

    const T = @TypeOf(field_value_ptr.*);
    const read_only = @typeInfo(@TypeOf(field_value_ptr)).pointer.is_const or opt.display != .read_write;

    switch (opt.widget_type) {
        .number_entry => {
            var box = dvui.box(src, .{ .dir = .horizontal }, .{});
            defer box.deinit();

            dvui.label(@src(), "{s}", .{opt.label orelse field_name}, .{ .margin = .{ .y = 4 } });

            var hbox_aligned = dvui.box(@src(), .{ .dir = .horizontal }, .{ .margin = alignment.margin(box.data().id) });
            defer hbox_aligned.deinit();
            alignment.record(box.data().id, hbox_aligned.data());

            if (!read_only) {
                const maybe_num = dvui.textEntryNumber(@src(), T, .{
                    .min = opt.minValue(T),
                    .max = opt.maxValue(T),
                    .value = field_value_ptr,
                    .show_min_max = opt.min != null and opt.max != null,
                }, .{});
                if (maybe_num.value == .Valid) {
                    field_value_ptr.* = maybe_num.value.Valid;
                }
            }
            if (!defaults.narrow or read_only)
                dvui.label(@src(), "{d}", .{field_value_ptr.*}, .{ .margin = .{ .y = 4 } });
        },
        .entry_on_enter => {
            var box = dvui.box(src, .{ .dir = .horizontal }, .{});
            defer box.deinit();

            dvui.label(@src(), "{s}", .{opt.label orelse field_name}, .{ .margin = .{ .y = 4 } });

            var enter_pressed = dvui.dataGetDefault(null, box.data().id, "_enter_pressed", bool, false);
            defer dvui.dataSet(null, box.data().id, "_enter_pressed", enter_pressed);

            var hbox_aligned = dvui.box(@src(), .{ .dir = .horizontal }, .{ .margin = alignment.margin(box.data().id) });
            defer hbox_aligned.deinit();
            alignment.record(box.data().id, hbox_aligned.data());

            if (!read_only) {
                const value_str = std.fmt.allocPrint(dvui.currentWindow().lifo(), "{d}", .{field_value_ptr.*}) catch "";
                defer dvui.currentWindow().lifo().free(value_str);
                var te_wd: dvui.WidgetData = undefined;
                const maybe_num = dvui.textEntryNumber(@src(), T, .{
                    .text = if (enter_pressed) "" else null,
                    .placeholder = value_str,
                }, .{ .data_out = &te_wd });
                if (maybe_num.value == .Valid and maybe_num.enter_pressed) {
                    field_value_ptr.* = std.math.clamp(
                        maybe_num.value.Valid,
                        opt.minValue(T),
                        opt.maxValue(T),
                    );
                    enter_pressed = true;
                } else if (maybe_num.value == .Valid and !maybe_num.enter_pressed) {
                    dvui.tooltip(@src(), .{
                        .active_rect = te_wd.borderRectScale().r,
                        .position = .vertical,
                    }, "Press Enter to set value", .{}, .{});
                } else {
                    enter_pressed = false;
                }
            }
            if (!defaults.narrow or read_only)
                dvui.label(@src(), "{d}", .{field_value_ptr.*}, .{ .margin = .{ .y = 4 } });
        },
        .slider => {
            var box = dvui.box(src, .{ .dir = .horizontal }, .{});
            defer box.deinit();

            dvui.label(@src(), "{s}", .{opt.label orelse field_name}, .{ .margin = .{ .y = 4 } });
            var hbox_aligned = dvui.box(@src(), .{ .dir = .horizontal }, .{ .margin = alignment.margin(box.data().id) });
            defer hbox_aligned.deinit();
            alignment.record(box.data().id, hbox_aligned.data());

            if (!read_only) {
                var percent = opt.toNormalizedPercent(T, field_value_ptr.*);
                _ = dvui.slider(@src(), .{ .fraction = &percent }, .{
                    .expand = .horizontal,
                    .min_size_content = .{ .w = 100, .h = 20 },
                });
                field_value_ptr.* = opt.normalizedPercentToNum(T, percent);
            }
            dvui.label(@src(), "{d}", .{field_value_ptr.*}, .{ .margin = .{ .y = 4 } });
        },
        .slider_entry => {
            var box = dvui.box(src, .{ .dir = .horizontal }, .{});
            defer box.deinit();
            dvui.label(@src(), "{s}", .{opt.label orelse field_name}, .{ .margin = .{ .y = 4 } });
            var hbox_aligned = dvui.box(@src(), .{ .dir = .horizontal }, .{ .margin = alignment.margin(box.data().id), .expand = .vertical });
            defer hbox_aligned.deinit();
            alignment.record(box.data().id, hbox_aligned.data());

            if (!read_only) {
                var se_wd: dvui.WidgetData = undefined;
                var value: f32 = NumberFieldOptions.cast(f32, field_value_ptr.*);
                if (dvui.sliderEntry(@src(), "{d:0.2}", .{
                    .value = &value,
                    .min = opt.minValue(f32),
                    .max = opt.maxValue(f32),
                }, .{ .data_out = &se_wd, .gravity_y = 0.5 })) {
                    field_value_ptr.* = NumberFieldOptions.cast(T, value);
                }
                if (dvui.focusedWidgetId() == se_wd.id) {
                    dvui.tooltip(@src(), .{
                        .active_rect = se_wd.borderRectScale().r,
                        .delay = 1_000_000,
                        .position = .vertical,
                    }, "Press Enter to type a value", .{}, .{});
                }
            } else {
                dvui.label(@src(), "{d}", .{field_value_ptr.*}, .{ .margin = .{ .y = 4 } });
            }
        },
    }
}