@@ -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
193196end
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
195209function 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
304366function 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
516606end
0 commit comments