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:
parent
cf76b5857a
commit
ece51922a3
|
@ -384,8 +384,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
|
||||||
|
|
||||||
|
@ -398,45 +400,59 @@ local function get_suggestions_rect(av)
|
||||||
local hide_info = config.plugins.autocomplete.hide_info
|
local hide_info = config.plugins.autocomplete.hide_info
|
||||||
local hide_icons = config.plugins.autocomplete.hide_icons
|
local hide_icons = config.plugins.autocomplete.hide_icons
|
||||||
|
|
||||||
|
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
|
local max_l_icon_width = 0
|
||||||
|
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 and not hide_info then
|
if s.info and not hide_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
|
||||||
local icon = s.icon or s.info
|
local icon = s.icon or s.info
|
||||||
if not hide_icons and icon and autocomplete.icons[icon] then
|
if not hide_icons and icon and autocomplete.icons[icon] then
|
||||||
w = w + autocomplete.icons[icon].font:get_width(
|
local icon_width = autocomplete.icons[icon].font:get_width(
|
||||||
autocomplete.icons[icon].char
|
autocomplete.icons[icon].char
|
||||||
) + (style.padding.x / 2)
|
)
|
||||||
|
if config.plugins.autocomplete.icon_position == "left" then
|
||||||
|
max_l_icon_width = math.max(max_l_icon_width, icon_width + (style.padding.x / 2))
|
||||||
|
end
|
||||||
|
w = w + icon_width + (style.padding.x / 2)
|
||||||
has_icons = true
|
has_icons = true
|
||||||
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 - max_l_icon_width
|
||||||
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,
|
||||||
has_icons
|
has_icons
|
||||||
end
|
end
|
||||||
|
@ -602,11 +618,24 @@ local function draw_suggestions_box(av)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local info_size = style.font:get_width(s.info) + 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(
|
-- Push clip to avoid that the suggestion text gets drawn over suggestion type/icon
|
||||||
|
core.push_clip_rect(rx + icon_l_padding + style.padding.x, y,
|
||||||
|
rw - info_size - icon_l_padding - icon_r_padding - style.padding.x, lh)
|
||||||
|
local x_adv = common.draw_text(
|
||||||
font, color, s.text, "left",
|
font, color, s.text, "left",
|
||||||
rx + icon_l_padding + style.padding.x, y, rw, lh
|
rx + icon_l_padding + 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 - icon_r_padding then
|
||||||
|
local ellipsis_size = font:get_width("…")
|
||||||
|
local ell_x = rx + rw - info_size - icon_r_padding - 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 and not hide_info then
|
if s.info and not hide_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(
|
common.draw_text(
|
||||||
|
|
Loading…
Reference in New Issue