DVUI

displayUnion

Display a union.

If the union has Struct or Union members, then StructOptions(T) should be provided for those members with an appropriate default_value. These default values will be used to populate the active union value when the user changes selections.

Parameters

#
src:std.builtin.SourceLocation
std.builtin.SourceLocation
field_name:[]const u8
[]const u8
field_value_ptr:anytype
anytype
depth:usize
usize
field_option:FieldOptions
FieldOptions
options:anytype
anytype

Source

Implementation

#
pub fn displayUnion(
    src: std.builtin.SourceLocation,
    comptime field_name: []const u8,
    field_value_ptr: anytype,
    comptime depth: usize,
    field_option: FieldOptions,
    options: anytype,
) void {
    validateFieldPtrType(field_name, &.{.@"union"}, "displayUnion", @TypeOf(field_value_ptr));
    if (field_option.displayMode() == .none) return;

    if (@typeInfo(@TypeOf(field_value_ptr.*)).@"union".tag_type == null) {
        @compileError(std.fmt.comptimePrint("Field {s} cannot be displayed. Only tagged unions are supported.", .{field_name}));
    }
    if (!validFieldOptionsType(field_name, field_option, .standard)) return;
    const current_choice = std.meta.activeTag(field_value_ptr.*);
    const read_only = @typeInfo(@TypeOf(field_value_ptr)).pointer.is_const or field_option.displayMode() != .read_write;

    if (displayContainer(src, field_option.displayLabel(field_name), field_option.defaultExpanded())) |vbox| {
        defer vbox.deinit();

        const UnionT = @TypeOf(field_value_ptr.*);
        const new_choice = unionFieldWidget(@src(), field_name, field_value_ptr, field_option);
        if (current_choice != new_choice) {
            switch (new_choice) {
                inline else => |choice| {
                    const default_value = defaultValue(
                        @FieldType(UnionT, @tagName(choice)),
                        UnionT,
                        field_name,
                        options,
                    );
                    if (!read_only) {
                        if (default_value) |default| {
                            field_value_ptr.* = @unionInit(UnionT, @tagName(choice), default);
                        } else {
                            log.debug(
                                "Union field {s}.{s} cannot be selected as no default value is provided. Use struct_ui.StructOptions({s}) to provide a default.",
                                .{
                                    field_name, @tagName(choice),
                                    switch (@typeInfo(@FieldType(UnionT, @tagName(choice)))) {
                                        .@"union", .@"struct" => @typeName(@FieldType(UnionT, @tagName(choice))),
                                        else => @typeName(UnionT),
                                    },
                                },
                            );
                            return;
                        }
                    }
                },
            }
        }
        switch (field_value_ptr.*) {
            inline else => |*active, active_tag| {
                var inner_vbox = dvui.box(@src(), .{ .dir = .vertical }, .{ .expand = .horizontal, .id_extra = @intFromEnum(active_tag) });
                defer inner_vbox.deinit();
                const struct_options: StructOptions(UnionT) = findMatchingStructOption(UnionT, field_name, options) orelse .initWithDefaults(.{}, null);
                var alignment: dvui.Alignment = .init(@src(), depth);
                defer alignment.deinit();

                // Will only display if an option exists for this field.
                if (struct_options.field_options.get(active_tag)) |union_field_option_| {
                    var union_field_option = union_field_option_;
                    if (field_option.displayMode() == .constant and union_field_option.displayMode() != .none) {
                        union_field_option.markConst();
                    }
                    displayField(@src(), UnionT, @tagName(active_tag), active, depth, union_field_option, options, &alignment);
                }
            },
        }
    }
}