@@ -68,6 +68,8 @@ local LAYOUT = {
6868 itemsCopyUseBtnW = 78 ,
6969 itemsCopyBtnH = 18 ,
7070 itemsBuyBtnW = 60 ,
71+ itemsMinColWidth = 700 ,
72+ itemsHScrollBarHeight = 16 ,
7173
7274 -- Calcs view
7375 calcsMaxCardWidth = 400 ,
@@ -131,6 +133,7 @@ local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", functio
131133
132134 -- Scroll offset for scrollable views
133135 self .scrollY = 0
136+ self .itemsScrollX = 0
134137
135138 -- Total content height for scroll clamping (populated at end of each Draw* pass)
136139 self .summaryTotalContentHeight = 0
@@ -1011,6 +1014,13 @@ function CompareTabClass:InitControls()
10111014 self .controls .calcsScrollBar .shown = function ()
10121015 return self .compareViewMode == " CALCS" and self :GetActiveCompare () ~= nil and calcsScrollBar .enabled
10131016 end
1017+
1018+ -- Horizontal scrollbar for Items sub-tab
1019+ self .controls .itemsHScrollBar = new (" ScrollBarControl" , nil , {0 , 0 , 0 , LAYOUT .itemsHScrollBarHeight }, 60 , " HORIZONTAL" , true )
1020+ local itemsHScrollBar = self .controls .itemsHScrollBar
1021+ self .controls .itemsHScrollBar .shown = function ()
1022+ return self .compareViewMode == " ITEMS" and self :GetActiveCompare () ~= nil and itemsHScrollBar .enabled
1023+ end
10141024end
10151025
10161026-- Get a short display name from a build name (strips "AccountName - " prefix)
@@ -1649,22 +1659,23 @@ function CompareTabClass:Draw(viewPort, inputEvents)
16491659 self .controls .itemsExpandedCheck .x = contentVP .x + 10 + self .controls .itemsExpandedCheck .labelWidth
16501660 self .controls .itemsExpandedCheck .y = contentVP .y + 8
16511661
1652- local colWidth = m_floor (contentVP .width / 2 )
1662+ local colWidth = m_max ( m_floor (contentVP .width / 2 ), LAYOUT . itemsMinColWidth )
16531663 local itemSetLabelW = DrawStringWidth (16 , " VAR" , " ^7Item set:" ) + 4
1664+ local scrollOffsetX = - (self .itemsScrollX or 0 )
16541665
16551666 -- Item set dropdowns
16561667 local row1Y = contentVP .y + 34
16571668
16581669 -- Primary build item set dropdown
1659- self .controls .primaryItemSetLabel .x = contentVP .x + 10
1670+ self .controls .primaryItemSetLabel .x = contentVP .x + scrollOffsetX + 10
16601671 self .controls .primaryItemSetLabel .y = row1Y + 2
1661- self .controls .primaryItemSetSelect .x = contentVP .x + 10 + itemSetLabelW
1672+ self .controls .primaryItemSetSelect .x = contentVP .x + scrollOffsetX + 10 + itemSetLabelW
16621673 self .controls .primaryItemSetSelect .y = row1Y
16631674
16641675 -- Compare build item set dropdown
1665- self .controls .compareItemSetLabel2 .x = contentVP .x + colWidth + 10
1676+ self .controls .compareItemSetLabel2 .x = contentVP .x + scrollOffsetX + colWidth + 10
16661677 self .controls .compareItemSetLabel2 .y = row1Y + 2
1667- self .controls .compareItemSetSelect2 .x = contentVP .x + colWidth + 10 + itemSetLabelW
1678+ self .controls .compareItemSetSelect2 .x = contentVP .x + scrollOffsetX + colWidth + 10 + itemSetLabelW
16681679 self .controls .compareItemSetSelect2 .y = row1Y
16691680
16701681 -- Populate primary build item set list
@@ -2234,7 +2245,8 @@ function CompareTabClass:HandleScrollInput(contentVP, inputEvents)
22342245 elseif self .compareViewMode == " SUMMARY" and self .summaryTotalContentHeight > 0 then
22352246 maxScroll = m_max (self .summaryTotalContentHeight - viewportH , 0 )
22362247 elseif self .compareViewMode == " ITEMS" and self .itemsTotalContentHeight > 0 then
2237- local scrollViewH = viewportH - LAYOUT .itemsCheckboxOffset
2248+ local hBarReserve = self .controls .itemsHScrollBar .enabled and LAYOUT .itemsHScrollBarHeight or 0
2249+ local scrollViewH = viewportH - LAYOUT .itemsCheckboxOffset - hBarReserve
22382250 maxScroll = m_max (self .itemsTotalContentHeight - scrollViewH , 0 )
22392251 elseif self .compareViewMode == " SKILLS" and self .skillsTotalContentHeight > 0 then
22402252 maxScroll = m_max (self .skillsTotalContentHeight - viewportH , 0 )
@@ -3408,11 +3420,25 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
34083420 local primaryEnv = self .primaryBuild .calcsTab and self .primaryBuild .calcsTab .mainEnv
34093421 local primaryHasRing3 = primaryEnv and primaryEnv .modDB :Flag (nil , " AdditionalRingSlot" )
34103422 local lineHeight = 20
3411- local colWidth = m_floor (vp .width / 2 )
3423+ local colWidth = m_max (m_floor (vp .width / 2 ), LAYOUT .itemsMinColWidth )
3424+ local contentWidth = colWidth * 2
3425+ local needsHScroll = contentWidth > vp .width
34123426
34133427 local checkboxOffset = LAYOUT .itemsCheckboxOffset
3414- SetViewport (vp .x , vp .y + checkboxOffset , vp .width , vp .height - checkboxOffset )
3428+
3429+ -- Position + configure the horizontal scrollbar
3430+ local hBar = self .controls .itemsHScrollBar
3431+ hBar .x = vp .x
3432+ hBar .y = vp .y + vp .height - LAYOUT .itemsHScrollBarHeight
3433+ hBar .width = vp .width
3434+ hBar :SetContentDimension (contentWidth , vp .width )
3435+ self .itemsScrollX = hBar .offset
3436+
3437+ local bottomReserve = needsHScroll and LAYOUT .itemsHScrollBarHeight or 0
3438+ local scrollViewH = vp .height - checkboxOffset - bottomReserve
3439+ SetViewport (vp .x , vp .y + checkboxOffset , vp .width , scrollViewH )
34153440 local drawY = 4 - self .scrollY
3441+ local scrollOffsetX = - self .itemsScrollX
34163442
34173443 -- Get cursor position relative to viewport for hover detection
34183444 local cursorX , cursorY = GetCursorPos ()
@@ -3437,8 +3463,8 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
34373463
34383464 -- Headers
34393465 SetDrawColor (1 , 1 , 1 )
3440- DrawString (10 , drawY , " LEFT" , 18 , " VAR" , colorCodes .POSITIVE .. self :GetShortBuildName (self .primaryBuild .buildName ))
3441- DrawString (colWidth + 10 , drawY , " LEFT" , 18 , " VAR" , colorCodes .WARNING .. (compareEntry .label or " Compare Build" ))
3466+ DrawString (scrollOffsetX + 10 , drawY , " LEFT" , 18 , " VAR" , colorCodes .POSITIVE .. self :GetShortBuildName (self .primaryBuild .buildName ))
3467+ DrawString (scrollOffsetX + colWidth + 10 , drawY , " LEFT" , 18 , " VAR" , colorCodes .WARNING .. (compareEntry .label or " Compare Build" ))
34423468 drawY = drawY + 24
34433469
34443470 -- Pre-compute max slot label width for alignment
@@ -3483,11 +3509,11 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
34833509 if self .itemsExpandedMode then
34843510 -- === EXPANDED MODE ===
34853511 SetDrawColor (1 , 1 , 1 )
3486- DrawString (10 , drawY , " LEFT" , 16 , " VAR" , " ^7" .. label .. " :" .. (pWarn or " " ))
3487- DrawString (colWidth - 10 , drawY , " RIGHT" , 14 , " VAR" , tradeHelpers .getSlotDiffLabel (pItem , cItem ))
3512+ DrawString (scrollOffsetX + 10 , drawY , " LEFT" , 16 , " VAR" , " ^7" .. label .. " :" .. (pWarn or " " ))
3513+ DrawString (scrollOffsetX + colWidth - 10 , drawY , " RIGHT" , 14 , " VAR" , tradeHelpers .getSlotDiffLabel (pItem , cItem ))
34883514
34893515 if cItem then
3490- local b1Hover , b2Hover , b3Hover , b2X , b2Y , b2W , b2H = tradeHelpers .drawCopyButtons (cursorX , cursorY , vp . width - 214 , drawY + 1 , slotMissing , LAYOUT .itemsCopyBtnW , LAYOUT .itemsCopyBtnH , LAYOUT .itemsBuyBtnW , LAYOUT .itemsCopyUseBtnW )
3516+ local b1Hover , b2Hover , b3Hover , b2X , b2Y , b2W , b2H = tradeHelpers .drawCopyButtons (cursorX , cursorY , scrollOffsetX + contentWidth - 214 , drawY + 1 , slotMissing , LAYOUT .itemsCopyBtnW , LAYOUT .itemsCopyBtnH , LAYOUT .itemsBuyBtnW , LAYOUT .itemsCopyUseBtnW )
34913517 processSlotButtons (b1Hover , b2Hover , b3Hover , b2X , b2Y , b2W , b2H , cItem , copySlotName , copyUseSlotName )
34923518 end
34933519
@@ -3496,12 +3522,12 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
34963522 local pModMap = tradeHelpers .buildModMap (pItem )
34973523 local cModMap = tradeHelpers .buildModMap (cItem )
34983524 local itemStartY = drawY
3499- local leftHeight = self :DrawItemExpanded (pItem , 20 , drawY , colWidth - 30 , cModMap )
3500- local rightHeight = self :DrawItemExpanded (cItem , colWidth + 20 , drawY , colWidth - 30 , pModMap )
3525+ local leftHeight = self :DrawItemExpanded (pItem , scrollOffsetX + 20 , drawY , colWidth - 30 , cModMap )
3526+ local rightHeight = self :DrawItemExpanded (cItem , scrollOffsetX + colWidth + 20 , drawY , colWidth - 30 , pModMap )
35013527
35023528 SetDrawColor (0.25 , 0.25 , 0.25 )
35033529 local maxH = m_max (leftHeight , rightHeight )
3504- DrawImage (nil , colWidth , itemStartY , 1 , maxH )
3530+ DrawImage (nil , scrollOffsetX + colWidth , itemStartY , 1 , maxH )
35053531
35063532 drawY = drawY + maxH + 6
35073533 else
@@ -3511,7 +3537,7 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
35113537 tradeHelpers .drawCompactSlotRow (drawY , label , pItem , cItem ,
35123538 colWidth , cursorX , cursorY , labelW ,
35133539 self .primaryBuild .itemsTab , compareEntry .itemsTab , pWarn , cWarn , slotMissing ,
3514- LAYOUT .itemsCopyBtnW , LAYOUT .itemsCopyBtnH , LAYOUT .itemsBuyBtnW , LAYOUT .itemsCopyUseBtnW )
3540+ LAYOUT .itemsCopyBtnW , LAYOUT .itemsCopyBtnH , LAYOUT .itemsBuyBtnW , LAYOUT .itemsCopyUseBtnW , scrollOffsetX )
35153541
35163542 if rowHoverItem then
35173543 hoverItem = rowHoverItem
@@ -3529,7 +3555,7 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
35293555 for _ , slotName in ipairs (baseSlots ) do
35303556 -- Separator
35313557 SetDrawColor (0.3 , 0.3 , 0.3 )
3532- DrawImage (nil , 4 , drawY , vp . width - 8 , 1 )
3558+ DrawImage (nil , scrollOffsetX + 4 , drawY , contentWidth - 8 , 1 )
35333559 drawY = drawY + 2
35343560
35353561 -- Get items from both builds
@@ -3545,21 +3571,21 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
35453571 -- === TREE SET DROPDOWNS ===
35463572 drawY = drawY + 12
35473573 SetDrawColor (0.5 , 0.5 , 0.5 )
3548- DrawImage (nil , 4 , drawY , vp . width - 8 , 1 )
3574+ DrawImage (nil , scrollOffsetX + 4 , drawY , contentWidth - 8 , 1 )
35493575 drawY = drawY + 10
35503576
35513577 -- Convert drawY to absolute screen coords for control positioning
35523578 local absY = vp .y + checkboxOffset + drawY
35533579 local treeSetLabelW = DrawStringWidth (16 , " VAR" , " ^7Tree set:" ) + 4
35543580
3555- self .controls .primaryTreeSetLabel .x = vp .x + 10
3581+ self .controls .primaryTreeSetLabel .x = vp .x + scrollOffsetX + 10
35563582 self .controls .primaryTreeSetLabel .y = absY + 2
3557- self .controls .primaryTreeSetSelect .x = vp .x + 10 + treeSetLabelW
3583+ self .controls .primaryTreeSetSelect .x = vp .x + scrollOffsetX + 10 + treeSetLabelW
35583584 self .controls .primaryTreeSetSelect .y = absY
35593585
3560- self .controls .compareTreeSetLabel .x = vp .x + colWidth + 10
3586+ self .controls .compareTreeSetLabel .x = vp .x + scrollOffsetX + colWidth + 10
35613587 self .controls .compareTreeSetLabel .y = absY + 2
3562- self .controls .compareTreeSetSelect .x = vp .x + colWidth + 10 + treeSetLabelW
3588+ self .controls .compareTreeSetSelect .x = vp .x + scrollOffsetX + colWidth + 10 + treeSetLabelW
35633589 self .controls .compareTreeSetSelect .y = absY
35643590
35653591 -- Populate tree set lists
@@ -3579,7 +3605,7 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
35793605 if # jewelSlots > 0 then
35803606 -- Section header
35813607 SetDrawColor (1 , 1 , 1 )
3582- DrawString (10 , drawY , " LEFT" , 16 , " VAR" , " ^7-- Jewels --" )
3608+ DrawString (scrollOffsetX + 10 , drawY , " LEFT" , 16 , " VAR" , " ^7-- Jewels --" )
35833609 drawY = drawY + 20
35843610
35853611 -- Pre-compute max jewel label width for alignment
@@ -3593,7 +3619,7 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents)
35933619 -- Separator (skip before first jewel since section header already has one)
35943620 if jIdx > 1 then
35953621 SetDrawColor (0.3 , 0.3 , 0.3 )
3596- DrawImage (nil , 4 , drawY , vp . width - 8 , 1 )
3622+ DrawImage (nil , scrollOffsetX + 4 , drawY , contentWidth - 8 , 1 )
35973623 drawY = drawY + 2
35983624 end
35993625
0 commit comments