port UI layout to lua + fun animations + fix memory leaks + add dragging support
parent
b105eb67cc
commit
f602c3a493
4
Makefile
4
Makefile
|
@ -1,10 +1,8 @@
|
||||||
all: editor
|
all: editor
|
||||||
|
|
||||||
editor: src/*.odin grep odin_highlighter buffer_search
|
editor: src/*.odin grep odin_highlighter
|
||||||
odin build src/ -out:bin/editor -lld
|
odin build src/ -out:bin/editor -lld
|
||||||
|
|
||||||
buffer_search:
|
|
||||||
odin build plugins/buffer_search/ -build-mode:dll -no-entry-point -out:bin/buffer_search
|
|
||||||
odin_highlighter:
|
odin_highlighter:
|
||||||
odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter
|
odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter
|
||||||
|
|
||||||
|
|
|
@ -1,234 +0,0 @@
|
||||||
// A simple window to view/search open buffers
|
|
||||||
package buffer_search;
|
|
||||||
|
|
||||||
import "core:runtime"
|
|
||||||
import "core:fmt"
|
|
||||||
import "core:path/filepath"
|
|
||||||
|
|
||||||
import p "../../src/plugin"
|
|
||||||
import "../../src/theme"
|
|
||||||
|
|
||||||
Plugin :: p.Plugin;
|
|
||||||
Iterator :: p.Iterator;
|
|
||||||
BufferIter :: p.BufferIter;
|
|
||||||
BufferIndex :: p.BufferIndex;
|
|
||||||
Key :: p.Key;
|
|
||||||
|
|
||||||
BufferListWindow :: struct {
|
|
||||||
selected_index: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
@export
|
|
||||||
OnInitialize :: proc "c" (plugin: Plugin) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
fmt.println("builtin buffer search plugin initialized!");
|
|
||||||
|
|
||||||
plugin.register_input_group(nil, .SPACE, proc "c" (plugin: Plugin, input_map: rawptr) {
|
|
||||||
plugin.register_input(input_map, .B, open_buffer_window, "show list of open buffers");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@export
|
|
||||||
OnExit :: proc "c" (plugin: Plugin) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
}
|
|
||||||
|
|
||||||
open_buffer_window :: proc "c" (plugin: Plugin) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
|
|
||||||
window := new(BufferListWindow);
|
|
||||||
window^ = BufferListWindow {};
|
|
||||||
|
|
||||||
plugin.create_window(window, proc "c" (plugin: Plugin, input_map: rawptr) {
|
|
||||||
plugin.register_input(input_map, .K, proc "c" (plugin: Plugin) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
|
|
||||||
win := cast(^BufferListWindow)plugin.get_window();
|
|
||||||
if win != nil {
|
|
||||||
if win.selected_index > 0 {
|
|
||||||
win.selected_index -= 1;
|
|
||||||
} else {
|
|
||||||
win.selected_index = plugin.buffer.get_num_buffers()-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, "move selection up");
|
|
||||||
plugin.register_input(input_map, .J, proc "c" (plugin: Plugin) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
|
|
||||||
win := cast(^BufferListWindow)plugin.get_window();
|
|
||||||
if win != nil {
|
|
||||||
if win.selected_index < plugin.buffer.get_num_buffers()-1 {
|
|
||||||
win.selected_index += 1;
|
|
||||||
} else {
|
|
||||||
win.selected_index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, "move selection down");
|
|
||||||
plugin.register_input(input_map, .ENTER, proc "c" (plugin: Plugin) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
|
|
||||||
win := cast(^BufferListWindow)plugin.get_window();
|
|
||||||
if win != nil {
|
|
||||||
plugin.buffer.set_current_buffer(win.selected_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.request_window_close();
|
|
||||||
}, "switch to buffer")
|
|
||||||
}, draw_buffer_window, free_buffer_window, nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
win := cast(^BufferListWindow)plugin.get_window();
|
|
||||||
if win == nil {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(win);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_list_iter :: proc(plugin: Plugin, buffer_index: ^int) -> (int, int, bool) {
|
|
||||||
if buffer_index^ == -1 {
|
|
||||||
return 0, 0, false;
|
|
||||||
}
|
|
||||||
|
|
||||||
index := plugin.iter.get_buffer_list_iter(buffer_index);
|
|
||||||
return index, 0, true;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
|
||||||
context = runtime.default_context();
|
|
||||||
runtime.free_all(context.temp_allocator);
|
|
||||||
|
|
||||||
win := cast(^BufferListWindow)win;
|
|
||||||
if win == nil {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen_width := plugin.get_screen_width();
|
|
||||||
screen_height := plugin.get_screen_height();
|
|
||||||
directory := string(plugin.get_current_directory());
|
|
||||||
|
|
||||||
canvas := plugin.ui.floating(plugin.ui.ui_context, "buffer search canvas", {0,0});
|
|
||||||
|
|
||||||
plugin.ui.push_parent(plugin.ui.ui_context, canvas);
|
|
||||||
{
|
|
||||||
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
|
||||||
|
|
||||||
plugin.ui.spacer(plugin.ui.ui_context, "left spacer");
|
|
||||||
centered_container := plugin.ui.rect(plugin.ui.ui_context, "centered container", false, false, .Vertical, {{4, 75}, {3, 0}});
|
|
||||||
plugin.ui.push_parent(plugin.ui.ui_context, centered_container);
|
|
||||||
{
|
|
||||||
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
|
||||||
|
|
||||||
plugin.ui.spacer(plugin.ui.ui_context, "top spacer");
|
|
||||||
ui_window := plugin.ui.rect(plugin.ui.ui_context, "buffer search window", true, true, .Horizontal, {{3, 0}, {4, 75}});
|
|
||||||
plugin.ui.push_parent(plugin.ui.ui_context, ui_window);
|
|
||||||
{
|
|
||||||
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
|
||||||
|
|
||||||
buffer_list_view := plugin.ui.rect(plugin.ui.ui_context, "buffer list view", false, false, .Vertical, {{4, 60}, {3, 0}});
|
|
||||||
plugin.ui.push_parent(plugin.ui.ui_context, buffer_list_view);
|
|
||||||
{
|
|
||||||
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
|
||||||
|
|
||||||
_buffer_index := 0;
|
|
||||||
for index in buffer_list_iter(plugin, &_buffer_index) {
|
|
||||||
buffer := plugin.buffer.get_buffer_info_from_index(index);
|
|
||||||
relative_file_path, _ := filepath.rel(directory, string(buffer.file_path), context.temp_allocator)
|
|
||||||
text := fmt.ctprintf("%s:%d", relative_file_path, buffer.cursor.line+1);
|
|
||||||
|
|
||||||
if index == win.selected_index {
|
|
||||||
plugin.ui.button(plugin.ui.ui_context, text);
|
|
||||||
} else {
|
|
||||||
plugin.ui.label(plugin.ui.ui_context, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_preview := plugin.ui.rect(plugin.ui.ui_context, "buffer preview", true, false, .Horizontal, {{3, 0}, {3, 0}});
|
|
||||||
plugin.ui.push_parent(plugin.ui.ui_context, buffer_preview);
|
|
||||||
{
|
|
||||||
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
|
||||||
|
|
||||||
plugin.ui.buffer_from_index(plugin.ui.ui_context, win.selected_index, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
plugin.ui.spacer(plugin.ui.ui_context, "bottom spacer");
|
|
||||||
}
|
|
||||||
plugin.ui.spacer(plugin.ui.ui_context, "right spacer");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
screen_width := plugin.get_screen_width();
|
|
||||||
screen_height := plugin.get_screen_height();
|
|
||||||
source_font_width := plugin.get_font_width();
|
|
||||||
source_font_height := plugin.get_font_height();
|
|
||||||
|
|
||||||
win_rec := [4]f32 {
|
|
||||||
f32(screen_width/8),
|
|
||||||
f32(screen_height/8),
|
|
||||||
f32(screen_width - screen_width/4),
|
|
||||||
f32(screen_height - screen_height/4),
|
|
||||||
};
|
|
||||||
plugin.draw_rect(
|
|
||||||
i32(win_rec.x),
|
|
||||||
i32(win_rec.y),
|
|
||||||
i32(win_rec.z),
|
|
||||||
i32(win_rec.w),
|
|
||||||
.Background4
|
|
||||||
);
|
|
||||||
|
|
||||||
win_margin := [2]f32 { f32(source_font_width), f32(source_font_height) };
|
|
||||||
|
|
||||||
buffer_prev_width := (win_rec.z - win_margin.x*2) / 2;
|
|
||||||
buffer_prev_height := win_rec.w - win_margin.y*2;
|
|
||||||
|
|
||||||
glyph_buffer_width := int(buffer_prev_width) / source_font_width - 1;
|
|
||||||
glyph_buffer_height := int(buffer_prev_height) / source_font_height;
|
|
||||||
|
|
||||||
directory := string(plugin.get_current_directory());
|
|
||||||
|
|
||||||
plugin.draw_rect(
|
|
||||||
i32(win_rec.x + win_rec.z / 2),
|
|
||||||
i32(win_rec.y + win_margin.y),
|
|
||||||
i32(buffer_prev_width),
|
|
||||||
i32(buffer_prev_height),
|
|
||||||
.Background2,
|
|
||||||
);
|
|
||||||
|
|
||||||
_buffer_index := 0;
|
|
||||||
for index in buffer_list_iter(plugin, &_buffer_index) {
|
|
||||||
buffer := plugin.buffer.get_buffer_info_from_index(index);
|
|
||||||
relative_file_path, _ := filepath.rel(directory, string(buffer.file_path), context.temp_allocator)
|
|
||||||
text := fmt.ctprintf("%s:%d", relative_file_path, buffer.cursor.line+1);
|
|
||||||
text_width := len(text) * source_font_width;
|
|
||||||
|
|
||||||
if index == win.selected_index {
|
|
||||||
plugin.draw_buffer_from_index(
|
|
||||||
index,
|
|
||||||
int(win_rec.x + win_margin.x + win_rec.z / 2),
|
|
||||||
int(win_rec.y + win_margin.y),
|
|
||||||
glyph_buffer_width,
|
|
||||||
glyph_buffer_height,
|
|
||||||
false);
|
|
||||||
|
|
||||||
plugin.draw_rect(
|
|
||||||
i32(win_rec.x + win_margin.x),
|
|
||||||
i32(win_rec.y + win_margin.y) + i32(index * source_font_height),
|
|
||||||
i32(text_width),
|
|
||||||
i32(source_font_height),
|
|
||||||
.Background2,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.draw_text(
|
|
||||||
text,
|
|
||||||
win_rec.x + win_margin.x, win_rec.y + win_margin.y + f32(index * source_font_height),
|
|
||||||
.Foreground2
|
|
||||||
);
|
|
||||||
|
|
||||||
runtime.free_all(context.temp_allocator);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
local WindowOpen = true
|
|
||||||
|
|
||||||
function buffer_list_iter()
|
|
||||||
local idx = 0
|
|
||||||
return function ()
|
|
||||||
buffer_info = Editor.buffer_info_from_index(idx)
|
|
||||||
idx = idx + 1
|
|
||||||
|
|
||||||
return buffer_info, idx-1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function render_ui_window(ctx)
|
|
||||||
if WindowOpen then
|
|
||||||
current_buffer_index = Editor.get_current_buffer_index()
|
|
||||||
|
|
||||||
tabs = UI.push_rect(ctx, "tabs", false, true, UI.Vertical, UI.ChildrenSum, UI.Fill)
|
|
||||||
UI.push_parent(ctx, tabs)
|
|
||||||
for buffer_info, i in buffer_list_iter() do
|
|
||||||
button_container = UI.push_rect(ctx, "button container"..i, false, false, UI.Horizontal, UI.ChildrenSum, UI.ChildrenSum)
|
|
||||||
UI.push_parent(ctx, button_container)
|
|
||||||
flags = {"Clickable", "Hoverable", "DrawText", "DrawBackground"}
|
|
||||||
if i ~= current_buffer_index then
|
|
||||||
table.insert(flags, 1, "DrawBorder")
|
|
||||||
end
|
|
||||||
|
|
||||||
if UI.advanced_button(ctx, " "..buffer_info.file_path.." ", flags, UI.PercentOfParent(25), UI.FitText).clicked then
|
|
||||||
Editor.set_current_buffer_from_index(i)
|
|
||||||
end
|
|
||||||
if UI.advanced_button(ctx, " x ", flags, UI.FitText, UI.FitText).clicked then
|
|
||||||
print("hahah, you can't close buffers yet silly")
|
|
||||||
end
|
|
||||||
UI.pop_parent(ctx)
|
|
||||||
end
|
|
||||||
UI.pop_parent(ctx)
|
|
||||||
|
|
||||||
-- if Tabs[CurrentTab] ~= nil then
|
|
||||||
UI.buffer(ctx, current_buffer_index)
|
|
||||||
-- else
|
|
||||||
-- UI.push_parent(ctx, UI.push_centered(ctx, "centered no files open", false, false, UI.Vertical, UI.Fill, UI.Fill))
|
|
||||||
-- if UI.button(ctx, "Open File").clicked then
|
|
||||||
-- Tabs[CurrentTab] = {0, "main.odin"}
|
|
||||||
-- end
|
|
||||||
-- UI.pop_parent(ctx)
|
|
||||||
-- end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function handle_buffer_input()
|
|
||||||
print("you inputted into a buffer")
|
|
||||||
end
|
|
||||||
|
|
||||||
function OnInit()
|
|
||||||
print("Test lua plugin initialized")
|
|
||||||
Editor.register_key_group({
|
|
||||||
{Editor.Key.T, "Open Test UI", (
|
|
||||||
function ()
|
|
||||||
WindowOpen = not WindowOpen
|
|
||||||
end
|
|
||||||
)},
|
|
||||||
})
|
|
||||||
|
|
||||||
Editor.register_hook(Editor.Hook.OnDraw, render_ui_window)
|
|
||||||
Editor.register_hook(Editor.Hook.OnBufferInput, handle_buffer_input)
|
|
||||||
end
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
local BufferSearchOpen = false
|
||||||
|
local BufferSearchOpenElapsed = 0
|
||||||
|
|
||||||
|
local CurrentPreviewBufferIndex = Editor.get_current_buffer_index()
|
||||||
|
local BufferSearchIndex = 0
|
||||||
|
|
||||||
|
local SideBarWidth = 128
|
||||||
|
|
||||||
|
function buffer_list_iter()
|
||||||
|
local idx = 0
|
||||||
|
return function ()
|
||||||
|
buffer_info = Editor.buffer_info_from_index(idx)
|
||||||
|
idx = idx + 1
|
||||||
|
|
||||||
|
return buffer_info, idx-1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function centered(ctx, label, axis, width, height, body)
|
||||||
|
UI.push_parent(ctx, UI.push_rect(ctx, label, false, false, UI.Horizontal, UI.Fill, UI.Fill))
|
||||||
|
UI.spacer(ctx, "left spacer")
|
||||||
|
UI.push_parent(ctx, UI.push_rect(ctx, "halfway centered", false, false, UI.Vertical, width, UI.Fill))
|
||||||
|
UI.spacer(ctx, "top spacer")
|
||||||
|
UI.push_parent(ctx, UI.push_rect(ctx, "centered container", false, false, axis, UI.Fill, height))
|
||||||
|
body()
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
UI.spacer(ctx, "bottom spacer")
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
UI.spacer(ctx, "right spacer")
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
end
|
||||||
|
|
||||||
|
function render_ui_window(ctx)
|
||||||
|
current_buffer_index = Editor.get_current_buffer_index()
|
||||||
|
|
||||||
|
numFrames = 7
|
||||||
|
CurrentPreviewBufferIndex = current_buffer_index
|
||||||
|
|
||||||
|
tabs = UI.push_rect(ctx, "tabs", false, false, UI.Vertical, UI.Exact(SideBarWidth), UI.Fill)
|
||||||
|
UI.push_parent(ctx, tabs)
|
||||||
|
UI.push_rect(ctx, "padded top open files", false, false, UI.Horizontal, UI.Fill, UI.Exact(8))
|
||||||
|
UI.push_parent(ctx, UI.push_rect(ctx, "padded open files", false, false, UI.Horizontal, UI.Fill, UI.ChildrenSum))
|
||||||
|
UI.push_rect(ctx, "padded top open files", false, false, UI.Horizontal, UI.Exact(8), UI.Fill)
|
||||||
|
UI.label(ctx, "Open Files")
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
UI.push_rect(ctx, "padded bottom open files", false, false, UI.Horizontal, UI.Fill, UI.Exact(8))
|
||||||
|
|
||||||
|
for buffer_info, i in buffer_list_iter() do
|
||||||
|
button_container = UI.push_rect(ctx, "button container"..i, false, false, UI.Horizontal, UI.Fill, UI.ChildrenSum)
|
||||||
|
UI.push_parent(ctx, button_container)
|
||||||
|
flags = {"Clickable", "Hoverable", "DrawText"}
|
||||||
|
if i == current_buffer_index then
|
||||||
|
table.insert(flags, 1, "DrawBackground")
|
||||||
|
end
|
||||||
|
|
||||||
|
if UI.advanced_button(ctx, " x ", flags, UI.FitText, UI.FitText).clicked then
|
||||||
|
print("hahah, you can't close buffers yet silly")
|
||||||
|
end
|
||||||
|
|
||||||
|
tab_button_interaction = UI.advanced_button(ctx, " "..buffer_info.file_path.." ", flags, UI.Fill, UI.FitText)
|
||||||
|
if tab_button_interaction.clicked then
|
||||||
|
Editor.set_current_buffer_from_index(i)
|
||||||
|
end
|
||||||
|
if tab_button_interaction.hovering then
|
||||||
|
CurrentPreviewBufferIndex = i
|
||||||
|
end
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
end
|
||||||
|
UI.spacer(ctx, "below tabs spacer")
|
||||||
|
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
if UI.advanced_button(ctx, "side bar grab handle", {"DrawBorder", "Hoverable"}, UI.Exact(16), UI.Fill).dragging then
|
||||||
|
x,y = UI.get_mouse_pos(ctx)
|
||||||
|
SideBarWidth = x-8
|
||||||
|
|
||||||
|
-- TODO: use some math.max function
|
||||||
|
if SideBarWidth < 128 then
|
||||||
|
SideBarWidth = 128
|
||||||
|
end
|
||||||
|
end
|
||||||
|
UI.buffer(ctx, CurrentPreviewBufferIndex)
|
||||||
|
|
||||||
|
render_buffer_search(ctx)
|
||||||
|
end
|
||||||
|
|
||||||
|
function render_buffer_search(ctx)
|
||||||
|
if BufferSearchOpen or BufferSearchOpenElapsed > 0 then
|
||||||
|
if BufferSearchOpen and BufferSearchOpenElapsed < numFrames then
|
||||||
|
BufferSearchOpenElapsed = BufferSearchOpenElapsed + 1
|
||||||
|
elseif not BufferSearchOpen and BufferSearchOpenElapsed > 0 then
|
||||||
|
BufferSearchOpenElapsed = BufferSearchOpenElapsed - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if BufferSearchOpen or BufferSearchOpenElapsed > 0 then
|
||||||
|
window_percent = 75
|
||||||
|
if BufferSearchOpenElapsed > 0 then
|
||||||
|
window_percent = ((BufferSearchOpenElapsed/numFrames) * 75)
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.push_parent(ctx, UI.push_floating(ctx, "buffer search canvas", 0, 0))
|
||||||
|
centered(ctx, "buffer search window", UI.Horizontal, UI.PercentOfParent(window_percent), UI.PercentOfParent(window_percent), (
|
||||||
|
function ()
|
||||||
|
UI.push_parent(ctx, UI.push_rect(ctx, "window", true, true, UI.Horizontal, UI.Fill, UI.Fill))
|
||||||
|
UI.push_parent(ctx, UI.push_rect(ctx, "buffer list", false, false, UI.Vertical, UI.Fill, UI.Fill))
|
||||||
|
for buffer_info, i in buffer_list_iter() do
|
||||||
|
flags = {"DrawText"}
|
||||||
|
|
||||||
|
if i == BufferSearchIndex then
|
||||||
|
table.insert(flags, 1, "DrawBorder")
|
||||||
|
end
|
||||||
|
interaction = UI.advanced_button(ctx, " "..buffer_info.file_path.." ", flags, UI.Fill, UI.FitText)
|
||||||
|
end
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
UI.buffer(ctx, BufferSearchIndex)
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
end
|
||||||
|
))
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function handle_buffer_input()
|
||||||
|
-- print("you inputted into a buffer")
|
||||||
|
end
|
||||||
|
|
||||||
|
function OnInit()
|
||||||
|
print("Main View plugin initialized")
|
||||||
|
Editor.register_key_group({
|
||||||
|
{Editor.Key.Space, "", {
|
||||||
|
{Editor.Key.B, "Buffer Search", (
|
||||||
|
function ()
|
||||||
|
BufferSearchOpen = true
|
||||||
|
BufferSearchIndex = 0
|
||||||
|
end
|
||||||
|
),
|
||||||
|
{
|
||||||
|
{Editor.Key.Escape, "Close Window", (
|
||||||
|
function ()
|
||||||
|
Editor.request_window_close()
|
||||||
|
BufferSearchOpen = false
|
||||||
|
end
|
||||||
|
)},
|
||||||
|
{Editor.Key.Enter, "Switch to Buffer", (
|
||||||
|
function ()
|
||||||
|
Editor.set_current_buffer_from_index(BufferSearchIndex)
|
||||||
|
Editor.request_window_close()
|
||||||
|
BufferSearchOpen = false
|
||||||
|
end
|
||||||
|
)},
|
||||||
|
-- TODO: don't scroll past buffers
|
||||||
|
{Editor.Key.K, "Move Selection Up", (function () BufferSearchIndex = BufferSearchIndex - 1 end)},
|
||||||
|
{Editor.Key.J, "Move Selection Down", (function () BufferSearchIndex = BufferSearchIndex + 1 end)},
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
})
|
||||||
|
|
||||||
|
Editor.register_hook(Editor.Hook.OnDraw, render_ui_window)
|
||||||
|
Editor.register_hook(Editor.Hook.OnBufferInput, handle_buffer_input)
|
||||||
|
end
|
|
@ -37,8 +37,9 @@ close_window_and_free :: proc(state: ^State) {
|
||||||
free(state.window);
|
free(state.window);
|
||||||
|
|
||||||
state.window = nil;
|
state.window = nil;
|
||||||
state.current_input_map = &state.input_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.current_input_map = &state.input_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaHookRef :: i32;
|
LuaHookRef :: i32;
|
||||||
|
@ -92,7 +93,11 @@ add_lua_hook :: proc(state: ^State, hook: plugin.Hook, hook_ref: LuaHookRef) {
|
||||||
|
|
||||||
runtime.append(&state.lua_hooks[hook], hook_ref);
|
runtime.append(&state.lua_hooks[hook], hook_ref);
|
||||||
}
|
}
|
||||||
LuaEditorAction :: i32;
|
|
||||||
|
LuaEditorAction :: struct {
|
||||||
|
fn_ref: i32,
|
||||||
|
maybe_input_map: InputMap,
|
||||||
|
};
|
||||||
PluginEditorAction :: proc "c" (plugin: plugin.Plugin);
|
PluginEditorAction :: proc "c" (plugin: plugin.Plugin);
|
||||||
EditorAction :: proc(state: ^State);
|
EditorAction :: proc(state: ^State);
|
||||||
InputGroup :: union {LuaEditorAction, PluginEditorAction, EditorAction, InputMap}
|
InputGroup :: union {LuaEditorAction, PluginEditorAction, EditorAction, InputMap}
|
||||||
|
|
|
@ -771,10 +771,8 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, sho
|
||||||
// draw cursor
|
// draw cursor
|
||||||
if state.mode == .Normal {
|
if state.mode == .Normal {
|
||||||
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Background4);
|
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Background4);
|
||||||
//raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Background4));
|
|
||||||
} else if state.mode == .Insert {
|
} else if state.mode == .Insert {
|
||||||
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Green);
|
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Green);
|
||||||
// raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Green));
|
|
||||||
|
|
||||||
num_line_break := 0;
|
num_line_break := 0;
|
||||||
line_length := 0;
|
line_length := 0;
|
||||||
|
@ -795,7 +793,6 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, sho
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Blue);
|
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Blue);
|
||||||
//raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Blue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for j in 0..<buffer.glyph_buffer_height {
|
for j in 0..<buffer.glyph_buffer_height {
|
||||||
|
@ -803,7 +800,6 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, sho
|
||||||
|
|
||||||
if show_line_numbers {
|
if show_line_numbers {
|
||||||
draw_text(state, fmt.tprintf("%d", begin + j + 1), x, text_y);
|
draw_text(state, fmt.tprintf("%d", begin + j + 1), x, text_y);
|
||||||
//raylib.DrawTextEx(font, raylib.TextFormat("%d", begin + j + 1), raylib.Vector2 { f32(x), f32(text_y) }, f32(state.source_font_height), 0, theme.get_palette_raylib_color(.Background4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..<buffer.glyph_buffer_width {
|
for i in 0..<buffer.glyph_buffer_width {
|
||||||
|
@ -813,7 +809,6 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, sho
|
||||||
if glyph.codepoint == 0 { break; }
|
if glyph.codepoint == 0 { break; }
|
||||||
|
|
||||||
draw_codepoint(state, rune(glyph.codepoint), text_x, text_y, glyph.color);
|
draw_codepoint(state, rune(glyph.codepoint), text_x, text_y, glyph.color);
|
||||||
//raylib.DrawTextCodepoint(font, rune(glyph.codepoint), raylib.Vector2 { f32(text_x), f32(text_y) }, f32(state.source_font_height), theme.get_palette_raylib_color(glyph.color));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
412
src/main.odin
412
src/main.odin
|
@ -64,7 +64,7 @@ do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||||
|
|
||||||
// TODO: use buffer list in state
|
// TODO: use buffer list in state
|
||||||
do_insert_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
do_insert_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||||
key := 0; // raylib.GetCharPressed();
|
key := 0;
|
||||||
|
|
||||||
for key > 0 {
|
for key > 0 {
|
||||||
if key >= 32 && key <= 125 && len(buffer.input_buffer) < 1024-1 {
|
if key >= 32 && key <= 125 && len(buffer.input_buffer) < 1024-1 {
|
||||||
|
@ -75,39 +75,10 @@ do_insert_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
key = 0; // raylib.GetCharPressed();
|
key = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if raylib.IsKeyPressed(.ENTER) {
|
|
||||||
// append(&buffer.input_buffer, '\n');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if raylib.IsKeyPressed(.ESCAPE) {
|
|
||||||
// state.mode = .Normal;
|
|
||||||
|
|
||||||
// core.insert_content(buffer, buffer.input_buffer[:]);
|
|
||||||
// runtime.clear(&buffer.input_buffer);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if raylib.IsKeyPressed(.BACKSPACE) {
|
|
||||||
// core.delete_content(buffer, 1);
|
|
||||||
|
|
||||||
// for hook_proc in state.hooks[plugin.Hook.BufferInput] {
|
|
||||||
// hook_proc(state.plugin_vtable, buffer);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch_to_buffer :: proc(state: ^State, item: ^ui.MenuBarItem) {
|
|
||||||
// for buffer, index in state.buffers {
|
|
||||||
// if strings.compare(buffer.file_path, item.text) == 0 {
|
|
||||||
// state.current_buffer = index;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
register_default_leader_actions :: proc(input_map: ^core.InputMap) {
|
register_default_leader_actions :: proc(input_map: ^core.InputMap) {
|
||||||
core.register_key_action(input_map, .Q, proc(state: ^State) {
|
core.register_key_action(input_map, .Q, proc(state: ^State) {
|
||||||
state.current_input_map = &state.input_map;
|
state.current_input_map = &state.input_map;
|
||||||
|
@ -163,26 +134,19 @@ register_default_input_actions :: proc(input_map: ^core.InputMap) {
|
||||||
// Scale font size
|
// Scale font size
|
||||||
{
|
{
|
||||||
core.register_ctrl_key_action(input_map, .MINUS, proc(state: ^State) {
|
core.register_ctrl_key_action(input_map, .MINUS, proc(state: ^State) {
|
||||||
fmt.print("You pressed <C>-MINUS", state.source_font_height, " ");
|
|
||||||
if state.source_font_height > 16 {
|
if state.source_font_height > 16 {
|
||||||
state.source_font_height -= 2;
|
state.source_font_height -= 2;
|
||||||
state.source_font_width = state.source_font_height / 2;
|
state.source_font_width = state.source_font_height / 2;
|
||||||
|
|
||||||
state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf");
|
state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf");
|
||||||
//state.font = raylib.LoadFontEx("/System/Library/Fonts/Supplemental/Andale Mono.ttf", i32(state.source_font_height*2), nil, 0);
|
|
||||||
//raylib.SetTextureFilter(state.font.texture, .BILINEAR);
|
|
||||||
}
|
}
|
||||||
fmt.println(state.source_font_height);
|
fmt.println(state.source_font_height);
|
||||||
}, "increase font size");
|
}, "increase font size");
|
||||||
core.register_ctrl_key_action(input_map, .EQUAL, proc(state: ^State) {
|
core.register_ctrl_key_action(input_map, .EQUAL, proc(state: ^State) {
|
||||||
fmt.println("You pressed <C>-EQUAL");
|
|
||||||
|
|
||||||
state.source_font_height += 2;
|
state.source_font_height += 2;
|
||||||
state.source_font_width = state.source_font_height / 2;
|
state.source_font_width = state.source_font_height / 2;
|
||||||
|
|
||||||
state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf");
|
state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf");
|
||||||
//state.font = raylib.LoadFontEx("/System/Library/Fonts/Supplemental/Andale Mono.ttf", i32(state.source_font_height*2), nil, 0);
|
|
||||||
//raylib.SetTextureFilter(state.font.texture, .BILINEAR);
|
|
||||||
}, "decrease font size");
|
}, "decrease font size");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,21 +446,11 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
|
||||||
core.draw_rect(&state, int(x), int(y), int(width), int(height), color);
|
core.draw_rect(&state, int(x), int(y), int(width), int(height), color);
|
||||||
//raylib.DrawRectangle(x, y, width, height, theme.get_palette_raylib_color(color));
|
|
||||||
},
|
},
|
||||||
draw_text = proc "c" (text: cstring, x: f32, y: f32, color: theme.PaletteColor) {
|
draw_text = proc "c" (text: cstring, x: f32, y: f32, color: theme.PaletteColor) {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
|
||||||
core.draw_text(&state, string(text), int(x), int(y), color);
|
core.draw_text(&state, string(text), int(x), int(y), color);
|
||||||
// for codepoint, index in text {
|
|
||||||
// raylib.DrawTextCodepoint(
|
|
||||||
// state.font,
|
|
||||||
// rune(codepoint),
|
|
||||||
// raylib.Vector2 { x + f32(index * state.source_font_width), y },
|
|
||||||
// f32(state.source_font_height),
|
|
||||||
// theme.get_palette_raylib_color(color)
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
draw_buffer_from_index = proc "c" (buffer_index: int, x: int, y: int, glyph_buffer_width: int, glyph_buffer_height: int, show_line_numbers: bool) {
|
draw_buffer_from_index = proc "c" (buffer_index: int, x: int, y: int, glyph_buffer_width: int, glyph_buffer_height: int, show_line_numbers: bool) {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
@ -1103,24 +1057,6 @@ main :: proc() {
|
||||||
return i32(lua.OK);
|
return i32(lua.OK);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
lua.L_Reg {
|
|
||||||
"register_key_action",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
key := lua.L_checkinteger(L, 1);
|
|
||||||
|
|
||||||
lua.L_checktype(L, 2, i32(lua.TFUNCTION));
|
|
||||||
lua.pushvalue(L, 2);
|
|
||||||
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
|
||||||
|
|
||||||
desc := strings.clone(string(lua.L_checkstring(L, 3)));
|
|
||||||
|
|
||||||
core.register_key_action_group(&state.input_map, plugin.Key(key), fn_ref, desc);
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
lua.L_Reg {
|
||||||
"register_key_group",
|
"register_key_group",
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
@ -1167,7 +1103,15 @@ main :: proc() {
|
||||||
|
|
||||||
case i32(lua.TFUNCTION):
|
case i32(lua.TFUNCTION):
|
||||||
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
||||||
core.register_key_action_group(input_map, key, fn_ref, desc);
|
|
||||||
|
if lua.rawgeti(L, -1, 4) == i32(lua.TTABLE) {
|
||||||
|
maybe_input_map := core.new_input_map();
|
||||||
|
table_to_action(L, lua.gettop(L), &maybe_input_map);
|
||||||
|
|
||||||
|
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, maybe_input_map }, desc);
|
||||||
|
} else {
|
||||||
|
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, core.InputMap {} }, desc);
|
||||||
|
}
|
||||||
|
|
||||||
case:
|
case:
|
||||||
lua.pop(L, 1);
|
lua.pop(L, 1);
|
||||||
|
@ -1177,32 +1121,15 @@ main :: proc() {
|
||||||
|
|
||||||
table_to_action(L, 1, state.current_input_map);
|
table_to_action(L, 1, state.current_input_map);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"request_window_close",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
// key := plugin.Key(lua.L_checkinteger(L, 1));
|
core.request_window_close(&state);
|
||||||
|
|
||||||
// lua.L_checktype(L, 2, i32(lua.TFUNCTION));
|
|
||||||
// lua.pushvalue(L, 2);
|
|
||||||
// fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
|
||||||
|
|
||||||
// desc := strings.clone(string(lua.L_checkstring(L, 3)));
|
|
||||||
|
|
||||||
// fmt.println("LUA: attempting to register:", key, "ref", fn_ref);
|
|
||||||
|
|
||||||
// if action, exists := state.current_input_map.key_actions[key]; exists {
|
|
||||||
// switch value in action.action {
|
|
||||||
// case core.LuaEditorAction:
|
|
||||||
// fmt.eprintln("Plugin attempted to register input group on existing key action (added from Lua)");
|
|
||||||
// case core.PluginEditorAction:
|
|
||||||
// fmt.eprintln("Plugin attempted to register input group on existing key action (added from Plugin)");
|
|
||||||
// case core.EditorAction:
|
|
||||||
// fmt.eprintln("Plugin attempted to register input group on existing key action");
|
|
||||||
// case core.InputMap:
|
|
||||||
// input_map := &(&state.current_input_map.key_actions[key]).action.(core.InputMap);
|
|
||||||
// core.register_key_action_group(input_map, key, fn_ref, desc);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// core.register_key_action(state.current_input_map, key, core.new_input_map(), desc);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
return i32(lua.OK);
|
||||||
}
|
}
|
||||||
|
@ -1303,13 +1230,43 @@ main :: proc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
push_lua_box_interaction :: proc(L: ^lua.State, interaction: ui.Interaction) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushboolean(L, b32(interaction.clicked));
|
||||||
|
lua.setfield(L, -2, "clicked");
|
||||||
|
|
||||||
|
lua.pushboolean(L, b32(interaction.hovering));
|
||||||
|
lua.setfield(L, -2, "hovering");
|
||||||
|
|
||||||
|
lua.pushboolean(L, b32(interaction.dragging));
|
||||||
|
lua.setfield(L, -2, "dragging");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ui_lib := [?]lua.L_Reg {
|
ui_lib := [?]lua.L_Reg {
|
||||||
|
lua.L_Reg {
|
||||||
|
"get_mouse_pos",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_x));
|
||||||
|
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_y));
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
},
|
||||||
lua.L_Reg {
|
lua.L_Reg {
|
||||||
"Exact",
|
"Exact",
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
|
||||||
value := lua.L_checkinteger(L, 1);
|
value := lua.L_checknumber(L, 1);
|
||||||
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Exact, int(value) });
|
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Exact, int(value) });
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1320,7 +1277,7 @@ main :: proc() {
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
|
||||||
value := lua.L_checkinteger(L, 1);
|
value := lua.L_checknumber(L, 1);
|
||||||
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.PercentOfParent, int(value) });
|
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.PercentOfParent, int(value) });
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1372,7 +1329,7 @@ main :: proc() {
|
||||||
x := int(lua.L_checkinteger(L, 3));
|
x := int(lua.L_checkinteger(L, 3));
|
||||||
y := int(lua.L_checkinteger(L, 4));
|
y := int(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
box := ui.push_floating(ui_ctx, strings.clone(string(label)), {x,y});
|
box := ui.push_floating(ui_ctx, strings.clone(string(label), context.temp_allocator), {x,y});
|
||||||
lua.pushlightuserdata(L, box);
|
lua.pushlightuserdata(L, box);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1397,7 +1354,7 @@ main :: proc() {
|
||||||
semantic_width := get_lua_semantic_size(L, 6);
|
semantic_width := get_lua_semantic_size(L, 6);
|
||||||
semantic_height := get_lua_semantic_size(L, 7);
|
semantic_height := get_lua_semantic_size(L, 7);
|
||||||
|
|
||||||
box := ui.push_rect(ui_ctx, strings.clone(string(label)), background, border, axis, { semantic_width, semantic_height });
|
box := ui.push_rect(ui_ctx, strings.clone(string(label), context.temp_allocator), background, border, axis, { semantic_width, semantic_height });
|
||||||
lua.pushlightuserdata(L, box);
|
lua.pushlightuserdata(L, box);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1423,7 +1380,7 @@ main :: proc() {
|
||||||
semantic_width := get_lua_semantic_size(L, 6);
|
semantic_width := get_lua_semantic_size(L, 6);
|
||||||
semantic_height := get_lua_semantic_size(L, 7);
|
semantic_height := get_lua_semantic_size(L, 7);
|
||||||
|
|
||||||
box := ui.push_centered(ui_ctx, strings.clone(string(label)), {.DrawBackground if background else nil, .DrawBorder if border else nil}, axis, { semantic_width, semantic_height });
|
box := ui.push_centered(ui_ctx, strings.clone(string(label), context.temp_allocator), {.DrawBackground if background else nil, .DrawBorder if border else nil}, axis, { semantic_width, semantic_height });
|
||||||
lua.pushlightuserdata(L, box);
|
lua.pushlightuserdata(L, box);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1442,14 +1399,30 @@ main :: proc() {
|
||||||
if ui_ctx != nil {
|
if ui_ctx != nil {
|
||||||
label := lua.L_checkstring(L, 2);
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
interaction := ui.spacer(ui_ctx, strings.clone(string(label)), semantic_size = {{.Exact, 8}, {.Fill, 0}});
|
interaction := ui.spacer(ui_ctx, strings.clone(string(label), context.temp_allocator), semantic_size = {{.Fill, 0}, {.Fill, 0}});
|
||||||
|
|
||||||
lua.newtable(L);
|
push_lua_box_interaction(L, interaction)
|
||||||
{
|
|
||||||
lua.pushboolean(L, b32(interaction.clicked));
|
return 1;
|
||||||
lua.setfield(L, -2, "clicked");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"label",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.label(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1467,13 +1440,8 @@ main :: proc() {
|
||||||
if ui_ctx != nil {
|
if ui_ctx != nil {
|
||||||
label := lua.L_checkstring(L, 2);
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
interaction := ui.button(ui_ctx, strings.clone(string(label)));
|
interaction := ui.button(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushboolean(L, b32(interaction.clicked));
|
|
||||||
lua.setfield(L, -2, "clicked");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1497,13 +1465,8 @@ main :: proc() {
|
||||||
semantic_width := get_lua_semantic_size(L, 4);
|
semantic_width := get_lua_semantic_size(L, 4);
|
||||||
semantic_height := get_lua_semantic_size(L, 5);
|
semantic_height := get_lua_semantic_size(L, 5);
|
||||||
|
|
||||||
interaction := ui.advanced_button(ui_ctx, strings.clone(string(label)), flags, { semantic_width, semantic_height });
|
interaction := ui.advanced_button(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, { semantic_width, semantic_height });
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushboolean(L, b32(interaction.clicked));
|
|
||||||
lua.setfield(L, -2, "clicked");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1540,6 +1503,9 @@ main :: proc() {
|
||||||
lua.newtable(L);
|
lua.newtable(L);
|
||||||
{
|
{
|
||||||
lua.newtable(L);
|
lua.newtable(L);
|
||||||
|
lua.pushinteger(L, lua.Integer(plugin.Key.B));
|
||||||
|
lua.setfield(L, -2, "B");
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(plugin.Key.T));
|
lua.pushinteger(L, lua.Integer(plugin.Key.T));
|
||||||
lua.setfield(L, -2, "T");
|
lua.setfield(L, -2, "T");
|
||||||
|
|
||||||
|
@ -1552,6 +1518,21 @@ main :: proc() {
|
||||||
lua.pushinteger(L, lua.Integer(plugin.Key.M));
|
lua.pushinteger(L, lua.Integer(plugin.Key.M));
|
||||||
lua.setfield(L, -2, "M");
|
lua.setfield(L, -2, "M");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(plugin.Key.K));
|
||||||
|
lua.setfield(L, -2, "K");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(plugin.Key.J));
|
||||||
|
lua.setfield(L, -2, "J");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(plugin.Key.Q));
|
||||||
|
lua.setfield(L, -2, "Q");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(plugin.Key.ESCAPE));
|
||||||
|
lua.setfield(L, -2, "Escape");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(plugin.Key.ENTER));
|
||||||
|
lua.setfield(L, -2, "Enter");
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(plugin.Key.SPACE));
|
lua.pushinteger(L, lua.Integer(plugin.Key.SPACE));
|
||||||
lua.setfield(L, -2, "Space");
|
lua.setfield(L, -2, "Space");
|
||||||
}
|
}
|
||||||
|
@ -1586,7 +1567,7 @@ main :: proc() {
|
||||||
lua.setglobal(L, "UI");
|
lua.setglobal(L, "UI");
|
||||||
}
|
}
|
||||||
|
|
||||||
if lua.L_dofile(L, "plugins/lua/lib.lua") == i32(lua.OK) {
|
if lua.L_dofile(L, "plugins/lua/view.lua") == i32(lua.OK) {
|
||||||
lua.pop(L, lua.gettop(L));
|
lua.pop(L, lua.gettop(L));
|
||||||
} else {
|
} else {
|
||||||
err := lua.tostring(L, lua.gettop(L));
|
err := lua.tostring(L, lua.gettop(L));
|
||||||
|
@ -1611,115 +1592,110 @@ main :: proc() {
|
||||||
|
|
||||||
control_key_pressed: bool;
|
control_key_pressed: bool;
|
||||||
for !state.should_close {
|
for !state.should_close {
|
||||||
if true {
|
// if false {
|
||||||
buffer := &state.buffers[state.current_buffer];
|
// buffer := &state.buffers[state.current_buffer];
|
||||||
|
|
||||||
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)}));
|
// 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);
|
// 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)}));
|
// 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);
|
// defer ui.pop_parent(&ui_context);
|
||||||
|
|
||||||
if ui.label(&ui_context, "Editor").clicked {
|
// if ui.label(&ui_context, "Editor").clicked {
|
||||||
fmt.println("you clicked the button");
|
// fmt.println("you clicked the button");
|
||||||
}
|
// }
|
||||||
|
|
||||||
ui.push_box(
|
// ui.push_box(
|
||||||
&ui_context,
|
// &ui_context,
|
||||||
"nav spacer",
|
// "nav spacer",
|
||||||
{.DrawBackground},
|
// {.DrawBackground},
|
||||||
semantic_size = {
|
// semantic_size = {
|
||||||
ui.make_semantic_size(.Exact, 16),
|
// ui.make_semantic_size(.Exact, 16),
|
||||||
ui.make_semantic_size(.Exact, state.source_font_height)
|
// ui.make_semantic_size(.Exact, state.source_font_height)
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
|
||||||
if ui.label(&ui_context, "Buffers").clicked {
|
// if ui.label(&ui_context, "Buffers").clicked {
|
||||||
fmt.println("you clicked the button");
|
// 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)}));
|
// 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);
|
// 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)}));
|
// 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);
|
// defer ui.pop_parent(&ui_context);
|
||||||
|
|
||||||
{
|
// {
|
||||||
if ui_file_buffer(&ui_context, &state.buffers[0]).clicked {
|
// if ui_file_buffer(&ui_context, &state.buffers[0]).clicked {
|
||||||
state.current_buffer = 0;
|
// state.current_buffer = 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
{
|
// {
|
||||||
if ui_file_buffer(&ui_context, &state.buffers[0+1]).clicked {
|
// if ui_file_buffer(&ui_context, &state.buffers[0+1]).clicked {
|
||||||
state.current_buffer = 1;
|
// state.current_buffer = 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
{
|
// {
|
||||||
if ui_file_buffer(&ui_context, &state.buffers[0+2]).clicked {
|
// if ui_file_buffer(&ui_context, &state.buffers[0+2]).clicked {
|
||||||
state.current_buffer = 2;
|
// 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)}));
|
// 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);
|
// defer ui.pop_parent(&ui_context);
|
||||||
|
|
||||||
{
|
// {
|
||||||
if ui_file_buffer(&ui_context, &state.buffers[state.current_buffer]).clicked {
|
// if ui_file_buffer(&ui_context, &state.buffers[state.current_buffer]).clicked {
|
||||||
state.current_buffer = 3;
|
// 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)}));
|
// 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);
|
// defer ui.pop_parent(&ui_context);
|
||||||
|
|
||||||
label := "";
|
// label := "";
|
||||||
if state.mode == .Insert {
|
// if state.mode == .Insert {
|
||||||
label = "INSERT";
|
// label = "INSERT";
|
||||||
} else if state.mode == .Normal {
|
// } else if state.mode == .Normal {
|
||||||
label = "NORMAL";
|
// label = "NORMAL";
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ui.label(&ui_context, label).clicked {
|
// if ui.label(&ui_context, label).clicked {
|
||||||
fmt.println("you clicked the button");
|
// 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)});
|
// 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)
|
// relative_file_path, _ := filepath.rel(state.directory, buffer.file_path, context.temp_allocator)
|
||||||
ui.label(&ui_context, relative_file_path);
|
// ui.label(&ui_context, relative_file_path);
|
||||||
|
|
||||||
ui.spacer(&ui_context, "stats inbetween");
|
// ui.spacer(&ui_context, "stats inbetween");
|
||||||
|
|
||||||
{
|
// {
|
||||||
ui.push_parent(&ui_context, ui.push_box(&ui_context, "center info", {}, semantic_size = ui.ChildrenSum));
|
// ui.push_parent(&ui_context, ui.push_box(&ui_context, "center info", {}, semantic_size = ui.ChildrenSum));
|
||||||
defer ui.pop_parent(&ui_context);
|
// defer ui.pop_parent(&ui_context);
|
||||||
|
|
||||||
line_info_text := fmt.tprintf(
|
// line_info_text := fmt.tprintf(
|
||||||
//"Line: %d, Col: %d, Len: %d --- Slice Index: %d, Content Index: %d",
|
// //"Line: %d, Col: %d, Len: %d --- Slice Index: %d, Content Index: %d",
|
||||||
"Line: %d, Col: %d",
|
// "Line: %d, Col: %d",
|
||||||
buffer.cursor.line + 1,
|
// buffer.cursor.line + 1,
|
||||||
buffer.cursor.col + 1,
|
// buffer.cursor.col + 1,
|
||||||
//core.file_buffer_line_length(buffer, buffer.cursor.index),
|
// //core.file_buffer_line_length(buffer, buffer.cursor.index),
|
||||||
// buffer.cursor.index.slice_index,
|
// // buffer.cursor.index.slice_index,
|
||||||
// buffer.cursor.index.content_index,
|
// // buffer.cursor.index.content_index,
|
||||||
);
|
// );
|
||||||
ui.label(&ui_context, line_info_text);
|
// ui.label(&ui_context, line_info_text);
|
||||||
|
|
||||||
mouse_pos_str := fmt.tprintf("x,y: [%d,%d]", ui_context.mouse_x, ui_context.mouse_y);
|
// mouse_pos_str := fmt.tprintf("x,y: [%d,%d]", ui_context.mouse_x, ui_context.mouse_y);
|
||||||
ui.label(&ui_context, mouse_pos_str);
|
// ui.label(&ui_context, mouse_pos_str);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
//ui.spacer(&ui_context, "frame time spacer");
|
// }
|
||||||
//frame_time := (60.0/f32(raylib.GetFPS())) * 10;
|
|
||||||
//frame_time_text := raylib.TextFormat("frame time: %fms", frame_time);
|
|
||||||
//ui.label(&ui_context, "lol have to figure out how to get the frame time");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for hook_ref in state.lua_hooks[plugin.Hook.Draw] {
|
for hook_ref in state.lua_hooks[plugin.Hook.Draw] {
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
||||||
|
@ -1779,8 +1755,7 @@ main :: proc() {
|
||||||
if action, exists := state.current_input_map.ctrl_key_actions[key]; exists {
|
if action, exists := state.current_input_map.ctrl_key_actions[key]; exists {
|
||||||
switch value in action.action {
|
switch value in action.action {
|
||||||
case core.LuaEditorAction:
|
case core.LuaEditorAction:
|
||||||
fmt.println("trying to call lua registered function:", value);
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref));
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value));
|
|
||||||
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
||||||
err := lua.tostring(L, lua.gettop(L));
|
err := lua.tostring(L, lua.gettop(L));
|
||||||
lua.pop(L, lua.gettop(L));
|
lua.pop(L, lua.gettop(L));
|
||||||
|
@ -1789,6 +1764,10 @@ main :: proc() {
|
||||||
} else {
|
} else {
|
||||||
lua.pop(L, lua.gettop(L));
|
lua.pop(L, lua.gettop(L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value.maybe_input_map.ctrl_key_actions != nil {
|
||||||
|
|
||||||
|
}
|
||||||
case core.PluginEditorAction:
|
case core.PluginEditorAction:
|
||||||
value(state.plugin_vtable);
|
value(state.plugin_vtable);
|
||||||
case core.EditorAction:
|
case core.EditorAction:
|
||||||
|
@ -1801,7 +1780,7 @@ main :: proc() {
|
||||||
if action, exists := state.current_input_map.key_actions[key]; exists {
|
if action, exists := state.current_input_map.key_actions[key]; exists {
|
||||||
switch value in action.action {
|
switch value in action.action {
|
||||||
case core.LuaEditorAction:
|
case core.LuaEditorAction:
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value));
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref));
|
||||||
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
||||||
err := lua.tostring(L, lua.gettop(L));
|
err := lua.tostring(L, lua.gettop(L));
|
||||||
lua.pop(L, lua.gettop(L));
|
lua.pop(L, lua.gettop(L));
|
||||||
|
@ -1810,6 +1789,11 @@ main :: proc() {
|
||||||
} else {
|
} else {
|
||||||
lua.pop(L, lua.gettop(L));
|
lua.pop(L, lua.gettop(L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value.maybe_input_map.key_actions != nil {
|
||||||
|
ptr_action := &(&state.current_input_map.key_actions[key]).action.(core.LuaEditorAction)
|
||||||
|
state.current_input_map = (&ptr_action.maybe_input_map)
|
||||||
|
}
|
||||||
case core.PluginEditorAction:
|
case core.PluginEditorAction:
|
||||||
value(state.plugin_vtable);
|
value(state.plugin_vtable);
|
||||||
case core.EditorAction:
|
case core.EditorAction:
|
||||||
|
|
|
@ -98,7 +98,7 @@ light_palette := []u32 {
|
||||||
get_palette_color :: proc(palette_color: PaletteColor) -> [4]u8 {
|
get_palette_color :: proc(palette_color: PaletteColor) -> [4]u8 {
|
||||||
color: [4]u8;
|
color: [4]u8;
|
||||||
|
|
||||||
c := palette[palette_color];
|
c := light_palette[palette_color];
|
||||||
for i in 0..<4 {
|
for i in 0..<4 {
|
||||||
color[i] = u8((c >> (8*u32(3-i)))&0xff);
|
color[i] = u8((c >> (8*u32(3-i)))&0xff);
|
||||||
}
|
}
|
||||||
|
|
148
src/ui/imm.odin
148
src/ui/imm.odin
|
@ -40,6 +40,7 @@ Key :: struct {
|
||||||
Interaction :: struct {
|
Interaction :: struct {
|
||||||
hovering: bool,
|
hovering: bool,
|
||||||
clicked: bool,
|
clicked: bool,
|
||||||
|
dragging: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
Flag :: enum {
|
Flag :: enum {
|
||||||
|
@ -115,11 +116,11 @@ init :: proc(renderer: ^sdl2.Renderer) -> Context {
|
||||||
gen_key :: proc(ctx: ^Context, label: string, value: int) -> Key {
|
gen_key :: proc(ctx: ^Context, label: string, value: int) -> Key {
|
||||||
key_label := ""
|
key_label := ""
|
||||||
if ctx != nil && (ctx.current_parent == nil || len(ctx.current_parent.key.label) < 1) {
|
if ctx != nil && (ctx.current_parent == nil || len(ctx.current_parent.key.label) < 1) {
|
||||||
key_label = strings.clone(label);
|
key_label = label;
|
||||||
} else if ctx != nil {
|
} else if ctx != nil {
|
||||||
key_label = fmt.aprintf("%s:%s", ctx.current_parent.key.label, label);
|
key_label = fmt.tprintf("%s:%s", ctx.current_parent.key.label, label);
|
||||||
} else {
|
} else {
|
||||||
key_label = fmt.aprintf("%s",label);
|
key_label = fmt.tprintf("%s",label);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Key {
|
return Key {
|
||||||
|
@ -233,15 +234,22 @@ test_box :: proc(ctx: ^Context, box: ^Box) -> Interaction {
|
||||||
hovering = true;
|
hovering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if hovering {
|
if hovering || box.active > 0 {
|
||||||
box.hot += 1;
|
box.hot += 1;
|
||||||
} else {
|
} else {
|
||||||
box.hot = 0;
|
box.hot = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hovering && mouse_is_clicked {
|
||||||
|
box.active += 1;
|
||||||
|
} else if !ctx.mouse_left_down {
|
||||||
|
box.active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return Interaction {
|
return Interaction {
|
||||||
hovering = hovering,
|
hovering = hovering || box.active > 0,
|
||||||
clicked = hovering && mouse_is_clicked,
|
clicked = hovering && mouse_is_clicked,
|
||||||
|
dragging = box.active > 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +335,7 @@ compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font
|
||||||
}
|
}
|
||||||
|
|
||||||
if .Floating in box.flags {
|
if .Floating in box.flags {
|
||||||
// box.computed_pos = {0,0};
|
box.computed_pos = {0,0};
|
||||||
} else if box.prev != nil {
|
} else if box.prev != nil {
|
||||||
prev := prev_non_floating_sibling(ctx, box);
|
prev := prev_non_floating_sibling(ctx, box);
|
||||||
|
|
||||||
|
@ -343,34 +351,18 @@ compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font
|
||||||
} else {
|
} else {
|
||||||
switch box.semantic_size.x.kind {
|
switch box.semantic_size.x.kind {
|
||||||
case .FitText: {
|
case .FitText: {
|
||||||
// TODO: don't use hardcoded font size
|
|
||||||
box.computed_size.x = len(box.label) * font_width;
|
box.computed_size.x = len(box.label) * font_width;
|
||||||
}
|
}
|
||||||
case .Exact: {
|
case .Exact: {
|
||||||
box.computed_size.x = box.semantic_size.x.value;
|
box.computed_size.x = box.semantic_size.x.value;
|
||||||
}
|
}
|
||||||
case .ChildrenSum: {
|
case .ChildrenSum: {
|
||||||
//compute_children = false;
|
|
||||||
post_compute_size[int(Axis.Horizontal)] = true;
|
post_compute_size[int(Axis.Horizontal)] = true;
|
||||||
// box.computed_size.x = 0;
|
|
||||||
|
|
||||||
// iter := BoxIter { box.first, 0 };
|
|
||||||
// for child in iterate_box(&iter) {
|
|
||||||
// compute_layout(canvas_size, font_width, font_height, child);
|
|
||||||
|
|
||||||
// switch box.axis {
|
|
||||||
// case .Horizontal: {
|
|
||||||
// box.computed_size.x += child.computed_size.x;
|
|
||||||
// }
|
|
||||||
// case .Vertical: {
|
|
||||||
// if child.computed_size.x > box.computed_size.x {
|
|
||||||
// box.computed_size.x = child.computed_size.x;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
case .Fill: {
|
case .Fill: {
|
||||||
|
if .Floating in box.flags {
|
||||||
|
box.computed_size.x = ancestor_size(ctx, box, .Horizontal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .PercentOfParent: {
|
case .PercentOfParent: {
|
||||||
box.computed_size.x = int(f32(ancestor_size(ctx, box, .Horizontal))*(f32(box.semantic_size.x.value)/100.0));
|
box.computed_size.x = int(f32(ancestor_size(ctx, box, .Horizontal))*(f32(box.semantic_size.x.value)/100.0));
|
||||||
|
@ -378,52 +370,18 @@ compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font
|
||||||
}
|
}
|
||||||
switch box.semantic_size.y.kind {
|
switch box.semantic_size.y.kind {
|
||||||
case .FitText: {
|
case .FitText: {
|
||||||
// TODO: don't use hardcoded font size
|
|
||||||
box.computed_size.y = font_height;
|
box.computed_size.y = font_height;
|
||||||
}
|
}
|
||||||
case .Exact: {
|
case .Exact: {
|
||||||
box.computed_size.y = box.semantic_size.y.value;
|
box.computed_size.y = box.semantic_size.y.value;
|
||||||
}
|
}
|
||||||
case .ChildrenSum: {
|
case .ChildrenSum: {
|
||||||
//compute_children = false;
|
|
||||||
post_compute_size[Axis.Vertical] = true;
|
post_compute_size[Axis.Vertical] = true;
|
||||||
|
|
||||||
// should_post_compute := false;
|
|
||||||
// number_of_fills := 0;
|
|
||||||
// box.computed_size.y = 0;
|
|
||||||
// parent_size := ancestor_size(box, .Vertical);
|
|
||||||
|
|
||||||
// iter := BoxIter { box.first, 0 };
|
|
||||||
// for child in iterate_box(&iter) {
|
|
||||||
// compute_layout(canvas_size, font_width, font_height, child);
|
|
||||||
|
|
||||||
// if child.semantic_size.y.kind == .Fill {
|
|
||||||
// number_of_fills += 1;
|
|
||||||
// should_post_compute := true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// switch box.axis {
|
|
||||||
// case .Horizontal: {
|
|
||||||
// if child.computed_size.y > box.computed_size.y {
|
|
||||||
// box.computed_size.y = child.computed_size.y;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// case .Vertical: {
|
|
||||||
// box.computed_size.y += child.computed_size.y;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if should_post_compute {
|
|
||||||
// iter := BoxIter { box.first, 0 };
|
|
||||||
// for child in iterate_box(&iter) {
|
|
||||||
// if compute_layout(canvas_size, font_width, font_height, child) {
|
|
||||||
// child.computed_size.y = (parent_size - box.computed_size.y) / number_of_fills;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
case .Fill: {
|
case .Fill: {
|
||||||
|
if .Floating in box.flags {
|
||||||
|
box.computed_size.y = ancestor_size(ctx, box, .Vertical);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .PercentOfParent: {
|
case .PercentOfParent: {
|
||||||
box.computed_size.y = int(f32(ancestor_size(ctx, box, .Vertical))*(f32(box.semantic_size.y.value)/100.0));
|
box.computed_size.y = int(f32(ancestor_size(ctx, box, .Vertical))*(f32(box.semantic_size.y.value)/100.0));
|
||||||
|
@ -433,7 +391,6 @@ compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font
|
||||||
|
|
||||||
if compute_children {
|
if compute_children {
|
||||||
iter := BoxIter { box.first, 0 };
|
iter := BoxIter { box.first, 0 };
|
||||||
should_post_compute := false;
|
|
||||||
child_size: [2]int = {0,0};
|
child_size: [2]int = {0,0};
|
||||||
|
|
||||||
// NOTE: the number of fills for the opposite axis of this box needs to be 1
|
// NOTE: the number of fills for the opposite axis of this box needs to be 1
|
||||||
|
@ -451,31 +408,22 @@ compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font
|
||||||
compute_layout(ctx, canvas_size, font_width, font_height, child);
|
compute_layout(ctx, canvas_size, font_width, font_height, child);
|
||||||
if child.semantic_size[box.axis].kind == .Fill {
|
if child.semantic_size[box.axis].kind == .Fill {
|
||||||
number_of_fills[box.axis] += 1;
|
number_of_fills[box.axis] += 1;
|
||||||
should_post_compute = true;
|
|
||||||
} else {
|
} else {
|
||||||
child_size[box.axis] += child.computed_size[box.axis];
|
child_size[box.axis] += child.computed_size[box.axis];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if true || should_post_compute {
|
iter = BoxIter { box.first, 0 };
|
||||||
iter := BoxIter { box.first, 0 };
|
|
||||||
for child in iterate_box(&iter) {
|
for child in iterate_box(&iter) {
|
||||||
|
if !(.Floating in child.flags) {
|
||||||
for axis in 0..<2 {
|
for axis in 0..<2 {
|
||||||
if child.semantic_size[axis].kind == .Fill {
|
if child.semantic_size[axis].kind == .Fill {
|
||||||
if false && child_size[axis] >= our_size[axis] {
|
|
||||||
child.computed_size[axis] = our_size[axis] / number_of_fills[axis];
|
|
||||||
} else {
|
|
||||||
child.computed_size[axis] = (our_size[axis] - child_size[axis]) / number_of_fills[axis];
|
child.computed_size[axis] = (our_size[axis] - child_size[axis]) / number_of_fills[axis];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_layout(ctx, canvas_size, font_width, font_height, child);
|
compute_layout(ctx, canvas_size, font_width, font_height, child);
|
||||||
|
|
||||||
if child.label == "2" {
|
|
||||||
fmt.println(child.label, child.computed_size, box.label, our_size, child_size, number_of_fills);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,19 +494,10 @@ push_clip :: proc(ctx: ^Context, pos: [2]int, size: [2]int) {
|
||||||
i32(rect.size.y)
|
i32(rect.size.y)
|
||||||
});
|
});
|
||||||
|
|
||||||
// raylib.BeginScissorMode(
|
|
||||||
// i32(rect.pos.x),
|
|
||||||
// i32(rect.pos.y),
|
|
||||||
// i32(rect.size.x),
|
|
||||||
// i32(rect.size.y)
|
|
||||||
// );
|
|
||||||
|
|
||||||
append(&ctx.clips, rect);
|
append(&ctx.clips, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_clip :: proc(ctx: ^Context) {
|
pop_clip :: proc(ctx: ^Context) {
|
||||||
//raylib.EndScissorMode();
|
|
||||||
|
|
||||||
if len(ctx.clips) > 0 {
|
if len(ctx.clips) > 0 {
|
||||||
rect := pop(&ctx.clips);
|
rect := pop(&ctx.clips);
|
||||||
|
|
||||||
|
@ -568,12 +507,6 @@ pop_clip :: proc(ctx: ^Context) {
|
||||||
i32(rect.size.x),
|
i32(rect.size.x),
|
||||||
i32(rect.size.y)
|
i32(rect.size.y)
|
||||||
});
|
});
|
||||||
// raylib.BeginScissorMode(
|
|
||||||
// i32(rect.pos.x),
|
|
||||||
// i32(rect.pos.y),
|
|
||||||
// i32(rect.size.x),
|
|
||||||
// i32(rect.size.y)
|
|
||||||
// );
|
|
||||||
} else {
|
} else {
|
||||||
sdl2.RenderSetClipRect(ctx.renderer, nil);
|
sdl2.RenderSetClipRect(ctx.renderer, nil);
|
||||||
}
|
}
|
||||||
|
@ -582,9 +515,8 @@ pop_clip :: proc(ctx: ^Context) {
|
||||||
draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: int, box: ^Box) {
|
draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: int, box: ^Box) {
|
||||||
if box == nil { return; }
|
if box == nil { return; }
|
||||||
|
|
||||||
// NOTE: for some reason if you place this right before the
|
|
||||||
// for loop, the clipping only works for the first child. Compiler bug?
|
|
||||||
push_clip(ctx, box.computed_pos, box.computed_size);
|
push_clip(ctx, box.computed_pos, box.computed_size);
|
||||||
|
{
|
||||||
defer pop_clip(ctx);
|
defer pop_clip(ctx);
|
||||||
|
|
||||||
if .Hoverable in box.flags && box.hot > 0 {
|
if .Hoverable in box.flags && box.hot > 0 {
|
||||||
|
@ -596,8 +528,7 @@ draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: in
|
||||||
box.computed_size.y,
|
box.computed_size.y,
|
||||||
.Background2
|
.Background2
|
||||||
);
|
);
|
||||||
}
|
} else if .DrawBackground in box.flags {
|
||||||
else if .DrawBackground in box.flags {
|
|
||||||
core.draw_rect(
|
core.draw_rect(
|
||||||
state,
|
state,
|
||||||
box.computed_pos.x,
|
box.computed_pos.x,
|
||||||
|
@ -608,16 +539,6 @@ draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: in
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if .DrawBorder in box.flags {
|
|
||||||
core.draw_rect_outline(
|
|
||||||
state,
|
|
||||||
box.computed_pos.x,
|
|
||||||
box.computed_pos.y,
|
|
||||||
box.computed_size.x,
|
|
||||||
box.computed_size.y,
|
|
||||||
.Background4
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if .DrawText in box.flags {
|
if .DrawText in box.flags {
|
||||||
core.draw_text(state, box.label, box.computed_pos.x, box.computed_pos.y);
|
core.draw_text(state, box.label, box.computed_pos.x, box.computed_pos.y);
|
||||||
}
|
}
|
||||||
|
@ -630,6 +551,21 @@ draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: in
|
||||||
for child in iterate_box(&iter) {
|
for child in iterate_box(&iter) {
|
||||||
draw(ctx, state, font_width, font_height, child);
|
draw(ctx, state, font_width, font_height, child);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_clip(ctx, box.computed_pos, box.computed_size);
|
||||||
|
defer pop_clip(ctx);
|
||||||
|
|
||||||
|
if .DrawBorder in box.flags {
|
||||||
|
core.draw_rect_outline(
|
||||||
|
state,
|
||||||
|
box.computed_pos.x,
|
||||||
|
box.computed_pos.y,
|
||||||
|
box.computed_size.x,
|
||||||
|
box.computed_size.y,
|
||||||
|
.Background4
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxIter :: struct {
|
BoxIter :: struct {
|
||||||
|
@ -693,19 +629,19 @@ push_rect :: proc(ctx: ^Context, label: string, background: bool = true, border:
|
||||||
push_centered :: proc(ctx: ^Context, label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText) -> ^Box {
|
push_centered :: proc(ctx: ^Context, label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText) -> ^Box {
|
||||||
box: ^Box;
|
box: ^Box;
|
||||||
|
|
||||||
push_parent(ctx, push_box(ctx, label, {}, semantic_size = Fill))
|
push_parent(ctx, push_box(ctx, label, {}, semantic_size = { {.Fill,0}, semantic_size.y }))
|
||||||
{
|
{
|
||||||
defer pop_parent(ctx);
|
defer pop_parent(ctx);
|
||||||
|
|
||||||
spacer(ctx, "left spacer");
|
spacer(ctx, "left spacer");
|
||||||
halfway_centered := push_rect(ctx, "halfway centered", false, false, .Vertical, { semantic_size.x, {.Fill,0} });
|
halfway_centered := push_rect(ctx, "halfway centered", false, false, .Vertical, { {.Fill, 0}, {.Fill,0} });
|
||||||
|
|
||||||
push_parent(ctx, halfway_centered);
|
push_parent(ctx, halfway_centered);
|
||||||
{
|
{
|
||||||
defer pop_parent(ctx);
|
defer pop_parent(ctx);
|
||||||
|
|
||||||
spacer(ctx, "top spacer");
|
spacer(ctx, "top spacer");
|
||||||
box = push_box(ctx, label, flags, axis, { {.Fill,0}, semantic_size.y });
|
box = push_box(ctx, label, flags, axis, FitText);
|
||||||
spacer(ctx, "bottom spacer");
|
spacer(ctx, "bottom spacer");
|
||||||
}
|
}
|
||||||
spacer(ctx, "right spacer");
|
spacer(ctx, "right spacer");
|
||||||
|
|
145
src/ui/ui.odin
145
src/ui/ui.odin
|
@ -4,148 +4,3 @@ import "core:math"
|
||||||
|
|
||||||
import "../core"
|
import "../core"
|
||||||
import "../theme"
|
import "../theme"
|
||||||
|
|
||||||
// MenuBarItemOnClick :: proc(state: ^core.State, item: ^MenuBarItem);
|
|
||||||
//
|
|
||||||
// text_padding :: 4;
|
|
||||||
//
|
|
||||||
// MenuBarItem :: struct {
|
|
||||||
// text: string,
|
|
||||||
// selected: bool,
|
|
||||||
// sub_items: []MenuBarItem,
|
|
||||||
// on_click: MenuBarItemOnClick,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MenuBarState :: struct {
|
|
||||||
// items: []MenuBarItem,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// draw_menu_bar_item :: proc(state: ^core.State, item: ^MenuBarItem, x, y: i32, parent_width, parent_height: i32, font_height: int, horizontal: bool = false) {
|
|
||||||
// foreground_color := theme.PaletteColor.Foreground3;
|
|
||||||
// if horizontal {
|
|
||||||
// if item.selected {
|
|
||||||
// foreground_color = theme.PaletteColor.Background4;
|
|
||||||
// } else {
|
|
||||||
// foreground_color = theme.PaletteColor.Foreground4;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// item_text := raylib.TextFormat("%s", item.text);
|
|
||||||
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
|
||||||
//
|
|
||||||
// raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(foreground_color));
|
|
||||||
// raylib.DrawTextEx(state.font, item_text, raylib.Vector2 { f32(x + text_padding), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Background1));
|
|
||||||
//
|
|
||||||
// if item.selected {
|
|
||||||
// // TODO: change to parent_width
|
|
||||||
// largest_sub_item: int
|
|
||||||
// for sub_item in item.sub_items {
|
|
||||||
// largest_sub_item = math.max(len(sub_item.text), largest_sub_item);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this_width := i32(largest_sub_item * state.source_font_width + text_padding*2);
|
|
||||||
// sub_list_x := x;
|
|
||||||
// if horizontal {
|
|
||||||
// sub_list_x += parent_width;
|
|
||||||
// }
|
|
||||||
// for _, index in item.sub_items {
|
|
||||||
// sub_item := &item.sub_items[index];
|
|
||||||
// item_text := raylib.TextFormat("%s", sub_item.text);
|
|
||||||
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
|
||||||
//
|
|
||||||
// index_offset := 1;
|
|
||||||
// if horizontal {
|
|
||||||
// index_offset = 0;
|
|
||||||
// }
|
|
||||||
// item_y := y + i32(font_height * (index+index_offset));
|
|
||||||
// draw_menu_bar_item(state, sub_item, sub_list_x, item_y, this_width, 0, font_height, true);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// draw_menu_bar :: proc(state: ^core.State, data: ^MenuBarState, x, y: i32, parent_width, parent_height: i32, font_height: int) {
|
|
||||||
// raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(.Background3));
|
|
||||||
//
|
|
||||||
// raylib.DrawTextEx(state.font, "Editor", raylib.Vector2 { f32(x), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Foreground1));
|
|
||||||
//
|
|
||||||
// x := x + i32((len("Editor") + 4) * state.source_font_width);
|
|
||||||
//
|
|
||||||
// for _, index in data.items {
|
|
||||||
// item := &data.items[index];
|
|
||||||
// item_text := raylib.TextFormat("%s", item.text);
|
|
||||||
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
|
||||||
//
|
|
||||||
// item_x := x + (i32(item_width) + text_padding*2) * i32(index);
|
|
||||||
// draw_menu_bar_item(state, item, item_x, y, i32(item_width + text_padding*2), i32(font_height), font_height);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// test_menu_item :: proc(state: ^core.State, item: ^MenuBarItem, rect: raylib.Rectangle, mouse_pos: raylib.Vector2, mouse_has_clicked: bool, font_height: int, horizontal: bool) -> bool {
|
|
||||||
// if raylib.CheckCollisionPointRec(mouse_pos, rect) {
|
|
||||||
// item.selected = true;
|
|
||||||
//
|
|
||||||
// if item.on_click != nil && mouse_has_clicked {
|
|
||||||
// item.on_click(state, item);
|
|
||||||
// }
|
|
||||||
// } else if item.selected {
|
|
||||||
// largest_sub_item: int
|
|
||||||
// for sub_item in item.sub_items {
|
|
||||||
// largest_sub_item = math.max(len(sub_item.text), largest_sub_item);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this_width := i32(largest_sub_item * state.source_font_width + text_padding*2);
|
|
||||||
// sub_list_x := rect.x;
|
|
||||||
// if horizontal {
|
|
||||||
// sub_list_x += rect.width;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// has_sub_item_selected := false;
|
|
||||||
// for _, index in item.sub_items {
|
|
||||||
// sub_item := &item.sub_items[index];
|
|
||||||
// item_text := raylib.TextFormat("%s", sub_item.text);
|
|
||||||
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
|
||||||
//
|
|
||||||
// index_offset := 1;
|
|
||||||
// if horizontal {
|
|
||||||
// index_offset = 0;
|
|
||||||
// }
|
|
||||||
// item_y := rect.y + f32(font_height * (index+index_offset));
|
|
||||||
//
|
|
||||||
// sub_rec := raylib.Rectangle {
|
|
||||||
// x = sub_list_x,
|
|
||||||
// y = item_y,
|
|
||||||
// width = f32(this_width),
|
|
||||||
// height = f32(font_height),
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// if test_menu_item(state, sub_item, sub_rec, mouse_pos, mouse_has_clicked, font_height, true) {
|
|
||||||
// has_sub_item_selected = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// item.selected = has_sub_item_selected;
|
|
||||||
// } else {
|
|
||||||
// item.selected = false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return item.selected;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// test_menu_bar :: proc(state: ^core.State, menu_bar: ^MenuBarState, x, y: i32, mouse_pos: raylib.Vector2, mouse_has_clicked: bool, font_height: int) {
|
|
||||||
// x := x + i32((len("Editor") + 4) * state.source_font_width);
|
|
||||||
//
|
|
||||||
// for _, index in menu_bar.items {
|
|
||||||
// item := &menu_bar.items[index];
|
|
||||||
// item_text := raylib.TextFormat("%s", item.text);
|
|
||||||
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
|
||||||
//
|
|
||||||
// item_rec := raylib.Rectangle {
|
|
||||||
// x = f32(x) + (item_width + f32(text_padding*2)) * f32(index),
|
|
||||||
// y = f32(y),
|
|
||||||
// width = f32(item_width + text_padding*2),
|
|
||||||
// height = f32(font_height),
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// test_menu_item(state, item, item_rec, mouse_pos, mouse_has_clicked, font_height, false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
Loading…
Reference in New Issue