Skip to content

Commit 2e4760d

Browse files
Fix scrollbar bug with scrollbox content being smaller than or the same size as scrollbox bounds + Improve Dropdown API (#1287)
* add scrollbar * add dropdown * errors for proper usage * polish * docs pt 1 * comment patches * scroll progress now saves on a per-instance basis * docs (final) * Update ui.lua * Update ui.lua * add stuff * fix scrolling and convert stuff to absolute positioning * reimplement scroll mult * pass args into dropdown_element_def * fix bug with underfull content * ehhhh why did this not get committed * more config Allows displayed options to be different from options stored in the options table * Update ui.lua * well that was less bad than i thought it was gonna be * Update ui.lua * Update ui.lua
1 parent 8f2cc88 commit 2e4760d

File tree

2 files changed

+113
-74
lines changed

2 files changed

+113
-74
lines changed

lsp_def/ui.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ function G.FUNCS.scrollbar(e) end
386386
---@field id? string Assigns the given id to the config table of the root of the button UIBox if set.
387387
---@field option_align? string Aligns the text of the dropdown options. Works just like aligning regular UI nodes. Default is "cl".
388388
---@field close_on_select? boolean If true, the dropdown menu will automatically close when an option is selected or unselected.
389+
---@field display_choice_func? fun(option: string): string? If defined, changes the displayed text for a choice to the returned value of this function. `option` is
389390

390391
---Returns a button that creates a dropdown selection menu when clicked on.
391392
---@param args DropdownSelectArgs

src/ui.lua

Lines changed: 112 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,7 +2711,8 @@ function SMODS.GUI.scrollbar(args)
27112711
if not args.ref_table or not args.ref_value then
27122712
args.ref_table = args.scroll_collision_obj.scroll_offset
27132713
args.ref_value = args.horizontal and "x" or "y"
2714-
args.max = args.scroll_collision_obj.content.T.h - args.scroll_collision_obj.T.h
2714+
local dim = args.horizontal and "w" or "h"
2715+
args.max = args.scroll_collision_obj.content.T[dim] - args.scroll_collision_obj.T[dim]
27152716
args.scroll_collision_obj.scroll_args.sync_mode = "offset"
27162717
args.scroll_collision_obj.scroll_sync_mode = "offset"
27172718
end
@@ -2787,24 +2788,36 @@ function G.FUNCS.scrollbar(e)
27872788
local ref_value = e.config.ref_value
27882789
local scrollbox = e.config.scroll_collision_obj
27892790
local percent = (ref_table[ref_value] - e.config.min) / (e.config.max - e.config.min)
2790-
if
2791-
G.CONTROLLER
2792-
and G.CONTROLLER.dragging.target
2793-
and (G.CONTROLLER.dragging.target == e or G.CONTROLLER.dragging.target == scrollbar_track)
2794-
then
2795-
if e.config.scroll_dir == "h" then
2796-
percent = (G.CURSOR.T.x - e.parent.T.x - G.ROOM.T.x - e.T.w / 2) / (scrollbar_track.T.w - e.T.w)
2791+
local should_scroll = true
2792+
if scrollbox then
2793+
if e.config.scroll_dir == "v" then
2794+
local h = scrollbox.scroll_args.overflow.node_config.h or scrollbox.scroll_args.overflow.node_config.maxh
2795+
should_scroll = scrollbox.content.T.h > (h or math.huge)
27972796
else
2798-
percent = (G.CURSOR.T.y - e.parent.T.y - G.ROOM.T.y - e.T.h / 2) / (scrollbar_track.T.h - e.T.h)
2797+
local w = scrollbox.scroll_args.overflow.node_config.w or scrollbox.scroll_args.overflow.node_config.maxw
2798+
should_scroll = scrollbox.content.T.w > (w or math.huge)
27992799
end
2800-
percent = math.max(0, math.min(1, percent))
2801-
ref_table[ref_value] = percent * (e.config.max - e.config.min) + e.config.min
2802-
elseif scrollbox and scrollbox:collides_with_point(G.CURSOR.T) or scrollbar_track:collides_with_point(G.CURSOR.T) then
2803-
local scroll_velocity = SMODS.wheel_velocity.y * (e.config.scroll_mult or 1) / G.TILESIZE
2804-
percent = (ref_table[ref_value] - e.config.min - scroll_velocity) / (e.config.max - e.config.min)
2805-
percent = math.max(0, math.min(1, percent))
2806-
ref_table[ref_value] = percent * (e.config.max - e.config.min) + e.config.min
2807-
end
2800+
end
2801+
if should_scroll then
2802+
if
2803+
G.CONTROLLER
2804+
and G.CONTROLLER.dragging.target
2805+
and (G.CONTROLLER.dragging.target == e or G.CONTROLLER.dragging.target == scrollbar_track)
2806+
then
2807+
if e.config.scroll_dir == "h" then
2808+
percent = (G.CURSOR.T.x - e.parent.T.x - G.ROOM.T.x - e.T.w / 2) / (scrollbar_track.T.w - e.T.w)
2809+
else
2810+
percent = (G.CURSOR.T.y - e.parent.T.y - G.ROOM.T.y - e.T.h / 2) / (scrollbar_track.T.h - e.T.h)
2811+
end
2812+
percent = math.max(0, math.min(1, percent))
2813+
ref_table[ref_value] = percent * (e.config.max - e.config.min) + e.config.min
2814+
elseif scrollbox and scrollbox:collides_with_point(G.CURSOR.T) or scrollbar_track:collides_with_point(G.CURSOR.T) then
2815+
local scroll_velocity = SMODS.wheel_velocity.y * (e.config.scroll_mult or 1) / G.TILESIZE
2816+
percent = (ref_table[ref_value] - e.config.min - scroll_velocity) / (e.config.max - e.config.min)
2817+
percent = math.max(0, math.min(1, percent))
2818+
ref_table[ref_value] = percent * (e.config.max - e.config.min) + e.config.min
2819+
end
2820+
end
28082821
if e.config.scroll_dir == "h" then
28092822
scrollbar_track.UIRoot.children[1].config.minw = percent * (scrollbar_track.T.w - e.T.w)
28102823
else
@@ -2832,69 +2845,71 @@ function SMODS.GUI.dropdown_select(args)
28322845
end
28332846
args.dropdown_bg_colour = args.dropdown_bg_colour or lighten(G.C.BLACK, 0.2)
28342847
args.selected_colour = args.selected_colour or G.C.BLACK
2848+
args.display_choice_func = args.display_choice_func or function(option)
2849+
return option
2850+
end
2851+
local table_ref = args.ref_table
28352852
local arrow = SMODS.create_sprite(0, 0, args.scale * 0.75, args.scale * 0.75, "dropdown_arrow", { x = 0, y = 0 })
2836-
local dropdown_button = UIBox({
2837-
definition = {
2838-
n = G.UIT.ROOT,
2839-
config = {
2840-
colour = args.colour or G.C.RED,
2841-
r = 0.1,
2842-
padding = 0.1,
2843-
button_dist = 0,
2844-
button = "toggle_dropdown_menu",
2845-
hover = true,
2846-
args_table = args,
2847-
id = args.id
2848-
},
2849-
nodes = {
2850-
{
2851-
n = G.UIT.C,
2852-
config = {
2853-
minw = args.minw,
2854-
align = args.align or "cm",
2855-
},
2856-
nodes = {
2857-
{
2858-
n = G.UIT.T,
2859-
config = {
2860-
ref_table = args.ref_table,
2861-
ref_value = args.ref_value,
2862-
colour = args.text_colour or G.C.UI.TEXT_LIGHT,
2863-
scale = args.scale,
2864-
},
2865-
},
2866-
}
2867-
},
2868-
{
2869-
n = G.UIT.C,
2870-
config = { align = "cm" },
2871-
nodes = {
2872-
{
2873-
n = G.UIT.O,
2874-
config = {
2875-
align = "cm",
2876-
object = arrow,
2877-
},
2878-
}
2879-
}
2880-
},
2881-
},
2882-
},
2883-
config = { align = "cm" },
2884-
})
28852853
return {
28862854
n = args.ui_type or G.UIT.R,
28872855
config = {
2888-
align = "cm"
2856+
align = "cm",
28892857
},
28902858
nodes = {
28912859
{
2892-
n = G.UIT.O,
2860+
n = G.UIT.R,
28932861
config = {
2894-
object = dropdown_button
2862+
colour = args.colour or G.C.RED,
2863+
r = 0.1,
2864+
padding = 0.1,
2865+
button_dist = 0,
2866+
button = "toggle_dropdown_menu",
2867+
hover = true,
2868+
args_table = args,
2869+
id = args.id
28952870
},
2896-
}
2897-
}
2871+
nodes = {
2872+
{
2873+
n = G.UIT.C,
2874+
config = {
2875+
minw = args.minw,
2876+
align = args.align or "cm",
2877+
},
2878+
nodes = {
2879+
{
2880+
n = G.UIT.T,
2881+
config = {
2882+
ref_table = setmetatable({}, {
2883+
__index = function(_, k)
2884+
if k == args.ref_value then
2885+
return args.display_choice_func(table_ref[k])
2886+
end
2887+
return table_ref[k]
2888+
end
2889+
}),
2890+
ref_value = args.ref_value,
2891+
colour = args.text_colour or G.C.UI.TEXT_LIGHT,
2892+
scale = args.scale,
2893+
},
2894+
},
2895+
}
2896+
},
2897+
{
2898+
n = G.UIT.C,
2899+
config = { align = "cm" },
2900+
nodes = {
2901+
{
2902+
n = G.UIT.O,
2903+
config = {
2904+
align = "cm",
2905+
object = arrow,
2906+
},
2907+
}
2908+
}
2909+
},
2910+
},
2911+
},
2912+
},
28982913
}
28992914
end
29002915

