Improve autocomplete suggestions box behavior (#1734)

* Improve `autocomplete` suggestions box sizing

This avoids that the box gets too big because of non-visible items, and makes it reactive to window sizing.

* Draw ellipsis when `autocomplete` entries aren't fully visible
This commit is contained in:
Guldoman
2024-03-23 20:26:43 +08:00
committed by takase1121
parent e568e4acdf
commit 499124d8e3
+38 -14
View File
@@ -276,8 +276,10 @@ local function get_active_view()
end end
end end
local last_max_width = 0
local function get_suggestions_rect(av) local function get_suggestions_rect(av)
if #suggestions == 0 then if #suggestions == 0 then
last_max_width = 0
return 0, 0, 0, 0 return 0, 0, 0, 0
end end
@@ -287,38 +289,47 @@ local function get_suggestions_rect(av)
local font = av:get_font() local font = av:get_font()
local th = font:get_height() local th = font:get_height()
local ah = config.plugins.autocomplete.max_height
local max_items = math.min(ah, #suggestions)
local show_count = math.min(#suggestions, ah)
local start_index = math.max(suggestions_idx-(ah-1), 1)
local max_width = 0 local max_width = 0
for _, s in ipairs(suggestions) do for i = start_index, start_index + show_count - 1 do
local s = suggestions[i]
local w = font:get_width(s.text) local w = font:get_width(s.text)
if s.info then if s.info then
w = w + style.font:get_width(s.info) + style.padding.x w = w + style.font:get_width(s.info) + style.padding.x
end end
max_width = math.max(max_width, w) max_width = math.max(max_width, w)
end end
max_width = math.max(last_max_width, max_width)
last_max_width = max_width
local ah = config.plugins.autocomplete.max_height max_width = max_width + style.padding.x * 2
x = x - style.padding.x
local max_items = #suggestions
if max_items > ah then
max_items = ah
end
-- additional line to display total items -- additional line to display total items
max_items = max_items + 1 max_items = max_items + 1
if max_width < 150 then if max_width > core.root_view.size.x then
max_width = 150 max_width = core.root_view.size.x
end
if max_width < 150 * SCALE then
max_width = 150 * SCALE
end end
-- if portion not visiable to right, reposition to DocView right margin -- if portion not visiable to right, reposition to DocView right margin
if (x - av.position.x) + max_width > av.size.x then if x + max_width > core.root_view.size.x then
x = (av.size.x + av.position.x) - max_width - (style.padding.x * 2) x = (av.size.x + av.position.x) - max_width
end end
return return
x - style.padding.x, x,
y - style.padding.y, y - style.padding.y,
max_width + style.padding.x * 2, max_width,
max_items * (th + style.padding.y) + style.padding.y max_items * (th + style.padding.y) + style.padding.y
end end
@@ -454,8 +465,21 @@ local function draw_suggestions_box(av)
break break
end end
local s = suggestions[i] local s = suggestions[i]
local info_size = s.info and (style.font:get_width(s.info) + style.padding.x) or style.padding.x
local color = (i == suggestions_idx) and style.accent or style.text local color = (i == suggestions_idx) and style.accent or style.text
common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh) -- Push clip to avoid that the suggestion text gets drawn over suggestion type/icon
core.push_clip_rect(rx + style.padding.x, y, rw - info_size - style.padding.x, lh)
local x_adv = common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh)
core.pop_clip_rect()
-- If the text wasn't fully visible, draw an ellipsis
if x_adv > rx + rw - info_size then
local ellipsis_size = font:get_width("")
local ell_x = rx + rw - info_size - ellipsis_size
renderer.draw_rect(ell_x, y, ellipsis_size, lh, style.background3)
common.draw_text(font, color, "", "left", ell_x, y, ellipsis_size, lh)
end
if s.info then if s.info then
color = (i == suggestions_idx) and style.text or style.dim color = (i == suggestions_idx) and style.text or style.dim
common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh) common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh)