Skip to content

Commit 24485cf

Browse files
mattniteCopper280z
authored andcommitted
Regz Wizard: UI to explore generated code (#596)
1 parent d76885c commit 24485cf

File tree

13 files changed

+318
-8
lines changed

13 files changed

+318
-8
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: tools/regz-wizard
2+
on:
3+
push:
4+
branches: [main]
5+
pull_request:
6+
branches: [main]
7+
8+
jobs:
9+
build:
10+
runs-on: ${{ matrix.os }}
11+
12+
strategy:
13+
matrix:
14+
os: [ubuntu-latest, windows-latest, macos-latest]
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Zig
20+
uses: mlugg/setup-zig@v2
21+
with:
22+
version: 0.14.1
23+
24+
- name: Build
25+
working-directory: tools/regz-wizard
26+
run: zig build
27+
28+
- name: Run Test Suite
29+
working-directory: tools/regz-wizard
30+
run: zig build test

tools/regz-wizard/build.zig

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const std = @import("std");
2+
3+
pub fn build(b: *std.Build) void {
4+
const target = b.standardTargetOptions(.{});
5+
const optimize = b.standardOptimizeOption(.{});
6+
7+
const dvui_dep = b.dependency("dvui", .{
8+
.target = target,
9+
.optimize = optimize,
10+
});
11+
12+
const regz_dep = b.dependency("regz", .{
13+
.target = target,
14+
.optimize = optimize,
15+
});
16+
17+
const regz_mod = regz_dep.module("regz");
18+
const dvui_mod = dvui_dep.module("dvui_sdl3");
19+
20+
const exe_mod = b.createModule(.{
21+
.root_source_file = b.path("src/main.zig"),
22+
.target = target,
23+
.optimize = optimize,
24+
.imports = &.{
25+
.{
26+
.name = "regz",
27+
.module = regz_mod,
28+
},
29+
.{
30+
.name = "dvui",
31+
.module = dvui_mod,
32+
},
33+
},
34+
});
35+
36+
const exe = b.addExecutable(.{
37+
.name = "regz_wizard",
38+
.root_module = exe_mod,
39+
});
40+
b.installArtifact(exe);
41+
42+
const run_cmd = b.addRunArtifact(exe);
43+
run_cmd.step.dependOn(b.getInstallStep());
44+
45+
if (b.args) |args| {
46+
run_cmd.addArgs(args);
47+
}
48+
49+
const run_step = b.step("run", "Run the app");
50+
run_step.dependOn(&run_cmd.step);
51+
52+
const exe_unit_tests = b.addTest(.{
53+
.root_module = exe_mod,
54+
});
55+
56+
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
57+
const test_step = b.step("test", "Run unit tests");
58+
test_step.dependOn(&run_exe_unit_tests.step);
59+
}

tools/regz-wizard/build.zig.zon

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.{
2+
.name = .tools_regzwizard,
3+
.version = "0.0.0",
4+
.fingerprint = 0xe9f2d03f97400569,
5+
.minimum_zig_version = "0.14.1",
6+
.dependencies = .{
7+
.regz = .{ .path = "../regz" },
8+
.dvui = .{
9+
.url = "git+https://github.com/david-vanderson/dvui.git#2fd3c7fcd700ea9c0fd96d217d6ff878ba0d02d7",
10+
.hash = "dvui-0.2.0-AQFJmTOVzgAbOn4QEgiYY-6CISQ25dLcsTsmYBWpSteB",
11+
},
12+
},
13+
.paths = .{
14+
"README.md",
15+
"build.zig",
16+
"build.zig.zon",
17+
"src",
18+
},
19+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Filesystem to store generated files
2+
gpa: Allocator,
3+
map: std.StringArrayHashMapUnmanaged([]const u8) = .{},
4+
5+
const std = @import("std");
6+
const Allocator = std.mem.Allocator;
7+
8+
const regz = @import("regz");
9+
const Directory = regz.Database.Directory;
10+
11+
const VirtualFilesystem = @This();
12+
13+
pub fn init(gpa: Allocator) VirtualFilesystem {
14+
return VirtualFilesystem{
15+
.gpa = gpa,
16+
};
17+
}
18+
19+
pub fn deinit(fs: *VirtualFilesystem) void {
20+
for (fs.map.keys(), fs.map.values()) |path, content| {
21+
fs.gpa.free(path);
22+
fs.gpa.free(content);
23+
}
24+
25+
fs.map.deinit(fs.gpa);
26+
}
27+
28+
pub fn dir(fs: *VirtualFilesystem) Directory {
29+
return Directory{
30+
.ptr = @ptrCast(fs),
31+
.vtable = &.{
32+
.create_file = create_file,
33+
},
34+
};
35+
}
36+
37+
fn create_file(ctx: *anyopaque, path: []const u8, content: []const u8) Directory.CreateFileError!void {
38+
const fs: *VirtualFilesystem = @alignCast(@ptrCast(ctx));
39+
const path_copy = try fs.gpa.dupe(u8, path);
40+
const content_copy = try fs.gpa.dupe(u8, content);
41+
// TODO: clean up collisions
42+
try fs.map.put(fs.gpa, path_copy, content_copy);
43+
}

tools/regz-wizard/src/Virtual_FS.zig

Whitespace-only changes.

tools/regz-wizard/src/main.zig

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
const std = @import("std");
2+
const regz = @import("regz");
3+
const dvui = @import("dvui");
4+
const VirtualFilesystem = @import("VirtualFilesystem.zig");
5+
6+
const window_icon_png = @embedFile("zig-favicon.png");
7+
8+
pub const dvui_app: dvui.App = .{
9+
.config = .{
10+
.options = .{
11+
.size = .{ .w = 800.0, .h = 600.0 },
12+
.min_size = .{ .w = 250.0, .h = 350.0 },
13+
.title = "Regz Wizard",
14+
.icon = window_icon_png,
15+
},
16+
},
17+
.frameFn = frame,
18+
.initFn = init,
19+
.deinitFn = deinit,
20+
};
21+
22+
pub const main = dvui.App.main;
23+
pub const panic = dvui.App.panic;
24+
pub const std_options: std.Options = .{
25+
.logFn = dvui.App.logFn,
26+
};
27+
28+
var db: ?*regz.Database = null;
29+
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
30+
const gpa = debug_allocator.allocator();
31+
var vfs: VirtualFilesystem = undefined;
32+
var current_gen_file: usize = 0;
33+
34+
pub fn init(win: *dvui.Window) void {
35+
_ = win;
36+
vfs = .init(gpa);
37+
}
38+
39+
// Run as app is shutting down before dvui.Window.deinit()
40+
pub fn deinit() void {
41+
if (db) |d| d.destroy();
42+
vfs.deinit();
43+
_ = debug_allocator.deinit();
44+
}
45+
46+
// TODO: add mechanism to open a file, this creates a brand new db instance.
47+
// - Some sort of menu bar
48+
// - File -> Drop down
49+
50+
// Run each frame to do normal UI
51+
pub fn frame() !dvui.App.Result {
52+
var scaler = try dvui.scale(@src(), .{ .scale = &dvui.currentWindow().content_scale, .pinch_zoom = .global }, .{ .rect = .cast(dvui.windowRect()) });
53+
scaler.deinit();
54+
55+
var scroll = try dvui.scrollArea(@src(), .{}, .{ .expand = .both, .color_fill = .fill_window });
56+
defer scroll.deinit();
57+
58+
var vbox = try dvui.box(@src(), .vertical, .{ .expand = .both, .margin = .{ .x = 4 } });
59+
defer vbox.deinit();
60+
61+
{
62+
var m = try dvui.menu(@src(), .horizontal, .{});
63+
defer m.deinit();
64+
65+
if (try dvui.menuItemLabel(@src(), "File", .{ .submenu = true }, .{ .expand = .horizontal })) |r| {
66+
var fw = try dvui.floatingMenu(@src(), .{ .from = r }, .{});
67+
defer fw.deinit();
68+
69+
if (try dvui.menuItemLabel(@src(), "Open", .{}, .{}) != null) blk: {
70+
defer fw.close();
71+
const filename = try dvui.dialogNativeFileOpen(dvui.currentWindow().arena(), .{ .title = "dvui native file open", .filters = &.{ "*.svd", "*.atdf" }, .filter_description = "images" });
72+
if (filename) |f| {
73+
const ext = std.fs.path.extension(f);
74+
const format: regz.Database.Format = if (std.mem.eql(u8, ext, ".svd"))
75+
.svd
76+
else if (std.mem.eql(u8, ext, ".atdf"))
77+
.atdf
78+
else
79+
break :blk;
80+
81+
if (db) |d| d.destroy();
82+
83+
vfs.deinit();
84+
vfs = .init(gpa);
85+
86+
db = try regz.Database.create_from_path(gpa, format, f);
87+
try db.?.to_zig(vfs.dir(), .{ .for_microzig = true });
88+
}
89+
}
90+
91+
if (try dvui.menuItemLabel(@src(), "Exit", .{}, .{})) |_| {
92+
return .close;
93+
}
94+
}
95+
96+
if (db != null) if (try dvui.menuItemLabel(@src(), "Edit", .{ .submenu = true }, .{ .expand = .horizontal })) |r| {
97+
var fw = try dvui.floatingMenu(@src(), .{ .from = r }, .{});
98+
defer fw.deinit();
99+
100+
if (try dvui.menuItemLabel(@src(), "Apply Patches", .{}, .{})) |_| {
101+
defer fw.close();
102+
103+
const filename = try dvui.dialogNativeFileOpen(dvui.currentWindow().arena(), .{ .title = "dvui native file open", .filters = &.{"*.json"}, .filter_description = "images" });
104+
_ = filename;
105+
}
106+
};
107+
108+
if (try dvui.menuItemLabel(@src(), "View", .{ .submenu = true }, .{ .expand = .horizontal })) |r| {
109+
var fw = try dvui.floatingMenu(@src(), .{ .from = r }, .{});
110+
defer fw.deinit();
111+
112+
if (try dvui.menuItemLabel(@src(), "Demo Window", .{}, .{})) |_| {
113+
dvui.Examples.show_demo_window = true;
114+
fw.close();
115+
}
116+
}
117+
}
118+
119+
// look at demo() for examples of dvui widgets, shows in a floating window
120+
try dvui.Examples.demo();
121+
122+
if (db != null) {
123+
const entries = vfs.map.keys();
124+
_ = try dvui.dropdown(@src(), entries, &current_gen_file, .{});
125+
126+
const current = entries[current_gen_file];
127+
128+
var font = dvui.themeGet().font_body;
129+
font.name = "VeraMono";
130+
131+
var tl = dvui.TextLayoutWidget.init(@src(), .{}, .{ .expand = .horizontal, .font = font });
132+
try tl.install(.{});
133+
defer tl.deinit();
134+
135+
try tl.addText(vfs.map.get(current).?, .{
136+
.font = font,
137+
});
138+
}
139+
140+
return .ok;
141+
}
337 Bytes
Loading

tools/regz/src/Database.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const gen = @import("gen.zig");
1616
const Patch = @import("patch.zig").Patch;
1717
const SQL_Options = @import("SQL_Options.zig");
1818
const Arch = @import("arch.zig").Arch;
19-
const Directory = @import("Directory.zig");
19+
pub const Directory = @import("Directory.zig");
2020

2121
const log = std.log.scoped(.db);
2222
const file_size_max = 100 * 1024 * 1024;

tools/regz/src/Directory.zig

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ pub const VTable = struct {
88
pub const CreateFileError = error{
99
TODO,
1010
System,
11-
};
12-
13-
pub const CreateDirectoryError = error{
14-
TODO,
15-
System,
11+
OutOfMemory,
1612
};
1713

1814
pub inline fn create_file(d: Directory, filename: []const u8, content: []const u8) CreateFileError!void {

website/assets/style.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ a:hover {
1111
text-decoration: underline;
1212
}
1313

14+
image {
15+
max-width: 100%;
16+
}
17+
1418
.upper-header {
1519
display: flex;
1620
flex-direction: row;

0 commit comments

Comments
 (0)