From 5386cc71eef6081df804de271221bd6bff5c373a Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:05:57 +0200 Subject: [PATCH 1/6] Fix multi-column item tooltip overflow If tooltips with more than 1 column overflow the viewport they are now moved to the left, as much as needed and the viewport allows --- src/Classes/Tooltip.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 47ae39bf53..1296ae6b4d 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -367,9 +367,15 @@ function TooltipClass:Draw(x, y, w, h, viewPort) ttY = m_max(viewPort.y, y + h - ttH) end end - + -- Initial column calculation local columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) + -- If extra columns don't fit, shift to left and recalculate drawStack + if columns > 1 and ttW * columns + ttX >= viewPort.x + viewPort.width then + ttX = m_max(viewPort.x, viewPort.x + viewPort.width - ttW * columns) + columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) + end + -- background shading currently must be drawn before text lines. API change will allow something like the commented lines below SetDrawColor(0, 0, 0, .85) --SetDrawLayer(nil, GetDrawLayer() - 5) From fdfa45733eb66c42bb90fd13b0545e558dc563fb Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:11:42 +0200 Subject: [PATCH 2/6] Make column shift fix only apply to hover tooltips --- src/Classes/Tooltip.lua | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 1296ae6b4d..0e07e38a39 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -300,7 +300,12 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) return columns, maxColumnHeight, drawStack end - +--- Draws tooltip to screen +---@param x number x-coordinate to draw the tooltip at +---@param y number y-coordinate to draw the tooltip at +---@param w number|nil optional width of the UI element being hovered over. Tooltip will position itself outside this box (if possible) +---@param h number|nil optional height of the UI element being hovered over. Needs to be provided alongside `w` +---@param viewPort table A table `{x, y, width, height}` contains active screen boundaries function TooltipClass:Draw(x, y, w, h, viewPort) if #self.lines == 0 then return @@ -355,7 +360,8 @@ function TooltipClass:Draw(x, y, w, h, viewPort) end local ttX = x local ttY = y - if w and h then + local isHoverToolTip = w and h -- `w` and `h` typically only provided for hover tooltips + if isHoverToolTip then ttX = ttX + w + 5 if ttX + ttW > viewPort.x + viewPort.width then ttX = m_max(viewPort.x, x - 5 - ttW) @@ -370,11 +376,22 @@ function TooltipClass:Draw(x, y, w, h, viewPort) -- Initial column calculation local columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) - -- If extra columns don't fit, shift to left and recalculate drawStack - if columns > 1 and ttW * columns + ttX >= viewPort.x + viewPort.width then - ttX = m_max(viewPort.x, viewPort.x + viewPort.width - ttW * columns) - columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) - end + -- If hover tooltip and extra columns don't fit, shift to left and adjust drawStack (because hover tooltips can't scroll) + if columns > 1 and isHoverToolTip and ttW * columns + ttX >= viewPort.x + viewPort.width then + local newX = m_max(viewPort.x, viewPort.x + viewPort.width - ttW * columns) + local offsetX = newX - ttX + ttX = newX + + for _, line in ipairs(drawStack) do + if #line < 6 then + -- Text element entries have 6 entries and `x` at `[2]` + line[2] = line[2] + offsetX + else + -- Image, Separators, etc. have 5 entries and `x` at `[1]` + line[1] = line[1] + offsetX + end + end + end -- background shading currently must be drawn before text lines. API change will allow something like the commented lines below SetDrawColor(0, 0, 0, .85) From 60eb67a75b965c9daf1bb2fb80e9159762701018 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 22 Apr 2026 13:56:12 +0200 Subject: [PATCH 3/6] Change `6` and `12` to use existing `H_PAD` var --- src/Classes/Tooltip.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 0e07e38a39..0d66f47184 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -235,7 +235,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) local curX = ttX + ttW / 2 - totalWidth / 2 -- Draw title t_insert(drawStack, {curX, y + (titleSize - titleSize)/2, "LEFT", titleSize, font, title.text}) - curX = curX + DrawStringWidth(titleSize, font, title.text) + 6 + curX = curX + DrawStringWidth(titleSize, font, title.text) + (H_PAD / 2) -- Draw oils local maxOilHeight = 0 @@ -273,7 +273,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) if lineCentered == nil then lineCentered = self.center end - local lineX = lineCentered and (x + ttW / 2) or (x + 6) + local lineX = lineCentered and (x + ttW / 2) or (x + (H_PAD / 2)) local lineAlign = lineCentered and "CENTER_X" or "LEFT" t_insert(drawStack, {lineX, y, lineAlign, data.size, font, data.text}) @@ -287,7 +287,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) columns = columns + 1 end currentBlock = data.block - t_insert(drawStack, {{ handle = data.separatorImage, isSeparator = true }, x + 6, y, ttW - 12, sepSize}) + t_insert(drawStack, {{ handle = data.separatorImage, isSeparator = true }, x + (H_PAD / 2), y, ttW - H_PAD, sepSize}) y = y + sepSize + 2 elseif self.lines[i + 1] and self.lines[i - 1] and self.lines[i + 1].text then From 75059149074d988a9f84cfe41670329d2731cb8a Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:44:08 +0200 Subject: [PATCH 4/6] Make extra tooltip columns shrink to min width Tooltip column size previously blindly copied the width of the first column, which could lead to massive waste of space for uniques with very long mods. --- src/Classes/Tooltip.lua | 75 +++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 0d66f47184..3c69ac3eab 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -186,8 +186,11 @@ end function TooltipClass:GetDynamicSize(viewPort) local staticttW, staticttH = self:GetSize() - local columns, ttH = self:CalculateColumns(0, 0, staticttH, staticttW, viewPort) - local ttW = columns * staticttW + local columns, ttH, _, extraColumnWidth = self:CalculateColumns(0, 0, staticttH, staticttW, viewPort) + + -- ensure extra column width has sensible value + extraColumnWidth = (columns > 1 and extraColumnWidth > 0) and extraColumnWidth or staticttW + local ttW = staticttW + (m_max(columns - 1, 0) * extraColumnWidth) return ttW + H_PAD, ttH + V_PAD end @@ -200,6 +203,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) local x = ttX local columns = 1 -- reset to count columns by block heights local currentBlock = 1 + local extraColumnWidth = 0 local maxColumnHeight = 0 local drawStack = {} local font @@ -279,6 +283,11 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) t_insert(drawStack, {lineX, y, lineAlign, data.size, font, data.text}) y = y + data.size + 2 + -- track max width for extra columns + if columns > 1 then + extraColumnWidth = m_max(extraColumnWidth, DrawStringWidth(data.size, font, data.text) + H_PAD) + end + elseif data.separatorImage and main.showFlavourText then local sepSize = data.size or 10 if currentBlock ~= data.block and y + sepSize > ttY + math.min(ttH, viewPort.height) then @@ -298,7 +307,44 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) maxColumnHeight = m_max(y - ttY + 2 * BORDER_WIDTH, maxColumnHeight) end - return columns, maxColumnHeight, drawStack + -- Resizing/Shrinking drawStack elements in extra columns + -- NOTE: this logic depends on the current structure of `drawStack` --> needs adjustment if lengths or coordinates logic changes + if columns > 1 and extraColumnWidth > 0 then + for _, line in ipairs(drawStack) do + local isText = #line >= 6 -- Text elements have 6 props, images/separators have 5 + local xIdx = isText and 1 or 2 -- `x` value at index 1 for text, 2 otherwise + local origX = line[xIdx] + + -- calculate column index (origX is at least x * original widths from start) + local colIndex = m_floor((origX - ttX) / ttW) + 1 + + if colIndex > 1 then + local oldBaseX = ttX + ttW * (colIndex - 1) + local newBaseX = ttX + ttW + extraColumnWidth * (colIndex - 2) -- `- 2` because first column is unchanged + + -- Update x coordinates + if isText and line[3] == "CENTER_X" then + -- centered texts + line[xIdx] = newBaseX + extraColumnWidth / 2 + else + -- "LEFT" aligned text and images (NOTE: "RIGHT" aligned does not seem to exist) + line[xIdx] = origX - oldBaseX + newBaseX + end + + -- Resize separators/dividers (technically unlikely to appear in extra columns, but just in case) + if not isText then + -- separator images have `width` value at index 4 + if line[1] and type(line[1]) == "table" and line[1].isSeparator then + line[4] = extraColumnWidth - H_PAD -- "fancy" separators get extra padding + else + line[4] = extraColumnWidth - BORDER_WIDTH + end + end + end + end + end + + return columns, maxColumnHeight, drawStack, extraColumnWidth end --- Draws tooltip to screen ---@param x number x-coordinate to draw the tooltip at @@ -374,11 +420,15 @@ function TooltipClass:Draw(x, y, w, h, viewPort) end end -- Initial column calculation - local columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) + local columns, maxColumnHeight, drawStack, extraColumnWidth = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) + + -- ensure extraColumnWidth has sensible value and calculate new total width (original width + extraColumns) + extraColumnWidth = (columns > 1 and extraColumnWidth > 0) and extraColumnWidth or ttW + local totalDrawWidth = ttW + (m_max(columns - 1, 0) * extraColumnWidth) -- If hover tooltip and extra columns don't fit, shift to left and adjust drawStack (because hover tooltips can't scroll) - if columns > 1 and isHoverToolTip and ttW * columns + ttX >= viewPort.x + viewPort.width then - local newX = m_max(viewPort.x, viewPort.x + viewPort.width - ttW * columns) + if columns > 1 and isHoverToolTip and totalDrawWidth + ttX >= viewPort.x + viewPort.width then + local newX = m_max(viewPort.x, viewPort.x + viewPort.width - totalDrawWidth) local offsetX = newX - ttX ttX = newX @@ -396,7 +446,7 @@ function TooltipClass:Draw(x, y, w, h, viewPort) -- background shading currently must be drawn before text lines. API change will allow something like the commented lines below SetDrawColor(0, 0, 0, .85) --SetDrawLayer(nil, GetDrawLayer() - 5) - DrawImage(nil, ttX, ttY + BORDER_WIDTH, ttW * columns - BORDER_WIDTH, maxColumnHeight - 2 * BORDER_WIDTH) + DrawImage(nil, ttX, ttY + BORDER_WIDTH, totalDrawWidth - BORDER_WIDTH, maxColumnHeight - 2 * BORDER_WIDTH) --SetDrawLayer(nil, GetDrawLayer()) SetDrawColor(1, 1, 1) @@ -540,11 +590,16 @@ function TooltipClass:Draw(x, y, w, h, viewPort) else SetDrawColor(unpack(self.color)) end + + -- draw vertical borders, accounting for separate extra column width for i = 0, columns do - DrawImage(nil, ttX + ttW * i - BORDER_WIDTH * math.ceil(i^2 / (i^2 + 1)), ttY, BORDER_WIDTH, maxColumnHeight) + local extraColXOffset = i > 0 and ttW + ((i - 1) * extraColumnWidth) or 0 + local currentX = ttX + extraColXOffset + DrawImage(nil, currentX - BORDER_WIDTH * math.ceil(i^2 / (i^2 + 1)), ttY, BORDER_WIDTH, maxColumnHeight) end - DrawImage(nil, ttX, ttY, ttW * columns, BORDER_WIDTH) -- top border - DrawImage(nil, ttX, ttY + maxColumnHeight - BORDER_WIDTH, ttW * columns, BORDER_WIDTH) -- bottom border + -- draw horizontal borders + DrawImage(nil, ttX, ttY, totalDrawWidth, BORDER_WIDTH) -- top + DrawImage(nil, ttX, ttY + maxColumnHeight - BORDER_WIDTH, totalDrawWidth, BORDER_WIDTH) -- bottom return ttW, ttH end From 3d3f48fce72bdd4f341018933d28944957b3ffe5 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:59:37 +0200 Subject: [PATCH 5/6] Add emmylua annotations to `TooltipClass:CalculateColumns()` Disclaimer: I had an AI generate the texts for this one, as it's just busy work, but I did check the output for correctness and I do find the annotations generally helpful. You can totally leave out this commit though, if you prefer --- src/Classes/Tooltip.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 3c69ac3eab..cebb4bfaf3 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -195,6 +195,17 @@ function TooltipClass:GetDynamicSize(viewPort) return ttW + H_PAD, ttH + V_PAD end +--- Calculates the column breaks, layout heights, and individual rendering instructions for tooltip lines. +--- By default, items exceeding window height will wrap to a new column. +---@param ttY number Base y-coordinate for the tooltip content +---@param ttX number Base x-coordinate for the tooltip content +---@param ttH number The total estimated height of the tooltip content, used to determine column breakpoints +---@param ttW number The pixel width of the primary (first) tooltip column +---@param viewPort table A table `{x, y, width, height}` containing active screen boundaries +---@return number columns The total number of layout columns generated +---@return number maxColumnHeight The maximum pixel height reached across all formatted columns +---@return table drawStack An array of sequential rendering instructions (texts, images, separators, and their coordinates) +---@return number extraColumnWidth The required dynamic pixel width calculated for any additional columns beyond the first function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) local y = ttY + 2 * BORDER_WIDTH if self.titleYOffset then From 4f6349f50dede9298be94f2a01ccfc118cd53469 Mon Sep 17 00:00:00 2001 From: majochem <77203255+majochem@users.noreply.github.com> Date: Thu, 23 Apr 2026 09:41:47 +0200 Subject: [PATCH 6/6] Fix indentation atrocities (here as well) --- src/Classes/Tooltip.lua | 88 ++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index cebb4bfaf3..31f8efe1bc 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -319,41 +319,41 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) end -- Resizing/Shrinking drawStack elements in extra columns - -- NOTE: this logic depends on the current structure of `drawStack` --> needs adjustment if lengths or coordinates logic changes - if columns > 1 and extraColumnWidth > 0 then - for _, line in ipairs(drawStack) do - local isText = #line >= 6 -- Text elements have 6 props, images/separators have 5 - local xIdx = isText and 1 or 2 -- `x` value at index 1 for text, 2 otherwise - local origX = line[xIdx] - - -- calculate column index (origX is at least x * original widths from start) - local colIndex = m_floor((origX - ttX) / ttW) + 1 - - if colIndex > 1 then - local oldBaseX = ttX + ttW * (colIndex - 1) - local newBaseX = ttX + ttW + extraColumnWidth * (colIndex - 2) -- `- 2` because first column is unchanged - - -- Update x coordinates - if isText and line[3] == "CENTER_X" then + -- NOTE: this logic depends on the current structure of `drawStack` --> needs adjustment if lengths or coordinates logic changes + if columns > 1 and extraColumnWidth > 0 then + for _, line in ipairs(drawStack) do + local isText = #line >= 6 -- Text elements have 6 props, images/separators have 5 + local xIdx = isText and 1 or 2 -- `x` value at index 1 for text, 2 otherwise + local origX = line[xIdx] + + -- calculate column index (origX is at least x * original widths from start) + local colIndex = m_floor((origX - ttX) / ttW) + 1 + + if colIndex > 1 then + local oldBaseX = ttX + ttW * (colIndex - 1) + local newBaseX = ttX + ttW + extraColumnWidth * (colIndex - 2) -- `- 2` because first column is unchanged + + -- Update x coordinates + if isText and line[3] == "CENTER_X" then -- centered texts - line[xIdx] = newBaseX + extraColumnWidth / 2 - else + line[xIdx] = newBaseX + extraColumnWidth / 2 + else -- "LEFT" aligned text and images (NOTE: "RIGHT" aligned does not seem to exist) - line[xIdx] = origX - oldBaseX + newBaseX - end + line[xIdx] = origX - oldBaseX + newBaseX + end - -- Resize separators/dividers (technically unlikely to appear in extra columns, but just in case) - if not isText then + -- Resize separators/dividers (technically unlikely to appear in extra columns, but just in case) + if not isText then -- separator images have `width` value at index 4 - if line[1] and type(line[1]) == "table" and line[1].isSeparator then - line[4] = extraColumnWidth - H_PAD -- "fancy" separators get extra padding - else - line[4] = extraColumnWidth - BORDER_WIDTH - end - end - end - end - end + if line[1] and type(line[1]) == "table" and line[1].isSeparator then + line[4] = extraColumnWidth - H_PAD -- "fancy" separators get extra padding + else + line[4] = extraColumnWidth - BORDER_WIDTH + end + end + end + end + end return columns, maxColumnHeight, drawStack, extraColumnWidth end @@ -435,24 +435,24 @@ function TooltipClass:Draw(x, y, w, h, viewPort) -- ensure extraColumnWidth has sensible value and calculate new total width (original width + extraColumns) extraColumnWidth = (columns > 1 and extraColumnWidth > 0) and extraColumnWidth or ttW - local totalDrawWidth = ttW + (m_max(columns - 1, 0) * extraColumnWidth) + local totalDrawWidth = ttW + (m_max(columns - 1, 0) * extraColumnWidth) -- If hover tooltip and extra columns don't fit, shift to left and adjust drawStack (because hover tooltips can't scroll) if columns > 1 and isHoverToolTip and totalDrawWidth + ttX >= viewPort.x + viewPort.width then - local newX = m_max(viewPort.x, viewPort.x + viewPort.width - totalDrawWidth) - local offsetX = newX - ttX - ttX = newX - - for _, line in ipairs(drawStack) do - if #line < 6 then + local newX = m_max(viewPort.x, viewPort.x + viewPort.width - totalDrawWidth) + local offsetX = newX - ttX + ttX = newX + + for _, line in ipairs(drawStack) do + if #line < 6 then -- Text element entries have 6 entries and `x` at `[2]` - line[2] = line[2] + offsetX - else + line[2] = line[2] + offsetX + else -- Image, Separators, etc. have 5 entries and `x` at `[1]` - line[1] = line[1] + offsetX - end - end - end + line[1] = line[1] + offsetX + end + end + end -- background shading currently must be drawn before text lines. API change will allow something like the commented lines below SetDrawColor(0, 0, 0, .85)