get dragging working properly with clicking
parent
187f48aa87
commit
f01eb452a9
|
@ -14,6 +14,9 @@ local CodeViews = {}
|
||||||
local MovingTab = nil
|
local MovingTab = nil
|
||||||
local MovingTabDest = nil
|
local MovingTabDest = nil
|
||||||
|
|
||||||
|
local LastMouseX = 0
|
||||||
|
local LastMouseY = 0
|
||||||
|
|
||||||
function buffer_list_iter()
|
function buffer_list_iter()
|
||||||
local idx = 0
|
local idx = 0
|
||||||
return function ()
|
return function ()
|
||||||
|
@ -42,15 +45,25 @@ function lerp(from, to, rate)
|
||||||
return (1 - rate) * from + rate*to
|
return (1 - rate) * from + rate*to
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function remove_buffer_from_code_view(code_view_index, file_path)
|
||||||
|
if code_view_index ~= nil and CodeViews[code_view_index] ~= nil then
|
||||||
|
CodeViews[code_view_index].tabs[file_path] = nil
|
||||||
|
k,v = pairs(CodeViews[code_view_index].tabs)(CodeViews[code_view_index].tabs)
|
||||||
|
CodeViews[code_view_index].current_tab = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function add_buffer_to_code_view(code_view_index, file_path, buffer_index)
|
function add_buffer_to_code_view(code_view_index, file_path, buffer_index)
|
||||||
if code_view_index == nil then
|
if code_view_index == nil then
|
||||||
code_view_index = 1
|
code_view_index = 1
|
||||||
ActiveCodeView = 1
|
ActiveCodeView = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- A new code view is being created
|
||||||
if CodeViews[code_view_index] == nil then
|
if CodeViews[code_view_index] == nil then
|
||||||
CodeViews[code_view_index] = {}
|
CodeViews[code_view_index] = {}
|
||||||
CodeViews[code_view_index].tabs = {}
|
CodeViews[code_view_index].tabs = {}
|
||||||
|
CodeViews[code_view_index].width = UI.Fill
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveCodeView = code_view_index
|
ActiveCodeView = code_view_index
|
||||||
|
@ -63,7 +76,7 @@ end
|
||||||
function ui_sidebar(ctx)
|
function ui_sidebar(ctx)
|
||||||
SideBarSmoothedWidth = lerp(SideBarSmoothedWidth, SideBarWidth, 0.3)
|
SideBarSmoothedWidth = lerp(SideBarSmoothedWidth, SideBarWidth, 0.3)
|
||||||
|
|
||||||
tabs = UI.push_rect(ctx, "for some reason it chooses this as the parent", false, false, UI.Vertical, UI.Exact(SideBarSmoothedWidth), UI.Fill)
|
tabs, _ = UI.push_rect(ctx, "for some reason it chooses this as the parent", false, false, UI.Vertical, UI.Exact(SideBarSmoothedWidth), UI.Fill)
|
||||||
UI.push_parent(ctx, tabs)
|
UI.push_parent(ctx, tabs)
|
||||||
UI.push_rect(ctx, "padded top open files", false, false, UI.Horizontal, UI.Fill, UI.Exact(8))
|
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_parent(ctx, UI.push_rect(ctx, "padded open files", false, false, UI.Horizontal, UI.Fill, UI.ChildrenSum))
|
||||||
|
@ -82,6 +95,7 @@ function ui_sidebar(ctx)
|
||||||
|
|
||||||
if UI.advanced_button(ctx, " x ", flags, UI.FitText, UI.FitText).clicked then
|
if UI.advanced_button(ctx, " x ", flags, UI.FitText, UI.FitText).clicked then
|
||||||
print("hahah, you can't close buffers yet silly")
|
print("hahah, you can't close buffers yet silly")
|
||||||
|
Editor.set_current_buffer_from_index(i)
|
||||||
add_buffer_to_code_view(ActiveCodeView+1, buffer_info.file_path, i)
|
add_buffer_to_code_view(ActiveCodeView+1, buffer_info.file_path, i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -104,71 +118,81 @@ function ui_code_view(ctx, code_view_index)
|
||||||
local code_view = CodeViews[code_view_index]
|
local code_view = CodeViews[code_view_index]
|
||||||
local is_tab_dest = MovingTab ~= nil and ActiveCodeView ~= code_view_index
|
local is_tab_dest = MovingTab ~= nil and ActiveCodeView ~= code_view_index
|
||||||
|
|
||||||
UI.push_parent(ctx, UI.push_rect(ctx, code_view_index.." code view", ActiveCodeView ~= code_view_index, true, UI.Vertical, UI.Fill, UI.Fill))
|
code_view_rect, code_view_interaction = UI.push_rect(ctx, code_view_index.." code view", ActiveCodeView ~= code_view_index, true, UI.Vertical, code_view.width, UI.Fill)
|
||||||
if is_tab_dest then
|
|
||||||
tab_dest_region = UI.push_box(ctx, "code view tab dest", {"Hoverable"}, UI.Vertical, UI.Fill, UI.Fill)
|
|
||||||
tab_dest_interaction = UI.box_interaction(ctx, tab_dest_region)
|
|
||||||
UI.push_parent(ctx, tab_dest_region)
|
|
||||||
|
|
||||||
-- if tab_dest_interaction
|
UI.push_parent(ctx, code_view_rect)
|
||||||
end
|
tab_dest_flags = {}
|
||||||
|
if is_tab_dest then tab_dest_flags = {"Hoverable"} end
|
||||||
|
|
||||||
UI.push_parent(ctx, UI.push_rect(ctx, "tabs", false, true, UI.Horizontal, UI.Fill, UI.ChildrenSum))
|
tab_dest_region, tab_dest_interaction = UI.push_box(ctx, "code view tab dest", tab_dest_flags, UI.Vertical, UI.Fill, UI.Fill)
|
||||||
for k,v in pairs(code_view.tabs) do
|
UI.push_parent(ctx, tab_dest_region)
|
||||||
show_border = v["buffer_index"] ~= code_view.current_buffer_index
|
if is_tab_dest then
|
||||||
background = not show_border
|
if tab_dest_interaction.hovering then
|
||||||
flags = {"Clickable", "Hoverable", "DrawText"}
|
MovingTabDest = code_view_index
|
||||||
|
end
|
||||||
UI.push_parent(ctx, UI.push_rect(ctx, k.." tab container", background, show_border, UI.Horizontal, UI.ChildrenSum, UI.ChildrenSum))
|
|
||||||
tab_button = UI.advanced_button(ctx, " "..k.." ", flags, UI.FitText, UI.Exact(32))
|
|
||||||
if tab_button.clicked then
|
|
||||||
ActiveCodeView = code_view_index
|
|
||||||
code_view.current_tab = k
|
|
||||||
end
|
|
||||||
|
|
||||||
local bb = "false"
|
|
||||||
if is_tab_dest then bb = "true" end
|
|
||||||
-- print("our code view "..code_view_index.." - "..k.." - is tab dest "..bb)
|
|
||||||
|
|
||||||
if tab_button.dragging then
|
|
||||||
if MovingTab == nil then
|
|
||||||
MovingTab = {}
|
|
||||||
MovingTab["code_view_index"] = code_view_index
|
|
||||||
MovingTab["tab"] = k
|
|
||||||
end
|
|
||||||
|
|
||||||
UI.push_parent(ctx, UI.push_floating(ctx, "dragging tab", x-(96/2), y-(32/2)))
|
|
||||||
UI.advanced_button(ctx, " "..k.." ", flags, UI.FitText, UI.Exact(32))
|
|
||||||
UI.pop_parent(ctx)
|
|
||||||
elseif MovingTab ~= nil and MovingTab["code_view_index"] == code_view_index and MovingTab["tab"] == k then
|
|
||||||
-- Editor.quit()
|
|
||||||
--print("attempting to move tab "..MovingTab["code_view_index"].." - "..MovingTab["tab"])
|
|
||||||
if MovingTabDest ~= nil then
|
|
||||||
print("attempting to place tab at code view "..MovingTabDest.code_view_index)
|
|
||||||
|
|
||||||
MovingTabDest = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
MovingTab = nil
|
|
||||||
end
|
|
||||||
UI.pop_parent(ctx)
|
|
||||||
end
|
end
|
||||||
UI.pop_parent(ctx)
|
|
||||||
|
|
||||||
current_tab = code_view.current_tab
|
UI.push_parent(ctx, UI.push_rect(ctx, "tabs", false, false, UI.Horizontal, UI.Fill, UI.ChildrenSum))
|
||||||
buffer_index = code_view.tabs[current_tab].buffer_index
|
for k,v in pairs(code_view.tabs) do
|
||||||
|
show_border = k ~= code_view.current_tab
|
||||||
|
background = show_border
|
||||||
|
flags = {"Clickable", "DrawText"}
|
||||||
|
if show_border then
|
||||||
|
table.insert(flags, 1, "DrawBorder")
|
||||||
|
table.insert(flags, 1, "Hoverable")
|
||||||
|
end
|
||||||
|
|
||||||
UI.buffer(ctx, buffer_index)
|
UI.push_parent(ctx, UI.push_rect(ctx, k.." tab container", background, false, UI.Horizontal, UI.ChildrenSum, UI.ChildrenSum))
|
||||||
|
tab_button = UI.advanced_button(ctx, " "..k.." ", flags, UI.FitText, UI.Exact(32))
|
||||||
|
if tab_button.clicked or tab_button.dragging then
|
||||||
|
ActiveCodeView = code_view_index
|
||||||
|
code_view.current_tab = k
|
||||||
|
|
||||||
if is_tab_dest then
|
Editor.set_current_buffer_from_index(v["buffer_index"])
|
||||||
|
end
|
||||||
|
|
||||||
|
if tab_button.dragging then
|
||||||
|
if MovingTab == nil then
|
||||||
|
MovingTab = {}
|
||||||
|
MovingTab["code_view_index"] = code_view_index
|
||||||
|
MovingTab["tab"] = k
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.push_parent(ctx, UI.push_floating(ctx, "dragging tab", x-(96/2), y-(32/2)))
|
||||||
|
UI.advanced_button(ctx, " "..k.." ", {"DrawText", "DrawBorder", "DrawBackground"}, UI.FitText, UI.Exact(32))
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
elseif MovingTab ~= nil and MovingTab["code_view_index"] == code_view_index and MovingTab["tab"] == k then
|
||||||
|
if MovingTabDest ~= nil then
|
||||||
|
add_buffer_to_code_view(MovingTabDest, k, v["buffer_index"])
|
||||||
|
remove_buffer_from_code_view(code_view_index, k)
|
||||||
|
|
||||||
|
MovingTabDest = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
MovingTab = nil
|
||||||
|
end
|
||||||
|
UI.pop_parent(ctx)
|
||||||
|
end
|
||||||
UI.pop_parent(ctx)
|
UI.pop_parent(ctx)
|
||||||
end
|
|
||||||
|
current_tab = code_view.current_tab
|
||||||
|
if code_view.tabs[current_tab] ~= nil then
|
||||||
|
buffer_index = code_view.tabs[current_tab].buffer_index
|
||||||
|
|
||||||
|
UI.buffer(ctx, buffer_index)
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.pop_parent(ctx)
|
||||||
UI.pop_parent(ctx)
|
UI.pop_parent(ctx)
|
||||||
|
|
||||||
|
return code_view_interaction
|
||||||
end
|
end
|
||||||
|
|
||||||
function render_ui_window(ctx)
|
function render_ui_window(ctx)
|
||||||
current_buffer_index = Editor.get_current_buffer_index()
|
current_buffer_index = Editor.get_current_buffer_index()
|
||||||
x,y = UI.get_mouse_pos(ctx)
|
x,y = UI.get_mouse_pos(ctx)
|
||||||
|
delta_x = LastMouseX - x
|
||||||
|
delta_y = LastMouseY - y
|
||||||
|
|
||||||
numFrames = 7
|
numFrames = 7
|
||||||
CurrentPreviewBufferIndex = current_buffer_index
|
CurrentPreviewBufferIndex = current_buffer_index
|
||||||
|
@ -176,7 +200,7 @@ function render_ui_window(ctx)
|
||||||
if not SidebarClosed or SideBarSmoothedWidth > 2 then
|
if not SidebarClosed or SideBarSmoothedWidth > 2 then
|
||||||
ui_sidebar(ctx)
|
ui_sidebar(ctx)
|
||||||
end
|
end
|
||||||
if UI.advanced_button(ctx, "side bar grab handle", {"DrawBorder", "Hoverable"}, UI.Exact(16), UI.Fill).dragging then
|
if UI.advanced_button(ctx, "side bar grab handle", {"DrawBorder", "Hoverable"}, UI.Exact(16), UI.Fill).dragging then
|
||||||
SideBarWidth = x-8
|
SideBarWidth = x-8
|
||||||
|
|
||||||
if SideBarWidth < 32 then
|
if SideBarWidth < 32 then
|
||||||
|
@ -192,11 +216,36 @@ function render_ui_window(ctx)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for k in ipairs(CodeViews) do
|
for k,v in ipairs(CodeViews) do
|
||||||
ui_code_view(ctx, k)
|
code_view_interaction = ui_code_view(ctx, k)
|
||||||
|
|
||||||
|
if next(CodeViews, k) ~= nil then
|
||||||
|
interaction = UI.advanced_button(ctx, k.."code view grab handle", {"DrawBorder", "Hoverable"}, UI.Exact(16), UI.Fill)
|
||||||
|
if interaction.dragging then
|
||||||
|
local width = math.max(32, x - code_view_interaction.box_pos.x)
|
||||||
|
v.width = UI.Exact(width)
|
||||||
|
elseif interaction.clicked then
|
||||||
|
v.width = UI.Fill
|
||||||
|
end
|
||||||
|
else
|
||||||
|
v.width = UI.Fill
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in ipairs(CodeViews) do
|
||||||
|
if next(v.tabs) == nil then
|
||||||
|
table.remove(CodeViews, k)
|
||||||
|
|
||||||
|
if ActiveCodeView > k then
|
||||||
|
ActiveCodeView = ActiveCodeView - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
render_buffer_search(ctx)
|
render_buffer_search(ctx)
|
||||||
|
|
||||||
|
LastMouseX = x
|
||||||
|
LastMouseY = y
|
||||||
end
|
end
|
||||||
|
|
||||||
function render_buffer_search(ctx)
|
function render_buffer_search(ctx)
|
||||||
|
@ -259,6 +308,9 @@ function OnInit()
|
||||||
)},
|
)},
|
||||||
{Editor.Key.Enter, "Switch to Buffer", (
|
{Editor.Key.Enter, "Switch to Buffer", (
|
||||||
function ()
|
function ()
|
||||||
|
buffer_info = Editor.buffer_info_from_index(BufferSearchIndex)
|
||||||
|
add_buffer_to_code_view(ActiveCodeView, buffer_info.file_path, BufferSearchIndex)
|
||||||
|
|
||||||
Editor.set_current_buffer_from_index(BufferSearchIndex)
|
Editor.set_current_buffer_from_index(BufferSearchIndex)
|
||||||
Editor.request_window_close()
|
Editor.request_window_close()
|
||||||
BufferSearchOpen = false
|
BufferSearchOpen = false
|
||||||
|
|
|
@ -120,6 +120,21 @@ draw_rect :: proc(state: ^State, x,y,w,h: int, color: theme.PaletteColor) {
|
||||||
sdl2.RenderFillRect(state.sdl_renderer, &sdl2.Rect { i32(x), i32(y), i32(w), i32(h) });
|
sdl2.RenderFillRect(state.sdl_renderer, &sdl2.Rect { i32(x), i32(y), i32(w), i32(h) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draw_rect_blend :: proc(state: ^State, x,y,w,h: int, color_from: theme.PaletteColor, color_to: theme.PaletteColor, t: f32) {
|
||||||
|
color_from := theme.get_palette_color(color_from);
|
||||||
|
color_to := theme.get_palette_color(color_to);
|
||||||
|
|
||||||
|
color_from_f32: [4]f32 = { f32(color_from.r), f32(color_from.g), f32(color_from.b), f32(color_from.a) };
|
||||||
|
color_to_f32: [4]f32 = { f32(color_to.r), f32(color_to.g), f32(color_to.b), f32(color_to.a) };
|
||||||
|
|
||||||
|
color_f32 := (1 - t) * color_from_f32 + t * color_to_f32;
|
||||||
|
|
||||||
|
color: [4]u8 = { u8(color_f32.r), u8(color_f32.g), u8(color_f32.b), u8(color_f32.a) };
|
||||||
|
|
||||||
|
sdl2.SetRenderDrawColor(state.sdl_renderer, color.r, color.g, color.b, color.a);
|
||||||
|
sdl2.RenderFillRect(state.sdl_renderer, &sdl2.Rect { i32(x), i32(y), i32(w), i32(h) });
|
||||||
|
}
|
||||||
|
|
||||||
draw_codepoint :: proc(state: ^State, codepoint: rune, x,y: int, color: theme.PaletteColor) {
|
draw_codepoint :: proc(state: ^State, codepoint: rune, x,y: int, color: theme.PaletteColor) {
|
||||||
color := theme.get_palette_color(color);
|
color := theme.get_palette_color(color);
|
||||||
|
|
||||||
|
|
|
@ -301,13 +301,16 @@ ui_file_buffer :: proc(ctx: ^ui.Context, buffer: ^FileBuffer) -> ui.Interaction
|
||||||
};
|
};
|
||||||
|
|
||||||
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.push_parent(ctx, ui.push_box(ctx, relative_file_path, {}, .Vertical, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Fill)}));
|
|
||||||
|
buffer_container, _ := ui.push_box(ctx, relative_file_path, {}, .Vertical, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Fill)});
|
||||||
|
ui.push_parent(ctx, buffer_container);
|
||||||
defer ui.pop_parent(ctx);
|
defer ui.pop_parent(ctx);
|
||||||
|
|
||||||
interaction := ui.custom(ctx, "buffer1", draw_func, transmute(rawptr)buffer);
|
interaction := ui.custom(ctx, "buffer1", draw_func, transmute(rawptr)buffer);
|
||||||
|
|
||||||
{
|
{
|
||||||
ui.push_parent(ctx, ui.push_box(ctx, "buffer info", {}, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Exact, state.source_font_height)}));
|
info_box, _ := ui.push_box(ctx, "buffer info", {}, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Exact, state.source_font_height)});
|
||||||
|
ui.push_parent(ctx, info_box);
|
||||||
defer ui.pop_parent(ctx);
|
defer ui.pop_parent(ctx);
|
||||||
|
|
||||||
ui.label(ctx, relative_file_path);
|
ui.label(ctx, relative_file_path);
|
||||||
|
@ -825,7 +828,8 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
|
||||||
ui_context := transmute(^ui.Context)ui_context;
|
ui_context := transmute(^ui.Context)ui_context;
|
||||||
label := strings.clone(string(label), context.temp_allocator);
|
label := strings.clone(string(label), context.temp_allocator);
|
||||||
|
|
||||||
return ui.push_floating(ui_context, label, pos);
|
floating, _ := ui.push_floating(ui_context, label, pos);
|
||||||
|
return floating;
|
||||||
},
|
},
|
||||||
rect = proc "c" (ui_context: rawptr, label: cstring, background: bool, border: bool, axis: plugin.UiAxis, size: [2]plugin.UiSemanticSize) -> plugin.UiBox {
|
rect = proc "c" (ui_context: rawptr, label: cstring, background: bool, border: bool, axis: plugin.UiAxis, size: [2]plugin.UiSemanticSize) -> plugin.UiBox {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
@ -843,7 +847,8 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return ui.push_rect(ui_context, label, background, border, ui.Axis(axis), size);
|
rect, _ := ui.push_rect(ui_context, label, background, border, ui.Axis(axis), size);
|
||||||
|
return rect;
|
||||||
},
|
},
|
||||||
|
|
||||||
label = proc "c" (ui_context: rawptr, label: cstring) -> plugin.UiInteraction {
|
label = proc "c" (ui_context: rawptr, label: cstring) -> plugin.UiInteraction {
|
||||||
|
@ -1251,6 +1256,16 @@ main :: proc() {
|
||||||
|
|
||||||
lua.pushboolean(L, b32(interaction.dragging));
|
lua.pushboolean(L, b32(interaction.dragging));
|
||||||
lua.setfield(L, -2, "dragging");
|
lua.setfield(L, -2, "dragging");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_pos.x));
|
||||||
|
lua.setfield(L, -2, "x");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_pos.y));
|
||||||
|
lua.setfield(L, -2, "y");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "box_pos");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,9 +1354,10 @@ 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), context.temp_allocator), {x,y});
|
box, interaction := ui.push_floating(ui_ctx, strings.clone(string(label), context.temp_allocator), {x,y});
|
||||||
lua.pushlightuserdata(L, box);
|
lua.pushlightuserdata(L, box);
|
||||||
return 1;
|
push_lua_box_interaction(L, interaction);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
return i32(lua.ERRRUN);
|
||||||
|
@ -1363,16 +1379,18 @@ main :: proc() {
|
||||||
semantic_width := get_lua_semantic_size(L, 5);
|
semantic_width := get_lua_semantic_size(L, 5);
|
||||||
semantic_height := get_lua_semantic_size(L, 6);
|
semantic_height := get_lua_semantic_size(L, 6);
|
||||||
|
|
||||||
box := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
||||||
|
|
||||||
lua.pushlightuserdata(L, box);
|
lua.pushlightuserdata(L, box);
|
||||||
return 1;
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
return i32(lua.ERRRUN);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
lua.L_Reg {
|
lua.L_Reg {
|
||||||
"box_interaction",
|
"_box_interaction",
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
context = state.ctx;
|
context = state.ctx;
|
||||||
|
|
||||||
|
@ -1408,35 +1426,10 @@ 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), context.temp_allocator), background, border, axis, { semantic_width, semantic_height });
|
box, interaction := 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;
|
push_lua_box_interaction(L, interaction)
|
||||||
}
|
return 2;
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"push_centered",
|
|
||||||
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);
|
|
||||||
background := bool(lua.toboolean(L, 3));
|
|
||||||
border := bool(lua.toboolean(L, 4));
|
|
||||||
axis := ui.Axis(lua.L_checkinteger(L, 5));
|
|
||||||
|
|
||||||
semantic_width := get_lua_semantic_size(L, 6);
|
|
||||||
semantic_height := get_lua_semantic_size(L, 7);
|
|
||||||
|
|
||||||
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);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
return i32(lua.ERRRUN);
|
||||||
|
@ -1772,6 +1765,9 @@ main :: proc() {
|
||||||
ui_context.last_mouse_left_down = ui_context.mouse_left_down;
|
ui_context.last_mouse_left_down = ui_context.mouse_left_down;
|
||||||
ui_context.last_mouse_right_down = ui_context.mouse_right_down;
|
ui_context.last_mouse_right_down = ui_context.mouse_right_down;
|
||||||
|
|
||||||
|
ui_context.last_mouse_x = ui_context.mouse_x;
|
||||||
|
ui_context.last_mouse_y = ui_context.mouse_y;
|
||||||
|
|
||||||
sdl_event: sdl2.Event;
|
sdl_event: sdl2.Event;
|
||||||
for(sdl2.PollEvent(&sdl_event)) {
|
for(sdl2.PollEvent(&sdl_event)) {
|
||||||
if sdl_event.type == .QUIT {
|
if sdl_event.type == .QUIT {
|
||||||
|
|
124
src/ui/imm.odin
124
src/ui/imm.odin
|
@ -17,6 +17,9 @@ Context :: struct {
|
||||||
clips: [dynamic]Rect,
|
clips: [dynamic]Rect,
|
||||||
renderer: ^sdl2.Renderer,
|
renderer: ^sdl2.Renderer,
|
||||||
|
|
||||||
|
last_mouse_x: int,
|
||||||
|
last_mouse_y: int,
|
||||||
|
|
||||||
mouse_x: int,
|
mouse_x: int,
|
||||||
mouse_y: int,
|
mouse_y: int,
|
||||||
|
|
||||||
|
@ -41,6 +44,9 @@ Interaction :: struct {
|
||||||
hovering: bool,
|
hovering: bool,
|
||||||
clicked: bool,
|
clicked: bool,
|
||||||
dragging: bool,
|
dragging: bool,
|
||||||
|
|
||||||
|
box_pos: [2]int,
|
||||||
|
box_size: [2]int,
|
||||||
}
|
}
|
||||||
|
|
||||||
Flag :: enum {
|
Flag :: enum {
|
||||||
|
@ -93,6 +99,8 @@ Box :: struct {
|
||||||
computed_size: [2]int,
|
computed_size: [2]int,
|
||||||
computed_pos: [2]int,
|
computed_pos: [2]int,
|
||||||
|
|
||||||
|
scroll_offset: int,
|
||||||
|
|
||||||
hot: int,
|
hot: int,
|
||||||
active: int,
|
active: int,
|
||||||
|
|
||||||
|
@ -215,11 +223,12 @@ Fill :[2]SemanticSize: {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
push_box :: proc(ctx: ^Context, label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText) -> ^Box {
|
push_box :: proc(ctx: ^Context, label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText) -> (^Box, Interaction) {
|
||||||
key := gen_key(ctx, label, 0);
|
key := gen_key(ctx, label, 0);
|
||||||
box := make_box(ctx, key, label, flags, axis, semantic_size);
|
box := make_box(ctx, key, label, flags, axis, semantic_size);
|
||||||
|
interaction := test_box(ctx, box);
|
||||||
|
|
||||||
return box;
|
return box, interaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_parent :: proc(ctx: ^Context, box: ^Box) {
|
push_parent :: proc(ctx: ^Context, box: ^Box) {
|
||||||
|
@ -236,11 +245,19 @@ test_box :: proc(ctx: ^Context, box: ^Box) -> Interaction {
|
||||||
hovering: bool;
|
hovering: bool;
|
||||||
|
|
||||||
mouse_is_clicked := !ctx.last_mouse_left_down && ctx.mouse_left_down;
|
mouse_is_clicked := !ctx.last_mouse_left_down && ctx.mouse_left_down;
|
||||||
|
mouse_is_released := ctx.last_mouse_left_down && !ctx.mouse_left_down;
|
||||||
|
mouse_is_dragging := !mouse_is_clicked && ctx.mouse_left_down && (ctx.last_mouse_x != ctx.mouse_x || ctx.last_mouse_y != ctx.mouse_y);
|
||||||
|
|
||||||
if ctx.mouse_x >= box.computed_pos.x && ctx.mouse_x <= box.computed_pos.x + box.computed_size.x &&
|
if ctx.mouse_x >= box.computed_pos.x && ctx.mouse_x <= box.computed_pos.x + box.computed_size.x &&
|
||||||
ctx.mouse_y >= box.computed_pos.y && ctx.mouse_y <= box.computed_pos.y + box.computed_size.y
|
ctx.mouse_y >= box.computed_pos.y && ctx.mouse_y <= box.computed_pos.y + box.computed_size.y
|
||||||
{
|
{
|
||||||
hovering = true;
|
if box.parent != nil && ctx.mouse_x >= box.parent.computed_pos.x && ctx.mouse_x <= box.parent.computed_pos.x + box.parent.computed_size.x &&
|
||||||
|
ctx.mouse_y >= box.parent.computed_pos.y && ctx.mouse_y <= box.parent.computed_pos.y + box.parent.computed_size.y
|
||||||
|
{
|
||||||
|
hovering = true;
|
||||||
|
} else if box.parent == nil {
|
||||||
|
hovering = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hovering || box.active > 0 {
|
if hovering || box.active > 0 {
|
||||||
|
@ -249,9 +266,11 @@ test_box :: proc(ctx: ^Context, box: ^Box) -> Interaction {
|
||||||
box.hot = 0;
|
box.hot = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if hovering && mouse_is_clicked {
|
if hovering && mouse_is_clicked && !mouse_is_dragging {
|
||||||
|
box.active = 1;
|
||||||
|
} else if hovering && mouse_is_dragging && box.active > 0 {
|
||||||
box.active += 1;
|
box.active += 1;
|
||||||
} else if !ctx.mouse_left_down {
|
} else if !ctx.mouse_left_down && !mouse_is_released {
|
||||||
box.active = 0;
|
box.active = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,8 +279,11 @@ test_box :: proc(ctx: ^Context, box: ^Box) -> Interaction {
|
||||||
}
|
}
|
||||||
return Interaction {
|
return Interaction {
|
||||||
hovering = hovering || box.active > 0,
|
hovering = hovering || box.active > 0,
|
||||||
clicked = hovering && mouse_is_clicked,
|
clicked = hovering && mouse_is_released && box.active > 0,
|
||||||
dragging = box.active > 0
|
dragging = box.active > 1,
|
||||||
|
|
||||||
|
box_pos = box.computed_pos,
|
||||||
|
box_size = box.computed_size,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +367,7 @@ compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font
|
||||||
axis := Axis.Horizontal;
|
axis := Axis.Horizontal;
|
||||||
if box.parent != nil && !(.Floating in box.flags) {
|
if box.parent != nil && !(.Floating in box.flags) {
|
||||||
axis = box.parent.axis;
|
axis = box.parent.axis;
|
||||||
box.computed_pos = box.parent.computed_pos;
|
box.computed_pos = box.parent.computed_pos - { 0, box.parent.scroll_offset };
|
||||||
}
|
}
|
||||||
|
|
||||||
if .Floating in box.flags {
|
if .Floating in box.flags {
|
||||||
|
@ -538,13 +560,15 @@ draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: in
|
||||||
defer pop_clip(ctx);
|
defer pop_clip(ctx);
|
||||||
|
|
||||||
if .Hoverable in box.flags && box.hot > 0 {
|
if .Hoverable in box.flags && box.hot > 0 {
|
||||||
core.draw_rect(
|
core.draw_rect_blend(
|
||||||
state,
|
state,
|
||||||
box.computed_pos.x,
|
box.computed_pos.x,
|
||||||
box.computed_pos.y,
|
box.computed_pos.y,
|
||||||
box.computed_size.x,
|
box.computed_size.x,
|
||||||
box.computed_size.y,
|
box.computed_size.y,
|
||||||
.Background2
|
.Background1,
|
||||||
|
.Background2,
|
||||||
|
f32(math.min(box.hot, 20))/20.0
|
||||||
);
|
);
|
||||||
} else if .DrawBackground in box.flags {
|
} else if .DrawBackground in box.flags {
|
||||||
core.draw_rect(
|
core.draw_rect(
|
||||||
|
@ -628,50 +652,26 @@ debug_print :: proc(ctx: ^Context, box: ^Box, depth: int = 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
spacer :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {}, semantic_size: [2]SemanticSize = {{.Fill, 0}, {.Fill,0}}) -> Interaction {
|
spacer :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {}, semantic_size: [2]SemanticSize = {{.Fill, 0}, {.Fill,0}}) -> Interaction {
|
||||||
box := push_box(ctx, label, flags, semantic_size = semantic_size);
|
box, interaction := push_box(ctx, label, flags, semantic_size = semantic_size);
|
||||||
|
|
||||||
return test_box(ctx, box);
|
return interaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_floating :: proc(ctx: ^Context, label: string, pos: [2]int, flags: bit_set[Flag] = {.Floating}, axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = Fill) -> ^Box {
|
push_floating :: proc(ctx: ^Context, label: string, pos: [2]int, flags: bit_set[Flag] = {.Floating}, axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = Fill) -> (^Box, Interaction) {
|
||||||
box := push_box(ctx, label, flags, semantic_size = semantic_size);
|
box, interaction := push_box(ctx, label, flags, semantic_size = semantic_size);
|
||||||
box.computed_pos = pos;
|
box.computed_pos = pos;
|
||||||
|
|
||||||
return box;
|
return box, interaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_rect :: proc(ctx: ^Context, label: string, background: bool = true, border: bool = true, axis: Axis = .Vertical, semantic_size: [2]SemanticSize = Fill) -> ^Box {
|
push_rect :: proc(ctx: ^Context, label: string, background: bool = true, border: bool = true, axis: Axis = .Vertical, semantic_size: [2]SemanticSize = Fill) -> (^Box, Interaction) {
|
||||||
return push_box(ctx, label, {.DrawBackground if background else nil, .DrawBorder if border else nil}, axis, semantic_size = semantic_size);
|
return push_box(ctx, label, {.DrawBackground if background else nil, .DrawBorder if border else nil}, axis, semantic_size = semantic_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
push_centered :: proc(ctx: ^Context, label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText) -> ^Box {
|
|
||||||
box: ^Box;
|
|
||||||
|
|
||||||
push_parent(ctx, push_box(ctx, label, {}, semantic_size = { {.Fill,0}, semantic_size.y }))
|
|
||||||
{
|
|
||||||
defer pop_parent(ctx);
|
|
||||||
|
|
||||||
spacer(ctx, "left spacer");
|
|
||||||
halfway_centered := push_rect(ctx, "halfway centered", false, false, .Vertical, { {.Fill, 0}, {.Fill,0} });
|
|
||||||
|
|
||||||
push_parent(ctx, halfway_centered);
|
|
||||||
{
|
|
||||||
defer pop_parent(ctx);
|
|
||||||
|
|
||||||
spacer(ctx, "top spacer");
|
|
||||||
box = push_box(ctx, label, flags, axis, FitText);
|
|
||||||
spacer(ctx, "bottom spacer");
|
|
||||||
}
|
|
||||||
spacer(ctx, "right spacer");
|
|
||||||
}
|
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
label :: proc(ctx: ^Context, label: string) -> Interaction {
|
label :: proc(ctx: ^Context, label: string) -> Interaction {
|
||||||
box := push_box(ctx, label, {.DrawText});
|
box, interaction := push_box(ctx, label, {.DrawText});
|
||||||
|
|
||||||
return test_box(ctx, box);
|
return interaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
button :: proc(ctx: ^Context, label: string) -> Interaction {
|
button :: proc(ctx: ^Context, label: string) -> Interaction {
|
||||||
|
@ -679,47 +679,15 @@ button :: proc(ctx: ^Context, label: string) -> Interaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
advanced_button :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {.Clickable, .Hoverable, .DrawText, .DrawBorder, .DrawBackground}, semantic_size: [2]SemanticSize = FitText) -> Interaction {
|
advanced_button :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {.Clickable, .Hoverable, .DrawText, .DrawBorder, .DrawBackground}, semantic_size: [2]SemanticSize = FitText) -> Interaction {
|
||||||
box := push_box(ctx, label, flags, semantic_size = semantic_size);
|
box, interaction := push_box(ctx, label, flags, semantic_size = semantic_size);
|
||||||
|
|
||||||
return test_box(ctx, box);
|
return interaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
custom :: proc(ctx: ^Context, label: string, draw_func: CustomDrawFunc, user_data: rawptr) -> Interaction {
|
custom :: proc(ctx: ^Context, label: string, draw_func: CustomDrawFunc, user_data: rawptr) -> Interaction {
|
||||||
box := push_box(ctx, label, {.CustomDrawFunc}, semantic_size = { make_semantic_size(.Fill), make_semantic_size(.Fill) });
|
box, interaction := push_box(ctx, label, {.CustomDrawFunc}, semantic_size = { make_semantic_size(.Fill), make_semantic_size(.Fill) });
|
||||||
box.custom_draw_func = draw_func;
|
box.custom_draw_func = draw_func;
|
||||||
box.user_data = user_data;
|
box.user_data = user_data;
|
||||||
|
|
||||||
return test_box(ctx, box);
|
return interaction;
|
||||||
}
|
|
||||||
|
|
||||||
two_buttons_test :: proc(ctx: ^Context, label1: string, label2: string) {
|
|
||||||
push_parent(ctx, push_box(ctx, "TWO BUTTONS TEST", {.DrawBorder}, .Vertical, semantic_size = {make_semantic_size(.PercentOfParent, 100), { .Fill, 256}}));
|
|
||||||
|
|
||||||
button(ctx, "Row 1");
|
|
||||||
button(ctx, "Row 2");
|
|
||||||
button(ctx, label1);
|
|
||||||
button(ctx, label2);
|
|
||||||
button(ctx, "Row 5");
|
|
||||||
button(ctx, "Row 6");
|
|
||||||
|
|
||||||
{
|
|
||||||
push_parent(ctx, push_box(ctx, "two_button_container_inner", {.DrawBorder}, semantic_size = {make_semantic_size(.Fill, 0), { .Fill, 64}}));
|
|
||||||
defer pop_parent(ctx);
|
|
||||||
|
|
||||||
push_box(ctx, "1", {.DrawText, .DrawBackground, .DrawBorder}, semantic_size = {make_semantic_size(.Fill, 100), { .FitText, 256}})
|
|
||||||
push_box(ctx, "2", {.DrawText, .DrawBackground, .DrawBorder}, semantic_size = {make_semantic_size(.Fill, 100), { .FitText, 256}})
|
|
||||||
|
|
||||||
{
|
|
||||||
push_parent(ctx, push_box(ctx, "two_button_container_inner_inner", {.DrawBorder}, .Vertical, semantic_size = {make_semantic_size(.Fill, 50), { .ChildrenSum, 256}}));
|
|
||||||
defer pop_parent(ctx);
|
|
||||||
|
|
||||||
button(ctx, "this is a test button");
|
|
||||||
button(ctx, "me in the middle");
|
|
||||||
button(ctx, "look at me, I'm a test button too");
|
|
||||||
}
|
|
||||||
|
|
||||||
push_box(ctx, "End", {.DrawBorder, .DrawBackground, .DrawText}, .Horizontal, semantic_size = {make_semantic_size(.Fill, 0), { .FitText, 0}})
|
|
||||||
}
|
|
||||||
button(ctx, "Help me I'm falling");
|
|
||||||
pop_parent(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue