hueSlider
Returns true if the hue was changed
hue >= 0 and hue < 360
Parameters
- src:std.builtin.SourceLocation
- std.builtin.SourceLocation
- dir:dvui.enums.Direction
- dvui.enums.Direction
- hue:*f32
- *f32
- opts:Options
- Options
Source
Implementation
pub fn hueSlider(src: std.builtin.SourceLocation, dir: dvui.enums.Direction, hue: *f32, opts: Options) bool {
var fraction = std.math.clamp(hue.* / 360, 0, 1);
std.debug.assert(fraction >= 0);
std.debug.assert(fraction <= 1);
const options = hue_slider_defaults.override(opts);
var b = dvui.box(src, .{ .dir = dir }, options);
defer b.deinit();
if (b.data().accesskit_node()) |ak_node| {
AccessKit.nodeAddAction(ak_node, AccessKit.Action.focus);
AccessKit.nodeAddAction(ak_node, AccessKit.Action.set_value);
AccessKit.nodeSetOrientation(ak_node, AccessKit.Orientation.horizontal);
AccessKit.nodeSetMinNumericValue(ak_node, 0);
AccessKit.nodeSetMaxNumericValue(ak_node, 359);
AccessKit.nodeSetNumericValue(ak_node, hue.*);
}
dvui.tabIndexSet(b.data().id, options.tab_index, b.data().rectScale().r);
const br = b.data().contentRect();
const knobsize: dvui.Size = switch (dir) {
.horizontal => .{ .w = 10, .h = br.h },
.vertical => .{ .w = br.w, .h = 10 },
};
const track_thickness = 10;
const track: dvui.Rect = switch (dir) {
.horizontal => .{ .x = 0, .y = br.h / 2 - track_thickness / 2, .w = br.w, .h = track_thickness },
.vertical => .{ .x = br.w / 2 - track_thickness / 2, .y = 0, .w = track_thickness, .h = br.h },
};
const trackrs = b.widget().screenRectScale(track);
var ret = false;
const rect = b.data().contentRect().justSize().outset(if (dir == .vertical) .{ .y = 5, .h = 5 } else .{ .x = 5, .w = 5 });
const rs = b.widget().screenRectScale(rect);
const evts = dvui.events();
for (evts) |*e| {
if (!dvui.eventMatch(e, .{ .id = b.data().id, .r = rs.r }))
continue;
switch (e.evt) {
.mouse => |me| {
var p: ?dvui.Point.Physical = null;
if (me.action == .focus) {
e.handle(@src(), b.data());
dvui.focusWidget(b.data().id, null, e.num);
} else if (me.action == .press and me.button.pointer()) {
// capture
dvui.captureMouse(b.data(), e.num);
e.handle(@src(), b.data());
p = me.p;
} else if (me.action == .release and me.button.pointer()) {
// stop capture
dvui.captureMouse(null, e.num);
dvui.dragEnd();
e.handle(@src(), b.data());
} else if (me.action == .motion and dvui.captured(b.data().id)) {
// handle only if we have capture
e.handle(@src(), b.data());
p = me.p;
} else if (me.action == .position) {
dvui.cursorSet(.arrow);
}
if (p) |pp| {
const val = switch (dir) {
.horizontal => (pp.x - trackrs.r.x) / trackrs.r.w,
.vertical => (pp.y - trackrs.r.y) / trackrs.r.h,
};
fraction = std.math.clamp(val, 0, 1);
ret = true;
}
},
.key => |ke| {
if (ke.action == .down or ke.action == .repeat) {
switch (ke.code) {
.left, .up => {
e.handle(@src(), b.data());
fraction = std.math.clamp(fraction - 0.05, 0, 1);
ret = true;
},
.right, .down => {
e.handle(@src(), b.data());
fraction = std.math.clamp(fraction + 0.05, 0, 1);
ret = true;
},
else => {},
}
}
},
.text => |te| {
switch (te.action) {
.value => |set| {
const new_hue = std.fmt.parseFloat(f32, set.txt) catch hue.*;
if (new_hue >= 0 and new_hue < 360) {
hue.* = new_hue;
}
},
else => {},
}
},
else => {},
}
}
if (ret) {
hue.* = fraction * 359.99;
dvui.refresh(null, @src(), b.data().id);
}
const uv_offset = comptime 0.5 / @as(f32, @floatFromInt(hue_selector_colors.len));
const texture = getHueSelectorTexture(dir) catch |err| blk: {
dvui.logError(@src(), err, "Could not get hue selector texture", .{});
break :blk null;
};
if (texture) |tex| {
dvui.renderTexture(tex, trackrs, .{
.corners = options.cornersGet(),
.uv = .{
.x = uv_offset,
.y = if (dir == .vertical) uv_offset else 1 - uv_offset,
.w = 1 - uv_offset,
.h = if (dir == .horizontal) uv_offset else 1 - uv_offset,
},
}) catch |err| {
dvui.logError(@src(), err, "Could not render hue selector texture", .{});
};
}
const knobRect = dvui.Rect.fromPoint(switch (dir) {
.horizontal => .{ .x = (br.w * fraction) - knobsize.w / 2 },
.vertical => .{ .y = (br.h * fraction) - knobsize.h / 2 },
}).toSize(knobsize);
var knob = dvui.box(@src(), .{ .dir = .horizontal }, .{
.rect = knobRect,
.padding = .{},
.margin = .{},
.background = true,
.border = .all(1),
.corners = .all(100),
.color_fill = (Color.HSV{ .h = hue.* }).toColor(),
});
if (b.data().id == dvui.focusedWidgetId()) {
knob.data().focusBorder();
}
knob.deinit();
return ret;
}