-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathcontext_menu.zig
More file actions
147 lines (130 loc) · 5.33 KB
/
Copy pathcontext_menu.zig
File metadata and controls
147 lines (130 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! ZigZag Context Menu Example
//! Demonstrates a popup context menu triggered by keyboard.
const std = @import("std");
const Writer = std.Io.Writer;
const zz = @import("zigzag");
const Action = enum { cut, copy, paste, delete, select_all, properties };
const CM = zz.ContextMenu(Action);
const Model = struct {
menu: CM,
status: []const u8,
items: [6][]const u8,
selected: usize,
pub const Msg = union(enum) {
key: zz.KeyEvent,
};
pub fn init(self: *Model, _: *zz.Context) zz.Cmd(Msg) {
self.menu = CM.init();
self.menu.addItem("Cut", "Ctrl+X", .cut);
self.menu.addItem("Copy", "Ctrl+C", .copy);
self.menu.addItem("Paste", "Ctrl+V", .paste);
self.menu.addSeparator();
self.menu.addItem("Delete", "Del", .delete);
self.menu.addItem("Select All", "Ctrl+A", .select_all);
self.menu.addSeparator();
self.menu.addDisabledItem("Properties", .properties);
self.status = "Press Space or Enter to open context menu";
self.items = .{ "Document.txt", "Image.png", "Notes.md", "Config.json", "Script.sh", "Data.csv" };
self.selected = 0;
return .none;
}
pub fn update(self: *Model, msg: Msg, _: *zz.Context) zz.Cmd(Msg) {
switch (msg) {
.key => |k| {
// Menu gets priority
if (self.menu.handleKey(k)) {
if (self.menu.getSelectedAction()) |act| {
self.status = switch (act) {
.cut => "Cut selected item",
.copy => "Copied to clipboard",
.paste => "Pasted from clipboard",
.delete => "Item deleted",
.select_all => "All items selected",
.properties => "Properties (disabled)",
};
}
return .none;
}
switch (k.key) {
.char => |c| switch (c) {
'q' => return .quit,
else => {},
},
.up => {
if (self.selected > 0) self.selected -= 1;
},
.down => {
if (self.selected < self.items.len - 1) self.selected += 1;
},
.space, .enter => {
// Open context menu at selected item position
self.menu.show(4, self.selected + 4);
},
.escape => {
if (self.menu.isVisible()) {
self.menu.hide();
} else {
return .quit;
}
},
else => {},
}
},
}
return .none;
}
pub fn view(self: *const Model, ctx: *const zz.Context) ![]const u8 {
var title_style = zz.Style{};
title_style = title_style.bold(true);
title_style = title_style.fg(zz.Color.magenta);
title_style = title_style.inline_style(true);
const title = try title_style.render(ctx.allocator, "Context Menu Example");
// File list
var list_buf: Writer.Allocating = .init(ctx.allocator);
const lw = &list_buf.writer;
for (self.items, 0..) |item, i| {
if (i > 0) try lw.writeByte('\n');
if (i == self.selected) {
var sel_style = zz.Style{};
sel_style = sel_style.bold(true);
sel_style = sel_style.fg(zz.Color.cyan);
sel_style = sel_style.inline_style(true);
const line = try std.fmt.allocPrint(ctx.allocator, " > {s}", .{item});
const styled = try sel_style.render(ctx.allocator, line);
try lw.writeAll(styled);
} else {
const line = try std.fmt.allocPrint(ctx.allocator, " {s}", .{item});
try lw.writeAll(line);
}
}
const file_list = try list_buf.toOwnedSlice();
// Status
var status_style = zz.Style{};
status_style = status_style.fg(zz.Color.green);
status_style = status_style.inline_style(true);
const styled_status = try status_style.render(ctx.allocator, self.status);
// Context menu overlay
const menu_view = try self.menu.view(ctx.allocator);
var help_style = zz.Style{};
help_style = help_style.fg(zz.Color.gray(12));
help_style = help_style.inline_style(true);
const help = try help_style.render(ctx.allocator, "Up/Down: navigate | Space/Enter: context menu | Esc: close | q: quit");
if (self.menu.isVisible()) {
return std.fmt.allocPrint(
ctx.allocator,
"{s}\n\n{s}\n\n{s}\n\n{s}\n\n{s}",
.{ title, file_list, menu_view, styled_status, help },
);
}
return std.fmt.allocPrint(
ctx.allocator,
"{s}\n\n{s}\n\n{s}\n\n{s}",
.{ title, file_list, styled_status, help },
);
}
};
pub fn main(init: std.process.Init) !void {
var program = zz.Program(Model).init(init.gpa, init.io, init.environ_map);
defer program.deinit();
try program.run();
}