zite/src/treeview.zig

140 lines
4.1 KiB
Zig

const std = @import("std");
const zig_sdl = @import("zig-sdl");
const sdl = zig_sdl.sdl;
const Ui = @import("ui.zig").Ui;
const colorTheme = @import("color_theme.zig").colorTheme;
pub const TreeView = struct {
const Entry = struct {
pub const height: i32 = 25;
name: []const u8 = "",
kind: std.fs.Dir.Entry.Kind,
texture: ?sdl.Texture = null,
y: i32 = 0,
textWidth: i32 = 0,
textHeight: i32 = 0,
highlighted: bool = false,
fn prerender(self: *Entry, ui: *Ui) !void {
if (self.texture) |texture| {
texture.deinit();
}
var color = if (self.kind == .Directory) colorTheme.treeFolderFg else colorTheme.treeFileFg;
var name = try std.mem.dupeZ(std.heap.c_allocator, u8, self.name);
var surface = try ui.uiFont.renderBlended(name, color);
defer surface.deinit();
self.texture = try ui.renderer.createTextureFromSurface(surface);
self.textWidth = surface.width();
self.textHeight = surface.height();
}
pub fn render(self: *Entry, ui: *Ui) !void {
if (self.texture == null) {
try self.prerender(ui);
}
if (self.highlighted) {
try ui.renderer.setDrawColor(colorTheme.treeEntryHighlightBg);
try ui.renderer.fillRect(sdl.Rect{
.x = 0,
.y = ui.scale(i32, self.y),
.w = ui.scale(i32, TreeView.width),
.h = ui.scale(i32, Entry.height),
});
ui.cursorManager.set(.Hand);
}
var y = @divTrunc(ui.scale(i32, Entry.height) - self.textHeight, 2);
var dst = sdl.Rect{
.x = ui.scale(i32, 10),
.y = ui.scale(i32, self.y) + y,
.w = self.textWidth,
.h = self.textHeight,
};
if (self.texture) |texture| {
try ui.renderer.copy(texture, null, dst);
}
}
pub fn mouseMotion(self: *Entry, event: sdl.MouseMotionEvent) void {
self.highlighted = event.y > self.y and event.y <= self.y + Entry.height and event.x <= TreeView.width;
}
pub fn mouseButton(self: *Entry, ui: *Ui, event: sdl.MouseButtonEvent) void {
if (event.state == .Released and self.highlighted) {
ui.openFile(self.name);
}
}
};
pub const width = 200;
height: i32 = 0,
// Temporary, std.heap.c_allocator was broken, so this for now
count: u64 = 0,
entries: [256]Entry = undefined,
pub fn init() TreeView {
return TreeView{};
}
pub fn deinit(self: TreeView) void {
for (self.entries[0..self.count]) |entry| {
if (entry.texture) |texture| {
texture.deinit();
}
}
}
pub fn render(self: *TreeView, ui: *Ui) !void {
try ui.renderer.setDrawColor(colorTheme.treeBg);
try ui.renderer.fillRect(sdl.Rect{
.x = 0,
.y = 0,
.w = ui.scale(i32, 200),
.h = ui.scale(i32, ui.height),
});
for (self.entries[0..self.count]) |*entry, i| {
try entry.render(ui);
}
}
pub fn refresh(self: *TreeView) !void {
var dir = try std.fs.cwd().openDir("./", .{ .iterate = true });
var iterator = dir.iterate();
var index: u32 = 0;
while (try iterator.next()) |file| {
self.entries[index] = Entry{
.name = file.name,
.kind = file.kind,
.y = @bitCast(i32, index) * Entry.height + 10,
};
index += 1;
}
self.count = index;
}
pub fn mouseMotion(self: *TreeView, event: sdl.MouseMotionEvent) void {
for (self.entries[0..self.count]) |*entry, i| {
entry.mouseMotion(event);
}
}
pub fn mouseButton(self: *TreeView, ui: *Ui, event: sdl.MouseButtonEvent) void {
for (self.entries[0..self.count]) |*entry, i| {
entry.mouseButton(ui, event);
}
}
};