refactor: pass relative click position to button click handlers
This a big refactor just to clean-up type definitions used by Button and Menu. The goals is to pass the click position as a cursor object.
This commit is contained in:
parent
35ccf7f1df
commit
ce87dcfa2b
21 changed files with 148 additions and 118 deletions
|
@ -4,6 +4,7 @@ const tp = @import("thespian");
|
|||
const EventHandler = @import("EventHandler");
|
||||
const Plane = @import("renderer").Plane;
|
||||
const input = @import("input");
|
||||
pub const Cursor = @import("Buffer").Cursor;
|
||||
|
||||
const Widget = @import("Widget.zig");
|
||||
const tui = @import("tui.zig");
|
||||
|
@ -14,20 +15,23 @@ pub fn Options(context: type) type {
|
|||
pos: Widget.Box = .{ .y = 0, .x = 0, .w = 8, .h = 1 },
|
||||
ctx: Context,
|
||||
|
||||
on_click: *const fn (ctx: *context, button: *State(Context)) void = do_nothing,
|
||||
on_click2: *const fn (ctx: *context, button: *State(Context)) void = do_nothing,
|
||||
on_click3: *const fn (ctx: *context, button: *State(Context)) void = do_nothing,
|
||||
on_click4: *const fn (ctx: *context, button: *State(Context)) void = do_nothing,
|
||||
on_click5: *const fn (ctx: *context, button: *State(Context)) void = do_nothing,
|
||||
on_render: *const fn (ctx: *context, button: *State(Context), theme: *const Widget.Theme) bool = on_render_default,
|
||||
on_layout: *const fn (ctx: *context, button: *State(Context)) Widget.Layout = on_layout_default,
|
||||
on_receive: *const fn (ctx: *context, button: *State(Context), from: tp.pid_ref, m: tp.message) error{Exit}!bool = on_receive_default,
|
||||
on_click: ClickHandler = do_nothing,
|
||||
on_click2: ClickHandler = do_nothing,
|
||||
on_click3: ClickHandler = do_nothing,
|
||||
on_click4: ClickHandler = do_nothing,
|
||||
on_click5: ClickHandler = do_nothing,
|
||||
on_render: *const fn (ctx: *context, button: *ButtonType, theme: *const Widget.Theme) bool = on_render_default,
|
||||
on_layout: *const fn (ctx: *context, button: *ButtonType) Widget.Layout = on_layout_default,
|
||||
on_receive: *const fn (ctx: *context, button: *ButtonType, from: tp.pid_ref, m: tp.message) error{Exit}!bool = on_receive_default,
|
||||
on_event: ?EventHandler = null,
|
||||
|
||||
pub const ButtonType = State(Context);
|
||||
pub const Context = context;
|
||||
pub fn do_nothing(_: *context, _: *State(Context)) void {}
|
||||
pub const ClickHandler = *const fn (ctx: *context, button: *ButtonType, pos: Cursor) void;
|
||||
|
||||
pub fn on_render_default(_: *context, self: *State(Context), theme: *const Widget.Theme) bool {
|
||||
pub fn do_nothing(_: *context, _: *ButtonType, _: Cursor) void {}
|
||||
|
||||
pub fn on_render_default(_: *context, self: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
self.plane.set_base_style(if (self.active) theme.scrollbar_active else if (self.hover) theme.scrollbar_hover else theme.scrollbar);
|
||||
self.plane.erase();
|
||||
self.plane.home();
|
||||
|
@ -35,18 +39,18 @@ pub fn Options(context: type) type {
|
|||
return false;
|
||||
}
|
||||
|
||||
pub fn on_layout_default(_: *context, self: *State(Context)) Widget.Layout {
|
||||
pub fn on_layout_default(_: *context, self: *ButtonType) Widget.Layout {
|
||||
return .{ .static = self.opts.label.len + 2 };
|
||||
}
|
||||
|
||||
pub fn on_receive_default(_: *context, _: *State(Context), _: tp.pid_ref, _: tp.message) error{Exit}!bool {
|
||||
pub fn on_receive_default(_: *context, _: *ButtonType, _: tp.pid_ref, _: tp.message) error{Exit}!bool {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: Options(ctx_type)) error{OutOfMemory}!*State(ctx_type) {
|
||||
const Self = State(ctx_type);
|
||||
pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts: Options(ctx_type)) error{OutOfMemory}!*Options(ctx_type).ButtonType {
|
||||
const Self = Options(ctx_type).ButtonType;
|
||||
const self = try allocator.create(Self);
|
||||
errdefer allocator.destroy(self);
|
||||
var n = try Plane.init(&opts.pos.opts(@typeName(Self)), parent);
|
||||
|
@ -67,7 +71,7 @@ pub fn create_widget(ctx_type: type, allocator: std.mem.Allocator, parent: Plane
|
|||
return Widget.to(try create(ctx_type, allocator, parent, opts));
|
||||
}
|
||||
|
||||
pub fn State(ctx_type: type) type {
|
||||
fn State(ctx_type: type) type {
|
||||
return struct {
|
||||
allocator: std.mem.Allocator,
|
||||
parent: Plane,
|
||||
|
@ -110,7 +114,9 @@ pub fn State(ctx_type: type) type {
|
|||
|
||||
pub fn receive(self: *Self, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
var btn: input.MouseType = 0;
|
||||
if (try m.match(.{ "B", input.event.press, tp.extract(&btn), tp.more })) {
|
||||
var x: c_int = undefined;
|
||||
var y: c_int = undefined;
|
||||
if (try m.match(.{ "B", input.event.press, tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.any, tp.any })) {
|
||||
const btn_enum: input.Mouse = @enumFromInt(btn);
|
||||
switch (btn_enum) {
|
||||
input.mouse.BUTTON1 => {
|
||||
|
@ -118,14 +124,14 @@ pub fn State(ctx_type: type) type {
|
|||
tui.need_render();
|
||||
},
|
||||
input.mouse.BUTTON4, input.mouse.BUTTON5 => {
|
||||
self.call_click_handler(btn_enum);
|
||||
self.call_click_handler(btn_enum, self.to_rel_cursor(x, y));
|
||||
return true;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return true;
|
||||
} else if (try m.match(.{ "B", input.event.release, tp.extract(&btn), tp.more })) {
|
||||
self.call_click_handler(@enumFromInt(btn));
|
||||
} else if (try m.match(.{ "B", input.event.release, tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.any, tp.any })) {
|
||||
self.call_click_handler(@enumFromInt(btn), self.to_rel_cursor(x, y));
|
||||
tui.need_render();
|
||||
return true;
|
||||
} else if (try m.match(.{ "D", input.event.press, tp.extract(&btn), tp.more })) {
|
||||
|
@ -134,12 +140,12 @@ pub fn State(ctx_type: type) type {
|
|||
h.send(from, m) catch {};
|
||||
}
|
||||
return true;
|
||||
} else if (try m.match(.{ "D", input.event.release, tp.extract(&btn), tp.more })) {
|
||||
} else if (try m.match(.{ "D", input.event.release, tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.any, tp.any })) {
|
||||
if (self.opts.on_event) |h| {
|
||||
self.active = false;
|
||||
h.send(from, m) catch {};
|
||||
}
|
||||
self.call_click_handler(@enumFromInt(btn));
|
||||
self.call_click_handler(@enumFromInt(btn), self.to_rel_cursor(x, y));
|
||||
tui.need_render();
|
||||
return true;
|
||||
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
|
||||
|
@ -150,18 +156,23 @@ pub fn State(ctx_type: type) type {
|
|||
return self.opts.on_receive(&self.opts.ctx, self, from, m);
|
||||
}
|
||||
|
||||
fn call_click_handler(self: *Self, btn: input.Mouse) void {
|
||||
fn to_rel_cursor(self: *const Self, abs_x: c_int, abs_y: c_int) Cursor {
|
||||
const rel_y, const rel_x = self.plane.abs_yx_to_rel(abs_y, abs_x);
|
||||
return .{ .row = @intCast(rel_y), .col = @intCast(rel_x) };
|
||||
}
|
||||
|
||||
fn call_click_handler(self: *Self, btn: input.Mouse, pos: Cursor) void {
|
||||
if (btn == input.mouse.BUTTON1) {
|
||||
if (!self.active) return;
|
||||
self.active = false;
|
||||
}
|
||||
if (!self.hover) return;
|
||||
switch (btn) {
|
||||
input.mouse.BUTTON1 => self.opts.on_click(&self.opts.ctx, self),
|
||||
input.mouse.BUTTON2 => self.opts.on_click2(&self.opts.ctx, self),
|
||||
input.mouse.BUTTON3 => self.opts.on_click3(&self.opts.ctx, self),
|
||||
input.mouse.BUTTON4 => self.opts.on_click4(&self.opts.ctx, self),
|
||||
input.mouse.BUTTON5 => self.opts.on_click5(&self.opts.ctx, self),
|
||||
input.mouse.BUTTON1 => self.opts.on_click(&self.opts.ctx, self, pos),
|
||||
input.mouse.BUTTON2 => self.opts.on_click2(&self.opts.ctx, self, pos),
|
||||
input.mouse.BUTTON3 => self.opts.on_click3(&self.opts.ctx, self, pos),
|
||||
input.mouse.BUTTON4 => self.opts.on_click4(&self.opts.ctx, self, pos),
|
||||
input.mouse.BUTTON5 => self.opts.on_click5(&self.opts.ctx, self, pos),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,20 +16,24 @@ pub fn Options(context: type) type {
|
|||
ctx: Context,
|
||||
style: Widget.Type,
|
||||
|
||||
on_click: *const fn (ctx: context, button: *Button.State(*State(Context))) void = do_nothing,
|
||||
on_click4: *const fn (menu: **State(Context), button: *Button.State(*State(Context))) void = do_nothing_click,
|
||||
on_click5: *const fn (menu: **State(Context), button: *Button.State(*State(Context))) void = do_nothing_click,
|
||||
on_render: *const fn (ctx: context, button: *Button.State(*State(Context)), theme: *const Widget.Theme, selected: bool) bool = on_render_default,
|
||||
on_layout: *const fn (ctx: context, button: *Button.State(*State(Context))) Widget.Layout = on_layout_default,
|
||||
prepare_resize: *const fn (ctx: context, menu: *State(Context), box: Widget.Box) Widget.Box = prepare_resize_default,
|
||||
after_resize: *const fn (ctx: context, menu: *State(Context), box: Widget.Box) void = after_resize_default,
|
||||
on_click: ClickHandler = do_nothing,
|
||||
on_click4: ButtonClickHandler = do_nothing_click,
|
||||
on_click5: ButtonClickHandler = do_nothing_click,
|
||||
on_render: *const fn (ctx: context, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool = on_render_default,
|
||||
on_layout: *const fn (ctx: context, button: *ButtonType) Widget.Layout = on_layout_default,
|
||||
prepare_resize: *const fn (ctx: context, menu: *MenuType, box: Widget.Box) Widget.Box = prepare_resize_default,
|
||||
after_resize: *const fn (ctx: context, menu: *MenuType, box: Widget.Box) void = after_resize_default,
|
||||
on_scroll: ?EventHandler = null,
|
||||
|
||||
pub const Context = context;
|
||||
pub fn do_nothing(_: context, _: *Button.State(*State(Context))) void {}
|
||||
pub fn do_nothing_click(_: **State(Context), _: *Button.State(*State(Context))) void {}
|
||||
pub const MenuType = State(Context);
|
||||
pub const ButtonType = Button.Options(*MenuType).ButtonType;
|
||||
pub const ButtonClickHandler = Button.Options(*MenuType).ClickHandler;
|
||||
pub const ClickHandler = *const fn (ctx: context, button: *ButtonType) void;
|
||||
pub fn do_nothing(_: context, _: *ButtonType) void {}
|
||||
pub fn do_nothing_click(_: **MenuType, _: *ButtonType, _: Button.Cursor) void {}
|
||||
|
||||
pub fn on_render_default(_: context, button: *Button.State(*State(Context)), theme: *const Widget.Theme, selected: bool) bool {
|
||||
pub fn on_render_default(_: context, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
const style_base = theme.editor;
|
||||
const style_label = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else style_base;
|
||||
button.plane.set_base_style(style_base);
|
||||
|
@ -44,17 +48,17 @@ pub fn Options(context: type) type {
|
|||
return false;
|
||||
}
|
||||
|
||||
pub fn on_layout_default(_: context, _: *Button.State(*State(Context))) Widget.Layout {
|
||||
pub fn on_layout_default(_: context, _: *ButtonType) Widget.Layout {
|
||||
return .{ .static = 1 };
|
||||
}
|
||||
|
||||
pub fn prepare_resize_default(_: context, state: *State(Context), box_: Widget.Box) Widget.Box {
|
||||
pub fn prepare_resize_default(_: context, state: *MenuType, box_: Widget.Box) Widget.Box {
|
||||
var box = box_;
|
||||
box.h = if (box_.h == 0) state.menu.widgets.items.len else box_.h;
|
||||
return box;
|
||||
}
|
||||
|
||||
pub fn after_resize_default(_: context, _: *State(Context), _: Widget.Box) void {}
|
||||
pub fn after_resize_default(_: context, _: *MenuType, _: Widget.Box) void {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -92,15 +96,15 @@ pub fn State(ctx_type: type) type {
|
|||
container_widget: Widget,
|
||||
frame_widget: ?Widget,
|
||||
scrollbar: ?*scrollbar_v,
|
||||
opts: options_type,
|
||||
opts: OptionsType,
|
||||
selected: ?usize = null,
|
||||
render_idx: usize = 0,
|
||||
selected_active: bool = false,
|
||||
header_count: usize = 0,
|
||||
|
||||
const Self = @This();
|
||||
const options_type = Options(ctx_type);
|
||||
const button_type = Button.State(*Self);
|
||||
pub const OptionsType = Options(ctx_type);
|
||||
pub const ButtonType = Button.Options(*Self).ButtonType;
|
||||
|
||||
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||
self.menu.deinit(allocator);
|
||||
|
@ -125,7 +129,7 @@ pub fn State(ctx_type: type) type {
|
|||
}));
|
||||
}
|
||||
|
||||
pub fn add_item_with_handler(self: *Self, label: []const u8, on_click: *const fn (_: **Self, _: *Button.State(*Self)) void) !void {
|
||||
pub fn add_item_with_handler(self: *Self, label: []const u8, on_click: OptionsType.ButtonClickHandler) !void {
|
||||
try self.menu.add(try Button.create_widget(*Self, self.allocator, self.menu.parent, .{
|
||||
.ctx = self,
|
||||
.on_layout = on_layout,
|
||||
|
@ -163,11 +167,11 @@ pub fn State(ctx_type: type) type {
|
|||
self.opts.after_resize(self.*.opts.ctx, self, box);
|
||||
}
|
||||
|
||||
pub fn on_layout(self: **Self, button: *Button.State(*Self)) Widget.Layout {
|
||||
pub fn on_layout(self: **Self, button: *ButtonType) Widget.Layout {
|
||||
return self.*.opts.on_layout(self.*.opts.ctx, button);
|
||||
}
|
||||
|
||||
pub fn on_render(self: **Self, button: *Button.State(*Self), theme: *const Widget.Theme) bool {
|
||||
pub fn on_render(self: **Self, button: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
defer self.*.render_idx += 1;
|
||||
std.debug.assert(self.*.render_idx < self.*.menu.widgets.items.len);
|
||||
return self.*.opts.on_render(self.*.opts.ctx, button, theme, self.*.render_idx == self.*.selected);
|
||||
|
@ -217,15 +221,15 @@ pub fn State(ctx_type: type) type {
|
|||
|
||||
pub fn activate_selected(self: *Self) void {
|
||||
const button = self.get_selected() orelse return;
|
||||
button.opts.on_click(&button.opts.ctx, button);
|
||||
button.opts.on_click(&button.opts.ctx, button, .{});
|
||||
}
|
||||
|
||||
pub fn get_selected(self: *Self) ?*button_type {
|
||||
pub fn get_selected(self: *Self) ?*ButtonType {
|
||||
const selected = self.selected orelse return null;
|
||||
self.selected_active = true;
|
||||
const pos = selected + self.header_count;
|
||||
return if (pos < self.menu.widgets.items.len)
|
||||
self.menu.widgets.items[pos].widget.dynamic_cast(button_type)
|
||||
self.menu.widgets.items[pos].widget.dynamic_cast(ButtonType)
|
||||
else
|
||||
null;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ const Commands = command.Collection(cmds);
|
|||
|
||||
allocator: std.mem.Allocator,
|
||||
plane: Plane,
|
||||
menu: *Menu.State(*Self),
|
||||
menu: *MenuType,
|
||||
logger: log.Logger,
|
||||
commands: Commands = undefined,
|
||||
|
||||
|
@ -35,6 +35,8 @@ entries: std.ArrayList(Entry) = undefined,
|
|||
selected: ?usize = null,
|
||||
box: Widget.Box = .{},
|
||||
|
||||
const MenuType = Menu.Options(*Self).MenuType;
|
||||
const ButtonType = MenuType.ButtonType;
|
||||
const path_column_ratio = 4;
|
||||
const widget_type: Widget.Type = .panel;
|
||||
|
||||
|
@ -136,7 +138,7 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
|
|||
return self.menu.container_widget.render(theme);
|
||||
}
|
||||
|
||||
fn handle_render_menu(self: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
|
||||
fn handle_render_menu(self: *Self, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
const style_base = theme.panel;
|
||||
const style_label = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.panel;
|
||||
const style_hint: Widget.Theme.Style = .{ .fg = theme.editor_hint.fg, .fs = theme.editor_hint.fs, .bg = style_label.bg };
|
||||
|
@ -195,7 +197,7 @@ fn update_scrollbar(self: *Self) void {
|
|||
scrollbar.set(@intCast(self.entries.items.len), @intCast(self.view_rows), @intCast(self.view_pos));
|
||||
}
|
||||
|
||||
fn mouse_click_button4(menu: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
|
||||
fn mouse_click_button4(menu: **MenuType, _: *ButtonType, _: Button.Cursor) void {
|
||||
const self = &menu.*.opts.ctx.*;
|
||||
self.selected = if (self.menu.selected) |sel_| sel_ + self.view_pos else self.selected;
|
||||
if (self.view_pos < Menu.scroll_lines) {
|
||||
|
@ -207,7 +209,7 @@ fn mouse_click_button4(menu: **Menu.State(*Self), _: *Button.State(*Menu.State(*
|
|||
self.update_scrollbar();
|
||||
}
|
||||
|
||||
fn mouse_click_button5(menu: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
|
||||
fn mouse_click_button5(menu: **MenuType, _: *ButtonType, _: Button.Cursor) void {
|
||||
const self = &menu.*.opts.ctx.*;
|
||||
self.selected = if (self.menu.selected) |sel_| sel_ + self.view_pos else self.selected;
|
||||
if (self.view_pos < @max(self.entries.items.len, self.view_rows) - self.view_rows)
|
||||
|
@ -226,7 +228,7 @@ fn update_selected(self: *Self) void {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_menu_action(menu: **Menu.State(*Self), button: *Button.State(*Menu.State(*Self))) void {
|
||||
fn handle_menu_action(menu: **MenuType, button: *ButtonType, _: Button.Cursor) void {
|
||||
const self = menu.*.opts.ctx;
|
||||
var idx: usize = undefined;
|
||||
var iter = button.opts.label;
|
||||
|
|
|
@ -82,6 +82,8 @@ home_style_bufs: [][]const u8,
|
|||
const Self = @This();
|
||||
|
||||
const widget_type: Widget.Type = .home;
|
||||
const MenuType = Menu.Options(*Self).MenuType;
|
||||
const ButtonType = MenuType.ButtonType;
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator, parent: Widget) !Widget {
|
||||
const logger = log.logger("home");
|
||||
|
@ -188,7 +190,7 @@ pub fn receive(_: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
return false;
|
||||
}
|
||||
|
||||
fn menu_on_render(self: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
|
||||
fn menu_on_render(self: *Self, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
var description: []const u8 = undefined;
|
||||
var hint: []const u8 = undefined;
|
||||
var command_name: []const u8 = undefined;
|
||||
|
@ -257,7 +259,7 @@ fn menu_on_render(self: *Self, button: *Button.State(*Menu.State(*Self)), theme:
|
|||
return false;
|
||||
}
|
||||
|
||||
fn menu_action(_: **Menu.State(*Self), button: *Button.State(*Menu.State(*Self))) void {
|
||||
fn menu_action(_: **Menu.State(*Self), button: *ButtonType, _: Button.Cursor) void {
|
||||
var description: []const u8 = undefined;
|
||||
var hint: []const u8 = undefined;
|
||||
var command_name: []const u8 = undefined;
|
||||
|
|
|
@ -54,11 +54,11 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
pub fn on_render_menu(_: *Type, button: *Type.ButtonState, theme: *const Widget.Theme, selected: bool) bool {
|
||||
pub fn on_render_menu(_: *Type, button: *Type.ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
return tui.render_file_item_cbor(&button.plane, button.opts.label, button.active, selected, button.hover, theme);
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var file_path: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &file_path) catch false)) return;
|
||||
|
@ -66,7 +66,7 @@ fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
|||
tp.self_pid().send(.{ "cmd", "navigate", .{ .file = file_path } }) catch |e| menu.*.opts.ctx.logger.err(module_name, e);
|
||||
}
|
||||
|
||||
pub fn delete_item(menu: *Type.MenuState, button: *Type.ButtonState) bool {
|
||||
pub fn delete_item(menu: *Type.MenuType, button: *Type.ButtonType) bool {
|
||||
var file_path: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &file_path) catch false)) return false;
|
||||
|
|
|
@ -52,7 +52,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var unused: []const u8 = undefined;
|
||||
var command_id: command.ID = undefined;
|
||||
var iter = button.opts.label;
|
||||
|
|
|
@ -83,7 +83,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
pub fn on_render_menu(_: *Type, button: *Type.ButtonState, theme: *const Widget.Theme, selected: bool) bool {
|
||||
pub fn on_render_menu(_: *Type, button: *Type.ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
var item_cbor: []const u8 = undefined;
|
||||
var matches_cbor: []const u8 = undefined;
|
||||
|
||||
|
@ -146,13 +146,13 @@ fn get_replace_selection(replace: Buffer.Selection) ?Buffer.Selection {
|
|||
replace;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
const label_, _, _, _, _ = get_values(button.opts.label);
|
||||
tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err(module_name, e);
|
||||
tp.self_pid().send(.{ "cmd", "insert_chars", .{label_} }) catch |e| menu.*.opts.ctx.logger.err(module_name, e);
|
||||
}
|
||||
|
||||
pub fn updated(palette: *Type, button_: ?*Type.ButtonState) !void {
|
||||
pub fn updated(palette: *Type, button_: ?*Type.ButtonType) !void {
|
||||
const button = button_ orelse return cancel(palette);
|
||||
_, _, _, const replace, _ = get_values(button.opts.label);
|
||||
const editor = tui.get_active_editor() orelse return error.NotFound;
|
||||
|
|
|
@ -71,7 +71,7 @@ pub fn Variant(comptime command: []const u8, comptime label_: []const u8, allow_
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
pub fn on_render_menu(_: *Type, button: *Type.ButtonState, theme: *const Widget.Theme, selected: bool) bool {
|
||||
pub fn on_render_menu(_: *Type, button: *Type.ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
const style_base = theme.editor_widget;
|
||||
const style_label = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.editor_widget;
|
||||
const style_hint = if (tui.find_scope_style(theme, "entity.name")) |sty| sty.style else style_label;
|
||||
|
@ -116,7 +116,7 @@ pub fn Variant(comptime command: []const u8, comptime label_: []const u8, allow_
|
|||
return false;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var description_: []const u8 = undefined;
|
||||
var icon_: []const u8 = undefined;
|
||||
var color: u24 = undefined;
|
||||
|
|
|
@ -56,7 +56,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var label_: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &label_) catch false)) return;
|
||||
|
@ -64,7 +64,7 @@ fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
|||
tp.self_pid().send(.{ "cmd", "set_fontface", .{label_} }) catch |e| menu.*.opts.ctx.logger.err("fontface_palette", e);
|
||||
}
|
||||
|
||||
pub fn updated(palette: *Type, button_: ?*Type.ButtonState) !void {
|
||||
pub fn updated(palette: *Type, button_: ?*Type.ButtonType) !void {
|
||||
const button = button_ orelse return cancel(palette);
|
||||
var label_: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
|
|
|
@ -69,7 +69,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var unused: []const u8 = undefined;
|
||||
var command_id: command.ID = undefined;
|
||||
var iter = button.opts.label;
|
||||
|
|
|
@ -28,7 +28,7 @@ const widget_type: Widget.Type = .palette;
|
|||
allocator: std.mem.Allocator,
|
||||
f: usize = 0,
|
||||
modal: *ModalBackground.State(*Self),
|
||||
menu: *Menu.State(*Self),
|
||||
menu: *MenuType,
|
||||
inputbox: *InputBox.State(*Self),
|
||||
logger: log.Logger,
|
||||
query_pending: bool = false,
|
||||
|
@ -39,6 +39,8 @@ commands: Commands = undefined,
|
|||
buffer_manager: ?*BufferManager,
|
||||
|
||||
const inputbox_label = "Search files by name";
|
||||
const MenuType = Menu.Options(*Self).MenuType;
|
||||
const ButtonType = MenuType.ButtonType;
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator) !tui.Mode {
|
||||
const mv = tui.mainview() orelse return error.NotFound;
|
||||
|
@ -104,11 +106,11 @@ inline fn max_menu_width() usize {
|
|||
return @max(15, width - (width / 5));
|
||||
}
|
||||
|
||||
fn on_render_menu(_: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
|
||||
fn on_render_menu(_: *Self, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
return tui.render_file_item_cbor(&button.plane, button.opts.label, button.active, selected, button.hover, theme);
|
||||
}
|
||||
|
||||
fn prepare_resize_menu(self: *Self, _: *Menu.State(*Self), _: Widget.Box) Widget.Box {
|
||||
fn prepare_resize_menu(self: *Self, _: *MenuType, _: Widget.Box) Widget.Box {
|
||||
return self.prepare_resize();
|
||||
}
|
||||
|
||||
|
@ -123,7 +125,7 @@ fn do_resize(self: *Self) void {
|
|||
self.menu.resize(self.prepare_resize());
|
||||
}
|
||||
|
||||
fn menu_action_open_file(menu: **Menu.State(*Self), button: *Button.State(*Menu.State(*Self))) void {
|
||||
fn menu_action_open_file(menu: **MenuType, button: *ButtonType, _: Button.Cursor) void {
|
||||
var file_path: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &file_path) catch false)) return;
|
||||
|
|
|
@ -63,7 +63,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var name_: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &name_) catch false)) return;
|
||||
|
@ -71,7 +71,7 @@ fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
|||
tp.self_pid().send(.{ "cmd", "change_project", .{name_} }) catch |e| menu.*.opts.ctx.logger.err("open_recent_project", e);
|
||||
}
|
||||
|
||||
pub fn delete_item(menu: *Type.MenuState, button: *Type.ButtonState) bool {
|
||||
pub fn delete_item(menu: *Type.MenuType, button: *Type.ButtonType) bool {
|
||||
var name_: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &name_) catch false)) return false;
|
||||
|
|
|
@ -46,8 +46,9 @@ pub fn Create(options: type) type {
|
|||
const Self = @This();
|
||||
const ValueType = if (@hasDecl(options, "ValueType")) options.ValueType else void;
|
||||
|
||||
pub const MenuState = Menu.State(*Self);
|
||||
pub const ButtonState = Button.State(*Menu.State(*Self));
|
||||
pub const MenuType = Menu.Options(*Self).MenuType;
|
||||
pub const ButtonType = MenuType.ButtonType;
|
||||
pub const Cursor = Button.Cursor;
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator) !tui.Mode {
|
||||
return create_with_args(allocator, .{});
|
||||
|
@ -131,7 +132,7 @@ pub fn Create(options: type) type {
|
|||
.{ .fg = theme.scrollbar.fg, .bg = theme.editor_widget.bg };
|
||||
}
|
||||
|
||||
fn on_render_menu(_: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
|
||||
fn on_render_menu(_: *Self, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
const style_base = theme.editor_widget;
|
||||
const style_label = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.editor_widget;
|
||||
const style_hint = if (tui.find_scope_style(theme, "entity.name")) |sty| sty.style else style_label;
|
||||
|
@ -211,7 +212,7 @@ pub fn Create(options: type) type {
|
|||
scrollbar.set(@intCast(@max(self.total_items, 1) - 1), @intCast(self.view_rows), @intCast(self.view_pos));
|
||||
}
|
||||
|
||||
fn mouse_click_button4(menu: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
|
||||
fn mouse_click_button4(menu: **Menu.State(*Self), _: *ButtonType, _: Button.Cursor) void {
|
||||
const self = &menu.*.opts.ctx.*;
|
||||
if (self.view_pos < Menu.scroll_lines) {
|
||||
self.view_pos = 0;
|
||||
|
@ -222,7 +223,7 @@ pub fn Create(options: type) type {
|
|||
self.start_query(0) catch {};
|
||||
}
|
||||
|
||||
fn mouse_click_button5(menu: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
|
||||
fn mouse_click_button5(menu: **Menu.State(*Self), _: *ButtonType, _: Button.Cursor) void {
|
||||
const self = &menu.*.opts.ctx.*;
|
||||
if (self.view_pos < @max(self.total_items, self.view_rows) - self.view_rows)
|
||||
self.view_pos += Menu.scroll_lines;
|
||||
|
|
|
@ -58,7 +58,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
pub fn on_render_menu(palette: *Type, button: *Type.ButtonState, theme: *const Widget.Theme, selected: bool) bool {
|
||||
pub fn on_render_menu(palette: *Type, button: *Type.ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
var entry: Entry = undefined;
|
||||
var iter = button.opts.label; // label contains cbor entry object and matches
|
||||
if (!(cbor.matchValue(&iter, cbor.extract(&entry)) catch false))
|
||||
|
@ -116,7 +116,7 @@ pub fn on_render_menu(palette: *Type, button: *Type.ButtonState, theme: *const W
|
|||
return false;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var entry: Entry = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchValue(&iter, cbor.extract(&entry)) catch false)) return;
|
||||
|
@ -130,7 +130,7 @@ fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn delete_item(menu: *Type.MenuState, button: *Type.ButtonState) bool {
|
||||
pub fn delete_item(menu: *Type.MenuType, button: *Type.ButtonType) bool {
|
||||
var entry: Entry = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchValue(&iter, cbor.extract(&entry)) catch false)) return false;
|
||||
|
|
|
@ -53,7 +53,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
|
|||
palette.items += 1;
|
||||
}
|
||||
|
||||
fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
||||
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Cursor) void {
|
||||
var description_: []const u8 = undefined;
|
||||
var name_: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
|
@ -65,7 +65,7 @@ fn select(menu: **Type.MenuState, button: *Type.ButtonState) void {
|
|||
tp.self_pid().send(.{ "cmd", "set_theme", .{name_} }) catch |e| menu.*.opts.ctx.logger.err("theme_palette", e);
|
||||
}
|
||||
|
||||
pub fn updated(palette: *Type, button_: ?*Type.ButtonState) !void {
|
||||
pub fn updated(palette: *Type, button_: ?*Type.ButtonType) !void {
|
||||
const button = button_ orelse return cancel(palette);
|
||||
var description_: []const u8 = undefined;
|
||||
var name_: []const u8 = undefined;
|
||||
|
|
|
@ -29,6 +29,7 @@ untracked: usize = 0,
|
|||
done: bool = true,
|
||||
|
||||
const Self = @This();
|
||||
const ButtonType = Button.Options(Self).ButtonType;
|
||||
|
||||
pub fn create(
|
||||
allocator: std.mem.Allocator,
|
||||
|
@ -61,7 +62,7 @@ pub fn ctx_deinit(self: *Self) void {
|
|||
if (self.behind) |p| self.allocator.free(p);
|
||||
}
|
||||
|
||||
fn on_click(self: *Self, _: *Button.State(Self)) void {
|
||||
fn on_click(self: *Self, _: *ButtonType, _: Button.Cursor) void {
|
||||
self.refresh_git_status();
|
||||
command.executeName("show_git_status", .{}) catch {};
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ fn refresh_git_status(self: *Self) void {
|
|||
if (self.workspace_path) |_| git.status(0) catch {};
|
||||
}
|
||||
|
||||
pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
pub fn receive(self: *Self, _: *ButtonType, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
if (try m.match(.{ "E", tp.more }))
|
||||
return self.process_event(m);
|
||||
if (try m.match(.{ "PRJ", "open" }))
|
||||
|
@ -195,14 +196,14 @@ fn format(self: *Self, buf: []u8) []const u8 {
|
|||
return fbs.getWritten();
|
||||
}
|
||||
|
||||
pub fn layout(self: *Self, btn: *Button.State(Self)) Widget.Layout {
|
||||
pub fn layout(self: *Self, btn: *ButtonType) Widget.Layout {
|
||||
var buf: [256]u8 = undefined;
|
||||
const text = self.format(&buf);
|
||||
const len = btn.plane.egc_chunk_width(text, 0, 1);
|
||||
return .{ .static = len };
|
||||
}
|
||||
|
||||
pub fn render(self: *Self, btn: *Button.State(Self), theme: *const Widget.Theme) bool {
|
||||
pub fn render(self: *Self, btn: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
var buf: [256]u8 = undefined;
|
||||
const text = self.format(&buf);
|
||||
if (text.len == 0) return false;
|
||||
|
|
|
@ -17,6 +17,7 @@ buf: [256]u8 = undefined,
|
|||
rendered: [:0]const u8 = "",
|
||||
|
||||
const Self = @This();
|
||||
const ButtonType = Button.Options(Self).ButtonType;
|
||||
|
||||
pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget {
|
||||
return Button.create_widget(Self, allocator, parent, .{
|
||||
|
@ -30,15 +31,15 @@ pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler,
|
|||
});
|
||||
}
|
||||
|
||||
fn on_click(_: *Self, _: *Button.State(Self)) void {
|
||||
fn on_click(_: *Self, _: *ButtonType, _: Button.Cursor) void {
|
||||
command.executeName("show_diagnostics", .{}) catch {};
|
||||
}
|
||||
|
||||
pub fn layout(self: *Self, _: *Button.State(Self)) Widget.Layout {
|
||||
pub fn layout(self: *Self, _: *ButtonType) Widget.Layout {
|
||||
return .{ .static = self.rendered.len };
|
||||
}
|
||||
|
||||
pub fn render(self: *Self, btn: *Button.State(Self), theme: *const Widget.Theme) bool {
|
||||
pub fn render(self: *Self, btn: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
const bg_style = if (btn.active) theme.editor_cursor else if (btn.hover) theme.statusbar_hover else theme.statusbar;
|
||||
btn.plane.set_base_style(theme.editor);
|
||||
btn.plane.erase();
|
||||
|
@ -61,7 +62,7 @@ fn format(self: *Self) void {
|
|||
self.buf[self.rendered.len] = 0;
|
||||
}
|
||||
|
||||
pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
pub fn receive(self: *Self, _: *ButtonType, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
if (try m.match(.{ "E", "diag", tp.extract(&self.errors), tp.extract(&self.warnings), tp.extract(&self.info), tp.extract(&self.hints) }))
|
||||
self.format();
|
||||
return false;
|
||||
|
|
|
@ -40,6 +40,7 @@ indent_mode: config.IndentMode = .spaces,
|
|||
|
||||
const project_icon = "";
|
||||
const Self = @This();
|
||||
const ButtonType = Button.Options(Self).ButtonType;
|
||||
|
||||
pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler, _: ?[]const u8) @import("widget.zig").CreateError!Widget {
|
||||
const btn = try Button.create(Self, allocator, parent, .{
|
||||
|
@ -64,23 +65,23 @@ pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler,
|
|||
return Widget.to(btn);
|
||||
}
|
||||
|
||||
fn on_click(_: *Self, _: *Button.State(Self)) void {
|
||||
fn on_click(_: *Self, _: *ButtonType, _: Button.Cursor) void {
|
||||
command.executeName("open_recent", .{}) catch {};
|
||||
}
|
||||
|
||||
fn on_click2(_: *Self, _: *Button.State(Self)) void {
|
||||
fn on_click2(_: *Self, _: *ButtonType, _: Button.Cursor) void {
|
||||
command.executeName("close_file", .{}) catch {};
|
||||
}
|
||||
|
||||
fn on_click3(self: *Self, _: *Button.State(Self)) void {
|
||||
fn on_click3(self: *Self, _: *ButtonType, _: Button.Cursor) void {
|
||||
self.detailed = !self.detailed;
|
||||
}
|
||||
|
||||
pub fn layout(_: *Self, _: *Button.State(Self)) Widget.Layout {
|
||||
pub fn layout(_: *Self, _: *ButtonType) Widget.Layout {
|
||||
return .dynamic;
|
||||
}
|
||||
|
||||
pub fn render(self: *Self, btn: *Button.State(Self), theme: *const Widget.Theme) bool {
|
||||
pub fn render(self: *Self, btn: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
const style_base = theme.statusbar;
|
||||
const style_label = if (btn.active) theme.editor_cursor else style_base;
|
||||
btn.plane.set_base_style(theme.editor);
|
||||
|
@ -205,7 +206,7 @@ fn render_terminal_title(self: *Self) void {
|
|||
tui.rdr().set_terminal_title(new_title);
|
||||
}
|
||||
|
||||
pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
pub fn receive(self: *Self, _: *ButtonType, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
if (try m.match(.{ "E", tp.more }))
|
||||
return self.process_event(m);
|
||||
if (try m.match(.{ "PRJ", "open" })) {
|
||||
|
|
|
@ -33,6 +33,7 @@ const Leader = enum {
|
|||
zero,
|
||||
};
|
||||
const Self = @This();
|
||||
const ButtonType = Button.Options(Self).ButtonType;
|
||||
|
||||
pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler, arg: ?[]const u8) @import("widget.zig").CreateError!Widget {
|
||||
const padding: ?usize, const leader: ?Leader, const style: ?DigitStyle = if (arg) |fmt| blk: {
|
||||
|
@ -59,17 +60,17 @@ pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler,
|
|||
});
|
||||
}
|
||||
|
||||
fn on_click(_: *Self, _: *Button.State(Self)) void {
|
||||
fn on_click(_: *Self, _: *ButtonType, _: Button.Cursor) void {
|
||||
command.executeName("goto", .{}) catch {};
|
||||
}
|
||||
|
||||
pub fn layout(self: *Self, btn: *Button.State(Self)) Widget.Layout {
|
||||
pub fn layout(self: *Self, btn: *ButtonType) Widget.Layout {
|
||||
const warn_len = if (self.utf8_sanitized) btn.plane.egc_chunk_width(utf8_sanitized_warning, 0, 1) else 0;
|
||||
const len = btn.plane.egc_chunk_width(self.rendered, 0, 1) + warn_len;
|
||||
return .{ .static = len };
|
||||
}
|
||||
|
||||
pub fn render(self: *Self, btn: *Button.State(Self), theme: *const Widget.Theme) bool {
|
||||
pub fn render(self: *Self, btn: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
btn.plane.set_base_style(theme.editor);
|
||||
btn.plane.erase();
|
||||
btn.plane.home();
|
||||
|
@ -120,7 +121,7 @@ fn format_count(self: *Self, writer: anytype, value: usize, width: usize) !void
|
|||
for (value_str, 0..) |_, i| try writer.writeAll(fonts.get_digit_ascii(value_str[i .. i + 1], self.style orelse .ascii));
|
||||
}
|
||||
|
||||
pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
pub fn receive(self: *Self, _: *ButtonType, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
if (try m.match(.{ "E", "pos", tp.extract(&self.lines), tp.extract(&self.line), tp.extract(&self.column) })) {
|
||||
self.format();
|
||||
} else if (try m.match(.{ "E", "eol_mode", tp.extract(&self.eol_mode), tp.extract(&self.utf8_sanitized), tp.extract(&self.indent_mode) })) {
|
||||
|
|
|
@ -18,6 +18,8 @@ const Style = enum {
|
|||
};
|
||||
const default_style = .fancy;
|
||||
|
||||
const ButtonType = Button.Options(Style).ButtonType;
|
||||
|
||||
pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler, arg: ?[]const u8) CreateError!Widget {
|
||||
const style_ = if (arg) |str_style| std.meta.stringToEnum(Style, str_style) orelse default_style else default_style;
|
||||
return Button.create_widget(Style, allocator, parent, .{
|
||||
|
@ -32,7 +34,7 @@ pub fn create(allocator: Allocator, parent: Plane, event_handler: ?EventHandler,
|
|||
});
|
||||
}
|
||||
|
||||
pub fn layout(_: *Style, btn: *Button.State(Style)) Widget.Layout {
|
||||
pub fn layout(_: *Style, btn: *ButtonType) Widget.Layout {
|
||||
const name = btn.plane.egc_chunk_width(tui.get_mode(), 0, 1);
|
||||
const logo = if (is_mini_mode() or is_overlay_mode()) 1 else btn.plane.egc_chunk_width(left ++ symbol ++ right, 0, 1);
|
||||
const padding: usize = 2;
|
||||
|
@ -48,7 +50,7 @@ fn is_overlay_mode() bool {
|
|||
return tui.input_mode_outer() != null;
|
||||
}
|
||||
|
||||
pub fn render(ctx: *Style, self: *Button.State(Style), theme: *const Widget.Theme) bool {
|
||||
pub fn render(ctx: *Style, self: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
const style_base = theme.statusbar;
|
||||
const style_label = switch (ctx.*) {
|
||||
.fancy => if (self.active) theme.editor_cursor else if (self.hover) theme.editor_selection else theme.statusbar_hover,
|
||||
|
@ -78,7 +80,7 @@ pub fn render(ctx: *Style, self: *Button.State(Style), theme: *const Widget.Them
|
|||
return false;
|
||||
}
|
||||
|
||||
fn render_separator(self: *Button.State(Style), theme: *const Widget.Theme) void {
|
||||
fn render_separator(self: *ButtonType, theme: *const Widget.Theme) void {
|
||||
self.plane.reverse_style();
|
||||
self.plane.set_base_style(.{ .bg = theme.editor.bg });
|
||||
if (theme.statusbar.bg) |bg| self.plane.set_style(.{ .bg = bg });
|
||||
|
@ -89,7 +91,7 @@ const left = " ";
|
|||
const symbol = "";
|
||||
const right = " ";
|
||||
|
||||
fn render_logo(self: *Button.State(Style), theme: *const Widget.Theme, style_label: Widget.Theme.Style) void {
|
||||
fn render_logo(self: *ButtonType, theme: *const Widget.Theme, style_label: Widget.Theme.Style) void {
|
||||
const style_braces: Widget.Theme.Style = if (tui.find_scope_style(theme, "punctuation")) |sty| .{ .fg = sty.style.fg, .bg = style_label.bg, .fs = style_label.fs } else style_label;
|
||||
if (left.len > 0) {
|
||||
self.plane.set_style(style_braces);
|
||||
|
@ -103,7 +105,7 @@ fn render_logo(self: *Button.State(Style), theme: *const Widget.Theme, style_lab
|
|||
}
|
||||
}
|
||||
|
||||
fn on_click(_: *Style, _: *Button.State(Style)) void {
|
||||
fn on_click(_: *Style, _: *ButtonType, _: Button.Cursor) void {
|
||||
if (is_mini_mode()) {
|
||||
command.executeName("exit_mini_mode", .{}) catch {};
|
||||
} else if (is_overlay_mode()) {
|
||||
|
@ -113,6 +115,6 @@ fn on_click(_: *Style, _: *Button.State(Style)) void {
|
|||
}
|
||||
}
|
||||
|
||||
fn toggle_panel(_: *Style, _: *Button.State(Style)) void {
|
||||
fn toggle_panel(_: *Style, _: *ButtonType, _: Button.Cursor) void {
|
||||
command.executeName("toggle_panel", .{}) catch {};
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ pub const TabBar = struct {
|
|||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
try self.update_tab_buffers();
|
||||
const prev_widget_count = self.widget_list.widgets.items.len;
|
||||
while (self.widget_list.pop()) |widget| if (widget.dynamic_cast(Button.State(Tab)) == null)
|
||||
while (self.widget_list.pop()) |widget| if (widget.dynamic_cast(Tab.ButtonType) == null)
|
||||
widget.deinit(self.widget_list.allocator);
|
||||
var first = true;
|
||||
for (self.tabs) |tab| {
|
||||
|
@ -194,7 +194,7 @@ pub const TabBar = struct {
|
|||
try self.widget_list.add(try self.make_spacer());
|
||||
}
|
||||
try self.widget_list.add(tab.widget);
|
||||
if (tab.widget.dynamic_cast(Button.State(Tab))) |btn| {
|
||||
if (tab.widget.dynamic_cast(Tab.ButtonType)) |btn| {
|
||||
if (buffer_manager.buffer_from_ref(tab.buffer_ref)) |buffer|
|
||||
try btn.update_label(Tab.name_from_buffer(buffer));
|
||||
}
|
||||
|
@ -327,6 +327,8 @@ const Tab = struct {
|
|||
|
||||
const Mode = enum { active, inactive, selected };
|
||||
|
||||
const ButtonType = Button.Options(@This()).ButtonType;
|
||||
|
||||
fn create(
|
||||
tabbar: *TabBar,
|
||||
buffer_ref: usize,
|
||||
|
@ -346,19 +348,19 @@ const Tab = struct {
|
|||
});
|
||||
}
|
||||
|
||||
fn on_click(self: *@This(), _: *Button.State(@This())) void {
|
||||
fn on_click(self: *@This(), _: *ButtonType, _: Button.Cursor) void {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
if (buffer_manager.buffer_from_ref(self.buffer_ref)) |buffer|
|
||||
tp.self_pid().send(.{ "cmd", "navigate", .{ .file = buffer.get_file_path() } }) catch {};
|
||||
}
|
||||
|
||||
fn on_click2(self: *@This(), _: *Button.State(@This())) void {
|
||||
fn on_click2(self: *@This(), _: *ButtonType, _: Button.Cursor) void {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
if (buffer_manager.buffer_from_ref(self.buffer_ref)) |buffer|
|
||||
tp.self_pid().send(.{ "cmd", "close_buffer", .{buffer.get_file_path()} }) catch {};
|
||||
}
|
||||
|
||||
fn render(self: *@This(), btn: *Button.State(@This()), theme: *const Widget.Theme) bool {
|
||||
fn render(self: *@This(), btn: *ButtonType, theme: *const Widget.Theme) bool {
|
||||
const active = self.tabbar.active_buffer_ref == self.buffer_ref;
|
||||
const mode: Mode = if (btn.hover) .selected else if (active) .active else .inactive;
|
||||
switch (mode) {
|
||||
|
@ -369,7 +371,7 @@ const Tab = struct {
|
|||
return false;
|
||||
}
|
||||
|
||||
fn render_selected(self: *@This(), btn: *Button.State(@This()), theme: *const Widget.Theme, active: bool) void {
|
||||
fn render_selected(self: *@This(), btn: *ButtonType, theme: *const Widget.Theme, active: bool) void {
|
||||
btn.plane.set_base_style(theme.editor);
|
||||
btn.plane.erase();
|
||||
btn.plane.home();
|
||||
|
@ -407,7 +409,7 @@ const Tab = struct {
|
|||
_ = btn.plane.putstr(self.tab_style.selected_right) catch {};
|
||||
}
|
||||
|
||||
fn render_active(self: *@This(), btn: *Button.State(@This()), theme: *const Widget.Theme) void {
|
||||
fn render_active(self: *@This(), btn: *ButtonType, theme: *const Widget.Theme) void {
|
||||
btn.plane.set_base_style(theme.editor);
|
||||
btn.plane.erase();
|
||||
btn.plane.home();
|
||||
|
@ -443,7 +445,7 @@ const Tab = struct {
|
|||
_ = btn.plane.putstr(self.tab_style.active_right) catch {};
|
||||
}
|
||||
|
||||
fn render_inactive(self: *@This(), btn: *Button.State(@This()), theme: *const Widget.Theme) void {
|
||||
fn render_inactive(self: *@This(), btn: *ButtonType, theme: *const Widget.Theme) void {
|
||||
btn.plane.set_base_style(theme.editor);
|
||||
btn.plane.erase();
|
||||
btn.plane.home();
|
||||
|
@ -473,7 +475,7 @@ const Tab = struct {
|
|||
_ = btn.plane.putstr(self.tab_style.inactive_right) catch {};
|
||||
}
|
||||
|
||||
fn render_content(self: *@This(), btn: *Button.State(@This()), fg: ?Widget.Theme.Color, theme: *const Widget.Theme) void {
|
||||
fn render_content(self: *@This(), btn: *ButtonType, fg: ?Widget.Theme.Color, theme: *const Widget.Theme) void {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
const buffer_ = buffer_manager.buffer_from_ref(self.buffer_ref);
|
||||
const is_dirty = if (buffer_) |buffer| buffer.is_dirty() else false;
|
||||
|
@ -513,7 +515,7 @@ const Tab = struct {
|
|||
while (padding > 0) : (padding -= 1) _ = plane.putstr(self.tab_style.padding) catch {};
|
||||
}
|
||||
|
||||
fn layout(self: *@This(), btn: *Button.State(@This())) Widget.Layout {
|
||||
fn layout(self: *@This(), btn: *ButtonType) Widget.Layout {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
const is_dirty = if (buffer_manager.buffer_from_ref(self.buffer_ref)) |buffer| buffer.is_dirty() else false;
|
||||
const active = self.tabbar.active_buffer_ref == self.buffer_ref;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue