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);
}
},
}
}
}