Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 103 additions & 14 deletions src/Classes/Tooltip.lua
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,26 @@ 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

--- 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
Expand All @@ -200,6 +214,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
Expand Down Expand Up @@ -235,7 +250,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
Expand Down Expand Up @@ -273,12 +288,17 @@ 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})
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
Expand All @@ -287,7 +307,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
Expand All @@ -298,9 +318,51 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
maxColumnHeight = m_max(y - ttY + 2 * BORDER_WIDTH, maxColumnHeight)
end

return columns, maxColumnHeight, drawStack
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
-- 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
---@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
Expand Down Expand Up @@ -355,7 +417,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)
Expand All @@ -367,13 +430,34 @@ function TooltipClass:Draw(x, y, w, h, viewPort)
ttY = m_max(viewPort.y, y + h - ttH)
end
end

local columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
-- Initial column calculation
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 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
-- 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)
--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)

Expand Down Expand Up @@ -517,11 +601,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
Loading