feat: add scrollbar to command palette
This commit is contained in:
parent
752331c717
commit
e7c8fea3f0
6 changed files with 156 additions and 43 deletions
|
@ -5,8 +5,12 @@ const planeutils = @import("renderer").planeutils;
|
|||
|
||||
const Widget = @import("Widget.zig");
|
||||
const WidgetList = @import("WidgetList.zig");
|
||||
const EventHandler = @import("EventHandler.zig");
|
||||
const Button = @import("Button.zig");
|
||||
const tui = @import("tui.zig");
|
||||
const scrollbar_v = @import("scrollbar_v.zig");
|
||||
|
||||
pub const Container = WidgetList;
|
||||
|
||||
pub fn Options(context: type) type {
|
||||
return struct {
|
||||
|
@ -16,6 +20,7 @@ pub fn Options(context: type) type {
|
|||
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,
|
||||
on_resize: *const fn (ctx: context, menu: *State(Context), box: Widget.Box) void = on_resize_default,
|
||||
on_scroll: ?EventHandler = null,
|
||||
|
||||
pub const Context = context;
|
||||
pub fn do_nothing(_: context, _: *Button.State(*State(Context))) void {}
|
||||
|
@ -35,23 +40,29 @@ pub fn Options(context: type) type {
|
|||
|
||||
pub fn on_resize_default(_: context, state: *State(Context), box_: Widget.Box) void {
|
||||
var box = box_;
|
||||
box.h = state.menu.widgets.items.len;
|
||||
state.menu.resize(box);
|
||||
box.h = if (box_.h == 0) state.menu.widgets.items.len else box_.h;
|
||||
state.container.resize(box);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn create(ctx_type: type, a: std.mem.Allocator, parent: Widget, opts: Options(ctx_type)) !*State(ctx_type) {
|
||||
const self = try a.create(State(ctx_type));
|
||||
const container = try WidgetList.createH(a, parent, @typeName(@This()), .dynamic);
|
||||
self.* = .{
|
||||
.a = a,
|
||||
.menu = try WidgetList.createV(a, parent, @typeName(@This()), .dynamic),
|
||||
.menu_widget = self.menu.widget(),
|
||||
.menu = try WidgetList.createV(a, container.widget(), @typeName(@This()), .dynamic),
|
||||
.container = container,
|
||||
.container_widget = container.widget(),
|
||||
.scrollbar = if (opts.on_scroll) |on_scroll| (try scrollbar_v.create(a, parent, null, on_scroll)).dynamic_cast(scrollbar_v).? else null,
|
||||
.opts = opts,
|
||||
};
|
||||
self.menu.ctx = self;
|
||||
self.menu.on_render = State(ctx_type).on_render_menu_widgetlist;
|
||||
self.menu.on_resize = State(ctx_type).on_resize_menu_widgetlist;
|
||||
self.menu.on_render = State(ctx_type).on_render_menu;
|
||||
container.ctx = self;
|
||||
container.on_resize = State(ctx_type).on_resize_container;
|
||||
try container.add(self.menu.widget());
|
||||
if (self.scrollbar) |sb| try container.add(sb.widget());
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -59,7 +70,9 @@ pub fn State(ctx_type: type) type {
|
|||
return struct {
|
||||
a: std.mem.Allocator,
|
||||
menu: *WidgetList,
|
||||
menu_widget: Widget,
|
||||
container: *WidgetList,
|
||||
container_widget: Widget,
|
||||
scrollbar: ?*scrollbar_v,
|
||||
opts: options_type,
|
||||
selected: ?usize = null,
|
||||
render_idx: usize = 0,
|
||||
|
@ -112,11 +125,16 @@ pub fn State(ctx_type: type) type {
|
|||
return self.menu.render(theme);
|
||||
}
|
||||
|
||||
fn on_render_menu_widgetlist(ctx: ?*anyopaque, _: *const Widget.Theme) void {
|
||||
fn on_render_menu(ctx: ?*anyopaque, _: *const Widget.Theme) void {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
self.render_idx = 0;
|
||||
}
|
||||
|
||||
fn on_resize_container(ctx: ?*anyopaque, _: *WidgetList, box: Widget.Box) void {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
self.opts.on_resize(self.*.opts.ctx, self, box);
|
||||
}
|
||||
|
||||
pub fn on_layout(self: **Self, button: *Button.State(*Self)) Widget.Layout {
|
||||
return self.*.opts.on_layout(self.*.opts.ctx, button);
|
||||
}
|
||||
|
@ -127,13 +145,8 @@ pub fn State(ctx_type: type) type {
|
|||
return self.*.opts.on_render(self.*.opts.ctx, button, theme, self.*.render_idx == self.*.selected);
|
||||
}
|
||||
|
||||
fn on_resize_menu_widgetlist(ctx: ?*anyopaque, _: *WidgetList, box: Widget.Box) void {
|
||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||
return self.opts.on_resize(self.opts.ctx, self, box);
|
||||
}
|
||||
|
||||
pub fn resize(self: *Self, box: Widget.Box) void {
|
||||
self.menu.resize(box);
|
||||
self.container.resize(box);
|
||||
}
|
||||
|
||||
pub fn update(self: *Self) void {
|
||||
|
@ -141,7 +154,7 @@ pub fn State(ctx_type: type) type {
|
|||
}
|
||||
|
||||
pub fn walk(self: *Self, walk_ctx: *anyopaque, f: Widget.WalkFn) bool {
|
||||
return self.menu.walk(walk_ctx, f, &self.menu_widget);
|
||||
return self.menu.walk(walk_ctx, f, &self.container_widget);
|
||||
}
|
||||
|
||||
pub fn count(self: *Self) usize {
|
||||
|
@ -163,6 +176,14 @@ pub fn State(ctx_type: type) type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn select_first(self: *Self) void {
|
||||
self.selected = if (self.count() > 0) 0 else null;
|
||||
}
|
||||
|
||||
pub fn select_last(self: *Self) void {
|
||||
self.selected = if (self.count() > 0) self.count() - self.header_count - 1 else null;
|
||||
}
|
||||
|
||||
pub fn activate_selected(self: *Self) void {
|
||||
const selected = self.selected orelse return;
|
||||
self.selected_active = true;
|
||||
|
|
|
@ -3655,7 +3655,7 @@ pub const EditorWidget = struct {
|
|||
const editorWidget = Widget.to(self);
|
||||
try container.add(try editor_gutter.create(a, container.widget(), editorWidget, &self.editor));
|
||||
try container.add(editorWidget);
|
||||
try container.add(try scrollbar_v.create(a, container.widget(), editorWidget));
|
||||
try container.add(try scrollbar_v.create(a, container.widget(), editorWidget, EventHandler.to_unowned(container)));
|
||||
return container.widget();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
|
|||
const tui = @import("../../tui.zig");
|
||||
const command = @import("../../command.zig");
|
||||
const EventHandler = @import("../../EventHandler.zig");
|
||||
const WidgetList = @import("../../WidgetList.zig");
|
||||
const Button = @import("../../Button.zig");
|
||||
const InputBox = @import("../../InputBox.zig");
|
||||
const Menu = @import("../../Menu.zig");
|
||||
|
@ -31,18 +32,29 @@ commands: Commands = undefined,
|
|||
hints: ?*const tui.KeybindHints = null,
|
||||
longest_hint: usize = 0,
|
||||
|
||||
items: usize = 0,
|
||||
view_rows: usize,
|
||||
view_pos: usize = 0,
|
||||
total_items: usize = 0,
|
||||
|
||||
pub fn create(a: std.mem.Allocator) !tui.Mode {
|
||||
const mv = if (tui.current().mainview.dynamic_cast(mainview)) |mv_| mv_ else return error.NotFound;
|
||||
const self: *Self = try a.create(Self);
|
||||
self.* = .{
|
||||
.a = a,
|
||||
.menu = try Menu.create(*Self, a, tui.current().mainview, .{ .ctx = self, .on_render = on_render_menu, .on_resize = on_resize_menu }),
|
||||
.menu = try Menu.create(*Self, a, tui.current().mainview, .{
|
||||
.ctx = self,
|
||||
.on_render = on_render_menu,
|
||||
.on_resize = on_resize_menu,
|
||||
.on_scroll = EventHandler.bind(self, Self.on_scroll),
|
||||
}),
|
||||
.logger = log.logger(@typeName(Self)),
|
||||
.inputbox = (try self.menu.add_header(try InputBox.create(*Self, self.a, self.menu.menu.parent, .{
|
||||
.ctx = self,
|
||||
.label = "Search commands",
|
||||
}))).dynamic_cast(InputBox.State(*Self)) orelse unreachable,
|
||||
.hints = if (tui.current().input_mode) |m| m.keybind_hints else null,
|
||||
.view_rows = get_view_rows(tui.current().screen()),
|
||||
};
|
||||
if (self.hints) |hints| {
|
||||
for (hints.values()) |val|
|
||||
|
@ -50,7 +62,7 @@ pub fn create(a: std.mem.Allocator) !tui.Mode {
|
|||
}
|
||||
try self.commands.init(self);
|
||||
try self.start_query();
|
||||
try mv.floating_views.add(self.menu.menu_widget);
|
||||
try mv.floating_views.add(self.menu.container_widget);
|
||||
return .{
|
||||
.handler = EventHandler.to_owned(self),
|
||||
.name = " command",
|
||||
|
@ -62,7 +74,7 @@ pub fn deinit(self: *Self) void {
|
|||
self.commands.deinit();
|
||||
tui.current().message_filters.remove_ptr(self);
|
||||
if (tui.current().mainview.dynamic_cast(mainview)) |mv|
|
||||
mv.floating_views.remove(self.menu.menu_widget);
|
||||
mv.floating_views.remove(self.menu.container_widget);
|
||||
self.logger.deinit();
|
||||
self.a.destroy(self);
|
||||
}
|
||||
|
@ -81,10 +93,7 @@ fn on_render_menu(_: *Self, button: *Button.State(*Menu.State(*Self)), theme: *c
|
|||
if (!(cbor.matchString(&iter, &keybind_hint) catch false))
|
||||
keybind_hint = "";
|
||||
const pointer = if (selected) "⏵" else " ";
|
||||
_ = button.plane.print("{s}{s} ", .{
|
||||
pointer,
|
||||
command_name,
|
||||
}) catch {};
|
||||
_ = button.plane.print("{s}{s} ", .{ pointer, command_name }) catch {};
|
||||
button.plane.set_style(style_keybind);
|
||||
_ = button.plane.print_aligned_right(0, "{s} ", .{keybind_hint}) catch {};
|
||||
var index: usize = 0;
|
||||
|
@ -110,7 +119,19 @@ fn on_resize_menu(self: *Self, _: *Menu.State(*Self), _: Widget.Box) void {
|
|||
}
|
||||
|
||||
fn do_resize(self: *Self) void {
|
||||
self.menu.resize(.{ .y = 0, .x = 25, .w = @min(self.longest, max_menu_width) + 2 });
|
||||
const screen = tui.current().screen();
|
||||
const w = @min(self.longest, max_menu_width) + 2 + 1 + self.longest_hint;
|
||||
const x = if (screen.w > w) (screen.w - w) / 2 else 0;
|
||||
self.view_rows = get_view_rows(screen);
|
||||
const h = @min(self.items, self.view_rows);
|
||||
self.menu.container.resize(.{ .y = 0, .x = x, .w = w, .h = h });
|
||||
self.update_scrollbar();
|
||||
}
|
||||
|
||||
fn get_view_rows(screen: Widget.Box) usize {
|
||||
var h = screen.h;
|
||||
if (h > 0) h = h / 5 * 4;
|
||||
return h;
|
||||
}
|
||||
|
||||
fn menu_action_execute_command(menu: **Menu.State(*Self), button: *Button.State(*Menu.State(*Self))) void {
|
||||
|
@ -121,6 +142,16 @@ fn menu_action_execute_command(menu: **Menu.State(*Self), button: *Button.State(
|
|||
tp.self_pid().send(.{ "cmd", command_name, .{} }) catch |e| menu.*.opts.ctx.logger.err("navigate", e);
|
||||
}
|
||||
|
||||
fn on_scroll(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!void {
|
||||
if (try m.match(.{ "scroll_to", tp.extract(&self.view_pos) })) {
|
||||
try self.start_query();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_scrollbar(self: *Self) void {
|
||||
self.menu.scrollbar.?.set(@intCast(self.total_items), @intCast(self.view_rows), @intCast(self.view_pos));
|
||||
}
|
||||
|
||||
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
var evtype: u32 = undefined;
|
||||
var keypress: u32 = undefined;
|
||||
|
@ -160,6 +191,8 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
key.ESC => self.cmd("exit_overlay_mode", .{}),
|
||||
key.UP => self.cmd("command_palette_menu_up", .{}),
|
||||
key.DOWN => self.cmd("command_palette_menu_down", .{}),
|
||||
key.PGUP => self.cmd("command_palette_menu_pageup", .{}),
|
||||
key.PGDOWN => self.cmd("command_palette_menu_pagedown", .{}),
|
||||
key.ENTER => self.cmd("command_palette_menu_activate", .{}),
|
||||
key.BACKSPACE => self.delete_word(),
|
||||
else => {},
|
||||
|
@ -191,6 +224,8 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
key.ESC => self.cmd("exit_overlay_mode", .{}),
|
||||
key.UP => self.cmd("command_palette_menu_up", .{}),
|
||||
key.DOWN => self.cmd("command_palette_menu_down", .{}),
|
||||
key.PGUP => self.cmd("command_palette_menu_pageup", .{}),
|
||||
key.PGDOWN => self.cmd("command_palette_menu_pagedown", .{}),
|
||||
key.ENTER => self.cmd("command_palette_menu_activate", .{}),
|
||||
key.BACKSPACE => self.delete_code_point(),
|
||||
else => if (!key.synthesized_p(keypress))
|
||||
|
@ -209,6 +244,7 @@ fn mapRelease(self: *Self, keypress: u32, _: u32) tp.result {
|
|||
}
|
||||
|
||||
fn start_query(self: *Self) tp.result {
|
||||
self.items = 0;
|
||||
self.menu.reset_items();
|
||||
self.menu.selected = null;
|
||||
for (command.commands.items) |cmd_| if (cmd_) |p| {
|
||||
|
@ -216,8 +252,14 @@ fn start_query(self: *Self) tp.result {
|
|||
};
|
||||
|
||||
if (self.inputbox.text.items.len == 0) {
|
||||
self.total_items = 0;
|
||||
var pos: usize = 0;
|
||||
for (command.commands.items) |cmd_| if (cmd_) |p| {
|
||||
self.add_item(p.name, null) catch |e| return tp.exit_error(e);
|
||||
defer self.total_items += 1;
|
||||
defer pos += 1;
|
||||
if (pos < self.view_pos) continue;
|
||||
if (self.items < self.view_rows)
|
||||
self.add_item(p.name, null) catch |e| return tp.exit_error(e);
|
||||
};
|
||||
} else {
|
||||
_ = self.query_commands(self.inputbox.text.items) catch |e| return tp.exit_error(e);
|
||||
|
@ -261,8 +303,15 @@ fn query_commands(self: *Self, query: []const u8) error{OutOfMemory}!usize {
|
|||
}.less_fn;
|
||||
std.mem.sort(Match, matches.items, {}, less_fn);
|
||||
|
||||
for (matches.items) |match|
|
||||
try self.add_item(match.name, match.matches);
|
||||
var pos: usize = 0;
|
||||
self.total_items = 0;
|
||||
for (matches.items) |match| {
|
||||
defer self.total_items += 1;
|
||||
defer pos += 1;
|
||||
if (pos < self.view_pos) continue;
|
||||
if (self.items < self.view_rows)
|
||||
try self.add_item(match.name, match.matches);
|
||||
}
|
||||
return matches.items.len;
|
||||
}
|
||||
|
||||
|
@ -271,10 +320,11 @@ fn add_item(self: *Self, command_name: []const u8, matches: ?[]const usize) !voi
|
|||
defer label.deinit();
|
||||
const writer = label.writer();
|
||||
try cbor.writeValue(writer, command_name);
|
||||
try cbor.writeValue(writer, if (self.hints) |hints| hints.get(command_name) else "");
|
||||
try cbor.writeValue(writer, if (self.hints) |hints| hints.get(command_name) orelse "" else "");
|
||||
if (matches) |matches_|
|
||||
try cbor.writeValue(writer, matches_);
|
||||
try self.menu.add_item_with_handler(label.items, menu_action_execute_command);
|
||||
self.items += 1;
|
||||
}
|
||||
|
||||
fn delete_word(self: *Self) tp.result {
|
||||
|
@ -284,6 +334,7 @@ fn delete_word(self: *Self) tp.result {
|
|||
self.inputbox.text.shrinkRetainingCapacity(0);
|
||||
}
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
self.view_pos = 0;
|
||||
return self.start_query();
|
||||
}
|
||||
|
||||
|
@ -292,6 +343,7 @@ fn delete_code_point(self: *Self) tp.result {
|
|||
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
}
|
||||
self.view_pos = 0;
|
||||
return self.start_query();
|
||||
}
|
||||
|
||||
|
@ -300,12 +352,14 @@ fn insert_code_point(self: *Self, c: u32) tp.result {
|
|||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.inputbox.text.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
self.view_pos = 0;
|
||||
return self.start_query();
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
self.inputbox.text.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
self.view_pos = 0;
|
||||
return self.start_query();
|
||||
}
|
||||
|
||||
|
@ -327,13 +381,46 @@ const cmds = struct {
|
|||
const Ctx = command.Context;
|
||||
|
||||
pub fn command_palette_menu_down(self: *Self, _: Ctx) tp.result {
|
||||
if (self.menu.selected) |selected| {
|
||||
if (selected == self.view_rows - 1) {
|
||||
self.view_pos += 1;
|
||||
try self.start_query();
|
||||
self.menu.select_last();
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.menu.select_down();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_up(self: *Self, _: Ctx) tp.result {
|
||||
if (self.menu.selected) |selected| {
|
||||
if (selected == 0 and self.view_pos > 0) {
|
||||
self.view_pos -= 1;
|
||||
try self.start_query();
|
||||
self.menu.select_first();
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.menu.select_up();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_pagedown(self: *Self, _: Ctx) tp.result {
|
||||
if (self.total_items > self.view_rows) {
|
||||
self.view_pos += self.view_rows;
|
||||
if (self.view_pos > self.total_items - self.view_rows)
|
||||
self.view_pos = self.total_items - self.view_rows;
|
||||
}
|
||||
try self.start_query();
|
||||
self.menu.select_last();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_pageup(self: *Self, _: Ctx) tp.result {
|
||||
if (self.view_pos > self.view_rows)
|
||||
self.view_pos -= self.view_rows;
|
||||
try self.start_query();
|
||||
self.menu.select_first();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_activate(self: *Self, _: Ctx) tp.result {
|
||||
self.menu.activate_selected();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,11 @@ pub fn create(a: std.mem.Allocator) !tui.Mode {
|
|||
const self: *Self = try a.create(Self);
|
||||
self.* = .{
|
||||
.a = a,
|
||||
.menu = try Menu.create(*Self, a, tui.current().mainview, .{ .ctx = self, .on_render = on_render_menu, .on_resize = on_resize_menu }),
|
||||
.menu = try Menu.create(*Self, a, tui.current().mainview, .{
|
||||
.ctx = self,
|
||||
.on_render = on_render_menu,
|
||||
.on_resize = on_resize_menu,
|
||||
}),
|
||||
.logger = log.logger(@typeName(Self)),
|
||||
.inputbox = (try self.menu.add_header(try InputBox.create(*Self, self.a, self.menu.menu.parent, .{
|
||||
.ctx = self,
|
||||
|
@ -53,7 +57,7 @@ pub fn create(a: std.mem.Allocator) !tui.Mode {
|
|||
self.query_pending = true;
|
||||
try project_manager.request_recent_files(max_recent_files);
|
||||
self.menu.resize(.{ .y = 0, .x = 25, .w = 32 });
|
||||
try mv.floating_views.add(self.menu.menu_widget);
|
||||
try mv.floating_views.add(self.menu.container_widget);
|
||||
return .{
|
||||
.handler = EventHandler.to_owned(self),
|
||||
.name = " open recent",
|
||||
|
@ -65,7 +69,7 @@ pub fn deinit(self: *Self) void {
|
|||
self.commands.deinit();
|
||||
tui.current().message_filters.remove_ptr(self);
|
||||
if (tui.current().mainview.dynamic_cast(mainview)) |mv|
|
||||
mv.floating_views.remove(self.menu.menu_widget);
|
||||
mv.floating_views.remove(self.menu.container_widget);
|
||||
self.logger.deinit();
|
||||
self.a.destroy(self);
|
||||
}
|
||||
|
|
|
@ -21,27 +21,24 @@ size_virt: u32 = 1,
|
|||
|
||||
max_ypx: i32 = 8,
|
||||
|
||||
parent: Widget,
|
||||
event_sink: EventHandler,
|
||||
hover: bool = false,
|
||||
active: bool = false,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn create(a: Allocator, parent: Widget, event_source: ?Widget) !Widget {
|
||||
pub fn create(a: Allocator, parent: Widget, event_source: ?Widget, event_sink: EventHandler) !Widget {
|
||||
const self: *Self = try a.create(Self);
|
||||
self.* = try init(parent);
|
||||
self.* = .{
|
||||
.plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent.plane.*),
|
||||
.event_sink = event_sink,
|
||||
};
|
||||
|
||||
if (event_source) |source|
|
||||
try source.subscribe(EventHandler.bind(self, handle_event));
|
||||
return self.widget();
|
||||
}
|
||||
|
||||
fn init(parent: Widget) !Self {
|
||||
return .{
|
||||
.plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent.plane.*),
|
||||
.parent = parent,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn widget(self: *Self) Widget {
|
||||
return Widget.to(self);
|
||||
}
|
||||
|
@ -108,7 +105,7 @@ fn move_to(self: *Self, y_: i32, ypx_: i32) void {
|
|||
const pos_virt = self.pos_scrn_to_virt(@intFromFloat(pos_scrn_clamped));
|
||||
|
||||
self.set(self.size_virt, self.view_virt, pos_virt);
|
||||
_ = self.parent.msg(.{ "scroll_to", pos_virt }) catch {};
|
||||
_ = self.event_sink.msg(.{ "scroll_to", pos_virt }) catch {};
|
||||
}
|
||||
|
||||
fn pos_scrn_to_virt(self: Self, pos_scrn_: u32) u32 {
|
||||
|
|
|
@ -676,10 +676,14 @@ pub fn need_render() void {
|
|||
}
|
||||
|
||||
pub fn resize(self: *Self) void {
|
||||
self.mainview.resize(Widget.Box.from(self.rdr.stdplane()));
|
||||
self.mainview.resize(self.screen());
|
||||
need_render();
|
||||
}
|
||||
|
||||
pub fn screen(self: *Self) Widget.Box {
|
||||
return Widget.Box.from(self.rdr.stdplane());
|
||||
}
|
||||
|
||||
pub fn get_theme_by_name(name: []const u8) ?Widget.Theme {
|
||||
for (Widget.themes) |theme| {
|
||||
if (std.mem.eql(u8, theme.name, name))
|
||||
|
|
Loading…
Add table
Reference in a new issue