1
0
Fork 0
zenolith/src/widgets/Button.zig

122 lines
4.1 KiB
Zig

//! A simple button widget. This will emit an ButtonActivated backevent when clicked on.
//! This widget requries the ButtonStyle attreebute to be set!
const std = @import("std");
const attreebute = @import("../attreebute.zig");
const backevent = @import("../backevent.zig");
const treev = @import("../treevent.zig");
const layout = @import("../layout.zig");
const Color = @import("../Color.zig");
const Span = @import("../text/Span.zig");
const Widget = @import("../widget.zig").Widget;
label_str: []const u8,
span: ?Span,
hovered: bool,
const Button = @This();
pub fn init(alloc: std.mem.Allocator, label: []const u8) !*Widget {
const self = Button{
.label_str = label,
.span = null,
.hovered = false,
};
return try Widget.init(alloc, self);
}
pub fn deinit(self: *Button, selfw: *Widget) void {
_ = selfw;
if (self.span) |span| span.deinit();
}
pub fn treevent(self: *Button, selfw: *Widget, tv: anytype) !void {
switch (@TypeOf(tv)) {
treev.LayoutSize => {
// TODO: do this in Link
const style = selfw.getAttreebute(attreebute.ButtonStyle) orelse
@panic("The Button widget must have the ButtonStyle attreebute set!");
if (self.span == null) {
const curfont = (selfw.getAttreebute(attreebute.CurrentFont) orelse
@panic("The Button widget must have the CurrentFont attreebute set!")).font;
self.span = try Span.init(selfw.data.allocator, .{
.font = curfont,
.style = style.font_style,
.text = self.label_str,
});
} else {
self.span.?.style = style.font_style;
self.span.?.layout();
}
selfw.data.size = layout.Size.two(style.padding * 2).add(self.span.?.layoutSize());
},
treev.Draw => {
const style = selfw.getAttreebute(attreebute.ButtonStyle) orelse
@panic("The Button widget must have the ButtonStyle attreebute set!");
if (self.span == null) {
const curfont = (selfw.getAttreebute(attreebute.CurrentFont) orelse
@panic("The Button widget must have the CurrentFont attreebute set!")).font;
self.span = try Span.init(selfw.data.allocator, .{
.font = curfont,
.style = style.font_style,
.text = self.label_str,
});
} else {
self.span.?.style = style.font_style;
self.span.?.layout();
}
try (if (self.hovered or selfw.data.platform.?.data.focused_widget == selfw)
style.background_hovered
else
style.background).drawBackground(
tv.painter,
.{ .pos = selfw.data.position, .size = selfw.data.size },
);
try tv.painter.span(
selfw.data.position.add(layout.Position.two(style.padding)).add(self.span.?.layoutOffset()),
self.span.?,
);
},
treev.Click => {
if (tv.button == .left and tv.action == .click and tv.isOnWidget(selfw.*)) {
try selfw.backevent(backevent.Backevent.create(
backevent.ButtonActivated{ .btn_widget = selfw },
{},
));
}
},
*treev.KeyInput => {
if (selfw.data.platform.?.data.focused_widget == selfw and
!tv.handled and
tv.action == .press and
tv.key == .space)
{
tv.handled = true;
try selfw.backevent(backevent.Backevent.create(
backevent.ButtonActivated{ .btn_widget = selfw },
{},
));
}
},
treev.MouseMove => {
self.hovered = tv.isOnWidget(selfw.*);
},
*treev.FocusNext => {
tv.acquireFocus(selfw);
try tv.dispatch(selfw);
},
else => try tv.dispatch(selfw),
}
}