@@ -2956,6 +2971,18 @@ function G.FUNCS.dropdown_select(e)
29562971
if args.close_on_select then
29572972
G.FUNCS.toggle_dropdown_menu(e.config.dropdown_button)
29582973
end
2974+
local text = args.display_choice_func(args.ref_table[args.ref_value])
2975+
local parent = e.config.dropdown_button.children[1].children[1]
2976+
if parent.config and parent.config.text and not parent.config.text_drawable then
2977+
parent.config.lang = parent.config.lang or G.LANG
2978+
parent.config.text_drawable = love.graphics.newText((parent.config.font or parent.config.lang.font).FONT, {G.C.WHITE,parent.config.text})
2979+
end
2980+
if text ~= parent.config.prev_value then
2981+
parent.config.text = text
2982+
parent.config.text_drawable:set(parent.config.text)
2983+
if not parent.config.prev_value or (parent.config.prev_value and string.len(parent.config.prev_value) ~= string.len(parent.config.text)) then parent.UIBox:recalculate() end
2984+
parent.config.prev_value = text
2985+
end
29592986
end
29602987

29612988
function G.FUNCS.update_dropdown_select(e)
@@ -3000,7 +3027,11 @@ function SMODS.GUI.create_UIBox_dropdown_menu(args, parent_width, parent)
30003027
nodes = {
30013028
{
30023029
n = G.UIT.T,
3003-
config = { scale = args.dropdown_scale or 0.4, text = opt, colour = args.dropdown_text_colour or G.C.UI.TEXT_LIGHT },
3030+
config = {
3031+
scale = args.dropdown_scale or 0.4,
3032+
text = args.display_choice_func(opt),
3033+
colour = args.dropdown_text_colour or G.C.UI.TEXT_LIGHT
3034+
},
30043035
},
30053036
},
30063037
},
@@ -3030,7 +3061,14 @@ function SMODS.GUI.create_UIBox_dropdown_menu(args, parent_width, parent)
30303061
},
30313062
sync_mode = "offset",
30323063
})
3033-
if args.max_menu_h then
3064+
local force_no_scrollbar = false
3065+
if args.max_menu_h and scrollbox.content.UIRoot.T.h < args.max_menu_h then
3066+
force_no_scrollbar = true
3067+
end
3068+
if force_no_scrollbar then
3069+
scrollbox.scroll_args.overflow.node_config.maxh = nil
3070+
end
3071+
if args.max_menu_h and not force_no_scrollbar then
30343072
local total_h = scrollbox.content.UIRoot.T.h
30353073
local scrollbox_rows = scrollbox.content.UIRoot.children[1].children
30363074
local curr = args.ref_table[args.ref_value]
@@ -3092,7 +3130,7 @@ function SMODS.GUI.create_UIBox_dropdown_menu(args, parent_width, parent)
30923130
nodes = {
30933131
SMODS.GUI.scrollbar({
30943132
w = 0.1,
3095-
h = args.max_menu_h - 0.1,
3133+
h = math.min(args.max_menu_h, scrollbox.content.UIRoot.T.h) - 0.1,
30963134
scroll_collision_obj = scrollbox,
30973135
knob_h = args.max_menu_h / 6,
30983136
bg_colour = { 0, 0, 0, 0.15 },

0 commit comments

Comments
 (0)