get base panel registration working
parent
0039da5c42
commit
6541256a8c
|
@ -4,6 +4,38 @@ M.version = "0.1"
|
|||
M.name = "Default_View"
|
||||
M.namespace = "nl_spacegirl_plugin_Default"
|
||||
|
||||
M.BufferListPanel = {
|
||||
num_clicks = 0
|
||||
}
|
||||
|
||||
M.SomeOtherPanel = {
|
||||
num_clicks_2 = 0
|
||||
}
|
||||
|
||||
function M.BufferListPanel.new()
|
||||
local p = {}
|
||||
setmetatable(p, {__index = M.BufferListPanel})
|
||||
return p
|
||||
end
|
||||
|
||||
function M.BufferListPanel:render(ctx)
|
||||
if UI.button(ctx, "Number of Clicks "..self.num_clicks).clicked then
|
||||
self.num_clicks = self.num_clicks + 1
|
||||
end
|
||||
end
|
||||
|
||||
function M.SomeOtherPanel.new()
|
||||
local p = {}
|
||||
setmetatable(p, {__index = M.SomeOtherPanel})
|
||||
return p
|
||||
end
|
||||
|
||||
function M.SomeOtherPanel:render(ctx)
|
||||
if UI.button(ctx, "Number of Clicks 2 "..self.num_clicks_2).clicked then
|
||||
self.num_clicks_2 = self.num_clicks_2 + 1
|
||||
end
|
||||
end
|
||||
|
||||
function M.open_file_search_window()
|
||||
local input = {
|
||||
{Editor.Key.Enter, "Open File", function() Editor.log("this should open a file") end}
|
||||
|
@ -26,11 +58,27 @@ function M.OnLoad()
|
|||
Editor.log("default view loaded")
|
||||
Editor.log(nl_spacegirl_plugin_Default_Legacy_View['namespace'])
|
||||
|
||||
local a = M.BufferListPanel.new()
|
||||
local b = M.BufferListPanel.new()
|
||||
|
||||
print(M.BufferListPanel)
|
||||
print(a)
|
||||
print(b)
|
||||
|
||||
Editor.register_key_group({
|
||||
{Editor.Key.Space, "", {
|
||||
{Editor.Key.F, "Open File", M.open_file_search_window}
|
||||
}}
|
||||
{Editor.Key.F, "Open File", M.open_file_search_window},
|
||||
{Editor.Key.J, "New Panel", function()
|
||||
Editor.run_command("nl.spacegirl.editor.core", "Open New Panel", "BufferListPanel")
|
||||
end},
|
||||
{Editor.Key.K, "Some Other Panel", function()
|
||||
Editor.run_command("nl.spacegirl.editor.core", "Open New Panel", "SomeOtherPanel")
|
||||
end}
|
||||
}},
|
||||
})
|
||||
|
||||
Editor.register_panel("BufferList", "BufferListPanel")
|
||||
Editor.register_panel("aksjdhflkasjdf", "SomeOtherPanel")
|
||||
end
|
||||
|
||||
function M.view_render(cx)
|
||||
|
|
|
@ -314,7 +314,7 @@ function M.render_ui_window(ctx)
|
|||
end
|
||||
|
||||
-- render_buffer_search(ctx)
|
||||
render_command_search(ctx)
|
||||
-- render_command_search(ctx)
|
||||
render_log_window(ctx)
|
||||
|
||||
LastMouseX = x
|
||||
|
@ -395,7 +395,7 @@ function M.open_buffer_search_window(ctx)
|
|||
-- end
|
||||
end
|
||||
|
||||
function M.open_command_palette(ctx)
|
||||
function M.open_command_palette()
|
||||
-- if CommandSearchOpen or CommandSearchOpenElapsed > 0 then
|
||||
-- if CommandSearchOpen and CommandSearchOpenElapsed < numFrames then
|
||||
-- CommandSearchOpenElapsed = CommandSearchOpenElapsed + 1
|
||||
|
@ -519,7 +519,7 @@ function M.OnLoad()
|
|||
}}
|
||||
})
|
||||
|
||||
Editor.register_hook(Editor.Hook.OnDraw, render_ui_window)
|
||||
Editor.register_hook(Editor.Hook.OnDraw, M.render_ui_window)
|
||||
Editor.register_hook(Editor.Hook.OnBufferInput, handle_buffer_input)
|
||||
end
|
||||
|
||||
|
|
|
@ -92,6 +92,9 @@ State :: struct {
|
|||
command_arena: runtime.Allocator,
|
||||
command_args: [dynamic]EditorCommandArgument,
|
||||
|
||||
active_panels: [128]Maybe(Panel),
|
||||
panel_catalog: [dynamic]PanelId,
|
||||
|
||||
plugins: [dynamic]plugin.Interface,
|
||||
new_plugins: [dynamic]plugin.NewInterface,
|
||||
plugin_vtable: plugin.Plugin,
|
||||
|
@ -111,11 +114,34 @@ EditorCommandExec :: struct {
|
|||
args: [dynamic]EditorCommandArgument,
|
||||
}
|
||||
|
||||
EditorCommandArgument :: union {
|
||||
EditorCommandArgument :: union #no_nil {
|
||||
string,
|
||||
i32
|
||||
}
|
||||
|
||||
PanelId :: union #no_nil {
|
||||
LuaPanelId,
|
||||
LibPanelId,
|
||||
}
|
||||
Panel :: union #no_nil {
|
||||
LuaPanel,
|
||||
LibPanel,
|
||||
}
|
||||
|
||||
|
||||
LuaPanelId :: struct {
|
||||
id: string,
|
||||
name: string,
|
||||
}
|
||||
LuaPanel :: struct {
|
||||
index: i32,
|
||||
render_ref: i32
|
||||
}
|
||||
|
||||
// TODO
|
||||
LibPanelId :: struct {}
|
||||
LibPanel :: struct {}
|
||||
|
||||
current_buffer :: proc(state: ^State) -> ^FileBuffer {
|
||||
if state.current_buffer == -2 {
|
||||
return &state.log_buffer;
|
||||
|
@ -398,3 +424,11 @@ where intrinsics.type_is_struct(T) {
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
register_panel_lua :: proc(state: ^State, name: string, id: string) {
|
||||
append(&state.panel_catalog, LuaPanelId {
|
||||
id = id,
|
||||
name = name,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
128
src/lua/lua.odin
128
src/lua/lua.odin
|
@ -63,6 +63,18 @@ new_state :: proc(_state: ^core.State) {
|
|||
"register_key_group",
|
||||
register_key_group,
|
||||
},
|
||||
lua.L_Reg {
|
||||
"register_panel",
|
||||
proc "c" (L: ^lua.State) -> i32 {
|
||||
context = state.ctx;
|
||||
|
||||
panel_name := strings.clone(string(lua.L_checkstring(L, 1)));
|
||||
panel_identifier := strings.clone(string(lua.L_checkstring(L, 2)));
|
||||
core.register_panel_lua(state, panel_name, panel_identifier)
|
||||
|
||||
return i32(lua.OK)
|
||||
}
|
||||
},
|
||||
lua.L_Reg {
|
||||
"spawn_floating_window",
|
||||
proc "c" (L: ^lua.State) -> i32 {
|
||||
|
@ -195,6 +207,25 @@ new_state :: proc(_state: ^core.State) {
|
|||
|
||||
group := lua.L_checkstring(L, 1);
|
||||
name := lua.L_checkstring(L, 2);
|
||||
|
||||
num_args := lua.gettop(state.L)
|
||||
for i in 0..<(num_args-2) {
|
||||
if lua.isstring(state.L, 3) {
|
||||
value := lua.L_checkstring(state.L, 3)
|
||||
lua.pop(L, 3);
|
||||
|
||||
core.push_command_arg(state, string(value))
|
||||
} else if lua.isinteger(state.L, 3) {
|
||||
value := lua.L_checkinteger(state.L, 3)
|
||||
lua.pop(L, 3);
|
||||
|
||||
core.push_command_arg(state, i32(value))
|
||||
} else {
|
||||
log.error("expected string or integer for command arguments")
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
core.run_command(state, string(group), string(name));
|
||||
|
||||
return 1;
|
||||
|
@ -860,13 +891,13 @@ ui_flags :: proc(L: ^lua.State, index: i32) -> (bit_set[ui.Flag], bool) {
|
|||
return flags, true
|
||||
}
|
||||
|
||||
run_editor_action :: proc(state: ^core.State, key: plugin.Key, action: core.LuaEditorAction) {
|
||||
run_editor_action :: proc(state: ^core.State, key: plugin.Key, action: core.LuaEditorAction, location := #caller_location) {
|
||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(action.fn_ref));
|
||||
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||
lua.pop(state.L, lua.gettop(state.L));
|
||||
|
||||
log.error(err);
|
||||
log.error(err, location);
|
||||
} else {
|
||||
lua.pop(state.L, lua.gettop(state.L));
|
||||
}
|
||||
|
@ -890,6 +921,99 @@ run_ui_function :: proc(state: ^core.State, ui_context: ^ui.Context, fn_ref: i32
|
|||
}
|
||||
}
|
||||
|
||||
run_panel_render :: proc(state: ^core.State, ui_context: ^ui.Context, panel_index: i32, fn_ref: i32) {
|
||||
lua.getglobal(state.L, "__core_panels")
|
||||
|
||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(fn_ref));
|
||||
|
||||
lua.pushinteger(state.L, lua.Integer(panel_index));
|
||||
lua.gettable(state.L, -3);
|
||||
|
||||
lua.pushlightuserdata(state.L, ui_context);
|
||||
if lua.pcall(state.L, 2, 0, 0) != i32(lua.OK) {
|
||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||
lua.pop(state.L, lua.gettop(state.L));
|
||||
|
||||
log.error(err);
|
||||
} else {
|
||||
lua.pop(state.L, lua.gettop(state.L));
|
||||
}
|
||||
}
|
||||
|
||||
add_panel :: proc(state: ^core.State, id: core.LuaPanelId) -> (new_panel: core.LuaPanel, ok: bool) {
|
||||
lua.getglobal(state.L, "__core_panels")
|
||||
|
||||
// create panel list if it doesn't already exist
|
||||
if !lua.istable(state.L, -1) {
|
||||
log.info("__core_panels doesn't exist yet, create it..")
|
||||
|
||||
lua.newtable(state.L)
|
||||
lua.setglobal(state.L, "__core_panels")
|
||||
}
|
||||
|
||||
lua.getglobal(state.L, "__core_panels")
|
||||
|
||||
l_panel_list := lua.gettop(state.L)
|
||||
|
||||
lua.len(state.L, l_panel_list);
|
||||
num_panels := lua.tointeger(state.L, -1);
|
||||
lua.pop(state.L, 1);
|
||||
|
||||
render_ref: i32
|
||||
|
||||
// lua.pushinteger(state.L, lua.Integer(num_panels + 1))
|
||||
{
|
||||
// create new panel object in lua
|
||||
|
||||
// FIXME: eventually grab the appropriate namespace from the panel id
|
||||
lua.getglobal(state.L, "nl_spacegirl_plugin_Default_Default_View");
|
||||
|
||||
lua.getfield(state.L, -1, strings.clone_to_cstring(id.id, allocator = context.temp_allocator));
|
||||
if (lua.isnil(state.L, -1)) {
|
||||
lua.pop(state.L, lua.gettop(state.L)-l_panel_list+1)
|
||||
|
||||
log.error("no lua panel with identifier:", id.id)
|
||||
return
|
||||
}
|
||||
|
||||
lua.getfield(state.L, -1, "render")
|
||||
if lua.isfunction(state.L, -1) {
|
||||
render_ref = lua.L_ref(state.L, i32(lua.REGISTRYINDEX));
|
||||
} else {
|
||||
lua.pop(state.L, lua.gettop(state.L)-l_panel_list+1)
|
||||
|
||||
log.error("no 'render' function for lua panel:", id.id)
|
||||
return
|
||||
}
|
||||
|
||||
lua.getfield(state.L, -1, "new")
|
||||
if (lua.isnil(state.L, -1)) {
|
||||
lua.pop(state.L, lua.gettop(state.L)-l_panel_list+1)
|
||||
|
||||
log.error("no 'new' function for lua panel:", id.id)
|
||||
return
|
||||
}
|
||||
|
||||
if lua.pcall(state.L, 0, 1, 0) != i32(lua.OK) {
|
||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||
lua.pop(state.L, lua.gettop(state.L)-l_panel_list+1);
|
||||
|
||||
// FIXME: do we need this?
|
||||
// lua.pop(state.L, 1);
|
||||
|
||||
log.error("failed to create new lua panel:", err);
|
||||
}
|
||||
log.info("called")
|
||||
}
|
||||
lua.rawseti(state.L, l_panel_list, num_panels + 1);
|
||||
lua.settable(state.L, l_panel_list)
|
||||
|
||||
return core.LuaPanel{
|
||||
index = i32(num_panels) + 1,
|
||||
render_ref = render_ref
|
||||
}, true
|
||||
}
|
||||
|
||||
// TODO: don't duplicate this procedure
|
||||
ui_file_buffer :: proc(ctx: ^ui.Context, buffer: ^core.FileBuffer) -> ui.Interaction {
|
||||
draw_func := proc(state: ^core.State, box: ^ui.Box, user_data: rawptr) {
|
||||
|
|
186
src/main.odin
186
src/main.odin
|
@ -1033,6 +1033,8 @@ main :: proc() {
|
|||
commands = make(core.EditorCommandList),
|
||||
command_arena = mem.arena_allocator(&_command_arena),
|
||||
|
||||
panel_catalog = make([dynamic]core.PanelId),
|
||||
|
||||
window = nil,
|
||||
directory = os.get_current_directory(),
|
||||
plugins = make([dynamic]plugin.Interface),
|
||||
|
@ -1062,8 +1064,8 @@ main :: proc() {
|
|||
}
|
||||
}
|
||||
|
||||
context.logger = core.new_logger(&state.log_buffer);
|
||||
// context.logger = log.create_console_logger();
|
||||
// context.logger = core.new_logger(&state.log_buffer);
|
||||
context.logger = log.create_console_logger();
|
||||
state.ctx = context;
|
||||
|
||||
// TODO: don't use this
|
||||
|
@ -1076,6 +1078,46 @@ main :: proc() {
|
|||
|
||||
register_default_text_input_actions(&state.input_map.mode[.Normal]);
|
||||
|
||||
core.register_editor_command(
|
||||
&state.commands,
|
||||
"nl.spacegirl.editor.core",
|
||||
"Open New Panel",
|
||||
"Opens a new panel",
|
||||
proc(state: ^State) {
|
||||
Args :: struct {
|
||||
panel_id: string
|
||||
}
|
||||
|
||||
if args, ok := core.attempt_read_command_args(Args, state.command_args[:]); ok {
|
||||
log.info("maybe going to open panel with id", args.panel_id)
|
||||
|
||||
for p in state.panel_catalog {
|
||||
switch v in p {
|
||||
case core.LuaPanelId:
|
||||
{
|
||||
if v.id == args.panel_id {
|
||||
if index, ok := lua.add_panel(state, v); ok {
|
||||
for i in 0..<len(state.active_panels) {
|
||||
if state.active_panels[i] == nil {
|
||||
state.active_panels[i] = index
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("failed to open panel")
|
||||
}
|
||||
}
|
||||
}
|
||||
case core.LibPanelId:
|
||||
{
|
||||
log.warn("lib panels not supported yet")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
core.register_editor_command(
|
||||
&state.commands,
|
||||
"nl.spacegirl.editor.core",
|
||||
|
@ -1218,137 +1260,25 @@ main :: proc() {
|
|||
|
||||
control_key_pressed: bool;
|
||||
for !state.should_close {
|
||||
// if false {
|
||||
// buffer := core.current_buffer(&state);
|
||||
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "main", {}, .Vertical, semantic_size = {ui.make_semantic_size(.Fill, 100), ui.make_semantic_size(.Fill, 100)}));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// {
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "top_nav", {.DrawBackground}, semantic_size = {ui.make_semantic_size(.PercentOfParent, 100), ui.make_semantic_size(.Exact, state.source_font_height)}));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// if ui.label(&ui_context, "Editor").clicked {
|
||||
// fmt.println("you clicked the button");
|
||||
// }
|
||||
|
||||
// ui.push_box(
|
||||
// &ui_context,
|
||||
// "nav spacer",
|
||||
// {.DrawBackground},
|
||||
// semantic_size = {
|
||||
// ui.make_semantic_size(.Exact, 16),
|
||||
// ui.make_semantic_size(.Exact, state.source_font_height)
|
||||
// }
|
||||
// );
|
||||
|
||||
// if ui.label(&ui_context, "Buffers").clicked {
|
||||
// fmt.println("you clicked the button");
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "deezbuffer", {}, .Horizontal, semantic_size = {ui.make_semantic_size(.PercentOfParent, 100), ui.make_semantic_size(.Fill, 0)}));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// {
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "left side", {}, .Vertical, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Fill, 0)}));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// {
|
||||
// if ui_file_buffer(&ui_context, &state.buffers[0]).clicked {
|
||||
// state.current_buffer = 0;
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// if ui_file_buffer(&ui_context, &state.buffers[0+1]).clicked {
|
||||
// state.current_buffer = 1;
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// if ui_file_buffer(&ui_context, &state.buffers[0+2]).clicked {
|
||||
// state.current_buffer = 2;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "right side", {}, .Vertical, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Fill, 0)}));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// {
|
||||
// if ui_file_buffer(&ui_context, core.current_buffer(&state)).clicked {
|
||||
// state.current_buffer = 3;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "bottom stats", {.DrawBackground}, semantic_size = {ui.make_semantic_size(.PercentOfParent, 100), ui.make_semantic_size(.Exact, state.source_font_height)}));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// label := "";
|
||||
// if state.mode == .Insert {
|
||||
// label = "INSERT";
|
||||
// } else if state.mode == .Normal {
|
||||
// label = "NORMAL";
|
||||
// }
|
||||
|
||||
// if ui.label(&ui_context, label).clicked {
|
||||
// fmt.println("you clicked the button");
|
||||
// }
|
||||
// ui.spacer(&ui_context, "mode spacer", semantic_size = {ui.make_semantic_size(.Exact, 16), ui.make_semantic_size(.Fill)});
|
||||
|
||||
// relative_file_path, _ := filepath.rel(state.directory, buffer.file_path, context.temp_allocator)
|
||||
// ui.label(&ui_context, relative_file_path);
|
||||
|
||||
// ui.spacer(&ui_context, "stats inbetween");
|
||||
|
||||
// {
|
||||
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "center info", {}, semantic_size = ui.ChildrenSum));
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
|
||||
// line_info_text := fmt.tprintf(
|
||||
// //"Line: %d, Col: %d, Len: %d --- Slice Index: %d, Content Index: %d",
|
||||
// "Line: %d, Col: %d",
|
||||
// buffer.cursor.line + 1,
|
||||
// buffer.cursor.col + 1,
|
||||
// //core.file_buffer_line_length(buffer, buffer.cursor.index),
|
||||
// // buffer.cursor.index.slice_index,
|
||||
// // buffer.cursor.index.content_index,
|
||||
// );
|
||||
// ui.label(&ui_context, line_info_text);
|
||||
|
||||
// mouse_pos_str := fmt.tprintf("x,y: [%d,%d]", ui_context.mouse_x, ui_context.mouse_y);
|
||||
// ui.label(&ui_context, mouse_pos_str);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: move this to view.lua
|
||||
// log_window, _ := ui.push_floating(&ui_context, "log", {0,0}, flags = {.Floating, .DrawBackground}, semantic_size = {ui.make_semantic_size(.PercentOfParent, 75), ui.make_semantic_size(.PercentOfParent, 75)});
|
||||
// ui.push_parent(&ui_context, log_window);
|
||||
{
|
||||
// defer ui.pop_parent(&ui_context);
|
||||
ui_file_buffer(&ui_context, &state.log_buffer);
|
||||
}
|
||||
|
||||
|
||||
// TODO: remove this functionality
|
||||
if draw_hooks, ok := state.lua_hooks[plugin.Hook.Draw]; ok {
|
||||
for hook_ref in draw_hooks {
|
||||
/*
|
||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
||||
lua.pushlightuserdata(state.L, &ui_context);
|
||||
if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) {
|
||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||
lua.pop(state.L, lua.gettop(state.L));
|
||||
|
||||
log.error(err);
|
||||
} else {
|
||||
lua.pop(state.L, lua.gettop(state.L));
|
||||
}
|
||||
*/
|
||||
lua.run_ui_function(&state, &ui_context, hook_ref)
|
||||
}
|
||||
}
|
||||
|
||||
for panel in state.active_panels {
|
||||
if panel != nil {
|
||||
switch v in panel.? {
|
||||
case core.LuaPanel:
|
||||
lua.run_panel_render(&state, &ui_context, v.index, v.render_ref)
|
||||
case core.LibPanel:
|
||||
log.warn("LibPanel not supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: mirror how this is done for Lua
|
||||
if state.window != nil && state.window.draw != nil {
|
||||
state.window.draw(state.plugin_vtable, state.window.user_data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue