forked from zenolith/zenolith
feat: implement builtin themes and make Labels use attreebutes
This commit is contained in:
parent
ab4a4395d8
commit
f84d6be6be
6 changed files with 141 additions and 14 deletions
|
@ -50,7 +50,7 @@ If you'd like to suggest a new feature or design change, please open an issue fi
|
|||
- [ ] Scrolled Pane
|
||||
- [x] Focus System
|
||||
- [x] Theming
|
||||
- [ ] Built-in themes
|
||||
- [x] Built-in themes
|
||||
- [ ] Layout overflow handling
|
||||
- [x] Logo
|
||||
- [x] Treevents (Tree-Bound, downwards events)
|
||||
|
|
97
src/Theme.zig
Normal file
97
src/Theme.zig
Normal file
|
@ -0,0 +1,97 @@
|
|||
//! A structure containing all theme-related values of zenolith's builtin widgets.
|
||||
//! This allows for convenient handling of themes for default widgets.
|
||||
const std = @import("std");
|
||||
|
||||
const AttreebuteMap = @import("attreebute.zig").AttreebuteMap;
|
||||
const BoxStyle = @import("attreebutes/BoxStyle.zig");
|
||||
const ButtonStyle = @import("attreebutes/ButtonStyle.zig");
|
||||
const Color = @import("Color.zig");
|
||||
const LabelStyle = @import("attreebutes/LabelStyle.zig");
|
||||
|
||||
pub const catppuccin_latte = Theme{
|
||||
.box = .{ .background = .{ .fill = Color.fromInt(0xeff1f5ff) } },
|
||||
.button = .{
|
||||
.background = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xe64553ff),
|
||||
.fill = Color.fromInt(0xccd0daff),
|
||||
.width = 4,
|
||||
} },
|
||||
.background_hovered = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xe64553ff),
|
||||
.fill = Color.fromInt(0xbcc0ccff),
|
||||
.width = 2,
|
||||
} },
|
||||
.padding = 4,
|
||||
.font_style = .{ .color = Color.fromInt(0x4c4f69ff) },
|
||||
},
|
||||
.label = .{ .font_style = .{ .color = Color.fromInt(0x4c4f69ff) } },
|
||||
};
|
||||
|
||||
pub const catppuccin_frappe = Theme{
|
||||
.box = .{ .background = .{ .fill = Color.fromInt(0x303446ff) } },
|
||||
.button = .{
|
||||
.background = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xea999cff),
|
||||
.fill = Color.fromInt(0x414559ff),
|
||||
.width = 4,
|
||||
} },
|
||||
.background_hovered = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xea999cff),
|
||||
.fill = Color.fromInt(0x51576dff),
|
||||
.width = 2,
|
||||
} },
|
||||
.padding = 4,
|
||||
.font_style = .{ .color = Color.fromInt(0xc6d0f5ff) },
|
||||
},
|
||||
.label = .{ .font_style = .{ .color = Color.fromInt(0xc6d0f5ff) } },
|
||||
};
|
||||
|
||||
pub const catppuccin_macchiato = Theme{
|
||||
.box = .{ .background = .{ .fill = Color.fromInt(0x24273aff) } },
|
||||
.button = .{
|
||||
.background = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xee99a0ff),
|
||||
.fill = Color.fromInt(0x363a4fff),
|
||||
.width = 4,
|
||||
} },
|
||||
.background_hovered = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xee99a0ff),
|
||||
.fill = Color.fromInt(0x09494d64ff),
|
||||
.width = 2,
|
||||
} },
|
||||
.padding = 4,
|
||||
.font_style = .{ .color = Color.fromInt(0xcad3f5ff) },
|
||||
},
|
||||
.label = .{ .font_style = .{ .color = Color.fromInt(0xcad3f5ff) } },
|
||||
};
|
||||
|
||||
pub const catppuccin_mocha = Theme{
|
||||
.box = .{ .background = .{ .fill = Color.fromInt(0x1e1e2eff) } },
|
||||
.button = .{
|
||||
.background = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xeba0acff),
|
||||
.fill = Color.fromInt(0x313244ff),
|
||||
.width = 4,
|
||||
} },
|
||||
.background_hovered = .{ .stroked = .{
|
||||
.stroke = Color.fromInt(0xeba0acff),
|
||||
.fill = Color.fromInt(0x45475aff),
|
||||
.width = 2,
|
||||
} },
|
||||
.padding = 4,
|
||||
.font_style = .{ .color = Color.fromInt(0xcdd6f4ff) },
|
||||
},
|
||||
.label = .{ .font_style = .{ .color = Color.fromInt(0xcdd6f4ff) } },
|
||||
};
|
||||
|
||||
box: BoxStyle,
|
||||
button: ButtonStyle,
|
||||
label: LabelStyle,
|
||||
|
||||
const Theme = @This();
|
||||
|
||||
pub fn apply(self: Theme, alloc: std.mem.Allocator, map: *AttreebuteMap) !void {
|
||||
(try map.mod(alloc, BoxStyle)).* = self.box;
|
||||
(try map.mod(alloc, ButtonStyle)).* = self.button;
|
||||
(try map.mod(alloc, LabelStyle)).* = self.label;
|
||||
}
|
|
@ -18,11 +18,13 @@ test {
|
|||
_ = BoxStyle;
|
||||
_ = ButtonStyle;
|
||||
_ = CurrentFont;
|
||||
_ = LabelStyle;
|
||||
}
|
||||
|
||||
pub const BoxStyle = @import("attreebutes/BoxStyle.zig");
|
||||
pub const ButtonStyle = @import("attreebutes/ButtonStyle.zig");
|
||||
pub const CurrentFont = @import("attreebutes/CurrentFont.zig");
|
||||
pub const LabelStyle = @import("attreebutes/LabelStyle.zig");
|
||||
|
||||
pub const AttreebuteMap = struct {
|
||||
const Context = struct {
|
||||
|
|
4
src/attreebutes/LabelStyle.zig
Normal file
4
src/attreebutes/LabelStyle.zig
Normal file
|
@ -0,0 +1,4 @@
|
|||
//! Style options for Labels.
|
||||
const Style = @import("../text/Style.zig");
|
||||
|
||||
font_style: Style,
|
|
@ -19,6 +19,7 @@ test {
|
|||
_ = widget;
|
||||
|
||||
_ = Color;
|
||||
_ = Theme;
|
||||
_ = WidgetIter;
|
||||
}
|
||||
|
||||
|
@ -35,6 +36,7 @@ pub const util = @import("util.zig");
|
|||
pub const widget = @import("widget.zig");
|
||||
|
||||
pub const Color = @import("Color.zig");
|
||||
pub const Theme = @import("Theme.zig");
|
||||
pub const WidgetIter = @import("WidgetIter.zig");
|
||||
|
||||
/// List of the default widget implementations included with Zenolith.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//! A simple text label with a given color and size.
|
||||
// TODO: use CurrentFont
|
||||
//! A simple text label displaying given text. Font style is controlled via attreebutes.
|
||||
const std = @import("std");
|
||||
|
||||
const font = @import("../text/font.zig");
|
||||
|
@ -7,42 +6,65 @@ const treev = @import("../treevent.zig");
|
|||
const layout = @import("../layout.zig");
|
||||
|
||||
const Color = @import("../Color.zig");
|
||||
const CurrentFont = @import("../attreebutes/CurrentFont.zig");
|
||||
const LabelStyle = @import("../attreebutes/LabelStyle.zig");
|
||||
const Span = @import("../text/Span.zig");
|
||||
const Widget = @import("../widget.zig").Widget;
|
||||
|
||||
font: *font.Font,
|
||||
span: Span,
|
||||
/// The text the Label is to be initialized with.
|
||||
/// This will not change if the text is updated afterwards.
|
||||
/// The reason this exists is that the widget is not linked into a tree and
|
||||
/// thus has no font yet when being constructed.
|
||||
initial_text: []const u8,
|
||||
|
||||
/// This is the inner span. Initialized upon the widget being linked.
|
||||
span: ?Span,
|
||||
|
||||
const Label = @This();
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, opts: Span.InitOptions) !*Widget {
|
||||
pub fn init(alloc: std.mem.Allocator, text: []const u8) !*Widget {
|
||||
const self = Label{
|
||||
.font = opts.font,
|
||||
.span = try Span.init(alloc, opts),
|
||||
.initial_text = text,
|
||||
.span = null,
|
||||
};
|
||||
errdefer self.span.deinit();
|
||||
|
||||
return try Widget.init(alloc, self);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Label, selfw: *Widget) void {
|
||||
_ = selfw;
|
||||
self.span.deinit();
|
||||
if (self.span) |s| s.deinit();
|
||||
}
|
||||
|
||||
pub fn treevent(self: *Label, selfw: *Widget, tv: anytype) !void {
|
||||
switch (@TypeOf(tv)) {
|
||||
treev.Link => {
|
||||
try tv.dispatch(selfw);
|
||||
|
||||
const curfont = selfw.getAttreebute(CurrentFont) orelse
|
||||
@panic("Labels require the CurrentFont attreebute!");
|
||||
self.span = try Span.init(selfw.data.allocator, .{
|
||||
.font = curfont.font,
|
||||
.text = self.initial_text,
|
||||
});
|
||||
},
|
||||
treev.LayoutSize => {
|
||||
selfw.data.size = tv.constraints.clamp(.{
|
||||
.width = self.span.baseline_width,
|
||||
.height = self.span.font.yOffset(self.span.style.size),
|
||||
.width = self.span.?.baseline_width,
|
||||
.height = self.span.?.font.yOffset(self.span.?.style.size),
|
||||
});
|
||||
},
|
||||
treev.Draw => {
|
||||
const style = selfw.getAttreebute(LabelStyle) orelse
|
||||
@panic("The Button widget must have the ButtonStyle attreebute set!");
|
||||
|
||||
self.span.?.style = style.font_style;
|
||||
self.span.?.layout();
|
||||
|
||||
try tv.painter.span(selfw.data.position.add(.{
|
||||
.x = 0,
|
||||
.y = self.span.font.yOffset(self.span.style.size) - self.span.baseline_y,
|
||||
}), self.span);
|
||||
.y = self.span.?.font.yOffset(self.span.?.style.size) - self.span.?.baseline_y,
|
||||
}), self.span.?);
|
||||
},
|
||||
else => try tv.dispatch(selfw),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue