textEntryColor
A text entry for hex color codes. Supports the same formats as Color.fromHex
Parameters
- src:std.builtin.SourceLocation
- std.builtin.SourceLocation
- init_opts:TextEntryColorInitOptions
- TextEntryColorInitOptions
- opts:Options
- Options
Source
Implementation
pub fn textEntryColor(src: std.builtin.SourceLocation, init_opts: TextEntryColorInitOptions, opts: Options) TextEntryColorResult {
const defaults = Options{ .name = "textEntryColor" };
var options = defaults.override(opts);
if (options.min_size_content == null) {
options = options.override(.{ .min_size_content = opts.fontGet().textSize(if (init_opts.allow_alpha) "#DDDDDDDD" else "#DDDDDD") });
}
const id = dvui.parentGet().extendId(src, opts.idExtra());
const default_bytes: [9]u8 = @splat(0);
const buffer = dataGetSliceDefault(null, id, "buffer", []u8, &default_bytes);
var te: TextEntryWidget = undefined;
te.init(src, .{ .text = .{ .buffer = buffer }, .placeholder = init_opts.placeholder }, options);
//initialize with input number
if (init_opts.value) |v| {
const old_value = dataGet(null, id, "value", Color);
if (old_value == null or
old_value.?.r != v.r or
old_value.?.g != v.g or
old_value.?.b != v.b or
old_value.?.a != v.a)
{
dataSet(null, id, "value", v.*);
@memset(buffer, 0); // clear out anything that was there before
if (init_opts.allow_alpha and v.a != 0xff) {
_ = std.fmt.bufPrint(buffer, "#{x:0>2}{x:0>2}{x:0>2}{x:0>2}", .{ v.r, v.g, v.b, v.a }) catch unreachable;
te.len = 9;
} else {
te.textSet(&(v.toHexString()), false);
}
}
}
te.processEvents();
// filter before drawing
te.filterIn(std.fmt.hex_charset ++ "ABCDEF" ++ "#");
var result: TextEntryColorResult = .{ .enter_pressed = te.enter_pressed };
// validation
const text = te.getText();
const color: ?Color = Color.tryFromHex(text) catch null;
//determine error if any
if (text.len == 0 and color == null) {
result.value = .Empty;
} else if (color == null) {
result.value = .{ .Invalid = .non_hex_value };
} else if (!init_opts.allow_alpha and color.?.a != 0xFF) {
result.value = .{ .Invalid = .alpha_passed_when_not_allowed };
} else {
result.value = .{ .Valid = color.? };
if (init_opts.value) |v| {
if ((te.enter_pressed or te.text_changed) and
(color.?.r != v.r or
color.?.g != v.g or
color.?.b != v.b or
color.?.a != v.a))
{
dataSet(null, id, "value", color.?);
v.* = color.?;
result.changed = true;
}
}
}
if (init_opts.value != null and result.value == .Empty and focusedWidgetId() != te.data().id) {
// If the text entry is empty and we loose focus,
// reset the hex value by invalidating the stored previous value
dataRemove(null, id, "value");
refresh(null, @src(), id);
}
te.draw();
if (result.value != .Valid and (init_opts.value != null or result.value != .Empty)) {
const rs = te.data().borderRectScale();
rs.r.outsetAll(1).stroke(te.data().options.cornersGet().scale(rs.s, CornerRect.Physical), .{ .thickness = 3 * rs.s, .color = dvui.themeGet().err.fill orelse .red, .after = true });
}
te.deinit();
return result;
}