Skip to content

Commit 44b7386

Browse files
github-actions[bot]majochemLocalIdentity
authored
Fix tooltip positioning and size for multi-column tooltips (#1841)
* Apply changes from PathOfBuildingCommunity/PathOfBuilding#9806 * Missing lines * remove Rej --------- Co-authored-by: majochem <majochem@users.noreply.github.com> Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent d674b18 commit 44b7386

1 file changed

Lines changed: 104 additions & 14 deletions

File tree

src/Classes/Tooltip.lua

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,26 @@ function TooltipClass:GetDynamicSize(viewPort)
186186
self.titleYOffset = config.textYOffset or 0
187187
staticttW = m_max(staticttW, DrawStringWidth(self.lines[1].size, self.lines[1].font, self.lines[1].text) + 50)
188188
end
189-
local columns, ttH = self:CalculateColumns(0, 0, staticttH, staticttW, viewPort)
190-
local ttW = columns * staticttW
189+
local columns, ttH, _, extraColumnWidth = self:CalculateColumns(0, 0, staticttH, staticttW, viewPort)
190+
191+
-- ensure extra column width has sensible value
192+
extraColumnWidth = (columns > 1 and extraColumnWidth > 0) and extraColumnWidth or staticttW
193+
local ttW = staticttW + (m_max(columns - 1, 0) * extraColumnWidth)
191194

192195
return ttW + H_PAD, ttH + V_PAD
193196
end
194197

198+
--- Calculates the column breaks, layout heights, and individual rendering instructions for tooltip lines.
199+
--- By default, items exceeding window height will wrap to a new column.
200+
---@param ttY number Base y-coordinate for the tooltip content
201+
---@param ttX number Base x-coordinate for the tooltip content
202+
---@param ttH number The total estimated height of the tooltip content, used to determine column breakpoints
203+
---@param ttW number The pixel width of the primary (first) tooltip column
204+
---@param viewPort table A table `{x, y, width, height}` containing active screen boundaries
205+
---@return number columns The total number of layout columns generated
206+
---@return number maxColumnHeight The maximum pixel height reached across all formatted columns
207+
---@return table drawStack An array of sequential rendering instructions (texts, images, separators, and their coordinates)
208+
---@return number extraColumnWidth The required dynamic pixel width calculated for any additional columns beyond the first
195209
function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
196210
local y = ttY + 2 * BORDER_WIDTH
197211
if self.titleYOffset then
@@ -200,6 +214,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
200214
local x = ttX
201215
local columns = 1 -- reset to count columns by block heights
202216
local currentBlock = 1
217+
local extraColumnWidth = 0
203218
local maxColumnHeight = 0
204219
local drawStack = {}
205220
local font
@@ -235,7 +250,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
235250
local curX = ttX + ttW / 2 - totalWidth / 2
236251
-- Draw title
237252
t_insert(drawStack, {curX, y + (titleSize - titleSize)/2, "LEFT", titleSize, font, title.text})
238-
curX = curX + DrawStringWidth(titleSize, font, title.text) + 6
253+
curX = curX + DrawStringWidth(titleSize, font, title.text) + (H_PAD / 2)
239254

240255
-- Draw oils
241256
local maxOilHeight = 0
@@ -272,11 +287,16 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
272287
if lineCentered == nil then
273288
lineCentered = self.center
274289
end
275-
local lineX = lineCentered and (x + ttW / 2) or (x + 6)
290+
local lineX = lineCentered and (x + ttW / 2) or (x + (H_PAD / 2))
276291
local lineAlign = lineCentered and "CENTER_X" or "LEFT"
277292

278293
t_insert(drawStack, {lineX, y, lineAlign, data.size, font, data.text, background = data.background})
279294
y = y + data.size + 2
295+
296+
-- track max width for extra columns
297+
if columns > 1 then
298+
extraColumnWidth = m_max(extraColumnWidth, DrawStringWidth(data.size, font, data.text) + H_PAD)
299+
end
280300

281301
elseif data.separatorImage and main.showFlavourText then
282302
local sepSize = data.size or 10
@@ -286,7 +306,7 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
286306
columns = columns + 1
287307
end
288308
currentBlock = data.block
289-
t_insert(drawStack, {{ handle = data.separatorImage, isSeparator = true }, x + 6, y, ttW - 12, sepSize})
309+
t_insert(drawStack, {{ handle = data.separatorImage, isSeparator = true }, x + (H_PAD / 2), y, ttW - H_PAD, sepSize})
290310
y = y + sepSize
291311

292312
elseif self.lines[i + 1] and self.lines[i - 1] and self.lines[i + 1].text then
@@ -297,9 +317,51 @@ function TooltipClass:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
297317
maxColumnHeight = m_max(y - ttY + 2 * BORDER_WIDTH, maxColumnHeight)
298318
end
299319

300-
return columns, maxColumnHeight, drawStack
301-
end
320+
-- Resizing/Shrinking drawStack elements in extra columns
321+
-- NOTE: this logic depends on the current structure of `drawStack` --> needs adjustment if lengths or coordinates logic changes
322+
if columns > 1 and extraColumnWidth > 0 then
323+
for _, line in ipairs(drawStack) do
324+
local isText = #line >= 6 -- Text elements have 6 props, images/separators have 5
325+
local xIdx = isText and 1 or 2 -- `x` value at index 1 for text, 2 otherwise
326+
local origX = line[xIdx]
327+
328+
-- calculate column index (origX is at least x * original widths from start)
329+
local colIndex = m_floor((origX - ttX) / ttW) + 1
330+
331+
if colIndex > 1 then
332+
local oldBaseX = ttX + ttW * (colIndex - 1)
333+
local newBaseX = ttX + ttW + extraColumnWidth * (colIndex - 2) -- `- 2` because first column is unchanged
334+
335+
-- Update x coordinates
336+
if isText and line[3] == "CENTER_X" then
337+
-- centered texts
338+
line[xIdx] = newBaseX + extraColumnWidth / 2
339+
else
340+
-- "LEFT" aligned text and images (NOTE: "RIGHT" aligned does not seem to exist)
341+
line[xIdx] = origX - oldBaseX + newBaseX
342+
end
302343

344+
-- Resize separators/dividers (technically unlikely to appear in extra columns, but just in case)
345+
if not isText then
346+
-- separator images have `width` value at index 4
347+
if line[1] and type(line[1]) == "table" and line[1].isSeparator then
348+
line[4] = extraColumnWidth - H_PAD -- "fancy" separators get extra padding
349+
else
350+
line[4] = extraColumnWidth - BORDER_WIDTH
351+
end
352+
end
353+
end
354+
end
355+
end
356+
357+
return columns, maxColumnHeight, drawStack, extraColumnWidth
358+
end
359+
--- Draws tooltip to screen
360+
---@param x number x-coordinate to draw the tooltip at
361+
---@param y number y-coordinate to draw the tooltip at
362+
---@param w number|nil optional width of the UI element being hovered over. Tooltip will position itself outside this box (if possible)
363+
---@param h number|nil optional height of the UI element being hovered over. Needs to be provided alongside `w`
364+
---@param viewPort table A table `{x, y, width, height}` contains active screen boundaries
303365

304366
function TooltipClass:Draw(x, y, w, h, viewPort)
305367
if #self.lines == 0 then
@@ -329,7 +391,8 @@ function TooltipClass:Draw(x, y, w, h, viewPort)
329391
end
330392
local ttX = x
331393
local ttY = y
332-
if w and h then
394+
local isHoverToolTip = w and h -- `w` and `h` typically only provided for hover tooltips
395+
if isHoverToolTip then
333396
ttX = ttX + w + 5
334397
if ttX + ttW > viewPort.x + viewPort.width then
335398
ttX = m_max(viewPort.x, x - 5 - ttW)
@@ -343,13 +406,35 @@ function TooltipClass:Draw(x, y, w, h, viewPort)
343406
end
344407

345408
SetDrawColor(1, 1, 1)
346-
347-
local columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
409+
410+
-- Initial column calculation
411+
local columns, maxColumnHeight, drawStack, extraColumnWidth = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort)
412+
413+
-- ensure extraColumnWidth has sensible value and calculate new total width (original width + extraColumns)
414+
extraColumnWidth = (columns > 1 and extraColumnWidth > 0) and extraColumnWidth or ttW
415+
local totalDrawWidth = ttW + (m_max(columns - 1, 0) * extraColumnWidth)
416+
417+
-- If hover tooltip and extra columns don't fit, shift to left and adjust drawStack (because hover tooltips can't scroll)
418+
if columns > 1 and isHoverToolTip and totalDrawWidth + ttX >= viewPort.x + viewPort.width then
419+
local newX = m_max(viewPort.x, viewPort.x + viewPort.width - totalDrawWidth)
420+
local offsetX = newX - ttX
421+
ttX = newX
422+
423+
for _, line in ipairs(drawStack) do
424+
if #line < 6 then
425+
-- Text element entries have 6 entries and `x` at `[2]`
426+
line[2] = line[2] + offsetX
427+
else
428+
-- Image, Separators, etc. have 5 entries and `x` at `[1]`
429+
line[1] = line[1] + offsetX
430+
end
431+
end
432+
end
348433

