Implement TreeView (aka TreeWidget)
This commit is contained in:
parent
0569bb5de7
commit
cfde59e2f4
3 changed files with 130 additions and 17 deletions
109
src/main.zig
109
src/main.zig
|
@ -1,6 +1,7 @@
|
|||
const std = @import("std");
|
||||
const sdl = @import("sdl.zig");
|
||||
const ttf = @import("ttf.zig");
|
||||
const dirent = @cImport(@cInclude("dirent.h"));
|
||||
|
||||
const Ui = struct {
|
||||
window: sdl.Window,
|
||||
|
@ -9,7 +10,7 @@ const Ui = struct {
|
|||
uiFont: ttf.Font,
|
||||
codeFont: ttf.Font,
|
||||
|
||||
treeWidget: TreeWidget,
|
||||
treeWidget: TreeView,
|
||||
|
||||
pub fn init() !Ui {
|
||||
try sdl.init();
|
||||
|
@ -20,7 +21,7 @@ const Ui = struct {
|
|||
var uiFont = try ttf.Font.init("/usr/share/fonts/ubuntu/Ubuntu-R.ttf", 16);
|
||||
var codeFont = try ttf.Font.init("/usr/share/fonts/TTF/Cascadia.ttf", 16);
|
||||
|
||||
var treeWidget = TreeWidget.init();
|
||||
var treeWidget = TreeView.init();
|
||||
|
||||
return Ui{
|
||||
.window = window,
|
||||
|
@ -45,44 +46,120 @@ const Ui = struct {
|
|||
sdl.quit();
|
||||
}
|
||||
|
||||
pub fn update(self: Ui) !void {
|
||||
pub fn update(self: *Ui) !void {
|
||||
while (sdl.Event.poll()) |event| {
|
||||
var type_ = event.type_();
|
||||
// std.debug.warn("event: {}\n", .{@tagName(type_)});
|
||||
|
||||
switch (type_) {
|
||||
.Quit => return error.Exiting,
|
||||
.MouseMotion => {
|
||||
var motion = event.mouseMotion().?;
|
||||
self.treeWidget.mouseMotion(motion);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(self: Ui) !void {
|
||||
pub fn render(self: *Ui) !void {
|
||||
try self.renderer.setDrawColor(.{ .r = 30, .g = 30, .b = 30 });
|
||||
try self.renderer.clear();
|
||||
|
||||
try self.treeWidget.render(self);
|
||||
try self.treeWidget.render(self.*);
|
||||
|
||||
self.renderer.present();
|
||||
}
|
||||
};
|
||||
|
||||
const TreeWidget = struct {
|
||||
pub fn init() TreeWidget {
|
||||
return .{};
|
||||
const TreeView = struct {
|
||||
const Entry = struct {
|
||||
name: []const u8,
|
||||
texture: ?sdl.Texture = null,
|
||||
y: i32,
|
||||
width: i32 = 0,
|
||||
height: i32 = 0,
|
||||
|
||||
highlighted: bool = false,
|
||||
|
||||
fn prerender(self: *Entry, ui: Ui) !void {
|
||||
var surface = try ui.uiFont.renderBlended(self.name, .{ .r = 255, .g = 255, .b = 255 });
|
||||
self.texture = try ui.renderer.createTextureFromSurface(surface);
|
||||
self.width = surface.width();
|
||||
self.height = surface.height();
|
||||
|
||||
// We don't need the surface anymore.
|
||||
surface.deinit();
|
||||
}
|
||||
|
||||
pub fn deinit(self: TreeWidget) void {}
|
||||
pub fn render(self: *Entry, ui: Ui) !void {
|
||||
if (self.texture == null) {
|
||||
try self.prerender(ui);
|
||||
}
|
||||
|
||||
pub fn render(self: TreeWidget, ui: Ui) !void {
|
||||
var surface = try ui.uiFont.renderBlended("Hello world", .{ .r = 255, .g = 255, .b = 255 });
|
||||
defer surface.deinit();
|
||||
if (self.highlighted) {
|
||||
try ui.renderer.setDrawColor(.{ .r = 42, .g = 45, .b = 46 });
|
||||
try ui.renderer.fillRect(sdl.Rect{ .x = 0, .y = self.y, .w = 200, .h = 25 });
|
||||
}
|
||||
|
||||
var texture = try ui.renderer.createTextureFromSurface(surface);
|
||||
defer texture.deinit();
|
||||
var y = @divTrunc(25 - self.height, 2);
|
||||
var dst = sdl.Rect{ .x = 10, .y = self.y + y, .w = self.width, .h = self.height };
|
||||
try ui.renderer.copy(self.texture.?, null, dst);
|
||||
}
|
||||
|
||||
var dst = sdl.Rect{ .w = surface.width(), .h = surface.height() };
|
||||
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 + 20;
|
||||
}
|
||||
};
|
||||
|
||||
cursorHand: *sdl.c.SDL_Cursor,
|
||||
count: u64 = 0,
|
||||
|
||||
// Temporary, std.heap.c_allocator was broken, so this for now
|
||||
entries: [256]Entry = undefined,
|
||||
|
||||
pub fn init() TreeView {
|
||||
var cursorHand = sdl.c.SDL_CreateSystemCursor(@intToEnum(sdl.c.SDL_SystemCursor, sdl.c.SDL_SYSTEM_CURSOR_HAND)).?;
|
||||
sdl.c.SDL_SetCursor(cursorHand);
|
||||
var self = TreeView{ .cursorHand = cursorHand };
|
||||
|
||||
self.refresh() catch unreachable;
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: TreeView) void {
|
||||
sdl.c.SDL_FreeCursor(self.cursorHand);
|
||||
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(.{ .r = 38, .g = 38, .b = 38 });
|
||||
try ui.renderer.fillRect(sdl.Rect{ .x = 0, .y = 0, .w = 200, .h = 720 });
|
||||
|
||||
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: u31 = 0;
|
||||
while (try iterator.next()) |file| {
|
||||
self.entries[index] = Entry{ .name = file.name, .y = index * 25 + 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
36
src/sdl.zig
36
src/sdl.zig
|
@ -84,6 +84,13 @@ pub const Renderer = struct {
|
|||
return error.SdlError;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fillRect(self: Renderer, rect: ?Rect) !void {
|
||||
var dst = if (rect) |inner| &inner.c() else null;
|
||||
if (c.SDL_RenderFillRect(self.renderer, dst) != 0) {
|
||||
return error.SdlError;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const Texture = struct {
|
||||
|
@ -238,6 +245,17 @@ pub const EventType = enum(u32) {
|
|||
_,
|
||||
};
|
||||
|
||||
pub const MouseMotionEvent = struct {
|
||||
timestamp: u32,
|
||||
windowId: u32,
|
||||
which: u32,
|
||||
state: u32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
xrel: i32,
|
||||
yrel: i32,
|
||||
};
|
||||
|
||||
pub const Event = struct {
|
||||
event: c.SDL_Event,
|
||||
|
||||
|
@ -252,4 +270,22 @@ pub const Event = struct {
|
|||
pub fn type_(self: Event) EventType {
|
||||
return @intToEnum(EventType, self.event.type);
|
||||
}
|
||||
|
||||
pub fn mouseMotion(self: Event) ?MouseMotionEvent {
|
||||
if (self.type_() != .MouseMotion) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var inner = self.event.motion;
|
||||
return MouseMotionEvent{
|
||||
.timestamp = inner.timestamp,
|
||||
.windowId = inner.windowID,
|
||||
.which = inner.which,
|
||||
.state = inner.state,
|
||||
.x = inner.x,
|
||||
.y = inner.y,
|
||||
.xrel = inner.xrel,
|
||||
.yrel = inner.yrel,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -36,7 +36,7 @@ pub const Font = struct {
|
|||
c.TTF_CloseFont(self.font);
|
||||
}
|
||||
|
||||
pub fn renderBlended(self: Font, text: [:0]const u8, color: sdl.Color) !sdl.Surface {
|
||||
pub fn renderBlended(self: Font, text: []const u8, color: sdl.Color) !sdl.Surface {
|
||||
var cText = @ptrCast([*c]const u8, text);
|
||||
if (c.TTF_RenderUTF8_Blended(self.font, cText, @bitCast(c.SDL_Color, color))) |surface| {
|
||||
return sdl.Surface{ .surface = @ptrCast(*sdl.c.SDL_Surface, surface) };
|
||||
|
|
Loading…
Reference in a new issue