349434
-- background shading currently must be drawn before text lines. API change will allow something like the commented lines below
350435
SetDrawColor(0, 0, 0, .85)
351436
--SetDrawLayer(nil, GetDrawLayer() - 5)
352-
DrawImage(nil, ttX, ttY + BORDER_WIDTH, ttW * columns - BORDER_WIDTH, maxColumnHeight - 2 * BORDER_WIDTH)
437+
DrawImage(nil, ttX, ttY + BORDER_WIDTH, totalDrawWidth - BORDER_WIDTH, maxColumnHeight - 2 * BORDER_WIDTH)
353438
--SetDrawLayer(nil, GetDrawLayer())
354439
SetDrawColor(1, 1, 1)
355440

@@ -506,11 +591,16 @@ function TooltipClass:Draw(x, y, w, h, viewPort)
506591
else
507592
SetDrawColor(unpack(self.color))
508593
end
594+
595+
-- draw vertical borders, accounting for separate extra column width
509596
for i = 0, columns do
510-
DrawImage(nil, ttX + ttW * i - BORDER_WIDTH * math.ceil(i^2 / (i^2 + 1)), ttY, BORDER_WIDTH, maxColumnHeight)
597+
local extraColXOffset = i > 0 and ttW + ((i - 1) * extraColumnWidth) or 0
598+
local currentX = ttX + extraColXOffset
599+
DrawImage(nil, currentX - BORDER_WIDTH * math.ceil(i^2 / (i^2 + 1)), ttY, BORDER_WIDTH, maxColumnHeight)
511600
end
512-
DrawImage(nil, ttX, ttY, ttW * columns, BORDER_WIDTH) -- top border
513-
DrawImage(nil, ttX, ttY + maxColumnHeight - BORDER_WIDTH, ttW * columns, BORDER_WIDTH) -- bottom border
601+
-- draw horizontal borders
602+
DrawImage(nil, ttX, ttY, totalDrawWidth, BORDER_WIDTH) -- top
603+
DrawImage(nil, ttX, ttY + maxColumnHeight - BORDER_WIDTH, totalDrawWidth, BORDER_WIDTH) -- bottom
514604

515605
return ttW, ttH
516606
end

0 commit comments

Comments
 (0)